

<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.amigaos.net/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Costel+Mincea</id>
	<title>AmigaOS Documentation Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.amigaos.net/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Costel+Mincea"/>
	<link rel="alternate" type="text/html" href="https://wiki.amigaos.net/wiki/Special:Contributions/Costel_Mincea"/>
	<updated>2026-10-06T07:53:15Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.0</generator>
	<entry>
		<id>https://wiki.amigaos.net/w/index.php?title=Amiga_Hardware_Manufacturer_ID_Registry&amp;diff=12608</id>
		<title>Amiga Hardware Manufacturer ID Registry</title>
		<link rel="alternate" type="text/html" href="https://wiki.amigaos.net/w/index.php?title=Amiga_Hardware_Manufacturer_ID_Registry&amp;diff=12608"/>
		<updated>2026-09-08T13:33:38Z</updated>

		<summary type="html">&lt;p&gt;Costel Mincea: Added Tim Schattkowsky (45141)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
= How to Obtain a Manufacturer Number =&lt;br /&gt;
&lt;br /&gt;
Manufacturer&#039;s numbers are assigned by the AmigaOS development team. To obtain your unique manufacturer number send a support request to [mailto:support@hyperion-entertainment.com support@hyperion-entertainment.com] including these information:&lt;br /&gt;
&lt;br /&gt;
 1. The name of the company or person which the number is assigned to&lt;br /&gt;
 &lt;br /&gt;
 2. Postal address/contact address&lt;br /&gt;
 &lt;br /&gt;
 3. Name of the contact person, with a corresponding e-mail address&lt;br /&gt;
 &lt;br /&gt;
 4. A brief description of the kind of products you want to produce&lt;br /&gt;
&lt;br /&gt;
= Your Manufacturer Number =&lt;br /&gt;
&lt;br /&gt;
Attention hardware manufacturers. If you are developing a hardware expansion product for the Classic Amiga (e.g. 500, 2000, 3000) then you will need to obtain a special manufacturer ID number from the AmigaOS development team to identify your product. This manufacturer number is used by the Amiga to link your hardware with its driver software at boot time.&lt;br /&gt;
&lt;br /&gt;
Your manufacturer number is part of the special protocol that the Amiga uses to automatically configure all expansion devices on the bus without the user having to cut jumpers or adjust dip switches. This is called auto-config.&lt;br /&gt;
&lt;br /&gt;
At start-up time, the system first polls each board in the system and assigns the board its own address space. If it is a memory board, its RAM is linked into the memory free pool. Later in the boot sequence, after DOS is initialized, the binddrivers program is run. Binddrivers will search the directory SYS:Expansion for the drivers that go with the boards.&lt;br /&gt;
&lt;br /&gt;
To do this binddrivers looks in the Tool Type field of all icon files in SYS:Expansion. If the first seven bytes of the Tool Type field are &amp;quot;PRODUCT&amp;quot;, then this is an icon file for a driver.&lt;br /&gt;
&lt;br /&gt;
Binddrivers will then attempt to match the drivers it has found with the boards that were found earlier. This is where your manufacturer number comes in.&lt;br /&gt;
&lt;br /&gt;
Your manufacturer number goes in two places. First, it is burned in hex form into the PAL which is part of ALL auto-config expansion products. Second, it appears in ASCII in the Tool Type field of the icon file for your product&#039;s driver. By matching these two numbers, the Amiga can automatically configure your board and bind it&#039;s software driver into the system as well.&lt;br /&gt;
&lt;br /&gt;
The manufacturer&#039;s number is a 16-bit ID which appears in PAL offsets $10-$17. There is also an 8-bit product number which you assign. The product number is for uniquely identifying different products from the same vendor. The product number will appear in PAL offsets $04-$07. This gives you a total of 24 bits to identify each of your products.&lt;br /&gt;
&lt;br /&gt;
These 24 bits of information in the PAL which identify your product are matched against the information in the Tool Type field of all icon files in the SYS:Expansion drawer. For example, suppose you are manufacturer #1019. You have two products, #1 and #2 which both use the same driver. The icon for your driver for these two products would have a Tool Type set to &amp;quot;PRODUCT=1019/1|1019/2&amp;quot;. This means: I am an icon for a driver that works with product number 1 or 2 from manufacturer 1019, now bind me. Spaces are not legal. Here are two other examples:&lt;br /&gt;
&lt;br /&gt;
; PRODUCT=1208/11&lt;br /&gt;
: is the Tool Type for a driver for product 11 from manufacturer number 1208.&lt;br /&gt;
&lt;br /&gt;
; PRODUCT=1017&lt;br /&gt;
: is the Tool Type for a driver for any product from manufacturer number 1017.&lt;br /&gt;
&lt;br /&gt;
For an informal explanation of the auto-configuration process, see the chapter on Software Expansion Architecture from the 2nd Annual Amiga Developer&#039;s Conference Notes (available on ADCD 2.1). For the details of timing, power, the PAL equations and PAL address specifications and the expansion library documentation, see sections 3.1 to 3.3 of the A500/A2000 Technical Reference Manual. The original auto-config spec appears in the A1000 Schematics and Expansion Specification.&lt;br /&gt;
&lt;br /&gt;
The auto-config process makes the addition of expansion products to the system very easy. All the user has to do is put the board in any slot and copy the driver from the release disk to his own SYS:Expansion drawer. Everything else is automatic. There are no jumpers or dip switches to set. Best of all, you will get a lot less support calls asking how to make your product work with the XYZ-Corp-battery-backed-clock.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
&lt;br /&gt;
Some notes on hardware manufacturer ID assignment.&lt;br /&gt;
&lt;br /&gt;
* Manufacturer ID numbers are assigned free of charge.&lt;br /&gt;
* Please provide the following information when requesting an ID:&lt;br /&gt;
*# Name of the company or person&lt;br /&gt;
*# Postal address/contact address&lt;br /&gt;
*# Name of the contact person, with a corresponding e-mail address&lt;br /&gt;
*# A brief description of the kind of products you want to produce&lt;br /&gt;
* All ID numbers smaller than 5000 must be considered unsafe because no information exists on which numbers exactly were taken during the time Commodore, Inc. disintegrated.&lt;br /&gt;
* ID numbers in the range 8192 to 18841 must be considered unsafe because some hardware developers mistook the numbers assigned to them to be given in hexadecimal format. Hence 0x2000 = 8192 and 0x4999 = 18841.&lt;br /&gt;
&lt;br /&gt;
= Example code =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
/*-----------------------------------------------*/&lt;br /&gt;
/* Here is a short program which will tell you   */&lt;br /&gt;
/* about the expansion boards configured in your */&lt;br /&gt;
/* system without you opening up the machine.    */&lt;br /&gt;
/* Code by Bill Koester of CATS                  */&lt;br /&gt;
/*-----------------------------------------------*/&lt;br /&gt;
#include &amp;lt;libraries/configvars.h&amp;gt;&lt;br /&gt;
#include &amp;lt;libraries/expansion.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
struct ExpansionBase *ExpansionBase;&lt;br /&gt;
&lt;br /&gt;
void cleanup();&lt;br /&gt;
void printdev();&lt;br /&gt;
&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
   struct ConfigDev *MyConfigDev;&lt;br /&gt;
&lt;br /&gt;
   /*----------------------------------*/&lt;br /&gt;
   /* Open the expansion library,      */&lt;br /&gt;
   /* if there is a problem then exit  */&lt;br /&gt;
   /*----------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   ExpansionBase =(struct ExpansionBase *) OpenLibrary(EXPANSIONNAME,0);&lt;br /&gt;
   if(ExpansionBase==NULL)&lt;br /&gt;
   {&lt;br /&gt;
      printf(&amp;quot;Error opening expansion library!!\n&amp;quot;);&lt;br /&gt;
      cleanup();&lt;br /&gt;
      exit(0);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   /*--------------------------------------------*/&lt;br /&gt;
   /* Use FindConfigDev to get info on the first */&lt;br /&gt;
   /* expansion board on the list maintained by  */&lt;br /&gt;
   /* Exec.  If there are no expansion boards in */&lt;br /&gt;
   /* the system then exit.                      */&lt;br /&gt;
   /*--------------------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   MyConfigDev = NULL;&lt;br /&gt;
&lt;br /&gt;
  /*--------------------------------------------------*/&lt;br /&gt;
  /* FindConfigDev(oldConfigDev,manufacturer,product) */&lt;br /&gt;
  /* oldConfigDev = NULL for the top of the list      */&lt;br /&gt;
  /* manufacturer = -1 for any manufacturer           */&lt;br /&gt;
  /* product      = -1 for any product                */&lt;br /&gt;
  /*--------------------------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   MyConfigDev = FindConfigDev(NULL,-1,-1);&lt;br /&gt;
&lt;br /&gt;
   if(MyConfigDev==NULL)&lt;br /&gt;
   {&lt;br /&gt;
      printf(&amp;quot;No Configured Devices found!!\n&amp;quot;);&lt;br /&gt;
      cleanup();&lt;br /&gt;
      exit(0);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   printdev(MyConfigDev);&lt;br /&gt;
&lt;br /&gt;
   /*-----------------------------------*/&lt;br /&gt;
   /* OK, there is at least one board,  */&lt;br /&gt;
   /* so loop and get the entire list   */&lt;br /&gt;
   /* printing as we go with printdev() */&lt;br /&gt;
   /*-----------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   while(MyConfigDev = FindConfigDev(MyConfigDev,-1,-1))&lt;br /&gt;
   {&lt;br /&gt;
      printdev(MyConfigDev);&lt;br /&gt;
   }&lt;br /&gt;
   cleanup();&lt;br /&gt;
   return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*-------------------*/&lt;br /&gt;
/* Close up shop...  */&lt;br /&gt;
/*-------------------*/&lt;br /&gt;
void cleanup()&lt;br /&gt;
{&lt;br /&gt;
   if(ExpansionBase)&lt;br /&gt;
      CloseLibrary(ExpansionBase);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*----------------------------------*/&lt;br /&gt;
/* Print out the contents of the    */&lt;br /&gt;
/* dev structure for this expansion */&lt;br /&gt;
/* product.                         */&lt;br /&gt;
/*----------------------------------*/&lt;br /&gt;
&lt;br /&gt;
void printdev(dev)&lt;br /&gt;
struct ConfigDev *dev;&lt;br /&gt;
{&lt;br /&gt;
   char buff[200];&lt;br /&gt;
&lt;br /&gt;
   printf(&amp;quot;Flags          = &amp;quot;);&lt;br /&gt;
   if(dev-&amp;gt;cd_Flags==NULL)&lt;br /&gt;
      printf(&amp;quot;NULL  &amp;quot;);&lt;br /&gt;
   if(dev-&amp;gt;cd_Flags&amp;amp;CDF_SHUTUP)&lt;br /&gt;
      printf(&amp;quot;CDF_SHUTUP  &amp;quot;);&lt;br /&gt;
   if(dev-&amp;gt;cd_Flags&amp;amp;CDF_CONFIGME)&lt;br /&gt;
      printf(&amp;quot;CDF_CONFIGME  &amp;quot;);&lt;br /&gt;
   printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
   printf(&amp;quot;Board Address  = %x\n&amp;quot;,dev-&amp;gt;cd_BoardAddr);&lt;br /&gt;
   printf(&amp;quot;Board Size     = %d bytes\n&amp;quot;,dev-&amp;gt;cd_BoardSize);&lt;br /&gt;
   printf(&amp;quot;Slot  Address  = %d\n&amp;quot;,dev-&amp;gt;cd_SlotAddr);&lt;br /&gt;
   printf(&amp;quot;Slot  Size     = %d\n&amp;quot;,dev-&amp;gt;cd_SlotSize);&lt;br /&gt;
   printf(&amp;quot;Driver code at   %x\n&amp;quot;,dev-&amp;gt;cd_Driver);&lt;br /&gt;
&lt;br /&gt;
   printf(&amp;quot;er_Type         = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Type);&lt;br /&gt;
   printf(&amp;quot;er_Product      = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Product);&lt;br /&gt;
   printf(&amp;quot;er_Flags        = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Flags);&lt;br /&gt;
   printf(&amp;quot;er_Reserved03   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved03);&lt;br /&gt;
   printf(&amp;quot;er_Manufacturer = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Manufacturer);&lt;br /&gt;
   printf(&amp;quot;er_SerialNumber = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_SerialNumber);&lt;br /&gt;
   printf(&amp;quot;er_InitDiagVec  = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_InitDiagVec);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0c   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0c);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0d   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0d);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0e   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0e);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0f   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0f);&lt;br /&gt;
&lt;br /&gt;
   printf(&amp;quot;Hit Return to continue:\n&amp;quot;);&lt;br /&gt;
   gets(buff);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Registry =&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! ID (decimal)&lt;br /&gt;
! ID (hexadecimal)&lt;br /&gt;
! Manufacturer&lt;br /&gt;
! Notes&lt;br /&gt;
|-&lt;br /&gt;
| 1&lt;br /&gt;
| 0001&lt;br /&gt;
| Micronik&lt;br /&gt;
|-&lt;br /&gt;
| 211&lt;br /&gt;
| 00D3&lt;br /&gt;
| Pacific Peripherals/Profex&lt;br /&gt;
|-&lt;br /&gt;
| 221&lt;br /&gt;
| 00DD&lt;br /&gt;
| Kupke Computertechnik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 256&lt;br /&gt;
| 0100&lt;br /&gt;
| Memphis&lt;br /&gt;
| Originally registered to MacroSystems US&lt;br /&gt;
|-&lt;br /&gt;
| 512&lt;br /&gt;
| 0200&lt;br /&gt;
| 3-State Computertechnik&lt;br /&gt;
|-&lt;br /&gt;
| 513&lt;br /&gt;
| 0201&lt;br /&gt;
| Commodore (Braunschweig)&lt;br /&gt;
|-&lt;br /&gt;
| 514&lt;br /&gt;
| 0202&lt;br /&gt;
| Commodore (West Chester)&lt;br /&gt;
|-&lt;br /&gt;
| 515&lt;br /&gt;
| 0203&lt;br /&gt;
| Commodore (West Chester)&lt;br /&gt;
| Originally registered to Combitech/Macrosystem&lt;br /&gt;
|-&lt;br /&gt;
| 756&lt;br /&gt;
| 02F4&lt;br /&gt;
| Progressive Peripherals &amp;amp; Software&lt;br /&gt;
|-&lt;br /&gt;
| 767&lt;br /&gt;
| 02FF&lt;br /&gt;
| Kolff Computer Supplies&lt;br /&gt;
|-&lt;br /&gt;
| 1001&lt;br /&gt;
| 03E9&lt;br /&gt;
| Tecmar&lt;br /&gt;
|-&lt;br /&gt;
| 1002&lt;br /&gt;
| 03EA&lt;br /&gt;
| Telesys&lt;br /&gt;
|-&lt;br /&gt;
| 1003&lt;br /&gt;
| 03EB&lt;br /&gt;
| The Micro-Forge&lt;br /&gt;
|-&lt;br /&gt;
| 1004&lt;br /&gt;
| 03EC&lt;br /&gt;
| Kronos/C Ltd.&lt;br /&gt;
| Originally registered to Card Co. (Supra)&lt;br /&gt;
|-&lt;br /&gt;
| 1005&lt;br /&gt;
| 03ED&lt;br /&gt;
| A-Squared&lt;br /&gt;
|-&lt;br /&gt;
| 1006&lt;br /&gt;
| 03EE&lt;br /&gt;
| Comspec Communications&lt;br /&gt;
|-&lt;br /&gt;
| 1007&lt;br /&gt;
| 03EF&lt;br /&gt;
| HT Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 1008&lt;br /&gt;
| 03F0&lt;br /&gt;
| RDS Software&lt;br /&gt;
|-&lt;br /&gt;
| 1009&lt;br /&gt;
| 03F1&lt;br /&gt;
| Anakin Research&lt;br /&gt;
|-&lt;br /&gt;
| 1010&lt;br /&gt;
| 03F2&lt;br /&gt;
| MicroBotics&lt;br /&gt;
|-&lt;br /&gt;
| 1011&lt;br /&gt;
| 03F3&lt;br /&gt;
| Bob Krauth&lt;br /&gt;
|-&lt;br /&gt;
| 1012&lt;br /&gt;
| 03F4&lt;br /&gt;
| Access Associates (Alegra)&lt;br /&gt;
|-&lt;br /&gt;
| 1013&lt;br /&gt;
| 03F5&lt;br /&gt;
| Mini Comp Systems Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 1014&lt;br /&gt;
| 03F6&lt;br /&gt;
| Cypress Technology&lt;br /&gt;
|-&lt;br /&gt;
| 1015&lt;br /&gt;
| 03F7&lt;br /&gt;
| Fuller Computers&lt;br /&gt;
|-&lt;br /&gt;
| 1016&lt;br /&gt;
| 03F8&lt;br /&gt;
| Galaxy Computers&lt;br /&gt;
|-&lt;br /&gt;
| 1017&lt;br /&gt;
| 03F9&lt;br /&gt;
| ADA Research&lt;br /&gt;
|-&lt;br /&gt;
| 1018&lt;br /&gt;
| 03FA&lt;br /&gt;
| Computer Service Italia&lt;br /&gt;
|-&lt;br /&gt;
| 1019&lt;br /&gt;
| 03FB&lt;br /&gt;
| Amigo&lt;br /&gt;
|-&lt;br /&gt;
| 1020&lt;br /&gt;
| 03FC&lt;br /&gt;
| Micro-Solutions Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1021&lt;br /&gt;
| 03FD&lt;br /&gt;
| Stacar International&lt;br /&gt;
|-&lt;br /&gt;
| 1022&lt;br /&gt;
| 03FE&lt;br /&gt;
| Video Precisions&lt;br /&gt;
|-&lt;br /&gt;
| 1023&lt;br /&gt;
| 03FF&lt;br /&gt;
| ASDG, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1025&lt;br /&gt;
| 0401&lt;br /&gt;
| Ing. Buero Kalawsky&lt;br /&gt;
|-&lt;br /&gt;
| 1026&lt;br /&gt;
| 0402&lt;br /&gt;
| Computer Tuning&lt;br /&gt;
|-&lt;br /&gt;
| 1027&lt;br /&gt;
| 0403&lt;br /&gt;
| Interplan Unternehmensberatung&lt;br /&gt;
|-&lt;br /&gt;
| 1028&lt;br /&gt;
| 0404&lt;br /&gt;
| Imtronics/Memphis&lt;br /&gt;
| Originally registered to Peter Ohlich&lt;br /&gt;
|-&lt;br /&gt;
| 1030&lt;br /&gt;
| 0406&lt;br /&gt;
| Commodore (Lowell University)&lt;br /&gt;
| Originally registered to Productivity Center&lt;br /&gt;
|-&lt;br /&gt;
| 1041&lt;br /&gt;
| 0411&lt;br /&gt;
| Design Labs&lt;br /&gt;
|-&lt;br /&gt;
| 1042&lt;br /&gt;
| 0412&lt;br /&gt;
| MCS&lt;br /&gt;
|-&lt;br /&gt;
| 1043&lt;br /&gt;
| 0413&lt;br /&gt;
| B. J. Freeman&lt;br /&gt;
|-&lt;br /&gt;
| 1044&lt;br /&gt;
| 0414&lt;br /&gt;
| Side Effects Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1045&lt;br /&gt;
| 0415&lt;br /&gt;
| Oklahoma Personal Comp.&lt;br /&gt;
|-&lt;br /&gt;
| 1046&lt;br /&gt;
| 0416&lt;br /&gt;
| Advanced Micro Innovations&lt;br /&gt;
|-&lt;br /&gt;
| 1047&lt;br /&gt;
| 0417&lt;br /&gt;
| Industrial Support Services&lt;br /&gt;
|-&lt;br /&gt;
| 1048&lt;br /&gt;
| 0418&lt;br /&gt;
| Technisoft&lt;br /&gt;
|-&lt;br /&gt;
| 1049&lt;br /&gt;
| 0419&lt;br /&gt;
| Prolific, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1050&lt;br /&gt;
| 041A&lt;br /&gt;
| Softeam, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1051&lt;br /&gt;
| 041B&lt;br /&gt;
| GRC Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 1052&lt;br /&gt;
| 041C&lt;br /&gt;
| David Lai&lt;br /&gt;
|-&lt;br /&gt;
| 1053&lt;br /&gt;
| 041D&lt;br /&gt;
| Ameristar Technologies&lt;br /&gt;
|-&lt;br /&gt;
| 1054&lt;br /&gt;
| 041E&lt;br /&gt;
| Cline Refrigeration&lt;br /&gt;
|-&lt;br /&gt;
| 1055&lt;br /&gt;
| 041F&lt;br /&gt;
| Cardiac Pacemakers, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1056&lt;br /&gt;
| 0420&lt;br /&gt;
| Supra Corp. (Creative Microsystems)&lt;br /&gt;
|-&lt;br /&gt;
| 1057&lt;br /&gt;
| 0421&lt;br /&gt;
| Wayne Diener&lt;br /&gt;
|-&lt;br /&gt;
| 1058&lt;br /&gt;
| 0422&lt;br /&gt;
| Computer Systems Associates (CSA)&lt;br /&gt;
|-&lt;br /&gt;
| 1059&lt;br /&gt;
| 0423&lt;br /&gt;
| Trionix, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1060&lt;br /&gt;
| 0424&lt;br /&gt;
| David Lucas&lt;br /&gt;
|-&lt;br /&gt;
| 1061&lt;br /&gt;
| 0425&lt;br /&gt;
| Analog Precision&lt;br /&gt;
| Also assigned to D &amp;amp; L Distributing&lt;br /&gt;
|-&lt;br /&gt;
| 1267&lt;br /&gt;
| 04F3&lt;br /&gt;
| RBM Digitaltechnik&lt;br /&gt;
|-&lt;br /&gt;
| 1282&lt;br /&gt;
| 0502&lt;br /&gt;
| M-TEC Hardware Design&lt;br /&gt;
|-&lt;br /&gt;
| 1337&lt;br /&gt;
| 0539&lt;br /&gt;
| Thomas Stenzel (DaFR34K)&lt;br /&gt;
|-&lt;br /&gt;
| 1576&lt;br /&gt;
| 0628&lt;br /&gt;
| Boris Križma&lt;br /&gt;
|-&lt;br /&gt;
| 1729&lt;br /&gt;
| 06C1&lt;br /&gt;
| Thomas Richter / OpenPCI-A1200 Mediator bridge&lt;br /&gt;
|-&lt;br /&gt;
| 1730&lt;br /&gt;
| 06C2&lt;br /&gt;
| Thomas Richter / OpenPCI-A4000 Mediator bridge&lt;br /&gt;
|-&lt;br /&gt;
| 1731&lt;br /&gt;
| 06C3&lt;br /&gt;
| Thomas Richter / OpenPCI-Prometheus bridge (Firestorm or original)&lt;br /&gt;
|-&lt;br /&gt;
| 1732&lt;br /&gt;
| 06C4&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved1&lt;br /&gt;
|-&lt;br /&gt;
| 1733&lt;br /&gt;
| 06C5&lt;br /&gt;
| Thomas Richter / OpenPCI-Grex bridge (both A1200 and A4000)&lt;br /&gt;
|-&lt;br /&gt;
| 1734&lt;br /&gt;
| 06C6&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved2&lt;br /&gt;
|-&lt;br /&gt;
| 1735&lt;br /&gt;
| 06C7&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved3&lt;br /&gt;
|-&lt;br /&gt;
| 1736&lt;br /&gt;
| 06C8&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved4&lt;br /&gt;
|-&lt;br /&gt;
| 1737&lt;br /&gt;
| 06C9&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved5&lt;br /&gt;
|-&lt;br /&gt;
| 1738&lt;br /&gt;
| 06CA&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved6&lt;br /&gt;
|-&lt;br /&gt;
| 1739&lt;br /&gt;
| 06CB&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved7&lt;br /&gt;
|-&lt;br /&gt;
| 1740&lt;br /&gt;
| 06CC&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved8&lt;br /&gt;
|-&lt;br /&gt;
| 1741&lt;br /&gt;
| 06CD&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved9&lt;br /&gt;
|-&lt;br /&gt;
| 1742&lt;br /&gt;
| 06CE&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved10&lt;br /&gt;
|-&lt;br /&gt;
| 1743&lt;br /&gt;
| 06CF&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved11&lt;br /&gt;
|-&lt;br /&gt;
| 1744&lt;br /&gt;
| 06D0&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved12&lt;br /&gt;
|-&lt;br /&gt;
| 1761&lt;br /&gt;
| 06E1&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
|-&lt;br /&gt;
| 1803&lt;br /&gt;
| 070B&lt;br /&gt;
| UAE Amiga Emulator&lt;br /&gt;
|-&lt;br /&gt;
| 2002&lt;br /&gt;
| 07D2&lt;br /&gt;
| Mimetics Corp.&lt;br /&gt;
|-&lt;br /&gt;
| 2003&lt;br /&gt;
| 07D3&lt;br /&gt;
| ACDA&lt;br /&gt;
|-&lt;br /&gt;
| 2004&lt;br /&gt;
| 07D4&lt;br /&gt;
| Finn R. Jacobsen&lt;br /&gt;
|-&lt;br /&gt;
| 2005&lt;br /&gt;
| 07D5&lt;br /&gt;
| Elthen Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2006&lt;br /&gt;
| 07D6&lt;br /&gt;
| Nine Tiles Computer Systems Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2007&lt;br /&gt;
| 07D7&lt;br /&gt;
| Analog Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2008&lt;br /&gt;
| 07D8&lt;br /&gt;
| Bell &amp;amp;amp; Howell&lt;br /&gt;
|-&lt;br /&gt;
| 2009&lt;br /&gt;
| 07D9&lt;br /&gt;
| Roland Kochler&lt;br /&gt;
|-&lt;br /&gt;
| 2010&lt;br /&gt;
| 07DA&lt;br /&gt;
| Byte Corp.&lt;br /&gt;
|-&lt;br /&gt;
| 2011&lt;br /&gt;
| 07DB&lt;br /&gt;
| Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 2012&lt;br /&gt;
| 07DC&lt;br /&gt;
| DKB, Inc.&lt;br /&gt;
| Previously named Michigan Software&lt;br /&gt;
|-&lt;br /&gt;
| 2013&lt;br /&gt;
| 07DD&lt;br /&gt;
| Pacific Peripherals&lt;br /&gt;
|-&lt;br /&gt;
| 2014&lt;br /&gt;
| 07DE&lt;br /&gt;
| Sysaphus Software&lt;br /&gt;
|-&lt;br /&gt;
| 2015&lt;br /&gt;
| 07DF&lt;br /&gt;
| Digitronics&lt;br /&gt;
|-&lt;br /&gt;
| 2016&lt;br /&gt;
| 07E0&lt;br /&gt;
| Akron Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2017&lt;br /&gt;
| 07E1&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
|-&lt;br /&gt;
| 2018&lt;br /&gt;
| 07E2&lt;br /&gt;
| Calmos&lt;br /&gt;
|-&lt;br /&gt;
| 2019&lt;br /&gt;
| 07E3&lt;br /&gt;
| Dover Research&lt;br /&gt;
|-&lt;br /&gt;
| 2020&lt;br /&gt;
| 07E4&lt;br /&gt;
| David Krehbiel&lt;br /&gt;
|-&lt;br /&gt;
| 2021&lt;br /&gt;
| 07E5&lt;br /&gt;
| Synergy Peripheral Systems&lt;br /&gt;
| Also known as California Access&lt;br /&gt;
|-&lt;br /&gt;
| 2022&lt;br /&gt;
| 07E6&lt;br /&gt;
| Xetec&lt;br /&gt;
|-&lt;br /&gt;
| 2023&lt;br /&gt;
| 07E7&lt;br /&gt;
| Micron Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2024&lt;br /&gt;
| 07E8&lt;br /&gt;
| CH Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2025&lt;br /&gt;
| 07E9&lt;br /&gt;
| American Liquid Light&lt;br /&gt;
|-&lt;br /&gt;
| 2026&lt;br /&gt;
| 07EA&lt;br /&gt;
| Progressive Peripherals &amp;amp;amp; Software&lt;br /&gt;
| Also used by Ateo&lt;br /&gt;
|-&lt;br /&gt;
| 2027&lt;br /&gt;
| 07EB&lt;br /&gt;
| Wicat Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2028&lt;br /&gt;
| 07EC&lt;br /&gt;
| Applied Systems &amp;amp;amp; Peripherals&lt;br /&gt;
|-&lt;br /&gt;
| 2029&lt;br /&gt;
| 07ED&lt;br /&gt;
| Delaware Valley Software&lt;br /&gt;
|-&lt;br /&gt;
| 2030&lt;br /&gt;
| 07EE&lt;br /&gt;
| Palomax&lt;br /&gt;
|-&lt;br /&gt;
| 2031&lt;br /&gt;
| 07EF&lt;br /&gt;
| Incognito Software&lt;br /&gt;
|-&lt;br /&gt;
| 2032&lt;br /&gt;
| 07F0&lt;br /&gt;
| Jadesign&lt;br /&gt;
|-&lt;br /&gt;
| 2033&lt;br /&gt;
| 07F1&lt;br /&gt;
| BVR&lt;br /&gt;
|-&lt;br /&gt;
| 2034&lt;br /&gt;
| 07F2&lt;br /&gt;
| Spirit Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2035&lt;br /&gt;
| 07F3&lt;br /&gt;
| Spirit Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2036&lt;br /&gt;
| 07F4&lt;br /&gt;
| Atronic&lt;br /&gt;
|-&lt;br /&gt;
| 2037&lt;br /&gt;
| 07F5&lt;br /&gt;
| Scott Karlin&lt;br /&gt;
|-&lt;br /&gt;
| 2038&lt;br /&gt;
| 07F6&lt;br /&gt;
| Howitch&lt;br /&gt;
|-&lt;br /&gt;
| 2039&lt;br /&gt;
| 07F7&lt;br /&gt;
| Sullivan Brothers Visual Engineers&lt;br /&gt;
|-&lt;br /&gt;
| 2040&lt;br /&gt;
| 07F8&lt;br /&gt;
| G I T&lt;br /&gt;
|-&lt;br /&gt;
| 2041&lt;br /&gt;
| 07F9&lt;br /&gt;
| Amigo Business Computers&lt;br /&gt;
|-&lt;br /&gt;
| 2042&lt;br /&gt;
| 07FA&lt;br /&gt;
| Micro E Ab&lt;br /&gt;
|-&lt;br /&gt;
| 2043&lt;br /&gt;
| 07FB&lt;br /&gt;
| Ralph Kruse&lt;br /&gt;
|-&lt;br /&gt;
| 2044&lt;br /&gt;
| 07FC&lt;br /&gt;
| Clearpoint Research&lt;br /&gt;
|-&lt;br /&gt;
| 2045&lt;br /&gt;
| 07FD&lt;br /&gt;
| Kodiak&lt;br /&gt;
|-&lt;br /&gt;
| 2046&lt;br /&gt;
| 07FE&lt;br /&gt;
| BSC&lt;br /&gt;
| Originally registered to Phoenix Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2047&lt;br /&gt;
| 07FF&lt;br /&gt;
| No Name Shown&lt;br /&gt;
|-&lt;br /&gt;
| 2048&lt;br /&gt;
| 0800&lt;br /&gt;
| Commodore Braunschweig&lt;br /&gt;
|-&lt;br /&gt;
| 2049&lt;br /&gt;
| 0801&lt;br /&gt;
| BSC&lt;br /&gt;
| Originally registered to Elaborate Bytes&lt;br /&gt;
|-&lt;br /&gt;
| 2050&lt;br /&gt;
| 0802&lt;br /&gt;
| Kronos/C Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2051&lt;br /&gt;
| 0803&lt;br /&gt;
| Spartanics&lt;br /&gt;
|-&lt;br /&gt;
| 2052&lt;br /&gt;
| 0804&lt;br /&gt;
| Jochheim Computer Tuning&lt;br /&gt;
|-&lt;br /&gt;
| 2053&lt;br /&gt;
| 0805&lt;br /&gt;
| Trans Data Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2054&lt;br /&gt;
| 0806&lt;br /&gt;
| Applied Systems &amp;amp;amp; Peripherals Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2055&lt;br /&gt;
| 0807&lt;br /&gt;
| Checkpoint Technologies&lt;br /&gt;
| Originally registered to Amiga Solutions&lt;br /&gt;
|-&lt;br /&gt;
| 2056&lt;br /&gt;
| 0808&lt;br /&gt;
| Adept Development&lt;br /&gt;
|-&lt;br /&gt;
| 2057&lt;br /&gt;
| 0809&lt;br /&gt;
| Advanced Computer Design&lt;br /&gt;
|-&lt;br /&gt;
| 2058&lt;br /&gt;
| 080A&lt;br /&gt;
| Sir Netics&lt;br /&gt;
|-&lt;br /&gt;
| 2059&lt;br /&gt;
| 080B&lt;br /&gt;
| Expert Services&lt;br /&gt;
|-&lt;br /&gt;
| 2060&lt;br /&gt;
| 080C&lt;br /&gt;
| Digital Art Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2061&lt;br /&gt;
| 080D&lt;br /&gt;
| Adept Development&lt;br /&gt;
|-&lt;br /&gt;
| 2062&lt;br /&gt;
| 080E&lt;br /&gt;
| Expansion Technologies (Expansion Systems)&lt;br /&gt;
|-&lt;br /&gt;
| 2063&lt;br /&gt;
| 080F&lt;br /&gt;
| Alphatech&lt;br /&gt;
|-&lt;br /&gt;
| 2064&lt;br /&gt;
| 0810&lt;br /&gt;
| Edotronik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2065&lt;br /&gt;
| 0811&lt;br /&gt;
| California Access/Synergy&lt;br /&gt;
| Originally registered to Logical Design Works&lt;br /&gt;
|-&lt;br /&gt;
| 2066&lt;br /&gt;
| 0812&lt;br /&gt;
| Bowden, Williams, Full &amp;amp; Assoc.&lt;br /&gt;
|-&lt;br /&gt;
| 2067&lt;br /&gt;
| 0813&lt;br /&gt;
| NES, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2068&lt;br /&gt;
| 0814&lt;br /&gt;
| Amdev&lt;br /&gt;
|-&lt;br /&gt;
| 2069&lt;br /&gt;
| 0815&lt;br /&gt;
| Big Brother Security Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2070&lt;br /&gt;
| 0816&lt;br /&gt;
| Active Circuits Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2071&lt;br /&gt;
| 0817&lt;br /&gt;
| ICD, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2072&lt;br /&gt;
| 0818&lt;br /&gt;
| Multi-Meg Electronique&lt;br /&gt;
|-&lt;br /&gt;
| 2073&lt;br /&gt;
| 0819&lt;br /&gt;
| Kupke Computertechnik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2074&lt;br /&gt;
| 081A&lt;br /&gt;
| The Checkered Ball&lt;br /&gt;
|-&lt;br /&gt;
| 2075&lt;br /&gt;
| 081B&lt;br /&gt;
| Hi Tension Computer Services Ltd. (UK)&lt;br /&gt;
|-&lt;br /&gt;
| 2076&lt;br /&gt;
| 081C&lt;br /&gt;
| Alfa Data&lt;br /&gt;
| Originally assigned to Elmtech Research, Ltd. (UK)&lt;br /&gt;
|-&lt;br /&gt;
| 2077&lt;br /&gt;
| 081D&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
| Originally registered to Clartscreen, Ltd. (UK)&lt;br /&gt;
|-&lt;br /&gt;
| 2078&lt;br /&gt;
| 081E&lt;br /&gt;
| Interworks&lt;br /&gt;
|-&lt;br /&gt;
| 2079&lt;br /&gt;
| 081F&lt;br /&gt;
| Galysh Enterprises&lt;br /&gt;
|-&lt;br /&gt;
| 2080&lt;br /&gt;
| 0820&lt;br /&gt;
| Hardital Synthesis&lt;br /&gt;
| Originally registered to Realtime Games Software Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2081&lt;br /&gt;
| 0821&lt;br /&gt;
| GBS&lt;br /&gt;
|-&lt;br /&gt;
| 2082&lt;br /&gt;
| 0822&lt;br /&gt;
| Circum Design Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2083&lt;br /&gt;
| 0823&lt;br /&gt;
| Alberta Micro Electronic Center&lt;br /&gt;
|-&lt;br /&gt;
| 2084&lt;br /&gt;
| 0824&lt;br /&gt;
| Bestech&lt;br /&gt;
|-&lt;br /&gt;
| 2085&lt;br /&gt;
| 0825&lt;br /&gt;
| Lasar Fantasy&lt;br /&gt;
|-&lt;br /&gt;
| 2086&lt;br /&gt;
| 0826&lt;br /&gt;
| Pulsar&lt;br /&gt;
|-&lt;br /&gt;
| 2087&lt;br /&gt;
| 0827&lt;br /&gt;
| Ivis&lt;br /&gt;
|-&lt;br /&gt;
| 2088&lt;br /&gt;
| 0828&lt;br /&gt;
| Applied Engineering&lt;br /&gt;
|-&lt;br /&gt;
| 2089&lt;br /&gt;
| 0829&lt;br /&gt;
| Solid-State Design &amp;amp;amp; Development&lt;br /&gt;
|-&lt;br /&gt;
| 2090&lt;br /&gt;
| 082A&lt;br /&gt;
| Vison Quest&lt;br /&gt;
|-&lt;br /&gt;
| 2091&lt;br /&gt;
| 082B&lt;br /&gt;
| Seaview Software&lt;br /&gt;
|-&lt;br /&gt;
| 2092&lt;br /&gt;
| 082C&lt;br /&gt;
| BSC&lt;br /&gt;
| Mistakenly used by ADS (Advanced Development Software)&lt;br /&gt;
|-&lt;br /&gt;
| 2093&lt;br /&gt;
| 082D&lt;br /&gt;
| Bernd Culenfeld&lt;br /&gt;
|-&lt;br /&gt;
| 2094&lt;br /&gt;
| 082E&lt;br /&gt;
| American Liquid Light&lt;br /&gt;
|-&lt;br /&gt;
| 2095&lt;br /&gt;
| 082F&lt;br /&gt;
| CEGITES&lt;br /&gt;
|-&lt;br /&gt;
| 2096&lt;br /&gt;
| 0830&lt;br /&gt;
| Quadlite Computers Ltd.&lt;br /&gt;
| Originally registered to EV Industries&lt;br /&gt;
|-&lt;br /&gt;
| 2097&lt;br /&gt;
| 0831&lt;br /&gt;
| Silicon Peace&lt;br /&gt;
|-&lt;br /&gt;
| 2098&lt;br /&gt;
| 0832&lt;br /&gt;
| Black Belt Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2099&lt;br /&gt;
| 0833&lt;br /&gt;
| Village Tronic&lt;br /&gt;
| Originally registerd to Steve Yaeger&lt;br /&gt;
|-&lt;br /&gt;
| 2100&lt;br /&gt;
| 0834&lt;br /&gt;
| ReadySoft&lt;br /&gt;
|-&lt;br /&gt;
| 2101&lt;br /&gt;
| 0835&lt;br /&gt;
| Phoenix Micro Technologies&lt;br /&gt;
|-&lt;br /&gt;
| 2102&lt;br /&gt;
| 0836&lt;br /&gt;
| Advanced Systems &amp;amp; Software&lt;br /&gt;
| Orignally assigned to Preferred Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2103&lt;br /&gt;
| 0837&lt;br /&gt;
| Rombo Productions&lt;br /&gt;
|-&lt;br /&gt;
| 2104&lt;br /&gt;
| 0838&lt;br /&gt;
| Impulse Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2105&lt;br /&gt;
| 0839&lt;br /&gt;
| Beta Unlimited&lt;br /&gt;
|-&lt;br /&gt;
| 2106&lt;br /&gt;
| 083A&lt;br /&gt;
| Memory Expansion System, Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2107&lt;br /&gt;
| 083B&lt;br /&gt;
| Vortex Computer Systems GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2108&lt;br /&gt;
| 083C&lt;br /&gt;
| Platypus Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2109&lt;br /&gt;
| 083D&lt;br /&gt;
| Gigatron OHG&lt;br /&gt;
|-&lt;br /&gt;
| 2110&lt;br /&gt;
| 083E&lt;br /&gt;
| PG Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2111&lt;br /&gt;
| 083F&lt;br /&gt;
| New Technologies Group&lt;br /&gt;
|-&lt;br /&gt;
| 2112&lt;br /&gt;
| 0840&lt;br /&gt;
| Interactive Video Systems (IVS)&lt;br /&gt;
| Pacific Peripherals&lt;br /&gt;
|-&lt;br /&gt;
| 2113&lt;br /&gt;
| 0841&lt;br /&gt;
| Vector&lt;br /&gt;
| Originally registered to H. K. Computer&lt;br /&gt;
|-&lt;br /&gt;
| 2114&lt;br /&gt;
| 0842&lt;br /&gt;
| Pacific Digital&lt;br /&gt;
| Originally registered to C. H. Helfrich Elektronik&lt;br /&gt;
|-&lt;br /&gt;
| 2115&lt;br /&gt;
| 0843&lt;br /&gt;
| Xanadu&lt;br /&gt;
|-&lt;br /&gt;
| 2116&lt;br /&gt;
| 0844&lt;br /&gt;
| Pacific Digital&lt;br /&gt;
| Originally registered to AMS&lt;br /&gt;
|-&lt;br /&gt;
| 2117&lt;br /&gt;
| 0845&lt;br /&gt;
| X-Pert&lt;br /&gt;
|-&lt;br /&gt;
| 2118&lt;br /&gt;
| 0846&lt;br /&gt;
| The Amiga Centre&lt;br /&gt;
|-&lt;br /&gt;
| 2119&lt;br /&gt;
| 0847&lt;br /&gt;
| Digital Pacific&lt;br /&gt;
|-&lt;br /&gt;
| 2120&lt;br /&gt;
| 0848&lt;br /&gt;
| Solid State Leisure&lt;br /&gt;
|-&lt;br /&gt;
| 2121&lt;br /&gt;
| 0849&lt;br /&gt;
| Hydra Systems&lt;br /&gt;
| Originally registered to Analog Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2122&lt;br /&gt;
| 084A&lt;br /&gt;
| Cumana&lt;br /&gt;
|-&lt;br /&gt;
| 2123&lt;br /&gt;
| 084B&lt;br /&gt;
| KAPS 2C Conception&lt;br /&gt;
|-&lt;br /&gt;
| 2124&lt;br /&gt;
| 084C&lt;br /&gt;
| Mike Mason&lt;br /&gt;
|-&lt;br /&gt;
| 2125&lt;br /&gt;
| 084D&lt;br /&gt;
| For Your Eyes&lt;br /&gt;
|-&lt;br /&gt;
| 2126&lt;br /&gt;
| 084E&lt;br /&gt;
| Volkmar Breitfeld Computersysteme&lt;br /&gt;
|-&lt;br /&gt;
| 2127&lt;br /&gt;
| 084F&lt;br /&gt;
| Sunrize Industries&lt;br /&gt;
|-&lt;br /&gt;
| 2128&lt;br /&gt;
| 0850&lt;br /&gt;
| Scott Advanced Micro Designs&lt;br /&gt;
|-&lt;br /&gt;
| 2129&lt;br /&gt;
| 0851&lt;br /&gt;
| Digital Micronics&lt;br /&gt;
|-&lt;br /&gt;
| 2130&lt;br /&gt;
| 0852&lt;br /&gt;
| Alfa-Laval&lt;br /&gt;
|-&lt;br /&gt;
| 2131&lt;br /&gt;
| 0853&lt;br /&gt;
| Multigros A/S&lt;br /&gt;
|-&lt;br /&gt;
| 2132&lt;br /&gt;
| 0854&lt;br /&gt;
| Archos&lt;br /&gt;
|-&lt;br /&gt;
| 2133&lt;br /&gt;
| 0855&lt;br /&gt;
| Icom Simulations&lt;br /&gt;
|-&lt;br /&gt;
| 2134&lt;br /&gt;
| 0856&lt;br /&gt;
| Commodore Test Engineering Group&lt;br /&gt;
|-&lt;br /&gt;
| 2135&lt;br /&gt;
| 0857&lt;br /&gt;
| Microcreations&lt;br /&gt;
|-&lt;br /&gt;
| 2136&lt;br /&gt;
| 0858&lt;br /&gt;
| Shoestring Productions&lt;br /&gt;
|-&lt;br /&gt;
| 2137&lt;br /&gt;
| 0859&lt;br /&gt;
| Faberushi&lt;br /&gt;
|-&lt;br /&gt;
| 2138&lt;br /&gt;
| 085A&lt;br /&gt;
| Evesham Micro Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2139&lt;br /&gt;
| 085B&lt;br /&gt;
| Panagolin Laser Software&lt;br /&gt;
|-&lt;br /&gt;
| 2140&lt;br /&gt;
| 085C&lt;br /&gt;
| Thomas Rudloff&lt;br /&gt;
|-&lt;br /&gt;
| 2141&lt;br /&gt;
| 085D&lt;br /&gt;
| Daniel Hohabir&lt;br /&gt;
|-&lt;br /&gt;
| 2142&lt;br /&gt;
| 085E&lt;br /&gt;
| GfxBase, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2143&lt;br /&gt;
| 085F&lt;br /&gt;
| Axellabs&lt;br /&gt;
|-&lt;br /&gt;
| 2144&lt;br /&gt;
| 0860&lt;br /&gt;
| Roctec Electronics Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2145&lt;br /&gt;
| 0861&lt;br /&gt;
| Omega Datentechnik&lt;br /&gt;
|-&lt;br /&gt;
| 2146&lt;br /&gt;
| 0862&lt;br /&gt;
| Atlantis&lt;br /&gt;
|-&lt;br /&gt;
| 2147&lt;br /&gt;
| 0863&lt;br /&gt;
| Skytec Computers&lt;br /&gt;
|-&lt;br /&gt;
| 2148&lt;br /&gt;
| 0864&lt;br /&gt;
| Protar Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2149&lt;br /&gt;
| 0865&lt;br /&gt;
| ACS&lt;br /&gt;
|-&lt;br /&gt;
| 2150&lt;br /&gt;
| 0866&lt;br /&gt;
| Software Results Enterprises&lt;br /&gt;
| Originally registered to University of Illinois&lt;br /&gt;
|-&lt;br /&gt;
| 2151&lt;br /&gt;
| 0867&lt;br /&gt;
| Infinity Systems Design Group&lt;br /&gt;
|-&lt;br /&gt;
| 2152&lt;br /&gt;
| 0868&lt;br /&gt;
| Trade It&lt;br /&gt;
|-&lt;br /&gt;
| 2153&lt;br /&gt;
| 0869&lt;br /&gt;
| Suntec, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2154&lt;br /&gt;
| 086A&lt;br /&gt;
| DJW Micro Systems&lt;br /&gt;
| Originally registered to Tritec Marketing&lt;br /&gt;
|-&lt;br /&gt;
| 2155&lt;br /&gt;
| 086B&lt;br /&gt;
| Power Computing Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2156&lt;br /&gt;
| 086C&lt;br /&gt;
| MacroSystems&lt;br /&gt;
|-&lt;br /&gt;
| 2157&lt;br /&gt;
| 086D&lt;br /&gt;
| Masoboshi GmbH (DCE)&lt;br /&gt;
|-&lt;br /&gt;
| 2158&lt;br /&gt;
| 086E&lt;br /&gt;
| HAL Software Hardware Handel&lt;br /&gt;
|-&lt;br /&gt;
| 2159&lt;br /&gt;
| 086F&lt;br /&gt;
| Mainhattan Data&lt;br /&gt;
| Originally registered to Michael Lamm Computersysteme&lt;br /&gt;
|-&lt;br /&gt;
| 2160&lt;br /&gt;
| 0870&lt;br /&gt;
| Digital Processing System&lt;br /&gt;
| Originally registered to bbdp Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2161&lt;br /&gt;
| 0871&lt;br /&gt;
| Blue Ribbon Soundworks&lt;br /&gt;
| Originally registered to Design Computer Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2162&lt;br /&gt;
| 0872&lt;br /&gt;
| XPert&lt;br /&gt;
| Originally registered to The Station&lt;br /&gt;
|-&lt;br /&gt;
| 2163&lt;br /&gt;
| 0873&lt;br /&gt;
| DelaComp&lt;br /&gt;
| Originally registered to Bryan Williams&lt;br /&gt;
|-&lt;br /&gt;
| 2164&lt;br /&gt;
| 0874&lt;br /&gt;
| Superformance Computer Engineering GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2165&lt;br /&gt;
| 0875&lt;br /&gt;
| Overland Engineering&lt;br /&gt;
|-&lt;br /&gt;
| 2166&lt;br /&gt;
| 0876&lt;br /&gt;
| Thomas Hamren&lt;br /&gt;
|-&lt;br /&gt;
| 2167&lt;br /&gt;
| 0877&lt;br /&gt;
| Village Tronic&lt;br /&gt;
|-&lt;br /&gt;
| 2168&lt;br /&gt;
| 0878&lt;br /&gt;
| Toolbox Design&lt;br /&gt;
|-&lt;br /&gt;
| 2169&lt;br /&gt;
| 0879&lt;br /&gt;
| Digital Processing System&lt;br /&gt;
|-&lt;br /&gt;
| 2170&lt;br /&gt;
| 087A&lt;br /&gt;
| Superformance&lt;br /&gt;
|-&lt;br /&gt;
| 2171&lt;br /&gt;
| 087B&lt;br /&gt;
| Utilities Unlimited&lt;br /&gt;
|-&lt;br /&gt;
| 2172&lt;br /&gt;
| 087C&lt;br /&gt;
| phase 5&lt;br /&gt;
|-&lt;br /&gt;
| 2173&lt;br /&gt;
| 087D&lt;br /&gt;
| Juergen Kommos&lt;br /&gt;
|-&lt;br /&gt;
| 2174&lt;br /&gt;
| 087E&lt;br /&gt;
| Electronic Design&lt;br /&gt;
|-&lt;br /&gt;
| 2175&lt;br /&gt;
| 087F&lt;br /&gt;
| James Cook University of North Queensland&lt;br /&gt;
|-&lt;br /&gt;
| 2176&lt;br /&gt;
| 0880&lt;br /&gt;
| AmiTrix Development&lt;br /&gt;
|-&lt;br /&gt;
| 2177&lt;br /&gt;
| 0881&lt;br /&gt;
| Ferranti&lt;br /&gt;
|-&lt;br /&gt;
| 2178&lt;br /&gt;
| 0882&lt;br /&gt;
| Leviathan Development&lt;br /&gt;
|-&lt;br /&gt;
| 2179&lt;br /&gt;
| 0883&lt;br /&gt;
| United Video Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2180&lt;br /&gt;
| 0884&lt;br /&gt;
| GPSoft Pty. Ltd.&lt;br /&gt;
| Originally registered to Juergen Kommos&lt;br /&gt;
|-&lt;br /&gt;
| 2181&lt;br /&gt;
| 0885&lt;br /&gt;
| ArMAX&lt;br /&gt;
| Oliver Bausch&lt;br /&gt;
|-&lt;br /&gt;
| 2182&lt;br /&gt;
| 0886&lt;br /&gt;
| CP Computer&lt;br /&gt;
|-&lt;br /&gt;
| 2183&lt;br /&gt;
| 0887&lt;br /&gt;
| Amiga Modula &amp;amp;amp; Oberon Klub&lt;br /&gt;
|-&lt;br /&gt;
| 2184&lt;br /&gt;
| 0888&lt;br /&gt;
| ITEK Neser &amp;amp;amp; Sieber GbR&lt;br /&gt;
|-&lt;br /&gt;
| 2185&lt;br /&gt;
| 0889&lt;br /&gt;
| Phillip C. Lello&lt;br /&gt;
|-&lt;br /&gt;
| 2186&lt;br /&gt;
| 088A&lt;br /&gt;
| Cyborg Design Services&lt;br /&gt;
|-&lt;br /&gt;
| 2187&lt;br /&gt;
| 088B&lt;br /&gt;
| G2 Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2188&lt;br /&gt;
| 088C&lt;br /&gt;
| Pro System Computersysteme&lt;br /&gt;
|-&lt;br /&gt;
| 2189&lt;br /&gt;
| 088D&lt;br /&gt;
| ZEUS Electronic&lt;br /&gt;
| Originally registered to MSPI (Markt &amp;amp;amp; Technik)&lt;br /&gt;
|-&lt;br /&gt;
| 2190&lt;br /&gt;
| 088E&lt;br /&gt;
| Altatech&lt;br /&gt;
|-&lt;br /&gt;
| 2191&lt;br /&gt;
| 088F&lt;br /&gt;
| NewTek&lt;br /&gt;
|-&lt;br /&gt;
| 2192&lt;br /&gt;
| 0890&lt;br /&gt;
| M-TEC Hardware Design&lt;br /&gt;
| Originally registered to Hardware Design Udo Neuroth&lt;br /&gt;
|-&lt;br /&gt;
| 2193&lt;br /&gt;
| 0891&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
| Originally registered to Viona Development&lt;br /&gt;
|-&lt;br /&gt;
| 2194&lt;br /&gt;
| 0892&lt;br /&gt;
| Amitek&lt;br /&gt;
| Originally assigned to Marpet Developments&lt;br /&gt;
|-&lt;br /&gt;
| 2195&lt;br /&gt;
| 0893&lt;br /&gt;
| Ingenieurbuero Helfrich&lt;br /&gt;
|-&lt;br /&gt;
| 2196&lt;br /&gt;
| 0894&lt;br /&gt;
| The Neo Group&lt;br /&gt;
|-&lt;br /&gt;
| 2197&lt;br /&gt;
| 0895&lt;br /&gt;
| Cyon&lt;br /&gt;
|-&lt;br /&gt;
| 2198&lt;br /&gt;
| 0896&lt;br /&gt;
| Bob Research Group&lt;br /&gt;
|-&lt;br /&gt;
| 2199&lt;br /&gt;
| 0897&lt;br /&gt;
| Richmond Sound Design Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2200&lt;br /&gt;
| 0898&lt;br /&gt;
| US Cybernetics&lt;br /&gt;
|-&lt;br /&gt;
| 2201&lt;br /&gt;
| 0899&lt;br /&gt;
| Fulvio Ieva&lt;br /&gt;
|-&lt;br /&gt;
| 2202&lt;br /&gt;
| 089A&lt;br /&gt;
| Silicon Studio&lt;br /&gt;
|-&lt;br /&gt;
| 2203&lt;br /&gt;
| 089B&lt;br /&gt;
| MacroSystems (USA)&lt;br /&gt;
| Was named Micro System Devices&lt;br /&gt;
|-&lt;br /&gt;
| 2204&lt;br /&gt;
| 089C&lt;br /&gt;
| Conspector Entertainment&lt;br /&gt;
|-&lt;br /&gt;
| 2205&lt;br /&gt;
| 089D&lt;br /&gt;
| Laserforum&lt;br /&gt;
|-&lt;br /&gt;
| 2206&lt;br /&gt;
| 089E&lt;br /&gt;
| Elbox Computer&lt;br /&gt;
| Mistakenly used by Index Information Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2207&lt;br /&gt;
| 089F&lt;br /&gt;
| Applied Magic Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2208&lt;br /&gt;
| 08A0&lt;br /&gt;
| SDL Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2560&lt;br /&gt;
| 0A00&lt;br /&gt;
| Harms&lt;br /&gt;
|-&lt;br /&gt;
| 2588&lt;br /&gt;
| 0A1C&lt;br /&gt;
| A1K.org Community&lt;br /&gt;
|-&lt;br /&gt;
| 2640&lt;br /&gt;
| 0A50&lt;br /&gt;
| Micronik&lt;br /&gt;
|-&lt;br /&gt;
| 2782&lt;br /&gt;
| 2782&lt;br /&gt;
| OA Design&lt;br /&gt;
|-&lt;br /&gt;
| 3084&lt;br /&gt;
| 0C0C&lt;br /&gt;
| Team 4&lt;br /&gt;
|-&lt;br /&gt;
| 3643&lt;br /&gt;
| 0E3B&lt;br /&gt;
| E3B&lt;br /&gt;
| Michael Boehmer&lt;br /&gt;
|-&lt;br /&gt;
| 3855&lt;br /&gt;
| 0F0F&lt;br /&gt;
| Micronik&lt;br /&gt;
|-&lt;br /&gt;
| 4096&lt;br /&gt;
| 1000&lt;br /&gt;
| MegaMicro&lt;br /&gt;
|-&lt;br /&gt;
| 4110&lt;br /&gt;
| 100E&lt;br /&gt;
| DigiFeX&lt;br /&gt;
|-&lt;br /&gt;
| 4136&lt;br /&gt;
| 1028&lt;br /&gt;
| Imtronics/Memphis&lt;br /&gt;
|-&lt;br /&gt;
| 4149&lt;br /&gt;
| 1035&lt;br /&gt;
| PROTAR&lt;br /&gt;
|-&lt;br /&gt;
| 4369&lt;br /&gt;
| 1111&lt;br /&gt;
| Frank Strauß Elektronik&lt;br /&gt;
| Also used by Kupke&lt;br /&gt;
|-&lt;br /&gt;
| 4626&lt;br /&gt;
| 1212&lt;br /&gt;
| Individual Computers&lt;br /&gt;
|-&lt;br /&gt;
| 4648&lt;br /&gt;
| 1228&lt;br /&gt;
| Flesch Hornemann Computer Elec.&lt;br /&gt;
|-&lt;br /&gt;
| 4680&lt;br /&gt;
| 1248&lt;br /&gt;
| Kupke Computertechnik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 4711&lt;br /&gt;
| 1267&lt;br /&gt;
| RBM digitaltechnik&lt;br /&gt;
|-&lt;br /&gt;
| 4754&lt;br /&gt;
| 1292&lt;br /&gt;
| MacroSystems&lt;br /&gt;
|-&lt;br /&gt;
| 5000&lt;br /&gt;
| 1388&lt;br /&gt;
| ITH&lt;br /&gt;
|-&lt;br /&gt;
| 5001&lt;br /&gt;
| 1389&lt;br /&gt;
| VMC&lt;br /&gt;
|-&lt;br /&gt;
| 5010&lt;br /&gt;
| 1392&lt;br /&gt;
| Ambience Creation Technology&lt;br /&gt;
|-&lt;br /&gt;
| 5011&lt;br /&gt;
| 1393&lt;br /&gt;
| Creative Development&lt;br /&gt;
|-&lt;br /&gt;
| 5012&lt;br /&gt;
| 1394&lt;br /&gt;
| Georg Braun&lt;br /&gt;
|-&lt;br /&gt;
| 5013&lt;br /&gt;
| 1395&lt;br /&gt;
| Swedish User Group of Amiga&lt;br /&gt;
|-&lt;br /&gt;
| 5014&lt;br /&gt;
| 1396&lt;br /&gt;
| Jakub Bednarski&lt;br /&gt;
|-&lt;br /&gt;
| 5015&lt;br /&gt;
| 1397&lt;br /&gt;
| KryoFlux, Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 5016&lt;br /&gt;
| 1398&lt;br /&gt;
| Igor Majstorovic&lt;br /&gt;
|-&lt;br /&gt;
| 5017&lt;br /&gt;
| 1399&lt;br /&gt;
| Alastair M. Robinson&lt;br /&gt;
|-&lt;br /&gt;
| 5018&lt;br /&gt;
| 139A&lt;br /&gt;
| Austex Software&lt;br /&gt;
|-&lt;br /&gt;
| 5019&lt;br /&gt;
| 139B&lt;br /&gt;
| Sören Gust&lt;br /&gt;
|-&lt;br /&gt;
| 5020&lt;br /&gt;
| 139C&lt;br /&gt;
| Rok Krajnc&lt;br /&gt;
|-&lt;br /&gt;
| 5030&lt;br /&gt;
| 13A6&lt;br /&gt;
| Tim Tashpulatov&lt;br /&gt;
|-&lt;br /&gt;
| 5040&lt;br /&gt;
| 13B0&lt;br /&gt;
| 7-bit&lt;br /&gt;
|-&lt;br /&gt;
| 5050&lt;br /&gt;
| 13BA&lt;br /&gt;
| Sakura IT&lt;br /&gt;
|-&lt;br /&gt;
| 5060&lt;br /&gt;
| 13C4&lt;br /&gt;
| FPGAArcade&lt;br /&gt;
|-&lt;br /&gt;
| 5070&lt;br /&gt;
| 13CE&lt;br /&gt;
| CancerSoft Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 5080&lt;br /&gt;
| 13D8&lt;br /&gt;
| Stephen Leary&lt;br /&gt;
|-&lt;br /&gt;
| 5090&lt;br /&gt;
| 13E2&lt;br /&gt;
| DMA Softlab LLC&lt;br /&gt;
|-&lt;br /&gt;
| 5100&lt;br /&gt;
| 13EC&lt;br /&gt;
| Brookhouse Engineering&lt;br /&gt;
|-&lt;br /&gt;
| 5110&lt;br /&gt;
| 13F6&lt;br /&gt;
| Eduardo Arana&lt;br /&gt;
|-&lt;br /&gt;
| 5120&lt;br /&gt;
| 1400&lt;br /&gt;
| CS-LAB&lt;br /&gt;
|-&lt;br /&gt;
| 5130&lt;br /&gt;
| 140A&lt;br /&gt;
| Robert Miranda&lt;br /&gt;
|-&lt;br /&gt;
| 5132&lt;br /&gt;
| 140C&lt;br /&gt;
| UAS Interface Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 5140&lt;br /&gt;
| 1414&lt;br /&gt;
| RastPort&lt;br /&gt;
|-&lt;br /&gt;
| 5150&lt;br /&gt;
| 141E&lt;br /&gt;
| Amiga Kit&lt;br /&gt;
|-&lt;br /&gt;
| 5160&lt;br /&gt;
| 1428&lt;br /&gt;
| Central Texas Commodore User Group&lt;br /&gt;
|-&lt;br /&gt;
| 5170&lt;br /&gt;
| 1432&lt;br /&gt;
| Confusion Research Center&lt;br /&gt;
|-&lt;br /&gt;
| 5180&lt;br /&gt;
| 143C&lt;br /&gt;
| Solar Soyuz Zaibatsu&lt;br /&gt;
|-&lt;br /&gt;
| 5190&lt;br /&gt;
| 1446&lt;br /&gt;
| BooBip&lt;br /&gt;
|-&lt;br /&gt;
| 5191&lt;br /&gt;
| 1447&lt;br /&gt;
| Matthias Hampel&lt;br /&gt;
|-&lt;br /&gt;
| 5192&lt;br /&gt;
| 1448&lt;br /&gt;
| dec0de Consulting Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 5193&lt;br /&gt;
| 1449&lt;br /&gt;
| Puppy Concepts&lt;br /&gt;
|-&lt;br /&gt;
| 5194&lt;br /&gt;
| 144A&lt;br /&gt;
| Open Amiga Hardware Repository&lt;br /&gt;
|-&lt;br /&gt;
| 5195&lt;br /&gt;
| 144B&lt;br /&gt;
| Double H Tech&lt;br /&gt;
|-&lt;br /&gt;
| 5196&lt;br /&gt;
| 144C&lt;br /&gt;
| Retromatik&lt;br /&gt;
|-&lt;br /&gt;
| 5500&lt;br /&gt;
| 157C&lt;br /&gt;
| Inhouse Information&lt;br /&gt;
|-&lt;br /&gt;
| 5768&lt;br /&gt;
| 1688&lt;br /&gt;
| Bio Con&lt;br /&gt;
|-&lt;br /&gt;
| 6148&lt;br /&gt;
| 1804&lt;br /&gt;
| HK-Computer&lt;br /&gt;
|-&lt;br /&gt;
| 6502&lt;br /&gt;
| 1966&lt;br /&gt;
| Cloanto&lt;br /&gt;
|-&lt;br /&gt;
| 6520&lt;br /&gt;
| 1978&lt;br /&gt;
| Oliver Gantert&lt;br /&gt;
|-&lt;br /&gt;
| 7777&lt;br /&gt;
| 1E61&lt;br /&gt;
| Rafal Gabriel Chyla&lt;br /&gt;
|-&lt;br /&gt;
| 8215&lt;br /&gt;
| 2017&lt;br /&gt;
| Vortex&lt;br /&gt;
|-&lt;br /&gt;
| 8244&lt;br /&gt;
| 2034&lt;br /&gt;
| Spirit Technology&lt;br /&gt;
|-&lt;br /&gt;
| 8290&lt;br /&gt;
| 2062&lt;br /&gt;
| Expansion Systems&lt;br /&gt;
|-&lt;br /&gt;
| 8448&lt;br /&gt;
| 2100&lt;br /&gt;
| ReadySoft&lt;br /&gt;
|-&lt;br /&gt;
| 8512&lt;br /&gt;
| 2140&lt;br /&gt;
| Phase 5 Digital Products&lt;br /&gt;
|-&lt;br /&gt;
| 8553&lt;br /&gt;
| 2169&lt;br /&gt;
| Digital Processing Systems Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 8704&lt;br /&gt;
| 2200&lt;br /&gt;
| ACT Elektronik&lt;br /&gt;
|-&lt;br /&gt;
| 8738&lt;br /&gt;
| 2222&lt;br /&gt;
| ACT Elektronik&lt;br /&gt;
|-&lt;br /&gt;
| 9512&lt;br /&gt;
| 2528&lt;br /&gt;
| Tower Technologies&lt;br /&gt;
|-&lt;br /&gt;
| 10676&lt;br /&gt;
| 29B4&lt;br /&gt;
| Electronic Design&lt;br /&gt;
|-&lt;br /&gt;
| 14195&lt;br /&gt;
| 3773&lt;br /&gt;
| Media-net-Point&lt;br /&gt;
|-&lt;br /&gt;
| 14501&lt;br /&gt;
| 38A5&lt;br /&gt;
| Petsoff, Finland&lt;br /&gt;
|-&lt;br /&gt;
| 16375&lt;br /&gt;
| 3FF7&lt;br /&gt;
| Uwe Gerlach&lt;br /&gt;
|-&lt;br /&gt;
| 16707&lt;br /&gt;
| 4143&lt;br /&gt;
| Ateo Concepts&lt;br /&gt;
|-&lt;br /&gt;
| 16708&lt;br /&gt;
| 4144&lt;br /&gt;
| ALiENDESiGN&lt;br /&gt;
|-&lt;br /&gt;
| 16945&lt;br /&gt;
| 4231&lt;br /&gt;
| A.C.T.&lt;br /&gt;
|-&lt;br /&gt;
| 17740&lt;br /&gt;
| 454C&lt;br /&gt;
| HK-Computer (ELSAT)&lt;br /&gt;
|-&lt;br /&gt;
| 18260&lt;br /&gt;
| 4754&lt;br /&gt;
| MacroSystems (Germany)&lt;br /&gt;
|-&lt;br /&gt;
| 19796&lt;br /&gt;
| 4D54&lt;br /&gt;
| Markt &amp;amp; Technik&lt;br /&gt;
|-&lt;br /&gt;
| 20480&lt;br /&gt;
| 5000&lt;br /&gt;
| François Lacombe&lt;br /&gt;
|-&lt;br /&gt;
| 22359&lt;br /&gt;
| 5757&lt;br /&gt;
| Markt &amp;amp; Technik&lt;br /&gt;
|-&lt;br /&gt;
| 26464&lt;br /&gt;
| 6760&lt;br /&gt;
| Combitec&lt;br /&gt;
|-&lt;br /&gt;
| 26470&lt;br /&gt;
| 6766&lt;br /&gt;
| Combitec&lt;br /&gt;
|-&lt;br /&gt;
| 28014&lt;br /&gt;
| 6D6E&lt;br /&gt;
| MNT Media and Technology UG&lt;br /&gt;
|-&lt;br /&gt;
| 28019&lt;br /&gt;
| 6D73&lt;br /&gt;
| Michal Schulz&lt;br /&gt;
|-&lt;br /&gt;
| 28020&lt;br /&gt;
| 6D74&lt;br /&gt;
| PiStorm&lt;br /&gt;
|-&lt;br /&gt;
| 32768&lt;br /&gt;
| 8000&lt;br /&gt;
| M.A.S.T.&lt;br /&gt;
|-&lt;br /&gt;
| 42240&lt;br /&gt;
| A500&lt;br /&gt;
| Aethreum Digital&lt;br /&gt;
|-&lt;br /&gt;
| 43437&lt;br /&gt;
| A9AD&lt;br /&gt;
| Reis-Ware&lt;br /&gt;
|-&lt;br /&gt;
| 43521&lt;br /&gt;
| AA01&lt;br /&gt;
| Cameron&lt;br /&gt;
|-&lt;br /&gt;
| 43537&lt;br /&gt;
| AA11&lt;br /&gt;
| Reis-Ware&lt;br /&gt;
|-&lt;br /&gt;
| 44359&lt;br /&gt;
| AD47&lt;br /&gt;
| Matay&lt;br /&gt;
|-&lt;br /&gt;
| 45141&lt;br /&gt;
| B055&lt;br /&gt;
| Tim Schattkowsky&lt;br /&gt;
|-&lt;br /&gt;
| 46504&lt;br /&gt;
| B5A8&lt;br /&gt;
| Phoenix&lt;br /&gt;
|-&lt;br /&gt;
| 48879&lt;br /&gt;
| BEEF&lt;br /&gt;
| Swiss Mountain Dog Products&lt;br /&gt;
|-&lt;br /&gt;
| 49160&lt;br /&gt;
| C008&lt;br /&gt;
| Combitec&lt;br /&gt;
|-&lt;br /&gt;
| 49374&lt;br /&gt;
| C0DE&lt;br /&gt;
| Stefan Reinauer&lt;br /&gt;
|-&lt;br /&gt;
| 61453&lt;br /&gt;
| F00D&lt;br /&gt;
| Forefront Technologies Inc.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
For any changes/additions to this registry see [[#How_to_Obtain_a_Manufacturer_Number|How to Obtain a Manufacturer Number]]&lt;/div&gt;</summary>
		<author><name>Costel Mincea</name></author>
	</entry>
	<entry>
		<id>https://wiki.amigaos.net/w/index.php?title=Amiga_Hardware_Manufacturer_ID_Registry&amp;diff=12607</id>
		<title>Amiga Hardware Manufacturer ID Registry</title>
		<link rel="alternate" type="text/html" href="https://wiki.amigaos.net/w/index.php?title=Amiga_Hardware_Manufacturer_ID_Registry&amp;diff=12607"/>
		<updated>2026-09-08T11:23:24Z</updated>

		<summary type="html">&lt;p&gt;Costel Mincea: /* Registry */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
= How to Obtain a Manufacturer Number =&lt;br /&gt;
&lt;br /&gt;
Manufacturer&#039;s numbers are assigned by the AmigaOS development team. To obtain your unique manufacturer number send a support request to [mailto:support@hyperion-entertainment.com support@hyperion-entertainment.com] including these information:&lt;br /&gt;
&lt;br /&gt;
 1. The name of the company or person which the number is assigned to&lt;br /&gt;
 &lt;br /&gt;
 2. Postal address/contact address&lt;br /&gt;
 &lt;br /&gt;
 3. Name of the contact person, with a corresponding e-mail address&lt;br /&gt;
 &lt;br /&gt;
 4. A brief description of the kind of products you want to produce&lt;br /&gt;
&lt;br /&gt;
= Your Manufacturer Number =&lt;br /&gt;
&lt;br /&gt;
Attention hardware manufacturers. If you are developing a hardware expansion product for the Classic Amiga (e.g. 500, 2000, 3000) then you will need to obtain a special manufacturer ID number from the AmigaOS development team to identify your product. This manufacturer number is used by the Amiga to link your hardware with its driver software at boot time.&lt;br /&gt;
&lt;br /&gt;
Your manufacturer number is part of the special protocol that the Amiga uses to automatically configure all expansion devices on the bus without the user having to cut jumpers or adjust dip switches. This is called auto-config.&lt;br /&gt;
&lt;br /&gt;
At start-up time, the system first polls each board in the system and assigns the board its own address space. If it is a memory board, its RAM is linked into the memory free pool. Later in the boot sequence, after DOS is initialized, the binddrivers program is run. Binddrivers will search the directory SYS:Expansion for the drivers that go with the boards.&lt;br /&gt;
&lt;br /&gt;
To do this binddrivers looks in the Tool Type field of all icon files in SYS:Expansion. If the first seven bytes of the Tool Type field are &amp;quot;PRODUCT&amp;quot;, then this is an icon file for a driver.&lt;br /&gt;
&lt;br /&gt;
Binddrivers will then attempt to match the drivers it has found with the boards that were found earlier. This is where your manufacturer number comes in.&lt;br /&gt;
&lt;br /&gt;
Your manufacturer number goes in two places. First, it is burned in hex form into the PAL which is part of ALL auto-config expansion products. Second, it appears in ASCII in the Tool Type field of the icon file for your product&#039;s driver. By matching these two numbers, the Amiga can automatically configure your board and bind it&#039;s software driver into the system as well.&lt;br /&gt;
&lt;br /&gt;
The manufacturer&#039;s number is a 16-bit ID which appears in PAL offsets $10-$17. There is also an 8-bit product number which you assign. The product number is for uniquely identifying different products from the same vendor. The product number will appear in PAL offsets $04-$07. This gives you a total of 24 bits to identify each of your products.&lt;br /&gt;
&lt;br /&gt;
These 24 bits of information in the PAL which identify your product are matched against the information in the Tool Type field of all icon files in the SYS:Expansion drawer. For example, suppose you are manufacturer #1019. You have two products, #1 and #2 which both use the same driver. The icon for your driver for these two products would have a Tool Type set to &amp;quot;PRODUCT=1019/1|1019/2&amp;quot;. This means: I am an icon for a driver that works with product number 1 or 2 from manufacturer 1019, now bind me. Spaces are not legal. Here are two other examples:&lt;br /&gt;
&lt;br /&gt;
; PRODUCT=1208/11&lt;br /&gt;
: is the Tool Type for a driver for product 11 from manufacturer number 1208.&lt;br /&gt;
&lt;br /&gt;
; PRODUCT=1017&lt;br /&gt;
: is the Tool Type for a driver for any product from manufacturer number 1017.&lt;br /&gt;
&lt;br /&gt;
For an informal explanation of the auto-configuration process, see the chapter on Software Expansion Architecture from the 2nd Annual Amiga Developer&#039;s Conference Notes (available on ADCD 2.1). For the details of timing, power, the PAL equations and PAL address specifications and the expansion library documentation, see sections 3.1 to 3.3 of the A500/A2000 Technical Reference Manual. The original auto-config spec appears in the A1000 Schematics and Expansion Specification.&lt;br /&gt;
&lt;br /&gt;
The auto-config process makes the addition of expansion products to the system very easy. All the user has to do is put the board in any slot and copy the driver from the release disk to his own SYS:Expansion drawer. Everything else is automatic. There are no jumpers or dip switches to set. Best of all, you will get a lot less support calls asking how to make your product work with the XYZ-Corp-battery-backed-clock.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
&lt;br /&gt;
Some notes on hardware manufacturer ID assignment.&lt;br /&gt;
&lt;br /&gt;
* Manufacturer ID numbers are assigned free of charge.&lt;br /&gt;
* Please provide the following information when requesting an ID:&lt;br /&gt;
*# Name of the company or person&lt;br /&gt;
*# Postal address/contact address&lt;br /&gt;
*# Name of the contact person, with a corresponding e-mail address&lt;br /&gt;
*# A brief description of the kind of products you want to produce&lt;br /&gt;
* All ID numbers smaller than 5000 must be considered unsafe because no information exists on which numbers exactly were taken during the time Commodore, Inc. disintegrated.&lt;br /&gt;
* ID numbers in the range 8192 to 18841 must be considered unsafe because some hardware developers mistook the numbers assigned to them to be given in hexadecimal format. Hence 0x2000 = 8192 and 0x4999 = 18841.&lt;br /&gt;
&lt;br /&gt;
= Example code =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
/*-----------------------------------------------*/&lt;br /&gt;
/* Here is a short program which will tell you   */&lt;br /&gt;
/* about the expansion boards configured in your */&lt;br /&gt;
/* system without you opening up the machine.    */&lt;br /&gt;
/* Code by Bill Koester of CATS                  */&lt;br /&gt;
/*-----------------------------------------------*/&lt;br /&gt;
#include &amp;lt;libraries/configvars.h&amp;gt;&lt;br /&gt;
#include &amp;lt;libraries/expansion.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
struct ExpansionBase *ExpansionBase;&lt;br /&gt;
&lt;br /&gt;
void cleanup();&lt;br /&gt;
void printdev();&lt;br /&gt;
&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
   struct ConfigDev *MyConfigDev;&lt;br /&gt;
&lt;br /&gt;
   /*----------------------------------*/&lt;br /&gt;
   /* Open the expansion library,      */&lt;br /&gt;
   /* if there is a problem then exit  */&lt;br /&gt;
   /*----------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   ExpansionBase =(struct ExpansionBase *) OpenLibrary(EXPANSIONNAME,0);&lt;br /&gt;
   if(ExpansionBase==NULL)&lt;br /&gt;
   {&lt;br /&gt;
      printf(&amp;quot;Error opening expansion library!!\n&amp;quot;);&lt;br /&gt;
      cleanup();&lt;br /&gt;
      exit(0);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   /*--------------------------------------------*/&lt;br /&gt;
   /* Use FindConfigDev to get info on the first */&lt;br /&gt;
   /* expansion board on the list maintained by  */&lt;br /&gt;
   /* Exec.  If there are no expansion boards in */&lt;br /&gt;
   /* the system then exit.                      */&lt;br /&gt;
   /*--------------------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   MyConfigDev = NULL;&lt;br /&gt;
&lt;br /&gt;
  /*--------------------------------------------------*/&lt;br /&gt;
  /* FindConfigDev(oldConfigDev,manufacturer,product) */&lt;br /&gt;
  /* oldConfigDev = NULL for the top of the list      */&lt;br /&gt;
  /* manufacturer = -1 for any manufacturer           */&lt;br /&gt;
  /* product      = -1 for any product                */&lt;br /&gt;
  /*--------------------------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   MyConfigDev = FindConfigDev(NULL,-1,-1);&lt;br /&gt;
&lt;br /&gt;
   if(MyConfigDev==NULL)&lt;br /&gt;
   {&lt;br /&gt;
      printf(&amp;quot;No Configured Devices found!!\n&amp;quot;);&lt;br /&gt;
      cleanup();&lt;br /&gt;
      exit(0);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   printdev(MyConfigDev);&lt;br /&gt;
&lt;br /&gt;
   /*-----------------------------------*/&lt;br /&gt;
   /* OK, there is at least one board,  */&lt;br /&gt;
   /* so loop and get the entire list   */&lt;br /&gt;
   /* printing as we go with printdev() */&lt;br /&gt;
   /*-----------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   while(MyConfigDev = FindConfigDev(MyConfigDev,-1,-1))&lt;br /&gt;
   {&lt;br /&gt;
      printdev(MyConfigDev);&lt;br /&gt;
   }&lt;br /&gt;
   cleanup();&lt;br /&gt;
   return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*-------------------*/&lt;br /&gt;
/* Close up shop...  */&lt;br /&gt;
/*-------------------*/&lt;br /&gt;
void cleanup()&lt;br /&gt;
{&lt;br /&gt;
   if(ExpansionBase)&lt;br /&gt;
      CloseLibrary(ExpansionBase);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*----------------------------------*/&lt;br /&gt;
/* Print out the contents of the    */&lt;br /&gt;
/* dev structure for this expansion */&lt;br /&gt;
/* product.                         */&lt;br /&gt;
/*----------------------------------*/&lt;br /&gt;
&lt;br /&gt;
void printdev(dev)&lt;br /&gt;
struct ConfigDev *dev;&lt;br /&gt;
{&lt;br /&gt;
   char buff[200];&lt;br /&gt;
&lt;br /&gt;
   printf(&amp;quot;Flags          = &amp;quot;);&lt;br /&gt;
   if(dev-&amp;gt;cd_Flags==NULL)&lt;br /&gt;
      printf(&amp;quot;NULL  &amp;quot;);&lt;br /&gt;
   if(dev-&amp;gt;cd_Flags&amp;amp;CDF_SHUTUP)&lt;br /&gt;
      printf(&amp;quot;CDF_SHUTUP  &amp;quot;);&lt;br /&gt;
   if(dev-&amp;gt;cd_Flags&amp;amp;CDF_CONFIGME)&lt;br /&gt;
      printf(&amp;quot;CDF_CONFIGME  &amp;quot;);&lt;br /&gt;
   printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
   printf(&amp;quot;Board Address  = %x\n&amp;quot;,dev-&amp;gt;cd_BoardAddr);&lt;br /&gt;
   printf(&amp;quot;Board Size     = %d bytes\n&amp;quot;,dev-&amp;gt;cd_BoardSize);&lt;br /&gt;
   printf(&amp;quot;Slot  Address  = %d\n&amp;quot;,dev-&amp;gt;cd_SlotAddr);&lt;br /&gt;
   printf(&amp;quot;Slot  Size     = %d\n&amp;quot;,dev-&amp;gt;cd_SlotSize);&lt;br /&gt;
   printf(&amp;quot;Driver code at   %x\n&amp;quot;,dev-&amp;gt;cd_Driver);&lt;br /&gt;
&lt;br /&gt;
   printf(&amp;quot;er_Type         = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Type);&lt;br /&gt;
   printf(&amp;quot;er_Product      = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Product);&lt;br /&gt;
   printf(&amp;quot;er_Flags        = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Flags);&lt;br /&gt;
   printf(&amp;quot;er_Reserved03   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved03);&lt;br /&gt;
   printf(&amp;quot;er_Manufacturer = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Manufacturer);&lt;br /&gt;
   printf(&amp;quot;er_SerialNumber = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_SerialNumber);&lt;br /&gt;
   printf(&amp;quot;er_InitDiagVec  = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_InitDiagVec);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0c   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0c);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0d   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0d);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0e   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0e);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0f   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0f);&lt;br /&gt;
&lt;br /&gt;
   printf(&amp;quot;Hit Return to continue:\n&amp;quot;);&lt;br /&gt;
   gets(buff);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Registry =&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! ID (decimal)&lt;br /&gt;
! ID (hexadecimal)&lt;br /&gt;
! Manufacturer&lt;br /&gt;
! Notes&lt;br /&gt;
|-&lt;br /&gt;
| 1&lt;br /&gt;
| 0001&lt;br /&gt;
| Micronik&lt;br /&gt;
|-&lt;br /&gt;
| 211&lt;br /&gt;
| 00D3&lt;br /&gt;
| Pacific Peripherals/Profex&lt;br /&gt;
|-&lt;br /&gt;
| 221&lt;br /&gt;
| 00DD&lt;br /&gt;
| Kupke Computertechnik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 256&lt;br /&gt;
| 0100&lt;br /&gt;
| Memphis&lt;br /&gt;
| Originally registered to MacroSystems US&lt;br /&gt;
|-&lt;br /&gt;
| 512&lt;br /&gt;
| 0200&lt;br /&gt;
| 3-State Computertechnik&lt;br /&gt;
|-&lt;br /&gt;
| 513&lt;br /&gt;
| 0201&lt;br /&gt;
| Commodore (Braunschweig)&lt;br /&gt;
|-&lt;br /&gt;
| 514&lt;br /&gt;
| 0202&lt;br /&gt;
| Commodore (West Chester)&lt;br /&gt;
|-&lt;br /&gt;
| 515&lt;br /&gt;
| 0203&lt;br /&gt;
| Commodore (West Chester)&lt;br /&gt;
| Originally registered to Combitech/Macrosystem&lt;br /&gt;
|-&lt;br /&gt;
| 756&lt;br /&gt;
| 02F4&lt;br /&gt;
| Progressive Peripherals &amp;amp; Software&lt;br /&gt;
|-&lt;br /&gt;
| 767&lt;br /&gt;
| 02FF&lt;br /&gt;
| Kolff Computer Supplies&lt;br /&gt;
|-&lt;br /&gt;
| 1001&lt;br /&gt;
| 03E9&lt;br /&gt;
| Tecmar&lt;br /&gt;
|-&lt;br /&gt;
| 1002&lt;br /&gt;
| 03EA&lt;br /&gt;
| Telesys&lt;br /&gt;
|-&lt;br /&gt;
| 1003&lt;br /&gt;
| 03EB&lt;br /&gt;
| The Micro-Forge&lt;br /&gt;
|-&lt;br /&gt;
| 1004&lt;br /&gt;
| 03EC&lt;br /&gt;
| Kronos/C Ltd.&lt;br /&gt;
| Originally registered to Card Co. (Supra)&lt;br /&gt;
|-&lt;br /&gt;
| 1005&lt;br /&gt;
| 03ED&lt;br /&gt;
| A-Squared&lt;br /&gt;
|-&lt;br /&gt;
| 1006&lt;br /&gt;
| 03EE&lt;br /&gt;
| Comspec Communications&lt;br /&gt;
|-&lt;br /&gt;
| 1007&lt;br /&gt;
| 03EF&lt;br /&gt;
| HT Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 1008&lt;br /&gt;
| 03F0&lt;br /&gt;
| RDS Software&lt;br /&gt;
|-&lt;br /&gt;
| 1009&lt;br /&gt;
| 03F1&lt;br /&gt;
| Anakin Research&lt;br /&gt;
|-&lt;br /&gt;
| 1010&lt;br /&gt;
| 03F2&lt;br /&gt;
| MicroBotics&lt;br /&gt;
|-&lt;br /&gt;
| 1011&lt;br /&gt;
| 03F3&lt;br /&gt;
| Bob Krauth&lt;br /&gt;
|-&lt;br /&gt;
| 1012&lt;br /&gt;
| 03F4&lt;br /&gt;
| Access Associates (Alegra)&lt;br /&gt;
|-&lt;br /&gt;
| 1013&lt;br /&gt;
| 03F5&lt;br /&gt;
| Mini Comp Systems Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 1014&lt;br /&gt;
| 03F6&lt;br /&gt;
| Cypress Technology&lt;br /&gt;
|-&lt;br /&gt;
| 1015&lt;br /&gt;
| 03F7&lt;br /&gt;
| Fuller Computers&lt;br /&gt;
|-&lt;br /&gt;
| 1016&lt;br /&gt;
| 03F8&lt;br /&gt;
| Galaxy Computers&lt;br /&gt;
|-&lt;br /&gt;
| 1017&lt;br /&gt;
| 03F9&lt;br /&gt;
| ADA Research&lt;br /&gt;
|-&lt;br /&gt;
| 1018&lt;br /&gt;
| 03FA&lt;br /&gt;
| Computer Service Italia&lt;br /&gt;
|-&lt;br /&gt;
| 1019&lt;br /&gt;
| 03FB&lt;br /&gt;
| Amigo&lt;br /&gt;
|-&lt;br /&gt;
| 1020&lt;br /&gt;
| 03FC&lt;br /&gt;
| Micro-Solutions Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1021&lt;br /&gt;
| 03FD&lt;br /&gt;
| Stacar International&lt;br /&gt;
|-&lt;br /&gt;
| 1022&lt;br /&gt;
| 03FE&lt;br /&gt;
| Video Precisions&lt;br /&gt;
|-&lt;br /&gt;
| 1023&lt;br /&gt;
| 03FF&lt;br /&gt;
| ASDG, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1025&lt;br /&gt;
| 0401&lt;br /&gt;
| Ing. Buero Kalawsky&lt;br /&gt;
|-&lt;br /&gt;
| 1026&lt;br /&gt;
| 0402&lt;br /&gt;
| Computer Tuning&lt;br /&gt;
|-&lt;br /&gt;
| 1027&lt;br /&gt;
| 0403&lt;br /&gt;
| Interplan Unternehmensberatung&lt;br /&gt;
|-&lt;br /&gt;
| 1028&lt;br /&gt;
| 0404&lt;br /&gt;
| Imtronics/Memphis&lt;br /&gt;
| Originally registered to Peter Ohlich&lt;br /&gt;
|-&lt;br /&gt;
| 1030&lt;br /&gt;
| 0406&lt;br /&gt;
| Commodore (Lowell University)&lt;br /&gt;
| Originally registered to Productivity Center&lt;br /&gt;
|-&lt;br /&gt;
| 1041&lt;br /&gt;
| 0411&lt;br /&gt;
| Design Labs&lt;br /&gt;
|-&lt;br /&gt;
| 1042&lt;br /&gt;
| 0412&lt;br /&gt;
| MCS&lt;br /&gt;
|-&lt;br /&gt;
| 1043&lt;br /&gt;
| 0413&lt;br /&gt;
| B. J. Freeman&lt;br /&gt;
|-&lt;br /&gt;
| 1044&lt;br /&gt;
| 0414&lt;br /&gt;
| Side Effects Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1045&lt;br /&gt;
| 0415&lt;br /&gt;
| Oklahoma Personal Comp.&lt;br /&gt;
|-&lt;br /&gt;
| 1046&lt;br /&gt;
| 0416&lt;br /&gt;
| Advanced Micro Innovations&lt;br /&gt;
|-&lt;br /&gt;
| 1047&lt;br /&gt;
| 0417&lt;br /&gt;
| Industrial Support Services&lt;br /&gt;
|-&lt;br /&gt;
| 1048&lt;br /&gt;
| 0418&lt;br /&gt;
| Technisoft&lt;br /&gt;
|-&lt;br /&gt;
| 1049&lt;br /&gt;
| 0419&lt;br /&gt;
| Prolific, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1050&lt;br /&gt;
| 041A&lt;br /&gt;
| Softeam, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1051&lt;br /&gt;
| 041B&lt;br /&gt;
| GRC Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 1052&lt;br /&gt;
| 041C&lt;br /&gt;
| David Lai&lt;br /&gt;
|-&lt;br /&gt;
| 1053&lt;br /&gt;
| 041D&lt;br /&gt;
| Ameristar Technologies&lt;br /&gt;
|-&lt;br /&gt;
| 1054&lt;br /&gt;
| 041E&lt;br /&gt;
| Cline Refrigeration&lt;br /&gt;
|-&lt;br /&gt;
| 1055&lt;br /&gt;
| 041F&lt;br /&gt;
| Cardiac Pacemakers, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1056&lt;br /&gt;
| 0420&lt;br /&gt;
| Supra Corp. (Creative Microsystems)&lt;br /&gt;
|-&lt;br /&gt;
| 1057&lt;br /&gt;
| 0421&lt;br /&gt;
| Wayne Diener&lt;br /&gt;
|-&lt;br /&gt;
| 1058&lt;br /&gt;
| 0422&lt;br /&gt;
| Computer Systems Associates (CSA)&lt;br /&gt;
|-&lt;br /&gt;
| 1059&lt;br /&gt;
| 0423&lt;br /&gt;
| Trionix, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1060&lt;br /&gt;
| 0424&lt;br /&gt;
| David Lucas&lt;br /&gt;
|-&lt;br /&gt;
| 1061&lt;br /&gt;
| 0425&lt;br /&gt;
| Analog Precision&lt;br /&gt;
| Also assigned to D &amp;amp; L Distributing&lt;br /&gt;
|-&lt;br /&gt;
| 1267&lt;br /&gt;
| 04F3&lt;br /&gt;
| RBM Digitaltechnik&lt;br /&gt;
|-&lt;br /&gt;
| 1282&lt;br /&gt;
| 0502&lt;br /&gt;
| M-TEC Hardware Design&lt;br /&gt;
|-&lt;br /&gt;
| 1337&lt;br /&gt;
| 0539&lt;br /&gt;
| Thomas Stenzel (DaFR34K)&lt;br /&gt;
|-&lt;br /&gt;
| 1576&lt;br /&gt;
| 0628&lt;br /&gt;
| Boris Križma&lt;br /&gt;
|-&lt;br /&gt;
| 1729&lt;br /&gt;
| 06C1&lt;br /&gt;
| Thomas Richter / OpenPCI-A1200 Mediator bridge&lt;br /&gt;
|-&lt;br /&gt;
| 1730&lt;br /&gt;
| 06C2&lt;br /&gt;
| Thomas Richter / OpenPCI-A4000 Mediator bridge&lt;br /&gt;
|-&lt;br /&gt;
| 1731&lt;br /&gt;
| 06C3&lt;br /&gt;
| Thomas Richter / OpenPCI-Prometheus bridge (Firestorm or original)&lt;br /&gt;
|-&lt;br /&gt;
| 1732&lt;br /&gt;
| 06C4&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved1&lt;br /&gt;
|-&lt;br /&gt;
| 1733&lt;br /&gt;
| 06C5&lt;br /&gt;
| Thomas Richter / OpenPCI-Grex bridge (both A1200 and A4000)&lt;br /&gt;
|-&lt;br /&gt;
| 1734&lt;br /&gt;
| 06C6&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved2&lt;br /&gt;
|-&lt;br /&gt;
| 1735&lt;br /&gt;
| 06C7&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved3&lt;br /&gt;
|-&lt;br /&gt;
| 1736&lt;br /&gt;
| 06C8&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved4&lt;br /&gt;
|-&lt;br /&gt;
| 1737&lt;br /&gt;
| 06C9&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved5&lt;br /&gt;
|-&lt;br /&gt;
| 1738&lt;br /&gt;
| 06CA&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved6&lt;br /&gt;
|-&lt;br /&gt;
| 1739&lt;br /&gt;
| 06CB&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved7&lt;br /&gt;
|-&lt;br /&gt;
| 1740&lt;br /&gt;
| 06CC&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved8&lt;br /&gt;
|-&lt;br /&gt;
| 1741&lt;br /&gt;
| 06CD&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved9&lt;br /&gt;
|-&lt;br /&gt;
| 1742&lt;br /&gt;
| 06CE&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved10&lt;br /&gt;
|-&lt;br /&gt;
| 1743&lt;br /&gt;
| 06CF&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved11&lt;br /&gt;
|-&lt;br /&gt;
| 1744&lt;br /&gt;
| 06D0&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved12&lt;br /&gt;
|-&lt;br /&gt;
| 1761&lt;br /&gt;
| 06E1&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
|-&lt;br /&gt;
| 1803&lt;br /&gt;
| 070B&lt;br /&gt;
| UAE Amiga Emulator&lt;br /&gt;
|-&lt;br /&gt;
| 2002&lt;br /&gt;
| 07D2&lt;br /&gt;
| Mimetics Corp.&lt;br /&gt;
|-&lt;br /&gt;
| 2003&lt;br /&gt;
| 07D3&lt;br /&gt;
| ACDA&lt;br /&gt;
|-&lt;br /&gt;
| 2004&lt;br /&gt;
| 07D4&lt;br /&gt;
| Finn R. Jacobsen&lt;br /&gt;
|-&lt;br /&gt;
| 2005&lt;br /&gt;
| 07D5&lt;br /&gt;
| Elthen Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2006&lt;br /&gt;
| 07D6&lt;br /&gt;
| Nine Tiles Computer Systems Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2007&lt;br /&gt;
| 07D7&lt;br /&gt;
| Analog Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2008&lt;br /&gt;
| 07D8&lt;br /&gt;
| Bell &amp;amp;amp; Howell&lt;br /&gt;
|-&lt;br /&gt;
| 2009&lt;br /&gt;
| 07D9&lt;br /&gt;
| Roland Kochler&lt;br /&gt;
|-&lt;br /&gt;
| 2010&lt;br /&gt;
| 07DA&lt;br /&gt;
| Byte Corp.&lt;br /&gt;
|-&lt;br /&gt;
| 2011&lt;br /&gt;
| 07DB&lt;br /&gt;
| Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 2012&lt;br /&gt;
| 07DC&lt;br /&gt;
| DKB, Inc.&lt;br /&gt;
| Previously named Michigan Software&lt;br /&gt;
|-&lt;br /&gt;
| 2013&lt;br /&gt;
| 07DD&lt;br /&gt;
| Pacific Peripherals&lt;br /&gt;
|-&lt;br /&gt;
| 2014&lt;br /&gt;
| 07DE&lt;br /&gt;
| Sysaphus Software&lt;br /&gt;
|-&lt;br /&gt;
| 2015&lt;br /&gt;
| 07DF&lt;br /&gt;
| Digitronics&lt;br /&gt;
|-&lt;br /&gt;
| 2016&lt;br /&gt;
| 07E0&lt;br /&gt;
| Akron Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2017&lt;br /&gt;
| 07E1&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
|-&lt;br /&gt;
| 2018&lt;br /&gt;
| 07E2&lt;br /&gt;
| Calmos&lt;br /&gt;
|-&lt;br /&gt;
| 2019&lt;br /&gt;
| 07E3&lt;br /&gt;
| Dover Research&lt;br /&gt;
|-&lt;br /&gt;
| 2020&lt;br /&gt;
| 07E4&lt;br /&gt;
| David Krehbiel&lt;br /&gt;
|-&lt;br /&gt;
| 2021&lt;br /&gt;
| 07E5&lt;br /&gt;
| Synergy Peripheral Systems&lt;br /&gt;
| Also known as California Access&lt;br /&gt;
|-&lt;br /&gt;
| 2022&lt;br /&gt;
| 07E6&lt;br /&gt;
| Xetec&lt;br /&gt;
|-&lt;br /&gt;
| 2023&lt;br /&gt;
| 07E7&lt;br /&gt;
| Micron Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2024&lt;br /&gt;
| 07E8&lt;br /&gt;
| CH Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2025&lt;br /&gt;
| 07E9&lt;br /&gt;
| American Liquid Light&lt;br /&gt;
|-&lt;br /&gt;
| 2026&lt;br /&gt;
| 07EA&lt;br /&gt;
| Progressive Peripherals &amp;amp;amp; Software&lt;br /&gt;
| Also used by Ateo&lt;br /&gt;
|-&lt;br /&gt;
| 2027&lt;br /&gt;
| 07EB&lt;br /&gt;
| Wicat Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2028&lt;br /&gt;
| 07EC&lt;br /&gt;
| Applied Systems &amp;amp;amp; Peripherals&lt;br /&gt;
|-&lt;br /&gt;
| 2029&lt;br /&gt;
| 07ED&lt;br /&gt;
| Delaware Valley Software&lt;br /&gt;
|-&lt;br /&gt;
| 2030&lt;br /&gt;
| 07EE&lt;br /&gt;
| Palomax&lt;br /&gt;
|-&lt;br /&gt;
| 2031&lt;br /&gt;
| 07EF&lt;br /&gt;
| Incognito Software&lt;br /&gt;
|-&lt;br /&gt;
| 2032&lt;br /&gt;
| 07F0&lt;br /&gt;
| Jadesign&lt;br /&gt;
|-&lt;br /&gt;
| 2033&lt;br /&gt;
| 07F1&lt;br /&gt;
| BVR&lt;br /&gt;
|-&lt;br /&gt;
| 2034&lt;br /&gt;
| 07F2&lt;br /&gt;
| Spirit Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2035&lt;br /&gt;
| 07F3&lt;br /&gt;
| Spirit Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2036&lt;br /&gt;
| 07F4&lt;br /&gt;
| Atronic&lt;br /&gt;
|-&lt;br /&gt;
| 2037&lt;br /&gt;
| 07F5&lt;br /&gt;
| Scott Karlin&lt;br /&gt;
|-&lt;br /&gt;
| 2038&lt;br /&gt;
| 07F6&lt;br /&gt;
| Howitch&lt;br /&gt;
|-&lt;br /&gt;
| 2039&lt;br /&gt;
| 07F7&lt;br /&gt;
| Sullivan Brothers Visual Engineers&lt;br /&gt;
|-&lt;br /&gt;
| 2040&lt;br /&gt;
| 07F8&lt;br /&gt;
| G I T&lt;br /&gt;
|-&lt;br /&gt;
| 2041&lt;br /&gt;
| 07F9&lt;br /&gt;
| Amigo Business Computers&lt;br /&gt;
|-&lt;br /&gt;
| 2042&lt;br /&gt;
| 07FA&lt;br /&gt;
| Micro E Ab&lt;br /&gt;
|-&lt;br /&gt;
| 2043&lt;br /&gt;
| 07FB&lt;br /&gt;
| Ralph Kruse&lt;br /&gt;
|-&lt;br /&gt;
| 2044&lt;br /&gt;
| 07FC&lt;br /&gt;
| Clearpoint Research&lt;br /&gt;
|-&lt;br /&gt;
| 2045&lt;br /&gt;
| 07FD&lt;br /&gt;
| Kodiak&lt;br /&gt;
|-&lt;br /&gt;
| 2046&lt;br /&gt;
| 07FE&lt;br /&gt;
| BSC&lt;br /&gt;
| Originally registered to Phoenix Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2047&lt;br /&gt;
| 07FF&lt;br /&gt;
| No Name Shown&lt;br /&gt;
|-&lt;br /&gt;
| 2048&lt;br /&gt;
| 0800&lt;br /&gt;
| Commodore Braunschweig&lt;br /&gt;
|-&lt;br /&gt;
| 2049&lt;br /&gt;
| 0801&lt;br /&gt;
| BSC&lt;br /&gt;
| Originally registered to Elaborate Bytes&lt;br /&gt;
|-&lt;br /&gt;
| 2050&lt;br /&gt;
| 0802&lt;br /&gt;
| Kronos/C Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2051&lt;br /&gt;
| 0803&lt;br /&gt;
| Spartanics&lt;br /&gt;
|-&lt;br /&gt;
| 2052&lt;br /&gt;
| 0804&lt;br /&gt;
| Jochheim Computer Tuning&lt;br /&gt;
|-&lt;br /&gt;
| 2053&lt;br /&gt;
| 0805&lt;br /&gt;
| Trans Data Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2054&lt;br /&gt;
| 0806&lt;br /&gt;
| Applied Systems &amp;amp;amp; Peripherals Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2055&lt;br /&gt;
| 0807&lt;br /&gt;
| Checkpoint Technologies&lt;br /&gt;
| Originally registered to Amiga Solutions&lt;br /&gt;
|-&lt;br /&gt;
| 2056&lt;br /&gt;
| 0808&lt;br /&gt;
| Adept Development&lt;br /&gt;
|-&lt;br /&gt;
| 2057&lt;br /&gt;
| 0809&lt;br /&gt;
| Advanced Computer Design&lt;br /&gt;
|-&lt;br /&gt;
| 2058&lt;br /&gt;
| 080A&lt;br /&gt;
| Sir Netics&lt;br /&gt;
|-&lt;br /&gt;
| 2059&lt;br /&gt;
| 080B&lt;br /&gt;
| Expert Services&lt;br /&gt;
|-&lt;br /&gt;
| 2060&lt;br /&gt;
| 080C&lt;br /&gt;
| Digital Art Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2061&lt;br /&gt;
| 080D&lt;br /&gt;
| Adept Development&lt;br /&gt;
|-&lt;br /&gt;
| 2062&lt;br /&gt;
| 080E&lt;br /&gt;
| Expansion Technologies (Expansion Systems)&lt;br /&gt;
|-&lt;br /&gt;
| 2063&lt;br /&gt;
| 080F&lt;br /&gt;
| Alphatech&lt;br /&gt;
|-&lt;br /&gt;
| 2064&lt;br /&gt;
| 0810&lt;br /&gt;
| Edotronik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2065&lt;br /&gt;
| 0811&lt;br /&gt;
| California Access/Synergy&lt;br /&gt;
| Originally registered to Logical Design Works&lt;br /&gt;
|-&lt;br /&gt;
| 2066&lt;br /&gt;
| 0812&lt;br /&gt;
| Bowden, Williams, Full &amp;amp; Assoc.&lt;br /&gt;
|-&lt;br /&gt;
| 2067&lt;br /&gt;
| 0813&lt;br /&gt;
| NES, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2068&lt;br /&gt;
| 0814&lt;br /&gt;
| Amdev&lt;br /&gt;
|-&lt;br /&gt;
| 2069&lt;br /&gt;
| 0815&lt;br /&gt;
| Big Brother Security Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2070&lt;br /&gt;
| 0816&lt;br /&gt;
| Active Circuits Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2071&lt;br /&gt;
| 0817&lt;br /&gt;
| ICD, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2072&lt;br /&gt;
| 0818&lt;br /&gt;
| Multi-Meg Electronique&lt;br /&gt;
|-&lt;br /&gt;
| 2073&lt;br /&gt;
| 0819&lt;br /&gt;
| Kupke Computertechnik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2074&lt;br /&gt;
| 081A&lt;br /&gt;
| The Checkered Ball&lt;br /&gt;
|-&lt;br /&gt;
| 2075&lt;br /&gt;
| 081B&lt;br /&gt;
| Hi Tension Computer Services Ltd. (UK)&lt;br /&gt;
|-&lt;br /&gt;
| 2076&lt;br /&gt;
| 081C&lt;br /&gt;
| Alfa Data&lt;br /&gt;
| Originally assigned to Elmtech Research, Ltd. (UK)&lt;br /&gt;
|-&lt;br /&gt;
| 2077&lt;br /&gt;
| 081D&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
| Originally registered to Clartscreen, Ltd. (UK)&lt;br /&gt;
|-&lt;br /&gt;
| 2078&lt;br /&gt;
| 081E&lt;br /&gt;
| Interworks&lt;br /&gt;
|-&lt;br /&gt;
| 2079&lt;br /&gt;
| 081F&lt;br /&gt;
| Galysh Enterprises&lt;br /&gt;
|-&lt;br /&gt;
| 2080&lt;br /&gt;
| 0820&lt;br /&gt;
| Hardital Synthesis&lt;br /&gt;
| Originally registered to Realtime Games Software Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2081&lt;br /&gt;
| 0821&lt;br /&gt;
| GBS&lt;br /&gt;
|-&lt;br /&gt;
| 2082&lt;br /&gt;
| 0822&lt;br /&gt;
| Circum Design Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2083&lt;br /&gt;
| 0823&lt;br /&gt;
| Alberta Micro Electronic Center&lt;br /&gt;
|-&lt;br /&gt;
| 2084&lt;br /&gt;
| 0824&lt;br /&gt;
| Bestech&lt;br /&gt;
|-&lt;br /&gt;
| 2085&lt;br /&gt;
| 0825&lt;br /&gt;
| Lasar Fantasy&lt;br /&gt;
|-&lt;br /&gt;
| 2086&lt;br /&gt;
| 0826&lt;br /&gt;
| Pulsar&lt;br /&gt;
|-&lt;br /&gt;
| 2087&lt;br /&gt;
| 0827&lt;br /&gt;
| Ivis&lt;br /&gt;
|-&lt;br /&gt;
| 2088&lt;br /&gt;
| 0828&lt;br /&gt;
| Applied Engineering&lt;br /&gt;
|-&lt;br /&gt;
| 2089&lt;br /&gt;
| 0829&lt;br /&gt;
| Solid-State Design &amp;amp;amp; Development&lt;br /&gt;
|-&lt;br /&gt;
| 2090&lt;br /&gt;
| 082A&lt;br /&gt;
| Vison Quest&lt;br /&gt;
|-&lt;br /&gt;
| 2091&lt;br /&gt;
| 082B&lt;br /&gt;
| Seaview Software&lt;br /&gt;
|-&lt;br /&gt;
| 2092&lt;br /&gt;
| 082C&lt;br /&gt;
| BSC&lt;br /&gt;
| Mistakenly used by ADS (Advanced Development Software)&lt;br /&gt;
|-&lt;br /&gt;
| 2093&lt;br /&gt;
| 082D&lt;br /&gt;
| Bernd Culenfeld&lt;br /&gt;
|-&lt;br /&gt;
| 2094&lt;br /&gt;
| 082E&lt;br /&gt;
| American Liquid Light&lt;br /&gt;
|-&lt;br /&gt;
| 2095&lt;br /&gt;
| 082F&lt;br /&gt;
| CEGITES&lt;br /&gt;
|-&lt;br /&gt;
| 2096&lt;br /&gt;
| 0830&lt;br /&gt;
| Quadlite Computers Ltd.&lt;br /&gt;
| Originally registered to EV Industries&lt;br /&gt;
|-&lt;br /&gt;
| 2097&lt;br /&gt;
| 0831&lt;br /&gt;
| Silicon Peace&lt;br /&gt;
|-&lt;br /&gt;
| 2098&lt;br /&gt;
| 0832&lt;br /&gt;
| Black Belt Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2099&lt;br /&gt;
| 0833&lt;br /&gt;
| Village Tronic&lt;br /&gt;
| Originally registerd to Steve Yaeger&lt;br /&gt;
|-&lt;br /&gt;
| 2100&lt;br /&gt;
| 0834&lt;br /&gt;
| ReadySoft&lt;br /&gt;
|-&lt;br /&gt;
| 2101&lt;br /&gt;
| 0835&lt;br /&gt;
| Phoenix Micro Technologies&lt;br /&gt;
|-&lt;br /&gt;
| 2102&lt;br /&gt;
| 0836&lt;br /&gt;
| Advanced Systems &amp;amp; Software&lt;br /&gt;
| Orignally assigned to Preferred Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2103&lt;br /&gt;
| 0837&lt;br /&gt;
| Rombo Productions&lt;br /&gt;
|-&lt;br /&gt;
| 2104&lt;br /&gt;
| 0838&lt;br /&gt;
| Impulse Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2105&lt;br /&gt;
| 0839&lt;br /&gt;
| Beta Unlimited&lt;br /&gt;
|-&lt;br /&gt;
| 2106&lt;br /&gt;
| 083A&lt;br /&gt;
| Memory Expansion System, Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2107&lt;br /&gt;
| 083B&lt;br /&gt;
| Vortex Computer Systems GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2108&lt;br /&gt;
| 083C&lt;br /&gt;
| Platypus Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2109&lt;br /&gt;
| 083D&lt;br /&gt;
| Gigatron OHG&lt;br /&gt;
|-&lt;br /&gt;
| 2110&lt;br /&gt;
| 083E&lt;br /&gt;
| PG Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2111&lt;br /&gt;
| 083F&lt;br /&gt;
| New Technologies Group&lt;br /&gt;
|-&lt;br /&gt;
| 2112&lt;br /&gt;
| 0840&lt;br /&gt;
| Interactive Video Systems (IVS)&lt;br /&gt;
| Pacific Peripherals&lt;br /&gt;
|-&lt;br /&gt;
| 2113&lt;br /&gt;
| 0841&lt;br /&gt;
| Vector&lt;br /&gt;
| Originally registered to H. K. Computer&lt;br /&gt;
|-&lt;br /&gt;
| 2114&lt;br /&gt;
| 0842&lt;br /&gt;
| Pacific Digital&lt;br /&gt;
| Originally registered to C. H. Helfrich Elektronik&lt;br /&gt;
|-&lt;br /&gt;
| 2115&lt;br /&gt;
| 0843&lt;br /&gt;
| Xanadu&lt;br /&gt;
|-&lt;br /&gt;
| 2116&lt;br /&gt;
| 0844&lt;br /&gt;
| Pacific Digital&lt;br /&gt;
| Originally registered to AMS&lt;br /&gt;
|-&lt;br /&gt;
| 2117&lt;br /&gt;
| 0845&lt;br /&gt;
| X-Pert&lt;br /&gt;
|-&lt;br /&gt;
| 2118&lt;br /&gt;
| 0846&lt;br /&gt;
| The Amiga Centre&lt;br /&gt;
|-&lt;br /&gt;
| 2119&lt;br /&gt;
| 0847&lt;br /&gt;
| Digital Pacific&lt;br /&gt;
|-&lt;br /&gt;
| 2120&lt;br /&gt;
| 0848&lt;br /&gt;
| Solid State Leisure&lt;br /&gt;
|-&lt;br /&gt;
| 2121&lt;br /&gt;
| 0849&lt;br /&gt;
| Hydra Systems&lt;br /&gt;
| Originally registered to Analog Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2122&lt;br /&gt;
| 084A&lt;br /&gt;
| Cumana&lt;br /&gt;
|-&lt;br /&gt;
| 2123&lt;br /&gt;
| 084B&lt;br /&gt;
| KAPS 2C Conception&lt;br /&gt;
|-&lt;br /&gt;
| 2124&lt;br /&gt;
| 084C&lt;br /&gt;
| Mike Mason&lt;br /&gt;
|-&lt;br /&gt;
| 2125&lt;br /&gt;
| 084D&lt;br /&gt;
| For Your Eyes&lt;br /&gt;
|-&lt;br /&gt;
| 2126&lt;br /&gt;
| 084E&lt;br /&gt;
| Volkmar Breitfeld Computersysteme&lt;br /&gt;
|-&lt;br /&gt;
| 2127&lt;br /&gt;
| 084F&lt;br /&gt;
| Sunrize Industries&lt;br /&gt;
|-&lt;br /&gt;
| 2128&lt;br /&gt;
| 0850&lt;br /&gt;
| Scott Advanced Micro Designs&lt;br /&gt;
|-&lt;br /&gt;
| 2129&lt;br /&gt;
| 0851&lt;br /&gt;
| Digital Micronics&lt;br /&gt;
|-&lt;br /&gt;
| 2130&lt;br /&gt;
| 0852&lt;br /&gt;
| Alfa-Laval&lt;br /&gt;
|-&lt;br /&gt;
| 2131&lt;br /&gt;
| 0853&lt;br /&gt;
| Multigros A/S&lt;br /&gt;
|-&lt;br /&gt;
| 2132&lt;br /&gt;
| 0854&lt;br /&gt;
| Archos&lt;br /&gt;
|-&lt;br /&gt;
| 2133&lt;br /&gt;
| 0855&lt;br /&gt;
| Icom Simulations&lt;br /&gt;
|-&lt;br /&gt;
| 2134&lt;br /&gt;
| 0856&lt;br /&gt;
| Commodore Test Engineering Group&lt;br /&gt;
|-&lt;br /&gt;
| 2135&lt;br /&gt;
| 0857&lt;br /&gt;
| Microcreations&lt;br /&gt;
|-&lt;br /&gt;
| 2136&lt;br /&gt;
| 0858&lt;br /&gt;
| Shoestring Productions&lt;br /&gt;
|-&lt;br /&gt;
| 2137&lt;br /&gt;
| 0859&lt;br /&gt;
| Faberushi&lt;br /&gt;
|-&lt;br /&gt;
| 2138&lt;br /&gt;
| 085A&lt;br /&gt;
| Evesham Micro Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2139&lt;br /&gt;
| 085B&lt;br /&gt;
| Panagolin Laser Software&lt;br /&gt;
|-&lt;br /&gt;
| 2140&lt;br /&gt;
| 085C&lt;br /&gt;
| Thomas Rudloff&lt;br /&gt;
|-&lt;br /&gt;
| 2141&lt;br /&gt;
| 085D&lt;br /&gt;
| Daniel Hohabir&lt;br /&gt;
|-&lt;br /&gt;
| 2142&lt;br /&gt;
| 085E&lt;br /&gt;
| GfxBase, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2143&lt;br /&gt;
| 085F&lt;br /&gt;
| Axellabs&lt;br /&gt;
|-&lt;br /&gt;
| 2144&lt;br /&gt;
| 0860&lt;br /&gt;
| Roctec Electronics Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2145&lt;br /&gt;
| 0861&lt;br /&gt;
| Omega Datentechnik&lt;br /&gt;
|-&lt;br /&gt;
| 2146&lt;br /&gt;
| 0862&lt;br /&gt;
| Atlantis&lt;br /&gt;
|-&lt;br /&gt;
| 2147&lt;br /&gt;
| 0863&lt;br /&gt;
| Skytec Computers&lt;br /&gt;
|-&lt;br /&gt;
| 2148&lt;br /&gt;
| 0864&lt;br /&gt;
| Protar Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2149&lt;br /&gt;
| 0865&lt;br /&gt;
| ACS&lt;br /&gt;
|-&lt;br /&gt;
| 2150&lt;br /&gt;
| 0866&lt;br /&gt;
| Software Results Enterprises&lt;br /&gt;
| Originally registered to University of Illinois&lt;br /&gt;
|-&lt;br /&gt;
| 2151&lt;br /&gt;
| 0867&lt;br /&gt;
| Infinity Systems Design Group&lt;br /&gt;
|-&lt;br /&gt;
| 2152&lt;br /&gt;
| 0868&lt;br /&gt;
| Trade It&lt;br /&gt;
|-&lt;br /&gt;
| 2153&lt;br /&gt;
| 0869&lt;br /&gt;
| Suntec, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2154&lt;br /&gt;
| 086A&lt;br /&gt;
| DJW Micro Systems&lt;br /&gt;
| Originally registered to Tritec Marketing&lt;br /&gt;
|-&lt;br /&gt;
| 2155&lt;br /&gt;
| 086B&lt;br /&gt;
| Power Computing Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2156&lt;br /&gt;
| 086C&lt;br /&gt;
| MacroSystems&lt;br /&gt;
|-&lt;br /&gt;
| 2157&lt;br /&gt;
| 086D&lt;br /&gt;
| Masoboshi GmbH (DCE)&lt;br /&gt;
|-&lt;br /&gt;
| 2158&lt;br /&gt;
| 086E&lt;br /&gt;
| HAL Software Hardware Handel&lt;br /&gt;
|-&lt;br /&gt;
| 2159&lt;br /&gt;
| 086F&lt;br /&gt;
| Mainhattan Data&lt;br /&gt;
| Originally registered to Michael Lamm Computersysteme&lt;br /&gt;
|-&lt;br /&gt;
| 2160&lt;br /&gt;
| 0870&lt;br /&gt;
| Digital Processing System&lt;br /&gt;
| Originally registered to bbdp Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2161&lt;br /&gt;
| 0871&lt;br /&gt;
| Blue Ribbon Soundworks&lt;br /&gt;
| Originally registered to Design Computer Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2162&lt;br /&gt;
| 0872&lt;br /&gt;
| XPert&lt;br /&gt;
| Originally registered to The Station&lt;br /&gt;
|-&lt;br /&gt;
| 2163&lt;br /&gt;
| 0873&lt;br /&gt;
| DelaComp&lt;br /&gt;
| Originally registered to Bryan Williams&lt;br /&gt;
|-&lt;br /&gt;
| 2164&lt;br /&gt;
| 0874&lt;br /&gt;
| Superformance Computer Engineering GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2165&lt;br /&gt;
| 0875&lt;br /&gt;
| Overland Engineering&lt;br /&gt;
|-&lt;br /&gt;
| 2166&lt;br /&gt;
| 0876&lt;br /&gt;
| Thomas Hamren&lt;br /&gt;
|-&lt;br /&gt;
| 2167&lt;br /&gt;
| 0877&lt;br /&gt;
| Village Tronic&lt;br /&gt;
|-&lt;br /&gt;
| 2168&lt;br /&gt;
| 0878&lt;br /&gt;
| Toolbox Design&lt;br /&gt;
|-&lt;br /&gt;
| 2169&lt;br /&gt;
| 0879&lt;br /&gt;
| Digital Processing System&lt;br /&gt;
|-&lt;br /&gt;
| 2170&lt;br /&gt;
| 087A&lt;br /&gt;
| Superformance&lt;br /&gt;
|-&lt;br /&gt;
| 2171&lt;br /&gt;
| 087B&lt;br /&gt;
| Utilities Unlimited&lt;br /&gt;
|-&lt;br /&gt;
| 2172&lt;br /&gt;
| 087C&lt;br /&gt;
| phase 5&lt;br /&gt;
|-&lt;br /&gt;
| 2173&lt;br /&gt;
| 087D&lt;br /&gt;
| Juergen Kommos&lt;br /&gt;
|-&lt;br /&gt;
| 2174&lt;br /&gt;
| 087E&lt;br /&gt;
| Electronic Design&lt;br /&gt;
|-&lt;br /&gt;
| 2175&lt;br /&gt;
| 087F&lt;br /&gt;
| James Cook University of North Queensland&lt;br /&gt;
|-&lt;br /&gt;
| 2176&lt;br /&gt;
| 0880&lt;br /&gt;
| AmiTrix Development&lt;br /&gt;
|-&lt;br /&gt;
| 2177&lt;br /&gt;
| 0881&lt;br /&gt;
| Ferranti&lt;br /&gt;
|-&lt;br /&gt;
| 2178&lt;br /&gt;
| 0882&lt;br /&gt;
| Leviathan Development&lt;br /&gt;
|-&lt;br /&gt;
| 2179&lt;br /&gt;
| 0883&lt;br /&gt;
| United Video Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2180&lt;br /&gt;
| 0884&lt;br /&gt;
| GPSoft Pty. Ltd.&lt;br /&gt;
| Originally registered to Juergen Kommos&lt;br /&gt;
|-&lt;br /&gt;
| 2181&lt;br /&gt;
| 0885&lt;br /&gt;
| ArMAX&lt;br /&gt;
| Oliver Bausch&lt;br /&gt;
|-&lt;br /&gt;
| 2182&lt;br /&gt;
| 0886&lt;br /&gt;
| CP Computer&lt;br /&gt;
|-&lt;br /&gt;
| 2183&lt;br /&gt;
| 0887&lt;br /&gt;
| Amiga Modula &amp;amp;amp; Oberon Klub&lt;br /&gt;
|-&lt;br /&gt;
| 2184&lt;br /&gt;
| 0888&lt;br /&gt;
| ITEK Neser &amp;amp;amp; Sieber GbR&lt;br /&gt;
|-&lt;br /&gt;
| 2185&lt;br /&gt;
| 0889&lt;br /&gt;
| Phillip C. Lello&lt;br /&gt;
|-&lt;br /&gt;
| 2186&lt;br /&gt;
| 088A&lt;br /&gt;
| Cyborg Design Services&lt;br /&gt;
|-&lt;br /&gt;
| 2187&lt;br /&gt;
| 088B&lt;br /&gt;
| G2 Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2188&lt;br /&gt;
| 088C&lt;br /&gt;
| Pro System Computersysteme&lt;br /&gt;
|-&lt;br /&gt;
| 2189&lt;br /&gt;
| 088D&lt;br /&gt;
| ZEUS Electronic&lt;br /&gt;
| Originally registered to MSPI (Markt &amp;amp;amp; Technik)&lt;br /&gt;
|-&lt;br /&gt;
| 2190&lt;br /&gt;
| 088E&lt;br /&gt;
| Altatech&lt;br /&gt;
|-&lt;br /&gt;
| 2191&lt;br /&gt;
| 088F&lt;br /&gt;
| NewTek&lt;br /&gt;
|-&lt;br /&gt;
| 2192&lt;br /&gt;
| 0890&lt;br /&gt;
| M-TEC Hardware Design&lt;br /&gt;
| Originally registered to Hardware Design Udo Neuroth&lt;br /&gt;
|-&lt;br /&gt;
| 2193&lt;br /&gt;
| 0891&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
| Originally registered to Viona Development&lt;br /&gt;
|-&lt;br /&gt;
| 2194&lt;br /&gt;
| 0892&lt;br /&gt;
| Amitek&lt;br /&gt;
| Originally assigned to Marpet Developments&lt;br /&gt;
|-&lt;br /&gt;
| 2195&lt;br /&gt;
| 0893&lt;br /&gt;
| Ingenieurbuero Helfrich&lt;br /&gt;
|-&lt;br /&gt;
| 2196&lt;br /&gt;
| 0894&lt;br /&gt;
| The Neo Group&lt;br /&gt;
|-&lt;br /&gt;
| 2197&lt;br /&gt;
| 0895&lt;br /&gt;
| Cyon&lt;br /&gt;
|-&lt;br /&gt;
| 2198&lt;br /&gt;
| 0896&lt;br /&gt;
| Bob Research Group&lt;br /&gt;
|-&lt;br /&gt;
| 2199&lt;br /&gt;
| 0897&lt;br /&gt;
| Richmond Sound Design Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2200&lt;br /&gt;
| 0898&lt;br /&gt;
| US Cybernetics&lt;br /&gt;
|-&lt;br /&gt;
| 2201&lt;br /&gt;
| 0899&lt;br /&gt;
| Fulvio Ieva&lt;br /&gt;
|-&lt;br /&gt;
| 2202&lt;br /&gt;
| 089A&lt;br /&gt;
| Silicon Studio&lt;br /&gt;
|-&lt;br /&gt;
| 2203&lt;br /&gt;
| 089B&lt;br /&gt;
| MacroSystems (USA)&lt;br /&gt;
| Was named Micro System Devices&lt;br /&gt;
|-&lt;br /&gt;
| 2204&lt;br /&gt;
| 089C&lt;br /&gt;
| Conspector Entertainment&lt;br /&gt;
|-&lt;br /&gt;
| 2205&lt;br /&gt;
| 089D&lt;br /&gt;
| Laserforum&lt;br /&gt;
|-&lt;br /&gt;
| 2206&lt;br /&gt;
| 089E&lt;br /&gt;
| Elbox Computer&lt;br /&gt;
| Mistakenly used by Index Information Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2207&lt;br /&gt;
| 089F&lt;br /&gt;
| Applied Magic Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2208&lt;br /&gt;
| 08A0&lt;br /&gt;
| SDL Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2560&lt;br /&gt;
| 0A00&lt;br /&gt;
| Harms&lt;br /&gt;
|-&lt;br /&gt;
| 2588&lt;br /&gt;
| 0A1C&lt;br /&gt;
| A1K.org Community&lt;br /&gt;
|-&lt;br /&gt;
| 2640&lt;br /&gt;
| 0A50&lt;br /&gt;
| Micronik&lt;br /&gt;
|-&lt;br /&gt;
| 2782&lt;br /&gt;
| 2782&lt;br /&gt;
| OA Design&lt;br /&gt;
|-&lt;br /&gt;
| 3084&lt;br /&gt;
| 0C0C&lt;br /&gt;
| Team 4&lt;br /&gt;
|-&lt;br /&gt;
| 3643&lt;br /&gt;
| 0E3B&lt;br /&gt;
| E3B&lt;br /&gt;
| Michael Boehmer&lt;br /&gt;
|-&lt;br /&gt;
| 3855&lt;br /&gt;
| 0F0F&lt;br /&gt;
| Micronik&lt;br /&gt;
|-&lt;br /&gt;
| 4096&lt;br /&gt;
| 1000&lt;br /&gt;
| MegaMicro&lt;br /&gt;
|-&lt;br /&gt;
| 4110&lt;br /&gt;
| 100E&lt;br /&gt;
| DigiFeX&lt;br /&gt;
|-&lt;br /&gt;
| 4136&lt;br /&gt;
| 1028&lt;br /&gt;
| Imtronics/Memphis&lt;br /&gt;
|-&lt;br /&gt;
| 4149&lt;br /&gt;
| 1035&lt;br /&gt;
| PROTAR&lt;br /&gt;
|-&lt;br /&gt;
| 4369&lt;br /&gt;
| 1111&lt;br /&gt;
| Frank Strauß Elektronik&lt;br /&gt;
| Also used by Kupke&lt;br /&gt;
|-&lt;br /&gt;
| 4626&lt;br /&gt;
| 1212&lt;br /&gt;
| Individual Computers&lt;br /&gt;
|-&lt;br /&gt;
| 4648&lt;br /&gt;
| 1228&lt;br /&gt;
| Flesch Hornemann Computer Elec.&lt;br /&gt;
|-&lt;br /&gt;
| 4680&lt;br /&gt;
| 1248&lt;br /&gt;
| Kupke Computertechnik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 4711&lt;br /&gt;
| 1267&lt;br /&gt;
| RBM digitaltechnik&lt;br /&gt;
|-&lt;br /&gt;
| 4754&lt;br /&gt;
| 1292&lt;br /&gt;
| MacroSystems&lt;br /&gt;
|-&lt;br /&gt;
| 5000&lt;br /&gt;
| 1388&lt;br /&gt;
| ITH&lt;br /&gt;
|-&lt;br /&gt;
| 5001&lt;br /&gt;
| 1389&lt;br /&gt;
| VMC&lt;br /&gt;
|-&lt;br /&gt;
| 5010&lt;br /&gt;
| 1392&lt;br /&gt;
| Ambience Creation Technology&lt;br /&gt;
|-&lt;br /&gt;
| 5011&lt;br /&gt;
| 1393&lt;br /&gt;
| Creative Development&lt;br /&gt;
|-&lt;br /&gt;
| 5012&lt;br /&gt;
| 1394&lt;br /&gt;
| Georg Braun&lt;br /&gt;
|-&lt;br /&gt;
| 5013&lt;br /&gt;
| 1395&lt;br /&gt;
| Swedish User Group of Amiga&lt;br /&gt;
|-&lt;br /&gt;
| 5014&lt;br /&gt;
| 1396&lt;br /&gt;
| Jakub Bednarski&lt;br /&gt;
|-&lt;br /&gt;
| 5015&lt;br /&gt;
| 1397&lt;br /&gt;
| KryoFlux, Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 5016&lt;br /&gt;
| 1398&lt;br /&gt;
| Igor Majstorovic&lt;br /&gt;
|-&lt;br /&gt;
| 5017&lt;br /&gt;
| 1399&lt;br /&gt;
| Alastair M. Robinson&lt;br /&gt;
|-&lt;br /&gt;
| 5018&lt;br /&gt;
| 139A&lt;br /&gt;
| Austex Software&lt;br /&gt;
|-&lt;br /&gt;
| 5019&lt;br /&gt;
| 139B&lt;br /&gt;
| Sören Gust&lt;br /&gt;
|-&lt;br /&gt;
| 5020&lt;br /&gt;
| 139C&lt;br /&gt;
| Rok Krajnc&lt;br /&gt;
|-&lt;br /&gt;
| 5030&lt;br /&gt;
| 13A6&lt;br /&gt;
| Tim Tashpulatov&lt;br /&gt;
|-&lt;br /&gt;
| 5040&lt;br /&gt;
| 13B0&lt;br /&gt;
| 7-bit&lt;br /&gt;
|-&lt;br /&gt;
| 5050&lt;br /&gt;
| 13BA&lt;br /&gt;
| Sakura IT&lt;br /&gt;
|-&lt;br /&gt;
| 5060&lt;br /&gt;
| 13C4&lt;br /&gt;
| FPGAArcade&lt;br /&gt;
|-&lt;br /&gt;
| 5070&lt;br /&gt;
| 13CE&lt;br /&gt;
| CancerSoft Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 5080&lt;br /&gt;
| 13D8&lt;br /&gt;
| Stephen Leary&lt;br /&gt;
|-&lt;br /&gt;
| 5090&lt;br /&gt;
| 13E2&lt;br /&gt;
| DMA Softlab LLC&lt;br /&gt;
|-&lt;br /&gt;
| 5100&lt;br /&gt;
| 13EC&lt;br /&gt;
| Brookhouse Engineering&lt;br /&gt;
|-&lt;br /&gt;
| 5110&lt;br /&gt;
| 13F6&lt;br /&gt;
| Eduardo Arana&lt;br /&gt;
|-&lt;br /&gt;
| 5120&lt;br /&gt;
| 1400&lt;br /&gt;
| CS-LAB&lt;br /&gt;
|-&lt;br /&gt;
| 5130&lt;br /&gt;
| 140A&lt;br /&gt;
| Robert Miranda&lt;br /&gt;
|-&lt;br /&gt;
| 5132&lt;br /&gt;
| 140C&lt;br /&gt;
| UAS Interface Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 5140&lt;br /&gt;
| 1414&lt;br /&gt;
| RastPort&lt;br /&gt;
|-&lt;br /&gt;
| 5150&lt;br /&gt;
| 141E&lt;br /&gt;
| Amiga Kit&lt;br /&gt;
|-&lt;br /&gt;
| 5160&lt;br /&gt;
| 1428&lt;br /&gt;
| Central Texas Commodore User Group&lt;br /&gt;
|-&lt;br /&gt;
| 5170&lt;br /&gt;
| 1432&lt;br /&gt;
| Confusion Research Center&lt;br /&gt;
|-&lt;br /&gt;
| 5180&lt;br /&gt;
| 143C&lt;br /&gt;
| Solar Soyuz Zaibatsu&lt;br /&gt;
|-&lt;br /&gt;
| 5190&lt;br /&gt;
| 1446&lt;br /&gt;
| BooBip&lt;br /&gt;
|-&lt;br /&gt;
| 5191&lt;br /&gt;
| 1447&lt;br /&gt;
| Matthias Hampel&lt;br /&gt;
|-&lt;br /&gt;
| 5192&lt;br /&gt;
| 1448&lt;br /&gt;
| dec0de Consulting Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 5193&lt;br /&gt;
| 1449&lt;br /&gt;
| Puppy Concepts&lt;br /&gt;
|-&lt;br /&gt;
| 5194&lt;br /&gt;
| 144A&lt;br /&gt;
| Open Amiga Hardware Repository&lt;br /&gt;
|-&lt;br /&gt;
| 5195&lt;br /&gt;
| 144B&lt;br /&gt;
| Double H Tech&lt;br /&gt;
|-&lt;br /&gt;
| 5196&lt;br /&gt;
| 144C&lt;br /&gt;
| Retromatik&lt;br /&gt;
|-&lt;br /&gt;
| 5500&lt;br /&gt;
| 157C&lt;br /&gt;
| Inhouse Information&lt;br /&gt;
|-&lt;br /&gt;
| 5768&lt;br /&gt;
| 1688&lt;br /&gt;
| Bio Con&lt;br /&gt;
|-&lt;br /&gt;
| 6148&lt;br /&gt;
| 1804&lt;br /&gt;
| HK-Computer&lt;br /&gt;
|-&lt;br /&gt;
| 6502&lt;br /&gt;
| 1966&lt;br /&gt;
| Cloanto&lt;br /&gt;
|-&lt;br /&gt;
| 6520&lt;br /&gt;
| 1978&lt;br /&gt;
| Oliver Gantert&lt;br /&gt;
|-&lt;br /&gt;
| 7777&lt;br /&gt;
| 1E61&lt;br /&gt;
| Rafal Gabriel Chyla&lt;br /&gt;
|-&lt;br /&gt;
| 8215&lt;br /&gt;
| 2017&lt;br /&gt;
| Vortex&lt;br /&gt;
|-&lt;br /&gt;
| 8244&lt;br /&gt;
| 2034&lt;br /&gt;
| Spirit Technology&lt;br /&gt;
|-&lt;br /&gt;
| 8290&lt;br /&gt;
| 2062&lt;br /&gt;
| Expansion Systems&lt;br /&gt;
|-&lt;br /&gt;
| 8448&lt;br /&gt;
| 2100&lt;br /&gt;
| ReadySoft&lt;br /&gt;
|-&lt;br /&gt;
| 8512&lt;br /&gt;
| 2140&lt;br /&gt;
| Phase 5 Digital Products&lt;br /&gt;
|-&lt;br /&gt;
| 8553&lt;br /&gt;
| 2169&lt;br /&gt;
| Digital Processing Systems Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 8704&lt;br /&gt;
| 2200&lt;br /&gt;
| ACT Elektronik&lt;br /&gt;
|-&lt;br /&gt;
| 8738&lt;br /&gt;
| 2222&lt;br /&gt;
| ACT Elektronik&lt;br /&gt;
|-&lt;br /&gt;
| 9512&lt;br /&gt;
| 2528&lt;br /&gt;
| Tower Technologies&lt;br /&gt;
|-&lt;br /&gt;
| 10676&lt;br /&gt;
| 29B4&lt;br /&gt;
| Electronic Design&lt;br /&gt;
|-&lt;br /&gt;
| 14195&lt;br /&gt;
| 3773&lt;br /&gt;
| Media-net-Point&lt;br /&gt;
|-&lt;br /&gt;
| 14501&lt;br /&gt;
| 38A5&lt;br /&gt;
| Petsoff, Finland&lt;br /&gt;
|-&lt;br /&gt;
| 16375&lt;br /&gt;
| 3FF7&lt;br /&gt;
| Uwe Gerlach&lt;br /&gt;
|-&lt;br /&gt;
| 16707&lt;br /&gt;
| 4143&lt;br /&gt;
| Ateo Concepts&lt;br /&gt;
|-&lt;br /&gt;
| 16708&lt;br /&gt;
| 4144&lt;br /&gt;
| ALiENDESiGN&lt;br /&gt;
|-&lt;br /&gt;
| 16945&lt;br /&gt;
| 4231&lt;br /&gt;
| A.C.T.&lt;br /&gt;
|-&lt;br /&gt;
| 17740&lt;br /&gt;
| 454C&lt;br /&gt;
| HK-Computer (ELSAT)&lt;br /&gt;
|-&lt;br /&gt;
| 18260&lt;br /&gt;
| 4754&lt;br /&gt;
| MacroSystems (Germany)&lt;br /&gt;
|-&lt;br /&gt;
| 19796&lt;br /&gt;
| 4D54&lt;br /&gt;
| Markt &amp;amp; Technik&lt;br /&gt;
|-&lt;br /&gt;
| 20480&lt;br /&gt;
| 5000&lt;br /&gt;
| François Lacombe&lt;br /&gt;
|-&lt;br /&gt;
| 22359&lt;br /&gt;
| 5757&lt;br /&gt;
| Markt &amp;amp; Technik&lt;br /&gt;
|-&lt;br /&gt;
| 26464&lt;br /&gt;
| 6760&lt;br /&gt;
| Combitec&lt;br /&gt;
|-&lt;br /&gt;
| 26470&lt;br /&gt;
| 6766&lt;br /&gt;
| Combitec&lt;br /&gt;
|-&lt;br /&gt;
| 28014&lt;br /&gt;
| 6D6E&lt;br /&gt;
| MNT Media and Technology UG&lt;br /&gt;
|-&lt;br /&gt;
| 28019&lt;br /&gt;
| 6D73&lt;br /&gt;
| Michal Schulz&lt;br /&gt;
|-&lt;br /&gt;
| 28020&lt;br /&gt;
| 6D74&lt;br /&gt;
| PiStorm&lt;br /&gt;
|-&lt;br /&gt;
| 32768&lt;br /&gt;
| 8000&lt;br /&gt;
| M.A.S.T.&lt;br /&gt;
|-&lt;br /&gt;
| 42240&lt;br /&gt;
| A500&lt;br /&gt;
| Aethreum Digital&lt;br /&gt;
|-&lt;br /&gt;
| 43437&lt;br /&gt;
| A9AD&lt;br /&gt;
| Reis-Ware&lt;br /&gt;
|-&lt;br /&gt;
| 43521&lt;br /&gt;
| AA01&lt;br /&gt;
| Cameron&lt;br /&gt;
|-&lt;br /&gt;
| 43537&lt;br /&gt;
| AA11&lt;br /&gt;
| Reis-Ware&lt;br /&gt;
|-&lt;br /&gt;
| 44359&lt;br /&gt;
| AD47&lt;br /&gt;
| Matay&lt;br /&gt;
|-&lt;br /&gt;
| 46504&lt;br /&gt;
| B5A8&lt;br /&gt;
| Phoenix&lt;br /&gt;
|-&lt;br /&gt;
| 48879&lt;br /&gt;
| BEEF&lt;br /&gt;
| Swiss Mountain Dog Products&lt;br /&gt;
|-&lt;br /&gt;
| 49160&lt;br /&gt;
| C008&lt;br /&gt;
| Combitec&lt;br /&gt;
|-&lt;br /&gt;
| 49374&lt;br /&gt;
| C0DE&lt;br /&gt;
| Stefan Reinauer&lt;br /&gt;
|-&lt;br /&gt;
| 61453&lt;br /&gt;
| F00D&lt;br /&gt;
| Forefront Technologies Inc.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
For any changes/additions to this registry see [[#How_to_Obtain_a_Manufacturer_Number|How to Obtain a Manufacturer Number]]&lt;/div&gt;</summary>
		<author><name>Costel Mincea</name></author>
	</entry>
	<entry>
		<id>https://wiki.amigaos.net/w/index.php?title=Amiga_Hardware_Manufacturer_ID_Registry&amp;diff=12606</id>
		<title>Amiga Hardware Manufacturer ID Registry</title>
		<link rel="alternate" type="text/html" href="https://wiki.amigaos.net/w/index.php?title=Amiga_Hardware_Manufacturer_ID_Registry&amp;diff=12606"/>
		<updated>2026-09-08T11:14:58Z</updated>

		<summary type="html">&lt;p&gt;Costel Mincea: Added Stefan Reinauer (49374)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
= How to Obtain a Manufacturer Number =&lt;br /&gt;
&lt;br /&gt;
Manufacturer&#039;s numbers are assigned by the AmigaOS development team. To obtain your unique manufacturer number send a support request to [mailto:support@hyperion-entertainment.com support@hyperion-entertainment.com] including these information:&lt;br /&gt;
&lt;br /&gt;
 1. The name of the company or person which the number is assigned to&lt;br /&gt;
 &lt;br /&gt;
 2. Postal address/contact address&lt;br /&gt;
 &lt;br /&gt;
 3. Name of the contact person, with a corresponding e-mail address&lt;br /&gt;
 &lt;br /&gt;
 4. A brief description of the kind of products you want to produce&lt;br /&gt;
&lt;br /&gt;
= Your Manufacturer Number =&lt;br /&gt;
&lt;br /&gt;
Attention hardware manufacturers. If you are developing a hardware expansion product for the Classic Amiga (e.g. 500, 2000, 3000) then you will need to obtain a special manufacturer ID number from the AmigaOS development team to identify your product. This manufacturer number is used by the Amiga to link your hardware with its driver software at boot time.&lt;br /&gt;
&lt;br /&gt;
Your manufacturer number is part of the special protocol that the Amiga uses to automatically configure all expansion devices on the bus without the user having to cut jumpers or adjust dip switches. This is called auto-config.&lt;br /&gt;
&lt;br /&gt;
At start-up time, the system first polls each board in the system and assigns the board its own address space. If it is a memory board, its RAM is linked into the memory free pool. Later in the boot sequence, after DOS is initialized, the binddrivers program is run. Binddrivers will search the directory SYS:Expansion for the drivers that go with the boards.&lt;br /&gt;
&lt;br /&gt;
To do this binddrivers looks in the Tool Type field of all icon files in SYS:Expansion. If the first seven bytes of the Tool Type field are &amp;quot;PRODUCT&amp;quot;, then this is an icon file for a driver.&lt;br /&gt;
&lt;br /&gt;
Binddrivers will then attempt to match the drivers it has found with the boards that were found earlier. This is where your manufacturer number comes in.&lt;br /&gt;
&lt;br /&gt;
Your manufacturer number goes in two places. First, it is burned in hex form into the PAL which is part of ALL auto-config expansion products. Second, it appears in ASCII in the Tool Type field of the icon file for your product&#039;s driver. By matching these two numbers, the Amiga can automatically configure your board and bind it&#039;s software driver into the system as well.&lt;br /&gt;
&lt;br /&gt;
The manufacturer&#039;s number is a 16-bit ID which appears in PAL offsets $10-$17. There is also an 8-bit product number which you assign. The product number is for uniquely identifying different products from the same vendor. The product number will appear in PAL offsets $04-$07. This gives you a total of 24 bits to identify each of your products.&lt;br /&gt;
&lt;br /&gt;
These 24 bits of information in the PAL which identify your product are matched against the information in the Tool Type field of all icon files in the SYS:Expansion drawer. For example, suppose you are manufacturer #1019. You have two products, #1 and #2 which both use the same driver. The icon for your driver for these two products would have a Tool Type set to &amp;quot;PRODUCT=1019/1|1019/2&amp;quot;. This means: I am an icon for a driver that works with product number 1 or 2 from manufacturer 1019, now bind me. Spaces are not legal. Here are two other examples:&lt;br /&gt;
&lt;br /&gt;
; PRODUCT=1208/11&lt;br /&gt;
: is the Tool Type for a driver for product 11 from manufacturer number 1208.&lt;br /&gt;
&lt;br /&gt;
; PRODUCT=1017&lt;br /&gt;
: is the Tool Type for a driver for any product from manufacturer number 1017.&lt;br /&gt;
&lt;br /&gt;
For an informal explanation of the auto-configuration process, see the chapter on Software Expansion Architecture from the 2nd Annual Amiga Developer&#039;s Conference Notes (available on ADCD 2.1). For the details of timing, power, the PAL equations and PAL address specifications and the expansion library documentation, see sections 3.1 to 3.3 of the A500/A2000 Technical Reference Manual. The original auto-config spec appears in the A1000 Schematics and Expansion Specification.&lt;br /&gt;
&lt;br /&gt;
The auto-config process makes the addition of expansion products to the system very easy. All the user has to do is put the board in any slot and copy the driver from the release disk to his own SYS:Expansion drawer. Everything else is automatic. There are no jumpers or dip switches to set. Best of all, you will get a lot less support calls asking how to make your product work with the XYZ-Corp-battery-backed-clock.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
&lt;br /&gt;
Some notes on hardware manufacturer ID assignment.&lt;br /&gt;
&lt;br /&gt;
* Manufacturer ID numbers are assigned free of charge.&lt;br /&gt;
* Please provide the following information when requesting an ID:&lt;br /&gt;
*# Name of the company or person&lt;br /&gt;
*# Postal address/contact address&lt;br /&gt;
*# Name of the contact person, with a corresponding e-mail address&lt;br /&gt;
*# A brief description of the kind of products you want to produce&lt;br /&gt;
* All ID numbers smaller than 5000 must be considered unsafe because no information exists on which numbers exactly were taken during the time Commodore, Inc. disintegrated.&lt;br /&gt;
* ID numbers in the range 8192 to 18841 must be considered unsafe because some hardware developers mistook the numbers assigned to them to be given in hexadecimal format. Hence 0x2000 = 8192 and 0x4999 = 18841.&lt;br /&gt;
&lt;br /&gt;
= Example code =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
/*-----------------------------------------------*/&lt;br /&gt;
/* Here is a short program which will tell you   */&lt;br /&gt;
/* about the expansion boards configured in your */&lt;br /&gt;
/* system without you opening up the machine.    */&lt;br /&gt;
/* Code by Bill Koester of CATS                  */&lt;br /&gt;
/*-----------------------------------------------*/&lt;br /&gt;
#include &amp;lt;libraries/configvars.h&amp;gt;&lt;br /&gt;
#include &amp;lt;libraries/expansion.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
struct ExpansionBase *ExpansionBase;&lt;br /&gt;
&lt;br /&gt;
void cleanup();&lt;br /&gt;
void printdev();&lt;br /&gt;
&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
   struct ConfigDev *MyConfigDev;&lt;br /&gt;
&lt;br /&gt;
   /*----------------------------------*/&lt;br /&gt;
   /* Open the expansion library,      */&lt;br /&gt;
   /* if there is a problem then exit  */&lt;br /&gt;
   /*----------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   ExpansionBase =(struct ExpansionBase *) OpenLibrary(EXPANSIONNAME,0);&lt;br /&gt;
   if(ExpansionBase==NULL)&lt;br /&gt;
   {&lt;br /&gt;
      printf(&amp;quot;Error opening expansion library!!\n&amp;quot;);&lt;br /&gt;
      cleanup();&lt;br /&gt;
      exit(0);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   /*--------------------------------------------*/&lt;br /&gt;
   /* Use FindConfigDev to get info on the first */&lt;br /&gt;
   /* expansion board on the list maintained by  */&lt;br /&gt;
   /* Exec.  If there are no expansion boards in */&lt;br /&gt;
   /* the system then exit.                      */&lt;br /&gt;
   /*--------------------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   MyConfigDev = NULL;&lt;br /&gt;
&lt;br /&gt;
  /*--------------------------------------------------*/&lt;br /&gt;
  /* FindConfigDev(oldConfigDev,manufacturer,product) */&lt;br /&gt;
  /* oldConfigDev = NULL for the top of the list      */&lt;br /&gt;
  /* manufacturer = -1 for any manufacturer           */&lt;br /&gt;
  /* product      = -1 for any product                */&lt;br /&gt;
  /*--------------------------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   MyConfigDev = FindConfigDev(NULL,-1,-1);&lt;br /&gt;
&lt;br /&gt;
   if(MyConfigDev==NULL)&lt;br /&gt;
   {&lt;br /&gt;
      printf(&amp;quot;No Configured Devices found!!\n&amp;quot;);&lt;br /&gt;
      cleanup();&lt;br /&gt;
      exit(0);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   printdev(MyConfigDev);&lt;br /&gt;
&lt;br /&gt;
   /*-----------------------------------*/&lt;br /&gt;
   /* OK, there is at least one board,  */&lt;br /&gt;
   /* so loop and get the entire list   */&lt;br /&gt;
   /* printing as we go with printdev() */&lt;br /&gt;
   /*-----------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   while(MyConfigDev = FindConfigDev(MyConfigDev,-1,-1))&lt;br /&gt;
   {&lt;br /&gt;
      printdev(MyConfigDev);&lt;br /&gt;
   }&lt;br /&gt;
   cleanup();&lt;br /&gt;
   return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*-------------------*/&lt;br /&gt;
/* Close up shop...  */&lt;br /&gt;
/*-------------------*/&lt;br /&gt;
void cleanup()&lt;br /&gt;
{&lt;br /&gt;
   if(ExpansionBase)&lt;br /&gt;
      CloseLibrary(ExpansionBase);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*----------------------------------*/&lt;br /&gt;
/* Print out the contents of the    */&lt;br /&gt;
/* dev structure for this expansion */&lt;br /&gt;
/* product.                         */&lt;br /&gt;
/*----------------------------------*/&lt;br /&gt;
&lt;br /&gt;
void printdev(dev)&lt;br /&gt;
struct ConfigDev *dev;&lt;br /&gt;
{&lt;br /&gt;
   char buff[200];&lt;br /&gt;
&lt;br /&gt;
   printf(&amp;quot;Flags          = &amp;quot;);&lt;br /&gt;
   if(dev-&amp;gt;cd_Flags==NULL)&lt;br /&gt;
      printf(&amp;quot;NULL  &amp;quot;);&lt;br /&gt;
   if(dev-&amp;gt;cd_Flags&amp;amp;CDF_SHUTUP)&lt;br /&gt;
      printf(&amp;quot;CDF_SHUTUP  &amp;quot;);&lt;br /&gt;
   if(dev-&amp;gt;cd_Flags&amp;amp;CDF_CONFIGME)&lt;br /&gt;
      printf(&amp;quot;CDF_CONFIGME  &amp;quot;);&lt;br /&gt;
   printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
   printf(&amp;quot;Board Address  = %x\n&amp;quot;,dev-&amp;gt;cd_BoardAddr);&lt;br /&gt;
   printf(&amp;quot;Board Size     = %d bytes\n&amp;quot;,dev-&amp;gt;cd_BoardSize);&lt;br /&gt;
   printf(&amp;quot;Slot  Address  = %d\n&amp;quot;,dev-&amp;gt;cd_SlotAddr);&lt;br /&gt;
   printf(&amp;quot;Slot  Size     = %d\n&amp;quot;,dev-&amp;gt;cd_SlotSize);&lt;br /&gt;
   printf(&amp;quot;Driver code at   %x\n&amp;quot;,dev-&amp;gt;cd_Driver);&lt;br /&gt;
&lt;br /&gt;
   printf(&amp;quot;er_Type         = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Type);&lt;br /&gt;
   printf(&amp;quot;er_Product      = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Product);&lt;br /&gt;
   printf(&amp;quot;er_Flags        = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Flags);&lt;br /&gt;
   printf(&amp;quot;er_Reserved03   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved03);&lt;br /&gt;
   printf(&amp;quot;er_Manufacturer = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Manufacturer);&lt;br /&gt;
   printf(&amp;quot;er_SerialNumber = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_SerialNumber);&lt;br /&gt;
   printf(&amp;quot;er_InitDiagVec  = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_InitDiagVec);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0c   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0c);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0d   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0d);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0e   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0e);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0f   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0f);&lt;br /&gt;
&lt;br /&gt;
   printf(&amp;quot;Hit Return to continue:\n&amp;quot;);&lt;br /&gt;
   gets(buff);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Registry =&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! ID (decimal)&lt;br /&gt;
! ID (hexadecimal)&lt;br /&gt;
! Manufacturer&lt;br /&gt;
! Notes&lt;br /&gt;
|-&lt;br /&gt;
| 1&lt;br /&gt;
| 0001&lt;br /&gt;
| Micronik&lt;br /&gt;
|-&lt;br /&gt;
| 211&lt;br /&gt;
| 00D3&lt;br /&gt;
| Pacific Peripherals/Profex&lt;br /&gt;
|-&lt;br /&gt;
| 221&lt;br /&gt;
| 00DD&lt;br /&gt;
| Kupke Computertechnik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 256&lt;br /&gt;
| 0100&lt;br /&gt;
| Memphis&lt;br /&gt;
| Originally registered to MacroSystems US&lt;br /&gt;
|-&lt;br /&gt;
| 512&lt;br /&gt;
| 0200&lt;br /&gt;
| 3-State Computertechnik&lt;br /&gt;
|-&lt;br /&gt;
| 513&lt;br /&gt;
| 0201&lt;br /&gt;
| Commodore (Braunschweig)&lt;br /&gt;
|-&lt;br /&gt;
| 514&lt;br /&gt;
| 0202&lt;br /&gt;
| Commodore (West Chester)&lt;br /&gt;
|-&lt;br /&gt;
| 515&lt;br /&gt;
| 0203&lt;br /&gt;
| Commodore (West Chester)&lt;br /&gt;
| Originally registered to Combitech/Macrosystem&lt;br /&gt;
|-&lt;br /&gt;
| 756&lt;br /&gt;
| 02F4&lt;br /&gt;
| Progressive Peripherals &amp;amp; Software&lt;br /&gt;
|-&lt;br /&gt;
| 767&lt;br /&gt;
| 02FF&lt;br /&gt;
| Kolff Computer Supplies&lt;br /&gt;
|-&lt;br /&gt;
| 1001&lt;br /&gt;
| 03E9&lt;br /&gt;
| Tecmar&lt;br /&gt;
|-&lt;br /&gt;
| 1002&lt;br /&gt;
| 03EA&lt;br /&gt;
| Telesys&lt;br /&gt;
|-&lt;br /&gt;
| 1003&lt;br /&gt;
| 03EB&lt;br /&gt;
| The Micro-Forge&lt;br /&gt;
|-&lt;br /&gt;
| 1004&lt;br /&gt;
| 03EC&lt;br /&gt;
| Kronos/C Ltd.&lt;br /&gt;
| Originally registered to Card Co. (Supra)&lt;br /&gt;
|-&lt;br /&gt;
| 1005&lt;br /&gt;
| 03ED&lt;br /&gt;
| A-Squared&lt;br /&gt;
|-&lt;br /&gt;
| 1006&lt;br /&gt;
| 03EE&lt;br /&gt;
| Comspec Communications&lt;br /&gt;
|-&lt;br /&gt;
| 1007&lt;br /&gt;
| 03EF&lt;br /&gt;
| HT Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 1008&lt;br /&gt;
| 03F0&lt;br /&gt;
| RDS Software&lt;br /&gt;
|-&lt;br /&gt;
| 1009&lt;br /&gt;
| 03F1&lt;br /&gt;
| Anakin Research&lt;br /&gt;
|-&lt;br /&gt;
| 1010&lt;br /&gt;
| 03F2&lt;br /&gt;
| MicroBotics&lt;br /&gt;
|-&lt;br /&gt;
| 1011&lt;br /&gt;
| 03F3&lt;br /&gt;
| Bob Krauth&lt;br /&gt;
|-&lt;br /&gt;
| 1012&lt;br /&gt;
| 03F4&lt;br /&gt;
| Access Associates (Alegra)&lt;br /&gt;
|-&lt;br /&gt;
| 1013&lt;br /&gt;
| 03F5&lt;br /&gt;
| Mini Comp Systems Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 1014&lt;br /&gt;
| 03F6&lt;br /&gt;
| Cypress Technology&lt;br /&gt;
|-&lt;br /&gt;
| 1015&lt;br /&gt;
| 03F7&lt;br /&gt;
| Fuller Computers&lt;br /&gt;
|-&lt;br /&gt;
| 1016&lt;br /&gt;
| 03F8&lt;br /&gt;
| Galaxy Computers&lt;br /&gt;
|-&lt;br /&gt;
| 1017&lt;br /&gt;
| 03F9&lt;br /&gt;
| ADA Research&lt;br /&gt;
|-&lt;br /&gt;
| 1018&lt;br /&gt;
| 03FA&lt;br /&gt;
| Computer Service Italia&lt;br /&gt;
|-&lt;br /&gt;
| 1019&lt;br /&gt;
| 03FB&lt;br /&gt;
| Amigo&lt;br /&gt;
|-&lt;br /&gt;
| 1020&lt;br /&gt;
| 03FC&lt;br /&gt;
| Micro-Solutions Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1021&lt;br /&gt;
| 03FD&lt;br /&gt;
| Stacar International&lt;br /&gt;
|-&lt;br /&gt;
| 1022&lt;br /&gt;
| 03FE&lt;br /&gt;
| Video Precisions&lt;br /&gt;
|-&lt;br /&gt;
| 1023&lt;br /&gt;
| 03FF&lt;br /&gt;
| ASDG, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1025&lt;br /&gt;
| 0401&lt;br /&gt;
| Ing. Buero Kalawsky&lt;br /&gt;
|-&lt;br /&gt;
| 1026&lt;br /&gt;
| 0402&lt;br /&gt;
| Computer Tuning&lt;br /&gt;
|-&lt;br /&gt;
| 1027&lt;br /&gt;
| 0403&lt;br /&gt;
| Interplan Unternehmensberatung&lt;br /&gt;
|-&lt;br /&gt;
| 1028&lt;br /&gt;
| 0404&lt;br /&gt;
| Imtronics/Memphis&lt;br /&gt;
| Originally registered to Peter Ohlich&lt;br /&gt;
|-&lt;br /&gt;
| 1030&lt;br /&gt;
| 0406&lt;br /&gt;
| Commodore (Lowell University)&lt;br /&gt;
| Originally registered to Productivity Center&lt;br /&gt;
|-&lt;br /&gt;
| 1041&lt;br /&gt;
| 0411&lt;br /&gt;
| Design Labs&lt;br /&gt;
|-&lt;br /&gt;
| 1042&lt;br /&gt;
| 0412&lt;br /&gt;
| MCS&lt;br /&gt;
|-&lt;br /&gt;
| 1043&lt;br /&gt;
| 0413&lt;br /&gt;
| B. J. Freeman&lt;br /&gt;
|-&lt;br /&gt;
| 1044&lt;br /&gt;
| 0414&lt;br /&gt;
| Side Effects Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1045&lt;br /&gt;
| 0415&lt;br /&gt;
| Oklahoma Personal Comp.&lt;br /&gt;
|-&lt;br /&gt;
| 1046&lt;br /&gt;
| 0416&lt;br /&gt;
| Advanced Micro Innovations&lt;br /&gt;
|-&lt;br /&gt;
| 1047&lt;br /&gt;
| 0417&lt;br /&gt;
| Industrial Support Services&lt;br /&gt;
|-&lt;br /&gt;
| 1048&lt;br /&gt;
| 0418&lt;br /&gt;
| Technisoft&lt;br /&gt;
|-&lt;br /&gt;
| 1049&lt;br /&gt;
| 0419&lt;br /&gt;
| Prolific, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1050&lt;br /&gt;
| 041A&lt;br /&gt;
| Softeam, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1051&lt;br /&gt;
| 041B&lt;br /&gt;
| GRC Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 1052&lt;br /&gt;
| 041C&lt;br /&gt;
| David Lai&lt;br /&gt;
|-&lt;br /&gt;
| 1053&lt;br /&gt;
| 041D&lt;br /&gt;
| Ameristar Technologies&lt;br /&gt;
|-&lt;br /&gt;
| 1054&lt;br /&gt;
| 041E&lt;br /&gt;
| Cline Refrigeration&lt;br /&gt;
|-&lt;br /&gt;
| 1055&lt;br /&gt;
| 041F&lt;br /&gt;
| Cardiac Pacemakers, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1056&lt;br /&gt;
| 0420&lt;br /&gt;
| Supra Corp. (Creative Microsystems)&lt;br /&gt;
|-&lt;br /&gt;
| 1057&lt;br /&gt;
| 0421&lt;br /&gt;
| Wayne Diener&lt;br /&gt;
|-&lt;br /&gt;
| 1058&lt;br /&gt;
| 0422&lt;br /&gt;
| Computer Systems Associates (CSA)&lt;br /&gt;
|-&lt;br /&gt;
| 1059&lt;br /&gt;
| 0423&lt;br /&gt;
| Trionix, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1060&lt;br /&gt;
| 0424&lt;br /&gt;
| David Lucas&lt;br /&gt;
|-&lt;br /&gt;
| 1061&lt;br /&gt;
| 0425&lt;br /&gt;
| Analog Precision&lt;br /&gt;
| Also assigned to D &amp;amp; L Distributing&lt;br /&gt;
|-&lt;br /&gt;
| 1267&lt;br /&gt;
| 04F3&lt;br /&gt;
| RBM Digitaltechnik&lt;br /&gt;
|-&lt;br /&gt;
| 1282&lt;br /&gt;
| 0502&lt;br /&gt;
| M-TEC Hardware Design&lt;br /&gt;
|-&lt;br /&gt;
| 1337&lt;br /&gt;
| 0539&lt;br /&gt;
| Thomas Stenzel (DaFR34K)&lt;br /&gt;
|-&lt;br /&gt;
| 1576&lt;br /&gt;
| 0628&lt;br /&gt;
| Boris Križma&lt;br /&gt;
|-&lt;br /&gt;
| 1729&lt;br /&gt;
| 06C1&lt;br /&gt;
| Thomas Richter / OpenPCI-A1200 Mediator bridge&lt;br /&gt;
|-&lt;br /&gt;
| 1730&lt;br /&gt;
| 06C2&lt;br /&gt;
| Thomas Richter / OpenPCI-A4000 Mediator bridge&lt;br /&gt;
|-&lt;br /&gt;
| 1731&lt;br /&gt;
| 06C3&lt;br /&gt;
| Thomas Richter / OpenPCI-Prometheus bridge (Firestorm or original)&lt;br /&gt;
|-&lt;br /&gt;
| 1732&lt;br /&gt;
| 06C4&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved1&lt;br /&gt;
|-&lt;br /&gt;
| 1733&lt;br /&gt;
| 06C5&lt;br /&gt;
| Thomas Richter / OpenPCI-Grex bridge (both A1200 and A4000)&lt;br /&gt;
|-&lt;br /&gt;
| 1734&lt;br /&gt;
| 06C6&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved2&lt;br /&gt;
|-&lt;br /&gt;
| 1735&lt;br /&gt;
| 06C7&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved3&lt;br /&gt;
|-&lt;br /&gt;
| 1736&lt;br /&gt;
| 06C8&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved4&lt;br /&gt;
|-&lt;br /&gt;
| 1737&lt;br /&gt;
| 06C9&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved5&lt;br /&gt;
|-&lt;br /&gt;
| 1738&lt;br /&gt;
| 06CA&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved6&lt;br /&gt;
|-&lt;br /&gt;
| 1739&lt;br /&gt;
| 06CB&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved7&lt;br /&gt;
|-&lt;br /&gt;
| 1740&lt;br /&gt;
| 06CC&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved8&lt;br /&gt;
|-&lt;br /&gt;
| 1741&lt;br /&gt;
| 06CD&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved9&lt;br /&gt;
|-&lt;br /&gt;
| 1742&lt;br /&gt;
| 06CE&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved10&lt;br /&gt;
|-&lt;br /&gt;
| 1743&lt;br /&gt;
| 06CF&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved11&lt;br /&gt;
|-&lt;br /&gt;
| 1744&lt;br /&gt;
| 06D0&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved12&lt;br /&gt;
|-&lt;br /&gt;
| 1761&lt;br /&gt;
| 06E1&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
|-&lt;br /&gt;
| 1803&lt;br /&gt;
| 070B&lt;br /&gt;
| UAE Amiga Emulator&lt;br /&gt;
|-&lt;br /&gt;
| 2002&lt;br /&gt;
| 07D2&lt;br /&gt;
| Mimetics Corp.&lt;br /&gt;
|-&lt;br /&gt;
| 2003&lt;br /&gt;
| 07D3&lt;br /&gt;
| ACDA&lt;br /&gt;
|-&lt;br /&gt;
| 2004&lt;br /&gt;
| 07D4&lt;br /&gt;
| Finn R. Jacobsen&lt;br /&gt;
|-&lt;br /&gt;
| 2005&lt;br /&gt;
| 07D5&lt;br /&gt;
| Elthen Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2006&lt;br /&gt;
| 07D6&lt;br /&gt;
| Nine Tiles Computer Systems Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2007&lt;br /&gt;
| 07D7&lt;br /&gt;
| Analog Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2008&lt;br /&gt;
| 07D8&lt;br /&gt;
| Bell &amp;amp;amp; Howell&lt;br /&gt;
|-&lt;br /&gt;
| 2009&lt;br /&gt;
| 07D9&lt;br /&gt;
| Roland Kochler&lt;br /&gt;
|-&lt;br /&gt;
| 2010&lt;br /&gt;
| 07DA&lt;br /&gt;
| Byte Corp.&lt;br /&gt;
|-&lt;br /&gt;
| 2011&lt;br /&gt;
| 07DB&lt;br /&gt;
| Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 2012&lt;br /&gt;
| 07DC&lt;br /&gt;
| DKB, Inc.&lt;br /&gt;
| Previously named Michigan Software&lt;br /&gt;
|-&lt;br /&gt;
| 2013&lt;br /&gt;
| 07DD&lt;br /&gt;
| Pacific Peripherals&lt;br /&gt;
|-&lt;br /&gt;
| 2014&lt;br /&gt;
| 07DE&lt;br /&gt;
| Sysaphus Software&lt;br /&gt;
|-&lt;br /&gt;
| 2015&lt;br /&gt;
| 07DF&lt;br /&gt;
| Digitronics&lt;br /&gt;
|-&lt;br /&gt;
| 2016&lt;br /&gt;
| 07E0&lt;br /&gt;
| Akron Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2017&lt;br /&gt;
| 07E1&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
|-&lt;br /&gt;
| 2018&lt;br /&gt;
| 07E2&lt;br /&gt;
| Calmos&lt;br /&gt;
|-&lt;br /&gt;
| 2019&lt;br /&gt;
| 07E3&lt;br /&gt;
| Dover Research&lt;br /&gt;
|-&lt;br /&gt;
| 2020&lt;br /&gt;
| 07E4&lt;br /&gt;
| David Krehbiel&lt;br /&gt;
|-&lt;br /&gt;
| 2021&lt;br /&gt;
| 07E5&lt;br /&gt;
| Synergy Peripheral Systems&lt;br /&gt;
| Also known as California Access&lt;br /&gt;
|-&lt;br /&gt;
| 2022&lt;br /&gt;
| 07E6&lt;br /&gt;
| Xetec&lt;br /&gt;
|-&lt;br /&gt;
| 2023&lt;br /&gt;
| 07E7&lt;br /&gt;
| Micron Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2024&lt;br /&gt;
| 07E8&lt;br /&gt;
| CH Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2025&lt;br /&gt;
| 07E9&lt;br /&gt;
| American Liquid Light&lt;br /&gt;
|-&lt;br /&gt;
| 2026&lt;br /&gt;
| 07EA&lt;br /&gt;
| Progressive Peripherals &amp;amp;amp; Software&lt;br /&gt;
| Also used by Ateo&lt;br /&gt;
|-&lt;br /&gt;
| 2027&lt;br /&gt;
| 07EB&lt;br /&gt;
| Wicat Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2028&lt;br /&gt;
| 07EC&lt;br /&gt;
| Applied Systems &amp;amp;amp; Peripherals&lt;br /&gt;
|-&lt;br /&gt;
| 2029&lt;br /&gt;
| 07ED&lt;br /&gt;
| Delaware Valley Software&lt;br /&gt;
|-&lt;br /&gt;
| 2030&lt;br /&gt;
| 07EE&lt;br /&gt;
| Palomax&lt;br /&gt;
|-&lt;br /&gt;
| 2031&lt;br /&gt;
| 07EF&lt;br /&gt;
| Incognito Software&lt;br /&gt;
|-&lt;br /&gt;
| 2032&lt;br /&gt;
| 07F0&lt;br /&gt;
| Jadesign&lt;br /&gt;
|-&lt;br /&gt;
| 2033&lt;br /&gt;
| 07F1&lt;br /&gt;
| BVR&lt;br /&gt;
|-&lt;br /&gt;
| 2034&lt;br /&gt;
| 07F2&lt;br /&gt;
| Spirit Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2035&lt;br /&gt;
| 07F3&lt;br /&gt;
| Spirit Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2036&lt;br /&gt;
| 07F4&lt;br /&gt;
| Atronic&lt;br /&gt;
|-&lt;br /&gt;
| 2037&lt;br /&gt;
| 07F5&lt;br /&gt;
| Scott Karlin&lt;br /&gt;
|-&lt;br /&gt;
| 2038&lt;br /&gt;
| 07F6&lt;br /&gt;
| Howitch&lt;br /&gt;
|-&lt;br /&gt;
| 2039&lt;br /&gt;
| 07F7&lt;br /&gt;
| Sullivan Brothers Visual Engineers&lt;br /&gt;
|-&lt;br /&gt;
| 2040&lt;br /&gt;
| 07F8&lt;br /&gt;
| G I T&lt;br /&gt;
|-&lt;br /&gt;
| 2041&lt;br /&gt;
| 07F9&lt;br /&gt;
| Amigo Business Computers&lt;br /&gt;
|-&lt;br /&gt;
| 2042&lt;br /&gt;
| 07FA&lt;br /&gt;
| Micro E Ab&lt;br /&gt;
|-&lt;br /&gt;
| 2043&lt;br /&gt;
| 07FB&lt;br /&gt;
| Ralph Kruse&lt;br /&gt;
|-&lt;br /&gt;
| 2044&lt;br /&gt;
| 07FC&lt;br /&gt;
| Clearpoint Research&lt;br /&gt;
|-&lt;br /&gt;
| 2045&lt;br /&gt;
| 07FD&lt;br /&gt;
| Kodiak&lt;br /&gt;
|-&lt;br /&gt;
| 2046&lt;br /&gt;
| 07FE&lt;br /&gt;
| BSC&lt;br /&gt;
| Originally registered to Phoenix Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2047&lt;br /&gt;
| 07FF&lt;br /&gt;
| No Name Shown&lt;br /&gt;
|-&lt;br /&gt;
| 2048&lt;br /&gt;
| 0800&lt;br /&gt;
| Commodore Braunschweig&lt;br /&gt;
|-&lt;br /&gt;
| 2049&lt;br /&gt;
| 0801&lt;br /&gt;
| BSC&lt;br /&gt;
| Originally registered to Elaborate Bytes&lt;br /&gt;
|-&lt;br /&gt;
| 2050&lt;br /&gt;
| 0802&lt;br /&gt;
| Kronos/C Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2051&lt;br /&gt;
| 0803&lt;br /&gt;
| Spartanics&lt;br /&gt;
|-&lt;br /&gt;
| 2052&lt;br /&gt;
| 0804&lt;br /&gt;
| Jochheim Computer Tuning&lt;br /&gt;
|-&lt;br /&gt;
| 2053&lt;br /&gt;
| 0805&lt;br /&gt;
| Trans Data Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2054&lt;br /&gt;
| 0806&lt;br /&gt;
| Applied Systems &amp;amp;amp; Peripherals Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2055&lt;br /&gt;
| 0807&lt;br /&gt;
| Checkpoint Technologies&lt;br /&gt;
| Originally registered to Amiga Solutions&lt;br /&gt;
|-&lt;br /&gt;
| 2056&lt;br /&gt;
| 0808&lt;br /&gt;
| Adept Development&lt;br /&gt;
|-&lt;br /&gt;
| 2057&lt;br /&gt;
| 0809&lt;br /&gt;
| Advanced Computer Design&lt;br /&gt;
|-&lt;br /&gt;
| 2058&lt;br /&gt;
| 080A&lt;br /&gt;
| Sir Netics&lt;br /&gt;
|-&lt;br /&gt;
| 2059&lt;br /&gt;
| 080B&lt;br /&gt;
| Expert Services&lt;br /&gt;
|-&lt;br /&gt;
| 2060&lt;br /&gt;
| 080C&lt;br /&gt;
| Digital Art Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2061&lt;br /&gt;
| 080D&lt;br /&gt;
| Adept Development&lt;br /&gt;
|-&lt;br /&gt;
| 2062&lt;br /&gt;
| 080E&lt;br /&gt;
| Expansion Technologies (Expansion Systems)&lt;br /&gt;
|-&lt;br /&gt;
| 2063&lt;br /&gt;
| 080F&lt;br /&gt;
| Alphatech&lt;br /&gt;
|-&lt;br /&gt;
| 2064&lt;br /&gt;
| 0810&lt;br /&gt;
| Edotronik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2065&lt;br /&gt;
| 0811&lt;br /&gt;
| California Access/Synergy&lt;br /&gt;
| Originally registered to Logical Design Works&lt;br /&gt;
|-&lt;br /&gt;
| 2066&lt;br /&gt;
| 0812&lt;br /&gt;
| Bowden, Williams, Full &amp;amp; Assoc.&lt;br /&gt;
|-&lt;br /&gt;
| 2067&lt;br /&gt;
| 0813&lt;br /&gt;
| NES, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2068&lt;br /&gt;
| 0814&lt;br /&gt;
| Amdev&lt;br /&gt;
|-&lt;br /&gt;
| 2069&lt;br /&gt;
| 0815&lt;br /&gt;
| Big Brother Security Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2070&lt;br /&gt;
| 0816&lt;br /&gt;
| Active Circuits Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2071&lt;br /&gt;
| 0817&lt;br /&gt;
| ICD, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2072&lt;br /&gt;
| 0818&lt;br /&gt;
| Multi-Meg Electronique&lt;br /&gt;
|-&lt;br /&gt;
| 2073&lt;br /&gt;
| 0819&lt;br /&gt;
| Kupke Computertechnik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2074&lt;br /&gt;
| 081A&lt;br /&gt;
| The Checkered Ball&lt;br /&gt;
|-&lt;br /&gt;
| 2075&lt;br /&gt;
| 081B&lt;br /&gt;
| Hi Tension Computer Services Ltd. (UK)&lt;br /&gt;
|-&lt;br /&gt;
| 2076&lt;br /&gt;
| 081C&lt;br /&gt;
| Alfa Data&lt;br /&gt;
| Originally assigned to Elmtech Research, Ltd. (UK)&lt;br /&gt;
|-&lt;br /&gt;
| 2077&lt;br /&gt;
| 081D&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
| Originally registered to Clartscreen, Ltd. (UK)&lt;br /&gt;
|-&lt;br /&gt;
| 2078&lt;br /&gt;
| 081E&lt;br /&gt;
| Interworks&lt;br /&gt;
|-&lt;br /&gt;
| 2079&lt;br /&gt;
| 081F&lt;br /&gt;
| Galysh Enterprises&lt;br /&gt;
|-&lt;br /&gt;
| 2080&lt;br /&gt;
| 0820&lt;br /&gt;
| Hardital Synthesis&lt;br /&gt;
| Originally registered to Realtime Games Software Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2081&lt;br /&gt;
| 0821&lt;br /&gt;
| GBS&lt;br /&gt;
|-&lt;br /&gt;
| 2082&lt;br /&gt;
| 0822&lt;br /&gt;
| Circum Design Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2083&lt;br /&gt;
| 0823&lt;br /&gt;
| Alberta Micro Electronic Center&lt;br /&gt;
|-&lt;br /&gt;
| 2084&lt;br /&gt;
| 0824&lt;br /&gt;
| Bestech&lt;br /&gt;
|-&lt;br /&gt;
| 2085&lt;br /&gt;
| 0825&lt;br /&gt;
| Lasar Fantasy&lt;br /&gt;
|-&lt;br /&gt;
| 2086&lt;br /&gt;
| 0826&lt;br /&gt;
| Pulsar&lt;br /&gt;
|-&lt;br /&gt;
| 2087&lt;br /&gt;
| 0827&lt;br /&gt;
| Ivis&lt;br /&gt;
|-&lt;br /&gt;
| 2088&lt;br /&gt;
| 0828&lt;br /&gt;
| Applied Engineering&lt;br /&gt;
|-&lt;br /&gt;
| 2089&lt;br /&gt;
| 0829&lt;br /&gt;
| Solid-State Design &amp;amp;amp; Development&lt;br /&gt;
|-&lt;br /&gt;
| 2090&lt;br /&gt;
| 082A&lt;br /&gt;
| Vison Quest&lt;br /&gt;
|-&lt;br /&gt;
| 2091&lt;br /&gt;
| 082B&lt;br /&gt;
| Seaview Software&lt;br /&gt;
|-&lt;br /&gt;
| 2092&lt;br /&gt;
| 082C&lt;br /&gt;
| BSC&lt;br /&gt;
| Mistakenly used by ADS (Advanced Development Software)&lt;br /&gt;
|-&lt;br /&gt;
| 2093&lt;br /&gt;
| 082D&lt;br /&gt;
| Bernd Culenfeld&lt;br /&gt;
|-&lt;br /&gt;
| 2094&lt;br /&gt;
| 082E&lt;br /&gt;
| American Liquid Light&lt;br /&gt;
|-&lt;br /&gt;
| 2095&lt;br /&gt;
| 082F&lt;br /&gt;
| CEGITES&lt;br /&gt;
|-&lt;br /&gt;
| 2096&lt;br /&gt;
| 0830&lt;br /&gt;
| Quadlite Computers Ltd.&lt;br /&gt;
| Originally registered to EV Industries&lt;br /&gt;
|-&lt;br /&gt;
| 2097&lt;br /&gt;
| 0831&lt;br /&gt;
| Silicon Peace&lt;br /&gt;
|-&lt;br /&gt;
| 2098&lt;br /&gt;
| 0832&lt;br /&gt;
| Black Belt Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2099&lt;br /&gt;
| 0833&lt;br /&gt;
| Village Tronic&lt;br /&gt;
| Originally registerd to Steve Yaeger&lt;br /&gt;
|-&lt;br /&gt;
| 2100&lt;br /&gt;
| 0834&lt;br /&gt;
| ReadySoft&lt;br /&gt;
|-&lt;br /&gt;
| 2101&lt;br /&gt;
| 0835&lt;br /&gt;
| Phoenix Micro Technologies&lt;br /&gt;
|-&lt;br /&gt;
| 2102&lt;br /&gt;
| 0836&lt;br /&gt;
| Advanced Systems &amp;amp; Software&lt;br /&gt;
| Orignally assigned to Preferred Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2103&lt;br /&gt;
| 0837&lt;br /&gt;
| Rombo Productions&lt;br /&gt;
|-&lt;br /&gt;
| 2104&lt;br /&gt;
| 0838&lt;br /&gt;
| Impulse Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2105&lt;br /&gt;
| 0839&lt;br /&gt;
| Beta Unlimited&lt;br /&gt;
|-&lt;br /&gt;
| 2106&lt;br /&gt;
| 083A&lt;br /&gt;
| Memory Expansion System, Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2107&lt;br /&gt;
| 083B&lt;br /&gt;
| Vortex Computer Systems GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2108&lt;br /&gt;
| 083C&lt;br /&gt;
| Platypus Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2109&lt;br /&gt;
| 083D&lt;br /&gt;
| Gigatron OHG&lt;br /&gt;
|-&lt;br /&gt;
| 2110&lt;br /&gt;
| 083E&lt;br /&gt;
| PG Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2111&lt;br /&gt;
| 083F&lt;br /&gt;
| New Technologies Group&lt;br /&gt;
|-&lt;br /&gt;
| 2112&lt;br /&gt;
| 0840&lt;br /&gt;
| Interactive Video Systems (IVS)&lt;br /&gt;
| Pacific Peripherals&lt;br /&gt;
|-&lt;br /&gt;
| 2113&lt;br /&gt;
| 0841&lt;br /&gt;
| Vector&lt;br /&gt;
| Originally registered to H. K. Computer&lt;br /&gt;
|-&lt;br /&gt;
| 2114&lt;br /&gt;
| 0842&lt;br /&gt;
| Pacific Digital&lt;br /&gt;
| Originally registered to C. H. Helfrich Elektronik&lt;br /&gt;
|-&lt;br /&gt;
| 2115&lt;br /&gt;
| 0843&lt;br /&gt;
| Xanadu&lt;br /&gt;
|-&lt;br /&gt;
| 2116&lt;br /&gt;
| 0844&lt;br /&gt;
| Pacific Digital&lt;br /&gt;
| Originally registered to AMS&lt;br /&gt;
|-&lt;br /&gt;
| 2117&lt;br /&gt;
| 0845&lt;br /&gt;
| X-Pert&lt;br /&gt;
|-&lt;br /&gt;
| 2118&lt;br /&gt;
| 0846&lt;br /&gt;
| The Amiga Centre&lt;br /&gt;
|-&lt;br /&gt;
| 2119&lt;br /&gt;
| 0847&lt;br /&gt;
| Digital Pacific&lt;br /&gt;
|-&lt;br /&gt;
| 2120&lt;br /&gt;
| 0848&lt;br /&gt;
| Solid State Leisure&lt;br /&gt;
|-&lt;br /&gt;
| 2121&lt;br /&gt;
| 0849&lt;br /&gt;
| Hydra Systems&lt;br /&gt;
| Originally registered to Analog Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2122&lt;br /&gt;
| 084A&lt;br /&gt;
| Cumana&lt;br /&gt;
|-&lt;br /&gt;
| 2123&lt;br /&gt;
| 084B&lt;br /&gt;
| KAPS 2C Conception&lt;br /&gt;
|-&lt;br /&gt;
| 2124&lt;br /&gt;
| 084C&lt;br /&gt;
| Mike Mason&lt;br /&gt;
|-&lt;br /&gt;
| 2125&lt;br /&gt;
| 084D&lt;br /&gt;
| For Your Eyes&lt;br /&gt;
|-&lt;br /&gt;
| 2126&lt;br /&gt;
| 084E&lt;br /&gt;
| Volkmar Breitfeld Computersysteme&lt;br /&gt;
|-&lt;br /&gt;
| 2127&lt;br /&gt;
| 084F&lt;br /&gt;
| Sunrize Industries&lt;br /&gt;
|-&lt;br /&gt;
| 2128&lt;br /&gt;
| 0850&lt;br /&gt;
| Scott Advanced Micro Designs&lt;br /&gt;
|-&lt;br /&gt;
| 2129&lt;br /&gt;
| 0851&lt;br /&gt;
| Digital Micronics&lt;br /&gt;
|-&lt;br /&gt;
| 2130&lt;br /&gt;
| 0852&lt;br /&gt;
| Alfa-Laval&lt;br /&gt;
|-&lt;br /&gt;
| 2131&lt;br /&gt;
| 0853&lt;br /&gt;
| Multigros A/S&lt;br /&gt;
|-&lt;br /&gt;
| 2132&lt;br /&gt;
| 0854&lt;br /&gt;
| Archos&lt;br /&gt;
|-&lt;br /&gt;
| 2133&lt;br /&gt;
| 0855&lt;br /&gt;
| Icom Simulations&lt;br /&gt;
|-&lt;br /&gt;
| 2134&lt;br /&gt;
| 0856&lt;br /&gt;
| Commodore Test Engineering Group&lt;br /&gt;
|-&lt;br /&gt;
| 2135&lt;br /&gt;
| 0857&lt;br /&gt;
| Microcreations&lt;br /&gt;
|-&lt;br /&gt;
| 2136&lt;br /&gt;
| 0858&lt;br /&gt;
| Shoestring Productions&lt;br /&gt;
|-&lt;br /&gt;
| 2137&lt;br /&gt;
| 0859&lt;br /&gt;
| Faberushi&lt;br /&gt;
|-&lt;br /&gt;
| 2138&lt;br /&gt;
| 085A&lt;br /&gt;
| Evesham Micro Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2139&lt;br /&gt;
| 085B&lt;br /&gt;
| Panagolin Laser Software&lt;br /&gt;
|-&lt;br /&gt;
| 2140&lt;br /&gt;
| 085C&lt;br /&gt;
| Thomas Rudloff&lt;br /&gt;
|-&lt;br /&gt;
| 2141&lt;br /&gt;
| 085D&lt;br /&gt;
| Daniel Hohabir&lt;br /&gt;
|-&lt;br /&gt;
| 2142&lt;br /&gt;
| 085E&lt;br /&gt;
| GfxBase, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2143&lt;br /&gt;
| 085F&lt;br /&gt;
| Axellabs&lt;br /&gt;
|-&lt;br /&gt;
| 2144&lt;br /&gt;
| 0860&lt;br /&gt;
| Roctec Electronics Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2145&lt;br /&gt;
| 0861&lt;br /&gt;
| Omega Datentechnik&lt;br /&gt;
|-&lt;br /&gt;
| 2146&lt;br /&gt;
| 0862&lt;br /&gt;
| Atlantis&lt;br /&gt;
|-&lt;br /&gt;
| 2147&lt;br /&gt;
| 0863&lt;br /&gt;
| Skytec Computers&lt;br /&gt;
|-&lt;br /&gt;
| 2148&lt;br /&gt;
| 0864&lt;br /&gt;
| Protar Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2149&lt;br /&gt;
| 0865&lt;br /&gt;
| ACS&lt;br /&gt;
|-&lt;br /&gt;
| 2150&lt;br /&gt;
| 0866&lt;br /&gt;
| Software Results Enterprises&lt;br /&gt;
| Originally registered to University of Illinois&lt;br /&gt;
|-&lt;br /&gt;
| 2151&lt;br /&gt;
| 0867&lt;br /&gt;
| Infinity Systems Design Group&lt;br /&gt;
|-&lt;br /&gt;
| 2152&lt;br /&gt;
| 0868&lt;br /&gt;
| Trade It&lt;br /&gt;
|-&lt;br /&gt;
| 2153&lt;br /&gt;
| 0869&lt;br /&gt;
| Suntec, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2154&lt;br /&gt;
| 086A&lt;br /&gt;
| DJW Micro Systems&lt;br /&gt;
| Originally registered to Tritec Marketing&lt;br /&gt;
|-&lt;br /&gt;
| 2155&lt;br /&gt;
| 086B&lt;br /&gt;
| Power Computing Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2156&lt;br /&gt;
| 086C&lt;br /&gt;
| MacroSystems&lt;br /&gt;
|-&lt;br /&gt;
| 2157&lt;br /&gt;
| 086D&lt;br /&gt;
| Masoboshi GmbH (DCE)&lt;br /&gt;
|-&lt;br /&gt;
| 2158&lt;br /&gt;
| 086E&lt;br /&gt;
| HAL Software Hardware Handel&lt;br /&gt;
|-&lt;br /&gt;
| 2159&lt;br /&gt;
| 086F&lt;br /&gt;
| Mainhattan Data&lt;br /&gt;
| Originally registered to Michael Lamm Computersysteme&lt;br /&gt;
|-&lt;br /&gt;
| 2160&lt;br /&gt;
| 0870&lt;br /&gt;
| Digital Processing System&lt;br /&gt;
| Originally registered to bbdp Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2161&lt;br /&gt;
| 0871&lt;br /&gt;
| Blue Ribbon Soundworks&lt;br /&gt;
| Originally registered to Design Computer Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2162&lt;br /&gt;
| 0872&lt;br /&gt;
| XPert&lt;br /&gt;
| Originally registered to The Station&lt;br /&gt;
|-&lt;br /&gt;
| 2163&lt;br /&gt;
| 0873&lt;br /&gt;
| DelaComp&lt;br /&gt;
| Originally registered to Bryan Williams&lt;br /&gt;
|-&lt;br /&gt;
| 2164&lt;br /&gt;
| 0874&lt;br /&gt;
| Superformance Computer Engineering GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2165&lt;br /&gt;
| 0875&lt;br /&gt;
| Overland Engineering&lt;br /&gt;
|-&lt;br /&gt;
| 2166&lt;br /&gt;
| 0876&lt;br /&gt;
| Thomas Hamren&lt;br /&gt;
|-&lt;br /&gt;
| 2167&lt;br /&gt;
| 0877&lt;br /&gt;
| Village Tronic&lt;br /&gt;
|-&lt;br /&gt;
| 2168&lt;br /&gt;
| 0878&lt;br /&gt;
| Toolbox Design&lt;br /&gt;
|-&lt;br /&gt;
| 2169&lt;br /&gt;
| 0879&lt;br /&gt;
| Digital Processing System&lt;br /&gt;
|-&lt;br /&gt;
| 2170&lt;br /&gt;
| 087A&lt;br /&gt;
| Superformance&lt;br /&gt;
|-&lt;br /&gt;
| 2171&lt;br /&gt;
| 087B&lt;br /&gt;
| Utilities Unlimited&lt;br /&gt;
|-&lt;br /&gt;
| 2172&lt;br /&gt;
| 087C&lt;br /&gt;
| phase 5&lt;br /&gt;
|-&lt;br /&gt;
| 2173&lt;br /&gt;
| 087D&lt;br /&gt;
| Juergen Kommos&lt;br /&gt;
|-&lt;br /&gt;
| 2174&lt;br /&gt;
| 087E&lt;br /&gt;
| Electronic Design&lt;br /&gt;
|-&lt;br /&gt;
| 2175&lt;br /&gt;
| 087F&lt;br /&gt;
| James Cook University of North Queensland&lt;br /&gt;
|-&lt;br /&gt;
| 2176&lt;br /&gt;
| 0880&lt;br /&gt;
| AmiTrix Development&lt;br /&gt;
|-&lt;br /&gt;
| 2177&lt;br /&gt;
| 0881&lt;br /&gt;
| Ferranti&lt;br /&gt;
|-&lt;br /&gt;
| 2178&lt;br /&gt;
| 0882&lt;br /&gt;
| Leviathan Development&lt;br /&gt;
|-&lt;br /&gt;
| 2179&lt;br /&gt;
| 0883&lt;br /&gt;
| United Video Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2180&lt;br /&gt;
| 0884&lt;br /&gt;
| GPSoft Pty. Ltd.&lt;br /&gt;
| Originally registered to Juergen Kommos&lt;br /&gt;
|-&lt;br /&gt;
| 2181&lt;br /&gt;
| 0885&lt;br /&gt;
| ArMAX&lt;br /&gt;
| Oliver Bausch&lt;br /&gt;
|-&lt;br /&gt;
| 2182&lt;br /&gt;
| 0886&lt;br /&gt;
| CP Computer&lt;br /&gt;
|-&lt;br /&gt;
| 2183&lt;br /&gt;
| 0887&lt;br /&gt;
| AMOK - Amiga Module &amp;amp;amp; Oberon Klub&lt;br /&gt;
|-&lt;br /&gt;
| 2184&lt;br /&gt;
| 0888&lt;br /&gt;
| ITEK Neser &amp;amp;amp; Sieber GbR&lt;br /&gt;
|-&lt;br /&gt;
| 2185&lt;br /&gt;
| 0889&lt;br /&gt;
| Phillip C. Lello&lt;br /&gt;
|-&lt;br /&gt;
| 2186&lt;br /&gt;
| 088A&lt;br /&gt;
| Cyborg Design Services&lt;br /&gt;
|-&lt;br /&gt;
| 2187&lt;br /&gt;
| 088B&lt;br /&gt;
| G2 Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2188&lt;br /&gt;
| 088C&lt;br /&gt;
| Pro System Computersysteme&lt;br /&gt;
|-&lt;br /&gt;
| 2189&lt;br /&gt;
| 088D&lt;br /&gt;
| ZEUS Electronic&lt;br /&gt;
| Originally registered to MSPI (Markt &amp;amp;amp; Technik)&lt;br /&gt;
|-&lt;br /&gt;
| 2190&lt;br /&gt;
| 088E&lt;br /&gt;
| Altatech&lt;br /&gt;
|-&lt;br /&gt;
| 2191&lt;br /&gt;
| 088F&lt;br /&gt;
| NewTek&lt;br /&gt;
|-&lt;br /&gt;
| 2192&lt;br /&gt;
| 0890&lt;br /&gt;
| M-TEC Hardware Design&lt;br /&gt;
| Originally registered to Hardware Design Udo Neuroth&lt;br /&gt;
|-&lt;br /&gt;
| 2193&lt;br /&gt;
| 0891&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
| Originally registered to Viona Development&lt;br /&gt;
|-&lt;br /&gt;
| 2194&lt;br /&gt;
| 0892&lt;br /&gt;
| Amitek&lt;br /&gt;
| Originally assigned to Marpet Developments&lt;br /&gt;
|-&lt;br /&gt;
| 2195&lt;br /&gt;
| 0893&lt;br /&gt;
| Ingenieurbuero Helfrich&lt;br /&gt;
|-&lt;br /&gt;
| 2196&lt;br /&gt;
| 0894&lt;br /&gt;
| The Neo Group&lt;br /&gt;
|-&lt;br /&gt;
| 2197&lt;br /&gt;
| 0895&lt;br /&gt;
| Cyon&lt;br /&gt;
|-&lt;br /&gt;
| 2198&lt;br /&gt;
| 0896&lt;br /&gt;
| Bob Research Group&lt;br /&gt;
|-&lt;br /&gt;
| 2199&lt;br /&gt;
| 0897&lt;br /&gt;
| Richmond Sound Design Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2200&lt;br /&gt;
| 0898&lt;br /&gt;
| US Cybernetics&lt;br /&gt;
|-&lt;br /&gt;
| 2201&lt;br /&gt;
| 0899&lt;br /&gt;
| Fulvio Ieva&lt;br /&gt;
|-&lt;br /&gt;
| 2202&lt;br /&gt;
| 089A&lt;br /&gt;
| Silicon Studio&lt;br /&gt;
|-&lt;br /&gt;
| 2203&lt;br /&gt;
| 089B&lt;br /&gt;
| MacroSystems (USA)&lt;br /&gt;
| Was named Micro System Devices&lt;br /&gt;
|-&lt;br /&gt;
| 2204&lt;br /&gt;
| 089C&lt;br /&gt;
| Conspector Entertainment&lt;br /&gt;
|-&lt;br /&gt;
| 2205&lt;br /&gt;
| 089D&lt;br /&gt;
| Laserforum&lt;br /&gt;
|-&lt;br /&gt;
| 2206&lt;br /&gt;
| 089E&lt;br /&gt;
| Elbox Computer&lt;br /&gt;
| Mistakenly used by Index Information Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2207&lt;br /&gt;
| 089F&lt;br /&gt;
| Applied Magic Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2208&lt;br /&gt;
| 08A0&lt;br /&gt;
| SDL Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2560&lt;br /&gt;
| 0A00&lt;br /&gt;
| Harms&lt;br /&gt;
|-&lt;br /&gt;
| 2588&lt;br /&gt;
| 0A1C&lt;br /&gt;
| A1K.org Community&lt;br /&gt;
|-&lt;br /&gt;
| 2640&lt;br /&gt;
| 0A50&lt;br /&gt;
| Micronik&lt;br /&gt;
|-&lt;br /&gt;
| 2782&lt;br /&gt;
| 2782&lt;br /&gt;
| OA Design&lt;br /&gt;
|-&lt;br /&gt;
| 3084&lt;br /&gt;
| 0C0C&lt;br /&gt;
| Team 4&lt;br /&gt;
|-&lt;br /&gt;
| 3643&lt;br /&gt;
| 0E3B&lt;br /&gt;
| E3B&lt;br /&gt;
| Michael Boehmer&lt;br /&gt;
|-&lt;br /&gt;
| 3855&lt;br /&gt;
| 0F0F&lt;br /&gt;
| Micronik&lt;br /&gt;
|-&lt;br /&gt;
| 4096&lt;br /&gt;
| 1000&lt;br /&gt;
| MegaMicro&lt;br /&gt;
|-&lt;br /&gt;
| 4110&lt;br /&gt;
| 100E&lt;br /&gt;
| DigiFeX&lt;br /&gt;
|-&lt;br /&gt;
| 4136&lt;br /&gt;
| 1028&lt;br /&gt;
| Imtronics/Memphis&lt;br /&gt;
|-&lt;br /&gt;
| 4149&lt;br /&gt;
| 1035&lt;br /&gt;
| PROTAR&lt;br /&gt;
|-&lt;br /&gt;
| 4369&lt;br /&gt;
| 1111&lt;br /&gt;
| Frank Strauß Elektronik&lt;br /&gt;
| Also used by Kupke&lt;br /&gt;
|-&lt;br /&gt;
| 4626&lt;br /&gt;
| 1212&lt;br /&gt;
| Individual Computers&lt;br /&gt;
|-&lt;br /&gt;
| 4648&lt;br /&gt;
| 1228&lt;br /&gt;
| Flesch Hornemann Computer Elec.&lt;br /&gt;
|-&lt;br /&gt;
| 4680&lt;br /&gt;
| 1248&lt;br /&gt;
| Kupke Computertechnik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 4711&lt;br /&gt;
| 1267&lt;br /&gt;
| RBM digitaltechnik&lt;br /&gt;
|-&lt;br /&gt;
| 4754&lt;br /&gt;
| 1292&lt;br /&gt;
| MacroSystems&lt;br /&gt;
|-&lt;br /&gt;
| 5000&lt;br /&gt;
| 1388&lt;br /&gt;
| ITH&lt;br /&gt;
|-&lt;br /&gt;
| 5001&lt;br /&gt;
| 1389&lt;br /&gt;
| VMC&lt;br /&gt;
|-&lt;br /&gt;
| 5010&lt;br /&gt;
| 1392&lt;br /&gt;
| Ambience Creation Technology&lt;br /&gt;
|-&lt;br /&gt;
| 5011&lt;br /&gt;
| 1393&lt;br /&gt;
| Creative Development&lt;br /&gt;
|-&lt;br /&gt;
| 5012&lt;br /&gt;
| 1394&lt;br /&gt;
| Georg Braun&lt;br /&gt;
|-&lt;br /&gt;
| 5013&lt;br /&gt;
| 1395&lt;br /&gt;
| Swedish User Group of Amiga&lt;br /&gt;
|-&lt;br /&gt;
| 5014&lt;br /&gt;
| 1396&lt;br /&gt;
| Jakub Bednarski&lt;br /&gt;
|-&lt;br /&gt;
| 5015&lt;br /&gt;
| 1397&lt;br /&gt;
| KryoFlux, Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 5016&lt;br /&gt;
| 1398&lt;br /&gt;
| Igor Majstorovic&lt;br /&gt;
|-&lt;br /&gt;
| 5017&lt;br /&gt;
| 1399&lt;br /&gt;
| Alastair M. Robinson&lt;br /&gt;
|-&lt;br /&gt;
| 5018&lt;br /&gt;
| 139A&lt;br /&gt;
| Austex Software&lt;br /&gt;
|-&lt;br /&gt;
| 5019&lt;br /&gt;
| 139B&lt;br /&gt;
| Sören Gust&lt;br /&gt;
|-&lt;br /&gt;
| 5020&lt;br /&gt;
| 139C&lt;br /&gt;
| Rok Krajnc&lt;br /&gt;
|-&lt;br /&gt;
| 5030&lt;br /&gt;
| 13A6&lt;br /&gt;
| Tim Tashpulatov&lt;br /&gt;
|-&lt;br /&gt;
| 5040&lt;br /&gt;
| 13B0&lt;br /&gt;
| 7-bit&lt;br /&gt;
|-&lt;br /&gt;
| 5050&lt;br /&gt;
| 13BA&lt;br /&gt;
| Sakura IT&lt;br /&gt;
|-&lt;br /&gt;
| 5060&lt;br /&gt;
| 13C4&lt;br /&gt;
| FPGAArcade&lt;br /&gt;
|-&lt;br /&gt;
| 5070&lt;br /&gt;
| 13CE&lt;br /&gt;
| CancerSoft Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 5080&lt;br /&gt;
| 13D8&lt;br /&gt;
| Stephen Leary&lt;br /&gt;
|-&lt;br /&gt;
| 5090&lt;br /&gt;
| 13E2&lt;br /&gt;
| DMA Softlab LLC&lt;br /&gt;
|-&lt;br /&gt;
| 5100&lt;br /&gt;
| 13EC&lt;br /&gt;
| Brookhouse Engineering&lt;br /&gt;
|-&lt;br /&gt;
| 5110&lt;br /&gt;
| 13F6&lt;br /&gt;
| Eduardo Arana&lt;br /&gt;
|-&lt;br /&gt;
| 5120&lt;br /&gt;
| 1400&lt;br /&gt;
| CS-LAB&lt;br /&gt;
|-&lt;br /&gt;
| 5130&lt;br /&gt;
| 140A&lt;br /&gt;
| Robert Miranda&lt;br /&gt;
|-&lt;br /&gt;
| 5140&lt;br /&gt;
| 1414&lt;br /&gt;
| RastPort&lt;br /&gt;
|-&lt;br /&gt;
| 5132&lt;br /&gt;
| 140C&lt;br /&gt;
| UAS Interface Ltd6&lt;br /&gt;
|-&lt;br /&gt;
| 5150&lt;br /&gt;
| 141E&lt;br /&gt;
| Amiga Kit&lt;br /&gt;
|-&lt;br /&gt;
| 5160&lt;br /&gt;
| 1428&lt;br /&gt;
| Central Texas Commodore User Group&lt;br /&gt;
|-&lt;br /&gt;
| 5170&lt;br /&gt;
| 1432&lt;br /&gt;
| Confusion Research Center&lt;br /&gt;
|-&lt;br /&gt;
| 5180&lt;br /&gt;
| 143C&lt;br /&gt;
| Solar Soyuz Zaibatsu&lt;br /&gt;
|-&lt;br /&gt;
| 5190&lt;br /&gt;
| 1446&lt;br /&gt;
| BooBip&lt;br /&gt;
|-&lt;br /&gt;
| 5191&lt;br /&gt;
| 1447&lt;br /&gt;
| Matthias Hampel&lt;br /&gt;
|-&lt;br /&gt;
| 5192&lt;br /&gt;
| 1448&lt;br /&gt;
| dec0de Consulting Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 5193&lt;br /&gt;
| 1449&lt;br /&gt;
| Puppy Concepts&lt;br /&gt;
|-&lt;br /&gt;
| 5194&lt;br /&gt;
| 144A&lt;br /&gt;
| Open Amiga Hardware Repository&lt;br /&gt;
|-&lt;br /&gt;
| 5195&lt;br /&gt;
| 144B&lt;br /&gt;
| Double H Tech&lt;br /&gt;
|-&lt;br /&gt;
| 5196&lt;br /&gt;
| 144C&lt;br /&gt;
| Retromatik&lt;br /&gt;
|-&lt;br /&gt;
| 5500&lt;br /&gt;
| 157C&lt;br /&gt;
| Inhouse Information&lt;br /&gt;
|-&lt;br /&gt;
| 5768&lt;br /&gt;
| 1688&lt;br /&gt;
| Bio Con&lt;br /&gt;
|-&lt;br /&gt;
| 6148&lt;br /&gt;
| 1804&lt;br /&gt;
| HK-Computer&lt;br /&gt;
|-&lt;br /&gt;
| 6502&lt;br /&gt;
| 1966&lt;br /&gt;
| Cloanto&lt;br /&gt;
|-&lt;br /&gt;
| 6520&lt;br /&gt;
| 1978&lt;br /&gt;
| Oliver Gantert&lt;br /&gt;
|-&lt;br /&gt;
| 7777&lt;br /&gt;
| 1E61&lt;br /&gt;
| Rafal Gabriel Chyla&lt;br /&gt;
|-&lt;br /&gt;
| 8215&lt;br /&gt;
| 2017&lt;br /&gt;
| Vortex&lt;br /&gt;
|-&lt;br /&gt;
| 8244&lt;br /&gt;
| 2034&lt;br /&gt;
| Spirit Technology&lt;br /&gt;
|-&lt;br /&gt;
| 8290&lt;br /&gt;
| 2062&lt;br /&gt;
| Expansion Systems&lt;br /&gt;
|-&lt;br /&gt;
| 8448&lt;br /&gt;
| 2100&lt;br /&gt;
| ReadySoft&lt;br /&gt;
|-&lt;br /&gt;
| 8512&lt;br /&gt;
| 2140&lt;br /&gt;
| Phase 5 Digital Products&lt;br /&gt;
|-&lt;br /&gt;
| 8553&lt;br /&gt;
| 2169&lt;br /&gt;
| Digital Processing Systems Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 8704&lt;br /&gt;
| 2200&lt;br /&gt;
| ACT Elektronik&lt;br /&gt;
|-&lt;br /&gt;
| 8738&lt;br /&gt;
| 2222&lt;br /&gt;
| ACT Elektronik&lt;br /&gt;
|-&lt;br /&gt;
| 9512&lt;br /&gt;
| 2528&lt;br /&gt;
| Tower Technologies&lt;br /&gt;
|-&lt;br /&gt;
| 10676&lt;br /&gt;
| 29B4&lt;br /&gt;
| Electronic Design&lt;br /&gt;
|-&lt;br /&gt;
| 14195&lt;br /&gt;
| 3773&lt;br /&gt;
| Media-net-Point&lt;br /&gt;
|-&lt;br /&gt;
| 14501&lt;br /&gt;
| 38A5&lt;br /&gt;
| Petsoff, Finland&lt;br /&gt;
|-&lt;br /&gt;
| 16375&lt;br /&gt;
| 3FF7&lt;br /&gt;
| Uwe Gerlach&lt;br /&gt;
|-&lt;br /&gt;
| 16707&lt;br /&gt;
| 4143&lt;br /&gt;
| Ateo Concepts&lt;br /&gt;
|-&lt;br /&gt;
| 16708&lt;br /&gt;
| 4144&lt;br /&gt;
| ALiENDESiGN&lt;br /&gt;
|-&lt;br /&gt;
| 16945&lt;br /&gt;
| 4231&lt;br /&gt;
| A.C.T.&lt;br /&gt;
|-&lt;br /&gt;
| 17740&lt;br /&gt;
| 454C&lt;br /&gt;
| HK-Computer (ELSAT)&lt;br /&gt;
|-&lt;br /&gt;
| 18260&lt;br /&gt;
| 4754&lt;br /&gt;
| MacroSystems (Germany)&lt;br /&gt;
|-&lt;br /&gt;
| 19796&lt;br /&gt;
| 4D54&lt;br /&gt;
| Markt &amp;amp; Technik&lt;br /&gt;
|-&lt;br /&gt;
| 20480&lt;br /&gt;
| 5000&lt;br /&gt;
| François Lacombe&lt;br /&gt;
|-&lt;br /&gt;
| 22359&lt;br /&gt;
| 5757&lt;br /&gt;
| Markt &amp;amp; Technik&lt;br /&gt;
|-&lt;br /&gt;
| 26464&lt;br /&gt;
| 6760&lt;br /&gt;
| Combitec&lt;br /&gt;
|-&lt;br /&gt;
| 26470&lt;br /&gt;
| 6766&lt;br /&gt;
| Combitec&lt;br /&gt;
|-&lt;br /&gt;
| 28014&lt;br /&gt;
| 6D6E&lt;br /&gt;
| MNT Media and Technology UG&lt;br /&gt;
|-&lt;br /&gt;
| 28019&lt;br /&gt;
| 6D73&lt;br /&gt;
| Michal Schulz&lt;br /&gt;
|-&lt;br /&gt;
| 28020&lt;br /&gt;
| 6D74&lt;br /&gt;
| PiStorm&lt;br /&gt;
|-&lt;br /&gt;
| 32768&lt;br /&gt;
| 8000&lt;br /&gt;
| M.A.S.T.&lt;br /&gt;
|-&lt;br /&gt;
| 42240&lt;br /&gt;
| A500&lt;br /&gt;
| Aethreum Digital&lt;br /&gt;
|-&lt;br /&gt;
| 43437&lt;br /&gt;
| A9AD&lt;br /&gt;
| Reis-Ware&lt;br /&gt;
|-&lt;br /&gt;
| 43521&lt;br /&gt;
| AA01&lt;br /&gt;
| Cameron&lt;br /&gt;
|-&lt;br /&gt;
| 43537&lt;br /&gt;
| AA11&lt;br /&gt;
| Reis-Ware&lt;br /&gt;
|-&lt;br /&gt;
| 44359&lt;br /&gt;
| AD47&lt;br /&gt;
| Matay&lt;br /&gt;
|-&lt;br /&gt;
| 46504&lt;br /&gt;
| B5A8&lt;br /&gt;
| Phoenix&lt;br /&gt;
|-&lt;br /&gt;
| 48879&lt;br /&gt;
| BEEF&lt;br /&gt;
| Swiss Mountain Dog Products&lt;br /&gt;
|-&lt;br /&gt;
| 49160&lt;br /&gt;
| C008&lt;br /&gt;
| Combitec&lt;br /&gt;
|-&lt;br /&gt;
| 49374&lt;br /&gt;
| C0DE&lt;br /&gt;
| Stefan Reinauer&lt;br /&gt;
|-&lt;br /&gt;
| 61453&lt;br /&gt;
| F00D&lt;br /&gt;
| Forefront Technologies Inc.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
For any changes/additions to this registry see [[#How_to_Obtain_a_Manufacturer_Number|How to Obtain a Manufacturer Number]]&lt;/div&gt;</summary>
		<author><name>Costel Mincea</name></author>
	</entry>
	<entry>
		<id>https://wiki.amigaos.net/w/index.php?title=Amiga_Hardware_Manufacturer_ID_Registry&amp;diff=12605</id>
		<title>Amiga Hardware Manufacturer ID Registry</title>
		<link rel="alternate" type="text/html" href="https://wiki.amigaos.net/w/index.php?title=Amiga_Hardware_Manufacturer_ID_Registry&amp;diff=12605"/>
		<updated>2026-09-08T11:13:41Z</updated>

		<summary type="html">&lt;p&gt;Costel Mincea: Added PiStorm (28020)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
= How to Obtain a Manufacturer Number =&lt;br /&gt;
&lt;br /&gt;
Manufacturer&#039;s numbers are assigned by the AmigaOS development team. To obtain your unique manufacturer number send a support request to [mailto:support@hyperion-entertainment.com support@hyperion-entertainment.com] including these information:&lt;br /&gt;
&lt;br /&gt;
 1. The name of the company or person which the number is assigned to&lt;br /&gt;
 &lt;br /&gt;
 2. Postal address/contact address&lt;br /&gt;
 &lt;br /&gt;
 3. Name of the contact person, with a corresponding e-mail address&lt;br /&gt;
 &lt;br /&gt;
 4. A brief description of the kind of products you want to produce&lt;br /&gt;
&lt;br /&gt;
= Your Manufacturer Number =&lt;br /&gt;
&lt;br /&gt;
Attention hardware manufacturers. If you are developing a hardware expansion product for the Classic Amiga (e.g. 500, 2000, 3000) then you will need to obtain a special manufacturer ID number from the AmigaOS development team to identify your product. This manufacturer number is used by the Amiga to link your hardware with its driver software at boot time.&lt;br /&gt;
&lt;br /&gt;
Your manufacturer number is part of the special protocol that the Amiga uses to automatically configure all expansion devices on the bus without the user having to cut jumpers or adjust dip switches. This is called auto-config.&lt;br /&gt;
&lt;br /&gt;
At start-up time, the system first polls each board in the system and assigns the board its own address space. If it is a memory board, its RAM is linked into the memory free pool. Later in the boot sequence, after DOS is initialized, the binddrivers program is run. Binddrivers will search the directory SYS:Expansion for the drivers that go with the boards.&lt;br /&gt;
&lt;br /&gt;
To do this binddrivers looks in the Tool Type field of all icon files in SYS:Expansion. If the first seven bytes of the Tool Type field are &amp;quot;PRODUCT&amp;quot;, then this is an icon file for a driver.&lt;br /&gt;
&lt;br /&gt;
Binddrivers will then attempt to match the drivers it has found with the boards that were found earlier. This is where your manufacturer number comes in.&lt;br /&gt;
&lt;br /&gt;
Your manufacturer number goes in two places. First, it is burned in hex form into the PAL which is part of ALL auto-config expansion products. Second, it appears in ASCII in the Tool Type field of the icon file for your product&#039;s driver. By matching these two numbers, the Amiga can automatically configure your board and bind it&#039;s software driver into the system as well.&lt;br /&gt;
&lt;br /&gt;
The manufacturer&#039;s number is a 16-bit ID which appears in PAL offsets $10-$17. There is also an 8-bit product number which you assign. The product number is for uniquely identifying different products from the same vendor. The product number will appear in PAL offsets $04-$07. This gives you a total of 24 bits to identify each of your products.&lt;br /&gt;
&lt;br /&gt;
These 24 bits of information in the PAL which identify your product are matched against the information in the Tool Type field of all icon files in the SYS:Expansion drawer. For example, suppose you are manufacturer #1019. You have two products, #1 and #2 which both use the same driver. The icon for your driver for these two products would have a Tool Type set to &amp;quot;PRODUCT=1019/1|1019/2&amp;quot;. This means: I am an icon for a driver that works with product number 1 or 2 from manufacturer 1019, now bind me. Spaces are not legal. Here are two other examples:&lt;br /&gt;
&lt;br /&gt;
; PRODUCT=1208/11&lt;br /&gt;
: is the Tool Type for a driver for product 11 from manufacturer number 1208.&lt;br /&gt;
&lt;br /&gt;
; PRODUCT=1017&lt;br /&gt;
: is the Tool Type for a driver for any product from manufacturer number 1017.&lt;br /&gt;
&lt;br /&gt;
For an informal explanation of the auto-configuration process, see the chapter on Software Expansion Architecture from the 2nd Annual Amiga Developer&#039;s Conference Notes (available on ADCD 2.1). For the details of timing, power, the PAL equations and PAL address specifications and the expansion library documentation, see sections 3.1 to 3.3 of the A500/A2000 Technical Reference Manual. The original auto-config spec appears in the A1000 Schematics and Expansion Specification.&lt;br /&gt;
&lt;br /&gt;
The auto-config process makes the addition of expansion products to the system very easy. All the user has to do is put the board in any slot and copy the driver from the release disk to his own SYS:Expansion drawer. Everything else is automatic. There are no jumpers or dip switches to set. Best of all, you will get a lot less support calls asking how to make your product work with the XYZ-Corp-battery-backed-clock.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
&lt;br /&gt;
Some notes on hardware manufacturer ID assignment.&lt;br /&gt;
&lt;br /&gt;
* Manufacturer ID numbers are assigned free of charge.&lt;br /&gt;
* Please provide the following information when requesting an ID:&lt;br /&gt;
*# Name of the company or person&lt;br /&gt;
*# Postal address/contact address&lt;br /&gt;
*# Name of the contact person, with a corresponding e-mail address&lt;br /&gt;
*# A brief description of the kind of products you want to produce&lt;br /&gt;
* All ID numbers smaller than 5000 must be considered unsafe because no information exists on which numbers exactly were taken during the time Commodore, Inc. disintegrated.&lt;br /&gt;
* ID numbers in the range 8192 to 18841 must be considered unsafe because some hardware developers mistook the numbers assigned to them to be given in hexadecimal format. Hence 0x2000 = 8192 and 0x4999 = 18841.&lt;br /&gt;
&lt;br /&gt;
= Example code =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
/*-----------------------------------------------*/&lt;br /&gt;
/* Here is a short program which will tell you   */&lt;br /&gt;
/* about the expansion boards configured in your */&lt;br /&gt;
/* system without you opening up the machine.    */&lt;br /&gt;
/* Code by Bill Koester of CATS                  */&lt;br /&gt;
/*-----------------------------------------------*/&lt;br /&gt;
#include &amp;lt;libraries/configvars.h&amp;gt;&lt;br /&gt;
#include &amp;lt;libraries/expansion.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
struct ExpansionBase *ExpansionBase;&lt;br /&gt;
&lt;br /&gt;
void cleanup();&lt;br /&gt;
void printdev();&lt;br /&gt;
&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
   struct ConfigDev *MyConfigDev;&lt;br /&gt;
&lt;br /&gt;
   /*----------------------------------*/&lt;br /&gt;
   /* Open the expansion library,      */&lt;br /&gt;
   /* if there is a problem then exit  */&lt;br /&gt;
   /*----------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   ExpansionBase =(struct ExpansionBase *) OpenLibrary(EXPANSIONNAME,0);&lt;br /&gt;
   if(ExpansionBase==NULL)&lt;br /&gt;
   {&lt;br /&gt;
      printf(&amp;quot;Error opening expansion library!!\n&amp;quot;);&lt;br /&gt;
      cleanup();&lt;br /&gt;
      exit(0);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   /*--------------------------------------------*/&lt;br /&gt;
   /* Use FindConfigDev to get info on the first */&lt;br /&gt;
   /* expansion board on the list maintained by  */&lt;br /&gt;
   /* Exec.  If there are no expansion boards in */&lt;br /&gt;
   /* the system then exit.                      */&lt;br /&gt;
   /*--------------------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   MyConfigDev = NULL;&lt;br /&gt;
&lt;br /&gt;
  /*--------------------------------------------------*/&lt;br /&gt;
  /* FindConfigDev(oldConfigDev,manufacturer,product) */&lt;br /&gt;
  /* oldConfigDev = NULL for the top of the list      */&lt;br /&gt;
  /* manufacturer = -1 for any manufacturer           */&lt;br /&gt;
  /* product      = -1 for any product                */&lt;br /&gt;
  /*--------------------------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   MyConfigDev = FindConfigDev(NULL,-1,-1);&lt;br /&gt;
&lt;br /&gt;
   if(MyConfigDev==NULL)&lt;br /&gt;
   {&lt;br /&gt;
      printf(&amp;quot;No Configured Devices found!!\n&amp;quot;);&lt;br /&gt;
      cleanup();&lt;br /&gt;
      exit(0);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   printdev(MyConfigDev);&lt;br /&gt;
&lt;br /&gt;
   /*-----------------------------------*/&lt;br /&gt;
   /* OK, there is at least one board,  */&lt;br /&gt;
   /* so loop and get the entire list   */&lt;br /&gt;
   /* printing as we go with printdev() */&lt;br /&gt;
   /*-----------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   while(MyConfigDev = FindConfigDev(MyConfigDev,-1,-1))&lt;br /&gt;
   {&lt;br /&gt;
      printdev(MyConfigDev);&lt;br /&gt;
   }&lt;br /&gt;
   cleanup();&lt;br /&gt;
   return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*-------------------*/&lt;br /&gt;
/* Close up shop...  */&lt;br /&gt;
/*-------------------*/&lt;br /&gt;
void cleanup()&lt;br /&gt;
{&lt;br /&gt;
   if(ExpansionBase)&lt;br /&gt;
      CloseLibrary(ExpansionBase);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*----------------------------------*/&lt;br /&gt;
/* Print out the contents of the    */&lt;br /&gt;
/* dev structure for this expansion */&lt;br /&gt;
/* product.                         */&lt;br /&gt;
/*----------------------------------*/&lt;br /&gt;
&lt;br /&gt;
void printdev(dev)&lt;br /&gt;
struct ConfigDev *dev;&lt;br /&gt;
{&lt;br /&gt;
   char buff[200];&lt;br /&gt;
&lt;br /&gt;
   printf(&amp;quot;Flags          = &amp;quot;);&lt;br /&gt;
   if(dev-&amp;gt;cd_Flags==NULL)&lt;br /&gt;
      printf(&amp;quot;NULL  &amp;quot;);&lt;br /&gt;
   if(dev-&amp;gt;cd_Flags&amp;amp;CDF_SHUTUP)&lt;br /&gt;
      printf(&amp;quot;CDF_SHUTUP  &amp;quot;);&lt;br /&gt;
   if(dev-&amp;gt;cd_Flags&amp;amp;CDF_CONFIGME)&lt;br /&gt;
      printf(&amp;quot;CDF_CONFIGME  &amp;quot;);&lt;br /&gt;
   printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
   printf(&amp;quot;Board Address  = %x\n&amp;quot;,dev-&amp;gt;cd_BoardAddr);&lt;br /&gt;
   printf(&amp;quot;Board Size     = %d bytes\n&amp;quot;,dev-&amp;gt;cd_BoardSize);&lt;br /&gt;
   printf(&amp;quot;Slot  Address  = %d\n&amp;quot;,dev-&amp;gt;cd_SlotAddr);&lt;br /&gt;
   printf(&amp;quot;Slot  Size     = %d\n&amp;quot;,dev-&amp;gt;cd_SlotSize);&lt;br /&gt;
   printf(&amp;quot;Driver code at   %x\n&amp;quot;,dev-&amp;gt;cd_Driver);&lt;br /&gt;
&lt;br /&gt;
   printf(&amp;quot;er_Type         = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Type);&lt;br /&gt;
   printf(&amp;quot;er_Product      = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Product);&lt;br /&gt;
   printf(&amp;quot;er_Flags        = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Flags);&lt;br /&gt;
   printf(&amp;quot;er_Reserved03   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved03);&lt;br /&gt;
   printf(&amp;quot;er_Manufacturer = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Manufacturer);&lt;br /&gt;
   printf(&amp;quot;er_SerialNumber = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_SerialNumber);&lt;br /&gt;
   printf(&amp;quot;er_InitDiagVec  = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_InitDiagVec);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0c   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0c);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0d   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0d);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0e   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0e);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0f   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0f);&lt;br /&gt;
&lt;br /&gt;
   printf(&amp;quot;Hit Return to continue:\n&amp;quot;);&lt;br /&gt;
   gets(buff);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Registry =&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! ID (decimal)&lt;br /&gt;
! ID (hexadecimal)&lt;br /&gt;
! Manufacturer&lt;br /&gt;
! Notes&lt;br /&gt;
|-&lt;br /&gt;
| 1&lt;br /&gt;
| 0001&lt;br /&gt;
| Micronik&lt;br /&gt;
|-&lt;br /&gt;
| 211&lt;br /&gt;
| 00D3&lt;br /&gt;
| Pacific Peripherals/Profex&lt;br /&gt;
|-&lt;br /&gt;
| 221&lt;br /&gt;
| 00DD&lt;br /&gt;
| Kupke Computertechnik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 256&lt;br /&gt;
| 0100&lt;br /&gt;
| Memphis&lt;br /&gt;
| Originally registered to MacroSystems US&lt;br /&gt;
|-&lt;br /&gt;
| 512&lt;br /&gt;
| 0200&lt;br /&gt;
| 3-State Computertechnik&lt;br /&gt;
|-&lt;br /&gt;
| 513&lt;br /&gt;
| 0201&lt;br /&gt;
| Commodore (Braunschweig)&lt;br /&gt;
|-&lt;br /&gt;
| 514&lt;br /&gt;
| 0202&lt;br /&gt;
| Commodore (West Chester)&lt;br /&gt;
|-&lt;br /&gt;
| 515&lt;br /&gt;
| 0203&lt;br /&gt;
| Commodore (West Chester)&lt;br /&gt;
| Originally registered to Combitech/Macrosystem&lt;br /&gt;
|-&lt;br /&gt;
| 756&lt;br /&gt;
| 02F4&lt;br /&gt;
| Progressive Peripherals &amp;amp; Software&lt;br /&gt;
|-&lt;br /&gt;
| 767&lt;br /&gt;
| 02FF&lt;br /&gt;
| Kolff Computer Supplies&lt;br /&gt;
|-&lt;br /&gt;
| 1001&lt;br /&gt;
| 03E9&lt;br /&gt;
| Tecmar&lt;br /&gt;
|-&lt;br /&gt;
| 1002&lt;br /&gt;
| 03EA&lt;br /&gt;
| Telesys&lt;br /&gt;
|-&lt;br /&gt;
| 1003&lt;br /&gt;
| 03EB&lt;br /&gt;
| The Micro-Forge&lt;br /&gt;
|-&lt;br /&gt;
| 1004&lt;br /&gt;
| 03EC&lt;br /&gt;
| Kronos/C Ltd.&lt;br /&gt;
| Originally registered to Card Co. (Supra)&lt;br /&gt;
|-&lt;br /&gt;
| 1005&lt;br /&gt;
| 03ED&lt;br /&gt;
| A-Squared&lt;br /&gt;
|-&lt;br /&gt;
| 1006&lt;br /&gt;
| 03EE&lt;br /&gt;
| Comspec Communications&lt;br /&gt;
|-&lt;br /&gt;
| 1007&lt;br /&gt;
| 03EF&lt;br /&gt;
| HT Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 1008&lt;br /&gt;
| 03F0&lt;br /&gt;
| RDS Software&lt;br /&gt;
|-&lt;br /&gt;
| 1009&lt;br /&gt;
| 03F1&lt;br /&gt;
| Anakin Research&lt;br /&gt;
|-&lt;br /&gt;
| 1010&lt;br /&gt;
| 03F2&lt;br /&gt;
| MicroBotics&lt;br /&gt;
|-&lt;br /&gt;
| 1011&lt;br /&gt;
| 03F3&lt;br /&gt;
| Bob Krauth&lt;br /&gt;
|-&lt;br /&gt;
| 1012&lt;br /&gt;
| 03F4&lt;br /&gt;
| Access Associates (Alegra)&lt;br /&gt;
|-&lt;br /&gt;
| 1013&lt;br /&gt;
| 03F5&lt;br /&gt;
| Mini Comp Systems Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 1014&lt;br /&gt;
| 03F6&lt;br /&gt;
| Cypress Technology&lt;br /&gt;
|-&lt;br /&gt;
| 1015&lt;br /&gt;
| 03F7&lt;br /&gt;
| Fuller Computers&lt;br /&gt;
|-&lt;br /&gt;
| 1016&lt;br /&gt;
| 03F8&lt;br /&gt;
| Galaxy Computers&lt;br /&gt;
|-&lt;br /&gt;
| 1017&lt;br /&gt;
| 03F9&lt;br /&gt;
| ADA Research&lt;br /&gt;
|-&lt;br /&gt;
| 1018&lt;br /&gt;
| 03FA&lt;br /&gt;
| Computer Service Italia&lt;br /&gt;
|-&lt;br /&gt;
| 1019&lt;br /&gt;
| 03FB&lt;br /&gt;
| Amigo&lt;br /&gt;
|-&lt;br /&gt;
| 1020&lt;br /&gt;
| 03FC&lt;br /&gt;
| Micro-Solutions Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1021&lt;br /&gt;
| 03FD&lt;br /&gt;
| Stacar International&lt;br /&gt;
|-&lt;br /&gt;
| 1022&lt;br /&gt;
| 03FE&lt;br /&gt;
| Video Precisions&lt;br /&gt;
|-&lt;br /&gt;
| 1023&lt;br /&gt;
| 03FF&lt;br /&gt;
| ASDG, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1025&lt;br /&gt;
| 0401&lt;br /&gt;
| Ing. Buero Kalawsky&lt;br /&gt;
|-&lt;br /&gt;
| 1026&lt;br /&gt;
| 0402&lt;br /&gt;
| Computer Tuning&lt;br /&gt;
|-&lt;br /&gt;
| 1027&lt;br /&gt;
| 0403&lt;br /&gt;
| Interplan Unternehmensberatung&lt;br /&gt;
|-&lt;br /&gt;
| 1028&lt;br /&gt;
| 0404&lt;br /&gt;
| Imtronics/Memphis&lt;br /&gt;
| Originally registered to Peter Ohlich&lt;br /&gt;
|-&lt;br /&gt;
| 1030&lt;br /&gt;
| 0406&lt;br /&gt;
| Commodore (Lowell University)&lt;br /&gt;
| Originally registered to Productivity Center&lt;br /&gt;
|-&lt;br /&gt;
| 1041&lt;br /&gt;
| 0411&lt;br /&gt;
| Design Labs&lt;br /&gt;
|-&lt;br /&gt;
| 1042&lt;br /&gt;
| 0412&lt;br /&gt;
| MCS&lt;br /&gt;
|-&lt;br /&gt;
| 1043&lt;br /&gt;
| 0413&lt;br /&gt;
| B. J. Freeman&lt;br /&gt;
|-&lt;br /&gt;
| 1044&lt;br /&gt;
| 0414&lt;br /&gt;
| Side Effects Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1045&lt;br /&gt;
| 0415&lt;br /&gt;
| Oklahoma Personal Comp.&lt;br /&gt;
|-&lt;br /&gt;
| 1046&lt;br /&gt;
| 0416&lt;br /&gt;
| Advanced Micro Innovations&lt;br /&gt;
|-&lt;br /&gt;
| 1047&lt;br /&gt;
| 0417&lt;br /&gt;
| Industrial Support Services&lt;br /&gt;
|-&lt;br /&gt;
| 1048&lt;br /&gt;
| 0418&lt;br /&gt;
| Technisoft&lt;br /&gt;
|-&lt;br /&gt;
| 1049&lt;br /&gt;
| 0419&lt;br /&gt;
| Prolific, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1050&lt;br /&gt;
| 041A&lt;br /&gt;
| Softeam, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1051&lt;br /&gt;
| 041B&lt;br /&gt;
| GRC Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 1052&lt;br /&gt;
| 041C&lt;br /&gt;
| David Lai&lt;br /&gt;
|-&lt;br /&gt;
| 1053&lt;br /&gt;
| 041D&lt;br /&gt;
| Ameristar Technologies&lt;br /&gt;
|-&lt;br /&gt;
| 1054&lt;br /&gt;
| 041E&lt;br /&gt;
| Cline Refrigeration&lt;br /&gt;
|-&lt;br /&gt;
| 1055&lt;br /&gt;
| 041F&lt;br /&gt;
| Cardiac Pacemakers, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1056&lt;br /&gt;
| 0420&lt;br /&gt;
| Supra Corp. (Creative Microsystems)&lt;br /&gt;
|-&lt;br /&gt;
| 1057&lt;br /&gt;
| 0421&lt;br /&gt;
| Wayne Diener&lt;br /&gt;
|-&lt;br /&gt;
| 1058&lt;br /&gt;
| 0422&lt;br /&gt;
| Computer Systems Associates (CSA)&lt;br /&gt;
|-&lt;br /&gt;
| 1059&lt;br /&gt;
| 0423&lt;br /&gt;
| Trionix, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1060&lt;br /&gt;
| 0424&lt;br /&gt;
| David Lucas&lt;br /&gt;
|-&lt;br /&gt;
| 1061&lt;br /&gt;
| 0425&lt;br /&gt;
| Analog Precision&lt;br /&gt;
| Also assigned to D &amp;amp; L Distributing&lt;br /&gt;
|-&lt;br /&gt;
| 1267&lt;br /&gt;
| 04F3&lt;br /&gt;
| RBM Digitaltechnik&lt;br /&gt;
|-&lt;br /&gt;
| 1282&lt;br /&gt;
| 0502&lt;br /&gt;
| M-TEC Hardware Design&lt;br /&gt;
|-&lt;br /&gt;
| 1337&lt;br /&gt;
| 0539&lt;br /&gt;
| Thomas Stenzel (DaFR34K)&lt;br /&gt;
|-&lt;br /&gt;
| 1576&lt;br /&gt;
| 0628&lt;br /&gt;
| Boris Križma&lt;br /&gt;
|-&lt;br /&gt;
| 1729&lt;br /&gt;
| 06C1&lt;br /&gt;
| Thomas Richter / OpenPCI-A1200 Mediator bridge&lt;br /&gt;
|-&lt;br /&gt;
| 1730&lt;br /&gt;
| 06C2&lt;br /&gt;
| Thomas Richter / OpenPCI-A4000 Mediator bridge&lt;br /&gt;
|-&lt;br /&gt;
| 1731&lt;br /&gt;
| 06C3&lt;br /&gt;
| Thomas Richter / OpenPCI-Prometheus bridge (Firestorm or original)&lt;br /&gt;
|-&lt;br /&gt;
| 1732&lt;br /&gt;
| 06C4&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved1&lt;br /&gt;
|-&lt;br /&gt;
| 1733&lt;br /&gt;
| 06C5&lt;br /&gt;
| Thomas Richter / OpenPCI-Grex bridge (both A1200 and A4000)&lt;br /&gt;
|-&lt;br /&gt;
| 1734&lt;br /&gt;
| 06C6&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved2&lt;br /&gt;
|-&lt;br /&gt;
| 1735&lt;br /&gt;
| 06C7&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved3&lt;br /&gt;
|-&lt;br /&gt;
| 1736&lt;br /&gt;
| 06C8&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved4&lt;br /&gt;
|-&lt;br /&gt;
| 1737&lt;br /&gt;
| 06C9&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved5&lt;br /&gt;
|-&lt;br /&gt;
| 1738&lt;br /&gt;
| 06CA&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved6&lt;br /&gt;
|-&lt;br /&gt;
| 1739&lt;br /&gt;
| 06CB&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved7&lt;br /&gt;
|-&lt;br /&gt;
| 1740&lt;br /&gt;
| 06CC&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved8&lt;br /&gt;
|-&lt;br /&gt;
| 1741&lt;br /&gt;
| 06CD&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved9&lt;br /&gt;
|-&lt;br /&gt;
| 1742&lt;br /&gt;
| 06CE&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved10&lt;br /&gt;
|-&lt;br /&gt;
| 1743&lt;br /&gt;
| 06CF&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved11&lt;br /&gt;
|-&lt;br /&gt;
| 1744&lt;br /&gt;
| 06D0&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved12&lt;br /&gt;
|-&lt;br /&gt;
| 1761&lt;br /&gt;
| 06E1&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
|-&lt;br /&gt;
| 1803&lt;br /&gt;
| 070B&lt;br /&gt;
| UAE Amiga Emulator&lt;br /&gt;
|-&lt;br /&gt;
| 2002&lt;br /&gt;
| 07D2&lt;br /&gt;
| Mimetics Corp.&lt;br /&gt;
|-&lt;br /&gt;
| 2003&lt;br /&gt;
| 07D3&lt;br /&gt;
| ACDA&lt;br /&gt;
|-&lt;br /&gt;
| 2004&lt;br /&gt;
| 07D4&lt;br /&gt;
| Finn R. Jacobsen&lt;br /&gt;
|-&lt;br /&gt;
| 2005&lt;br /&gt;
| 07D5&lt;br /&gt;
| Elthen Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2006&lt;br /&gt;
| 07D6&lt;br /&gt;
| Nine Tiles Computer Systems Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2007&lt;br /&gt;
| 07D7&lt;br /&gt;
| Analog Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2008&lt;br /&gt;
| 07D8&lt;br /&gt;
| Bell &amp;amp;amp; Howell&lt;br /&gt;
|-&lt;br /&gt;
| 2009&lt;br /&gt;
| 07D9&lt;br /&gt;
| Roland Kochler&lt;br /&gt;
|-&lt;br /&gt;
| 2010&lt;br /&gt;
| 07DA&lt;br /&gt;
| Byte Corp.&lt;br /&gt;
|-&lt;br /&gt;
| 2011&lt;br /&gt;
| 07DB&lt;br /&gt;
| Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 2012&lt;br /&gt;
| 07DC&lt;br /&gt;
| DKB, Inc.&lt;br /&gt;
| Previously named Michigan Software&lt;br /&gt;
|-&lt;br /&gt;
| 2013&lt;br /&gt;
| 07DD&lt;br /&gt;
| Pacific Peripherals&lt;br /&gt;
|-&lt;br /&gt;
| 2014&lt;br /&gt;
| 07DE&lt;br /&gt;
| Sysaphus Software&lt;br /&gt;
|-&lt;br /&gt;
| 2015&lt;br /&gt;
| 07DF&lt;br /&gt;
| Digitronics&lt;br /&gt;
|-&lt;br /&gt;
| 2016&lt;br /&gt;
| 07E0&lt;br /&gt;
| Akron Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2017&lt;br /&gt;
| 07E1&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
|-&lt;br /&gt;
| 2018&lt;br /&gt;
| 07E2&lt;br /&gt;
| Calmos&lt;br /&gt;
|-&lt;br /&gt;
| 2019&lt;br /&gt;
| 07E3&lt;br /&gt;
| Dover Research&lt;br /&gt;
|-&lt;br /&gt;
| 2020&lt;br /&gt;
| 07E4&lt;br /&gt;
| David Krehbiel&lt;br /&gt;
|-&lt;br /&gt;
| 2021&lt;br /&gt;
| 07E5&lt;br /&gt;
| Synergy Peripheral Systems&lt;br /&gt;
| Also known as California Access&lt;br /&gt;
|-&lt;br /&gt;
| 2022&lt;br /&gt;
| 07E6&lt;br /&gt;
| Xetec&lt;br /&gt;
|-&lt;br /&gt;
| 2023&lt;br /&gt;
| 07E7&lt;br /&gt;
| Micron Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2024&lt;br /&gt;
| 07E8&lt;br /&gt;
| CH Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2025&lt;br /&gt;
| 07E9&lt;br /&gt;
| American Liquid Light&lt;br /&gt;
|-&lt;br /&gt;
| 2026&lt;br /&gt;
| 07EA&lt;br /&gt;
| Progressive Peripherals &amp;amp;amp; Software&lt;br /&gt;
| Also used by Ateo&lt;br /&gt;
|-&lt;br /&gt;
| 2027&lt;br /&gt;
| 07EB&lt;br /&gt;
| Wicat Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2028&lt;br /&gt;
| 07EC&lt;br /&gt;
| Applied Systems &amp;amp;amp; Peripherals&lt;br /&gt;
|-&lt;br /&gt;
| 2029&lt;br /&gt;
| 07ED&lt;br /&gt;
| Delaware Valley Software&lt;br /&gt;
|-&lt;br /&gt;
| 2030&lt;br /&gt;
| 07EE&lt;br /&gt;
| Palomax&lt;br /&gt;
|-&lt;br /&gt;
| 2031&lt;br /&gt;
| 07EF&lt;br /&gt;
| Incognito Software&lt;br /&gt;
|-&lt;br /&gt;
| 2032&lt;br /&gt;
| 07F0&lt;br /&gt;
| Jadesign&lt;br /&gt;
|-&lt;br /&gt;
| 2033&lt;br /&gt;
| 07F1&lt;br /&gt;
| BVR&lt;br /&gt;
|-&lt;br /&gt;
| 2034&lt;br /&gt;
| 07F2&lt;br /&gt;
| Spirit Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2035&lt;br /&gt;
| 07F3&lt;br /&gt;
| Spirit Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2036&lt;br /&gt;
| 07F4&lt;br /&gt;
| Atronic&lt;br /&gt;
|-&lt;br /&gt;
| 2037&lt;br /&gt;
| 07F5&lt;br /&gt;
| Scott Karlin&lt;br /&gt;
|-&lt;br /&gt;
| 2038&lt;br /&gt;
| 07F6&lt;br /&gt;
| Howitch&lt;br /&gt;
|-&lt;br /&gt;
| 2039&lt;br /&gt;
| 07F7&lt;br /&gt;
| Sullivan Brothers Visual Engineers&lt;br /&gt;
|-&lt;br /&gt;
| 2040&lt;br /&gt;
| 07F8&lt;br /&gt;
| G I T&lt;br /&gt;
|-&lt;br /&gt;
| 2041&lt;br /&gt;
| 07F9&lt;br /&gt;
| Amigo Business Computers&lt;br /&gt;
|-&lt;br /&gt;
| 2042&lt;br /&gt;
| 07FA&lt;br /&gt;
| Micro E Ab&lt;br /&gt;
|-&lt;br /&gt;
| 2043&lt;br /&gt;
| 07FB&lt;br /&gt;
| Ralph Kruse&lt;br /&gt;
|-&lt;br /&gt;
| 2044&lt;br /&gt;
| 07FC&lt;br /&gt;
| Clearpoint Research&lt;br /&gt;
|-&lt;br /&gt;
| 2045&lt;br /&gt;
| 07FD&lt;br /&gt;
| Kodiak&lt;br /&gt;
|-&lt;br /&gt;
| 2046&lt;br /&gt;
| 07FE&lt;br /&gt;
| BSC&lt;br /&gt;
| Originally registered to Phoenix Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2047&lt;br /&gt;
| 07FF&lt;br /&gt;
| No Name Shown&lt;br /&gt;
|-&lt;br /&gt;
| 2048&lt;br /&gt;
| 0800&lt;br /&gt;
| Commodore Braunschweig&lt;br /&gt;
|-&lt;br /&gt;
| 2049&lt;br /&gt;
| 0801&lt;br /&gt;
| BSC&lt;br /&gt;
| Originally registered to Elaborate Bytes&lt;br /&gt;
|-&lt;br /&gt;
| 2050&lt;br /&gt;
| 0802&lt;br /&gt;
| Kronos/C Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2051&lt;br /&gt;
| 0803&lt;br /&gt;
| Spartanics&lt;br /&gt;
|-&lt;br /&gt;
| 2052&lt;br /&gt;
| 0804&lt;br /&gt;
| Jochheim Computer Tuning&lt;br /&gt;
|-&lt;br /&gt;
| 2053&lt;br /&gt;
| 0805&lt;br /&gt;
| Trans Data Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2054&lt;br /&gt;
| 0806&lt;br /&gt;
| Applied Systems &amp;amp;amp; Peripherals Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2055&lt;br /&gt;
| 0807&lt;br /&gt;
| Checkpoint Technologies&lt;br /&gt;
| Originally registered to Amiga Solutions&lt;br /&gt;
|-&lt;br /&gt;
| 2056&lt;br /&gt;
| 0808&lt;br /&gt;
| Adept Development&lt;br /&gt;
|-&lt;br /&gt;
| 2057&lt;br /&gt;
| 0809&lt;br /&gt;
| Advanced Computer Design&lt;br /&gt;
|-&lt;br /&gt;
| 2058&lt;br /&gt;
| 080A&lt;br /&gt;
| Sir Netics&lt;br /&gt;
|-&lt;br /&gt;
| 2059&lt;br /&gt;
| 080B&lt;br /&gt;
| Expert Services&lt;br /&gt;
|-&lt;br /&gt;
| 2060&lt;br /&gt;
| 080C&lt;br /&gt;
| Digital Art Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2061&lt;br /&gt;
| 080D&lt;br /&gt;
| Adept Development&lt;br /&gt;
|-&lt;br /&gt;
| 2062&lt;br /&gt;
| 080E&lt;br /&gt;
| Expansion Technologies (Expansion Systems)&lt;br /&gt;
|-&lt;br /&gt;
| 2063&lt;br /&gt;
| 080F&lt;br /&gt;
| Alphatech&lt;br /&gt;
|-&lt;br /&gt;
| 2064&lt;br /&gt;
| 0810&lt;br /&gt;
| Edotronik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2065&lt;br /&gt;
| 0811&lt;br /&gt;
| California Access/Synergy&lt;br /&gt;
| Originally registered to Logical Design Works&lt;br /&gt;
|-&lt;br /&gt;
| 2066&lt;br /&gt;
| 0812&lt;br /&gt;
| Bowden, Williams, Full &amp;amp; Assoc.&lt;br /&gt;
|-&lt;br /&gt;
| 2067&lt;br /&gt;
| 0813&lt;br /&gt;
| NES, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2068&lt;br /&gt;
| 0814&lt;br /&gt;
| Amdev&lt;br /&gt;
|-&lt;br /&gt;
| 2069&lt;br /&gt;
| 0815&lt;br /&gt;
| Big Brother Security Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2070&lt;br /&gt;
| 0816&lt;br /&gt;
| Active Circuits Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2071&lt;br /&gt;
| 0817&lt;br /&gt;
| ICD, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2072&lt;br /&gt;
| 0818&lt;br /&gt;
| Multi-Meg Electronique&lt;br /&gt;
|-&lt;br /&gt;
| 2073&lt;br /&gt;
| 0819&lt;br /&gt;
| Kupke Computertechnik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2074&lt;br /&gt;
| 081A&lt;br /&gt;
| The Checkered Ball&lt;br /&gt;
|-&lt;br /&gt;
| 2075&lt;br /&gt;
| 081B&lt;br /&gt;
| Hi Tension Computer Services Ltd. (UK)&lt;br /&gt;
|-&lt;br /&gt;
| 2076&lt;br /&gt;
| 081C&lt;br /&gt;
| Alfa Data&lt;br /&gt;
| Originally assigned to Elmtech Research, Ltd. (UK)&lt;br /&gt;
|-&lt;br /&gt;
| 2077&lt;br /&gt;
| 081D&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
| Originally registered to Clartscreen, Ltd. (UK)&lt;br /&gt;
|-&lt;br /&gt;
| 2078&lt;br /&gt;
| 081E&lt;br /&gt;
| Interworks&lt;br /&gt;
|-&lt;br /&gt;
| 2079&lt;br /&gt;
| 081F&lt;br /&gt;
| Galysh Enterprises&lt;br /&gt;
|-&lt;br /&gt;
| 2080&lt;br /&gt;
| 0820&lt;br /&gt;
| Hardital Synthesis&lt;br /&gt;
| Originally registered to Realtime Games Software Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2081&lt;br /&gt;
| 0821&lt;br /&gt;
| GBS&lt;br /&gt;
|-&lt;br /&gt;
| 2082&lt;br /&gt;
| 0822&lt;br /&gt;
| Circum Design Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2083&lt;br /&gt;
| 0823&lt;br /&gt;
| Alberta Micro Electronic Center&lt;br /&gt;
|-&lt;br /&gt;
| 2084&lt;br /&gt;
| 0824&lt;br /&gt;
| Bestech&lt;br /&gt;
|-&lt;br /&gt;
| 2085&lt;br /&gt;
| 0825&lt;br /&gt;
| Lasar Fantasy&lt;br /&gt;
|-&lt;br /&gt;
| 2086&lt;br /&gt;
| 0826&lt;br /&gt;
| Pulsar&lt;br /&gt;
|-&lt;br /&gt;
| 2087&lt;br /&gt;
| 0827&lt;br /&gt;
| Ivis&lt;br /&gt;
|-&lt;br /&gt;
| 2088&lt;br /&gt;
| 0828&lt;br /&gt;
| Applied Engineering&lt;br /&gt;
|-&lt;br /&gt;
| 2089&lt;br /&gt;
| 0829&lt;br /&gt;
| Solid-State Design &amp;amp;amp; Development&lt;br /&gt;
|-&lt;br /&gt;
| 2090&lt;br /&gt;
| 082A&lt;br /&gt;
| Vison Quest&lt;br /&gt;
|-&lt;br /&gt;
| 2091&lt;br /&gt;
| 082B&lt;br /&gt;
| Seaview Software&lt;br /&gt;
|-&lt;br /&gt;
| 2092&lt;br /&gt;
| 082C&lt;br /&gt;
| BSC&lt;br /&gt;
| Mistakenly used by ADS (Advanced Development Software)&lt;br /&gt;
|-&lt;br /&gt;
| 2093&lt;br /&gt;
| 082D&lt;br /&gt;
| Bernd Culenfeld&lt;br /&gt;
|-&lt;br /&gt;
| 2094&lt;br /&gt;
| 082E&lt;br /&gt;
| American Liquid Light&lt;br /&gt;
|-&lt;br /&gt;
| 2095&lt;br /&gt;
| 082F&lt;br /&gt;
| CEGITES&lt;br /&gt;
|-&lt;br /&gt;
| 2096&lt;br /&gt;
| 0830&lt;br /&gt;
| Quadlite Computers Ltd.&lt;br /&gt;
| Originally registered to EV Industries&lt;br /&gt;
|-&lt;br /&gt;
| 2097&lt;br /&gt;
| 0831&lt;br /&gt;
| Silicon Peace&lt;br /&gt;
|-&lt;br /&gt;
| 2098&lt;br /&gt;
| 0832&lt;br /&gt;
| Black Belt Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2099&lt;br /&gt;
| 0833&lt;br /&gt;
| Village Tronic&lt;br /&gt;
| Originally registerd to Steve Yaeger&lt;br /&gt;
|-&lt;br /&gt;
| 2100&lt;br /&gt;
| 0834&lt;br /&gt;
| ReadySoft&lt;br /&gt;
|-&lt;br /&gt;
| 2101&lt;br /&gt;
| 0835&lt;br /&gt;
| Phoenix Micro Technologies&lt;br /&gt;
|-&lt;br /&gt;
| 2102&lt;br /&gt;
| 0836&lt;br /&gt;
| Advanced Systems &amp;amp; Software&lt;br /&gt;
| Orignally assigned to Preferred Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2103&lt;br /&gt;
| 0837&lt;br /&gt;
| Rombo Productions&lt;br /&gt;
|-&lt;br /&gt;
| 2104&lt;br /&gt;
| 0838&lt;br /&gt;
| Impulse Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2105&lt;br /&gt;
| 0839&lt;br /&gt;
| Beta Unlimited&lt;br /&gt;
|-&lt;br /&gt;
| 2106&lt;br /&gt;
| 083A&lt;br /&gt;
| Memory Expansion System, Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2107&lt;br /&gt;
| 083B&lt;br /&gt;
| Vortex Computer Systems GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2108&lt;br /&gt;
| 083C&lt;br /&gt;
| Platypus Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2109&lt;br /&gt;
| 083D&lt;br /&gt;
| Gigatron OHG&lt;br /&gt;
|-&lt;br /&gt;
| 2110&lt;br /&gt;
| 083E&lt;br /&gt;
| PG Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2111&lt;br /&gt;
| 083F&lt;br /&gt;
| New Technologies Group&lt;br /&gt;
|-&lt;br /&gt;
| 2112&lt;br /&gt;
| 0840&lt;br /&gt;
| Interactive Video Systems (IVS)&lt;br /&gt;
| Pacific Peripherals&lt;br /&gt;
|-&lt;br /&gt;
| 2113&lt;br /&gt;
| 0841&lt;br /&gt;
| Vector&lt;br /&gt;
| Originally registered to H. K. Computer&lt;br /&gt;
|-&lt;br /&gt;
| 2114&lt;br /&gt;
| 0842&lt;br /&gt;
| Pacific Digital&lt;br /&gt;
| Originally registered to C. H. Helfrich Elektronik&lt;br /&gt;
|-&lt;br /&gt;
| 2115&lt;br /&gt;
| 0843&lt;br /&gt;
| Xanadu&lt;br /&gt;
|-&lt;br /&gt;
| 2116&lt;br /&gt;
| 0844&lt;br /&gt;
| Pacific Digital&lt;br /&gt;
| Originally registered to AMS&lt;br /&gt;
|-&lt;br /&gt;
| 2117&lt;br /&gt;
| 0845&lt;br /&gt;
| X-Pert&lt;br /&gt;
|-&lt;br /&gt;
| 2118&lt;br /&gt;
| 0846&lt;br /&gt;
| The Amiga Centre&lt;br /&gt;
|-&lt;br /&gt;
| 2119&lt;br /&gt;
| 0847&lt;br /&gt;
| Digital Pacific&lt;br /&gt;
|-&lt;br /&gt;
| 2120&lt;br /&gt;
| 0848&lt;br /&gt;
| Solid State Leisure&lt;br /&gt;
|-&lt;br /&gt;
| 2121&lt;br /&gt;
| 0849&lt;br /&gt;
| Hydra Systems&lt;br /&gt;
| Originally registered to Analog Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2122&lt;br /&gt;
| 084A&lt;br /&gt;
| Cumana&lt;br /&gt;
|-&lt;br /&gt;
| 2123&lt;br /&gt;
| 084B&lt;br /&gt;
| KAPS 2C Conception&lt;br /&gt;
|-&lt;br /&gt;
| 2124&lt;br /&gt;
| 084C&lt;br /&gt;
| Mike Mason&lt;br /&gt;
|-&lt;br /&gt;
| 2125&lt;br /&gt;
| 084D&lt;br /&gt;
| For Your Eyes&lt;br /&gt;
|-&lt;br /&gt;
| 2126&lt;br /&gt;
| 084E&lt;br /&gt;
| Volkmar Breitfeld Computersysteme&lt;br /&gt;
|-&lt;br /&gt;
| 2127&lt;br /&gt;
| 084F&lt;br /&gt;
| Sunrize Industries&lt;br /&gt;
|-&lt;br /&gt;
| 2128&lt;br /&gt;
| 0850&lt;br /&gt;
| Scott Advanced Micro Designs&lt;br /&gt;
|-&lt;br /&gt;
| 2129&lt;br /&gt;
| 0851&lt;br /&gt;
| Digital Micronics&lt;br /&gt;
|-&lt;br /&gt;
| 2130&lt;br /&gt;
| 0852&lt;br /&gt;
| Alfa-Laval&lt;br /&gt;
|-&lt;br /&gt;
| 2131&lt;br /&gt;
| 0853&lt;br /&gt;
| Multigros A/S&lt;br /&gt;
|-&lt;br /&gt;
| 2132&lt;br /&gt;
| 0854&lt;br /&gt;
| Archos&lt;br /&gt;
|-&lt;br /&gt;
| 2133&lt;br /&gt;
| 0855&lt;br /&gt;
| Icom Simulations&lt;br /&gt;
|-&lt;br /&gt;
| 2134&lt;br /&gt;
| 0856&lt;br /&gt;
| Commodore Test Engineering Group&lt;br /&gt;
|-&lt;br /&gt;
| 2135&lt;br /&gt;
| 0857&lt;br /&gt;
| Microcreations&lt;br /&gt;
|-&lt;br /&gt;
| 2136&lt;br /&gt;
| 0858&lt;br /&gt;
| Shoestring Productions&lt;br /&gt;
|-&lt;br /&gt;
| 2137&lt;br /&gt;
| 0859&lt;br /&gt;
| Faberushi&lt;br /&gt;
|-&lt;br /&gt;
| 2138&lt;br /&gt;
| 085A&lt;br /&gt;
| Evesham Micro Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2139&lt;br /&gt;
| 085B&lt;br /&gt;
| Panagolin Laser Software&lt;br /&gt;
|-&lt;br /&gt;
| 2140&lt;br /&gt;
| 085C&lt;br /&gt;
| Thomas Rudloff&lt;br /&gt;
|-&lt;br /&gt;
| 2141&lt;br /&gt;
| 085D&lt;br /&gt;
| Daniel Hohabir&lt;br /&gt;
|-&lt;br /&gt;
| 2142&lt;br /&gt;
| 085E&lt;br /&gt;
| GfxBase, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2143&lt;br /&gt;
| 085F&lt;br /&gt;
| Axellabs&lt;br /&gt;
|-&lt;br /&gt;
| 2144&lt;br /&gt;
| 0860&lt;br /&gt;
| Roctec Electronics Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2145&lt;br /&gt;
| 0861&lt;br /&gt;
| Omega Datentechnik&lt;br /&gt;
|-&lt;br /&gt;
| 2146&lt;br /&gt;
| 0862&lt;br /&gt;
| Atlantis&lt;br /&gt;
|-&lt;br /&gt;
| 2147&lt;br /&gt;
| 0863&lt;br /&gt;
| Skytec Computers&lt;br /&gt;
|-&lt;br /&gt;
| 2148&lt;br /&gt;
| 0864&lt;br /&gt;
| Protar Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2149&lt;br /&gt;
| 0865&lt;br /&gt;
| ACS&lt;br /&gt;
|-&lt;br /&gt;
| 2150&lt;br /&gt;
| 0866&lt;br /&gt;
| Software Results Enterprises&lt;br /&gt;
| Originally registered to University of Illinois&lt;br /&gt;
|-&lt;br /&gt;
| 2151&lt;br /&gt;
| 0867&lt;br /&gt;
| Infinity Systems Design Group&lt;br /&gt;
|-&lt;br /&gt;
| 2152&lt;br /&gt;
| 0868&lt;br /&gt;
| Trade It&lt;br /&gt;
|-&lt;br /&gt;
| 2153&lt;br /&gt;
| 0869&lt;br /&gt;
| Suntec, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2154&lt;br /&gt;
| 086A&lt;br /&gt;
| DJW Micro Systems&lt;br /&gt;
| Originally registered to Tritec Marketing&lt;br /&gt;
|-&lt;br /&gt;
| 2155&lt;br /&gt;
| 086B&lt;br /&gt;
| Power Computing Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2156&lt;br /&gt;
| 086C&lt;br /&gt;
| MacroSystems&lt;br /&gt;
|-&lt;br /&gt;
| 2157&lt;br /&gt;
| 086D&lt;br /&gt;
| Masoboshi GmbH (DCE)&lt;br /&gt;
|-&lt;br /&gt;
| 2158&lt;br /&gt;
| 086E&lt;br /&gt;
| HAL Software Hardware Handel&lt;br /&gt;
|-&lt;br /&gt;
| 2159&lt;br /&gt;
| 086F&lt;br /&gt;
| Mainhattan Data&lt;br /&gt;
| Originally registered to Michael Lamm Computersysteme&lt;br /&gt;
|-&lt;br /&gt;
| 2160&lt;br /&gt;
| 0870&lt;br /&gt;
| Digital Processing System&lt;br /&gt;
| Originally registered to bbdp Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2161&lt;br /&gt;
| 0871&lt;br /&gt;
| Blue Ribbon Soundworks&lt;br /&gt;
| Originally registered to Design Computer Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2162&lt;br /&gt;
| 0872&lt;br /&gt;
| XPert&lt;br /&gt;
| Originally registered to The Station&lt;br /&gt;
|-&lt;br /&gt;
| 2163&lt;br /&gt;
| 0873&lt;br /&gt;
| DelaComp&lt;br /&gt;
| Originally registered to Bryan Williams&lt;br /&gt;
|-&lt;br /&gt;
| 2164&lt;br /&gt;
| 0874&lt;br /&gt;
| Superformance Computer Engineering GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2165&lt;br /&gt;
| 0875&lt;br /&gt;
| Overland Engineering&lt;br /&gt;
|-&lt;br /&gt;
| 2166&lt;br /&gt;
| 0876&lt;br /&gt;
| Thomas Hamren&lt;br /&gt;
|-&lt;br /&gt;
| 2167&lt;br /&gt;
| 0877&lt;br /&gt;
| Village Tronic&lt;br /&gt;
|-&lt;br /&gt;
| 2168&lt;br /&gt;
| 0878&lt;br /&gt;
| Toolbox Design&lt;br /&gt;
|-&lt;br /&gt;
| 2169&lt;br /&gt;
| 0879&lt;br /&gt;
| Digital Processing System&lt;br /&gt;
|-&lt;br /&gt;
| 2170&lt;br /&gt;
| 087A&lt;br /&gt;
| Superformance&lt;br /&gt;
|-&lt;br /&gt;
| 2171&lt;br /&gt;
| 087B&lt;br /&gt;
| Utilities Unlimited&lt;br /&gt;
|-&lt;br /&gt;
| 2172&lt;br /&gt;
| 087C&lt;br /&gt;
| phase 5&lt;br /&gt;
|-&lt;br /&gt;
| 2173&lt;br /&gt;
| 087D&lt;br /&gt;
| Juergen Kommos&lt;br /&gt;
|-&lt;br /&gt;
| 2174&lt;br /&gt;
| 087E&lt;br /&gt;
| Electronic Design&lt;br /&gt;
|-&lt;br /&gt;
| 2175&lt;br /&gt;
| 087F&lt;br /&gt;
| James Cook University of North Queensland&lt;br /&gt;
|-&lt;br /&gt;
| 2176&lt;br /&gt;
| 0880&lt;br /&gt;
| AmiTrix Development&lt;br /&gt;
|-&lt;br /&gt;
| 2177&lt;br /&gt;
| 0881&lt;br /&gt;
| Ferranti&lt;br /&gt;
|-&lt;br /&gt;
| 2178&lt;br /&gt;
| 0882&lt;br /&gt;
| Leviathan Development&lt;br /&gt;
|-&lt;br /&gt;
| 2179&lt;br /&gt;
| 0883&lt;br /&gt;
| United Video Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2180&lt;br /&gt;
| 0884&lt;br /&gt;
| GPSoft Pty. Ltd.&lt;br /&gt;
| Originally registered to Juergen Kommos&lt;br /&gt;
|-&lt;br /&gt;
| 2181&lt;br /&gt;
| 0885&lt;br /&gt;
| ArMAX&lt;br /&gt;
| Oliver Bausch&lt;br /&gt;
|-&lt;br /&gt;
| 2182&lt;br /&gt;
| 0886&lt;br /&gt;
| CP Computer&lt;br /&gt;
|-&lt;br /&gt;
| 2183&lt;br /&gt;
| 0887&lt;br /&gt;
| AMOK - Amiga Module &amp;amp;amp; Oberon Klub&lt;br /&gt;
|-&lt;br /&gt;
| 2184&lt;br /&gt;
| 0888&lt;br /&gt;
| ITEK Neser &amp;amp;amp; Sieber GbR&lt;br /&gt;
|-&lt;br /&gt;
| 2185&lt;br /&gt;
| 0889&lt;br /&gt;
| Phillip C. Lello&lt;br /&gt;
|-&lt;br /&gt;
| 2186&lt;br /&gt;
| 088A&lt;br /&gt;
| Cyborg Design Services&lt;br /&gt;
|-&lt;br /&gt;
| 2187&lt;br /&gt;
| 088B&lt;br /&gt;
| G2 Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2188&lt;br /&gt;
| 088C&lt;br /&gt;
| Pro System Computersysteme&lt;br /&gt;
|-&lt;br /&gt;
| 2189&lt;br /&gt;
| 088D&lt;br /&gt;
| ZEUS Electronic&lt;br /&gt;
| Originally registered to MSPI (Markt &amp;amp;amp; Technik)&lt;br /&gt;
|-&lt;br /&gt;
| 2190&lt;br /&gt;
| 088E&lt;br /&gt;
| Altatech&lt;br /&gt;
|-&lt;br /&gt;
| 2191&lt;br /&gt;
| 088F&lt;br /&gt;
| NewTek&lt;br /&gt;
|-&lt;br /&gt;
| 2192&lt;br /&gt;
| 0890&lt;br /&gt;
| M-TEC Hardware Design&lt;br /&gt;
| Originally registered to Hardware Design Udo Neuroth&lt;br /&gt;
|-&lt;br /&gt;
| 2193&lt;br /&gt;
| 0891&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
| Originally registered to Viona Development&lt;br /&gt;
|-&lt;br /&gt;
| 2194&lt;br /&gt;
| 0892&lt;br /&gt;
| Amitek&lt;br /&gt;
| Originally assigned to Marpet Developments&lt;br /&gt;
|-&lt;br /&gt;
| 2195&lt;br /&gt;
| 0893&lt;br /&gt;
| Ingenieurbuero Helfrich&lt;br /&gt;
|-&lt;br /&gt;
| 2196&lt;br /&gt;
| 0894&lt;br /&gt;
| The Neo Group&lt;br /&gt;
|-&lt;br /&gt;
| 2197&lt;br /&gt;
| 0895&lt;br /&gt;
| Cyon&lt;br /&gt;
|-&lt;br /&gt;
| 2198&lt;br /&gt;
| 0896&lt;br /&gt;
| Bob Research Group&lt;br /&gt;
|-&lt;br /&gt;
| 2199&lt;br /&gt;
| 0897&lt;br /&gt;
| Richmond Sound Design Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2200&lt;br /&gt;
| 0898&lt;br /&gt;
| US Cybernetics&lt;br /&gt;
|-&lt;br /&gt;
| 2201&lt;br /&gt;
| 0899&lt;br /&gt;
| Fulvio Ieva&lt;br /&gt;
|-&lt;br /&gt;
| 2202&lt;br /&gt;
| 089A&lt;br /&gt;
| Silicon Studio&lt;br /&gt;
|-&lt;br /&gt;
| 2203&lt;br /&gt;
| 089B&lt;br /&gt;
| MacroSystems (USA)&lt;br /&gt;
| Was named Micro System Devices&lt;br /&gt;
|-&lt;br /&gt;
| 2204&lt;br /&gt;
| 089C&lt;br /&gt;
| Conspector Entertainment&lt;br /&gt;
|-&lt;br /&gt;
| 2205&lt;br /&gt;
| 089D&lt;br /&gt;
| Laserforum&lt;br /&gt;
|-&lt;br /&gt;
| 2206&lt;br /&gt;
| 089E&lt;br /&gt;
| Elbox Computer&lt;br /&gt;
| Mistakenly used by Index Information Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2207&lt;br /&gt;
| 089F&lt;br /&gt;
| Applied Magic Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2208&lt;br /&gt;
| 08A0&lt;br /&gt;
| SDL Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2560&lt;br /&gt;
| 0A00&lt;br /&gt;
| Harms&lt;br /&gt;
|-&lt;br /&gt;
| 2588&lt;br /&gt;
| 0A1C&lt;br /&gt;
| A1K.org Community&lt;br /&gt;
|-&lt;br /&gt;
| 2640&lt;br /&gt;
| 0A50&lt;br /&gt;
| Micronik&lt;br /&gt;
|-&lt;br /&gt;
| 2782&lt;br /&gt;
| 2782&lt;br /&gt;
| OA Design&lt;br /&gt;
|-&lt;br /&gt;
| 3084&lt;br /&gt;
| 0C0C&lt;br /&gt;
| Team 4&lt;br /&gt;
|-&lt;br /&gt;
| 3643&lt;br /&gt;
| 0E3B&lt;br /&gt;
| E3B&lt;br /&gt;
| Michael Boehmer&lt;br /&gt;
|-&lt;br /&gt;
| 3855&lt;br /&gt;
| 0F0F&lt;br /&gt;
| Micronik&lt;br /&gt;
|-&lt;br /&gt;
| 4096&lt;br /&gt;
| 1000&lt;br /&gt;
| MegaMicro&lt;br /&gt;
|-&lt;br /&gt;
| 4110&lt;br /&gt;
| 100E&lt;br /&gt;
| DigiFeX&lt;br /&gt;
|-&lt;br /&gt;
| 4136&lt;br /&gt;
| 1028&lt;br /&gt;
| Imtronics/Memphis&lt;br /&gt;
|-&lt;br /&gt;
| 4149&lt;br /&gt;
| 1035&lt;br /&gt;
| PROTAR&lt;br /&gt;
|-&lt;br /&gt;
| 4369&lt;br /&gt;
| 1111&lt;br /&gt;
| Frank Strauß Elektronik&lt;br /&gt;
| Also used by Kupke&lt;br /&gt;
|-&lt;br /&gt;
| 4626&lt;br /&gt;
| 1212&lt;br /&gt;
| Individual Computers&lt;br /&gt;
|-&lt;br /&gt;
| 4648&lt;br /&gt;
| 1228&lt;br /&gt;
| Flesch Hornemann Computer Elec.&lt;br /&gt;
|-&lt;br /&gt;
| 4680&lt;br /&gt;
| 1248&lt;br /&gt;
| Kupke Computertechnik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 4711&lt;br /&gt;
| 1267&lt;br /&gt;
| RBM digitaltechnik&lt;br /&gt;
|-&lt;br /&gt;
| 4754&lt;br /&gt;
| 1292&lt;br /&gt;
| MacroSystems&lt;br /&gt;
|-&lt;br /&gt;
| 5000&lt;br /&gt;
| 1388&lt;br /&gt;
| ITH&lt;br /&gt;
|-&lt;br /&gt;
| 5001&lt;br /&gt;
| 1389&lt;br /&gt;
| VMC&lt;br /&gt;
|-&lt;br /&gt;
| 5010&lt;br /&gt;
| 1392&lt;br /&gt;
| Ambience Creation Technology&lt;br /&gt;
|-&lt;br /&gt;
| 5011&lt;br /&gt;
| 1393&lt;br /&gt;
| Creative Development&lt;br /&gt;
|-&lt;br /&gt;
| 5012&lt;br /&gt;
| 1394&lt;br /&gt;
| Georg Braun&lt;br /&gt;
|-&lt;br /&gt;
| 5013&lt;br /&gt;
| 1395&lt;br /&gt;
| Swedish User Group of Amiga&lt;br /&gt;
|-&lt;br /&gt;
| 5014&lt;br /&gt;
| 1396&lt;br /&gt;
| Jakub Bednarski&lt;br /&gt;
|-&lt;br /&gt;
| 5015&lt;br /&gt;
| 1397&lt;br /&gt;
| KryoFlux, Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 5016&lt;br /&gt;
| 1398&lt;br /&gt;
| Igor Majstorovic&lt;br /&gt;
|-&lt;br /&gt;
| 5017&lt;br /&gt;
| 1399&lt;br /&gt;
| Alastair M. Robinson&lt;br /&gt;
|-&lt;br /&gt;
| 5018&lt;br /&gt;
| 139A&lt;br /&gt;
| Austex Software&lt;br /&gt;
|-&lt;br /&gt;
| 5019&lt;br /&gt;
| 139B&lt;br /&gt;
| Sören Gust&lt;br /&gt;
|-&lt;br /&gt;
| 5020&lt;br /&gt;
| 139C&lt;br /&gt;
| Rok Krajnc&lt;br /&gt;
|-&lt;br /&gt;
| 5030&lt;br /&gt;
| 13A6&lt;br /&gt;
| Tim Tashpulatov&lt;br /&gt;
|-&lt;br /&gt;
| 5040&lt;br /&gt;
| 13B0&lt;br /&gt;
| 7-bit&lt;br /&gt;
|-&lt;br /&gt;
| 5050&lt;br /&gt;
| 13BA&lt;br /&gt;
| Sakura IT&lt;br /&gt;
|-&lt;br /&gt;
| 5060&lt;br /&gt;
| 13C4&lt;br /&gt;
| FPGAArcade&lt;br /&gt;
|-&lt;br /&gt;
| 5070&lt;br /&gt;
| 13CE&lt;br /&gt;
| CancerSoft Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 5080&lt;br /&gt;
| 13D8&lt;br /&gt;
| Stephen Leary&lt;br /&gt;
|-&lt;br /&gt;
| 5090&lt;br /&gt;
| 13E2&lt;br /&gt;
| DMA Softlab LLC&lt;br /&gt;
|-&lt;br /&gt;
| 5100&lt;br /&gt;
| 13EC&lt;br /&gt;
| Brookhouse Engineering&lt;br /&gt;
|-&lt;br /&gt;
| 5110&lt;br /&gt;
| 13F6&lt;br /&gt;
| Eduardo Arana&lt;br /&gt;
|-&lt;br /&gt;
| 5120&lt;br /&gt;
| 1400&lt;br /&gt;
| CS-LAB&lt;br /&gt;
|-&lt;br /&gt;
| 5130&lt;br /&gt;
| 140A&lt;br /&gt;
| Robert Miranda&lt;br /&gt;
|-&lt;br /&gt;
| 5140&lt;br /&gt;
| 1414&lt;br /&gt;
| RastPort&lt;br /&gt;
|-&lt;br /&gt;
| 5132&lt;br /&gt;
| 140C&lt;br /&gt;
| UAS Interface Ltd6&lt;br /&gt;
|-&lt;br /&gt;
| 5150&lt;br /&gt;
| 141E&lt;br /&gt;
| Amiga Kit&lt;br /&gt;
|-&lt;br /&gt;
| 5160&lt;br /&gt;
| 1428&lt;br /&gt;
| Central Texas Commodore User Group&lt;br /&gt;
|-&lt;br /&gt;
| 5170&lt;br /&gt;
| 1432&lt;br /&gt;
| Confusion Research Center&lt;br /&gt;
|-&lt;br /&gt;
| 5180&lt;br /&gt;
| 143C&lt;br /&gt;
| Solar Soyuz Zaibatsu&lt;br /&gt;
|-&lt;br /&gt;
| 5190&lt;br /&gt;
| 1446&lt;br /&gt;
| BooBip&lt;br /&gt;
|-&lt;br /&gt;
| 5191&lt;br /&gt;
| 1447&lt;br /&gt;
| Matthias Hampel&lt;br /&gt;
|-&lt;br /&gt;
| 5192&lt;br /&gt;
| 1448&lt;br /&gt;
| dec0de Consulting Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 5193&lt;br /&gt;
| 1449&lt;br /&gt;
| Puppy Concepts&lt;br /&gt;
|-&lt;br /&gt;
| 5194&lt;br /&gt;
| 144A&lt;br /&gt;
| Open Amiga Hardware Repository&lt;br /&gt;
|-&lt;br /&gt;
| 5195&lt;br /&gt;
| 144B&lt;br /&gt;
| Double H Tech&lt;br /&gt;
|-&lt;br /&gt;
| 5196&lt;br /&gt;
| 144C&lt;br /&gt;
| Retromatik&lt;br /&gt;
|-&lt;br /&gt;
| 5500&lt;br /&gt;
| 157C&lt;br /&gt;
| Inhouse Information&lt;br /&gt;
|-&lt;br /&gt;
| 5768&lt;br /&gt;
| 1688&lt;br /&gt;
| Bio Con&lt;br /&gt;
|-&lt;br /&gt;
| 6148&lt;br /&gt;
| 1804&lt;br /&gt;
| HK-Computer&lt;br /&gt;
|-&lt;br /&gt;
| 6502&lt;br /&gt;
| 1966&lt;br /&gt;
| Cloanto&lt;br /&gt;
|-&lt;br /&gt;
| 6520&lt;br /&gt;
| 1978&lt;br /&gt;
| Oliver Gantert&lt;br /&gt;
|-&lt;br /&gt;
| 7777&lt;br /&gt;
| 1E61&lt;br /&gt;
| Rafal Gabriel Chyla&lt;br /&gt;
|-&lt;br /&gt;
| 8215&lt;br /&gt;
| 2017&lt;br /&gt;
| Vortex&lt;br /&gt;
|-&lt;br /&gt;
| 8244&lt;br /&gt;
| 2034&lt;br /&gt;
| Spirit Technology&lt;br /&gt;
|-&lt;br /&gt;
| 8290&lt;br /&gt;
| 2062&lt;br /&gt;
| Expansion Systems&lt;br /&gt;
|-&lt;br /&gt;
| 8448&lt;br /&gt;
| 2100&lt;br /&gt;
| ReadySoft&lt;br /&gt;
|-&lt;br /&gt;
| 8512&lt;br /&gt;
| 2140&lt;br /&gt;
| Phase 5 Digital Products&lt;br /&gt;
|-&lt;br /&gt;
| 8553&lt;br /&gt;
| 2169&lt;br /&gt;
| Digital Processing Systems Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 8704&lt;br /&gt;
| 2200&lt;br /&gt;
| ACT Elektronik&lt;br /&gt;
|-&lt;br /&gt;
| 8738&lt;br /&gt;
| 2222&lt;br /&gt;
| ACT Elektronik&lt;br /&gt;
|-&lt;br /&gt;
| 9512&lt;br /&gt;
| 2528&lt;br /&gt;
| Tower Technologies&lt;br /&gt;
|-&lt;br /&gt;
| 10676&lt;br /&gt;
| 29B4&lt;br /&gt;
| Electronic Design&lt;br /&gt;
|-&lt;br /&gt;
| 14195&lt;br /&gt;
| 3773&lt;br /&gt;
| Media-net-Point&lt;br /&gt;
|-&lt;br /&gt;
| 14501&lt;br /&gt;
| 38A5&lt;br /&gt;
| Petsoff, Finland&lt;br /&gt;
|-&lt;br /&gt;
| 16375&lt;br /&gt;
| 3FF7&lt;br /&gt;
| Uwe Gerlach&lt;br /&gt;
|-&lt;br /&gt;
| 16707&lt;br /&gt;
| 4143&lt;br /&gt;
| Ateo Concepts&lt;br /&gt;
|-&lt;br /&gt;
| 16708&lt;br /&gt;
| 4144&lt;br /&gt;
| ALiENDESiGN&lt;br /&gt;
|-&lt;br /&gt;
| 16945&lt;br /&gt;
| 4231&lt;br /&gt;
| A.C.T.&lt;br /&gt;
|-&lt;br /&gt;
| 17740&lt;br /&gt;
| 454C&lt;br /&gt;
| HK-Computer (ELSAT)&lt;br /&gt;
|-&lt;br /&gt;
| 18260&lt;br /&gt;
| 4754&lt;br /&gt;
| MacroSystems (Germany)&lt;br /&gt;
|-&lt;br /&gt;
| 19796&lt;br /&gt;
| 4D54&lt;br /&gt;
| Markt &amp;amp; Technik&lt;br /&gt;
|-&lt;br /&gt;
| 20480&lt;br /&gt;
| 5000&lt;br /&gt;
| François Lacombe&lt;br /&gt;
|-&lt;br /&gt;
| 22359&lt;br /&gt;
| 5757&lt;br /&gt;
| Markt &amp;amp; Technik&lt;br /&gt;
|-&lt;br /&gt;
| 26464&lt;br /&gt;
| 6760&lt;br /&gt;
| Combitec&lt;br /&gt;
|-&lt;br /&gt;
| 26470&lt;br /&gt;
| 6766&lt;br /&gt;
| Combitec&lt;br /&gt;
|-&lt;br /&gt;
| 28014&lt;br /&gt;
| 6D6E&lt;br /&gt;
| MNT Media and Technology UG&lt;br /&gt;
|-&lt;br /&gt;
| 28019&lt;br /&gt;
| 6D73&lt;br /&gt;
| Michal Schulz&lt;br /&gt;
|-&lt;br /&gt;
| 28020&lt;br /&gt;
| 6D74&lt;br /&gt;
| PiStorm&lt;br /&gt;
|-&lt;br /&gt;
| 32768&lt;br /&gt;
| 8000&lt;br /&gt;
| M.A.S.T.&lt;br /&gt;
|-&lt;br /&gt;
| 42240&lt;br /&gt;
| A500&lt;br /&gt;
| Aethreum Digital&lt;br /&gt;
|-&lt;br /&gt;
| 43437&lt;br /&gt;
| A9AD&lt;br /&gt;
| Reis-Ware&lt;br /&gt;
|-&lt;br /&gt;
| 43521&lt;br /&gt;
| AA01&lt;br /&gt;
| Cameron&lt;br /&gt;
|-&lt;br /&gt;
| 43537&lt;br /&gt;
| AA11&lt;br /&gt;
| Reis-Ware&lt;br /&gt;
|-&lt;br /&gt;
| 44359&lt;br /&gt;
| AD47&lt;br /&gt;
| Matay&lt;br /&gt;
|-&lt;br /&gt;
| 46504&lt;br /&gt;
| B5A8&lt;br /&gt;
| Phoenix&lt;br /&gt;
|-&lt;br /&gt;
| 48879&lt;br /&gt;
| BEEF&lt;br /&gt;
| Swiss Mountain Dog Products&lt;br /&gt;
|-&lt;br /&gt;
| 49160&lt;br /&gt;
| C008&lt;br /&gt;
| Combitec&lt;br /&gt;
|-&lt;br /&gt;
| 61453&lt;br /&gt;
| F00D&lt;br /&gt;
| Forefront Technologies Inc.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
For any changes/additions to this registry see [[#How_to_Obtain_a_Manufacturer_Number|How to Obtain a Manufacturer Number]]&lt;/div&gt;</summary>
		<author><name>Costel Mincea</name></author>
	</entry>
	<entry>
		<id>https://wiki.amigaos.net/w/index.php?title=Amiga_Hardware_Manufacturer_ID_Registry&amp;diff=12604</id>
		<title>Amiga Hardware Manufacturer ID Registry</title>
		<link rel="alternate" type="text/html" href="https://wiki.amigaos.net/w/index.php?title=Amiga_Hardware_Manufacturer_ID_Registry&amp;diff=12604"/>
		<updated>2026-09-08T11:12:47Z</updated>

		<summary type="html">&lt;p&gt;Costel Mincea: Added Michal Schulz (28019)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
= How to Obtain a Manufacturer Number =&lt;br /&gt;
&lt;br /&gt;
Manufacturer&#039;s numbers are assigned by the AmigaOS development team. To obtain your unique manufacturer number send a support request to [mailto:support@hyperion-entertainment.com support@hyperion-entertainment.com] including these information:&lt;br /&gt;
&lt;br /&gt;
 1. The name of the company or person which the number is assigned to&lt;br /&gt;
 &lt;br /&gt;
 2. Postal address/contact address&lt;br /&gt;
 &lt;br /&gt;
 3. Name of the contact person, with a corresponding e-mail address&lt;br /&gt;
 &lt;br /&gt;
 4. A brief description of the kind of products you want to produce&lt;br /&gt;
&lt;br /&gt;
= Your Manufacturer Number =&lt;br /&gt;
&lt;br /&gt;
Attention hardware manufacturers. If you are developing a hardware expansion product for the Classic Amiga (e.g. 500, 2000, 3000) then you will need to obtain a special manufacturer ID number from the AmigaOS development team to identify your product. This manufacturer number is used by the Amiga to link your hardware with its driver software at boot time.&lt;br /&gt;
&lt;br /&gt;
Your manufacturer number is part of the special protocol that the Amiga uses to automatically configure all expansion devices on the bus without the user having to cut jumpers or adjust dip switches. This is called auto-config.&lt;br /&gt;
&lt;br /&gt;
At start-up time, the system first polls each board in the system and assigns the board its own address space. If it is a memory board, its RAM is linked into the memory free pool. Later in the boot sequence, after DOS is initialized, the binddrivers program is run. Binddrivers will search the directory SYS:Expansion for the drivers that go with the boards.&lt;br /&gt;
&lt;br /&gt;
To do this binddrivers looks in the Tool Type field of all icon files in SYS:Expansion. If the first seven bytes of the Tool Type field are &amp;quot;PRODUCT&amp;quot;, then this is an icon file for a driver.&lt;br /&gt;
&lt;br /&gt;
Binddrivers will then attempt to match the drivers it has found with the boards that were found earlier. This is where your manufacturer number comes in.&lt;br /&gt;
&lt;br /&gt;
Your manufacturer number goes in two places. First, it is burned in hex form into the PAL which is part of ALL auto-config expansion products. Second, it appears in ASCII in the Tool Type field of the icon file for your product&#039;s driver. By matching these two numbers, the Amiga can automatically configure your board and bind it&#039;s software driver into the system as well.&lt;br /&gt;
&lt;br /&gt;
The manufacturer&#039;s number is a 16-bit ID which appears in PAL offsets $10-$17. There is also an 8-bit product number which you assign. The product number is for uniquely identifying different products from the same vendor. The product number will appear in PAL offsets $04-$07. This gives you a total of 24 bits to identify each of your products.&lt;br /&gt;
&lt;br /&gt;
These 24 bits of information in the PAL which identify your product are matched against the information in the Tool Type field of all icon files in the SYS:Expansion drawer. For example, suppose you are manufacturer #1019. You have two products, #1 and #2 which both use the same driver. The icon for your driver for these two products would have a Tool Type set to &amp;quot;PRODUCT=1019/1|1019/2&amp;quot;. This means: I am an icon for a driver that works with product number 1 or 2 from manufacturer 1019, now bind me. Spaces are not legal. Here are two other examples:&lt;br /&gt;
&lt;br /&gt;
; PRODUCT=1208/11&lt;br /&gt;
: is the Tool Type for a driver for product 11 from manufacturer number 1208.&lt;br /&gt;
&lt;br /&gt;
; PRODUCT=1017&lt;br /&gt;
: is the Tool Type for a driver for any product from manufacturer number 1017.&lt;br /&gt;
&lt;br /&gt;
For an informal explanation of the auto-configuration process, see the chapter on Software Expansion Architecture from the 2nd Annual Amiga Developer&#039;s Conference Notes (available on ADCD 2.1). For the details of timing, power, the PAL equations and PAL address specifications and the expansion library documentation, see sections 3.1 to 3.3 of the A500/A2000 Technical Reference Manual. The original auto-config spec appears in the A1000 Schematics and Expansion Specification.&lt;br /&gt;
&lt;br /&gt;
The auto-config process makes the addition of expansion products to the system very easy. All the user has to do is put the board in any slot and copy the driver from the release disk to his own SYS:Expansion drawer. Everything else is automatic. There are no jumpers or dip switches to set. Best of all, you will get a lot less support calls asking how to make your product work with the XYZ-Corp-battery-backed-clock.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
&lt;br /&gt;
Some notes on hardware manufacturer ID assignment.&lt;br /&gt;
&lt;br /&gt;
* Manufacturer ID numbers are assigned free of charge.&lt;br /&gt;
* Please provide the following information when requesting an ID:&lt;br /&gt;
*# Name of the company or person&lt;br /&gt;
*# Postal address/contact address&lt;br /&gt;
*# Name of the contact person, with a corresponding e-mail address&lt;br /&gt;
*# A brief description of the kind of products you want to produce&lt;br /&gt;
* All ID numbers smaller than 5000 must be considered unsafe because no information exists on which numbers exactly were taken during the time Commodore, Inc. disintegrated.&lt;br /&gt;
* ID numbers in the range 8192 to 18841 must be considered unsafe because some hardware developers mistook the numbers assigned to them to be given in hexadecimal format. Hence 0x2000 = 8192 and 0x4999 = 18841.&lt;br /&gt;
&lt;br /&gt;
= Example code =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
/*-----------------------------------------------*/&lt;br /&gt;
/* Here is a short program which will tell you   */&lt;br /&gt;
/* about the expansion boards configured in your */&lt;br /&gt;
/* system without you opening up the machine.    */&lt;br /&gt;
/* Code by Bill Koester of CATS                  */&lt;br /&gt;
/*-----------------------------------------------*/&lt;br /&gt;
#include &amp;lt;libraries/configvars.h&amp;gt;&lt;br /&gt;
#include &amp;lt;libraries/expansion.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
struct ExpansionBase *ExpansionBase;&lt;br /&gt;
&lt;br /&gt;
void cleanup();&lt;br /&gt;
void printdev();&lt;br /&gt;
&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
   struct ConfigDev *MyConfigDev;&lt;br /&gt;
&lt;br /&gt;
   /*----------------------------------*/&lt;br /&gt;
   /* Open the expansion library,      */&lt;br /&gt;
   /* if there is a problem then exit  */&lt;br /&gt;
   /*----------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   ExpansionBase =(struct ExpansionBase *) OpenLibrary(EXPANSIONNAME,0);&lt;br /&gt;
   if(ExpansionBase==NULL)&lt;br /&gt;
   {&lt;br /&gt;
      printf(&amp;quot;Error opening expansion library!!\n&amp;quot;);&lt;br /&gt;
      cleanup();&lt;br /&gt;
      exit(0);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   /*--------------------------------------------*/&lt;br /&gt;
   /* Use FindConfigDev to get info on the first */&lt;br /&gt;
   /* expansion board on the list maintained by  */&lt;br /&gt;
   /* Exec.  If there are no expansion boards in */&lt;br /&gt;
   /* the system then exit.                      */&lt;br /&gt;
   /*--------------------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   MyConfigDev = NULL;&lt;br /&gt;
&lt;br /&gt;
  /*--------------------------------------------------*/&lt;br /&gt;
  /* FindConfigDev(oldConfigDev,manufacturer,product) */&lt;br /&gt;
  /* oldConfigDev = NULL for the top of the list      */&lt;br /&gt;
  /* manufacturer = -1 for any manufacturer           */&lt;br /&gt;
  /* product      = -1 for any product                */&lt;br /&gt;
  /*--------------------------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   MyConfigDev = FindConfigDev(NULL,-1,-1);&lt;br /&gt;
&lt;br /&gt;
   if(MyConfigDev==NULL)&lt;br /&gt;
   {&lt;br /&gt;
      printf(&amp;quot;No Configured Devices found!!\n&amp;quot;);&lt;br /&gt;
      cleanup();&lt;br /&gt;
      exit(0);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   printdev(MyConfigDev);&lt;br /&gt;
&lt;br /&gt;
   /*-----------------------------------*/&lt;br /&gt;
   /* OK, there is at least one board,  */&lt;br /&gt;
   /* so loop and get the entire list   */&lt;br /&gt;
   /* printing as we go with printdev() */&lt;br /&gt;
   /*-----------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   while(MyConfigDev = FindConfigDev(MyConfigDev,-1,-1))&lt;br /&gt;
   {&lt;br /&gt;
      printdev(MyConfigDev);&lt;br /&gt;
   }&lt;br /&gt;
   cleanup();&lt;br /&gt;
   return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*-------------------*/&lt;br /&gt;
/* Close up shop...  */&lt;br /&gt;
/*-------------------*/&lt;br /&gt;
void cleanup()&lt;br /&gt;
{&lt;br /&gt;
   if(ExpansionBase)&lt;br /&gt;
      CloseLibrary(ExpansionBase);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*----------------------------------*/&lt;br /&gt;
/* Print out the contents of the    */&lt;br /&gt;
/* dev structure for this expansion */&lt;br /&gt;
/* product.                         */&lt;br /&gt;
/*----------------------------------*/&lt;br /&gt;
&lt;br /&gt;
void printdev(dev)&lt;br /&gt;
struct ConfigDev *dev;&lt;br /&gt;
{&lt;br /&gt;
   char buff[200];&lt;br /&gt;
&lt;br /&gt;
   printf(&amp;quot;Flags          = &amp;quot;);&lt;br /&gt;
   if(dev-&amp;gt;cd_Flags==NULL)&lt;br /&gt;
      printf(&amp;quot;NULL  &amp;quot;);&lt;br /&gt;
   if(dev-&amp;gt;cd_Flags&amp;amp;CDF_SHUTUP)&lt;br /&gt;
      printf(&amp;quot;CDF_SHUTUP  &amp;quot;);&lt;br /&gt;
   if(dev-&amp;gt;cd_Flags&amp;amp;CDF_CONFIGME)&lt;br /&gt;
      printf(&amp;quot;CDF_CONFIGME  &amp;quot;);&lt;br /&gt;
   printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
   printf(&amp;quot;Board Address  = %x\n&amp;quot;,dev-&amp;gt;cd_BoardAddr);&lt;br /&gt;
   printf(&amp;quot;Board Size     = %d bytes\n&amp;quot;,dev-&amp;gt;cd_BoardSize);&lt;br /&gt;
   printf(&amp;quot;Slot  Address  = %d\n&amp;quot;,dev-&amp;gt;cd_SlotAddr);&lt;br /&gt;
   printf(&amp;quot;Slot  Size     = %d\n&amp;quot;,dev-&amp;gt;cd_SlotSize);&lt;br /&gt;
   printf(&amp;quot;Driver code at   %x\n&amp;quot;,dev-&amp;gt;cd_Driver);&lt;br /&gt;
&lt;br /&gt;
   printf(&amp;quot;er_Type         = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Type);&lt;br /&gt;
   printf(&amp;quot;er_Product      = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Product);&lt;br /&gt;
   printf(&amp;quot;er_Flags        = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Flags);&lt;br /&gt;
   printf(&amp;quot;er_Reserved03   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved03);&lt;br /&gt;
   printf(&amp;quot;er_Manufacturer = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Manufacturer);&lt;br /&gt;
   printf(&amp;quot;er_SerialNumber = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_SerialNumber);&lt;br /&gt;
   printf(&amp;quot;er_InitDiagVec  = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_InitDiagVec);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0c   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0c);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0d   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0d);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0e   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0e);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0f   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0f);&lt;br /&gt;
&lt;br /&gt;
   printf(&amp;quot;Hit Return to continue:\n&amp;quot;);&lt;br /&gt;
   gets(buff);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Registry =&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! ID (decimal)&lt;br /&gt;
! ID (hexadecimal)&lt;br /&gt;
! Manufacturer&lt;br /&gt;
! Notes&lt;br /&gt;
|-&lt;br /&gt;
| 1&lt;br /&gt;
| 0001&lt;br /&gt;
| Micronik&lt;br /&gt;
|-&lt;br /&gt;
| 211&lt;br /&gt;
| 00D3&lt;br /&gt;
| Pacific Peripherals/Profex&lt;br /&gt;
|-&lt;br /&gt;
| 221&lt;br /&gt;
| 00DD&lt;br /&gt;
| Kupke Computertechnik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 256&lt;br /&gt;
| 0100&lt;br /&gt;
| Memphis&lt;br /&gt;
| Originally registered to MacroSystems US&lt;br /&gt;
|-&lt;br /&gt;
| 512&lt;br /&gt;
| 0200&lt;br /&gt;
| 3-State Computertechnik&lt;br /&gt;
|-&lt;br /&gt;
| 513&lt;br /&gt;
| 0201&lt;br /&gt;
| Commodore (Braunschweig)&lt;br /&gt;
|-&lt;br /&gt;
| 514&lt;br /&gt;
| 0202&lt;br /&gt;
| Commodore (West Chester)&lt;br /&gt;
|-&lt;br /&gt;
| 515&lt;br /&gt;
| 0203&lt;br /&gt;
| Commodore (West Chester)&lt;br /&gt;
| Originally registered to Combitech/Macrosystem&lt;br /&gt;
|-&lt;br /&gt;
| 756&lt;br /&gt;
| 02F4&lt;br /&gt;
| Progressive Peripherals &amp;amp; Software&lt;br /&gt;
|-&lt;br /&gt;
| 767&lt;br /&gt;
| 02FF&lt;br /&gt;
| Kolff Computer Supplies&lt;br /&gt;
|-&lt;br /&gt;
| 1001&lt;br /&gt;
| 03E9&lt;br /&gt;
| Tecmar&lt;br /&gt;
|-&lt;br /&gt;
| 1002&lt;br /&gt;
| 03EA&lt;br /&gt;
| Telesys&lt;br /&gt;
|-&lt;br /&gt;
| 1003&lt;br /&gt;
| 03EB&lt;br /&gt;
| The Micro-Forge&lt;br /&gt;
|-&lt;br /&gt;
| 1004&lt;br /&gt;
| 03EC&lt;br /&gt;
| Kronos/C Ltd.&lt;br /&gt;
| Originally registered to Card Co. (Supra)&lt;br /&gt;
|-&lt;br /&gt;
| 1005&lt;br /&gt;
| 03ED&lt;br /&gt;
| A-Squared&lt;br /&gt;
|-&lt;br /&gt;
| 1006&lt;br /&gt;
| 03EE&lt;br /&gt;
| Comspec Communications&lt;br /&gt;
|-&lt;br /&gt;
| 1007&lt;br /&gt;
| 03EF&lt;br /&gt;
| HT Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 1008&lt;br /&gt;
| 03F0&lt;br /&gt;
| RDS Software&lt;br /&gt;
|-&lt;br /&gt;
| 1009&lt;br /&gt;
| 03F1&lt;br /&gt;
| Anakin Research&lt;br /&gt;
|-&lt;br /&gt;
| 1010&lt;br /&gt;
| 03F2&lt;br /&gt;
| MicroBotics&lt;br /&gt;
|-&lt;br /&gt;
| 1011&lt;br /&gt;
| 03F3&lt;br /&gt;
| Bob Krauth&lt;br /&gt;
|-&lt;br /&gt;
| 1012&lt;br /&gt;
| 03F4&lt;br /&gt;
| Access Associates (Alegra)&lt;br /&gt;
|-&lt;br /&gt;
| 1013&lt;br /&gt;
| 03F5&lt;br /&gt;
| Mini Comp Systems Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 1014&lt;br /&gt;
| 03F6&lt;br /&gt;
| Cypress Technology&lt;br /&gt;
|-&lt;br /&gt;
| 1015&lt;br /&gt;
| 03F7&lt;br /&gt;
| Fuller Computers&lt;br /&gt;
|-&lt;br /&gt;
| 1016&lt;br /&gt;
| 03F8&lt;br /&gt;
| Galaxy Computers&lt;br /&gt;
|-&lt;br /&gt;
| 1017&lt;br /&gt;
| 03F9&lt;br /&gt;
| ADA Research&lt;br /&gt;
|-&lt;br /&gt;
| 1018&lt;br /&gt;
| 03FA&lt;br /&gt;
| Computer Service Italia&lt;br /&gt;
|-&lt;br /&gt;
| 1019&lt;br /&gt;
| 03FB&lt;br /&gt;
| Amigo&lt;br /&gt;
|-&lt;br /&gt;
| 1020&lt;br /&gt;
| 03FC&lt;br /&gt;
| Micro-Solutions Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1021&lt;br /&gt;
| 03FD&lt;br /&gt;
| Stacar International&lt;br /&gt;
|-&lt;br /&gt;
| 1022&lt;br /&gt;
| 03FE&lt;br /&gt;
| Video Precisions&lt;br /&gt;
|-&lt;br /&gt;
| 1023&lt;br /&gt;
| 03FF&lt;br /&gt;
| ASDG, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1025&lt;br /&gt;
| 0401&lt;br /&gt;
| Ing. Buero Kalawsky&lt;br /&gt;
|-&lt;br /&gt;
| 1026&lt;br /&gt;
| 0402&lt;br /&gt;
| Computer Tuning&lt;br /&gt;
|-&lt;br /&gt;
| 1027&lt;br /&gt;
| 0403&lt;br /&gt;
| Interplan Unternehmensberatung&lt;br /&gt;
|-&lt;br /&gt;
| 1028&lt;br /&gt;
| 0404&lt;br /&gt;
| Imtronics/Memphis&lt;br /&gt;
| Originally registered to Peter Ohlich&lt;br /&gt;
|-&lt;br /&gt;
| 1030&lt;br /&gt;
| 0406&lt;br /&gt;
| Commodore (Lowell University)&lt;br /&gt;
| Originally registered to Productivity Center&lt;br /&gt;
|-&lt;br /&gt;
| 1041&lt;br /&gt;
| 0411&lt;br /&gt;
| Design Labs&lt;br /&gt;
|-&lt;br /&gt;
| 1042&lt;br /&gt;
| 0412&lt;br /&gt;
| MCS&lt;br /&gt;
|-&lt;br /&gt;
| 1043&lt;br /&gt;
| 0413&lt;br /&gt;
| B. J. Freeman&lt;br /&gt;
|-&lt;br /&gt;
| 1044&lt;br /&gt;
| 0414&lt;br /&gt;
| Side Effects Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1045&lt;br /&gt;
| 0415&lt;br /&gt;
| Oklahoma Personal Comp.&lt;br /&gt;
|-&lt;br /&gt;
| 1046&lt;br /&gt;
| 0416&lt;br /&gt;
| Advanced Micro Innovations&lt;br /&gt;
|-&lt;br /&gt;
| 1047&lt;br /&gt;
| 0417&lt;br /&gt;
| Industrial Support Services&lt;br /&gt;
|-&lt;br /&gt;
| 1048&lt;br /&gt;
| 0418&lt;br /&gt;
| Technisoft&lt;br /&gt;
|-&lt;br /&gt;
| 1049&lt;br /&gt;
| 0419&lt;br /&gt;
| Prolific, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1050&lt;br /&gt;
| 041A&lt;br /&gt;
| Softeam, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1051&lt;br /&gt;
| 041B&lt;br /&gt;
| GRC Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 1052&lt;br /&gt;
| 041C&lt;br /&gt;
| David Lai&lt;br /&gt;
|-&lt;br /&gt;
| 1053&lt;br /&gt;
| 041D&lt;br /&gt;
| Ameristar Technologies&lt;br /&gt;
|-&lt;br /&gt;
| 1054&lt;br /&gt;
| 041E&lt;br /&gt;
| Cline Refrigeration&lt;br /&gt;
|-&lt;br /&gt;
| 1055&lt;br /&gt;
| 041F&lt;br /&gt;
| Cardiac Pacemakers, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1056&lt;br /&gt;
| 0420&lt;br /&gt;
| Supra Corp. (Creative Microsystems)&lt;br /&gt;
|-&lt;br /&gt;
| 1057&lt;br /&gt;
| 0421&lt;br /&gt;
| Wayne Diener&lt;br /&gt;
|-&lt;br /&gt;
| 1058&lt;br /&gt;
| 0422&lt;br /&gt;
| Computer Systems Associates (CSA)&lt;br /&gt;
|-&lt;br /&gt;
| 1059&lt;br /&gt;
| 0423&lt;br /&gt;
| Trionix, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1060&lt;br /&gt;
| 0424&lt;br /&gt;
| David Lucas&lt;br /&gt;
|-&lt;br /&gt;
| 1061&lt;br /&gt;
| 0425&lt;br /&gt;
| Analog Precision&lt;br /&gt;
| Also assigned to D &amp;amp; L Distributing&lt;br /&gt;
|-&lt;br /&gt;
| 1267&lt;br /&gt;
| 04F3&lt;br /&gt;
| RBM Digitaltechnik&lt;br /&gt;
|-&lt;br /&gt;
| 1282&lt;br /&gt;
| 0502&lt;br /&gt;
| M-TEC Hardware Design&lt;br /&gt;
|-&lt;br /&gt;
| 1337&lt;br /&gt;
| 0539&lt;br /&gt;
| Thomas Stenzel (DaFR34K)&lt;br /&gt;
|-&lt;br /&gt;
| 1576&lt;br /&gt;
| 0628&lt;br /&gt;
| Boris Križma&lt;br /&gt;
|-&lt;br /&gt;
| 1729&lt;br /&gt;
| 06C1&lt;br /&gt;
| Thomas Richter / OpenPCI-A1200 Mediator bridge&lt;br /&gt;
|-&lt;br /&gt;
| 1730&lt;br /&gt;
| 06C2&lt;br /&gt;
| Thomas Richter / OpenPCI-A4000 Mediator bridge&lt;br /&gt;
|-&lt;br /&gt;
| 1731&lt;br /&gt;
| 06C3&lt;br /&gt;
| Thomas Richter / OpenPCI-Prometheus bridge (Firestorm or original)&lt;br /&gt;
|-&lt;br /&gt;
| 1732&lt;br /&gt;
| 06C4&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved1&lt;br /&gt;
|-&lt;br /&gt;
| 1733&lt;br /&gt;
| 06C5&lt;br /&gt;
| Thomas Richter / OpenPCI-Grex bridge (both A1200 and A4000)&lt;br /&gt;
|-&lt;br /&gt;
| 1734&lt;br /&gt;
| 06C6&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved2&lt;br /&gt;
|-&lt;br /&gt;
| 1735&lt;br /&gt;
| 06C7&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved3&lt;br /&gt;
|-&lt;br /&gt;
| 1736&lt;br /&gt;
| 06C8&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved4&lt;br /&gt;
|-&lt;br /&gt;
| 1737&lt;br /&gt;
| 06C9&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved5&lt;br /&gt;
|-&lt;br /&gt;
| 1738&lt;br /&gt;
| 06CA&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved6&lt;br /&gt;
|-&lt;br /&gt;
| 1739&lt;br /&gt;
| 06CB&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved7&lt;br /&gt;
|-&lt;br /&gt;
| 1740&lt;br /&gt;
| 06CC&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved8&lt;br /&gt;
|-&lt;br /&gt;
| 1741&lt;br /&gt;
| 06CD&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved9&lt;br /&gt;
|-&lt;br /&gt;
| 1742&lt;br /&gt;
| 06CE&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved10&lt;br /&gt;
|-&lt;br /&gt;
| 1743&lt;br /&gt;
| 06CF&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved11&lt;br /&gt;
|-&lt;br /&gt;
| 1744&lt;br /&gt;
| 06D0&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved12&lt;br /&gt;
|-&lt;br /&gt;
| 1761&lt;br /&gt;
| 06E1&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
|-&lt;br /&gt;
| 1803&lt;br /&gt;
| 070B&lt;br /&gt;
| UAE Amiga Emulator&lt;br /&gt;
|-&lt;br /&gt;
| 2002&lt;br /&gt;
| 07D2&lt;br /&gt;
| Mimetics Corp.&lt;br /&gt;
|-&lt;br /&gt;
| 2003&lt;br /&gt;
| 07D3&lt;br /&gt;
| ACDA&lt;br /&gt;
|-&lt;br /&gt;
| 2004&lt;br /&gt;
| 07D4&lt;br /&gt;
| Finn R. Jacobsen&lt;br /&gt;
|-&lt;br /&gt;
| 2005&lt;br /&gt;
| 07D5&lt;br /&gt;
| Elthen Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2006&lt;br /&gt;
| 07D6&lt;br /&gt;
| Nine Tiles Computer Systems Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2007&lt;br /&gt;
| 07D7&lt;br /&gt;
| Analog Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2008&lt;br /&gt;
| 07D8&lt;br /&gt;
| Bell &amp;amp;amp; Howell&lt;br /&gt;
|-&lt;br /&gt;
| 2009&lt;br /&gt;
| 07D9&lt;br /&gt;
| Roland Kochler&lt;br /&gt;
|-&lt;br /&gt;
| 2010&lt;br /&gt;
| 07DA&lt;br /&gt;
| Byte Corp.&lt;br /&gt;
|-&lt;br /&gt;
| 2011&lt;br /&gt;
| 07DB&lt;br /&gt;
| Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 2012&lt;br /&gt;
| 07DC&lt;br /&gt;
| DKB, Inc.&lt;br /&gt;
| Previously named Michigan Software&lt;br /&gt;
|-&lt;br /&gt;
| 2013&lt;br /&gt;
| 07DD&lt;br /&gt;
| Pacific Peripherals&lt;br /&gt;
|-&lt;br /&gt;
| 2014&lt;br /&gt;
| 07DE&lt;br /&gt;
| Sysaphus Software&lt;br /&gt;
|-&lt;br /&gt;
| 2015&lt;br /&gt;
| 07DF&lt;br /&gt;
| Digitronics&lt;br /&gt;
|-&lt;br /&gt;
| 2016&lt;br /&gt;
| 07E0&lt;br /&gt;
| Akron Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2017&lt;br /&gt;
| 07E1&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
|-&lt;br /&gt;
| 2018&lt;br /&gt;
| 07E2&lt;br /&gt;
| Calmos&lt;br /&gt;
|-&lt;br /&gt;
| 2019&lt;br /&gt;
| 07E3&lt;br /&gt;
| Dover Research&lt;br /&gt;
|-&lt;br /&gt;
| 2020&lt;br /&gt;
| 07E4&lt;br /&gt;
| David Krehbiel&lt;br /&gt;
|-&lt;br /&gt;
| 2021&lt;br /&gt;
| 07E5&lt;br /&gt;
| Synergy Peripheral Systems&lt;br /&gt;
| Also known as California Access&lt;br /&gt;
|-&lt;br /&gt;
| 2022&lt;br /&gt;
| 07E6&lt;br /&gt;
| Xetec&lt;br /&gt;
|-&lt;br /&gt;
| 2023&lt;br /&gt;
| 07E7&lt;br /&gt;
| Micron Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2024&lt;br /&gt;
| 07E8&lt;br /&gt;
| CH Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2025&lt;br /&gt;
| 07E9&lt;br /&gt;
| American Liquid Light&lt;br /&gt;
|-&lt;br /&gt;
| 2026&lt;br /&gt;
| 07EA&lt;br /&gt;
| Progressive Peripherals &amp;amp;amp; Software&lt;br /&gt;
| Also used by Ateo&lt;br /&gt;
|-&lt;br /&gt;
| 2027&lt;br /&gt;
| 07EB&lt;br /&gt;
| Wicat Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2028&lt;br /&gt;
| 07EC&lt;br /&gt;
| Applied Systems &amp;amp;amp; Peripherals&lt;br /&gt;
|-&lt;br /&gt;
| 2029&lt;br /&gt;
| 07ED&lt;br /&gt;
| Delaware Valley Software&lt;br /&gt;
|-&lt;br /&gt;
| 2030&lt;br /&gt;
| 07EE&lt;br /&gt;
| Palomax&lt;br /&gt;
|-&lt;br /&gt;
| 2031&lt;br /&gt;
| 07EF&lt;br /&gt;
| Incognito Software&lt;br /&gt;
|-&lt;br /&gt;
| 2032&lt;br /&gt;
| 07F0&lt;br /&gt;
| Jadesign&lt;br /&gt;
|-&lt;br /&gt;
| 2033&lt;br /&gt;
| 07F1&lt;br /&gt;
| BVR&lt;br /&gt;
|-&lt;br /&gt;
| 2034&lt;br /&gt;
| 07F2&lt;br /&gt;
| Spirit Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2035&lt;br /&gt;
| 07F3&lt;br /&gt;
| Spirit Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2036&lt;br /&gt;
| 07F4&lt;br /&gt;
| Atronic&lt;br /&gt;
|-&lt;br /&gt;
| 2037&lt;br /&gt;
| 07F5&lt;br /&gt;
| Scott Karlin&lt;br /&gt;
|-&lt;br /&gt;
| 2038&lt;br /&gt;
| 07F6&lt;br /&gt;
| Howitch&lt;br /&gt;
|-&lt;br /&gt;
| 2039&lt;br /&gt;
| 07F7&lt;br /&gt;
| Sullivan Brothers Visual Engineers&lt;br /&gt;
|-&lt;br /&gt;
| 2040&lt;br /&gt;
| 07F8&lt;br /&gt;
| G I T&lt;br /&gt;
|-&lt;br /&gt;
| 2041&lt;br /&gt;
| 07F9&lt;br /&gt;
| Amigo Business Computers&lt;br /&gt;
|-&lt;br /&gt;
| 2042&lt;br /&gt;
| 07FA&lt;br /&gt;
| Micro E Ab&lt;br /&gt;
|-&lt;br /&gt;
| 2043&lt;br /&gt;
| 07FB&lt;br /&gt;
| Ralph Kruse&lt;br /&gt;
|-&lt;br /&gt;
| 2044&lt;br /&gt;
| 07FC&lt;br /&gt;
| Clearpoint Research&lt;br /&gt;
|-&lt;br /&gt;
| 2045&lt;br /&gt;
| 07FD&lt;br /&gt;
| Kodiak&lt;br /&gt;
|-&lt;br /&gt;
| 2046&lt;br /&gt;
| 07FE&lt;br /&gt;
| BSC&lt;br /&gt;
| Originally registered to Phoenix Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2047&lt;br /&gt;
| 07FF&lt;br /&gt;
| No Name Shown&lt;br /&gt;
|-&lt;br /&gt;
| 2048&lt;br /&gt;
| 0800&lt;br /&gt;
| Commodore Braunschweig&lt;br /&gt;
|-&lt;br /&gt;
| 2049&lt;br /&gt;
| 0801&lt;br /&gt;
| BSC&lt;br /&gt;
| Originally registered to Elaborate Bytes&lt;br /&gt;
|-&lt;br /&gt;
| 2050&lt;br /&gt;
| 0802&lt;br /&gt;
| Kronos/C Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2051&lt;br /&gt;
| 0803&lt;br /&gt;
| Spartanics&lt;br /&gt;
|-&lt;br /&gt;
| 2052&lt;br /&gt;
| 0804&lt;br /&gt;
| Jochheim Computer Tuning&lt;br /&gt;
|-&lt;br /&gt;
| 2053&lt;br /&gt;
| 0805&lt;br /&gt;
| Trans Data Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2054&lt;br /&gt;
| 0806&lt;br /&gt;
| Applied Systems &amp;amp;amp; Peripherals Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2055&lt;br /&gt;
| 0807&lt;br /&gt;
| Checkpoint Technologies&lt;br /&gt;
| Originally registered to Amiga Solutions&lt;br /&gt;
|-&lt;br /&gt;
| 2056&lt;br /&gt;
| 0808&lt;br /&gt;
| Adept Development&lt;br /&gt;
|-&lt;br /&gt;
| 2057&lt;br /&gt;
| 0809&lt;br /&gt;
| Advanced Computer Design&lt;br /&gt;
|-&lt;br /&gt;
| 2058&lt;br /&gt;
| 080A&lt;br /&gt;
| Sir Netics&lt;br /&gt;
|-&lt;br /&gt;
| 2059&lt;br /&gt;
| 080B&lt;br /&gt;
| Expert Services&lt;br /&gt;
|-&lt;br /&gt;
| 2060&lt;br /&gt;
| 080C&lt;br /&gt;
| Digital Art Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2061&lt;br /&gt;
| 080D&lt;br /&gt;
| Adept Development&lt;br /&gt;
|-&lt;br /&gt;
| 2062&lt;br /&gt;
| 080E&lt;br /&gt;
| Expansion Technologies (Expansion Systems)&lt;br /&gt;
|-&lt;br /&gt;
| 2063&lt;br /&gt;
| 080F&lt;br /&gt;
| Alphatech&lt;br /&gt;
|-&lt;br /&gt;
| 2064&lt;br /&gt;
| 0810&lt;br /&gt;
| Edotronik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2065&lt;br /&gt;
| 0811&lt;br /&gt;
| California Access/Synergy&lt;br /&gt;
| Originally registered to Logical Design Works&lt;br /&gt;
|-&lt;br /&gt;
| 2066&lt;br /&gt;
| 0812&lt;br /&gt;
| Bowden, Williams, Full &amp;amp; Assoc.&lt;br /&gt;
|-&lt;br /&gt;
| 2067&lt;br /&gt;
| 0813&lt;br /&gt;
| NES, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2068&lt;br /&gt;
| 0814&lt;br /&gt;
| Amdev&lt;br /&gt;
|-&lt;br /&gt;
| 2069&lt;br /&gt;
| 0815&lt;br /&gt;
| Big Brother Security Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2070&lt;br /&gt;
| 0816&lt;br /&gt;
| Active Circuits Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2071&lt;br /&gt;
| 0817&lt;br /&gt;
| ICD, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2072&lt;br /&gt;
| 0818&lt;br /&gt;
| Multi-Meg Electronique&lt;br /&gt;
|-&lt;br /&gt;
| 2073&lt;br /&gt;
| 0819&lt;br /&gt;
| Kupke Computertechnik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2074&lt;br /&gt;
| 081A&lt;br /&gt;
| The Checkered Ball&lt;br /&gt;
|-&lt;br /&gt;
| 2075&lt;br /&gt;
| 081B&lt;br /&gt;
| Hi Tension Computer Services Ltd. (UK)&lt;br /&gt;
|-&lt;br /&gt;
| 2076&lt;br /&gt;
| 081C&lt;br /&gt;
| Alfa Data&lt;br /&gt;
| Originally assigned to Elmtech Research, Ltd. (UK)&lt;br /&gt;
|-&lt;br /&gt;
| 2077&lt;br /&gt;
| 081D&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
| Originally registered to Clartscreen, Ltd. (UK)&lt;br /&gt;
|-&lt;br /&gt;
| 2078&lt;br /&gt;
| 081E&lt;br /&gt;
| Interworks&lt;br /&gt;
|-&lt;br /&gt;
| 2079&lt;br /&gt;
| 081F&lt;br /&gt;
| Galysh Enterprises&lt;br /&gt;
|-&lt;br /&gt;
| 2080&lt;br /&gt;
| 0820&lt;br /&gt;
| Hardital Synthesis&lt;br /&gt;
| Originally registered to Realtime Games Software Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2081&lt;br /&gt;
| 0821&lt;br /&gt;
| GBS&lt;br /&gt;
|-&lt;br /&gt;
| 2082&lt;br /&gt;
| 0822&lt;br /&gt;
| Circum Design Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2083&lt;br /&gt;
| 0823&lt;br /&gt;
| Alberta Micro Electronic Center&lt;br /&gt;
|-&lt;br /&gt;
| 2084&lt;br /&gt;
| 0824&lt;br /&gt;
| Bestech&lt;br /&gt;
|-&lt;br /&gt;
| 2085&lt;br /&gt;
| 0825&lt;br /&gt;
| Lasar Fantasy&lt;br /&gt;
|-&lt;br /&gt;
| 2086&lt;br /&gt;
| 0826&lt;br /&gt;
| Pulsar&lt;br /&gt;
|-&lt;br /&gt;
| 2087&lt;br /&gt;
| 0827&lt;br /&gt;
| Ivis&lt;br /&gt;
|-&lt;br /&gt;
| 2088&lt;br /&gt;
| 0828&lt;br /&gt;
| Applied Engineering&lt;br /&gt;
|-&lt;br /&gt;
| 2089&lt;br /&gt;
| 0829&lt;br /&gt;
| Solid-State Design &amp;amp;amp; Development&lt;br /&gt;
|-&lt;br /&gt;
| 2090&lt;br /&gt;
| 082A&lt;br /&gt;
| Vison Quest&lt;br /&gt;
|-&lt;br /&gt;
| 2091&lt;br /&gt;
| 082B&lt;br /&gt;
| Seaview Software&lt;br /&gt;
|-&lt;br /&gt;
| 2092&lt;br /&gt;
| 082C&lt;br /&gt;
| BSC&lt;br /&gt;
| Mistakenly used by ADS (Advanced Development Software)&lt;br /&gt;
|-&lt;br /&gt;
| 2093&lt;br /&gt;
| 082D&lt;br /&gt;
| Bernd Culenfeld&lt;br /&gt;
|-&lt;br /&gt;
| 2094&lt;br /&gt;
| 082E&lt;br /&gt;
| American Liquid Light&lt;br /&gt;
|-&lt;br /&gt;
| 2095&lt;br /&gt;
| 082F&lt;br /&gt;
| CEGITES&lt;br /&gt;
|-&lt;br /&gt;
| 2096&lt;br /&gt;
| 0830&lt;br /&gt;
| Quadlite Computers Ltd.&lt;br /&gt;
| Originally registered to EV Industries&lt;br /&gt;
|-&lt;br /&gt;
| 2097&lt;br /&gt;
| 0831&lt;br /&gt;
| Silicon Peace&lt;br /&gt;
|-&lt;br /&gt;
| 2098&lt;br /&gt;
| 0832&lt;br /&gt;
| Black Belt Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2099&lt;br /&gt;
| 0833&lt;br /&gt;
| Village Tronic&lt;br /&gt;
| Originally registerd to Steve Yaeger&lt;br /&gt;
|-&lt;br /&gt;
| 2100&lt;br /&gt;
| 0834&lt;br /&gt;
| ReadySoft&lt;br /&gt;
|-&lt;br /&gt;
| 2101&lt;br /&gt;
| 0835&lt;br /&gt;
| Phoenix Micro Technologies&lt;br /&gt;
|-&lt;br /&gt;
| 2102&lt;br /&gt;
| 0836&lt;br /&gt;
| Advanced Systems &amp;amp; Software&lt;br /&gt;
| Orignally assigned to Preferred Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2103&lt;br /&gt;
| 0837&lt;br /&gt;
| Rombo Productions&lt;br /&gt;
|-&lt;br /&gt;
| 2104&lt;br /&gt;
| 0838&lt;br /&gt;
| Impulse Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2105&lt;br /&gt;
| 0839&lt;br /&gt;
| Beta Unlimited&lt;br /&gt;
|-&lt;br /&gt;
| 2106&lt;br /&gt;
| 083A&lt;br /&gt;
| Memory Expansion System, Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2107&lt;br /&gt;
| 083B&lt;br /&gt;
| Vortex Computer Systems GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2108&lt;br /&gt;
| 083C&lt;br /&gt;
| Platypus Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2109&lt;br /&gt;
| 083D&lt;br /&gt;
| Gigatron OHG&lt;br /&gt;
|-&lt;br /&gt;
| 2110&lt;br /&gt;
| 083E&lt;br /&gt;
| PG Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2111&lt;br /&gt;
| 083F&lt;br /&gt;
| New Technologies Group&lt;br /&gt;
|-&lt;br /&gt;
| 2112&lt;br /&gt;
| 0840&lt;br /&gt;
| Interactive Video Systems (IVS)&lt;br /&gt;
| Pacific Peripherals&lt;br /&gt;
|-&lt;br /&gt;
| 2113&lt;br /&gt;
| 0841&lt;br /&gt;
| Vector&lt;br /&gt;
| Originally registered to H. K. Computer&lt;br /&gt;
|-&lt;br /&gt;
| 2114&lt;br /&gt;
| 0842&lt;br /&gt;
| Pacific Digital&lt;br /&gt;
| Originally registered to C. H. Helfrich Elektronik&lt;br /&gt;
|-&lt;br /&gt;
| 2115&lt;br /&gt;
| 0843&lt;br /&gt;
| Xanadu&lt;br /&gt;
|-&lt;br /&gt;
| 2116&lt;br /&gt;
| 0844&lt;br /&gt;
| Pacific Digital&lt;br /&gt;
| Originally registered to AMS&lt;br /&gt;
|-&lt;br /&gt;
| 2117&lt;br /&gt;
| 0845&lt;br /&gt;
| X-Pert&lt;br /&gt;
|-&lt;br /&gt;
| 2118&lt;br /&gt;
| 0846&lt;br /&gt;
| The Amiga Centre&lt;br /&gt;
|-&lt;br /&gt;
| 2119&lt;br /&gt;
| 0847&lt;br /&gt;
| Digital Pacific&lt;br /&gt;
|-&lt;br /&gt;
| 2120&lt;br /&gt;
| 0848&lt;br /&gt;
| Solid State Leisure&lt;br /&gt;
|-&lt;br /&gt;
| 2121&lt;br /&gt;
| 0849&lt;br /&gt;
| Hydra Systems&lt;br /&gt;
| Originally registered to Analog Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2122&lt;br /&gt;
| 084A&lt;br /&gt;
| Cumana&lt;br /&gt;
|-&lt;br /&gt;
| 2123&lt;br /&gt;
| 084B&lt;br /&gt;
| KAPS 2C Conception&lt;br /&gt;
|-&lt;br /&gt;
| 2124&lt;br /&gt;
| 084C&lt;br /&gt;
| Mike Mason&lt;br /&gt;
|-&lt;br /&gt;
| 2125&lt;br /&gt;
| 084D&lt;br /&gt;
| For Your Eyes&lt;br /&gt;
|-&lt;br /&gt;
| 2126&lt;br /&gt;
| 084E&lt;br /&gt;
| Volkmar Breitfeld Computersysteme&lt;br /&gt;
|-&lt;br /&gt;
| 2127&lt;br /&gt;
| 084F&lt;br /&gt;
| Sunrize Industries&lt;br /&gt;
|-&lt;br /&gt;
| 2128&lt;br /&gt;
| 0850&lt;br /&gt;
| Scott Advanced Micro Designs&lt;br /&gt;
|-&lt;br /&gt;
| 2129&lt;br /&gt;
| 0851&lt;br /&gt;
| Digital Micronics&lt;br /&gt;
|-&lt;br /&gt;
| 2130&lt;br /&gt;
| 0852&lt;br /&gt;
| Alfa-Laval&lt;br /&gt;
|-&lt;br /&gt;
| 2131&lt;br /&gt;
| 0853&lt;br /&gt;
| Multigros A/S&lt;br /&gt;
|-&lt;br /&gt;
| 2132&lt;br /&gt;
| 0854&lt;br /&gt;
| Archos&lt;br /&gt;
|-&lt;br /&gt;
| 2133&lt;br /&gt;
| 0855&lt;br /&gt;
| Icom Simulations&lt;br /&gt;
|-&lt;br /&gt;
| 2134&lt;br /&gt;
| 0856&lt;br /&gt;
| Commodore Test Engineering Group&lt;br /&gt;
|-&lt;br /&gt;
| 2135&lt;br /&gt;
| 0857&lt;br /&gt;
| Microcreations&lt;br /&gt;
|-&lt;br /&gt;
| 2136&lt;br /&gt;
| 0858&lt;br /&gt;
| Shoestring Productions&lt;br /&gt;
|-&lt;br /&gt;
| 2137&lt;br /&gt;
| 0859&lt;br /&gt;
| Faberushi&lt;br /&gt;
|-&lt;br /&gt;
| 2138&lt;br /&gt;
| 085A&lt;br /&gt;
| Evesham Micro Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2139&lt;br /&gt;
| 085B&lt;br /&gt;
| Panagolin Laser Software&lt;br /&gt;
|-&lt;br /&gt;
| 2140&lt;br /&gt;
| 085C&lt;br /&gt;
| Thomas Rudloff&lt;br /&gt;
|-&lt;br /&gt;
| 2141&lt;br /&gt;
| 085D&lt;br /&gt;
| Daniel Hohabir&lt;br /&gt;
|-&lt;br /&gt;
| 2142&lt;br /&gt;
| 085E&lt;br /&gt;
| GfxBase, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2143&lt;br /&gt;
| 085F&lt;br /&gt;
| Axellabs&lt;br /&gt;
|-&lt;br /&gt;
| 2144&lt;br /&gt;
| 0860&lt;br /&gt;
| Roctec Electronics Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2145&lt;br /&gt;
| 0861&lt;br /&gt;
| Omega Datentechnik&lt;br /&gt;
|-&lt;br /&gt;
| 2146&lt;br /&gt;
| 0862&lt;br /&gt;
| Atlantis&lt;br /&gt;
|-&lt;br /&gt;
| 2147&lt;br /&gt;
| 0863&lt;br /&gt;
| Skytec Computers&lt;br /&gt;
|-&lt;br /&gt;
| 2148&lt;br /&gt;
| 0864&lt;br /&gt;
| Protar Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2149&lt;br /&gt;
| 0865&lt;br /&gt;
| ACS&lt;br /&gt;
|-&lt;br /&gt;
| 2150&lt;br /&gt;
| 0866&lt;br /&gt;
| Software Results Enterprises&lt;br /&gt;
| Originally registered to University of Illinois&lt;br /&gt;
|-&lt;br /&gt;
| 2151&lt;br /&gt;
| 0867&lt;br /&gt;
| Infinity Systems Design Group&lt;br /&gt;
|-&lt;br /&gt;
| 2152&lt;br /&gt;
| 0868&lt;br /&gt;
| Trade It&lt;br /&gt;
|-&lt;br /&gt;
| 2153&lt;br /&gt;
| 0869&lt;br /&gt;
| Suntec, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2154&lt;br /&gt;
| 086A&lt;br /&gt;
| DJW Micro Systems&lt;br /&gt;
| Originally registered to Tritec Marketing&lt;br /&gt;
|-&lt;br /&gt;
| 2155&lt;br /&gt;
| 086B&lt;br /&gt;
| Power Computing Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2156&lt;br /&gt;
| 086C&lt;br /&gt;
| MacroSystems&lt;br /&gt;
|-&lt;br /&gt;
| 2157&lt;br /&gt;
| 086D&lt;br /&gt;
| Masoboshi GmbH (DCE)&lt;br /&gt;
|-&lt;br /&gt;
| 2158&lt;br /&gt;
| 086E&lt;br /&gt;
| HAL Software Hardware Handel&lt;br /&gt;
|-&lt;br /&gt;
| 2159&lt;br /&gt;
| 086F&lt;br /&gt;
| Mainhattan Data&lt;br /&gt;
| Originally registered to Michael Lamm Computersysteme&lt;br /&gt;
|-&lt;br /&gt;
| 2160&lt;br /&gt;
| 0870&lt;br /&gt;
| Digital Processing System&lt;br /&gt;
| Originally registered to bbdp Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2161&lt;br /&gt;
| 0871&lt;br /&gt;
| Blue Ribbon Soundworks&lt;br /&gt;
| Originally registered to Design Computer Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2162&lt;br /&gt;
| 0872&lt;br /&gt;
| XPert&lt;br /&gt;
| Originally registered to The Station&lt;br /&gt;
|-&lt;br /&gt;
| 2163&lt;br /&gt;
| 0873&lt;br /&gt;
| DelaComp&lt;br /&gt;
| Originally registered to Bryan Williams&lt;br /&gt;
|-&lt;br /&gt;
| 2164&lt;br /&gt;
| 0874&lt;br /&gt;
| Superformance Computer Engineering GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2165&lt;br /&gt;
| 0875&lt;br /&gt;
| Overland Engineering&lt;br /&gt;
|-&lt;br /&gt;
| 2166&lt;br /&gt;
| 0876&lt;br /&gt;
| Thomas Hamren&lt;br /&gt;
|-&lt;br /&gt;
| 2167&lt;br /&gt;
| 0877&lt;br /&gt;
| Village Tronic&lt;br /&gt;
|-&lt;br /&gt;
| 2168&lt;br /&gt;
| 0878&lt;br /&gt;
| Toolbox Design&lt;br /&gt;
|-&lt;br /&gt;
| 2169&lt;br /&gt;
| 0879&lt;br /&gt;
| Digital Processing System&lt;br /&gt;
|-&lt;br /&gt;
| 2170&lt;br /&gt;
| 087A&lt;br /&gt;
| Superformance&lt;br /&gt;
|-&lt;br /&gt;
| 2171&lt;br /&gt;
| 087B&lt;br /&gt;
| Utilities Unlimited&lt;br /&gt;
|-&lt;br /&gt;
| 2172&lt;br /&gt;
| 087C&lt;br /&gt;
| phase 5&lt;br /&gt;
|-&lt;br /&gt;
| 2173&lt;br /&gt;
| 087D&lt;br /&gt;
| Juergen Kommos&lt;br /&gt;
|-&lt;br /&gt;
| 2174&lt;br /&gt;
| 087E&lt;br /&gt;
| Electronic Design&lt;br /&gt;
|-&lt;br /&gt;
| 2175&lt;br /&gt;
| 087F&lt;br /&gt;
| James Cook University of North Queensland&lt;br /&gt;
|-&lt;br /&gt;
| 2176&lt;br /&gt;
| 0880&lt;br /&gt;
| AmiTrix Development&lt;br /&gt;
|-&lt;br /&gt;
| 2177&lt;br /&gt;
| 0881&lt;br /&gt;
| Ferranti&lt;br /&gt;
|-&lt;br /&gt;
| 2178&lt;br /&gt;
| 0882&lt;br /&gt;
| Leviathan Development&lt;br /&gt;
|-&lt;br /&gt;
| 2179&lt;br /&gt;
| 0883&lt;br /&gt;
| United Video Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2180&lt;br /&gt;
| 0884&lt;br /&gt;
| GPSoft Pty. Ltd.&lt;br /&gt;
| Originally registered to Juergen Kommos&lt;br /&gt;
|-&lt;br /&gt;
| 2181&lt;br /&gt;
| 0885&lt;br /&gt;
| ArMAX&lt;br /&gt;
| Oliver Bausch&lt;br /&gt;
|-&lt;br /&gt;
| 2182&lt;br /&gt;
| 0886&lt;br /&gt;
| CP Computer&lt;br /&gt;
|-&lt;br /&gt;
| 2183&lt;br /&gt;
| 0887&lt;br /&gt;
| AMOK - Amiga Module &amp;amp;amp; Oberon Klub&lt;br /&gt;
|-&lt;br /&gt;
| 2184&lt;br /&gt;
| 0888&lt;br /&gt;
| ITEK Neser &amp;amp;amp; Sieber GbR&lt;br /&gt;
|-&lt;br /&gt;
| 2185&lt;br /&gt;
| 0889&lt;br /&gt;
| Phillip C. Lello&lt;br /&gt;
|-&lt;br /&gt;
| 2186&lt;br /&gt;
| 088A&lt;br /&gt;
| Cyborg Design Services&lt;br /&gt;
|-&lt;br /&gt;
| 2187&lt;br /&gt;
| 088B&lt;br /&gt;
| G2 Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2188&lt;br /&gt;
| 088C&lt;br /&gt;
| Pro System Computersysteme&lt;br /&gt;
|-&lt;br /&gt;
| 2189&lt;br /&gt;
| 088D&lt;br /&gt;
| ZEUS Electronic&lt;br /&gt;
| Originally registered to MSPI (Markt &amp;amp;amp; Technik)&lt;br /&gt;
|-&lt;br /&gt;
| 2190&lt;br /&gt;
| 088E&lt;br /&gt;
| Altatech&lt;br /&gt;
|-&lt;br /&gt;
| 2191&lt;br /&gt;
| 088F&lt;br /&gt;
| NewTek&lt;br /&gt;
|-&lt;br /&gt;
| 2192&lt;br /&gt;
| 0890&lt;br /&gt;
| M-TEC Hardware Design&lt;br /&gt;
| Originally registered to Hardware Design Udo Neuroth&lt;br /&gt;
|-&lt;br /&gt;
| 2193&lt;br /&gt;
| 0891&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
| Originally registered to Viona Development&lt;br /&gt;
|-&lt;br /&gt;
| 2194&lt;br /&gt;
| 0892&lt;br /&gt;
| Amitek&lt;br /&gt;
| Originally assigned to Marpet Developments&lt;br /&gt;
|-&lt;br /&gt;
| 2195&lt;br /&gt;
| 0893&lt;br /&gt;
| Ingenieurbuero Helfrich&lt;br /&gt;
|-&lt;br /&gt;
| 2196&lt;br /&gt;
| 0894&lt;br /&gt;
| The Neo Group&lt;br /&gt;
|-&lt;br /&gt;
| 2197&lt;br /&gt;
| 0895&lt;br /&gt;
| Cyon&lt;br /&gt;
|-&lt;br /&gt;
| 2198&lt;br /&gt;
| 0896&lt;br /&gt;
| Bob Research Group&lt;br /&gt;
|-&lt;br /&gt;
| 2199&lt;br /&gt;
| 0897&lt;br /&gt;
| Richmond Sound Design Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2200&lt;br /&gt;
| 0898&lt;br /&gt;
| US Cybernetics&lt;br /&gt;
|-&lt;br /&gt;
| 2201&lt;br /&gt;
| 0899&lt;br /&gt;
| Fulvio Ieva&lt;br /&gt;
|-&lt;br /&gt;
| 2202&lt;br /&gt;
| 089A&lt;br /&gt;
| Silicon Studio&lt;br /&gt;
|-&lt;br /&gt;
| 2203&lt;br /&gt;
| 089B&lt;br /&gt;
| MacroSystems (USA)&lt;br /&gt;
| Was named Micro System Devices&lt;br /&gt;
|-&lt;br /&gt;
| 2204&lt;br /&gt;
| 089C&lt;br /&gt;
| Conspector Entertainment&lt;br /&gt;
|-&lt;br /&gt;
| 2205&lt;br /&gt;
| 089D&lt;br /&gt;
| Laserforum&lt;br /&gt;
|-&lt;br /&gt;
| 2206&lt;br /&gt;
| 089E&lt;br /&gt;
| Elbox Computer&lt;br /&gt;
| Mistakenly used by Index Information Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2207&lt;br /&gt;
| 089F&lt;br /&gt;
| Applied Magic Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2208&lt;br /&gt;
| 08A0&lt;br /&gt;
| SDL Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2560&lt;br /&gt;
| 0A00&lt;br /&gt;
| Harms&lt;br /&gt;
|-&lt;br /&gt;
| 2588&lt;br /&gt;
| 0A1C&lt;br /&gt;
| A1K.org Community&lt;br /&gt;
|-&lt;br /&gt;
| 2640&lt;br /&gt;
| 0A50&lt;br /&gt;
| Micronik&lt;br /&gt;
|-&lt;br /&gt;
| 2782&lt;br /&gt;
| 2782&lt;br /&gt;
| OA Design&lt;br /&gt;
|-&lt;br /&gt;
| 3084&lt;br /&gt;
| 0C0C&lt;br /&gt;
| Team 4&lt;br /&gt;
|-&lt;br /&gt;
| 3643&lt;br /&gt;
| 0E3B&lt;br /&gt;
| E3B&lt;br /&gt;
| Michael Boehmer&lt;br /&gt;
|-&lt;br /&gt;
| 3855&lt;br /&gt;
| 0F0F&lt;br /&gt;
| Micronik&lt;br /&gt;
|-&lt;br /&gt;
| 4096&lt;br /&gt;
| 1000&lt;br /&gt;
| MegaMicro&lt;br /&gt;
|-&lt;br /&gt;
| 4110&lt;br /&gt;
| 100E&lt;br /&gt;
| DigiFeX&lt;br /&gt;
|-&lt;br /&gt;
| 4136&lt;br /&gt;
| 1028&lt;br /&gt;
| Imtronics/Memphis&lt;br /&gt;
|-&lt;br /&gt;
| 4149&lt;br /&gt;
| 1035&lt;br /&gt;
| PROTAR&lt;br /&gt;
|-&lt;br /&gt;
| 4369&lt;br /&gt;
| 1111&lt;br /&gt;
| Frank Strauß Elektronik&lt;br /&gt;
| Also used by Kupke&lt;br /&gt;
|-&lt;br /&gt;
| 4626&lt;br /&gt;
| 1212&lt;br /&gt;
| Individual Computers&lt;br /&gt;
|-&lt;br /&gt;
| 4648&lt;br /&gt;
| 1228&lt;br /&gt;
| Flesch Hornemann Computer Elec.&lt;br /&gt;
|-&lt;br /&gt;
| 4680&lt;br /&gt;
| 1248&lt;br /&gt;
| Kupke Computertechnik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 4711&lt;br /&gt;
| 1267&lt;br /&gt;
| RBM digitaltechnik&lt;br /&gt;
|-&lt;br /&gt;
| 4754&lt;br /&gt;
| 1292&lt;br /&gt;
| MacroSystems&lt;br /&gt;
|-&lt;br /&gt;
| 5000&lt;br /&gt;
| 1388&lt;br /&gt;
| ITH&lt;br /&gt;
|-&lt;br /&gt;
| 5001&lt;br /&gt;
| 1389&lt;br /&gt;
| VMC&lt;br /&gt;
|-&lt;br /&gt;
| 5010&lt;br /&gt;
| 1392&lt;br /&gt;
| Ambience Creation Technology&lt;br /&gt;
|-&lt;br /&gt;
| 5011&lt;br /&gt;
| 1393&lt;br /&gt;
| Creative Development&lt;br /&gt;
|-&lt;br /&gt;
| 5012&lt;br /&gt;
| 1394&lt;br /&gt;
| Georg Braun&lt;br /&gt;
|-&lt;br /&gt;
| 5013&lt;br /&gt;
| 1395&lt;br /&gt;
| Swedish User Group of Amiga&lt;br /&gt;
|-&lt;br /&gt;
| 5014&lt;br /&gt;
| 1396&lt;br /&gt;
| Jakub Bednarski&lt;br /&gt;
|-&lt;br /&gt;
| 5015&lt;br /&gt;
| 1397&lt;br /&gt;
| KryoFlux, Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 5016&lt;br /&gt;
| 1398&lt;br /&gt;
| Igor Majstorovic&lt;br /&gt;
|-&lt;br /&gt;
| 5017&lt;br /&gt;
| 1399&lt;br /&gt;
| Alastair M. Robinson&lt;br /&gt;
|-&lt;br /&gt;
| 5018&lt;br /&gt;
| 139A&lt;br /&gt;
| Austex Software&lt;br /&gt;
|-&lt;br /&gt;
| 5019&lt;br /&gt;
| 139B&lt;br /&gt;
| Sören Gust&lt;br /&gt;
|-&lt;br /&gt;
| 5020&lt;br /&gt;
| 139C&lt;br /&gt;
| Rok Krajnc&lt;br /&gt;
|-&lt;br /&gt;
| 5030&lt;br /&gt;
| 13A6&lt;br /&gt;
| Tim Tashpulatov&lt;br /&gt;
|-&lt;br /&gt;
| 5040&lt;br /&gt;
| 13B0&lt;br /&gt;
| 7-bit&lt;br /&gt;
|-&lt;br /&gt;
| 5050&lt;br /&gt;
| 13BA&lt;br /&gt;
| Sakura IT&lt;br /&gt;
|-&lt;br /&gt;
| 5060&lt;br /&gt;
| 13C4&lt;br /&gt;
| FPGAArcade&lt;br /&gt;
|-&lt;br /&gt;
| 5070&lt;br /&gt;
| 13CE&lt;br /&gt;
| CancerSoft Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 5080&lt;br /&gt;
| 13D8&lt;br /&gt;
| Stephen Leary&lt;br /&gt;
|-&lt;br /&gt;
| 5090&lt;br /&gt;
| 13E2&lt;br /&gt;
| DMA Softlab LLC&lt;br /&gt;
|-&lt;br /&gt;
| 5100&lt;br /&gt;
| 13EC&lt;br /&gt;
| Brookhouse Engineering&lt;br /&gt;
|-&lt;br /&gt;
| 5110&lt;br /&gt;
| 13F6&lt;br /&gt;
| Eduardo Arana&lt;br /&gt;
|-&lt;br /&gt;
| 5120&lt;br /&gt;
| 1400&lt;br /&gt;
| CS-LAB&lt;br /&gt;
|-&lt;br /&gt;
| 5130&lt;br /&gt;
| 140A&lt;br /&gt;
| Robert Miranda&lt;br /&gt;
|-&lt;br /&gt;
| 5140&lt;br /&gt;
| 1414&lt;br /&gt;
| RastPort&lt;br /&gt;
|-&lt;br /&gt;
| 5132&lt;br /&gt;
| 140C&lt;br /&gt;
| UAS Interface Ltd6&lt;br /&gt;
|-&lt;br /&gt;
| 5150&lt;br /&gt;
| 141E&lt;br /&gt;
| Amiga Kit&lt;br /&gt;
|-&lt;br /&gt;
| 5160&lt;br /&gt;
| 1428&lt;br /&gt;
| Central Texas Commodore User Group&lt;br /&gt;
|-&lt;br /&gt;
| 5170&lt;br /&gt;
| 1432&lt;br /&gt;
| Confusion Research Center&lt;br /&gt;
|-&lt;br /&gt;
| 5180&lt;br /&gt;
| 143C&lt;br /&gt;
| Solar Soyuz Zaibatsu&lt;br /&gt;
|-&lt;br /&gt;
| 5190&lt;br /&gt;
| 1446&lt;br /&gt;
| BooBip&lt;br /&gt;
|-&lt;br /&gt;
| 5191&lt;br /&gt;
| 1447&lt;br /&gt;
| Matthias Hampel&lt;br /&gt;
|-&lt;br /&gt;
| 5192&lt;br /&gt;
| 1448&lt;br /&gt;
| dec0de Consulting Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 5193&lt;br /&gt;
| 1449&lt;br /&gt;
| Puppy Concepts&lt;br /&gt;
|-&lt;br /&gt;
| 5194&lt;br /&gt;
| 144A&lt;br /&gt;
| Open Amiga Hardware Repository&lt;br /&gt;
|-&lt;br /&gt;
| 5195&lt;br /&gt;
| 144B&lt;br /&gt;
| Double H Tech&lt;br /&gt;
|-&lt;br /&gt;
| 5196&lt;br /&gt;
| 144C&lt;br /&gt;
| Retromatik&lt;br /&gt;
|-&lt;br /&gt;
| 5500&lt;br /&gt;
| 157C&lt;br /&gt;
| Inhouse Information&lt;br /&gt;
|-&lt;br /&gt;
| 5768&lt;br /&gt;
| 1688&lt;br /&gt;
| Bio Con&lt;br /&gt;
|-&lt;br /&gt;
| 6148&lt;br /&gt;
| 1804&lt;br /&gt;
| HK-Computer&lt;br /&gt;
|-&lt;br /&gt;
| 6502&lt;br /&gt;
| 1966&lt;br /&gt;
| Cloanto&lt;br /&gt;
|-&lt;br /&gt;
| 6520&lt;br /&gt;
| 1978&lt;br /&gt;
| Oliver Gantert&lt;br /&gt;
|-&lt;br /&gt;
| 7777&lt;br /&gt;
| 1E61&lt;br /&gt;
| Rafal Gabriel Chyla&lt;br /&gt;
|-&lt;br /&gt;
| 8215&lt;br /&gt;
| 2017&lt;br /&gt;
| Vortex&lt;br /&gt;
|-&lt;br /&gt;
| 8244&lt;br /&gt;
| 2034&lt;br /&gt;
| Spirit Technology&lt;br /&gt;
|-&lt;br /&gt;
| 8290&lt;br /&gt;
| 2062&lt;br /&gt;
| Expansion Systems&lt;br /&gt;
|-&lt;br /&gt;
| 8448&lt;br /&gt;
| 2100&lt;br /&gt;
| ReadySoft&lt;br /&gt;
|-&lt;br /&gt;
| 8512&lt;br /&gt;
| 2140&lt;br /&gt;
| Phase 5 Digital Products&lt;br /&gt;
|-&lt;br /&gt;
| 8553&lt;br /&gt;
| 2169&lt;br /&gt;
| Digital Processing Systems Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 8704&lt;br /&gt;
| 2200&lt;br /&gt;
| ACT Elektronik&lt;br /&gt;
|-&lt;br /&gt;
| 8738&lt;br /&gt;
| 2222&lt;br /&gt;
| ACT Elektronik&lt;br /&gt;
|-&lt;br /&gt;
| 9512&lt;br /&gt;
| 2528&lt;br /&gt;
| Tower Technologies&lt;br /&gt;
|-&lt;br /&gt;
| 10676&lt;br /&gt;
| 29B4&lt;br /&gt;
| Electronic Design&lt;br /&gt;
|-&lt;br /&gt;
| 14195&lt;br /&gt;
| 3773&lt;br /&gt;
| Media-net-Point&lt;br /&gt;
|-&lt;br /&gt;
| 14501&lt;br /&gt;
| 38A5&lt;br /&gt;
| Petsoff, Finland&lt;br /&gt;
|-&lt;br /&gt;
| 16375&lt;br /&gt;
| 3FF7&lt;br /&gt;
| Uwe Gerlach&lt;br /&gt;
|-&lt;br /&gt;
| 16707&lt;br /&gt;
| 4143&lt;br /&gt;
| Ateo Concepts&lt;br /&gt;
|-&lt;br /&gt;
| 16708&lt;br /&gt;
| 4144&lt;br /&gt;
| ALiENDESiGN&lt;br /&gt;
|-&lt;br /&gt;
| 16945&lt;br /&gt;
| 4231&lt;br /&gt;
| A.C.T.&lt;br /&gt;
|-&lt;br /&gt;
| 17740&lt;br /&gt;
| 454C&lt;br /&gt;
| HK-Computer (ELSAT)&lt;br /&gt;
|-&lt;br /&gt;
| 18260&lt;br /&gt;
| 4754&lt;br /&gt;
| MacroSystems (Germany)&lt;br /&gt;
|-&lt;br /&gt;
| 19796&lt;br /&gt;
| 4D54&lt;br /&gt;
| Markt &amp;amp; Technik&lt;br /&gt;
|-&lt;br /&gt;
| 20480&lt;br /&gt;
| 5000&lt;br /&gt;
| François Lacombe&lt;br /&gt;
|-&lt;br /&gt;
| 22359&lt;br /&gt;
| 5757&lt;br /&gt;
| Markt &amp;amp; Technik&lt;br /&gt;
|-&lt;br /&gt;
| 26464&lt;br /&gt;
| 6760&lt;br /&gt;
| Combitec&lt;br /&gt;
|-&lt;br /&gt;
| 26470&lt;br /&gt;
| 6766&lt;br /&gt;
| Combitec&lt;br /&gt;
|-&lt;br /&gt;
| 28014&lt;br /&gt;
| 6D6E&lt;br /&gt;
| MNT Media and Technology UG&lt;br /&gt;
|-&lt;br /&gt;
| 28019&lt;br /&gt;
| 6D73&lt;br /&gt;
| Michal Schulz&lt;br /&gt;
|-&lt;br /&gt;
| 32768&lt;br /&gt;
| 8000&lt;br /&gt;
| M.A.S.T.&lt;br /&gt;
|-&lt;br /&gt;
| 42240&lt;br /&gt;
| A500&lt;br /&gt;
| Aethreum Digital&lt;br /&gt;
|-&lt;br /&gt;
| 43437&lt;br /&gt;
| A9AD&lt;br /&gt;
| Reis-Ware&lt;br /&gt;
|-&lt;br /&gt;
| 43521&lt;br /&gt;
| AA01&lt;br /&gt;
| Cameron&lt;br /&gt;
|-&lt;br /&gt;
| 43537&lt;br /&gt;
| AA11&lt;br /&gt;
| Reis-Ware&lt;br /&gt;
|-&lt;br /&gt;
| 44359&lt;br /&gt;
| AD47&lt;br /&gt;
| Matay&lt;br /&gt;
|-&lt;br /&gt;
| 46504&lt;br /&gt;
| B5A8&lt;br /&gt;
| Phoenix&lt;br /&gt;
|-&lt;br /&gt;
| 48879&lt;br /&gt;
| BEEF&lt;br /&gt;
| Swiss Mountain Dog Products&lt;br /&gt;
|-&lt;br /&gt;
| 49160&lt;br /&gt;
| C008&lt;br /&gt;
| Combitec&lt;br /&gt;
|-&lt;br /&gt;
| 61453&lt;br /&gt;
| F00D&lt;br /&gt;
| Forefront Technologies Inc.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
For any changes/additions to this registry see [[#How_to_Obtain_a_Manufacturer_Number|How to Obtain a Manufacturer Number]]&lt;/div&gt;</summary>
		<author><name>Costel Mincea</name></author>
	</entry>
	<entry>
		<id>https://wiki.amigaos.net/w/index.php?title=Amiga_Hardware_Manufacturer_ID_Registry&amp;diff=12603</id>
		<title>Amiga Hardware Manufacturer ID Registry</title>
		<link rel="alternate" type="text/html" href="https://wiki.amigaos.net/w/index.php?title=Amiga_Hardware_Manufacturer_ID_Registry&amp;diff=12603"/>
		<updated>2026-09-08T11:11:20Z</updated>

		<summary type="html">&lt;p&gt;Costel Mincea: Added François Lacombe (20480)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
= How to Obtain a Manufacturer Number =&lt;br /&gt;
&lt;br /&gt;
Manufacturer&#039;s numbers are assigned by the AmigaOS development team. To obtain your unique manufacturer number send a support request to [mailto:support@hyperion-entertainment.com support@hyperion-entertainment.com] including these information:&lt;br /&gt;
&lt;br /&gt;
 1. The name of the company or person which the number is assigned to&lt;br /&gt;
 &lt;br /&gt;
 2. Postal address/contact address&lt;br /&gt;
 &lt;br /&gt;
 3. Name of the contact person, with a corresponding e-mail address&lt;br /&gt;
 &lt;br /&gt;
 4. A brief description of the kind of products you want to produce&lt;br /&gt;
&lt;br /&gt;
= Your Manufacturer Number =&lt;br /&gt;
&lt;br /&gt;
Attention hardware manufacturers. If you are developing a hardware expansion product for the Classic Amiga (e.g. 500, 2000, 3000) then you will need to obtain a special manufacturer ID number from the AmigaOS development team to identify your product. This manufacturer number is used by the Amiga to link your hardware with its driver software at boot time.&lt;br /&gt;
&lt;br /&gt;
Your manufacturer number is part of the special protocol that the Amiga uses to automatically configure all expansion devices on the bus without the user having to cut jumpers or adjust dip switches. This is called auto-config.&lt;br /&gt;
&lt;br /&gt;
At start-up time, the system first polls each board in the system and assigns the board its own address space. If it is a memory board, its RAM is linked into the memory free pool. Later in the boot sequence, after DOS is initialized, the binddrivers program is run. Binddrivers will search the directory SYS:Expansion for the drivers that go with the boards.&lt;br /&gt;
&lt;br /&gt;
To do this binddrivers looks in the Tool Type field of all icon files in SYS:Expansion. If the first seven bytes of the Tool Type field are &amp;quot;PRODUCT&amp;quot;, then this is an icon file for a driver.&lt;br /&gt;
&lt;br /&gt;
Binddrivers will then attempt to match the drivers it has found with the boards that were found earlier. This is where your manufacturer number comes in.&lt;br /&gt;
&lt;br /&gt;
Your manufacturer number goes in two places. First, it is burned in hex form into the PAL which is part of ALL auto-config expansion products. Second, it appears in ASCII in the Tool Type field of the icon file for your product&#039;s driver. By matching these two numbers, the Amiga can automatically configure your board and bind it&#039;s software driver into the system as well.&lt;br /&gt;
&lt;br /&gt;
The manufacturer&#039;s number is a 16-bit ID which appears in PAL offsets $10-$17. There is also an 8-bit product number which you assign. The product number is for uniquely identifying different products from the same vendor. The product number will appear in PAL offsets $04-$07. This gives you a total of 24 bits to identify each of your products.&lt;br /&gt;
&lt;br /&gt;
These 24 bits of information in the PAL which identify your product are matched against the information in the Tool Type field of all icon files in the SYS:Expansion drawer. For example, suppose you are manufacturer #1019. You have two products, #1 and #2 which both use the same driver. The icon for your driver for these two products would have a Tool Type set to &amp;quot;PRODUCT=1019/1|1019/2&amp;quot;. This means: I am an icon for a driver that works with product number 1 or 2 from manufacturer 1019, now bind me. Spaces are not legal. Here are two other examples:&lt;br /&gt;
&lt;br /&gt;
; PRODUCT=1208/11&lt;br /&gt;
: is the Tool Type for a driver for product 11 from manufacturer number 1208.&lt;br /&gt;
&lt;br /&gt;
; PRODUCT=1017&lt;br /&gt;
: is the Tool Type for a driver for any product from manufacturer number 1017.&lt;br /&gt;
&lt;br /&gt;
For an informal explanation of the auto-configuration process, see the chapter on Software Expansion Architecture from the 2nd Annual Amiga Developer&#039;s Conference Notes (available on ADCD 2.1). For the details of timing, power, the PAL equations and PAL address specifications and the expansion library documentation, see sections 3.1 to 3.3 of the A500/A2000 Technical Reference Manual. The original auto-config spec appears in the A1000 Schematics and Expansion Specification.&lt;br /&gt;
&lt;br /&gt;
The auto-config process makes the addition of expansion products to the system very easy. All the user has to do is put the board in any slot and copy the driver from the release disk to his own SYS:Expansion drawer. Everything else is automatic. There are no jumpers or dip switches to set. Best of all, you will get a lot less support calls asking how to make your product work with the XYZ-Corp-battery-backed-clock.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
&lt;br /&gt;
Some notes on hardware manufacturer ID assignment.&lt;br /&gt;
&lt;br /&gt;
* Manufacturer ID numbers are assigned free of charge.&lt;br /&gt;
* Please provide the following information when requesting an ID:&lt;br /&gt;
*# Name of the company or person&lt;br /&gt;
*# Postal address/contact address&lt;br /&gt;
*# Name of the contact person, with a corresponding e-mail address&lt;br /&gt;
*# A brief description of the kind of products you want to produce&lt;br /&gt;
* All ID numbers smaller than 5000 must be considered unsafe because no information exists on which numbers exactly were taken during the time Commodore, Inc. disintegrated.&lt;br /&gt;
* ID numbers in the range 8192 to 18841 must be considered unsafe because some hardware developers mistook the numbers assigned to them to be given in hexadecimal format. Hence 0x2000 = 8192 and 0x4999 = 18841.&lt;br /&gt;
&lt;br /&gt;
= Example code =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
/*-----------------------------------------------*/&lt;br /&gt;
/* Here is a short program which will tell you   */&lt;br /&gt;
/* about the expansion boards configured in your */&lt;br /&gt;
/* system without you opening up the machine.    */&lt;br /&gt;
/* Code by Bill Koester of CATS                  */&lt;br /&gt;
/*-----------------------------------------------*/&lt;br /&gt;
#include &amp;lt;libraries/configvars.h&amp;gt;&lt;br /&gt;
#include &amp;lt;libraries/expansion.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
struct ExpansionBase *ExpansionBase;&lt;br /&gt;
&lt;br /&gt;
void cleanup();&lt;br /&gt;
void printdev();&lt;br /&gt;
&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
   struct ConfigDev *MyConfigDev;&lt;br /&gt;
&lt;br /&gt;
   /*----------------------------------*/&lt;br /&gt;
   /* Open the expansion library,      */&lt;br /&gt;
   /* if there is a problem then exit  */&lt;br /&gt;
   /*----------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   ExpansionBase =(struct ExpansionBase *) OpenLibrary(EXPANSIONNAME,0);&lt;br /&gt;
   if(ExpansionBase==NULL)&lt;br /&gt;
   {&lt;br /&gt;
      printf(&amp;quot;Error opening expansion library!!\n&amp;quot;);&lt;br /&gt;
      cleanup();&lt;br /&gt;
      exit(0);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   /*--------------------------------------------*/&lt;br /&gt;
   /* Use FindConfigDev to get info on the first */&lt;br /&gt;
   /* expansion board on the list maintained by  */&lt;br /&gt;
   /* Exec.  If there are no expansion boards in */&lt;br /&gt;
   /* the system then exit.                      */&lt;br /&gt;
   /*--------------------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   MyConfigDev = NULL;&lt;br /&gt;
&lt;br /&gt;
  /*--------------------------------------------------*/&lt;br /&gt;
  /* FindConfigDev(oldConfigDev,manufacturer,product) */&lt;br /&gt;
  /* oldConfigDev = NULL for the top of the list      */&lt;br /&gt;
  /* manufacturer = -1 for any manufacturer           */&lt;br /&gt;
  /* product      = -1 for any product                */&lt;br /&gt;
  /*--------------------------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   MyConfigDev = FindConfigDev(NULL,-1,-1);&lt;br /&gt;
&lt;br /&gt;
   if(MyConfigDev==NULL)&lt;br /&gt;
   {&lt;br /&gt;
      printf(&amp;quot;No Configured Devices found!!\n&amp;quot;);&lt;br /&gt;
      cleanup();&lt;br /&gt;
      exit(0);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   printdev(MyConfigDev);&lt;br /&gt;
&lt;br /&gt;
   /*-----------------------------------*/&lt;br /&gt;
   /* OK, there is at least one board,  */&lt;br /&gt;
   /* so loop and get the entire list   */&lt;br /&gt;
   /* printing as we go with printdev() */&lt;br /&gt;
   /*-----------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   while(MyConfigDev = FindConfigDev(MyConfigDev,-1,-1))&lt;br /&gt;
   {&lt;br /&gt;
      printdev(MyConfigDev);&lt;br /&gt;
   }&lt;br /&gt;
   cleanup();&lt;br /&gt;
   return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*-------------------*/&lt;br /&gt;
/* Close up shop...  */&lt;br /&gt;
/*-------------------*/&lt;br /&gt;
void cleanup()&lt;br /&gt;
{&lt;br /&gt;
   if(ExpansionBase)&lt;br /&gt;
      CloseLibrary(ExpansionBase);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*----------------------------------*/&lt;br /&gt;
/* Print out the contents of the    */&lt;br /&gt;
/* dev structure for this expansion */&lt;br /&gt;
/* product.                         */&lt;br /&gt;
/*----------------------------------*/&lt;br /&gt;
&lt;br /&gt;
void printdev(dev)&lt;br /&gt;
struct ConfigDev *dev;&lt;br /&gt;
{&lt;br /&gt;
   char buff[200];&lt;br /&gt;
&lt;br /&gt;
   printf(&amp;quot;Flags          = &amp;quot;);&lt;br /&gt;
   if(dev-&amp;gt;cd_Flags==NULL)&lt;br /&gt;
      printf(&amp;quot;NULL  &amp;quot;);&lt;br /&gt;
   if(dev-&amp;gt;cd_Flags&amp;amp;CDF_SHUTUP)&lt;br /&gt;
      printf(&amp;quot;CDF_SHUTUP  &amp;quot;);&lt;br /&gt;
   if(dev-&amp;gt;cd_Flags&amp;amp;CDF_CONFIGME)&lt;br /&gt;
      printf(&amp;quot;CDF_CONFIGME  &amp;quot;);&lt;br /&gt;
   printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
   printf(&amp;quot;Board Address  = %x\n&amp;quot;,dev-&amp;gt;cd_BoardAddr);&lt;br /&gt;
   printf(&amp;quot;Board Size     = %d bytes\n&amp;quot;,dev-&amp;gt;cd_BoardSize);&lt;br /&gt;
   printf(&amp;quot;Slot  Address  = %d\n&amp;quot;,dev-&amp;gt;cd_SlotAddr);&lt;br /&gt;
   printf(&amp;quot;Slot  Size     = %d\n&amp;quot;,dev-&amp;gt;cd_SlotSize);&lt;br /&gt;
   printf(&amp;quot;Driver code at   %x\n&amp;quot;,dev-&amp;gt;cd_Driver);&lt;br /&gt;
&lt;br /&gt;
   printf(&amp;quot;er_Type         = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Type);&lt;br /&gt;
   printf(&amp;quot;er_Product      = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Product);&lt;br /&gt;
   printf(&amp;quot;er_Flags        = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Flags);&lt;br /&gt;
   printf(&amp;quot;er_Reserved03   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved03);&lt;br /&gt;
   printf(&amp;quot;er_Manufacturer = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Manufacturer);&lt;br /&gt;
   printf(&amp;quot;er_SerialNumber = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_SerialNumber);&lt;br /&gt;
   printf(&amp;quot;er_InitDiagVec  = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_InitDiagVec);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0c   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0c);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0d   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0d);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0e   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0e);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0f   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0f);&lt;br /&gt;
&lt;br /&gt;
   printf(&amp;quot;Hit Return to continue:\n&amp;quot;);&lt;br /&gt;
   gets(buff);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Registry =&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! ID (decimal)&lt;br /&gt;
! ID (hexadecimal)&lt;br /&gt;
! Manufacturer&lt;br /&gt;
! Notes&lt;br /&gt;
|-&lt;br /&gt;
| 1&lt;br /&gt;
| 0001&lt;br /&gt;
| Micronik&lt;br /&gt;
|-&lt;br /&gt;
| 211&lt;br /&gt;
| 00D3&lt;br /&gt;
| Pacific Peripherals/Profex&lt;br /&gt;
|-&lt;br /&gt;
| 221&lt;br /&gt;
| 00DD&lt;br /&gt;
| Kupke Computertechnik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 256&lt;br /&gt;
| 0100&lt;br /&gt;
| Memphis&lt;br /&gt;
| Originally registered to MacroSystems US&lt;br /&gt;
|-&lt;br /&gt;
| 512&lt;br /&gt;
| 0200&lt;br /&gt;
| 3-State Computertechnik&lt;br /&gt;
|-&lt;br /&gt;
| 513&lt;br /&gt;
| 0201&lt;br /&gt;
| Commodore (Braunschweig)&lt;br /&gt;
|-&lt;br /&gt;
| 514&lt;br /&gt;
| 0202&lt;br /&gt;
| Commodore (West Chester)&lt;br /&gt;
|-&lt;br /&gt;
| 515&lt;br /&gt;
| 0203&lt;br /&gt;
| Commodore (West Chester)&lt;br /&gt;
| Originally registered to Combitech/Macrosystem&lt;br /&gt;
|-&lt;br /&gt;
| 756&lt;br /&gt;
| 02F4&lt;br /&gt;
| Progressive Peripherals &amp;amp; Software&lt;br /&gt;
|-&lt;br /&gt;
| 767&lt;br /&gt;
| 02FF&lt;br /&gt;
| Kolff Computer Supplies&lt;br /&gt;
|-&lt;br /&gt;
| 1001&lt;br /&gt;
| 03E9&lt;br /&gt;
| Tecmar&lt;br /&gt;
|-&lt;br /&gt;
| 1002&lt;br /&gt;
| 03EA&lt;br /&gt;
| Telesys&lt;br /&gt;
|-&lt;br /&gt;
| 1003&lt;br /&gt;
| 03EB&lt;br /&gt;
| The Micro-Forge&lt;br /&gt;
|-&lt;br /&gt;
| 1004&lt;br /&gt;
| 03EC&lt;br /&gt;
| Kronos/C Ltd.&lt;br /&gt;
| Originally registered to Card Co. (Supra)&lt;br /&gt;
|-&lt;br /&gt;
| 1005&lt;br /&gt;
| 03ED&lt;br /&gt;
| A-Squared&lt;br /&gt;
|-&lt;br /&gt;
| 1006&lt;br /&gt;
| 03EE&lt;br /&gt;
| Comspec Communications&lt;br /&gt;
|-&lt;br /&gt;
| 1007&lt;br /&gt;
| 03EF&lt;br /&gt;
| HT Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 1008&lt;br /&gt;
| 03F0&lt;br /&gt;
| RDS Software&lt;br /&gt;
|-&lt;br /&gt;
| 1009&lt;br /&gt;
| 03F1&lt;br /&gt;
| Anakin Research&lt;br /&gt;
|-&lt;br /&gt;
| 1010&lt;br /&gt;
| 03F2&lt;br /&gt;
| MicroBotics&lt;br /&gt;
|-&lt;br /&gt;
| 1011&lt;br /&gt;
| 03F3&lt;br /&gt;
| Bob Krauth&lt;br /&gt;
|-&lt;br /&gt;
| 1012&lt;br /&gt;
| 03F4&lt;br /&gt;
| Access Associates (Alegra)&lt;br /&gt;
|-&lt;br /&gt;
| 1013&lt;br /&gt;
| 03F5&lt;br /&gt;
| Mini Comp Systems Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 1014&lt;br /&gt;
| 03F6&lt;br /&gt;
| Cypress Technology&lt;br /&gt;
|-&lt;br /&gt;
| 1015&lt;br /&gt;
| 03F7&lt;br /&gt;
| Fuller Computers&lt;br /&gt;
|-&lt;br /&gt;
| 1016&lt;br /&gt;
| 03F8&lt;br /&gt;
| Galaxy Computers&lt;br /&gt;
|-&lt;br /&gt;
| 1017&lt;br /&gt;
| 03F9&lt;br /&gt;
| ADA Research&lt;br /&gt;
|-&lt;br /&gt;
| 1018&lt;br /&gt;
| 03FA&lt;br /&gt;
| Computer Service Italia&lt;br /&gt;
|-&lt;br /&gt;
| 1019&lt;br /&gt;
| 03FB&lt;br /&gt;
| Amigo&lt;br /&gt;
|-&lt;br /&gt;
| 1020&lt;br /&gt;
| 03FC&lt;br /&gt;
| Micro-Solutions Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1021&lt;br /&gt;
| 03FD&lt;br /&gt;
| Stacar International&lt;br /&gt;
|-&lt;br /&gt;
| 1022&lt;br /&gt;
| 03FE&lt;br /&gt;
| Video Precisions&lt;br /&gt;
|-&lt;br /&gt;
| 1023&lt;br /&gt;
| 03FF&lt;br /&gt;
| ASDG, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1025&lt;br /&gt;
| 0401&lt;br /&gt;
| Ing. Buero Kalawsky&lt;br /&gt;
|-&lt;br /&gt;
| 1026&lt;br /&gt;
| 0402&lt;br /&gt;
| Computer Tuning&lt;br /&gt;
|-&lt;br /&gt;
| 1027&lt;br /&gt;
| 0403&lt;br /&gt;
| Interplan Unternehmensberatung&lt;br /&gt;
|-&lt;br /&gt;
| 1028&lt;br /&gt;
| 0404&lt;br /&gt;
| Imtronics/Memphis&lt;br /&gt;
| Originally registered to Peter Ohlich&lt;br /&gt;
|-&lt;br /&gt;
| 1030&lt;br /&gt;
| 0406&lt;br /&gt;
| Commodore (Lowell University)&lt;br /&gt;
| Originally registered to Productivity Center&lt;br /&gt;
|-&lt;br /&gt;
| 1041&lt;br /&gt;
| 0411&lt;br /&gt;
| Design Labs&lt;br /&gt;
|-&lt;br /&gt;
| 1042&lt;br /&gt;
| 0412&lt;br /&gt;
| MCS&lt;br /&gt;
|-&lt;br /&gt;
| 1043&lt;br /&gt;
| 0413&lt;br /&gt;
| B. J. Freeman&lt;br /&gt;
|-&lt;br /&gt;
| 1044&lt;br /&gt;
| 0414&lt;br /&gt;
| Side Effects Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1045&lt;br /&gt;
| 0415&lt;br /&gt;
| Oklahoma Personal Comp.&lt;br /&gt;
|-&lt;br /&gt;
| 1046&lt;br /&gt;
| 0416&lt;br /&gt;
| Advanced Micro Innovations&lt;br /&gt;
|-&lt;br /&gt;
| 1047&lt;br /&gt;
| 0417&lt;br /&gt;
| Industrial Support Services&lt;br /&gt;
|-&lt;br /&gt;
| 1048&lt;br /&gt;
| 0418&lt;br /&gt;
| Technisoft&lt;br /&gt;
|-&lt;br /&gt;
| 1049&lt;br /&gt;
| 0419&lt;br /&gt;
| Prolific, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1050&lt;br /&gt;
| 041A&lt;br /&gt;
| Softeam, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1051&lt;br /&gt;
| 041B&lt;br /&gt;
| GRC Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 1052&lt;br /&gt;
| 041C&lt;br /&gt;
| David Lai&lt;br /&gt;
|-&lt;br /&gt;
| 1053&lt;br /&gt;
| 041D&lt;br /&gt;
| Ameristar Technologies&lt;br /&gt;
|-&lt;br /&gt;
| 1054&lt;br /&gt;
| 041E&lt;br /&gt;
| Cline Refrigeration&lt;br /&gt;
|-&lt;br /&gt;
| 1055&lt;br /&gt;
| 041F&lt;br /&gt;
| Cardiac Pacemakers, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1056&lt;br /&gt;
| 0420&lt;br /&gt;
| Supra Corp. (Creative Microsystems)&lt;br /&gt;
|-&lt;br /&gt;
| 1057&lt;br /&gt;
| 0421&lt;br /&gt;
| Wayne Diener&lt;br /&gt;
|-&lt;br /&gt;
| 1058&lt;br /&gt;
| 0422&lt;br /&gt;
| Computer Systems Associates (CSA)&lt;br /&gt;
|-&lt;br /&gt;
| 1059&lt;br /&gt;
| 0423&lt;br /&gt;
| Trionix, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1060&lt;br /&gt;
| 0424&lt;br /&gt;
| David Lucas&lt;br /&gt;
|-&lt;br /&gt;
| 1061&lt;br /&gt;
| 0425&lt;br /&gt;
| Analog Precision&lt;br /&gt;
| Also assigned to D &amp;amp; L Distributing&lt;br /&gt;
|-&lt;br /&gt;
| 1267&lt;br /&gt;
| 04F3&lt;br /&gt;
| RBM Digitaltechnik&lt;br /&gt;
|-&lt;br /&gt;
| 1282&lt;br /&gt;
| 0502&lt;br /&gt;
| M-TEC Hardware Design&lt;br /&gt;
|-&lt;br /&gt;
| 1337&lt;br /&gt;
| 0539&lt;br /&gt;
| Thomas Stenzel (DaFR34K)&lt;br /&gt;
|-&lt;br /&gt;
| 1576&lt;br /&gt;
| 0628&lt;br /&gt;
| Boris Križma&lt;br /&gt;
|-&lt;br /&gt;
| 1729&lt;br /&gt;
| 06C1&lt;br /&gt;
| Thomas Richter / OpenPCI-A1200 Mediator bridge&lt;br /&gt;
|-&lt;br /&gt;
| 1730&lt;br /&gt;
| 06C2&lt;br /&gt;
| Thomas Richter / OpenPCI-A4000 Mediator bridge&lt;br /&gt;
|-&lt;br /&gt;
| 1731&lt;br /&gt;
| 06C3&lt;br /&gt;
| Thomas Richter / OpenPCI-Prometheus bridge (Firestorm or original)&lt;br /&gt;
|-&lt;br /&gt;
| 1732&lt;br /&gt;
| 06C4&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved1&lt;br /&gt;
|-&lt;br /&gt;
| 1733&lt;br /&gt;
| 06C5&lt;br /&gt;
| Thomas Richter / OpenPCI-Grex bridge (both A1200 and A4000)&lt;br /&gt;
|-&lt;br /&gt;
| 1734&lt;br /&gt;
| 06C6&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved2&lt;br /&gt;
|-&lt;br /&gt;
| 1735&lt;br /&gt;
| 06C7&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved3&lt;br /&gt;
|-&lt;br /&gt;
| 1736&lt;br /&gt;
| 06C8&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved4&lt;br /&gt;
|-&lt;br /&gt;
| 1737&lt;br /&gt;
| 06C9&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved5&lt;br /&gt;
|-&lt;br /&gt;
| 1738&lt;br /&gt;
| 06CA&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved6&lt;br /&gt;
|-&lt;br /&gt;
| 1739&lt;br /&gt;
| 06CB&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved7&lt;br /&gt;
|-&lt;br /&gt;
| 1740&lt;br /&gt;
| 06CC&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved8&lt;br /&gt;
|-&lt;br /&gt;
| 1741&lt;br /&gt;
| 06CD&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved9&lt;br /&gt;
|-&lt;br /&gt;
| 1742&lt;br /&gt;
| 06CE&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved10&lt;br /&gt;
|-&lt;br /&gt;
| 1743&lt;br /&gt;
| 06CF&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved11&lt;br /&gt;
|-&lt;br /&gt;
| 1744&lt;br /&gt;
| 06D0&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved12&lt;br /&gt;
|-&lt;br /&gt;
| 1761&lt;br /&gt;
| 06E1&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
|-&lt;br /&gt;
| 1803&lt;br /&gt;
| 070B&lt;br /&gt;
| UAE Amiga Emulator&lt;br /&gt;
|-&lt;br /&gt;
| 2002&lt;br /&gt;
| 07D2&lt;br /&gt;
| Mimetics Corp.&lt;br /&gt;
|-&lt;br /&gt;
| 2003&lt;br /&gt;
| 07D3&lt;br /&gt;
| ACDA&lt;br /&gt;
|-&lt;br /&gt;
| 2004&lt;br /&gt;
| 07D4&lt;br /&gt;
| Finn R. Jacobsen&lt;br /&gt;
|-&lt;br /&gt;
| 2005&lt;br /&gt;
| 07D5&lt;br /&gt;
| Elthen Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2006&lt;br /&gt;
| 07D6&lt;br /&gt;
| Nine Tiles Computer Systems Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2007&lt;br /&gt;
| 07D7&lt;br /&gt;
| Analog Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2008&lt;br /&gt;
| 07D8&lt;br /&gt;
| Bell &amp;amp;amp; Howell&lt;br /&gt;
|-&lt;br /&gt;
| 2009&lt;br /&gt;
| 07D9&lt;br /&gt;
| Roland Kochler&lt;br /&gt;
|-&lt;br /&gt;
| 2010&lt;br /&gt;
| 07DA&lt;br /&gt;
| Byte Corp.&lt;br /&gt;
|-&lt;br /&gt;
| 2011&lt;br /&gt;
| 07DB&lt;br /&gt;
| Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 2012&lt;br /&gt;
| 07DC&lt;br /&gt;
| DKB, Inc.&lt;br /&gt;
| Previously named Michigan Software&lt;br /&gt;
|-&lt;br /&gt;
| 2013&lt;br /&gt;
| 07DD&lt;br /&gt;
| Pacific Peripherals&lt;br /&gt;
|-&lt;br /&gt;
| 2014&lt;br /&gt;
| 07DE&lt;br /&gt;
| Sysaphus Software&lt;br /&gt;
|-&lt;br /&gt;
| 2015&lt;br /&gt;
| 07DF&lt;br /&gt;
| Digitronics&lt;br /&gt;
|-&lt;br /&gt;
| 2016&lt;br /&gt;
| 07E0&lt;br /&gt;
| Akron Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2017&lt;br /&gt;
| 07E1&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
|-&lt;br /&gt;
| 2018&lt;br /&gt;
| 07E2&lt;br /&gt;
| Calmos&lt;br /&gt;
|-&lt;br /&gt;
| 2019&lt;br /&gt;
| 07E3&lt;br /&gt;
| Dover Research&lt;br /&gt;
|-&lt;br /&gt;
| 2020&lt;br /&gt;
| 07E4&lt;br /&gt;
| David Krehbiel&lt;br /&gt;
|-&lt;br /&gt;
| 2021&lt;br /&gt;
| 07E5&lt;br /&gt;
| Synergy Peripheral Systems&lt;br /&gt;
| Also known as California Access&lt;br /&gt;
|-&lt;br /&gt;
| 2022&lt;br /&gt;
| 07E6&lt;br /&gt;
| Xetec&lt;br /&gt;
|-&lt;br /&gt;
| 2023&lt;br /&gt;
| 07E7&lt;br /&gt;
| Micron Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2024&lt;br /&gt;
| 07E8&lt;br /&gt;
| CH Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2025&lt;br /&gt;
| 07E9&lt;br /&gt;
| American Liquid Light&lt;br /&gt;
|-&lt;br /&gt;
| 2026&lt;br /&gt;
| 07EA&lt;br /&gt;
| Progressive Peripherals &amp;amp;amp; Software&lt;br /&gt;
| Also used by Ateo&lt;br /&gt;
|-&lt;br /&gt;
| 2027&lt;br /&gt;
| 07EB&lt;br /&gt;
| Wicat Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2028&lt;br /&gt;
| 07EC&lt;br /&gt;
| Applied Systems &amp;amp;amp; Peripherals&lt;br /&gt;
|-&lt;br /&gt;
| 2029&lt;br /&gt;
| 07ED&lt;br /&gt;
| Delaware Valley Software&lt;br /&gt;
|-&lt;br /&gt;
| 2030&lt;br /&gt;
| 07EE&lt;br /&gt;
| Palomax&lt;br /&gt;
|-&lt;br /&gt;
| 2031&lt;br /&gt;
| 07EF&lt;br /&gt;
| Incognito Software&lt;br /&gt;
|-&lt;br /&gt;
| 2032&lt;br /&gt;
| 07F0&lt;br /&gt;
| Jadesign&lt;br /&gt;
|-&lt;br /&gt;
| 2033&lt;br /&gt;
| 07F1&lt;br /&gt;
| BVR&lt;br /&gt;
|-&lt;br /&gt;
| 2034&lt;br /&gt;
| 07F2&lt;br /&gt;
| Spirit Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2035&lt;br /&gt;
| 07F3&lt;br /&gt;
| Spirit Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2036&lt;br /&gt;
| 07F4&lt;br /&gt;
| Atronic&lt;br /&gt;
|-&lt;br /&gt;
| 2037&lt;br /&gt;
| 07F5&lt;br /&gt;
| Scott Karlin&lt;br /&gt;
|-&lt;br /&gt;
| 2038&lt;br /&gt;
| 07F6&lt;br /&gt;
| Howitch&lt;br /&gt;
|-&lt;br /&gt;
| 2039&lt;br /&gt;
| 07F7&lt;br /&gt;
| Sullivan Brothers Visual Engineers&lt;br /&gt;
|-&lt;br /&gt;
| 2040&lt;br /&gt;
| 07F8&lt;br /&gt;
| G I T&lt;br /&gt;
|-&lt;br /&gt;
| 2041&lt;br /&gt;
| 07F9&lt;br /&gt;
| Amigo Business Computers&lt;br /&gt;
|-&lt;br /&gt;
| 2042&lt;br /&gt;
| 07FA&lt;br /&gt;
| Micro E Ab&lt;br /&gt;
|-&lt;br /&gt;
| 2043&lt;br /&gt;
| 07FB&lt;br /&gt;
| Ralph Kruse&lt;br /&gt;
|-&lt;br /&gt;
| 2044&lt;br /&gt;
| 07FC&lt;br /&gt;
| Clearpoint Research&lt;br /&gt;
|-&lt;br /&gt;
| 2045&lt;br /&gt;
| 07FD&lt;br /&gt;
| Kodiak&lt;br /&gt;
|-&lt;br /&gt;
| 2046&lt;br /&gt;
| 07FE&lt;br /&gt;
| BSC&lt;br /&gt;
| Originally registered to Phoenix Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2047&lt;br /&gt;
| 07FF&lt;br /&gt;
| No Name Shown&lt;br /&gt;
|-&lt;br /&gt;
| 2048&lt;br /&gt;
| 0800&lt;br /&gt;
| Commodore Braunschweig&lt;br /&gt;
|-&lt;br /&gt;
| 2049&lt;br /&gt;
| 0801&lt;br /&gt;
| BSC&lt;br /&gt;
| Originally registered to Elaborate Bytes&lt;br /&gt;
|-&lt;br /&gt;
| 2050&lt;br /&gt;
| 0802&lt;br /&gt;
| Kronos/C Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2051&lt;br /&gt;
| 0803&lt;br /&gt;
| Spartanics&lt;br /&gt;
|-&lt;br /&gt;
| 2052&lt;br /&gt;
| 0804&lt;br /&gt;
| Jochheim Computer Tuning&lt;br /&gt;
|-&lt;br /&gt;
| 2053&lt;br /&gt;
| 0805&lt;br /&gt;
| Trans Data Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2054&lt;br /&gt;
| 0806&lt;br /&gt;
| Applied Systems &amp;amp;amp; Peripherals Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2055&lt;br /&gt;
| 0807&lt;br /&gt;
| Checkpoint Technologies&lt;br /&gt;
| Originally registered to Amiga Solutions&lt;br /&gt;
|-&lt;br /&gt;
| 2056&lt;br /&gt;
| 0808&lt;br /&gt;
| Adept Development&lt;br /&gt;
|-&lt;br /&gt;
| 2057&lt;br /&gt;
| 0809&lt;br /&gt;
| Advanced Computer Design&lt;br /&gt;
|-&lt;br /&gt;
| 2058&lt;br /&gt;
| 080A&lt;br /&gt;
| Sir Netics&lt;br /&gt;
|-&lt;br /&gt;
| 2059&lt;br /&gt;
| 080B&lt;br /&gt;
| Expert Services&lt;br /&gt;
|-&lt;br /&gt;
| 2060&lt;br /&gt;
| 080C&lt;br /&gt;
| Digital Art Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2061&lt;br /&gt;
| 080D&lt;br /&gt;
| Adept Development&lt;br /&gt;
|-&lt;br /&gt;
| 2062&lt;br /&gt;
| 080E&lt;br /&gt;
| Expansion Technologies (Expansion Systems)&lt;br /&gt;
|-&lt;br /&gt;
| 2063&lt;br /&gt;
| 080F&lt;br /&gt;
| Alphatech&lt;br /&gt;
|-&lt;br /&gt;
| 2064&lt;br /&gt;
| 0810&lt;br /&gt;
| Edotronik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2065&lt;br /&gt;
| 0811&lt;br /&gt;
| California Access/Synergy&lt;br /&gt;
| Originally registered to Logical Design Works&lt;br /&gt;
|-&lt;br /&gt;
| 2066&lt;br /&gt;
| 0812&lt;br /&gt;
| Bowden, Williams, Full &amp;amp; Assoc.&lt;br /&gt;
|-&lt;br /&gt;
| 2067&lt;br /&gt;
| 0813&lt;br /&gt;
| NES, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2068&lt;br /&gt;
| 0814&lt;br /&gt;
| Amdev&lt;br /&gt;
|-&lt;br /&gt;
| 2069&lt;br /&gt;
| 0815&lt;br /&gt;
| Big Brother Security Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2070&lt;br /&gt;
| 0816&lt;br /&gt;
| Active Circuits Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2071&lt;br /&gt;
| 0817&lt;br /&gt;
| ICD, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2072&lt;br /&gt;
| 0818&lt;br /&gt;
| Multi-Meg Electronique&lt;br /&gt;
|-&lt;br /&gt;
| 2073&lt;br /&gt;
| 0819&lt;br /&gt;
| Kupke Computertechnik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2074&lt;br /&gt;
| 081A&lt;br /&gt;
| The Checkered Ball&lt;br /&gt;
|-&lt;br /&gt;
| 2075&lt;br /&gt;
| 081B&lt;br /&gt;
| Hi Tension Computer Services Ltd. (UK)&lt;br /&gt;
|-&lt;br /&gt;
| 2076&lt;br /&gt;
| 081C&lt;br /&gt;
| Alfa Data&lt;br /&gt;
| Originally assigned to Elmtech Research, Ltd. (UK)&lt;br /&gt;
|-&lt;br /&gt;
| 2077&lt;br /&gt;
| 081D&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
| Originally registered to Clartscreen, Ltd. (UK)&lt;br /&gt;
|-&lt;br /&gt;
| 2078&lt;br /&gt;
| 081E&lt;br /&gt;
| Interworks&lt;br /&gt;
|-&lt;br /&gt;
| 2079&lt;br /&gt;
| 081F&lt;br /&gt;
| Galysh Enterprises&lt;br /&gt;
|-&lt;br /&gt;
| 2080&lt;br /&gt;
| 0820&lt;br /&gt;
| Hardital Synthesis&lt;br /&gt;
| Originally registered to Realtime Games Software Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2081&lt;br /&gt;
| 0821&lt;br /&gt;
| GBS&lt;br /&gt;
|-&lt;br /&gt;
| 2082&lt;br /&gt;
| 0822&lt;br /&gt;
| Circum Design Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2083&lt;br /&gt;
| 0823&lt;br /&gt;
| Alberta Micro Electronic Center&lt;br /&gt;
|-&lt;br /&gt;
| 2084&lt;br /&gt;
| 0824&lt;br /&gt;
| Bestech&lt;br /&gt;
|-&lt;br /&gt;
| 2085&lt;br /&gt;
| 0825&lt;br /&gt;
| Lasar Fantasy&lt;br /&gt;
|-&lt;br /&gt;
| 2086&lt;br /&gt;
| 0826&lt;br /&gt;
| Pulsar&lt;br /&gt;
|-&lt;br /&gt;
| 2087&lt;br /&gt;
| 0827&lt;br /&gt;
| Ivis&lt;br /&gt;
|-&lt;br /&gt;
| 2088&lt;br /&gt;
| 0828&lt;br /&gt;
| Applied Engineering&lt;br /&gt;
|-&lt;br /&gt;
| 2089&lt;br /&gt;
| 0829&lt;br /&gt;
| Solid-State Design &amp;amp;amp; Development&lt;br /&gt;
|-&lt;br /&gt;
| 2090&lt;br /&gt;
| 082A&lt;br /&gt;
| Vison Quest&lt;br /&gt;
|-&lt;br /&gt;
| 2091&lt;br /&gt;
| 082B&lt;br /&gt;
| Seaview Software&lt;br /&gt;
|-&lt;br /&gt;
| 2092&lt;br /&gt;
| 082C&lt;br /&gt;
| BSC&lt;br /&gt;
| Mistakenly used by ADS (Advanced Development Software)&lt;br /&gt;
|-&lt;br /&gt;
| 2093&lt;br /&gt;
| 082D&lt;br /&gt;
| Bernd Culenfeld&lt;br /&gt;
|-&lt;br /&gt;
| 2094&lt;br /&gt;
| 082E&lt;br /&gt;
| American Liquid Light&lt;br /&gt;
|-&lt;br /&gt;
| 2095&lt;br /&gt;
| 082F&lt;br /&gt;
| CEGITES&lt;br /&gt;
|-&lt;br /&gt;
| 2096&lt;br /&gt;
| 0830&lt;br /&gt;
| Quadlite Computers Ltd.&lt;br /&gt;
| Originally registered to EV Industries&lt;br /&gt;
|-&lt;br /&gt;
| 2097&lt;br /&gt;
| 0831&lt;br /&gt;
| Silicon Peace&lt;br /&gt;
|-&lt;br /&gt;
| 2098&lt;br /&gt;
| 0832&lt;br /&gt;
| Black Belt Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2099&lt;br /&gt;
| 0833&lt;br /&gt;
| Village Tronic&lt;br /&gt;
| Originally registerd to Steve Yaeger&lt;br /&gt;
|-&lt;br /&gt;
| 2100&lt;br /&gt;
| 0834&lt;br /&gt;
| ReadySoft&lt;br /&gt;
|-&lt;br /&gt;
| 2101&lt;br /&gt;
| 0835&lt;br /&gt;
| Phoenix Micro Technologies&lt;br /&gt;
|-&lt;br /&gt;
| 2102&lt;br /&gt;
| 0836&lt;br /&gt;
| Advanced Systems &amp;amp; Software&lt;br /&gt;
| Orignally assigned to Preferred Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2103&lt;br /&gt;
| 0837&lt;br /&gt;
| Rombo Productions&lt;br /&gt;
|-&lt;br /&gt;
| 2104&lt;br /&gt;
| 0838&lt;br /&gt;
| Impulse Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2105&lt;br /&gt;
| 0839&lt;br /&gt;
| Beta Unlimited&lt;br /&gt;
|-&lt;br /&gt;
| 2106&lt;br /&gt;
| 083A&lt;br /&gt;
| Memory Expansion System, Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2107&lt;br /&gt;
| 083B&lt;br /&gt;
| Vortex Computer Systems GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2108&lt;br /&gt;
| 083C&lt;br /&gt;
| Platypus Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2109&lt;br /&gt;
| 083D&lt;br /&gt;
| Gigatron OHG&lt;br /&gt;
|-&lt;br /&gt;
| 2110&lt;br /&gt;
| 083E&lt;br /&gt;
| PG Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2111&lt;br /&gt;
| 083F&lt;br /&gt;
| New Technologies Group&lt;br /&gt;
|-&lt;br /&gt;
| 2112&lt;br /&gt;
| 0840&lt;br /&gt;
| Interactive Video Systems (IVS)&lt;br /&gt;
| Pacific Peripherals&lt;br /&gt;
|-&lt;br /&gt;
| 2113&lt;br /&gt;
| 0841&lt;br /&gt;
| Vector&lt;br /&gt;
| Originally registered to H. K. Computer&lt;br /&gt;
|-&lt;br /&gt;
| 2114&lt;br /&gt;
| 0842&lt;br /&gt;
| Pacific Digital&lt;br /&gt;
| Originally registered to C. H. Helfrich Elektronik&lt;br /&gt;
|-&lt;br /&gt;
| 2115&lt;br /&gt;
| 0843&lt;br /&gt;
| Xanadu&lt;br /&gt;
|-&lt;br /&gt;
| 2116&lt;br /&gt;
| 0844&lt;br /&gt;
| Pacific Digital&lt;br /&gt;
| Originally registered to AMS&lt;br /&gt;
|-&lt;br /&gt;
| 2117&lt;br /&gt;
| 0845&lt;br /&gt;
| X-Pert&lt;br /&gt;
|-&lt;br /&gt;
| 2118&lt;br /&gt;
| 0846&lt;br /&gt;
| The Amiga Centre&lt;br /&gt;
|-&lt;br /&gt;
| 2119&lt;br /&gt;
| 0847&lt;br /&gt;
| Digital Pacific&lt;br /&gt;
|-&lt;br /&gt;
| 2120&lt;br /&gt;
| 0848&lt;br /&gt;
| Solid State Leisure&lt;br /&gt;
|-&lt;br /&gt;
| 2121&lt;br /&gt;
| 0849&lt;br /&gt;
| Hydra Systems&lt;br /&gt;
| Originally registered to Analog Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2122&lt;br /&gt;
| 084A&lt;br /&gt;
| Cumana&lt;br /&gt;
|-&lt;br /&gt;
| 2123&lt;br /&gt;
| 084B&lt;br /&gt;
| KAPS 2C Conception&lt;br /&gt;
|-&lt;br /&gt;
| 2124&lt;br /&gt;
| 084C&lt;br /&gt;
| Mike Mason&lt;br /&gt;
|-&lt;br /&gt;
| 2125&lt;br /&gt;
| 084D&lt;br /&gt;
| For Your Eyes&lt;br /&gt;
|-&lt;br /&gt;
| 2126&lt;br /&gt;
| 084E&lt;br /&gt;
| Volkmar Breitfeld Computersysteme&lt;br /&gt;
|-&lt;br /&gt;
| 2127&lt;br /&gt;
| 084F&lt;br /&gt;
| Sunrize Industries&lt;br /&gt;
|-&lt;br /&gt;
| 2128&lt;br /&gt;
| 0850&lt;br /&gt;
| Scott Advanced Micro Designs&lt;br /&gt;
|-&lt;br /&gt;
| 2129&lt;br /&gt;
| 0851&lt;br /&gt;
| Digital Micronics&lt;br /&gt;
|-&lt;br /&gt;
| 2130&lt;br /&gt;
| 0852&lt;br /&gt;
| Alfa-Laval&lt;br /&gt;
|-&lt;br /&gt;
| 2131&lt;br /&gt;
| 0853&lt;br /&gt;
| Multigros A/S&lt;br /&gt;
|-&lt;br /&gt;
| 2132&lt;br /&gt;
| 0854&lt;br /&gt;
| Archos&lt;br /&gt;
|-&lt;br /&gt;
| 2133&lt;br /&gt;
| 0855&lt;br /&gt;
| Icom Simulations&lt;br /&gt;
|-&lt;br /&gt;
| 2134&lt;br /&gt;
| 0856&lt;br /&gt;
| Commodore Test Engineering Group&lt;br /&gt;
|-&lt;br /&gt;
| 2135&lt;br /&gt;
| 0857&lt;br /&gt;
| Microcreations&lt;br /&gt;
|-&lt;br /&gt;
| 2136&lt;br /&gt;
| 0858&lt;br /&gt;
| Shoestring Productions&lt;br /&gt;
|-&lt;br /&gt;
| 2137&lt;br /&gt;
| 0859&lt;br /&gt;
| Faberushi&lt;br /&gt;
|-&lt;br /&gt;
| 2138&lt;br /&gt;
| 085A&lt;br /&gt;
| Evesham Micro Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2139&lt;br /&gt;
| 085B&lt;br /&gt;
| Panagolin Laser Software&lt;br /&gt;
|-&lt;br /&gt;
| 2140&lt;br /&gt;
| 085C&lt;br /&gt;
| Thomas Rudloff&lt;br /&gt;
|-&lt;br /&gt;
| 2141&lt;br /&gt;
| 085D&lt;br /&gt;
| Daniel Hohabir&lt;br /&gt;
|-&lt;br /&gt;
| 2142&lt;br /&gt;
| 085E&lt;br /&gt;
| GfxBase, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2143&lt;br /&gt;
| 085F&lt;br /&gt;
| Axellabs&lt;br /&gt;
|-&lt;br /&gt;
| 2144&lt;br /&gt;
| 0860&lt;br /&gt;
| Roctec Electronics Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2145&lt;br /&gt;
| 0861&lt;br /&gt;
| Omega Datentechnik&lt;br /&gt;
|-&lt;br /&gt;
| 2146&lt;br /&gt;
| 0862&lt;br /&gt;
| Atlantis&lt;br /&gt;
|-&lt;br /&gt;
| 2147&lt;br /&gt;
| 0863&lt;br /&gt;
| Skytec Computers&lt;br /&gt;
|-&lt;br /&gt;
| 2148&lt;br /&gt;
| 0864&lt;br /&gt;
| Protar Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2149&lt;br /&gt;
| 0865&lt;br /&gt;
| ACS&lt;br /&gt;
|-&lt;br /&gt;
| 2150&lt;br /&gt;
| 0866&lt;br /&gt;
| Software Results Enterprises&lt;br /&gt;
| Originally registered to University of Illinois&lt;br /&gt;
|-&lt;br /&gt;
| 2151&lt;br /&gt;
| 0867&lt;br /&gt;
| Infinity Systems Design Group&lt;br /&gt;
|-&lt;br /&gt;
| 2152&lt;br /&gt;
| 0868&lt;br /&gt;
| Trade It&lt;br /&gt;
|-&lt;br /&gt;
| 2153&lt;br /&gt;
| 0869&lt;br /&gt;
| Suntec, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2154&lt;br /&gt;
| 086A&lt;br /&gt;
| DJW Micro Systems&lt;br /&gt;
| Originally registered to Tritec Marketing&lt;br /&gt;
|-&lt;br /&gt;
| 2155&lt;br /&gt;
| 086B&lt;br /&gt;
| Power Computing Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2156&lt;br /&gt;
| 086C&lt;br /&gt;
| MacroSystems&lt;br /&gt;
|-&lt;br /&gt;
| 2157&lt;br /&gt;
| 086D&lt;br /&gt;
| Masoboshi GmbH (DCE)&lt;br /&gt;
|-&lt;br /&gt;
| 2158&lt;br /&gt;
| 086E&lt;br /&gt;
| HAL Software Hardware Handel&lt;br /&gt;
|-&lt;br /&gt;
| 2159&lt;br /&gt;
| 086F&lt;br /&gt;
| Mainhattan Data&lt;br /&gt;
| Originally registered to Michael Lamm Computersysteme&lt;br /&gt;
|-&lt;br /&gt;
| 2160&lt;br /&gt;
| 0870&lt;br /&gt;
| Digital Processing System&lt;br /&gt;
| Originally registered to bbdp Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2161&lt;br /&gt;
| 0871&lt;br /&gt;
| Blue Ribbon Soundworks&lt;br /&gt;
| Originally registered to Design Computer Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2162&lt;br /&gt;
| 0872&lt;br /&gt;
| XPert&lt;br /&gt;
| Originally registered to The Station&lt;br /&gt;
|-&lt;br /&gt;
| 2163&lt;br /&gt;
| 0873&lt;br /&gt;
| DelaComp&lt;br /&gt;
| Originally registered to Bryan Williams&lt;br /&gt;
|-&lt;br /&gt;
| 2164&lt;br /&gt;
| 0874&lt;br /&gt;
| Superformance Computer Engineering GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2165&lt;br /&gt;
| 0875&lt;br /&gt;
| Overland Engineering&lt;br /&gt;
|-&lt;br /&gt;
| 2166&lt;br /&gt;
| 0876&lt;br /&gt;
| Thomas Hamren&lt;br /&gt;
|-&lt;br /&gt;
| 2167&lt;br /&gt;
| 0877&lt;br /&gt;
| Village Tronic&lt;br /&gt;
|-&lt;br /&gt;
| 2168&lt;br /&gt;
| 0878&lt;br /&gt;
| Toolbox Design&lt;br /&gt;
|-&lt;br /&gt;
| 2169&lt;br /&gt;
| 0879&lt;br /&gt;
| Digital Processing System&lt;br /&gt;
|-&lt;br /&gt;
| 2170&lt;br /&gt;
| 087A&lt;br /&gt;
| Superformance&lt;br /&gt;
|-&lt;br /&gt;
| 2171&lt;br /&gt;
| 087B&lt;br /&gt;
| Utilities Unlimited&lt;br /&gt;
|-&lt;br /&gt;
| 2172&lt;br /&gt;
| 087C&lt;br /&gt;
| phase 5&lt;br /&gt;
|-&lt;br /&gt;
| 2173&lt;br /&gt;
| 087D&lt;br /&gt;
| Juergen Kommos&lt;br /&gt;
|-&lt;br /&gt;
| 2174&lt;br /&gt;
| 087E&lt;br /&gt;
| Electronic Design&lt;br /&gt;
|-&lt;br /&gt;
| 2175&lt;br /&gt;
| 087F&lt;br /&gt;
| James Cook University of North Queensland&lt;br /&gt;
|-&lt;br /&gt;
| 2176&lt;br /&gt;
| 0880&lt;br /&gt;
| AmiTrix Development&lt;br /&gt;
|-&lt;br /&gt;
| 2177&lt;br /&gt;
| 0881&lt;br /&gt;
| Ferranti&lt;br /&gt;
|-&lt;br /&gt;
| 2178&lt;br /&gt;
| 0882&lt;br /&gt;
| Leviathan Development&lt;br /&gt;
|-&lt;br /&gt;
| 2179&lt;br /&gt;
| 0883&lt;br /&gt;
| United Video Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2180&lt;br /&gt;
| 0884&lt;br /&gt;
| GPSoft Pty. Ltd.&lt;br /&gt;
| Originally registered to Juergen Kommos&lt;br /&gt;
|-&lt;br /&gt;
| 2181&lt;br /&gt;
| 0885&lt;br /&gt;
| ArMAX&lt;br /&gt;
| Oliver Bausch&lt;br /&gt;
|-&lt;br /&gt;
| 2182&lt;br /&gt;
| 0886&lt;br /&gt;
| CP Computer&lt;br /&gt;
|-&lt;br /&gt;
| 2183&lt;br /&gt;
| 0887&lt;br /&gt;
| AMOK - Amiga Module &amp;amp;amp; Oberon Klub&lt;br /&gt;
|-&lt;br /&gt;
| 2184&lt;br /&gt;
| 0888&lt;br /&gt;
| ITEK Neser &amp;amp;amp; Sieber GbR&lt;br /&gt;
|-&lt;br /&gt;
| 2185&lt;br /&gt;
| 0889&lt;br /&gt;
| Phillip C. Lello&lt;br /&gt;
|-&lt;br /&gt;
| 2186&lt;br /&gt;
| 088A&lt;br /&gt;
| Cyborg Design Services&lt;br /&gt;
|-&lt;br /&gt;
| 2187&lt;br /&gt;
| 088B&lt;br /&gt;
| G2 Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2188&lt;br /&gt;
| 088C&lt;br /&gt;
| Pro System Computersysteme&lt;br /&gt;
|-&lt;br /&gt;
| 2189&lt;br /&gt;
| 088D&lt;br /&gt;
| ZEUS Electronic&lt;br /&gt;
| Originally registered to MSPI (Markt &amp;amp;amp; Technik)&lt;br /&gt;
|-&lt;br /&gt;
| 2190&lt;br /&gt;
| 088E&lt;br /&gt;
| Altatech&lt;br /&gt;
|-&lt;br /&gt;
| 2191&lt;br /&gt;
| 088F&lt;br /&gt;
| NewTek&lt;br /&gt;
|-&lt;br /&gt;
| 2192&lt;br /&gt;
| 0890&lt;br /&gt;
| M-TEC Hardware Design&lt;br /&gt;
| Originally registered to Hardware Design Udo Neuroth&lt;br /&gt;
|-&lt;br /&gt;
| 2193&lt;br /&gt;
| 0891&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
| Originally registered to Viona Development&lt;br /&gt;
|-&lt;br /&gt;
| 2194&lt;br /&gt;
| 0892&lt;br /&gt;
| Amitek&lt;br /&gt;
| Originally assigned to Marpet Developments&lt;br /&gt;
|-&lt;br /&gt;
| 2195&lt;br /&gt;
| 0893&lt;br /&gt;
| Ingenieurbuero Helfrich&lt;br /&gt;
|-&lt;br /&gt;
| 2196&lt;br /&gt;
| 0894&lt;br /&gt;
| The Neo Group&lt;br /&gt;
|-&lt;br /&gt;
| 2197&lt;br /&gt;
| 0895&lt;br /&gt;
| Cyon&lt;br /&gt;
|-&lt;br /&gt;
| 2198&lt;br /&gt;
| 0896&lt;br /&gt;
| Bob Research Group&lt;br /&gt;
|-&lt;br /&gt;
| 2199&lt;br /&gt;
| 0897&lt;br /&gt;
| Richmond Sound Design Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2200&lt;br /&gt;
| 0898&lt;br /&gt;
| US Cybernetics&lt;br /&gt;
|-&lt;br /&gt;
| 2201&lt;br /&gt;
| 0899&lt;br /&gt;
| Fulvio Ieva&lt;br /&gt;
|-&lt;br /&gt;
| 2202&lt;br /&gt;
| 089A&lt;br /&gt;
| Silicon Studio&lt;br /&gt;
|-&lt;br /&gt;
| 2203&lt;br /&gt;
| 089B&lt;br /&gt;
| MacroSystems (USA)&lt;br /&gt;
| Was named Micro System Devices&lt;br /&gt;
|-&lt;br /&gt;
| 2204&lt;br /&gt;
| 089C&lt;br /&gt;
| Conspector Entertainment&lt;br /&gt;
|-&lt;br /&gt;
| 2205&lt;br /&gt;
| 089D&lt;br /&gt;
| Laserforum&lt;br /&gt;
|-&lt;br /&gt;
| 2206&lt;br /&gt;
| 089E&lt;br /&gt;
| Elbox Computer&lt;br /&gt;
| Mistakenly used by Index Information Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2207&lt;br /&gt;
| 089F&lt;br /&gt;
| Applied Magic Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2208&lt;br /&gt;
| 08A0&lt;br /&gt;
| SDL Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2560&lt;br /&gt;
| 0A00&lt;br /&gt;
| Harms&lt;br /&gt;
|-&lt;br /&gt;
| 2588&lt;br /&gt;
| 0A1C&lt;br /&gt;
| A1K.org Community&lt;br /&gt;
|-&lt;br /&gt;
| 2640&lt;br /&gt;
| 0A50&lt;br /&gt;
| Micronik&lt;br /&gt;
|-&lt;br /&gt;
| 2782&lt;br /&gt;
| 2782&lt;br /&gt;
| OA Design&lt;br /&gt;
|-&lt;br /&gt;
| 3084&lt;br /&gt;
| 0C0C&lt;br /&gt;
| Team 4&lt;br /&gt;
|-&lt;br /&gt;
| 3643&lt;br /&gt;
| 0E3B&lt;br /&gt;
| E3B&lt;br /&gt;
| Michael Boehmer&lt;br /&gt;
|-&lt;br /&gt;
| 3855&lt;br /&gt;
| 0F0F&lt;br /&gt;
| Micronik&lt;br /&gt;
|-&lt;br /&gt;
| 4096&lt;br /&gt;
| 1000&lt;br /&gt;
| MegaMicro&lt;br /&gt;
|-&lt;br /&gt;
| 4110&lt;br /&gt;
| 100E&lt;br /&gt;
| DigiFeX&lt;br /&gt;
|-&lt;br /&gt;
| 4136&lt;br /&gt;
| 1028&lt;br /&gt;
| Imtronics/Memphis&lt;br /&gt;
|-&lt;br /&gt;
| 4149&lt;br /&gt;
| 1035&lt;br /&gt;
| PROTAR&lt;br /&gt;
|-&lt;br /&gt;
| 4369&lt;br /&gt;
| 1111&lt;br /&gt;
| Frank Strauß Elektronik&lt;br /&gt;
| Also used by Kupke&lt;br /&gt;
|-&lt;br /&gt;
| 4626&lt;br /&gt;
| 1212&lt;br /&gt;
| Individual Computers&lt;br /&gt;
|-&lt;br /&gt;
| 4648&lt;br /&gt;
| 1228&lt;br /&gt;
| Flesch Hornemann Computer Elec.&lt;br /&gt;
|-&lt;br /&gt;
| 4680&lt;br /&gt;
| 1248&lt;br /&gt;
| Kupke Computertechnik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 4711&lt;br /&gt;
| 1267&lt;br /&gt;
| RBM digitaltechnik&lt;br /&gt;
|-&lt;br /&gt;
| 4754&lt;br /&gt;
| 1292&lt;br /&gt;
| MacroSystems&lt;br /&gt;
|-&lt;br /&gt;
| 5000&lt;br /&gt;
| 1388&lt;br /&gt;
| ITH&lt;br /&gt;
|-&lt;br /&gt;
| 5001&lt;br /&gt;
| 1389&lt;br /&gt;
| VMC&lt;br /&gt;
|-&lt;br /&gt;
| 5010&lt;br /&gt;
| 1392&lt;br /&gt;
| Ambience Creation Technology&lt;br /&gt;
|-&lt;br /&gt;
| 5011&lt;br /&gt;
| 1393&lt;br /&gt;
| Creative Development&lt;br /&gt;
|-&lt;br /&gt;
| 5012&lt;br /&gt;
| 1394&lt;br /&gt;
| Georg Braun&lt;br /&gt;
|-&lt;br /&gt;
| 5013&lt;br /&gt;
| 1395&lt;br /&gt;
| Swedish User Group of Amiga&lt;br /&gt;
|-&lt;br /&gt;
| 5014&lt;br /&gt;
| 1396&lt;br /&gt;
| Jakub Bednarski&lt;br /&gt;
|-&lt;br /&gt;
| 5015&lt;br /&gt;
| 1397&lt;br /&gt;
| KryoFlux, Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 5016&lt;br /&gt;
| 1398&lt;br /&gt;
| Igor Majstorovic&lt;br /&gt;
|-&lt;br /&gt;
| 5017&lt;br /&gt;
| 1399&lt;br /&gt;
| Alastair M. Robinson&lt;br /&gt;
|-&lt;br /&gt;
| 5018&lt;br /&gt;
| 139A&lt;br /&gt;
| Austex Software&lt;br /&gt;
|-&lt;br /&gt;
| 5019&lt;br /&gt;
| 139B&lt;br /&gt;
| Sören Gust&lt;br /&gt;
|-&lt;br /&gt;
| 5020&lt;br /&gt;
| 139C&lt;br /&gt;
| Rok Krajnc&lt;br /&gt;
|-&lt;br /&gt;
| 5030&lt;br /&gt;
| 13A6&lt;br /&gt;
| Tim Tashpulatov&lt;br /&gt;
|-&lt;br /&gt;
| 5040&lt;br /&gt;
| 13B0&lt;br /&gt;
| 7-bit&lt;br /&gt;
|-&lt;br /&gt;
| 5050&lt;br /&gt;
| 13BA&lt;br /&gt;
| Sakura IT&lt;br /&gt;
|-&lt;br /&gt;
| 5060&lt;br /&gt;
| 13C4&lt;br /&gt;
| FPGAArcade&lt;br /&gt;
|-&lt;br /&gt;
| 5070&lt;br /&gt;
| 13CE&lt;br /&gt;
| CancerSoft Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 5080&lt;br /&gt;
| 13D8&lt;br /&gt;
| Stephen Leary&lt;br /&gt;
|-&lt;br /&gt;
| 5090&lt;br /&gt;
| 13E2&lt;br /&gt;
| DMA Softlab LLC&lt;br /&gt;
|-&lt;br /&gt;
| 5100&lt;br /&gt;
| 13EC&lt;br /&gt;
| Brookhouse Engineering&lt;br /&gt;
|-&lt;br /&gt;
| 5110&lt;br /&gt;
| 13F6&lt;br /&gt;
| Eduardo Arana&lt;br /&gt;
|-&lt;br /&gt;
| 5120&lt;br /&gt;
| 1400&lt;br /&gt;
| CS-LAB&lt;br /&gt;
|-&lt;br /&gt;
| 5130&lt;br /&gt;
| 140A&lt;br /&gt;
| Robert Miranda&lt;br /&gt;
|-&lt;br /&gt;
| 5140&lt;br /&gt;
| 1414&lt;br /&gt;
| RastPort&lt;br /&gt;
|-&lt;br /&gt;
| 5132&lt;br /&gt;
| 140C&lt;br /&gt;
| UAS Interface Ltd6&lt;br /&gt;
|-&lt;br /&gt;
| 5150&lt;br /&gt;
| 141E&lt;br /&gt;
| Amiga Kit&lt;br /&gt;
|-&lt;br /&gt;
| 5160&lt;br /&gt;
| 1428&lt;br /&gt;
| Central Texas Commodore User Group&lt;br /&gt;
|-&lt;br /&gt;
| 5170&lt;br /&gt;
| 1432&lt;br /&gt;
| Confusion Research Center&lt;br /&gt;
|-&lt;br /&gt;
| 5180&lt;br /&gt;
| 143C&lt;br /&gt;
| Solar Soyuz Zaibatsu&lt;br /&gt;
|-&lt;br /&gt;
| 5190&lt;br /&gt;
| 1446&lt;br /&gt;
| BooBip&lt;br /&gt;
|-&lt;br /&gt;
| 5191&lt;br /&gt;
| 1447&lt;br /&gt;
| Matthias Hampel&lt;br /&gt;
|-&lt;br /&gt;
| 5192&lt;br /&gt;
| 1448&lt;br /&gt;
| dec0de Consulting Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 5193&lt;br /&gt;
| 1449&lt;br /&gt;
| Puppy Concepts&lt;br /&gt;
|-&lt;br /&gt;
| 5194&lt;br /&gt;
| 144A&lt;br /&gt;
| Open Amiga Hardware Repository&lt;br /&gt;
|-&lt;br /&gt;
| 5195&lt;br /&gt;
| 144B&lt;br /&gt;
| Double H Tech&lt;br /&gt;
|-&lt;br /&gt;
| 5196&lt;br /&gt;
| 144C&lt;br /&gt;
| Retromatik&lt;br /&gt;
|-&lt;br /&gt;
| 5500&lt;br /&gt;
| 157C&lt;br /&gt;
| Inhouse Information&lt;br /&gt;
|-&lt;br /&gt;
| 5768&lt;br /&gt;
| 1688&lt;br /&gt;
| Bio Con&lt;br /&gt;
|-&lt;br /&gt;
| 6148&lt;br /&gt;
| 1804&lt;br /&gt;
| HK-Computer&lt;br /&gt;
|-&lt;br /&gt;
| 6502&lt;br /&gt;
| 1966&lt;br /&gt;
| Cloanto&lt;br /&gt;
|-&lt;br /&gt;
| 6520&lt;br /&gt;
| 1978&lt;br /&gt;
| Oliver Gantert&lt;br /&gt;
|-&lt;br /&gt;
| 7777&lt;br /&gt;
| 1E61&lt;br /&gt;
| Rafal Gabriel Chyla&lt;br /&gt;
|-&lt;br /&gt;
| 8215&lt;br /&gt;
| 2017&lt;br /&gt;
| Vortex&lt;br /&gt;
|-&lt;br /&gt;
| 8244&lt;br /&gt;
| 2034&lt;br /&gt;
| Spirit Technology&lt;br /&gt;
|-&lt;br /&gt;
| 8290&lt;br /&gt;
| 2062&lt;br /&gt;
| Expansion Systems&lt;br /&gt;
|-&lt;br /&gt;
| 8448&lt;br /&gt;
| 2100&lt;br /&gt;
| ReadySoft&lt;br /&gt;
|-&lt;br /&gt;
| 8512&lt;br /&gt;
| 2140&lt;br /&gt;
| Phase 5 Digital Products&lt;br /&gt;
|-&lt;br /&gt;
| 8553&lt;br /&gt;
| 2169&lt;br /&gt;
| Digital Processing Systems Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 8704&lt;br /&gt;
| 2200&lt;br /&gt;
| ACT Elektronik&lt;br /&gt;
|-&lt;br /&gt;
| 8738&lt;br /&gt;
| 2222&lt;br /&gt;
| ACT Elektronik&lt;br /&gt;
|-&lt;br /&gt;
| 9512&lt;br /&gt;
| 2528&lt;br /&gt;
| Tower Technologies&lt;br /&gt;
|-&lt;br /&gt;
| 10676&lt;br /&gt;
| 29B4&lt;br /&gt;
| Electronic Design&lt;br /&gt;
|-&lt;br /&gt;
| 14195&lt;br /&gt;
| 3773&lt;br /&gt;
| Media-net-Point&lt;br /&gt;
|-&lt;br /&gt;
| 14501&lt;br /&gt;
| 38A5&lt;br /&gt;
| Petsoff, Finland&lt;br /&gt;
|-&lt;br /&gt;
| 16375&lt;br /&gt;
| 3FF7&lt;br /&gt;
| Uwe Gerlach&lt;br /&gt;
|-&lt;br /&gt;
| 16707&lt;br /&gt;
| 4143&lt;br /&gt;
| Ateo Concepts&lt;br /&gt;
|-&lt;br /&gt;
| 16708&lt;br /&gt;
| 4144&lt;br /&gt;
| ALiENDESiGN&lt;br /&gt;
|-&lt;br /&gt;
| 16945&lt;br /&gt;
| 4231&lt;br /&gt;
| A.C.T.&lt;br /&gt;
|-&lt;br /&gt;
| 17740&lt;br /&gt;
| 454C&lt;br /&gt;
| HK-Computer (ELSAT)&lt;br /&gt;
|-&lt;br /&gt;
| 18260&lt;br /&gt;
| 4754&lt;br /&gt;
| MacroSystems (Germany)&lt;br /&gt;
|-&lt;br /&gt;
| 19796&lt;br /&gt;
| 4D54&lt;br /&gt;
| Markt &amp;amp; Technik&lt;br /&gt;
|-&lt;br /&gt;
| 20480&lt;br /&gt;
| 5000&lt;br /&gt;
| François Lacombe&lt;br /&gt;
|-&lt;br /&gt;
| 22359&lt;br /&gt;
| 5757&lt;br /&gt;
| Markt &amp;amp; Technik&lt;br /&gt;
|-&lt;br /&gt;
| 26464&lt;br /&gt;
| 6760&lt;br /&gt;
| Combitec&lt;br /&gt;
|-&lt;br /&gt;
| 26470&lt;br /&gt;
| 6766&lt;br /&gt;
| Combitec&lt;br /&gt;
|-&lt;br /&gt;
| 28014&lt;br /&gt;
| 6D6E&lt;br /&gt;
| MNT Media and Technology UG&lt;br /&gt;
|-&lt;br /&gt;
| 32768&lt;br /&gt;
| 8000&lt;br /&gt;
| M.A.S.T.&lt;br /&gt;
|-&lt;br /&gt;
| 42240&lt;br /&gt;
| A500&lt;br /&gt;
| Aethreum Digital&lt;br /&gt;
|-&lt;br /&gt;
| 43437&lt;br /&gt;
| A9AD&lt;br /&gt;
| Reis-Ware&lt;br /&gt;
|-&lt;br /&gt;
| 43521&lt;br /&gt;
| AA01&lt;br /&gt;
| Cameron&lt;br /&gt;
|-&lt;br /&gt;
| 43537&lt;br /&gt;
| AA11&lt;br /&gt;
| Reis-Ware&lt;br /&gt;
|-&lt;br /&gt;
| 44359&lt;br /&gt;
| AD47&lt;br /&gt;
| Matay&lt;br /&gt;
|-&lt;br /&gt;
| 46504&lt;br /&gt;
| B5A8&lt;br /&gt;
| Phoenix&lt;br /&gt;
|-&lt;br /&gt;
| 48879&lt;br /&gt;
| BEEF&lt;br /&gt;
| Swiss Mountain Dog Products&lt;br /&gt;
|-&lt;br /&gt;
| 49160&lt;br /&gt;
| C008&lt;br /&gt;
| Combitec&lt;br /&gt;
|-&lt;br /&gt;
| 61453&lt;br /&gt;
| F00D&lt;br /&gt;
| Forefront Technologies Inc.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
For any changes/additions to this registry see [[#How_to_Obtain_a_Manufacturer_Number|How to Obtain a Manufacturer Number]]&lt;/div&gt;</summary>
		<author><name>Costel Mincea</name></author>
	</entry>
	<entry>
		<id>https://wiki.amigaos.net/w/index.php?title=Amiga_Hardware_Manufacturer_ID_Registry&amp;diff=12602</id>
		<title>Amiga Hardware Manufacturer ID Registry</title>
		<link rel="alternate" type="text/html" href="https://wiki.amigaos.net/w/index.php?title=Amiga_Hardware_Manufacturer_ID_Registry&amp;diff=12602"/>
		<updated>2026-09-08T11:09:43Z</updated>

		<summary type="html">&lt;p&gt;Costel Mincea: /* Registry */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
= How to Obtain a Manufacturer Number =&lt;br /&gt;
&lt;br /&gt;
Manufacturer&#039;s numbers are assigned by the AmigaOS development team. To obtain your unique manufacturer number send a support request to [mailto:support@hyperion-entertainment.com support@hyperion-entertainment.com] including these information:&lt;br /&gt;
&lt;br /&gt;
 1. The name of the company or person which the number is assigned to&lt;br /&gt;
 &lt;br /&gt;
 2. Postal address/contact address&lt;br /&gt;
 &lt;br /&gt;
 3. Name of the contact person, with a corresponding e-mail address&lt;br /&gt;
 &lt;br /&gt;
 4. A brief description of the kind of products you want to produce&lt;br /&gt;
&lt;br /&gt;
= Your Manufacturer Number =&lt;br /&gt;
&lt;br /&gt;
Attention hardware manufacturers. If you are developing a hardware expansion product for the Classic Amiga (e.g. 500, 2000, 3000) then you will need to obtain a special manufacturer ID number from the AmigaOS development team to identify your product. This manufacturer number is used by the Amiga to link your hardware with its driver software at boot time.&lt;br /&gt;
&lt;br /&gt;
Your manufacturer number is part of the special protocol that the Amiga uses to automatically configure all expansion devices on the bus without the user having to cut jumpers or adjust dip switches. This is called auto-config.&lt;br /&gt;
&lt;br /&gt;
At start-up time, the system first polls each board in the system and assigns the board its own address space. If it is a memory board, its RAM is linked into the memory free pool. Later in the boot sequence, after DOS is initialized, the binddrivers program is run. Binddrivers will search the directory SYS:Expansion for the drivers that go with the boards.&lt;br /&gt;
&lt;br /&gt;
To do this binddrivers looks in the Tool Type field of all icon files in SYS:Expansion. If the first seven bytes of the Tool Type field are &amp;quot;PRODUCT&amp;quot;, then this is an icon file for a driver.&lt;br /&gt;
&lt;br /&gt;
Binddrivers will then attempt to match the drivers it has found with the boards that were found earlier. This is where your manufacturer number comes in.&lt;br /&gt;
&lt;br /&gt;
Your manufacturer number goes in two places. First, it is burned in hex form into the PAL which is part of ALL auto-config expansion products. Second, it appears in ASCII in the Tool Type field of the icon file for your product&#039;s driver. By matching these two numbers, the Amiga can automatically configure your board and bind it&#039;s software driver into the system as well.&lt;br /&gt;
&lt;br /&gt;
The manufacturer&#039;s number is a 16-bit ID which appears in PAL offsets $10-$17. There is also an 8-bit product number which you assign. The product number is for uniquely identifying different products from the same vendor. The product number will appear in PAL offsets $04-$07. This gives you a total of 24 bits to identify each of your products.&lt;br /&gt;
&lt;br /&gt;
These 24 bits of information in the PAL which identify your product are matched against the information in the Tool Type field of all icon files in the SYS:Expansion drawer. For example, suppose you are manufacturer #1019. You have two products, #1 and #2 which both use the same driver. The icon for your driver for these two products would have a Tool Type set to &amp;quot;PRODUCT=1019/1|1019/2&amp;quot;. This means: I am an icon for a driver that works with product number 1 or 2 from manufacturer 1019, now bind me. Spaces are not legal. Here are two other examples:&lt;br /&gt;
&lt;br /&gt;
; PRODUCT=1208/11&lt;br /&gt;
: is the Tool Type for a driver for product 11 from manufacturer number 1208.&lt;br /&gt;
&lt;br /&gt;
; PRODUCT=1017&lt;br /&gt;
: is the Tool Type for a driver for any product from manufacturer number 1017.&lt;br /&gt;
&lt;br /&gt;
For an informal explanation of the auto-configuration process, see the chapter on Software Expansion Architecture from the 2nd Annual Amiga Developer&#039;s Conference Notes (available on ADCD 2.1). For the details of timing, power, the PAL equations and PAL address specifications and the expansion library documentation, see sections 3.1 to 3.3 of the A500/A2000 Technical Reference Manual. The original auto-config spec appears in the A1000 Schematics and Expansion Specification.&lt;br /&gt;
&lt;br /&gt;
The auto-config process makes the addition of expansion products to the system very easy. All the user has to do is put the board in any slot and copy the driver from the release disk to his own SYS:Expansion drawer. Everything else is automatic. There are no jumpers or dip switches to set. Best of all, you will get a lot less support calls asking how to make your product work with the XYZ-Corp-battery-backed-clock.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
&lt;br /&gt;
Some notes on hardware manufacturer ID assignment.&lt;br /&gt;
&lt;br /&gt;
* Manufacturer ID numbers are assigned free of charge.&lt;br /&gt;
* Please provide the following information when requesting an ID:&lt;br /&gt;
*# Name of the company or person&lt;br /&gt;
*# Postal address/contact address&lt;br /&gt;
*# Name of the contact person, with a corresponding e-mail address&lt;br /&gt;
*# A brief description of the kind of products you want to produce&lt;br /&gt;
* All ID numbers smaller than 5000 must be considered unsafe because no information exists on which numbers exactly were taken during the time Commodore, Inc. disintegrated.&lt;br /&gt;
* ID numbers in the range 8192 to 18841 must be considered unsafe because some hardware developers mistook the numbers assigned to them to be given in hexadecimal format. Hence 0x2000 = 8192 and 0x4999 = 18841.&lt;br /&gt;
&lt;br /&gt;
= Example code =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
/*-----------------------------------------------*/&lt;br /&gt;
/* Here is a short program which will tell you   */&lt;br /&gt;
/* about the expansion boards configured in your */&lt;br /&gt;
/* system without you opening up the machine.    */&lt;br /&gt;
/* Code by Bill Koester of CATS                  */&lt;br /&gt;
/*-----------------------------------------------*/&lt;br /&gt;
#include &amp;lt;libraries/configvars.h&amp;gt;&lt;br /&gt;
#include &amp;lt;libraries/expansion.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
struct ExpansionBase *ExpansionBase;&lt;br /&gt;
&lt;br /&gt;
void cleanup();&lt;br /&gt;
void printdev();&lt;br /&gt;
&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
   struct ConfigDev *MyConfigDev;&lt;br /&gt;
&lt;br /&gt;
   /*----------------------------------*/&lt;br /&gt;
   /* Open the expansion library,      */&lt;br /&gt;
   /* if there is a problem then exit  */&lt;br /&gt;
   /*----------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   ExpansionBase =(struct ExpansionBase *) OpenLibrary(EXPANSIONNAME,0);&lt;br /&gt;
   if(ExpansionBase==NULL)&lt;br /&gt;
   {&lt;br /&gt;
      printf(&amp;quot;Error opening expansion library!!\n&amp;quot;);&lt;br /&gt;
      cleanup();&lt;br /&gt;
      exit(0);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   /*--------------------------------------------*/&lt;br /&gt;
   /* Use FindConfigDev to get info on the first */&lt;br /&gt;
   /* expansion board on the list maintained by  */&lt;br /&gt;
   /* Exec.  If there are no expansion boards in */&lt;br /&gt;
   /* the system then exit.                      */&lt;br /&gt;
   /*--------------------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   MyConfigDev = NULL;&lt;br /&gt;
&lt;br /&gt;
  /*--------------------------------------------------*/&lt;br /&gt;
  /* FindConfigDev(oldConfigDev,manufacturer,product) */&lt;br /&gt;
  /* oldConfigDev = NULL for the top of the list      */&lt;br /&gt;
  /* manufacturer = -1 for any manufacturer           */&lt;br /&gt;
  /* product      = -1 for any product                */&lt;br /&gt;
  /*--------------------------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   MyConfigDev = FindConfigDev(NULL,-1,-1);&lt;br /&gt;
&lt;br /&gt;
   if(MyConfigDev==NULL)&lt;br /&gt;
   {&lt;br /&gt;
      printf(&amp;quot;No Configured Devices found!!\n&amp;quot;);&lt;br /&gt;
      cleanup();&lt;br /&gt;
      exit(0);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   printdev(MyConfigDev);&lt;br /&gt;
&lt;br /&gt;
   /*-----------------------------------*/&lt;br /&gt;
   /* OK, there is at least one board,  */&lt;br /&gt;
   /* so loop and get the entire list   */&lt;br /&gt;
   /* printing as we go with printdev() */&lt;br /&gt;
   /*-----------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   while(MyConfigDev = FindConfigDev(MyConfigDev,-1,-1))&lt;br /&gt;
   {&lt;br /&gt;
      printdev(MyConfigDev);&lt;br /&gt;
   }&lt;br /&gt;
   cleanup();&lt;br /&gt;
   return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*-------------------*/&lt;br /&gt;
/* Close up shop...  */&lt;br /&gt;
/*-------------------*/&lt;br /&gt;
void cleanup()&lt;br /&gt;
{&lt;br /&gt;
   if(ExpansionBase)&lt;br /&gt;
      CloseLibrary(ExpansionBase);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*----------------------------------*/&lt;br /&gt;
/* Print out the contents of the    */&lt;br /&gt;
/* dev structure for this expansion */&lt;br /&gt;
/* product.                         */&lt;br /&gt;
/*----------------------------------*/&lt;br /&gt;
&lt;br /&gt;
void printdev(dev)&lt;br /&gt;
struct ConfigDev *dev;&lt;br /&gt;
{&lt;br /&gt;
   char buff[200];&lt;br /&gt;
&lt;br /&gt;
   printf(&amp;quot;Flags          = &amp;quot;);&lt;br /&gt;
   if(dev-&amp;gt;cd_Flags==NULL)&lt;br /&gt;
      printf(&amp;quot;NULL  &amp;quot;);&lt;br /&gt;
   if(dev-&amp;gt;cd_Flags&amp;amp;CDF_SHUTUP)&lt;br /&gt;
      printf(&amp;quot;CDF_SHUTUP  &amp;quot;);&lt;br /&gt;
   if(dev-&amp;gt;cd_Flags&amp;amp;CDF_CONFIGME)&lt;br /&gt;
      printf(&amp;quot;CDF_CONFIGME  &amp;quot;);&lt;br /&gt;
   printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
   printf(&amp;quot;Board Address  = %x\n&amp;quot;,dev-&amp;gt;cd_BoardAddr);&lt;br /&gt;
   printf(&amp;quot;Board Size     = %d bytes\n&amp;quot;,dev-&amp;gt;cd_BoardSize);&lt;br /&gt;
   printf(&amp;quot;Slot  Address  = %d\n&amp;quot;,dev-&amp;gt;cd_SlotAddr);&lt;br /&gt;
   printf(&amp;quot;Slot  Size     = %d\n&amp;quot;,dev-&amp;gt;cd_SlotSize);&lt;br /&gt;
   printf(&amp;quot;Driver code at   %x\n&amp;quot;,dev-&amp;gt;cd_Driver);&lt;br /&gt;
&lt;br /&gt;
   printf(&amp;quot;er_Type         = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Type);&lt;br /&gt;
   printf(&amp;quot;er_Product      = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Product);&lt;br /&gt;
   printf(&amp;quot;er_Flags        = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Flags);&lt;br /&gt;
   printf(&amp;quot;er_Reserved03   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved03);&lt;br /&gt;
   printf(&amp;quot;er_Manufacturer = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Manufacturer);&lt;br /&gt;
   printf(&amp;quot;er_SerialNumber = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_SerialNumber);&lt;br /&gt;
   printf(&amp;quot;er_InitDiagVec  = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_InitDiagVec);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0c   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0c);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0d   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0d);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0e   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0e);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0f   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0f);&lt;br /&gt;
&lt;br /&gt;
   printf(&amp;quot;Hit Return to continue:\n&amp;quot;);&lt;br /&gt;
   gets(buff);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Registry =&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! ID (decimal)&lt;br /&gt;
! ID (hexadecimal)&lt;br /&gt;
! Manufacturer&lt;br /&gt;
! Notes&lt;br /&gt;
|-&lt;br /&gt;
| 1&lt;br /&gt;
| 0001&lt;br /&gt;
| Micronik&lt;br /&gt;
|-&lt;br /&gt;
| 211&lt;br /&gt;
| 00D3&lt;br /&gt;
| Pacific Peripherals/Profex&lt;br /&gt;
|-&lt;br /&gt;
| 221&lt;br /&gt;
| 00DD&lt;br /&gt;
| Kupke Computertechnik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 256&lt;br /&gt;
| 0100&lt;br /&gt;
| Memphis&lt;br /&gt;
| Originally registered to MacroSystems US&lt;br /&gt;
|-&lt;br /&gt;
| 512&lt;br /&gt;
| 0200&lt;br /&gt;
| 3-State Computertechnik&lt;br /&gt;
|-&lt;br /&gt;
| 513&lt;br /&gt;
| 0201&lt;br /&gt;
| Commodore (Braunschweig)&lt;br /&gt;
|-&lt;br /&gt;
| 514&lt;br /&gt;
| 0202&lt;br /&gt;
| Commodore (West Chester)&lt;br /&gt;
|-&lt;br /&gt;
| 515&lt;br /&gt;
| 0203&lt;br /&gt;
| Commodore (West Chester)&lt;br /&gt;
| Originally registered to Combitech/Macrosystem&lt;br /&gt;
|-&lt;br /&gt;
| 756&lt;br /&gt;
| 02F4&lt;br /&gt;
| Progressive Peripherals &amp;amp; Software&lt;br /&gt;
|-&lt;br /&gt;
| 767&lt;br /&gt;
| 02FF&lt;br /&gt;
| Kolff Computer Supplies&lt;br /&gt;
|-&lt;br /&gt;
| 1001&lt;br /&gt;
| 03E9&lt;br /&gt;
| Tecmar&lt;br /&gt;
|-&lt;br /&gt;
| 1002&lt;br /&gt;
| 03EA&lt;br /&gt;
| Telesys&lt;br /&gt;
|-&lt;br /&gt;
| 1003&lt;br /&gt;
| 03EB&lt;br /&gt;
| The Micro-Forge&lt;br /&gt;
|-&lt;br /&gt;
| 1004&lt;br /&gt;
| 03EC&lt;br /&gt;
| Kronos/C Ltd.&lt;br /&gt;
| Originally registered to Card Co. (Supra)&lt;br /&gt;
|-&lt;br /&gt;
| 1005&lt;br /&gt;
| 03ED&lt;br /&gt;
| A-Squared&lt;br /&gt;
|-&lt;br /&gt;
| 1006&lt;br /&gt;
| 03EE&lt;br /&gt;
| Comspec Communications&lt;br /&gt;
|-&lt;br /&gt;
| 1007&lt;br /&gt;
| 03EF&lt;br /&gt;
| HT Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 1008&lt;br /&gt;
| 03F0&lt;br /&gt;
| RDS Software&lt;br /&gt;
|-&lt;br /&gt;
| 1009&lt;br /&gt;
| 03F1&lt;br /&gt;
| Anakin Research&lt;br /&gt;
|-&lt;br /&gt;
| 1010&lt;br /&gt;
| 03F2&lt;br /&gt;
| MicroBotics&lt;br /&gt;
|-&lt;br /&gt;
| 1011&lt;br /&gt;
| 03F3&lt;br /&gt;
| Bob Krauth&lt;br /&gt;
|-&lt;br /&gt;
| 1012&lt;br /&gt;
| 03F4&lt;br /&gt;
| Access Associates (Alegra)&lt;br /&gt;
|-&lt;br /&gt;
| 1013&lt;br /&gt;
| 03F5&lt;br /&gt;
| Mini Comp Systems Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 1014&lt;br /&gt;
| 03F6&lt;br /&gt;
| Cypress Technology&lt;br /&gt;
|-&lt;br /&gt;
| 1015&lt;br /&gt;
| 03F7&lt;br /&gt;
| Fuller Computers&lt;br /&gt;
|-&lt;br /&gt;
| 1016&lt;br /&gt;
| 03F8&lt;br /&gt;
| Galaxy Computers&lt;br /&gt;
|-&lt;br /&gt;
| 1017&lt;br /&gt;
| 03F9&lt;br /&gt;
| ADA Research&lt;br /&gt;
|-&lt;br /&gt;
| 1018&lt;br /&gt;
| 03FA&lt;br /&gt;
| Computer Service Italia&lt;br /&gt;
|-&lt;br /&gt;
| 1019&lt;br /&gt;
| 03FB&lt;br /&gt;
| Amigo&lt;br /&gt;
|-&lt;br /&gt;
| 1020&lt;br /&gt;
| 03FC&lt;br /&gt;
| Micro-Solutions Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1021&lt;br /&gt;
| 03FD&lt;br /&gt;
| Stacar International&lt;br /&gt;
|-&lt;br /&gt;
| 1022&lt;br /&gt;
| 03FE&lt;br /&gt;
| Video Precisions&lt;br /&gt;
|-&lt;br /&gt;
| 1023&lt;br /&gt;
| 03FF&lt;br /&gt;
| ASDG, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1025&lt;br /&gt;
| 0401&lt;br /&gt;
| Ing. Buero Kalawsky&lt;br /&gt;
|-&lt;br /&gt;
| 1026&lt;br /&gt;
| 0402&lt;br /&gt;
| Computer Tuning&lt;br /&gt;
|-&lt;br /&gt;
| 1027&lt;br /&gt;
| 0403&lt;br /&gt;
| Interplan Unternehmensberatung&lt;br /&gt;
|-&lt;br /&gt;
| 1028&lt;br /&gt;
| 0404&lt;br /&gt;
| Imtronics/Memphis&lt;br /&gt;
| Originally registered to Peter Ohlich&lt;br /&gt;
|-&lt;br /&gt;
| 1030&lt;br /&gt;
| 0406&lt;br /&gt;
| Commodore (Lowell University)&lt;br /&gt;
| Originally registered to Productivity Center&lt;br /&gt;
|-&lt;br /&gt;
| 1041&lt;br /&gt;
| 0411&lt;br /&gt;
| Design Labs&lt;br /&gt;
|-&lt;br /&gt;
| 1042&lt;br /&gt;
| 0412&lt;br /&gt;
| MCS&lt;br /&gt;
|-&lt;br /&gt;
| 1043&lt;br /&gt;
| 0413&lt;br /&gt;
| B. J. Freeman&lt;br /&gt;
|-&lt;br /&gt;
| 1044&lt;br /&gt;
| 0414&lt;br /&gt;
| Side Effects Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1045&lt;br /&gt;
| 0415&lt;br /&gt;
| Oklahoma Personal Comp.&lt;br /&gt;
|-&lt;br /&gt;
| 1046&lt;br /&gt;
| 0416&lt;br /&gt;
| Advanced Micro Innovations&lt;br /&gt;
|-&lt;br /&gt;
| 1047&lt;br /&gt;
| 0417&lt;br /&gt;
| Industrial Support Services&lt;br /&gt;
|-&lt;br /&gt;
| 1048&lt;br /&gt;
| 0418&lt;br /&gt;
| Technisoft&lt;br /&gt;
|-&lt;br /&gt;
| 1049&lt;br /&gt;
| 0419&lt;br /&gt;
| Prolific, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1050&lt;br /&gt;
| 041A&lt;br /&gt;
| Softeam, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1051&lt;br /&gt;
| 041B&lt;br /&gt;
| GRC Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 1052&lt;br /&gt;
| 041C&lt;br /&gt;
| David Lai&lt;br /&gt;
|-&lt;br /&gt;
| 1053&lt;br /&gt;
| 041D&lt;br /&gt;
| Ameristar Technologies&lt;br /&gt;
|-&lt;br /&gt;
| 1054&lt;br /&gt;
| 041E&lt;br /&gt;
| Cline Refrigeration&lt;br /&gt;
|-&lt;br /&gt;
| 1055&lt;br /&gt;
| 041F&lt;br /&gt;
| Cardiac Pacemakers, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1056&lt;br /&gt;
| 0420&lt;br /&gt;
| Supra Corp. (Creative Microsystems)&lt;br /&gt;
|-&lt;br /&gt;
| 1057&lt;br /&gt;
| 0421&lt;br /&gt;
| Wayne Diener&lt;br /&gt;
|-&lt;br /&gt;
| 1058&lt;br /&gt;
| 0422&lt;br /&gt;
| Computer Systems Associates (CSA)&lt;br /&gt;
|-&lt;br /&gt;
| 1059&lt;br /&gt;
| 0423&lt;br /&gt;
| Trionix, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1060&lt;br /&gt;
| 0424&lt;br /&gt;
| David Lucas&lt;br /&gt;
|-&lt;br /&gt;
| 1061&lt;br /&gt;
| 0425&lt;br /&gt;
| Analog Precision&lt;br /&gt;
| Also assigned to D &amp;amp; L Distributing&lt;br /&gt;
|-&lt;br /&gt;
| 1267&lt;br /&gt;
| 04F3&lt;br /&gt;
| RBM Digitaltechnik&lt;br /&gt;
|-&lt;br /&gt;
| 1282&lt;br /&gt;
| 0502&lt;br /&gt;
| M-TEC Hardware Design&lt;br /&gt;
|-&lt;br /&gt;
| 1337&lt;br /&gt;
| 0539&lt;br /&gt;
| Thomas Stenzel (DaFR34K)&lt;br /&gt;
|-&lt;br /&gt;
| 1576&lt;br /&gt;
| 0628&lt;br /&gt;
| Boris Križma&lt;br /&gt;
|-&lt;br /&gt;
| 1729&lt;br /&gt;
| 06C1&lt;br /&gt;
| Thomas Richter / OpenPCI-A1200 Mediator bridge&lt;br /&gt;
|-&lt;br /&gt;
| 1730&lt;br /&gt;
| 06C2&lt;br /&gt;
| Thomas Richter / OpenPCI-A4000 Mediator bridge&lt;br /&gt;
|-&lt;br /&gt;
| 1731&lt;br /&gt;
| 06C3&lt;br /&gt;
| Thomas Richter / OpenPCI-Prometheus bridge (Firestorm or original)&lt;br /&gt;
|-&lt;br /&gt;
| 1732&lt;br /&gt;
| 06C4&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved1&lt;br /&gt;
|-&lt;br /&gt;
| 1733&lt;br /&gt;
| 06C5&lt;br /&gt;
| Thomas Richter / OpenPCI-Grex bridge (both A1200 and A4000)&lt;br /&gt;
|-&lt;br /&gt;
| 1734&lt;br /&gt;
| 06C6&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved2&lt;br /&gt;
|-&lt;br /&gt;
| 1735&lt;br /&gt;
| 06C7&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved3&lt;br /&gt;
|-&lt;br /&gt;
| 1736&lt;br /&gt;
| 06C8&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved4&lt;br /&gt;
|-&lt;br /&gt;
| 1737&lt;br /&gt;
| 06C9&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved5&lt;br /&gt;
|-&lt;br /&gt;
| 1738&lt;br /&gt;
| 06CA&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved6&lt;br /&gt;
|-&lt;br /&gt;
| 1739&lt;br /&gt;
| 06CB&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved7&lt;br /&gt;
|-&lt;br /&gt;
| 1740&lt;br /&gt;
| 06CC&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved8&lt;br /&gt;
|-&lt;br /&gt;
| 1741&lt;br /&gt;
| 06CD&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved9&lt;br /&gt;
|-&lt;br /&gt;
| 1742&lt;br /&gt;
| 06CE&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved10&lt;br /&gt;
|-&lt;br /&gt;
| 1743&lt;br /&gt;
| 06CF&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved11&lt;br /&gt;
|-&lt;br /&gt;
| 1744&lt;br /&gt;
| 06D0&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved12&lt;br /&gt;
|-&lt;br /&gt;
| 1761&lt;br /&gt;
| 06E1&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
|-&lt;br /&gt;
| 1803&lt;br /&gt;
| 070B&lt;br /&gt;
| UAE Amiga Emulator&lt;br /&gt;
|-&lt;br /&gt;
| 2002&lt;br /&gt;
| 07D2&lt;br /&gt;
| Mimetics Corp.&lt;br /&gt;
|-&lt;br /&gt;
| 2003&lt;br /&gt;
| 07D3&lt;br /&gt;
| ACDA&lt;br /&gt;
|-&lt;br /&gt;
| 2004&lt;br /&gt;
| 07D4&lt;br /&gt;
| Finn R. Jacobsen&lt;br /&gt;
|-&lt;br /&gt;
| 2005&lt;br /&gt;
| 07D5&lt;br /&gt;
| Elthen Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2006&lt;br /&gt;
| 07D6&lt;br /&gt;
| Nine Tiles Computer Systems Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2007&lt;br /&gt;
| 07D7&lt;br /&gt;
| Analog Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2008&lt;br /&gt;
| 07D8&lt;br /&gt;
| Bell &amp;amp;amp; Howell&lt;br /&gt;
|-&lt;br /&gt;
| 2009&lt;br /&gt;
| 07D9&lt;br /&gt;
| Roland Kochler&lt;br /&gt;
|-&lt;br /&gt;
| 2010&lt;br /&gt;
| 07DA&lt;br /&gt;
| Byte Corp.&lt;br /&gt;
|-&lt;br /&gt;
| 2011&lt;br /&gt;
| 07DB&lt;br /&gt;
| Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 2012&lt;br /&gt;
| 07DC&lt;br /&gt;
| DKB, Inc.&lt;br /&gt;
| Previously named Michigan Software&lt;br /&gt;
|-&lt;br /&gt;
| 2013&lt;br /&gt;
| 07DD&lt;br /&gt;
| Pacific Peripherals&lt;br /&gt;
|-&lt;br /&gt;
| 2014&lt;br /&gt;
| 07DE&lt;br /&gt;
| Sysaphus Software&lt;br /&gt;
|-&lt;br /&gt;
| 2015&lt;br /&gt;
| 07DF&lt;br /&gt;
| Digitronics&lt;br /&gt;
|-&lt;br /&gt;
| 2016&lt;br /&gt;
| 07E0&lt;br /&gt;
| Akron Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2017&lt;br /&gt;
| 07E1&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
|-&lt;br /&gt;
| 2018&lt;br /&gt;
| 07E2&lt;br /&gt;
| Calmos&lt;br /&gt;
|-&lt;br /&gt;
| 2019&lt;br /&gt;
| 07E3&lt;br /&gt;
| Dover Research&lt;br /&gt;
|-&lt;br /&gt;
| 2020&lt;br /&gt;
| 07E4&lt;br /&gt;
| David Krehbiel&lt;br /&gt;
|-&lt;br /&gt;
| 2021&lt;br /&gt;
| 07E5&lt;br /&gt;
| Synergy Peripheral Systems&lt;br /&gt;
| Also known as California Access&lt;br /&gt;
|-&lt;br /&gt;
| 2022&lt;br /&gt;
| 07E6&lt;br /&gt;
| Xetec&lt;br /&gt;
|-&lt;br /&gt;
| 2023&lt;br /&gt;
| 07E7&lt;br /&gt;
| Micron Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2024&lt;br /&gt;
| 07E8&lt;br /&gt;
| CH Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2025&lt;br /&gt;
| 07E9&lt;br /&gt;
| American Liquid Light&lt;br /&gt;
|-&lt;br /&gt;
| 2026&lt;br /&gt;
| 07EA&lt;br /&gt;
| Progressive Peripherals &amp;amp;amp; Software&lt;br /&gt;
| Also used by Ateo&lt;br /&gt;
|-&lt;br /&gt;
| 2027&lt;br /&gt;
| 07EB&lt;br /&gt;
| Wicat Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2028&lt;br /&gt;
| 07EC&lt;br /&gt;
| Applied Systems &amp;amp;amp; Peripherals&lt;br /&gt;
|-&lt;br /&gt;
| 2029&lt;br /&gt;
| 07ED&lt;br /&gt;
| Delaware Valley Software&lt;br /&gt;
|-&lt;br /&gt;
| 2030&lt;br /&gt;
| 07EE&lt;br /&gt;
| Palomax&lt;br /&gt;
|-&lt;br /&gt;
| 2031&lt;br /&gt;
| 07EF&lt;br /&gt;
| Incognito Software&lt;br /&gt;
|-&lt;br /&gt;
| 2032&lt;br /&gt;
| 07F0&lt;br /&gt;
| Jadesign&lt;br /&gt;
|-&lt;br /&gt;
| 2033&lt;br /&gt;
| 07F1&lt;br /&gt;
| BVR&lt;br /&gt;
|-&lt;br /&gt;
| 2034&lt;br /&gt;
| 07F2&lt;br /&gt;
| Spirit Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2035&lt;br /&gt;
| 07F3&lt;br /&gt;
| Spirit Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2036&lt;br /&gt;
| 07F4&lt;br /&gt;
| Atronic&lt;br /&gt;
|-&lt;br /&gt;
| 2037&lt;br /&gt;
| 07F5&lt;br /&gt;
| Scott Karlin&lt;br /&gt;
|-&lt;br /&gt;
| 2038&lt;br /&gt;
| 07F6&lt;br /&gt;
| Howitch&lt;br /&gt;
|-&lt;br /&gt;
| 2039&lt;br /&gt;
| 07F7&lt;br /&gt;
| Sullivan Brothers Visual Engineers&lt;br /&gt;
|-&lt;br /&gt;
| 2040&lt;br /&gt;
| 07F8&lt;br /&gt;
| G I T&lt;br /&gt;
|-&lt;br /&gt;
| 2041&lt;br /&gt;
| 07F9&lt;br /&gt;
| Amigo Business Computers&lt;br /&gt;
|-&lt;br /&gt;
| 2042&lt;br /&gt;
| 07FA&lt;br /&gt;
| Micro E Ab&lt;br /&gt;
|-&lt;br /&gt;
| 2043&lt;br /&gt;
| 07FB&lt;br /&gt;
| Ralph Kruse&lt;br /&gt;
|-&lt;br /&gt;
| 2044&lt;br /&gt;
| 07FC&lt;br /&gt;
| Clearpoint Research&lt;br /&gt;
|-&lt;br /&gt;
| 2045&lt;br /&gt;
| 07FD&lt;br /&gt;
| Kodiak&lt;br /&gt;
|-&lt;br /&gt;
| 2046&lt;br /&gt;
| 07FE&lt;br /&gt;
| BSC&lt;br /&gt;
| Originally registered to Phoenix Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2047&lt;br /&gt;
| 07FF&lt;br /&gt;
| No Name Shown&lt;br /&gt;
|-&lt;br /&gt;
| 2048&lt;br /&gt;
| 0800&lt;br /&gt;
| Commodore Braunschweig&lt;br /&gt;
|-&lt;br /&gt;
| 2049&lt;br /&gt;
| 0801&lt;br /&gt;
| BSC&lt;br /&gt;
| Originally registered to Elaborate Bytes&lt;br /&gt;
|-&lt;br /&gt;
| 2050&lt;br /&gt;
| 0802&lt;br /&gt;
| Kronos/C Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2051&lt;br /&gt;
| 0803&lt;br /&gt;
| Spartanics&lt;br /&gt;
|-&lt;br /&gt;
| 2052&lt;br /&gt;
| 0804&lt;br /&gt;
| Jochheim Computer Tuning&lt;br /&gt;
|-&lt;br /&gt;
| 2053&lt;br /&gt;
| 0805&lt;br /&gt;
| Trans Data Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2054&lt;br /&gt;
| 0806&lt;br /&gt;
| Applied Systems &amp;amp;amp; Peripherals Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2055&lt;br /&gt;
| 0807&lt;br /&gt;
| Checkpoint Technologies&lt;br /&gt;
| Originally registered to Amiga Solutions&lt;br /&gt;
|-&lt;br /&gt;
| 2056&lt;br /&gt;
| 0808&lt;br /&gt;
| Adept Development&lt;br /&gt;
|-&lt;br /&gt;
| 2057&lt;br /&gt;
| 0809&lt;br /&gt;
| Advanced Computer Design&lt;br /&gt;
|-&lt;br /&gt;
| 2058&lt;br /&gt;
| 080A&lt;br /&gt;
| Sir Netics&lt;br /&gt;
|-&lt;br /&gt;
| 2059&lt;br /&gt;
| 080B&lt;br /&gt;
| Expert Services&lt;br /&gt;
|-&lt;br /&gt;
| 2060&lt;br /&gt;
| 080C&lt;br /&gt;
| Digital Art Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2061&lt;br /&gt;
| 080D&lt;br /&gt;
| Adept Development&lt;br /&gt;
|-&lt;br /&gt;
| 2062&lt;br /&gt;
| 080E&lt;br /&gt;
| Expansion Technologies (Expansion Systems)&lt;br /&gt;
|-&lt;br /&gt;
| 2063&lt;br /&gt;
| 080F&lt;br /&gt;
| Alphatech&lt;br /&gt;
|-&lt;br /&gt;
| 2064&lt;br /&gt;
| 0810&lt;br /&gt;
| Edotronik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2065&lt;br /&gt;
| 0811&lt;br /&gt;
| California Access/Synergy&lt;br /&gt;
| Originally registered to Logical Design Works&lt;br /&gt;
|-&lt;br /&gt;
| 2066&lt;br /&gt;
| 0812&lt;br /&gt;
| Bowden, Williams, Full &amp;amp; Assoc.&lt;br /&gt;
|-&lt;br /&gt;
| 2067&lt;br /&gt;
| 0813&lt;br /&gt;
| NES, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2068&lt;br /&gt;
| 0814&lt;br /&gt;
| Amdev&lt;br /&gt;
|-&lt;br /&gt;
| 2069&lt;br /&gt;
| 0815&lt;br /&gt;
| Big Brother Security Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2070&lt;br /&gt;
| 0816&lt;br /&gt;
| Active Circuits Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2071&lt;br /&gt;
| 0817&lt;br /&gt;
| ICD, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2072&lt;br /&gt;
| 0818&lt;br /&gt;
| Multi-Meg Electronique&lt;br /&gt;
|-&lt;br /&gt;
| 2073&lt;br /&gt;
| 0819&lt;br /&gt;
| Kupke Computertechnik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2074&lt;br /&gt;
| 081A&lt;br /&gt;
| The Checkered Ball&lt;br /&gt;
|-&lt;br /&gt;
| 2075&lt;br /&gt;
| 081B&lt;br /&gt;
| Hi Tension Computer Services Ltd. (UK)&lt;br /&gt;
|-&lt;br /&gt;
| 2076&lt;br /&gt;
| 081C&lt;br /&gt;
| Alfa Data&lt;br /&gt;
| Originally assigned to Elmtech Research, Ltd. (UK)&lt;br /&gt;
|-&lt;br /&gt;
| 2077&lt;br /&gt;
| 081D&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
| Originally registered to Clartscreen, Ltd. (UK)&lt;br /&gt;
|-&lt;br /&gt;
| 2078&lt;br /&gt;
| 081E&lt;br /&gt;
| Interworks&lt;br /&gt;
|-&lt;br /&gt;
| 2079&lt;br /&gt;
| 081F&lt;br /&gt;
| Galysh Enterprises&lt;br /&gt;
|-&lt;br /&gt;
| 2080&lt;br /&gt;
| 0820&lt;br /&gt;
| Hardital Synthesis&lt;br /&gt;
| Originally registered to Realtime Games Software Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2081&lt;br /&gt;
| 0821&lt;br /&gt;
| GBS&lt;br /&gt;
|-&lt;br /&gt;
| 2082&lt;br /&gt;
| 0822&lt;br /&gt;
| Circum Design Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2083&lt;br /&gt;
| 0823&lt;br /&gt;
| Alberta Micro Electronic Center&lt;br /&gt;
|-&lt;br /&gt;
| 2084&lt;br /&gt;
| 0824&lt;br /&gt;
| Bestech&lt;br /&gt;
|-&lt;br /&gt;
| 2085&lt;br /&gt;
| 0825&lt;br /&gt;
| Lasar Fantasy&lt;br /&gt;
|-&lt;br /&gt;
| 2086&lt;br /&gt;
| 0826&lt;br /&gt;
| Pulsar&lt;br /&gt;
|-&lt;br /&gt;
| 2087&lt;br /&gt;
| 0827&lt;br /&gt;
| Ivis&lt;br /&gt;
|-&lt;br /&gt;
| 2088&lt;br /&gt;
| 0828&lt;br /&gt;
| Applied Engineering&lt;br /&gt;
|-&lt;br /&gt;
| 2089&lt;br /&gt;
| 0829&lt;br /&gt;
| Solid-State Design &amp;amp;amp; Development&lt;br /&gt;
|-&lt;br /&gt;
| 2090&lt;br /&gt;
| 082A&lt;br /&gt;
| Vison Quest&lt;br /&gt;
|-&lt;br /&gt;
| 2091&lt;br /&gt;
| 082B&lt;br /&gt;
| Seaview Software&lt;br /&gt;
|-&lt;br /&gt;
| 2092&lt;br /&gt;
| 082C&lt;br /&gt;
| BSC&lt;br /&gt;
| Mistakenly used by ADS (Advanced Development Software)&lt;br /&gt;
|-&lt;br /&gt;
| 2093&lt;br /&gt;
| 082D&lt;br /&gt;
| Bernd Culenfeld&lt;br /&gt;
|-&lt;br /&gt;
| 2094&lt;br /&gt;
| 082E&lt;br /&gt;
| American Liquid Light&lt;br /&gt;
|-&lt;br /&gt;
| 2095&lt;br /&gt;
| 082F&lt;br /&gt;
| CEGITES&lt;br /&gt;
|-&lt;br /&gt;
| 2096&lt;br /&gt;
| 0830&lt;br /&gt;
| Quadlite Computers Ltd.&lt;br /&gt;
| Originally registered to EV Industries&lt;br /&gt;
|-&lt;br /&gt;
| 2097&lt;br /&gt;
| 0831&lt;br /&gt;
| Silicon Peace&lt;br /&gt;
|-&lt;br /&gt;
| 2098&lt;br /&gt;
| 0832&lt;br /&gt;
| Black Belt Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2099&lt;br /&gt;
| 0833&lt;br /&gt;
| Village Tronic&lt;br /&gt;
| Originally registerd to Steve Yaeger&lt;br /&gt;
|-&lt;br /&gt;
| 2100&lt;br /&gt;
| 0834&lt;br /&gt;
| ReadySoft&lt;br /&gt;
|-&lt;br /&gt;
| 2101&lt;br /&gt;
| 0835&lt;br /&gt;
| Phoenix Micro Technologies&lt;br /&gt;
|-&lt;br /&gt;
| 2102&lt;br /&gt;
| 0836&lt;br /&gt;
| Advanced Systems &amp;amp; Software&lt;br /&gt;
| Orignally assigned to Preferred Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2103&lt;br /&gt;
| 0837&lt;br /&gt;
| Rombo Productions&lt;br /&gt;
|-&lt;br /&gt;
| 2104&lt;br /&gt;
| 0838&lt;br /&gt;
| Impulse Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2105&lt;br /&gt;
| 0839&lt;br /&gt;
| Beta Unlimited&lt;br /&gt;
|-&lt;br /&gt;
| 2106&lt;br /&gt;
| 083A&lt;br /&gt;
| Memory Expansion System, Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2107&lt;br /&gt;
| 083B&lt;br /&gt;
| Vortex Computer Systems GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2108&lt;br /&gt;
| 083C&lt;br /&gt;
| Platypus Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2109&lt;br /&gt;
| 083D&lt;br /&gt;
| Gigatron OHG&lt;br /&gt;
|-&lt;br /&gt;
| 2110&lt;br /&gt;
| 083E&lt;br /&gt;
| PG Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2111&lt;br /&gt;
| 083F&lt;br /&gt;
| New Technologies Group&lt;br /&gt;
|-&lt;br /&gt;
| 2112&lt;br /&gt;
| 0840&lt;br /&gt;
| Interactive Video Systems (IVS)&lt;br /&gt;
| Pacific Peripherals&lt;br /&gt;
|-&lt;br /&gt;
| 2113&lt;br /&gt;
| 0841&lt;br /&gt;
| Vector&lt;br /&gt;
| Originally registered to H. K. Computer&lt;br /&gt;
|-&lt;br /&gt;
| 2114&lt;br /&gt;
| 0842&lt;br /&gt;
| Pacific Digital&lt;br /&gt;
| Originally registered to C. H. Helfrich Elektronik&lt;br /&gt;
|-&lt;br /&gt;
| 2115&lt;br /&gt;
| 0843&lt;br /&gt;
| Xanadu&lt;br /&gt;
|-&lt;br /&gt;
| 2116&lt;br /&gt;
| 0844&lt;br /&gt;
| Pacific Digital&lt;br /&gt;
| Originally registered to AMS&lt;br /&gt;
|-&lt;br /&gt;
| 2117&lt;br /&gt;
| 0845&lt;br /&gt;
| X-Pert&lt;br /&gt;
|-&lt;br /&gt;
| 2118&lt;br /&gt;
| 0846&lt;br /&gt;
| The Amiga Centre&lt;br /&gt;
|-&lt;br /&gt;
| 2119&lt;br /&gt;
| 0847&lt;br /&gt;
| Digital Pacific&lt;br /&gt;
|-&lt;br /&gt;
| 2120&lt;br /&gt;
| 0848&lt;br /&gt;
| Solid State Leisure&lt;br /&gt;
|-&lt;br /&gt;
| 2121&lt;br /&gt;
| 0849&lt;br /&gt;
| Hydra Systems&lt;br /&gt;
| Originally registered to Analog Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2122&lt;br /&gt;
| 084A&lt;br /&gt;
| Cumana&lt;br /&gt;
|-&lt;br /&gt;
| 2123&lt;br /&gt;
| 084B&lt;br /&gt;
| KAPS 2C Conception&lt;br /&gt;
|-&lt;br /&gt;
| 2124&lt;br /&gt;
| 084C&lt;br /&gt;
| Mike Mason&lt;br /&gt;
|-&lt;br /&gt;
| 2125&lt;br /&gt;
| 084D&lt;br /&gt;
| For Your Eyes&lt;br /&gt;
|-&lt;br /&gt;
| 2126&lt;br /&gt;
| 084E&lt;br /&gt;
| Volkmar Breitfeld Computersysteme&lt;br /&gt;
|-&lt;br /&gt;
| 2127&lt;br /&gt;
| 084F&lt;br /&gt;
| Sunrize Industries&lt;br /&gt;
|-&lt;br /&gt;
| 2128&lt;br /&gt;
| 0850&lt;br /&gt;
| Scott Advanced Micro Designs&lt;br /&gt;
|-&lt;br /&gt;
| 2129&lt;br /&gt;
| 0851&lt;br /&gt;
| Digital Micronics&lt;br /&gt;
|-&lt;br /&gt;
| 2130&lt;br /&gt;
| 0852&lt;br /&gt;
| Alfa-Laval&lt;br /&gt;
|-&lt;br /&gt;
| 2131&lt;br /&gt;
| 0853&lt;br /&gt;
| Multigros A/S&lt;br /&gt;
|-&lt;br /&gt;
| 2132&lt;br /&gt;
| 0854&lt;br /&gt;
| Archos&lt;br /&gt;
|-&lt;br /&gt;
| 2133&lt;br /&gt;
| 0855&lt;br /&gt;
| Icom Simulations&lt;br /&gt;
|-&lt;br /&gt;
| 2134&lt;br /&gt;
| 0856&lt;br /&gt;
| Commodore Test Engineering Group&lt;br /&gt;
|-&lt;br /&gt;
| 2135&lt;br /&gt;
| 0857&lt;br /&gt;
| Microcreations&lt;br /&gt;
|-&lt;br /&gt;
| 2136&lt;br /&gt;
| 0858&lt;br /&gt;
| Shoestring Productions&lt;br /&gt;
|-&lt;br /&gt;
| 2137&lt;br /&gt;
| 0859&lt;br /&gt;
| Faberushi&lt;br /&gt;
|-&lt;br /&gt;
| 2138&lt;br /&gt;
| 085A&lt;br /&gt;
| Evesham Micro Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2139&lt;br /&gt;
| 085B&lt;br /&gt;
| Panagolin Laser Software&lt;br /&gt;
|-&lt;br /&gt;
| 2140&lt;br /&gt;
| 085C&lt;br /&gt;
| Thomas Rudloff&lt;br /&gt;
|-&lt;br /&gt;
| 2141&lt;br /&gt;
| 085D&lt;br /&gt;
| Daniel Hohabir&lt;br /&gt;
|-&lt;br /&gt;
| 2142&lt;br /&gt;
| 085E&lt;br /&gt;
| GfxBase, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2143&lt;br /&gt;
| 085F&lt;br /&gt;
| Axellabs&lt;br /&gt;
|-&lt;br /&gt;
| 2144&lt;br /&gt;
| 0860&lt;br /&gt;
| Roctec Electronics Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2145&lt;br /&gt;
| 0861&lt;br /&gt;
| Omega Datentechnik&lt;br /&gt;
|-&lt;br /&gt;
| 2146&lt;br /&gt;
| 0862&lt;br /&gt;
| Atlantis&lt;br /&gt;
|-&lt;br /&gt;
| 2147&lt;br /&gt;
| 0863&lt;br /&gt;
| Skytec Computers&lt;br /&gt;
|-&lt;br /&gt;
| 2148&lt;br /&gt;
| 0864&lt;br /&gt;
| Protar Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2149&lt;br /&gt;
| 0865&lt;br /&gt;
| ACS&lt;br /&gt;
|-&lt;br /&gt;
| 2150&lt;br /&gt;
| 0866&lt;br /&gt;
| Software Results Enterprises&lt;br /&gt;
| Originally registered to University of Illinois&lt;br /&gt;
|-&lt;br /&gt;
| 2151&lt;br /&gt;
| 0867&lt;br /&gt;
| Infinity Systems Design Group&lt;br /&gt;
|-&lt;br /&gt;
| 2152&lt;br /&gt;
| 0868&lt;br /&gt;
| Trade It&lt;br /&gt;
|-&lt;br /&gt;
| 2153&lt;br /&gt;
| 0869&lt;br /&gt;
| Suntec, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2154&lt;br /&gt;
| 086A&lt;br /&gt;
| DJW Micro Systems&lt;br /&gt;
| Originally registered to Tritec Marketing&lt;br /&gt;
|-&lt;br /&gt;
| 2155&lt;br /&gt;
| 086B&lt;br /&gt;
| Power Computing Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2156&lt;br /&gt;
| 086C&lt;br /&gt;
| MacroSystems&lt;br /&gt;
|-&lt;br /&gt;
| 2157&lt;br /&gt;
| 086D&lt;br /&gt;
| Masoboshi GmbH (DCE)&lt;br /&gt;
|-&lt;br /&gt;
| 2158&lt;br /&gt;
| 086E&lt;br /&gt;
| HAL Software Hardware Handel&lt;br /&gt;
|-&lt;br /&gt;
| 2159&lt;br /&gt;
| 086F&lt;br /&gt;
| Mainhattan Data&lt;br /&gt;
| Originally registered to Michael Lamm Computersysteme&lt;br /&gt;
|-&lt;br /&gt;
| 2160&lt;br /&gt;
| 0870&lt;br /&gt;
| Digital Processing System&lt;br /&gt;
| Originally registered to bbdp Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2161&lt;br /&gt;
| 0871&lt;br /&gt;
| Blue Ribbon Soundworks&lt;br /&gt;
| Originally registered to Design Computer Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2162&lt;br /&gt;
| 0872&lt;br /&gt;
| XPert&lt;br /&gt;
| Originally registered to The Station&lt;br /&gt;
|-&lt;br /&gt;
| 2163&lt;br /&gt;
| 0873&lt;br /&gt;
| DelaComp&lt;br /&gt;
| Originally registered to Bryan Williams&lt;br /&gt;
|-&lt;br /&gt;
| 2164&lt;br /&gt;
| 0874&lt;br /&gt;
| Superformance Computer Engineering GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2165&lt;br /&gt;
| 0875&lt;br /&gt;
| Overland Engineering&lt;br /&gt;
|-&lt;br /&gt;
| 2166&lt;br /&gt;
| 0876&lt;br /&gt;
| Thomas Hamren&lt;br /&gt;
|-&lt;br /&gt;
| 2167&lt;br /&gt;
| 0877&lt;br /&gt;
| Village Tronic&lt;br /&gt;
|-&lt;br /&gt;
| 2168&lt;br /&gt;
| 0878&lt;br /&gt;
| Toolbox Design&lt;br /&gt;
|-&lt;br /&gt;
| 2169&lt;br /&gt;
| 0879&lt;br /&gt;
| Digital Processing System&lt;br /&gt;
|-&lt;br /&gt;
| 2170&lt;br /&gt;
| 087A&lt;br /&gt;
| Superformance&lt;br /&gt;
|-&lt;br /&gt;
| 2171&lt;br /&gt;
| 087B&lt;br /&gt;
| Utilities Unlimited&lt;br /&gt;
|-&lt;br /&gt;
| 2172&lt;br /&gt;
| 087C&lt;br /&gt;
| phase 5&lt;br /&gt;
|-&lt;br /&gt;
| 2173&lt;br /&gt;
| 087D&lt;br /&gt;
| Juergen Kommos&lt;br /&gt;
|-&lt;br /&gt;
| 2174&lt;br /&gt;
| 087E&lt;br /&gt;
| Electronic Design&lt;br /&gt;
|-&lt;br /&gt;
| 2175&lt;br /&gt;
| 087F&lt;br /&gt;
| James Cook University of North Queensland&lt;br /&gt;
|-&lt;br /&gt;
| 2176&lt;br /&gt;
| 0880&lt;br /&gt;
| AmiTrix Development&lt;br /&gt;
|-&lt;br /&gt;
| 2177&lt;br /&gt;
| 0881&lt;br /&gt;
| Ferranti&lt;br /&gt;
|-&lt;br /&gt;
| 2178&lt;br /&gt;
| 0882&lt;br /&gt;
| Leviathan Development&lt;br /&gt;
|-&lt;br /&gt;
| 2179&lt;br /&gt;
| 0883&lt;br /&gt;
| United Video Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2180&lt;br /&gt;
| 0884&lt;br /&gt;
| GPSoft Pty. Ltd.&lt;br /&gt;
| Originally registered to Juergen Kommos&lt;br /&gt;
|-&lt;br /&gt;
| 2181&lt;br /&gt;
| 0885&lt;br /&gt;
| ArMAX&lt;br /&gt;
| Oliver Bausch&lt;br /&gt;
|-&lt;br /&gt;
| 2182&lt;br /&gt;
| 0886&lt;br /&gt;
| CP Computer&lt;br /&gt;
|-&lt;br /&gt;
| 2183&lt;br /&gt;
| 0887&lt;br /&gt;
| AMOK - Amiga Module &amp;amp;amp; Oberon Klub&lt;br /&gt;
|-&lt;br /&gt;
| 2184&lt;br /&gt;
| 0888&lt;br /&gt;
| ITEK Neser &amp;amp;amp; Sieber GbR&lt;br /&gt;
|-&lt;br /&gt;
| 2185&lt;br /&gt;
| 0889&lt;br /&gt;
| Phillip C. Lello&lt;br /&gt;
|-&lt;br /&gt;
| 2186&lt;br /&gt;
| 088A&lt;br /&gt;
| Cyborg Design Services&lt;br /&gt;
|-&lt;br /&gt;
| 2187&lt;br /&gt;
| 088B&lt;br /&gt;
| G2 Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2188&lt;br /&gt;
| 088C&lt;br /&gt;
| Pro System Computersysteme&lt;br /&gt;
|-&lt;br /&gt;
| 2189&lt;br /&gt;
| 088D&lt;br /&gt;
| ZEUS Electronic&lt;br /&gt;
| Originally registered to MSPI (Markt &amp;amp;amp; Technik)&lt;br /&gt;
|-&lt;br /&gt;
| 2190&lt;br /&gt;
| 088E&lt;br /&gt;
| Altatech&lt;br /&gt;
|-&lt;br /&gt;
| 2191&lt;br /&gt;
| 088F&lt;br /&gt;
| NewTek&lt;br /&gt;
|-&lt;br /&gt;
| 2192&lt;br /&gt;
| 0890&lt;br /&gt;
| M-TEC Hardware Design&lt;br /&gt;
| Originally registered to Hardware Design Udo Neuroth&lt;br /&gt;
|-&lt;br /&gt;
| 2193&lt;br /&gt;
| 0891&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
| Originally registered to Viona Development&lt;br /&gt;
|-&lt;br /&gt;
| 2194&lt;br /&gt;
| 0892&lt;br /&gt;
| Amitek&lt;br /&gt;
| Originally assigned to Marpet Developments&lt;br /&gt;
|-&lt;br /&gt;
| 2195&lt;br /&gt;
| 0893&lt;br /&gt;
| Ingenieurbuero Helfrich&lt;br /&gt;
|-&lt;br /&gt;
| 2196&lt;br /&gt;
| 0894&lt;br /&gt;
| The Neo Group&lt;br /&gt;
|-&lt;br /&gt;
| 2197&lt;br /&gt;
| 0895&lt;br /&gt;
| Cyon&lt;br /&gt;
|-&lt;br /&gt;
| 2198&lt;br /&gt;
| 0896&lt;br /&gt;
| Bob Research Group&lt;br /&gt;
|-&lt;br /&gt;
| 2199&lt;br /&gt;
| 0897&lt;br /&gt;
| Richmond Sound Design Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2200&lt;br /&gt;
| 0898&lt;br /&gt;
| US Cybernetics&lt;br /&gt;
|-&lt;br /&gt;
| 2201&lt;br /&gt;
| 0899&lt;br /&gt;
| Fulvio Ieva&lt;br /&gt;
|-&lt;br /&gt;
| 2202&lt;br /&gt;
| 089A&lt;br /&gt;
| Silicon Studio&lt;br /&gt;
|-&lt;br /&gt;
| 2203&lt;br /&gt;
| 089B&lt;br /&gt;
| MacroSystems (USA)&lt;br /&gt;
| Was named Micro System Devices&lt;br /&gt;
|-&lt;br /&gt;
| 2204&lt;br /&gt;
| 089C&lt;br /&gt;
| Conspector Entertainment&lt;br /&gt;
|-&lt;br /&gt;
| 2205&lt;br /&gt;
| 089D&lt;br /&gt;
| Laserforum&lt;br /&gt;
|-&lt;br /&gt;
| 2206&lt;br /&gt;
| 089E&lt;br /&gt;
| Elbox Computer&lt;br /&gt;
| Mistakenly used by Index Information Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2207&lt;br /&gt;
| 089F&lt;br /&gt;
| Applied Magic Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2208&lt;br /&gt;
| 08A0&lt;br /&gt;
| SDL Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2560&lt;br /&gt;
| 0A00&lt;br /&gt;
| Harms&lt;br /&gt;
|-&lt;br /&gt;
| 2588&lt;br /&gt;
| 0A1C&lt;br /&gt;
| A1K.org Community&lt;br /&gt;
|-&lt;br /&gt;
| 2640&lt;br /&gt;
| 0A50&lt;br /&gt;
| Micronik&lt;br /&gt;
|-&lt;br /&gt;
| 2782&lt;br /&gt;
| 2782&lt;br /&gt;
| OA Design&lt;br /&gt;
|-&lt;br /&gt;
| 3084&lt;br /&gt;
| 0C0C&lt;br /&gt;
| Team 4&lt;br /&gt;
|-&lt;br /&gt;
| 3643&lt;br /&gt;
| 0E3B&lt;br /&gt;
| E3B&lt;br /&gt;
| Michael Boehmer&lt;br /&gt;
|-&lt;br /&gt;
| 3855&lt;br /&gt;
| 0F0F&lt;br /&gt;
| Micronik&lt;br /&gt;
|-&lt;br /&gt;
| 4096&lt;br /&gt;
| 1000&lt;br /&gt;
| MegaMicro&lt;br /&gt;
|-&lt;br /&gt;
| 4110&lt;br /&gt;
| 100E&lt;br /&gt;
| DigiFeX&lt;br /&gt;
|-&lt;br /&gt;
| 4136&lt;br /&gt;
| 1028&lt;br /&gt;
| Imtronics/Memphis&lt;br /&gt;
|-&lt;br /&gt;
| 4149&lt;br /&gt;
| 1035&lt;br /&gt;
| PROTAR&lt;br /&gt;
|-&lt;br /&gt;
| 4369&lt;br /&gt;
| 1111&lt;br /&gt;
| Frank Strauß Elektronik&lt;br /&gt;
| Also used by Kupke&lt;br /&gt;
|-&lt;br /&gt;
| 4626&lt;br /&gt;
| 1212&lt;br /&gt;
| Individual Computers&lt;br /&gt;
|-&lt;br /&gt;
| 4648&lt;br /&gt;
| 1228&lt;br /&gt;
| Flesch Hornemann Computer Elec.&lt;br /&gt;
|-&lt;br /&gt;
| 4680&lt;br /&gt;
| 1248&lt;br /&gt;
| Kupke Computertechnik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 4711&lt;br /&gt;
| 1267&lt;br /&gt;
| RBM digitaltechnik&lt;br /&gt;
|-&lt;br /&gt;
| 4754&lt;br /&gt;
| 1292&lt;br /&gt;
| MacroSystems&lt;br /&gt;
|-&lt;br /&gt;
| 5000&lt;br /&gt;
| 1388&lt;br /&gt;
| ITH&lt;br /&gt;
|-&lt;br /&gt;
| 5001&lt;br /&gt;
| 1389&lt;br /&gt;
| VMC&lt;br /&gt;
|-&lt;br /&gt;
| 5010&lt;br /&gt;
| 1392&lt;br /&gt;
| Ambience Creation Technology&lt;br /&gt;
|-&lt;br /&gt;
| 5011&lt;br /&gt;
| 1393&lt;br /&gt;
| Creative Development&lt;br /&gt;
|-&lt;br /&gt;
| 5012&lt;br /&gt;
| 1394&lt;br /&gt;
| Georg Braun&lt;br /&gt;
|-&lt;br /&gt;
| 5013&lt;br /&gt;
| 1395&lt;br /&gt;
| Swedish User Group of Amiga&lt;br /&gt;
|-&lt;br /&gt;
| 5014&lt;br /&gt;
| 1396&lt;br /&gt;
| Jakub Bednarski&lt;br /&gt;
|-&lt;br /&gt;
| 5015&lt;br /&gt;
| 1397&lt;br /&gt;
| KryoFlux, Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 5016&lt;br /&gt;
| 1398&lt;br /&gt;
| Igor Majstorovic&lt;br /&gt;
|-&lt;br /&gt;
| 5017&lt;br /&gt;
| 1399&lt;br /&gt;
| Alastair M. Robinson&lt;br /&gt;
|-&lt;br /&gt;
| 5018&lt;br /&gt;
| 139A&lt;br /&gt;
| Austex Software&lt;br /&gt;
|-&lt;br /&gt;
| 5019&lt;br /&gt;
| 139B&lt;br /&gt;
| Sören Gust&lt;br /&gt;
|-&lt;br /&gt;
| 5020&lt;br /&gt;
| 139C&lt;br /&gt;
| Rok Krajnc&lt;br /&gt;
|-&lt;br /&gt;
| 5030&lt;br /&gt;
| 13A6&lt;br /&gt;
| Tim Tashpulatov&lt;br /&gt;
|-&lt;br /&gt;
| 5040&lt;br /&gt;
| 13B0&lt;br /&gt;
| 7-bit&lt;br /&gt;
|-&lt;br /&gt;
| 5050&lt;br /&gt;
| 13BA&lt;br /&gt;
| Sakura IT&lt;br /&gt;
|-&lt;br /&gt;
| 5060&lt;br /&gt;
| 13C4&lt;br /&gt;
| FPGAArcade&lt;br /&gt;
|-&lt;br /&gt;
| 5070&lt;br /&gt;
| 13CE&lt;br /&gt;
| CancerSoft Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 5080&lt;br /&gt;
| 13D8&lt;br /&gt;
| Stephen Leary&lt;br /&gt;
|-&lt;br /&gt;
| 5090&lt;br /&gt;
| 13E2&lt;br /&gt;
| DMA Softlab LLC&lt;br /&gt;
|-&lt;br /&gt;
| 5100&lt;br /&gt;
| 13EC&lt;br /&gt;
| Brookhouse Engineering&lt;br /&gt;
|-&lt;br /&gt;
| 5110&lt;br /&gt;
| 13F6&lt;br /&gt;
| Eduardo Arana&lt;br /&gt;
|-&lt;br /&gt;
| 5120&lt;br /&gt;
| 1400&lt;br /&gt;
| CS-LAB&lt;br /&gt;
|-&lt;br /&gt;
| 5130&lt;br /&gt;
| 140A&lt;br /&gt;
| Robert Miranda&lt;br /&gt;
|-&lt;br /&gt;
| 5140&lt;br /&gt;
| 1414&lt;br /&gt;
| RastPort&lt;br /&gt;
|-&lt;br /&gt;
| 5132&lt;br /&gt;
| 140C&lt;br /&gt;
| UAS Interface Ltd6&lt;br /&gt;
|-&lt;br /&gt;
| 5150&lt;br /&gt;
| 141E&lt;br /&gt;
| Amiga Kit&lt;br /&gt;
|-&lt;br /&gt;
| 5160&lt;br /&gt;
| 1428&lt;br /&gt;
| Central Texas Commodore User Group&lt;br /&gt;
|-&lt;br /&gt;
| 5170&lt;br /&gt;
| 1432&lt;br /&gt;
| Confusion Research Center&lt;br /&gt;
|-&lt;br /&gt;
| 5180&lt;br /&gt;
| 143C&lt;br /&gt;
| Solar Soyuz Zaibatsu&lt;br /&gt;
|-&lt;br /&gt;
| 5190&lt;br /&gt;
| 1446&lt;br /&gt;
| BooBip&lt;br /&gt;
|-&lt;br /&gt;
| 5191&lt;br /&gt;
| 1447&lt;br /&gt;
| Matthias Hampel&lt;br /&gt;
|-&lt;br /&gt;
| 5192&lt;br /&gt;
| 1448&lt;br /&gt;
| dec0de Consulting Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 5193&lt;br /&gt;
| 1449&lt;br /&gt;
| Puppy Concepts&lt;br /&gt;
|-&lt;br /&gt;
| 5194&lt;br /&gt;
| 144A&lt;br /&gt;
| Open Amiga Hardware Repository&lt;br /&gt;
|-&lt;br /&gt;
| 5195&lt;br /&gt;
| 144B&lt;br /&gt;
| Double H Tech&lt;br /&gt;
|-&lt;br /&gt;
| 5196&lt;br /&gt;
| 144C&lt;br /&gt;
| Retromatik&lt;br /&gt;
|-&lt;br /&gt;
| 5500&lt;br /&gt;
| 157C&lt;br /&gt;
| Inhouse Information&lt;br /&gt;
|-&lt;br /&gt;
| 5768&lt;br /&gt;
| 1688&lt;br /&gt;
| Bio Con&lt;br /&gt;
|-&lt;br /&gt;
| 6148&lt;br /&gt;
| 1804&lt;br /&gt;
| HK-Computer&lt;br /&gt;
|-&lt;br /&gt;
| 6502&lt;br /&gt;
| 1966&lt;br /&gt;
| Cloanto&lt;br /&gt;
|-&lt;br /&gt;
| 6520&lt;br /&gt;
| 1978&lt;br /&gt;
| Oliver Gantert&lt;br /&gt;
|-&lt;br /&gt;
| 7777&lt;br /&gt;
| 1E61&lt;br /&gt;
| Rafal Gabriel Chyla&lt;br /&gt;
|-&lt;br /&gt;
| 8215&lt;br /&gt;
| 2017&lt;br /&gt;
| Vortex&lt;br /&gt;
|-&lt;br /&gt;
| 8244&lt;br /&gt;
| 2034&lt;br /&gt;
| Spirit Technology&lt;br /&gt;
|-&lt;br /&gt;
| 8290&lt;br /&gt;
| 2062&lt;br /&gt;
| Expansion Systems&lt;br /&gt;
|-&lt;br /&gt;
| 8448&lt;br /&gt;
| 2100&lt;br /&gt;
| ReadySoft&lt;br /&gt;
|-&lt;br /&gt;
| 8512&lt;br /&gt;
| 2140&lt;br /&gt;
| Phase 5 Digital Products&lt;br /&gt;
|-&lt;br /&gt;
| 8553&lt;br /&gt;
| 2169&lt;br /&gt;
| Digital Processing Systems Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 8704&lt;br /&gt;
| 2200&lt;br /&gt;
| ACT Elektronik&lt;br /&gt;
|-&lt;br /&gt;
| 8738&lt;br /&gt;
| 2222&lt;br /&gt;
| ACT Elektronik&lt;br /&gt;
|-&lt;br /&gt;
| 9512&lt;br /&gt;
| 2528&lt;br /&gt;
| Tower Technologies&lt;br /&gt;
|-&lt;br /&gt;
| 10676&lt;br /&gt;
| 29B4&lt;br /&gt;
| Electronic Design&lt;br /&gt;
|-&lt;br /&gt;
| 14195&lt;br /&gt;
| 3773&lt;br /&gt;
| Media-net-Point&lt;br /&gt;
|-&lt;br /&gt;
| 14501&lt;br /&gt;
| 38A5&lt;br /&gt;
| Petsoff, Finland&lt;br /&gt;
|-&lt;br /&gt;
| 16375&lt;br /&gt;
| 3FF7&lt;br /&gt;
| Uwe Gerlach&lt;br /&gt;
|-&lt;br /&gt;
| 16707&lt;br /&gt;
| 4143&lt;br /&gt;
| Ateo Concepts&lt;br /&gt;
|-&lt;br /&gt;
| 16708&lt;br /&gt;
| 4144&lt;br /&gt;
| ALiENDESiGN&lt;br /&gt;
|-&lt;br /&gt;
| 16945&lt;br /&gt;
| 4231&lt;br /&gt;
| A.C.T.&lt;br /&gt;
|-&lt;br /&gt;
| 17740&lt;br /&gt;
| 454C&lt;br /&gt;
| HK-Computer (ELSAT)&lt;br /&gt;
|-&lt;br /&gt;
| 18260&lt;br /&gt;
| 4754&lt;br /&gt;
| MacroSystems (Germany)&lt;br /&gt;
|-&lt;br /&gt;
| 19796&lt;br /&gt;
| 4D54&lt;br /&gt;
| Markt &amp;amp; Technik&lt;br /&gt;
|-&lt;br /&gt;
| 22359&lt;br /&gt;
| 5757&lt;br /&gt;
| Markt &amp;amp; Technik&lt;br /&gt;
|-&lt;br /&gt;
| 26464&lt;br /&gt;
| 6760&lt;br /&gt;
| Combitec&lt;br /&gt;
|-&lt;br /&gt;
| 26470&lt;br /&gt;
| 6766&lt;br /&gt;
| Combitec&lt;br /&gt;
|-&lt;br /&gt;
| 28014&lt;br /&gt;
| 6D6E&lt;br /&gt;
| MNT Media and Technology UG&lt;br /&gt;
|-&lt;br /&gt;
| 32768&lt;br /&gt;
| 8000&lt;br /&gt;
| M.A.S.T.&lt;br /&gt;
|-&lt;br /&gt;
| 42240&lt;br /&gt;
| A500&lt;br /&gt;
| Aethreum Digital&lt;br /&gt;
|-&lt;br /&gt;
| 43437&lt;br /&gt;
| A9AD&lt;br /&gt;
| Reis-Ware&lt;br /&gt;
|-&lt;br /&gt;
| 43521&lt;br /&gt;
| AA01&lt;br /&gt;
| Cameron&lt;br /&gt;
|-&lt;br /&gt;
| 43537&lt;br /&gt;
| AA11&lt;br /&gt;
| Reis-Ware&lt;br /&gt;
|-&lt;br /&gt;
| 44359&lt;br /&gt;
| AD47&lt;br /&gt;
| Matay&lt;br /&gt;
|-&lt;br /&gt;
| 46504&lt;br /&gt;
| B5A8&lt;br /&gt;
| Phoenix&lt;br /&gt;
|-&lt;br /&gt;
| 48879&lt;br /&gt;
| BEEF&lt;br /&gt;
| Swiss Mountain Dog Products&lt;br /&gt;
|-&lt;br /&gt;
| 49160&lt;br /&gt;
| C008&lt;br /&gt;
| Combitec&lt;br /&gt;
|-&lt;br /&gt;
| 61453&lt;br /&gt;
| F00D&lt;br /&gt;
| Forefront Technologies Inc.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
For any changes/additions to this registry see [[#How_to_Obtain_a_Manufacturer_Number|How to Obtain a Manufacturer Number]]&lt;/div&gt;</summary>
		<author><name>Costel Mincea</name></author>
	</entry>
	<entry>
		<id>https://wiki.amigaos.net/w/index.php?title=Amiga_Hardware_Manufacturer_ID_Registry&amp;diff=12601</id>
		<title>Amiga Hardware Manufacturer ID Registry</title>
		<link rel="alternate" type="text/html" href="https://wiki.amigaos.net/w/index.php?title=Amiga_Hardware_Manufacturer_ID_Registry&amp;diff=12601"/>
		<updated>2026-09-08T11:08:52Z</updated>

		<summary type="html">&lt;p&gt;Costel Mincea: Added 2782 Oliver Achten&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
= How to Obtain a Manufacturer Number =&lt;br /&gt;
&lt;br /&gt;
Manufacturer&#039;s numbers are assigned by the AmigaOS development team. To obtain your unique manufacturer number send a support request to [mailto:support@hyperion-entertainment.com support@hyperion-entertainment.com] including these information:&lt;br /&gt;
&lt;br /&gt;
 1. The name of the company or person which the number is assigned to&lt;br /&gt;
 &lt;br /&gt;
 2. Postal address/contact address&lt;br /&gt;
 &lt;br /&gt;
 3. Name of the contact person, with a corresponding e-mail address&lt;br /&gt;
 &lt;br /&gt;
 4. A brief description of the kind of products you want to produce&lt;br /&gt;
&lt;br /&gt;
= Your Manufacturer Number =&lt;br /&gt;
&lt;br /&gt;
Attention hardware manufacturers. If you are developing a hardware expansion product for the Classic Amiga (e.g. 500, 2000, 3000) then you will need to obtain a special manufacturer ID number from the AmigaOS development team to identify your product. This manufacturer number is used by the Amiga to link your hardware with its driver software at boot time.&lt;br /&gt;
&lt;br /&gt;
Your manufacturer number is part of the special protocol that the Amiga uses to automatically configure all expansion devices on the bus without the user having to cut jumpers or adjust dip switches. This is called auto-config.&lt;br /&gt;
&lt;br /&gt;
At start-up time, the system first polls each board in the system and assigns the board its own address space. If it is a memory board, its RAM is linked into the memory free pool. Later in the boot sequence, after DOS is initialized, the binddrivers program is run. Binddrivers will search the directory SYS:Expansion for the drivers that go with the boards.&lt;br /&gt;
&lt;br /&gt;
To do this binddrivers looks in the Tool Type field of all icon files in SYS:Expansion. If the first seven bytes of the Tool Type field are &amp;quot;PRODUCT&amp;quot;, then this is an icon file for a driver.&lt;br /&gt;
&lt;br /&gt;
Binddrivers will then attempt to match the drivers it has found with the boards that were found earlier. This is where your manufacturer number comes in.&lt;br /&gt;
&lt;br /&gt;
Your manufacturer number goes in two places. First, it is burned in hex form into the PAL which is part of ALL auto-config expansion products. Second, it appears in ASCII in the Tool Type field of the icon file for your product&#039;s driver. By matching these two numbers, the Amiga can automatically configure your board and bind it&#039;s software driver into the system as well.&lt;br /&gt;
&lt;br /&gt;
The manufacturer&#039;s number is a 16-bit ID which appears in PAL offsets $10-$17. There is also an 8-bit product number which you assign. The product number is for uniquely identifying different products from the same vendor. The product number will appear in PAL offsets $04-$07. This gives you a total of 24 bits to identify each of your products.&lt;br /&gt;
&lt;br /&gt;
These 24 bits of information in the PAL which identify your product are matched against the information in the Tool Type field of all icon files in the SYS:Expansion drawer. For example, suppose you are manufacturer #1019. You have two products, #1 and #2 which both use the same driver. The icon for your driver for these two products would have a Tool Type set to &amp;quot;PRODUCT=1019/1|1019/2&amp;quot;. This means: I am an icon for a driver that works with product number 1 or 2 from manufacturer 1019, now bind me. Spaces are not legal. Here are two other examples:&lt;br /&gt;
&lt;br /&gt;
; PRODUCT=1208/11&lt;br /&gt;
: is the Tool Type for a driver for product 11 from manufacturer number 1208.&lt;br /&gt;
&lt;br /&gt;
; PRODUCT=1017&lt;br /&gt;
: is the Tool Type for a driver for any product from manufacturer number 1017.&lt;br /&gt;
&lt;br /&gt;
For an informal explanation of the auto-configuration process, see the chapter on Software Expansion Architecture from the 2nd Annual Amiga Developer&#039;s Conference Notes (available on ADCD 2.1). For the details of timing, power, the PAL equations and PAL address specifications and the expansion library documentation, see sections 3.1 to 3.3 of the A500/A2000 Technical Reference Manual. The original auto-config spec appears in the A1000 Schematics and Expansion Specification.&lt;br /&gt;
&lt;br /&gt;
The auto-config process makes the addition of expansion products to the system very easy. All the user has to do is put the board in any slot and copy the driver from the release disk to his own SYS:Expansion drawer. Everything else is automatic. There are no jumpers or dip switches to set. Best of all, you will get a lot less support calls asking how to make your product work with the XYZ-Corp-battery-backed-clock.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
&lt;br /&gt;
Some notes on hardware manufacturer ID assignment.&lt;br /&gt;
&lt;br /&gt;
* Manufacturer ID numbers are assigned free of charge.&lt;br /&gt;
* Please provide the following information when requesting an ID:&lt;br /&gt;
*# Name of the company or person&lt;br /&gt;
*# Postal address/contact address&lt;br /&gt;
*# Name of the contact person, with a corresponding e-mail address&lt;br /&gt;
*# A brief description of the kind of products you want to produce&lt;br /&gt;
* All ID numbers smaller than 5000 must be considered unsafe because no information exists on which numbers exactly were taken during the time Commodore, Inc. disintegrated.&lt;br /&gt;
* ID numbers in the range 8192 to 18841 must be considered unsafe because some hardware developers mistook the numbers assigned to them to be given in hexadecimal format. Hence 0x2000 = 8192 and 0x4999 = 18841.&lt;br /&gt;
&lt;br /&gt;
= Example code =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
/*-----------------------------------------------*/&lt;br /&gt;
/* Here is a short program which will tell you   */&lt;br /&gt;
/* about the expansion boards configured in your */&lt;br /&gt;
/* system without you opening up the machine.    */&lt;br /&gt;
/* Code by Bill Koester of CATS                  */&lt;br /&gt;
/*-----------------------------------------------*/&lt;br /&gt;
#include &amp;lt;libraries/configvars.h&amp;gt;&lt;br /&gt;
#include &amp;lt;libraries/expansion.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
struct ExpansionBase *ExpansionBase;&lt;br /&gt;
&lt;br /&gt;
void cleanup();&lt;br /&gt;
void printdev();&lt;br /&gt;
&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
   struct ConfigDev *MyConfigDev;&lt;br /&gt;
&lt;br /&gt;
   /*----------------------------------*/&lt;br /&gt;
   /* Open the expansion library,      */&lt;br /&gt;
   /* if there is a problem then exit  */&lt;br /&gt;
   /*----------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   ExpansionBase =(struct ExpansionBase *) OpenLibrary(EXPANSIONNAME,0);&lt;br /&gt;
   if(ExpansionBase==NULL)&lt;br /&gt;
   {&lt;br /&gt;
      printf(&amp;quot;Error opening expansion library!!\n&amp;quot;);&lt;br /&gt;
      cleanup();&lt;br /&gt;
      exit(0);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   /*--------------------------------------------*/&lt;br /&gt;
   /* Use FindConfigDev to get info on the first */&lt;br /&gt;
   /* expansion board on the list maintained by  */&lt;br /&gt;
   /* Exec.  If there are no expansion boards in */&lt;br /&gt;
   /* the system then exit.                      */&lt;br /&gt;
   /*--------------------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   MyConfigDev = NULL;&lt;br /&gt;
&lt;br /&gt;
  /*--------------------------------------------------*/&lt;br /&gt;
  /* FindConfigDev(oldConfigDev,manufacturer,product) */&lt;br /&gt;
  /* oldConfigDev = NULL for the top of the list      */&lt;br /&gt;
  /* manufacturer = -1 for any manufacturer           */&lt;br /&gt;
  /* product      = -1 for any product                */&lt;br /&gt;
  /*--------------------------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   MyConfigDev = FindConfigDev(NULL,-1,-1);&lt;br /&gt;
&lt;br /&gt;
   if(MyConfigDev==NULL)&lt;br /&gt;
   {&lt;br /&gt;
      printf(&amp;quot;No Configured Devices found!!\n&amp;quot;);&lt;br /&gt;
      cleanup();&lt;br /&gt;
      exit(0);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   printdev(MyConfigDev);&lt;br /&gt;
&lt;br /&gt;
   /*-----------------------------------*/&lt;br /&gt;
   /* OK, there is at least one board,  */&lt;br /&gt;
   /* so loop and get the entire list   */&lt;br /&gt;
   /* printing as we go with printdev() */&lt;br /&gt;
   /*-----------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   while(MyConfigDev = FindConfigDev(MyConfigDev,-1,-1))&lt;br /&gt;
   {&lt;br /&gt;
      printdev(MyConfigDev);&lt;br /&gt;
   }&lt;br /&gt;
   cleanup();&lt;br /&gt;
   return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*-------------------*/&lt;br /&gt;
/* Close up shop...  */&lt;br /&gt;
/*-------------------*/&lt;br /&gt;
void cleanup()&lt;br /&gt;
{&lt;br /&gt;
   if(ExpansionBase)&lt;br /&gt;
      CloseLibrary(ExpansionBase);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*----------------------------------*/&lt;br /&gt;
/* Print out the contents of the    */&lt;br /&gt;
/* dev structure for this expansion */&lt;br /&gt;
/* product.                         */&lt;br /&gt;
/*----------------------------------*/&lt;br /&gt;
&lt;br /&gt;
void printdev(dev)&lt;br /&gt;
struct ConfigDev *dev;&lt;br /&gt;
{&lt;br /&gt;
   char buff[200];&lt;br /&gt;
&lt;br /&gt;
   printf(&amp;quot;Flags          = &amp;quot;);&lt;br /&gt;
   if(dev-&amp;gt;cd_Flags==NULL)&lt;br /&gt;
      printf(&amp;quot;NULL  &amp;quot;);&lt;br /&gt;
   if(dev-&amp;gt;cd_Flags&amp;amp;CDF_SHUTUP)&lt;br /&gt;
      printf(&amp;quot;CDF_SHUTUP  &amp;quot;);&lt;br /&gt;
   if(dev-&amp;gt;cd_Flags&amp;amp;CDF_CONFIGME)&lt;br /&gt;
      printf(&amp;quot;CDF_CONFIGME  &amp;quot;);&lt;br /&gt;
   printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
   printf(&amp;quot;Board Address  = %x\n&amp;quot;,dev-&amp;gt;cd_BoardAddr);&lt;br /&gt;
   printf(&amp;quot;Board Size     = %d bytes\n&amp;quot;,dev-&amp;gt;cd_BoardSize);&lt;br /&gt;
   printf(&amp;quot;Slot  Address  = %d\n&amp;quot;,dev-&amp;gt;cd_SlotAddr);&lt;br /&gt;
   printf(&amp;quot;Slot  Size     = %d\n&amp;quot;,dev-&amp;gt;cd_SlotSize);&lt;br /&gt;
   printf(&amp;quot;Driver code at   %x\n&amp;quot;,dev-&amp;gt;cd_Driver);&lt;br /&gt;
&lt;br /&gt;
   printf(&amp;quot;er_Type         = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Type);&lt;br /&gt;
   printf(&amp;quot;er_Product      = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Product);&lt;br /&gt;
   printf(&amp;quot;er_Flags        = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Flags);&lt;br /&gt;
   printf(&amp;quot;er_Reserved03   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved03);&lt;br /&gt;
   printf(&amp;quot;er_Manufacturer = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Manufacturer);&lt;br /&gt;
   printf(&amp;quot;er_SerialNumber = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_SerialNumber);&lt;br /&gt;
   printf(&amp;quot;er_InitDiagVec  = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_InitDiagVec);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0c   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0c);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0d   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0d);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0e   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0e);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0f   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0f);&lt;br /&gt;
&lt;br /&gt;
   printf(&amp;quot;Hit Return to continue:\n&amp;quot;);&lt;br /&gt;
   gets(buff);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Registry =&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! ID (decimal)&lt;br /&gt;
! ID (hexadecimal)&lt;br /&gt;
! Manufacturer&lt;br /&gt;
! Notes&lt;br /&gt;
|-&lt;br /&gt;
| 1&lt;br /&gt;
| 0001&lt;br /&gt;
| Micronik&lt;br /&gt;
|-&lt;br /&gt;
| 211&lt;br /&gt;
| 00D3&lt;br /&gt;
| Pacific Peripherals/Profex&lt;br /&gt;
|-&lt;br /&gt;
| 221&lt;br /&gt;
| 00DD&lt;br /&gt;
| Kupke Computertechnik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 256&lt;br /&gt;
| 0100&lt;br /&gt;
| Memphis&lt;br /&gt;
| Originally registered to MacroSystems US&lt;br /&gt;
|-&lt;br /&gt;
| 512&lt;br /&gt;
| 0200&lt;br /&gt;
| 3-State Computertechnik&lt;br /&gt;
|-&lt;br /&gt;
| 513&lt;br /&gt;
| 0201&lt;br /&gt;
| Commodore (Braunschweig)&lt;br /&gt;
|-&lt;br /&gt;
| 514&lt;br /&gt;
| 0202&lt;br /&gt;
| Commodore (West Chester)&lt;br /&gt;
|-&lt;br /&gt;
| 515&lt;br /&gt;
| 0203&lt;br /&gt;
| Commodore (West Chester)&lt;br /&gt;
| Originally registered to Combitech/Macrosystem&lt;br /&gt;
|-&lt;br /&gt;
| 756&lt;br /&gt;
| 02F4&lt;br /&gt;
| Progressive Peripherals &amp;amp; Software&lt;br /&gt;
|-&lt;br /&gt;
| 767&lt;br /&gt;
| 02FF&lt;br /&gt;
| Kolff Computer Supplies&lt;br /&gt;
|-&lt;br /&gt;
| 1001&lt;br /&gt;
| 03E9&lt;br /&gt;
| Tecmar&lt;br /&gt;
|-&lt;br /&gt;
| 1002&lt;br /&gt;
| 03EA&lt;br /&gt;
| Telesys&lt;br /&gt;
|-&lt;br /&gt;
| 1003&lt;br /&gt;
| 03EB&lt;br /&gt;
| The Micro-Forge&lt;br /&gt;
|-&lt;br /&gt;
| 1004&lt;br /&gt;
| 03EC&lt;br /&gt;
| Kronos/C Ltd.&lt;br /&gt;
| Originally registered to Card Co. (Supra)&lt;br /&gt;
|-&lt;br /&gt;
| 1005&lt;br /&gt;
| 03ED&lt;br /&gt;
| A-Squared&lt;br /&gt;
|-&lt;br /&gt;
| 1006&lt;br /&gt;
| 03EE&lt;br /&gt;
| Comspec Communications&lt;br /&gt;
|-&lt;br /&gt;
| 1007&lt;br /&gt;
| 03EF&lt;br /&gt;
| HT Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 1008&lt;br /&gt;
| 03F0&lt;br /&gt;
| RDS Software&lt;br /&gt;
|-&lt;br /&gt;
| 1009&lt;br /&gt;
| 03F1&lt;br /&gt;
| Anakin Research&lt;br /&gt;
|-&lt;br /&gt;
| 1010&lt;br /&gt;
| 03F2&lt;br /&gt;
| MicroBotics&lt;br /&gt;
|-&lt;br /&gt;
| 1011&lt;br /&gt;
| 03F3&lt;br /&gt;
| Bob Krauth&lt;br /&gt;
|-&lt;br /&gt;
| 1012&lt;br /&gt;
| 03F4&lt;br /&gt;
| Access Associates (Alegra)&lt;br /&gt;
|-&lt;br /&gt;
| 1013&lt;br /&gt;
| 03F5&lt;br /&gt;
| Mini Comp Systems Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 1014&lt;br /&gt;
| 03F6&lt;br /&gt;
| Cypress Technology&lt;br /&gt;
|-&lt;br /&gt;
| 1015&lt;br /&gt;
| 03F7&lt;br /&gt;
| Fuller Computers&lt;br /&gt;
|-&lt;br /&gt;
| 1016&lt;br /&gt;
| 03F8&lt;br /&gt;
| Galaxy Computers&lt;br /&gt;
|-&lt;br /&gt;
| 1017&lt;br /&gt;
| 03F9&lt;br /&gt;
| ADA Research&lt;br /&gt;
|-&lt;br /&gt;
| 1018&lt;br /&gt;
| 03FA&lt;br /&gt;
| Computer Service Italia&lt;br /&gt;
|-&lt;br /&gt;
| 1019&lt;br /&gt;
| 03FB&lt;br /&gt;
| Amigo&lt;br /&gt;
|-&lt;br /&gt;
| 1020&lt;br /&gt;
| 03FC&lt;br /&gt;
| Micro-Solutions Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1021&lt;br /&gt;
| 03FD&lt;br /&gt;
| Stacar International&lt;br /&gt;
|-&lt;br /&gt;
| 1022&lt;br /&gt;
| 03FE&lt;br /&gt;
| Video Precisions&lt;br /&gt;
|-&lt;br /&gt;
| 1023&lt;br /&gt;
| 03FF&lt;br /&gt;
| ASDG, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1025&lt;br /&gt;
| 0401&lt;br /&gt;
| Ing. Buero Kalawsky&lt;br /&gt;
|-&lt;br /&gt;
| 1026&lt;br /&gt;
| 0402&lt;br /&gt;
| Computer Tuning&lt;br /&gt;
|-&lt;br /&gt;
| 1027&lt;br /&gt;
| 0403&lt;br /&gt;
| Interplan Unternehmensberatung&lt;br /&gt;
|-&lt;br /&gt;
| 1028&lt;br /&gt;
| 0404&lt;br /&gt;
| Imtronics/Memphis&lt;br /&gt;
| Originally registered to Peter Ohlich&lt;br /&gt;
|-&lt;br /&gt;
| 1030&lt;br /&gt;
| 0406&lt;br /&gt;
| Commodore (Lowell University)&lt;br /&gt;
| Originally registered to Productivity Center&lt;br /&gt;
|-&lt;br /&gt;
| 1041&lt;br /&gt;
| 0411&lt;br /&gt;
| Design Labs&lt;br /&gt;
|-&lt;br /&gt;
| 1042&lt;br /&gt;
| 0412&lt;br /&gt;
| MCS&lt;br /&gt;
|-&lt;br /&gt;
| 1043&lt;br /&gt;
| 0413&lt;br /&gt;
| B. J. Freeman&lt;br /&gt;
|-&lt;br /&gt;
| 1044&lt;br /&gt;
| 0414&lt;br /&gt;
| Side Effects Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1045&lt;br /&gt;
| 0415&lt;br /&gt;
| Oklahoma Personal Comp.&lt;br /&gt;
|-&lt;br /&gt;
| 1046&lt;br /&gt;
| 0416&lt;br /&gt;
| Advanced Micro Innovations&lt;br /&gt;
|-&lt;br /&gt;
| 1047&lt;br /&gt;
| 0417&lt;br /&gt;
| Industrial Support Services&lt;br /&gt;
|-&lt;br /&gt;
| 1048&lt;br /&gt;
| 0418&lt;br /&gt;
| Technisoft&lt;br /&gt;
|-&lt;br /&gt;
| 1049&lt;br /&gt;
| 0419&lt;br /&gt;
| Prolific, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1050&lt;br /&gt;
| 041A&lt;br /&gt;
| Softeam, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1051&lt;br /&gt;
| 041B&lt;br /&gt;
| GRC Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 1052&lt;br /&gt;
| 041C&lt;br /&gt;
| David Lai&lt;br /&gt;
|-&lt;br /&gt;
| 1053&lt;br /&gt;
| 041D&lt;br /&gt;
| Ameristar Technologies&lt;br /&gt;
|-&lt;br /&gt;
| 1054&lt;br /&gt;
| 041E&lt;br /&gt;
| Cline Refrigeration&lt;br /&gt;
|-&lt;br /&gt;
| 1055&lt;br /&gt;
| 041F&lt;br /&gt;
| Cardiac Pacemakers, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1056&lt;br /&gt;
| 0420&lt;br /&gt;
| Supra Corp. (Creative Microsystems)&lt;br /&gt;
|-&lt;br /&gt;
| 1057&lt;br /&gt;
| 0421&lt;br /&gt;
| Wayne Diener&lt;br /&gt;
|-&lt;br /&gt;
| 1058&lt;br /&gt;
| 0422&lt;br /&gt;
| Computer Systems Associates (CSA)&lt;br /&gt;
|-&lt;br /&gt;
| 1059&lt;br /&gt;
| 0423&lt;br /&gt;
| Trionix, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1060&lt;br /&gt;
| 0424&lt;br /&gt;
| David Lucas&lt;br /&gt;
|-&lt;br /&gt;
| 1061&lt;br /&gt;
| 0425&lt;br /&gt;
| Analog Precision&lt;br /&gt;
| Also assigned to D &amp;amp; L Distributing&lt;br /&gt;
|-&lt;br /&gt;
| 1267&lt;br /&gt;
| 04F3&lt;br /&gt;
| RBM Digitaltechnik&lt;br /&gt;
|-&lt;br /&gt;
| 1282&lt;br /&gt;
| 0502&lt;br /&gt;
| M-TEC Hardware Design&lt;br /&gt;
|-&lt;br /&gt;
| 1337&lt;br /&gt;
| 0539&lt;br /&gt;
| Thomas Stenzel (DaFR34K)&lt;br /&gt;
|-&lt;br /&gt;
| 1576&lt;br /&gt;
| 0628&lt;br /&gt;
| Boris Križma&lt;br /&gt;
|-&lt;br /&gt;
| 1729&lt;br /&gt;
| 06C1&lt;br /&gt;
| Thomas Richter / OpenPCI-A1200 Mediator bridge&lt;br /&gt;
|-&lt;br /&gt;
| 1730&lt;br /&gt;
| 06C2&lt;br /&gt;
| Thomas Richter / OpenPCI-A4000 Mediator bridge&lt;br /&gt;
|-&lt;br /&gt;
| 1731&lt;br /&gt;
| 06C3&lt;br /&gt;
| Thomas Richter / OpenPCI-Prometheus bridge (Firestorm or original)&lt;br /&gt;
|-&lt;br /&gt;
| 1732&lt;br /&gt;
| 06C4&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved1&lt;br /&gt;
|-&lt;br /&gt;
| 1733&lt;br /&gt;
| 06C5&lt;br /&gt;
| Thomas Richter / OpenPCI-Grex bridge (both A1200 and A4000)&lt;br /&gt;
|-&lt;br /&gt;
| 1734&lt;br /&gt;
| 06C6&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved2&lt;br /&gt;
|-&lt;br /&gt;
| 1735&lt;br /&gt;
| 06C7&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved3&lt;br /&gt;
|-&lt;br /&gt;
| 1736&lt;br /&gt;
| 06C8&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved4&lt;br /&gt;
|-&lt;br /&gt;
| 1737&lt;br /&gt;
| 06C9&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved5&lt;br /&gt;
|-&lt;br /&gt;
| 1738&lt;br /&gt;
| 06CA&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved6&lt;br /&gt;
|-&lt;br /&gt;
| 1739&lt;br /&gt;
| 06CB&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved7&lt;br /&gt;
|-&lt;br /&gt;
| 1740&lt;br /&gt;
| 06CC&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved8&lt;br /&gt;
|-&lt;br /&gt;
| 1741&lt;br /&gt;
| 06CD&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved9&lt;br /&gt;
|-&lt;br /&gt;
| 1742&lt;br /&gt;
| 06CE&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved10&lt;br /&gt;
|-&lt;br /&gt;
| 1743&lt;br /&gt;
| 06CF&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved11&lt;br /&gt;
|-&lt;br /&gt;
| 1744&lt;br /&gt;
| 06D0&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved12&lt;br /&gt;
|-&lt;br /&gt;
| 1761&lt;br /&gt;
| 06E1&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
|-&lt;br /&gt;
| 1803&lt;br /&gt;
| 070B&lt;br /&gt;
| UAE Amiga Emulator&lt;br /&gt;
|-&lt;br /&gt;
| 2002&lt;br /&gt;
| 07D2&lt;br /&gt;
| Mimetics Corp.&lt;br /&gt;
|-&lt;br /&gt;
| 2003&lt;br /&gt;
| 07D3&lt;br /&gt;
| ACDA&lt;br /&gt;
|-&lt;br /&gt;
| 2004&lt;br /&gt;
| 07D4&lt;br /&gt;
| Finn R. Jacobsen&lt;br /&gt;
|-&lt;br /&gt;
| 2005&lt;br /&gt;
| 07D5&lt;br /&gt;
| Elthen Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2006&lt;br /&gt;
| 07D6&lt;br /&gt;
| Nine Tiles Computer Systems Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2007&lt;br /&gt;
| 07D7&lt;br /&gt;
| Analog Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2008&lt;br /&gt;
| 07D8&lt;br /&gt;
| Bell &amp;amp;amp; Howell&lt;br /&gt;
|-&lt;br /&gt;
| 2009&lt;br /&gt;
| 07D9&lt;br /&gt;
| Roland Kochler&lt;br /&gt;
|-&lt;br /&gt;
| 2010&lt;br /&gt;
| 07DA&lt;br /&gt;
| Byte Corp.&lt;br /&gt;
|-&lt;br /&gt;
| 2011&lt;br /&gt;
| 07DB&lt;br /&gt;
| Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 2012&lt;br /&gt;
| 07DC&lt;br /&gt;
| DKB, Inc.&lt;br /&gt;
| Previously named Michigan Software&lt;br /&gt;
|-&lt;br /&gt;
| 2013&lt;br /&gt;
| 07DD&lt;br /&gt;
| Pacific Peripherals&lt;br /&gt;
|-&lt;br /&gt;
| 2014&lt;br /&gt;
| 07DE&lt;br /&gt;
| Sysaphus Software&lt;br /&gt;
|-&lt;br /&gt;
| 2015&lt;br /&gt;
| 07DF&lt;br /&gt;
| Digitronics&lt;br /&gt;
|-&lt;br /&gt;
| 2016&lt;br /&gt;
| 07E0&lt;br /&gt;
| Akron Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2017&lt;br /&gt;
| 07E1&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
|-&lt;br /&gt;
| 2018&lt;br /&gt;
| 07E2&lt;br /&gt;
| Calmos&lt;br /&gt;
|-&lt;br /&gt;
| 2019&lt;br /&gt;
| 07E3&lt;br /&gt;
| Dover Research&lt;br /&gt;
|-&lt;br /&gt;
| 2020&lt;br /&gt;
| 07E4&lt;br /&gt;
| David Krehbiel&lt;br /&gt;
|-&lt;br /&gt;
| 2021&lt;br /&gt;
| 07E5&lt;br /&gt;
| Synergy Peripheral Systems&lt;br /&gt;
| Also known as California Access&lt;br /&gt;
|-&lt;br /&gt;
| 2022&lt;br /&gt;
| 07E6&lt;br /&gt;
| Xetec&lt;br /&gt;
|-&lt;br /&gt;
| 2023&lt;br /&gt;
| 07E7&lt;br /&gt;
| Micron Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2024&lt;br /&gt;
| 07E8&lt;br /&gt;
| CH Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2025&lt;br /&gt;
| 07E9&lt;br /&gt;
| American Liquid Light&lt;br /&gt;
|-&lt;br /&gt;
| 2026&lt;br /&gt;
| 07EA&lt;br /&gt;
| Progressive Peripherals &amp;amp;amp; Software&lt;br /&gt;
| Also used by Ateo&lt;br /&gt;
|-&lt;br /&gt;
| 2027&lt;br /&gt;
| 07EB&lt;br /&gt;
| Wicat Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2028&lt;br /&gt;
| 07EC&lt;br /&gt;
| Applied Systems &amp;amp;amp; Peripherals&lt;br /&gt;
|-&lt;br /&gt;
| 2029&lt;br /&gt;
| 07ED&lt;br /&gt;
| Delaware Valley Software&lt;br /&gt;
|-&lt;br /&gt;
| 2030&lt;br /&gt;
| 07EE&lt;br /&gt;
| Palomax&lt;br /&gt;
|-&lt;br /&gt;
| 2031&lt;br /&gt;
| 07EF&lt;br /&gt;
| Incognito Software&lt;br /&gt;
|-&lt;br /&gt;
| 2032&lt;br /&gt;
| 07F0&lt;br /&gt;
| Jadesign&lt;br /&gt;
|-&lt;br /&gt;
| 2033&lt;br /&gt;
| 07F1&lt;br /&gt;
| BVR&lt;br /&gt;
|-&lt;br /&gt;
| 2034&lt;br /&gt;
| 07F2&lt;br /&gt;
| Spirit Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2035&lt;br /&gt;
| 07F3&lt;br /&gt;
| Spirit Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2036&lt;br /&gt;
| 07F4&lt;br /&gt;
| Atronic&lt;br /&gt;
|-&lt;br /&gt;
| 2037&lt;br /&gt;
| 07F5&lt;br /&gt;
| Scott Karlin&lt;br /&gt;
|-&lt;br /&gt;
| 2038&lt;br /&gt;
| 07F6&lt;br /&gt;
| Howitch&lt;br /&gt;
|-&lt;br /&gt;
| 2039&lt;br /&gt;
| 07F7&lt;br /&gt;
| Sullivan Brothers Visual Engineers&lt;br /&gt;
|-&lt;br /&gt;
| 2040&lt;br /&gt;
| 07F8&lt;br /&gt;
| G I T&lt;br /&gt;
|-&lt;br /&gt;
| 2041&lt;br /&gt;
| 07F9&lt;br /&gt;
| Amigo Business Computers&lt;br /&gt;
|-&lt;br /&gt;
| 2042&lt;br /&gt;
| 07FA&lt;br /&gt;
| Micro E Ab&lt;br /&gt;
|-&lt;br /&gt;
| 2043&lt;br /&gt;
| 07FB&lt;br /&gt;
| Ralph Kruse&lt;br /&gt;
|-&lt;br /&gt;
| 2044&lt;br /&gt;
| 07FC&lt;br /&gt;
| Clearpoint Research&lt;br /&gt;
|-&lt;br /&gt;
| 2045&lt;br /&gt;
| 07FD&lt;br /&gt;
| Kodiak&lt;br /&gt;
|-&lt;br /&gt;
| 2046&lt;br /&gt;
| 07FE&lt;br /&gt;
| BSC&lt;br /&gt;
| Originally registered to Phoenix Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2047&lt;br /&gt;
| 07FF&lt;br /&gt;
| No Name Shown&lt;br /&gt;
|-&lt;br /&gt;
| 2048&lt;br /&gt;
| 0800&lt;br /&gt;
| Commodore Braunschweig&lt;br /&gt;
|-&lt;br /&gt;
| 2049&lt;br /&gt;
| 0801&lt;br /&gt;
| BSC&lt;br /&gt;
| Originally registered to Elaborate Bytes&lt;br /&gt;
|-&lt;br /&gt;
| 2050&lt;br /&gt;
| 0802&lt;br /&gt;
| Kronos/C Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2051&lt;br /&gt;
| 0803&lt;br /&gt;
| Spartanics&lt;br /&gt;
|-&lt;br /&gt;
| 2052&lt;br /&gt;
| 0804&lt;br /&gt;
| Jochheim Computer Tuning&lt;br /&gt;
|-&lt;br /&gt;
| 2053&lt;br /&gt;
| 0805&lt;br /&gt;
| Trans Data Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2054&lt;br /&gt;
| 0806&lt;br /&gt;
| Applied Systems &amp;amp;amp; Peripherals Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2055&lt;br /&gt;
| 0807&lt;br /&gt;
| Checkpoint Technologies&lt;br /&gt;
| Originally registered to Amiga Solutions&lt;br /&gt;
|-&lt;br /&gt;
| 2056&lt;br /&gt;
| 0808&lt;br /&gt;
| Adept Development&lt;br /&gt;
|-&lt;br /&gt;
| 2057&lt;br /&gt;
| 0809&lt;br /&gt;
| Advanced Computer Design&lt;br /&gt;
|-&lt;br /&gt;
| 2058&lt;br /&gt;
| 080A&lt;br /&gt;
| Sir Netics&lt;br /&gt;
|-&lt;br /&gt;
| 2059&lt;br /&gt;
| 080B&lt;br /&gt;
| Expert Services&lt;br /&gt;
|-&lt;br /&gt;
| 2060&lt;br /&gt;
| 080C&lt;br /&gt;
| Digital Art Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2061&lt;br /&gt;
| 080D&lt;br /&gt;
| Adept Development&lt;br /&gt;
|-&lt;br /&gt;
| 2062&lt;br /&gt;
| 080E&lt;br /&gt;
| Expansion Technologies (Expansion Systems)&lt;br /&gt;
|-&lt;br /&gt;
| 2063&lt;br /&gt;
| 080F&lt;br /&gt;
| Alphatech&lt;br /&gt;
|-&lt;br /&gt;
| 2064&lt;br /&gt;
| 0810&lt;br /&gt;
| Edotronik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2065&lt;br /&gt;
| 0811&lt;br /&gt;
| California Access/Synergy&lt;br /&gt;
| Originally registered to Logical Design Works&lt;br /&gt;
|-&lt;br /&gt;
| 2066&lt;br /&gt;
| 0812&lt;br /&gt;
| Bowden, Williams, Full &amp;amp; Assoc.&lt;br /&gt;
|-&lt;br /&gt;
| 2067&lt;br /&gt;
| 0813&lt;br /&gt;
| NES, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2068&lt;br /&gt;
| 0814&lt;br /&gt;
| Amdev&lt;br /&gt;
|-&lt;br /&gt;
| 2069&lt;br /&gt;
| 0815&lt;br /&gt;
| Big Brother Security Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2070&lt;br /&gt;
| 0816&lt;br /&gt;
| Active Circuits Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2071&lt;br /&gt;
| 0817&lt;br /&gt;
| ICD, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2072&lt;br /&gt;
| 0818&lt;br /&gt;
| Multi-Meg Electronique&lt;br /&gt;
|-&lt;br /&gt;
| 2073&lt;br /&gt;
| 0819&lt;br /&gt;
| Kupke Computertechnik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2074&lt;br /&gt;
| 081A&lt;br /&gt;
| The Checkered Ball&lt;br /&gt;
|-&lt;br /&gt;
| 2075&lt;br /&gt;
| 081B&lt;br /&gt;
| Hi Tension Computer Services Ltd. (UK)&lt;br /&gt;
|-&lt;br /&gt;
| 2076&lt;br /&gt;
| 081C&lt;br /&gt;
| Alfa Data&lt;br /&gt;
| Originally assigned to Elmtech Research, Ltd. (UK)&lt;br /&gt;
|-&lt;br /&gt;
| 2077&lt;br /&gt;
| 081D&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
| Originally registered to Clartscreen, Ltd. (UK)&lt;br /&gt;
|-&lt;br /&gt;
| 2078&lt;br /&gt;
| 081E&lt;br /&gt;
| Interworks&lt;br /&gt;
|-&lt;br /&gt;
| 2079&lt;br /&gt;
| 081F&lt;br /&gt;
| Galysh Enterprises&lt;br /&gt;
|-&lt;br /&gt;
| 2080&lt;br /&gt;
| 0820&lt;br /&gt;
| Hardital Synthesis&lt;br /&gt;
| Originally registered to Realtime Games Software Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2081&lt;br /&gt;
| 0821&lt;br /&gt;
| GBS&lt;br /&gt;
|-&lt;br /&gt;
| 2082&lt;br /&gt;
| 0822&lt;br /&gt;
| Circum Design Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2083&lt;br /&gt;
| 0823&lt;br /&gt;
| Alberta Micro Electronic Center&lt;br /&gt;
|-&lt;br /&gt;
| 2084&lt;br /&gt;
| 0824&lt;br /&gt;
| Bestech&lt;br /&gt;
|-&lt;br /&gt;
| 2085&lt;br /&gt;
| 0825&lt;br /&gt;
| Lasar Fantasy&lt;br /&gt;
|-&lt;br /&gt;
| 2086&lt;br /&gt;
| 0826&lt;br /&gt;
| Pulsar&lt;br /&gt;
|-&lt;br /&gt;
| 2087&lt;br /&gt;
| 0827&lt;br /&gt;
| Ivis&lt;br /&gt;
|-&lt;br /&gt;
| 2088&lt;br /&gt;
| 0828&lt;br /&gt;
| Applied Engineering&lt;br /&gt;
|-&lt;br /&gt;
| 2089&lt;br /&gt;
| 0829&lt;br /&gt;
| Solid-State Design &amp;amp;amp; Development&lt;br /&gt;
|-&lt;br /&gt;
| 2090&lt;br /&gt;
| 082A&lt;br /&gt;
| Vison Quest&lt;br /&gt;
|-&lt;br /&gt;
| 2091&lt;br /&gt;
| 082B&lt;br /&gt;
| Seaview Software&lt;br /&gt;
|-&lt;br /&gt;
| 2092&lt;br /&gt;
| 082C&lt;br /&gt;
| BSC&lt;br /&gt;
| Mistakenly used by ADS (Advanced Development Software)&lt;br /&gt;
|-&lt;br /&gt;
| 2093&lt;br /&gt;
| 082D&lt;br /&gt;
| Bernd Culenfeld&lt;br /&gt;
|-&lt;br /&gt;
| 2094&lt;br /&gt;
| 082E&lt;br /&gt;
| American Liquid Light&lt;br /&gt;
|-&lt;br /&gt;
| 2095&lt;br /&gt;
| 082F&lt;br /&gt;
| CEGITES&lt;br /&gt;
|-&lt;br /&gt;
| 2096&lt;br /&gt;
| 0830&lt;br /&gt;
| Quadlite Computers Ltd.&lt;br /&gt;
| Originally registered to EV Industries&lt;br /&gt;
|-&lt;br /&gt;
| 2097&lt;br /&gt;
| 0831&lt;br /&gt;
| Silicon Peace&lt;br /&gt;
|-&lt;br /&gt;
| 2098&lt;br /&gt;
| 0832&lt;br /&gt;
| Black Belt Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2099&lt;br /&gt;
| 0833&lt;br /&gt;
| Village Tronic&lt;br /&gt;
| Originally registerd to Steve Yaeger&lt;br /&gt;
|-&lt;br /&gt;
| 2100&lt;br /&gt;
| 0834&lt;br /&gt;
| ReadySoft&lt;br /&gt;
|-&lt;br /&gt;
| 2101&lt;br /&gt;
| 0835&lt;br /&gt;
| Phoenix Micro Technologies&lt;br /&gt;
|-&lt;br /&gt;
| 2102&lt;br /&gt;
| 0836&lt;br /&gt;
| Advanced Systems &amp;amp; Software&lt;br /&gt;
| Orignally assigned to Preferred Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2103&lt;br /&gt;
| 0837&lt;br /&gt;
| Rombo Productions&lt;br /&gt;
|-&lt;br /&gt;
| 2104&lt;br /&gt;
| 0838&lt;br /&gt;
| Impulse Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2105&lt;br /&gt;
| 0839&lt;br /&gt;
| Beta Unlimited&lt;br /&gt;
|-&lt;br /&gt;
| 2106&lt;br /&gt;
| 083A&lt;br /&gt;
| Memory Expansion System, Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2107&lt;br /&gt;
| 083B&lt;br /&gt;
| Vortex Computer Systems GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2108&lt;br /&gt;
| 083C&lt;br /&gt;
| Platypus Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2109&lt;br /&gt;
| 083D&lt;br /&gt;
| Gigatron OHG&lt;br /&gt;
|-&lt;br /&gt;
| 2110&lt;br /&gt;
| 083E&lt;br /&gt;
| PG Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2111&lt;br /&gt;
| 083F&lt;br /&gt;
| New Technologies Group&lt;br /&gt;
|-&lt;br /&gt;
| 2112&lt;br /&gt;
| 0840&lt;br /&gt;
| Interactive Video Systems (IVS)&lt;br /&gt;
| Pacific Peripherals&lt;br /&gt;
|-&lt;br /&gt;
| 2113&lt;br /&gt;
| 0841&lt;br /&gt;
| Vector&lt;br /&gt;
| Originally registered to H. K. Computer&lt;br /&gt;
|-&lt;br /&gt;
| 2114&lt;br /&gt;
| 0842&lt;br /&gt;
| Pacific Digital&lt;br /&gt;
| Originally registered to C. H. Helfrich Elektronik&lt;br /&gt;
|-&lt;br /&gt;
| 2115&lt;br /&gt;
| 0843&lt;br /&gt;
| Xanadu&lt;br /&gt;
|-&lt;br /&gt;
| 2116&lt;br /&gt;
| 0844&lt;br /&gt;
| Pacific Digital&lt;br /&gt;
| Originally registered to AMS&lt;br /&gt;
|-&lt;br /&gt;
| 2117&lt;br /&gt;
| 0845&lt;br /&gt;
| X-Pert&lt;br /&gt;
|-&lt;br /&gt;
| 2118&lt;br /&gt;
| 0846&lt;br /&gt;
| The Amiga Centre&lt;br /&gt;
|-&lt;br /&gt;
| 2119&lt;br /&gt;
| 0847&lt;br /&gt;
| Digital Pacific&lt;br /&gt;
|-&lt;br /&gt;
| 2120&lt;br /&gt;
| 0848&lt;br /&gt;
| Solid State Leisure&lt;br /&gt;
|-&lt;br /&gt;
| 2121&lt;br /&gt;
| 0849&lt;br /&gt;
| Hydra Systems&lt;br /&gt;
| Originally registered to Analog Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2122&lt;br /&gt;
| 084A&lt;br /&gt;
| Cumana&lt;br /&gt;
|-&lt;br /&gt;
| 2123&lt;br /&gt;
| 084B&lt;br /&gt;
| KAPS 2C Conception&lt;br /&gt;
|-&lt;br /&gt;
| 2124&lt;br /&gt;
| 084C&lt;br /&gt;
| Mike Mason&lt;br /&gt;
|-&lt;br /&gt;
| 2125&lt;br /&gt;
| 084D&lt;br /&gt;
| For Your Eyes&lt;br /&gt;
|-&lt;br /&gt;
| 2126&lt;br /&gt;
| 084E&lt;br /&gt;
| Volkmar Breitfeld Computersysteme&lt;br /&gt;
|-&lt;br /&gt;
| 2127&lt;br /&gt;
| 084F&lt;br /&gt;
| Sunrize Industries&lt;br /&gt;
|-&lt;br /&gt;
| 2128&lt;br /&gt;
| 0850&lt;br /&gt;
| Scott Advanced Micro Designs&lt;br /&gt;
|-&lt;br /&gt;
| 2129&lt;br /&gt;
| 0851&lt;br /&gt;
| Digital Micronics&lt;br /&gt;
|-&lt;br /&gt;
| 2130&lt;br /&gt;
| 0852&lt;br /&gt;
| Alfa-Laval&lt;br /&gt;
|-&lt;br /&gt;
| 2131&lt;br /&gt;
| 0853&lt;br /&gt;
| Multigros A/S&lt;br /&gt;
|-&lt;br /&gt;
| 2132&lt;br /&gt;
| 0854&lt;br /&gt;
| Archos&lt;br /&gt;
|-&lt;br /&gt;
| 2133&lt;br /&gt;
| 0855&lt;br /&gt;
| Icom Simulations&lt;br /&gt;
|-&lt;br /&gt;
| 2134&lt;br /&gt;
| 0856&lt;br /&gt;
| Commodore Test Engineering Group&lt;br /&gt;
|-&lt;br /&gt;
| 2135&lt;br /&gt;
| 0857&lt;br /&gt;
| Microcreations&lt;br /&gt;
|-&lt;br /&gt;
| 2136&lt;br /&gt;
| 0858&lt;br /&gt;
| Shoestring Productions&lt;br /&gt;
|-&lt;br /&gt;
| 2137&lt;br /&gt;
| 0859&lt;br /&gt;
| Faberushi&lt;br /&gt;
|-&lt;br /&gt;
| 2138&lt;br /&gt;
| 085A&lt;br /&gt;
| Evesham Micro Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2139&lt;br /&gt;
| 085B&lt;br /&gt;
| Panagolin Laser Software&lt;br /&gt;
|-&lt;br /&gt;
| 2140&lt;br /&gt;
| 085C&lt;br /&gt;
| Thomas Rudloff&lt;br /&gt;
|-&lt;br /&gt;
| 2141&lt;br /&gt;
| 085D&lt;br /&gt;
| Daniel Hohabir&lt;br /&gt;
|-&lt;br /&gt;
| 2142&lt;br /&gt;
| 085E&lt;br /&gt;
| GfxBase, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2143&lt;br /&gt;
| 085F&lt;br /&gt;
| Axellabs&lt;br /&gt;
|-&lt;br /&gt;
| 2144&lt;br /&gt;
| 0860&lt;br /&gt;
| Roctec Electronics Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2145&lt;br /&gt;
| 0861&lt;br /&gt;
| Omega Datentechnik&lt;br /&gt;
|-&lt;br /&gt;
| 2146&lt;br /&gt;
| 0862&lt;br /&gt;
| Atlantis&lt;br /&gt;
|-&lt;br /&gt;
| 2147&lt;br /&gt;
| 0863&lt;br /&gt;
| Skytec Computers&lt;br /&gt;
|-&lt;br /&gt;
| 2148&lt;br /&gt;
| 0864&lt;br /&gt;
| Protar Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2149&lt;br /&gt;
| 0865&lt;br /&gt;
| ACS&lt;br /&gt;
|-&lt;br /&gt;
| 2150&lt;br /&gt;
| 0866&lt;br /&gt;
| Software Results Enterprises&lt;br /&gt;
| Originally registered to University of Illinois&lt;br /&gt;
|-&lt;br /&gt;
| 2151&lt;br /&gt;
| 0867&lt;br /&gt;
| Infinity Systems Design Group&lt;br /&gt;
|-&lt;br /&gt;
| 2152&lt;br /&gt;
| 0868&lt;br /&gt;
| Trade It&lt;br /&gt;
|-&lt;br /&gt;
| 2153&lt;br /&gt;
| 0869&lt;br /&gt;
| Suntec, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2154&lt;br /&gt;
| 086A&lt;br /&gt;
| DJW Micro Systems&lt;br /&gt;
| Originally registered to Tritec Marketing&lt;br /&gt;
|-&lt;br /&gt;
| 2155&lt;br /&gt;
| 086B&lt;br /&gt;
| Power Computing Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2156&lt;br /&gt;
| 086C&lt;br /&gt;
| MacroSystems&lt;br /&gt;
|-&lt;br /&gt;
| 2157&lt;br /&gt;
| 086D&lt;br /&gt;
| Masoboshi GmbH (DCE)&lt;br /&gt;
|-&lt;br /&gt;
| 2158&lt;br /&gt;
| 086E&lt;br /&gt;
| HAL Software Hardware Handel&lt;br /&gt;
|-&lt;br /&gt;
| 2159&lt;br /&gt;
| 086F&lt;br /&gt;
| Mainhattan Data&lt;br /&gt;
| Originally registered to Michael Lamm Computersysteme&lt;br /&gt;
|-&lt;br /&gt;
| 2160&lt;br /&gt;
| 0870&lt;br /&gt;
| Digital Processing System&lt;br /&gt;
| Originally registered to bbdp Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2161&lt;br /&gt;
| 0871&lt;br /&gt;
| Blue Ribbon Soundworks&lt;br /&gt;
| Originally registered to Design Computer Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2162&lt;br /&gt;
| 0872&lt;br /&gt;
| XPert&lt;br /&gt;
| Originally registered to The Station&lt;br /&gt;
|-&lt;br /&gt;
| 2163&lt;br /&gt;
| 0873&lt;br /&gt;
| DelaComp&lt;br /&gt;
| Originally registered to Bryan Williams&lt;br /&gt;
|-&lt;br /&gt;
| 2164&lt;br /&gt;
| 0874&lt;br /&gt;
| Superformance Computer Engineering GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2165&lt;br /&gt;
| 0875&lt;br /&gt;
| Overland Engineering&lt;br /&gt;
|-&lt;br /&gt;
| 2166&lt;br /&gt;
| 0876&lt;br /&gt;
| Thomas Hamren&lt;br /&gt;
|-&lt;br /&gt;
| 2167&lt;br /&gt;
| 0877&lt;br /&gt;
| Village Tronic&lt;br /&gt;
|-&lt;br /&gt;
| 2168&lt;br /&gt;
| 0878&lt;br /&gt;
| Toolbox Design&lt;br /&gt;
|-&lt;br /&gt;
| 2169&lt;br /&gt;
| 0879&lt;br /&gt;
| Digital Processing System&lt;br /&gt;
|-&lt;br /&gt;
| 2170&lt;br /&gt;
| 087A&lt;br /&gt;
| Superformance&lt;br /&gt;
|-&lt;br /&gt;
| 2171&lt;br /&gt;
| 087B&lt;br /&gt;
| Utilities Unlimited&lt;br /&gt;
|-&lt;br /&gt;
| 2172&lt;br /&gt;
| 087C&lt;br /&gt;
| phase 5&lt;br /&gt;
|-&lt;br /&gt;
| 2173&lt;br /&gt;
| 087D&lt;br /&gt;
| Juergen Kommos&lt;br /&gt;
|-&lt;br /&gt;
| 2174&lt;br /&gt;
| 087E&lt;br /&gt;
| Electronic Design&lt;br /&gt;
|-&lt;br /&gt;
| 2175&lt;br /&gt;
| 087F&lt;br /&gt;
| James Cook University of North Queensland&lt;br /&gt;
|-&lt;br /&gt;
| 2176&lt;br /&gt;
| 0880&lt;br /&gt;
| AmiTrix Development&lt;br /&gt;
|-&lt;br /&gt;
| 2177&lt;br /&gt;
| 0881&lt;br /&gt;
| Ferranti&lt;br /&gt;
|-&lt;br /&gt;
| 2178&lt;br /&gt;
| 0882&lt;br /&gt;
| Leviathan Development&lt;br /&gt;
|-&lt;br /&gt;
| 2179&lt;br /&gt;
| 0883&lt;br /&gt;
| United Video Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2180&lt;br /&gt;
| 0884&lt;br /&gt;
| GPSoft Pty. Ltd.&lt;br /&gt;
| Originally registered to Juergen Kommos&lt;br /&gt;
|-&lt;br /&gt;
| 2181&lt;br /&gt;
| 0885&lt;br /&gt;
| ArMAX&lt;br /&gt;
| Oliver Bausch&lt;br /&gt;
|-&lt;br /&gt;
| 2182&lt;br /&gt;
| 0886&lt;br /&gt;
| CP Computer&lt;br /&gt;
|-&lt;br /&gt;
| 2183&lt;br /&gt;
| 0887&lt;br /&gt;
| AMOK - Amiga Module &amp;amp;amp; Oberon Klub&lt;br /&gt;
|-&lt;br /&gt;
| 2184&lt;br /&gt;
| 0888&lt;br /&gt;
| ITEK Neser &amp;amp;amp; Sieber GbR&lt;br /&gt;
|-&lt;br /&gt;
| 2185&lt;br /&gt;
| 0889&lt;br /&gt;
| Phillip C. Lello&lt;br /&gt;
|-&lt;br /&gt;
| 2186&lt;br /&gt;
| 088A&lt;br /&gt;
| Cyborg Design Services&lt;br /&gt;
|-&lt;br /&gt;
| 2187&lt;br /&gt;
| 088B&lt;br /&gt;
| G2 Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2188&lt;br /&gt;
| 088C&lt;br /&gt;
| Pro System Computersysteme&lt;br /&gt;
|-&lt;br /&gt;
| 2189&lt;br /&gt;
| 088D&lt;br /&gt;
| ZEUS Electronic&lt;br /&gt;
| Originally registered to MSPI (Markt &amp;amp;amp; Technik)&lt;br /&gt;
|-&lt;br /&gt;
| 2190&lt;br /&gt;
| 088E&lt;br /&gt;
| Altatech&lt;br /&gt;
|-&lt;br /&gt;
| 2191&lt;br /&gt;
| 088F&lt;br /&gt;
| NewTek&lt;br /&gt;
|-&lt;br /&gt;
| 2192&lt;br /&gt;
| 0890&lt;br /&gt;
| M-TEC Hardware Design&lt;br /&gt;
| Originally registered to Hardware Design Udo Neuroth&lt;br /&gt;
|-&lt;br /&gt;
| 2193&lt;br /&gt;
| 0891&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
| Originally registered to Viona Development&lt;br /&gt;
|-&lt;br /&gt;
| 2194&lt;br /&gt;
| 0892&lt;br /&gt;
| Amitek&lt;br /&gt;
| Originally assigned to Marpet Developments&lt;br /&gt;
|-&lt;br /&gt;
| 2195&lt;br /&gt;
| 0893&lt;br /&gt;
| Ingenieurbuero Helfrich&lt;br /&gt;
|-&lt;br /&gt;
| 2196&lt;br /&gt;
| 0894&lt;br /&gt;
| The Neo Group&lt;br /&gt;
|-&lt;br /&gt;
| 2197&lt;br /&gt;
| 0895&lt;br /&gt;
| Cyon&lt;br /&gt;
|-&lt;br /&gt;
| 2198&lt;br /&gt;
| 0896&lt;br /&gt;
| Bob Research Group&lt;br /&gt;
|-&lt;br /&gt;
| 2199&lt;br /&gt;
| 0897&lt;br /&gt;
| Richmond Sound Design Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2200&lt;br /&gt;
| 0898&lt;br /&gt;
| US Cybernetics&lt;br /&gt;
|-&lt;br /&gt;
| 2201&lt;br /&gt;
| 0899&lt;br /&gt;
| Fulvio Ieva&lt;br /&gt;
|-&lt;br /&gt;
| 2202&lt;br /&gt;
| 089A&lt;br /&gt;
| Silicon Studio&lt;br /&gt;
|-&lt;br /&gt;
| 2203&lt;br /&gt;
| 089B&lt;br /&gt;
| MacroSystems (USA)&lt;br /&gt;
| Was named Micro System Devices&lt;br /&gt;
|-&lt;br /&gt;
| 2204&lt;br /&gt;
| 089C&lt;br /&gt;
| Conspector Entertainment&lt;br /&gt;
|-&lt;br /&gt;
| 2205&lt;br /&gt;
| 089D&lt;br /&gt;
| Laserforum&lt;br /&gt;
|-&lt;br /&gt;
| 2206&lt;br /&gt;
| 089E&lt;br /&gt;
| Elbox Computer&lt;br /&gt;
| Mistakenly used by Index Information Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2207&lt;br /&gt;
| 089F&lt;br /&gt;
| Applied Magic Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2208&lt;br /&gt;
| 08A0&lt;br /&gt;
| SDL Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2560&lt;br /&gt;
| 0A00&lt;br /&gt;
| Harms&lt;br /&gt;
|-&lt;br /&gt;
| 2588&lt;br /&gt;
| 0A1C&lt;br /&gt;
| A1K.org Community&lt;br /&gt;
|-&lt;br /&gt;
| 2640&lt;br /&gt;
| 0A50&lt;br /&gt;
| Micronik&lt;br /&gt;
|-&lt;br /&gt;
| 2782&lt;br /&gt;
| 2782&lt;br /&gt;
| Oliver Achten&lt;br /&gt;
|-&lt;br /&gt;
| 3084&lt;br /&gt;
| 0C0C&lt;br /&gt;
| Team 4&lt;br /&gt;
|-&lt;br /&gt;
| 3643&lt;br /&gt;
| 0E3B&lt;br /&gt;
| E3B&lt;br /&gt;
| Michael Boehmer&lt;br /&gt;
|-&lt;br /&gt;
| 3855&lt;br /&gt;
| 0F0F&lt;br /&gt;
| Micronik&lt;br /&gt;
|-&lt;br /&gt;
| 4096&lt;br /&gt;
| 1000&lt;br /&gt;
| MegaMicro&lt;br /&gt;
|-&lt;br /&gt;
| 4110&lt;br /&gt;
| 100E&lt;br /&gt;
| DigiFeX&lt;br /&gt;
|-&lt;br /&gt;
| 4136&lt;br /&gt;
| 1028&lt;br /&gt;
| Imtronics/Memphis&lt;br /&gt;
|-&lt;br /&gt;
| 4149&lt;br /&gt;
| 1035&lt;br /&gt;
| PROTAR&lt;br /&gt;
|-&lt;br /&gt;
| 4369&lt;br /&gt;
| 1111&lt;br /&gt;
| Frank Strauß Elektronik&lt;br /&gt;
| Also used by Kupke&lt;br /&gt;
|-&lt;br /&gt;
| 4626&lt;br /&gt;
| 1212&lt;br /&gt;
| Individual Computers&lt;br /&gt;
|-&lt;br /&gt;
| 4648&lt;br /&gt;
| 1228&lt;br /&gt;
| Flesch Hornemann Computer Elec.&lt;br /&gt;
|-&lt;br /&gt;
| 4680&lt;br /&gt;
| 1248&lt;br /&gt;
| Kupke Computertechnik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 4711&lt;br /&gt;
| 1267&lt;br /&gt;
| RBM digitaltechnik&lt;br /&gt;
|-&lt;br /&gt;
| 4754&lt;br /&gt;
| 1292&lt;br /&gt;
| MacroSystems&lt;br /&gt;
|-&lt;br /&gt;
| 5000&lt;br /&gt;
| 1388&lt;br /&gt;
| ITH&lt;br /&gt;
|-&lt;br /&gt;
| 5001&lt;br /&gt;
| 1389&lt;br /&gt;
| VMC&lt;br /&gt;
|-&lt;br /&gt;
| 5010&lt;br /&gt;
| 1392&lt;br /&gt;
| Ambience Creation Technology&lt;br /&gt;
|-&lt;br /&gt;
| 5011&lt;br /&gt;
| 1393&lt;br /&gt;
| Creative Development&lt;br /&gt;
|-&lt;br /&gt;
| 5012&lt;br /&gt;
| 1394&lt;br /&gt;
| Georg Braun&lt;br /&gt;
|-&lt;br /&gt;
| 5013&lt;br /&gt;
| 1395&lt;br /&gt;
| Swedish User Group of Amiga&lt;br /&gt;
|-&lt;br /&gt;
| 5014&lt;br /&gt;
| 1396&lt;br /&gt;
| Jakub Bednarski&lt;br /&gt;
|-&lt;br /&gt;
| 5015&lt;br /&gt;
| 1397&lt;br /&gt;
| KryoFlux, Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 5016&lt;br /&gt;
| 1398&lt;br /&gt;
| Igor Majstorovic&lt;br /&gt;
|-&lt;br /&gt;
| 5017&lt;br /&gt;
| 1399&lt;br /&gt;
| Alastair M. Robinson&lt;br /&gt;
|-&lt;br /&gt;
| 5018&lt;br /&gt;
| 139A&lt;br /&gt;
| Austex Software&lt;br /&gt;
|-&lt;br /&gt;
| 5019&lt;br /&gt;
| 139B&lt;br /&gt;
| Sören Gust&lt;br /&gt;
|-&lt;br /&gt;
| 5020&lt;br /&gt;
| 139C&lt;br /&gt;
| Rok Krajnc&lt;br /&gt;
|-&lt;br /&gt;
| 5030&lt;br /&gt;
| 13A6&lt;br /&gt;
| Tim Tashpulatov&lt;br /&gt;
|-&lt;br /&gt;
| 5040&lt;br /&gt;
| 13B0&lt;br /&gt;
| 7-bit&lt;br /&gt;
|-&lt;br /&gt;
| 5050&lt;br /&gt;
| 13BA&lt;br /&gt;
| Sakura IT&lt;br /&gt;
|-&lt;br /&gt;
| 5060&lt;br /&gt;
| 13C4&lt;br /&gt;
| FPGAArcade&lt;br /&gt;
|-&lt;br /&gt;
| 5070&lt;br /&gt;
| 13CE&lt;br /&gt;
| CancerSoft Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 5080&lt;br /&gt;
| 13D8&lt;br /&gt;
| Stephen Leary&lt;br /&gt;
|-&lt;br /&gt;
| 5090&lt;br /&gt;
| 13E2&lt;br /&gt;
| DMA Softlab LLC&lt;br /&gt;
|-&lt;br /&gt;
| 5100&lt;br /&gt;
| 13EC&lt;br /&gt;
| Brookhouse Engineering&lt;br /&gt;
|-&lt;br /&gt;
| 5110&lt;br /&gt;
| 13F6&lt;br /&gt;
| Eduardo Arana&lt;br /&gt;
|-&lt;br /&gt;
| 5120&lt;br /&gt;
| 1400&lt;br /&gt;
| CS-LAB&lt;br /&gt;
|-&lt;br /&gt;
| 5130&lt;br /&gt;
| 140A&lt;br /&gt;
| Robert Miranda&lt;br /&gt;
|-&lt;br /&gt;
| 5140&lt;br /&gt;
| 1414&lt;br /&gt;
| RastPort&lt;br /&gt;
|-&lt;br /&gt;
| 5132&lt;br /&gt;
| 140C&lt;br /&gt;
| UAS Interface Ltd6&lt;br /&gt;
|-&lt;br /&gt;
| 5150&lt;br /&gt;
| 141E&lt;br /&gt;
| Amiga Kit&lt;br /&gt;
|-&lt;br /&gt;
| 5160&lt;br /&gt;
| 1428&lt;br /&gt;
| Central Texas Commodore User Group&lt;br /&gt;
|-&lt;br /&gt;
| 5170&lt;br /&gt;
| 1432&lt;br /&gt;
| Confusion Research Center&lt;br /&gt;
|-&lt;br /&gt;
| 5180&lt;br /&gt;
| 143C&lt;br /&gt;
| Solar Soyuz Zaibatsu&lt;br /&gt;
|-&lt;br /&gt;
| 5190&lt;br /&gt;
| 1446&lt;br /&gt;
| BooBip&lt;br /&gt;
|-&lt;br /&gt;
| 5191&lt;br /&gt;
| 1447&lt;br /&gt;
| Matthias Hampel&lt;br /&gt;
|-&lt;br /&gt;
| 5192&lt;br /&gt;
| 1448&lt;br /&gt;
| dec0de Consulting Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 5193&lt;br /&gt;
| 1449&lt;br /&gt;
| Puppy Concepts&lt;br /&gt;
|-&lt;br /&gt;
| 5194&lt;br /&gt;
| 144A&lt;br /&gt;
| Open Amiga Hardware Repository&lt;br /&gt;
|-&lt;br /&gt;
| 5195&lt;br /&gt;
| 144B&lt;br /&gt;
| Double H Tech&lt;br /&gt;
|-&lt;br /&gt;
| 5196&lt;br /&gt;
| 144C&lt;br /&gt;
| Retromatik&lt;br /&gt;
|-&lt;br /&gt;
| 5500&lt;br /&gt;
| 157C&lt;br /&gt;
| Inhouse Information&lt;br /&gt;
|-&lt;br /&gt;
| 5768&lt;br /&gt;
| 1688&lt;br /&gt;
| Bio Con&lt;br /&gt;
|-&lt;br /&gt;
| 6148&lt;br /&gt;
| 1804&lt;br /&gt;
| HK-Computer&lt;br /&gt;
|-&lt;br /&gt;
| 6502&lt;br /&gt;
| 1966&lt;br /&gt;
| Cloanto&lt;br /&gt;
|-&lt;br /&gt;
| 6520&lt;br /&gt;
| 1978&lt;br /&gt;
| Oliver Gantert&lt;br /&gt;
|-&lt;br /&gt;
| 7777&lt;br /&gt;
| 1E61&lt;br /&gt;
| Rafal Gabriel Chyla&lt;br /&gt;
|-&lt;br /&gt;
| 8215&lt;br /&gt;
| 2017&lt;br /&gt;
| Vortex&lt;br /&gt;
|-&lt;br /&gt;
| 8244&lt;br /&gt;
| 2034&lt;br /&gt;
| Spirit Technology&lt;br /&gt;
|-&lt;br /&gt;
| 8290&lt;br /&gt;
| 2062&lt;br /&gt;
| Expansion Systems&lt;br /&gt;
|-&lt;br /&gt;
| 8448&lt;br /&gt;
| 2100&lt;br /&gt;
| ReadySoft&lt;br /&gt;
|-&lt;br /&gt;
| 8512&lt;br /&gt;
| 2140&lt;br /&gt;
| Phase 5 Digital Products&lt;br /&gt;
|-&lt;br /&gt;
| 8553&lt;br /&gt;
| 2169&lt;br /&gt;
| Digital Processing Systems Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 8704&lt;br /&gt;
| 2200&lt;br /&gt;
| ACT Elektronik&lt;br /&gt;
|-&lt;br /&gt;
| 8738&lt;br /&gt;
| 2222&lt;br /&gt;
| ACT Elektronik&lt;br /&gt;
|-&lt;br /&gt;
| 9512&lt;br /&gt;
| 2528&lt;br /&gt;
| Tower Technologies&lt;br /&gt;
|-&lt;br /&gt;
| 10676&lt;br /&gt;
| 29B4&lt;br /&gt;
| Electronic Design&lt;br /&gt;
|-&lt;br /&gt;
| 14195&lt;br /&gt;
| 3773&lt;br /&gt;
| Media-net-Point&lt;br /&gt;
|-&lt;br /&gt;
| 14501&lt;br /&gt;
| 38A5&lt;br /&gt;
| Petsoff, Finland&lt;br /&gt;
|-&lt;br /&gt;
| 16375&lt;br /&gt;
| 3FF7&lt;br /&gt;
| Uwe Gerlach&lt;br /&gt;
|-&lt;br /&gt;
| 16707&lt;br /&gt;
| 4143&lt;br /&gt;
| Ateo Concepts&lt;br /&gt;
|-&lt;br /&gt;
| 16708&lt;br /&gt;
| 4144&lt;br /&gt;
| ALiENDESiGN&lt;br /&gt;
|-&lt;br /&gt;
| 16945&lt;br /&gt;
| 4231&lt;br /&gt;
| A.C.T.&lt;br /&gt;
|-&lt;br /&gt;
| 17740&lt;br /&gt;
| 454C&lt;br /&gt;
| HK-Computer (ELSAT)&lt;br /&gt;
|-&lt;br /&gt;
| 18260&lt;br /&gt;
| 4754&lt;br /&gt;
| MacroSystems (Germany)&lt;br /&gt;
|-&lt;br /&gt;
| 19796&lt;br /&gt;
| 4D54&lt;br /&gt;
| Markt &amp;amp; Technik&lt;br /&gt;
|-&lt;br /&gt;
| 22359&lt;br /&gt;
| 5757&lt;br /&gt;
| Markt &amp;amp; Technik&lt;br /&gt;
|-&lt;br /&gt;
| 26464&lt;br /&gt;
| 6760&lt;br /&gt;
| Combitec&lt;br /&gt;
|-&lt;br /&gt;
| 26470&lt;br /&gt;
| 6766&lt;br /&gt;
| Combitec&lt;br /&gt;
|-&lt;br /&gt;
| 28014&lt;br /&gt;
| 6D6E&lt;br /&gt;
| MNT Media and Technology UG&lt;br /&gt;
|-&lt;br /&gt;
| 32768&lt;br /&gt;
| 8000&lt;br /&gt;
| M.A.S.T.&lt;br /&gt;
|-&lt;br /&gt;
| 42240&lt;br /&gt;
| A500&lt;br /&gt;
| Aethreum Digital&lt;br /&gt;
|-&lt;br /&gt;
| 43437&lt;br /&gt;
| A9AD&lt;br /&gt;
| Reis-Ware&lt;br /&gt;
|-&lt;br /&gt;
| 43521&lt;br /&gt;
| AA01&lt;br /&gt;
| Cameron&lt;br /&gt;
|-&lt;br /&gt;
| 43537&lt;br /&gt;
| AA11&lt;br /&gt;
| Reis-Ware&lt;br /&gt;
|-&lt;br /&gt;
| 44359&lt;br /&gt;
| AD47&lt;br /&gt;
| Matay&lt;br /&gt;
|-&lt;br /&gt;
| 46504&lt;br /&gt;
| B5A8&lt;br /&gt;
| Phoenix&lt;br /&gt;
|-&lt;br /&gt;
| 48879&lt;br /&gt;
| BEEF&lt;br /&gt;
| Swiss Mountain Dog Products&lt;br /&gt;
|-&lt;br /&gt;
| 49160&lt;br /&gt;
| C008&lt;br /&gt;
| Combitec&lt;br /&gt;
|-&lt;br /&gt;
| 61453&lt;br /&gt;
| F00D&lt;br /&gt;
| Forefront Technologies Inc.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
For any changes/additions to this registry see [[#How_to_Obtain_a_Manufacturer_Number|How to Obtain a Manufacturer Number]]&lt;/div&gt;</summary>
		<author><name>Costel Mincea</name></author>
	</entry>
	<entry>
		<id>https://wiki.amigaos.net/w/index.php?title=Amiga_Hardware_Manufacturer_ID_Registry&amp;diff=12600</id>
		<title>Amiga Hardware Manufacturer ID Registry</title>
		<link rel="alternate" type="text/html" href="https://wiki.amigaos.net/w/index.php?title=Amiga_Hardware_Manufacturer_ID_Registry&amp;diff=12600"/>
		<updated>2026-09-08T11:06:16Z</updated>

		<summary type="html">&lt;p&gt;Costel Mincea: Added IDs 1729-1744 for OpenPCI/Thomas Richter&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
= How to Obtain a Manufacturer Number =&lt;br /&gt;
&lt;br /&gt;
Manufacturer&#039;s numbers are assigned by the AmigaOS development team. To obtain your unique manufacturer number send a support request to [mailto:support@hyperion-entertainment.com support@hyperion-entertainment.com] including these information:&lt;br /&gt;
&lt;br /&gt;
 1. The name of the company or person which the number is assigned to&lt;br /&gt;
 &lt;br /&gt;
 2. Postal address/contact address&lt;br /&gt;
 &lt;br /&gt;
 3. Name of the contact person, with a corresponding e-mail address&lt;br /&gt;
 &lt;br /&gt;
 4. A brief description of the kind of products you want to produce&lt;br /&gt;
&lt;br /&gt;
= Your Manufacturer Number =&lt;br /&gt;
&lt;br /&gt;
Attention hardware manufacturers. If you are developing a hardware expansion product for the Classic Amiga (e.g. 500, 2000, 3000) then you will need to obtain a special manufacturer ID number from the AmigaOS development team to identify your product. This manufacturer number is used by the Amiga to link your hardware with its driver software at boot time.&lt;br /&gt;
&lt;br /&gt;
Your manufacturer number is part of the special protocol that the Amiga uses to automatically configure all expansion devices on the bus without the user having to cut jumpers or adjust dip switches. This is called auto-config.&lt;br /&gt;
&lt;br /&gt;
At start-up time, the system first polls each board in the system and assigns the board its own address space. If it is a memory board, its RAM is linked into the memory free pool. Later in the boot sequence, after DOS is initialized, the binddrivers program is run. Binddrivers will search the directory SYS:Expansion for the drivers that go with the boards.&lt;br /&gt;
&lt;br /&gt;
To do this binddrivers looks in the Tool Type field of all icon files in SYS:Expansion. If the first seven bytes of the Tool Type field are &amp;quot;PRODUCT&amp;quot;, then this is an icon file for a driver.&lt;br /&gt;
&lt;br /&gt;
Binddrivers will then attempt to match the drivers it has found with the boards that were found earlier. This is where your manufacturer number comes in.&lt;br /&gt;
&lt;br /&gt;
Your manufacturer number goes in two places. First, it is burned in hex form into the PAL which is part of ALL auto-config expansion products. Second, it appears in ASCII in the Tool Type field of the icon file for your product&#039;s driver. By matching these two numbers, the Amiga can automatically configure your board and bind it&#039;s software driver into the system as well.&lt;br /&gt;
&lt;br /&gt;
The manufacturer&#039;s number is a 16-bit ID which appears in PAL offsets $10-$17. There is also an 8-bit product number which you assign. The product number is for uniquely identifying different products from the same vendor. The product number will appear in PAL offsets $04-$07. This gives you a total of 24 bits to identify each of your products.&lt;br /&gt;
&lt;br /&gt;
These 24 bits of information in the PAL which identify your product are matched against the information in the Tool Type field of all icon files in the SYS:Expansion drawer. For example, suppose you are manufacturer #1019. You have two products, #1 and #2 which both use the same driver. The icon for your driver for these two products would have a Tool Type set to &amp;quot;PRODUCT=1019/1|1019/2&amp;quot;. This means: I am an icon for a driver that works with product number 1 or 2 from manufacturer 1019, now bind me. Spaces are not legal. Here are two other examples:&lt;br /&gt;
&lt;br /&gt;
; PRODUCT=1208/11&lt;br /&gt;
: is the Tool Type for a driver for product 11 from manufacturer number 1208.&lt;br /&gt;
&lt;br /&gt;
; PRODUCT=1017&lt;br /&gt;
: is the Tool Type for a driver for any product from manufacturer number 1017.&lt;br /&gt;
&lt;br /&gt;
For an informal explanation of the auto-configuration process, see the chapter on Software Expansion Architecture from the 2nd Annual Amiga Developer&#039;s Conference Notes (available on ADCD 2.1). For the details of timing, power, the PAL equations and PAL address specifications and the expansion library documentation, see sections 3.1 to 3.3 of the A500/A2000 Technical Reference Manual. The original auto-config spec appears in the A1000 Schematics and Expansion Specification.&lt;br /&gt;
&lt;br /&gt;
The auto-config process makes the addition of expansion products to the system very easy. All the user has to do is put the board in any slot and copy the driver from the release disk to his own SYS:Expansion drawer. Everything else is automatic. There are no jumpers or dip switches to set. Best of all, you will get a lot less support calls asking how to make your product work with the XYZ-Corp-battery-backed-clock.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
&lt;br /&gt;
Some notes on hardware manufacturer ID assignment.&lt;br /&gt;
&lt;br /&gt;
* Manufacturer ID numbers are assigned free of charge.&lt;br /&gt;
* Please provide the following information when requesting an ID:&lt;br /&gt;
*# Name of the company or person&lt;br /&gt;
*# Postal address/contact address&lt;br /&gt;
*# Name of the contact person, with a corresponding e-mail address&lt;br /&gt;
*# A brief description of the kind of products you want to produce&lt;br /&gt;
* All ID numbers smaller than 5000 must be considered unsafe because no information exists on which numbers exactly were taken during the time Commodore, Inc. disintegrated.&lt;br /&gt;
* ID numbers in the range 8192 to 18841 must be considered unsafe because some hardware developers mistook the numbers assigned to them to be given in hexadecimal format. Hence 0x2000 = 8192 and 0x4999 = 18841.&lt;br /&gt;
&lt;br /&gt;
= Example code =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
/*-----------------------------------------------*/&lt;br /&gt;
/* Here is a short program which will tell you   */&lt;br /&gt;
/* about the expansion boards configured in your */&lt;br /&gt;
/* system without you opening up the machine.    */&lt;br /&gt;
/* Code by Bill Koester of CATS                  */&lt;br /&gt;
/*-----------------------------------------------*/&lt;br /&gt;
#include &amp;lt;libraries/configvars.h&amp;gt;&lt;br /&gt;
#include &amp;lt;libraries/expansion.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
struct ExpansionBase *ExpansionBase;&lt;br /&gt;
&lt;br /&gt;
void cleanup();&lt;br /&gt;
void printdev();&lt;br /&gt;
&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
   struct ConfigDev *MyConfigDev;&lt;br /&gt;
&lt;br /&gt;
   /*----------------------------------*/&lt;br /&gt;
   /* Open the expansion library,      */&lt;br /&gt;
   /* if there is a problem then exit  */&lt;br /&gt;
   /*----------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   ExpansionBase =(struct ExpansionBase *) OpenLibrary(EXPANSIONNAME,0);&lt;br /&gt;
   if(ExpansionBase==NULL)&lt;br /&gt;
   {&lt;br /&gt;
      printf(&amp;quot;Error opening expansion library!!\n&amp;quot;);&lt;br /&gt;
      cleanup();&lt;br /&gt;
      exit(0);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   /*--------------------------------------------*/&lt;br /&gt;
   /* Use FindConfigDev to get info on the first */&lt;br /&gt;
   /* expansion board on the list maintained by  */&lt;br /&gt;
   /* Exec.  If there are no expansion boards in */&lt;br /&gt;
   /* the system then exit.                      */&lt;br /&gt;
   /*--------------------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   MyConfigDev = NULL;&lt;br /&gt;
&lt;br /&gt;
  /*--------------------------------------------------*/&lt;br /&gt;
  /* FindConfigDev(oldConfigDev,manufacturer,product) */&lt;br /&gt;
  /* oldConfigDev = NULL for the top of the list      */&lt;br /&gt;
  /* manufacturer = -1 for any manufacturer           */&lt;br /&gt;
  /* product      = -1 for any product                */&lt;br /&gt;
  /*--------------------------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   MyConfigDev = FindConfigDev(NULL,-1,-1);&lt;br /&gt;
&lt;br /&gt;
   if(MyConfigDev==NULL)&lt;br /&gt;
   {&lt;br /&gt;
      printf(&amp;quot;No Configured Devices found!!\n&amp;quot;);&lt;br /&gt;
      cleanup();&lt;br /&gt;
      exit(0);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   printdev(MyConfigDev);&lt;br /&gt;
&lt;br /&gt;
   /*-----------------------------------*/&lt;br /&gt;
   /* OK, there is at least one board,  */&lt;br /&gt;
   /* so loop and get the entire list   */&lt;br /&gt;
   /* printing as we go with printdev() */&lt;br /&gt;
   /*-----------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   while(MyConfigDev = FindConfigDev(MyConfigDev,-1,-1))&lt;br /&gt;
   {&lt;br /&gt;
      printdev(MyConfigDev);&lt;br /&gt;
   }&lt;br /&gt;
   cleanup();&lt;br /&gt;
   return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*-------------------*/&lt;br /&gt;
/* Close up shop...  */&lt;br /&gt;
/*-------------------*/&lt;br /&gt;
void cleanup()&lt;br /&gt;
{&lt;br /&gt;
   if(ExpansionBase)&lt;br /&gt;
      CloseLibrary(ExpansionBase);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*----------------------------------*/&lt;br /&gt;
/* Print out the contents of the    */&lt;br /&gt;
/* dev structure for this expansion */&lt;br /&gt;
/* product.                         */&lt;br /&gt;
/*----------------------------------*/&lt;br /&gt;
&lt;br /&gt;
void printdev(dev)&lt;br /&gt;
struct ConfigDev *dev;&lt;br /&gt;
{&lt;br /&gt;
   char buff[200];&lt;br /&gt;
&lt;br /&gt;
   printf(&amp;quot;Flags          = &amp;quot;);&lt;br /&gt;
   if(dev-&amp;gt;cd_Flags==NULL)&lt;br /&gt;
      printf(&amp;quot;NULL  &amp;quot;);&lt;br /&gt;
   if(dev-&amp;gt;cd_Flags&amp;amp;CDF_SHUTUP)&lt;br /&gt;
      printf(&amp;quot;CDF_SHUTUP  &amp;quot;);&lt;br /&gt;
   if(dev-&amp;gt;cd_Flags&amp;amp;CDF_CONFIGME)&lt;br /&gt;
      printf(&amp;quot;CDF_CONFIGME  &amp;quot;);&lt;br /&gt;
   printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
   printf(&amp;quot;Board Address  = %x\n&amp;quot;,dev-&amp;gt;cd_BoardAddr);&lt;br /&gt;
   printf(&amp;quot;Board Size     = %d bytes\n&amp;quot;,dev-&amp;gt;cd_BoardSize);&lt;br /&gt;
   printf(&amp;quot;Slot  Address  = %d\n&amp;quot;,dev-&amp;gt;cd_SlotAddr);&lt;br /&gt;
   printf(&amp;quot;Slot  Size     = %d\n&amp;quot;,dev-&amp;gt;cd_SlotSize);&lt;br /&gt;
   printf(&amp;quot;Driver code at   %x\n&amp;quot;,dev-&amp;gt;cd_Driver);&lt;br /&gt;
&lt;br /&gt;
   printf(&amp;quot;er_Type         = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Type);&lt;br /&gt;
   printf(&amp;quot;er_Product      = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Product);&lt;br /&gt;
   printf(&amp;quot;er_Flags        = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Flags);&lt;br /&gt;
   printf(&amp;quot;er_Reserved03   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved03);&lt;br /&gt;
   printf(&amp;quot;er_Manufacturer = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Manufacturer);&lt;br /&gt;
   printf(&amp;quot;er_SerialNumber = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_SerialNumber);&lt;br /&gt;
   printf(&amp;quot;er_InitDiagVec  = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_InitDiagVec);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0c   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0c);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0d   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0d);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0e   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0e);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0f   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0f);&lt;br /&gt;
&lt;br /&gt;
   printf(&amp;quot;Hit Return to continue:\n&amp;quot;);&lt;br /&gt;
   gets(buff);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Registry =&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! ID (decimal)&lt;br /&gt;
! ID (hexadecimal)&lt;br /&gt;
! Manufacturer&lt;br /&gt;
! Notes&lt;br /&gt;
|-&lt;br /&gt;
| 1&lt;br /&gt;
| 0001&lt;br /&gt;
| Micronik&lt;br /&gt;
|-&lt;br /&gt;
| 211&lt;br /&gt;
| 00D3&lt;br /&gt;
| Pacific Peripherals/Profex&lt;br /&gt;
|-&lt;br /&gt;
| 221&lt;br /&gt;
| 00DD&lt;br /&gt;
| Kupke Computertechnik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 256&lt;br /&gt;
| 0100&lt;br /&gt;
| Memphis&lt;br /&gt;
| Originally registered to MacroSystems US&lt;br /&gt;
|-&lt;br /&gt;
| 512&lt;br /&gt;
| 0200&lt;br /&gt;
| 3-State Computertechnik&lt;br /&gt;
|-&lt;br /&gt;
| 513&lt;br /&gt;
| 0201&lt;br /&gt;
| Commodore (Braunschweig)&lt;br /&gt;
|-&lt;br /&gt;
| 514&lt;br /&gt;
| 0202&lt;br /&gt;
| Commodore (West Chester)&lt;br /&gt;
|-&lt;br /&gt;
| 515&lt;br /&gt;
| 0203&lt;br /&gt;
| Commodore (West Chester)&lt;br /&gt;
| Originally registered to Combitech/Macrosystem&lt;br /&gt;
|-&lt;br /&gt;
| 756&lt;br /&gt;
| 02F4&lt;br /&gt;
| Progressive Peripherals &amp;amp; Software&lt;br /&gt;
|-&lt;br /&gt;
| 767&lt;br /&gt;
| 02FF&lt;br /&gt;
| Kolff Computer Supplies&lt;br /&gt;
|-&lt;br /&gt;
| 1001&lt;br /&gt;
| 03E9&lt;br /&gt;
| Tecmar&lt;br /&gt;
|-&lt;br /&gt;
| 1002&lt;br /&gt;
| 03EA&lt;br /&gt;
| Telesys&lt;br /&gt;
|-&lt;br /&gt;
| 1003&lt;br /&gt;
| 03EB&lt;br /&gt;
| The Micro-Forge&lt;br /&gt;
|-&lt;br /&gt;
| 1004&lt;br /&gt;
| 03EC&lt;br /&gt;
| Kronos/C Ltd.&lt;br /&gt;
| Originally registered to Card Co. (Supra)&lt;br /&gt;
|-&lt;br /&gt;
| 1005&lt;br /&gt;
| 03ED&lt;br /&gt;
| A-Squared&lt;br /&gt;
|-&lt;br /&gt;
| 1006&lt;br /&gt;
| 03EE&lt;br /&gt;
| Comspec Communications&lt;br /&gt;
|-&lt;br /&gt;
| 1007&lt;br /&gt;
| 03EF&lt;br /&gt;
| HT Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 1008&lt;br /&gt;
| 03F0&lt;br /&gt;
| RDS Software&lt;br /&gt;
|-&lt;br /&gt;
| 1009&lt;br /&gt;
| 03F1&lt;br /&gt;
| Anakin Research&lt;br /&gt;
|-&lt;br /&gt;
| 1010&lt;br /&gt;
| 03F2&lt;br /&gt;
| MicroBotics&lt;br /&gt;
|-&lt;br /&gt;
| 1011&lt;br /&gt;
| 03F3&lt;br /&gt;
| Bob Krauth&lt;br /&gt;
|-&lt;br /&gt;
| 1012&lt;br /&gt;
| 03F4&lt;br /&gt;
| Access Associates (Alegra)&lt;br /&gt;
|-&lt;br /&gt;
| 1013&lt;br /&gt;
| 03F5&lt;br /&gt;
| Mini Comp Systems Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 1014&lt;br /&gt;
| 03F6&lt;br /&gt;
| Cypress Technology&lt;br /&gt;
|-&lt;br /&gt;
| 1015&lt;br /&gt;
| 03F7&lt;br /&gt;
| Fuller Computers&lt;br /&gt;
|-&lt;br /&gt;
| 1016&lt;br /&gt;
| 03F8&lt;br /&gt;
| Galaxy Computers&lt;br /&gt;
|-&lt;br /&gt;
| 1017&lt;br /&gt;
| 03F9&lt;br /&gt;
| ADA Research&lt;br /&gt;
|-&lt;br /&gt;
| 1018&lt;br /&gt;
| 03FA&lt;br /&gt;
| Computer Service Italia&lt;br /&gt;
|-&lt;br /&gt;
| 1019&lt;br /&gt;
| 03FB&lt;br /&gt;
| Amigo&lt;br /&gt;
|-&lt;br /&gt;
| 1020&lt;br /&gt;
| 03FC&lt;br /&gt;
| Micro-Solutions Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1021&lt;br /&gt;
| 03FD&lt;br /&gt;
| Stacar International&lt;br /&gt;
|-&lt;br /&gt;
| 1022&lt;br /&gt;
| 03FE&lt;br /&gt;
| Video Precisions&lt;br /&gt;
|-&lt;br /&gt;
| 1023&lt;br /&gt;
| 03FF&lt;br /&gt;
| ASDG, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1025&lt;br /&gt;
| 0401&lt;br /&gt;
| Ing. Buero Kalawsky&lt;br /&gt;
|-&lt;br /&gt;
| 1026&lt;br /&gt;
| 0402&lt;br /&gt;
| Computer Tuning&lt;br /&gt;
|-&lt;br /&gt;
| 1027&lt;br /&gt;
| 0403&lt;br /&gt;
| Interplan Unternehmensberatung&lt;br /&gt;
|-&lt;br /&gt;
| 1028&lt;br /&gt;
| 0404&lt;br /&gt;
| Imtronics/Memphis&lt;br /&gt;
| Originally registered to Peter Ohlich&lt;br /&gt;
|-&lt;br /&gt;
| 1030&lt;br /&gt;
| 0406&lt;br /&gt;
| Commodore (Lowell University)&lt;br /&gt;
| Originally registered to Productivity Center&lt;br /&gt;
|-&lt;br /&gt;
| 1041&lt;br /&gt;
| 0411&lt;br /&gt;
| Design Labs&lt;br /&gt;
|-&lt;br /&gt;
| 1042&lt;br /&gt;
| 0412&lt;br /&gt;
| MCS&lt;br /&gt;
|-&lt;br /&gt;
| 1043&lt;br /&gt;
| 0413&lt;br /&gt;
| B. J. Freeman&lt;br /&gt;
|-&lt;br /&gt;
| 1044&lt;br /&gt;
| 0414&lt;br /&gt;
| Side Effects Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1045&lt;br /&gt;
| 0415&lt;br /&gt;
| Oklahoma Personal Comp.&lt;br /&gt;
|-&lt;br /&gt;
| 1046&lt;br /&gt;
| 0416&lt;br /&gt;
| Advanced Micro Innovations&lt;br /&gt;
|-&lt;br /&gt;
| 1047&lt;br /&gt;
| 0417&lt;br /&gt;
| Industrial Support Services&lt;br /&gt;
|-&lt;br /&gt;
| 1048&lt;br /&gt;
| 0418&lt;br /&gt;
| Technisoft&lt;br /&gt;
|-&lt;br /&gt;
| 1049&lt;br /&gt;
| 0419&lt;br /&gt;
| Prolific, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1050&lt;br /&gt;
| 041A&lt;br /&gt;
| Softeam, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1051&lt;br /&gt;
| 041B&lt;br /&gt;
| GRC Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 1052&lt;br /&gt;
| 041C&lt;br /&gt;
| David Lai&lt;br /&gt;
|-&lt;br /&gt;
| 1053&lt;br /&gt;
| 041D&lt;br /&gt;
| Ameristar Technologies&lt;br /&gt;
|-&lt;br /&gt;
| 1054&lt;br /&gt;
| 041E&lt;br /&gt;
| Cline Refrigeration&lt;br /&gt;
|-&lt;br /&gt;
| 1055&lt;br /&gt;
| 041F&lt;br /&gt;
| Cardiac Pacemakers, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1056&lt;br /&gt;
| 0420&lt;br /&gt;
| Supra Corp. (Creative Microsystems)&lt;br /&gt;
|-&lt;br /&gt;
| 1057&lt;br /&gt;
| 0421&lt;br /&gt;
| Wayne Diener&lt;br /&gt;
|-&lt;br /&gt;
| 1058&lt;br /&gt;
| 0422&lt;br /&gt;
| Computer Systems Associates (CSA)&lt;br /&gt;
|-&lt;br /&gt;
| 1059&lt;br /&gt;
| 0423&lt;br /&gt;
| Trionix, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1060&lt;br /&gt;
| 0424&lt;br /&gt;
| David Lucas&lt;br /&gt;
|-&lt;br /&gt;
| 1061&lt;br /&gt;
| 0425&lt;br /&gt;
| Analog Precision&lt;br /&gt;
| Also assigned to D &amp;amp; L Distributing&lt;br /&gt;
|-&lt;br /&gt;
| 1267&lt;br /&gt;
| 04F3&lt;br /&gt;
| RBM Digitaltechnik&lt;br /&gt;
|-&lt;br /&gt;
| 1282&lt;br /&gt;
| 0502&lt;br /&gt;
| M-TEC Hardware Design&lt;br /&gt;
|-&lt;br /&gt;
| 1337&lt;br /&gt;
| 0539&lt;br /&gt;
| Thomas Stenzel (DaFR34K)&lt;br /&gt;
|-&lt;br /&gt;
| 1576&lt;br /&gt;
| 0628&lt;br /&gt;
| Boris Križma&lt;br /&gt;
|-&lt;br /&gt;
| 1729&lt;br /&gt;
| 06C1&lt;br /&gt;
| Thomas Richter / OpenPCI-A1200 Mediator bridge&lt;br /&gt;
|-&lt;br /&gt;
| 1730&lt;br /&gt;
| 06C2&lt;br /&gt;
| Thomas Richter / OpenPCI-A4000 Mediator bridge&lt;br /&gt;
|-&lt;br /&gt;
| 1731&lt;br /&gt;
| 06C3&lt;br /&gt;
| Thomas Richter / OpenPCI-Prometheus bridge (Firestorm or original)&lt;br /&gt;
|-&lt;br /&gt;
| 1732&lt;br /&gt;
| 06C4&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved1&lt;br /&gt;
|-&lt;br /&gt;
| 1733&lt;br /&gt;
| 06C5&lt;br /&gt;
| Thomas Richter / OpenPCI-Grex bridge (both A1200 and A4000)&lt;br /&gt;
|-&lt;br /&gt;
| 1734&lt;br /&gt;
| 06C6&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved2&lt;br /&gt;
|-&lt;br /&gt;
| 1735&lt;br /&gt;
| 06C7&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved3&lt;br /&gt;
|-&lt;br /&gt;
| 1736&lt;br /&gt;
| 06C8&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved4&lt;br /&gt;
|-&lt;br /&gt;
| 1737&lt;br /&gt;
| 06C9&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved5&lt;br /&gt;
|-&lt;br /&gt;
| 1738&lt;br /&gt;
| 06CA&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved6&lt;br /&gt;
|-&lt;br /&gt;
| 1739&lt;br /&gt;
| 06CB&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved7&lt;br /&gt;
|-&lt;br /&gt;
| 1740&lt;br /&gt;
| 06CC&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved8&lt;br /&gt;
|-&lt;br /&gt;
| 1741&lt;br /&gt;
| 06CD&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved9&lt;br /&gt;
|-&lt;br /&gt;
| 1742&lt;br /&gt;
| 06CE&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved10&lt;br /&gt;
|-&lt;br /&gt;
| 1743&lt;br /&gt;
| 06CF&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved11&lt;br /&gt;
|-&lt;br /&gt;
| 1744&lt;br /&gt;
| 06D0&lt;br /&gt;
| Thomas Richter / OpenPCI-Reserved12&lt;br /&gt;
|-&lt;br /&gt;
| 1761&lt;br /&gt;
| 06E1&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
|-&lt;br /&gt;
| 1803&lt;br /&gt;
| 070B&lt;br /&gt;
| UAE Amiga Emulator&lt;br /&gt;
|-&lt;br /&gt;
| 2002&lt;br /&gt;
| 07D2&lt;br /&gt;
| Mimetics Corp.&lt;br /&gt;
|-&lt;br /&gt;
| 2003&lt;br /&gt;
| 07D3&lt;br /&gt;
| ACDA&lt;br /&gt;
|-&lt;br /&gt;
| 2004&lt;br /&gt;
| 07D4&lt;br /&gt;
| Finn R. Jacobsen&lt;br /&gt;
|-&lt;br /&gt;
| 2005&lt;br /&gt;
| 07D5&lt;br /&gt;
| Elthen Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2006&lt;br /&gt;
| 07D6&lt;br /&gt;
| Nine Tiles Computer Systems Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2007&lt;br /&gt;
| 07D7&lt;br /&gt;
| Analog Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2008&lt;br /&gt;
| 07D8&lt;br /&gt;
| Bell &amp;amp;amp; Howell&lt;br /&gt;
|-&lt;br /&gt;
| 2009&lt;br /&gt;
| 07D9&lt;br /&gt;
| Roland Kochler&lt;br /&gt;
|-&lt;br /&gt;
| 2010&lt;br /&gt;
| 07DA&lt;br /&gt;
| Byte Corp.&lt;br /&gt;
|-&lt;br /&gt;
| 2011&lt;br /&gt;
| 07DB&lt;br /&gt;
| Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 2012&lt;br /&gt;
| 07DC&lt;br /&gt;
| DKB, Inc.&lt;br /&gt;
| Previously named Michigan Software&lt;br /&gt;
|-&lt;br /&gt;
| 2013&lt;br /&gt;
| 07DD&lt;br /&gt;
| Pacific Peripherals&lt;br /&gt;
|-&lt;br /&gt;
| 2014&lt;br /&gt;
| 07DE&lt;br /&gt;
| Sysaphus Software&lt;br /&gt;
|-&lt;br /&gt;
| 2015&lt;br /&gt;
| 07DF&lt;br /&gt;
| Digitronics&lt;br /&gt;
|-&lt;br /&gt;
| 2016&lt;br /&gt;
| 07E0&lt;br /&gt;
| Akron Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2017&lt;br /&gt;
| 07E1&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
|-&lt;br /&gt;
| 2018&lt;br /&gt;
| 07E2&lt;br /&gt;
| Calmos&lt;br /&gt;
|-&lt;br /&gt;
| 2019&lt;br /&gt;
| 07E3&lt;br /&gt;
| Dover Research&lt;br /&gt;
|-&lt;br /&gt;
| 2020&lt;br /&gt;
| 07E4&lt;br /&gt;
| David Krehbiel&lt;br /&gt;
|-&lt;br /&gt;
| 2021&lt;br /&gt;
| 07E5&lt;br /&gt;
| Synergy Peripheral Systems&lt;br /&gt;
| Also known as California Access&lt;br /&gt;
|-&lt;br /&gt;
| 2022&lt;br /&gt;
| 07E6&lt;br /&gt;
| Xetec&lt;br /&gt;
|-&lt;br /&gt;
| 2023&lt;br /&gt;
| 07E7&lt;br /&gt;
| Micron Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2024&lt;br /&gt;
| 07E8&lt;br /&gt;
| CH Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2025&lt;br /&gt;
| 07E9&lt;br /&gt;
| American Liquid Light&lt;br /&gt;
|-&lt;br /&gt;
| 2026&lt;br /&gt;
| 07EA&lt;br /&gt;
| Progressive Peripherals &amp;amp;amp; Software&lt;br /&gt;
| Also used by Ateo&lt;br /&gt;
|-&lt;br /&gt;
| 2027&lt;br /&gt;
| 07EB&lt;br /&gt;
| Wicat Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2028&lt;br /&gt;
| 07EC&lt;br /&gt;
| Applied Systems &amp;amp;amp; Peripherals&lt;br /&gt;
|-&lt;br /&gt;
| 2029&lt;br /&gt;
| 07ED&lt;br /&gt;
| Delaware Valley Software&lt;br /&gt;
|-&lt;br /&gt;
| 2030&lt;br /&gt;
| 07EE&lt;br /&gt;
| Palomax&lt;br /&gt;
|-&lt;br /&gt;
| 2031&lt;br /&gt;
| 07EF&lt;br /&gt;
| Incognito Software&lt;br /&gt;
|-&lt;br /&gt;
| 2032&lt;br /&gt;
| 07F0&lt;br /&gt;
| Jadesign&lt;br /&gt;
|-&lt;br /&gt;
| 2033&lt;br /&gt;
| 07F1&lt;br /&gt;
| BVR&lt;br /&gt;
|-&lt;br /&gt;
| 2034&lt;br /&gt;
| 07F2&lt;br /&gt;
| Spirit Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2035&lt;br /&gt;
| 07F3&lt;br /&gt;
| Spirit Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2036&lt;br /&gt;
| 07F4&lt;br /&gt;
| Atronic&lt;br /&gt;
|-&lt;br /&gt;
| 2037&lt;br /&gt;
| 07F5&lt;br /&gt;
| Scott Karlin&lt;br /&gt;
|-&lt;br /&gt;
| 2038&lt;br /&gt;
| 07F6&lt;br /&gt;
| Howitch&lt;br /&gt;
|-&lt;br /&gt;
| 2039&lt;br /&gt;
| 07F7&lt;br /&gt;
| Sullivan Brothers Visual Engineers&lt;br /&gt;
|-&lt;br /&gt;
| 2040&lt;br /&gt;
| 07F8&lt;br /&gt;
| G I T&lt;br /&gt;
|-&lt;br /&gt;
| 2041&lt;br /&gt;
| 07F9&lt;br /&gt;
| Amigo Business Computers&lt;br /&gt;
|-&lt;br /&gt;
| 2042&lt;br /&gt;
| 07FA&lt;br /&gt;
| Micro E Ab&lt;br /&gt;
|-&lt;br /&gt;
| 2043&lt;br /&gt;
| 07FB&lt;br /&gt;
| Ralph Kruse&lt;br /&gt;
|-&lt;br /&gt;
| 2044&lt;br /&gt;
| 07FC&lt;br /&gt;
| Clearpoint Research&lt;br /&gt;
|-&lt;br /&gt;
| 2045&lt;br /&gt;
| 07FD&lt;br /&gt;
| Kodiak&lt;br /&gt;
|-&lt;br /&gt;
| 2046&lt;br /&gt;
| 07FE&lt;br /&gt;
| BSC&lt;br /&gt;
| Originally registered to Phoenix Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2047&lt;br /&gt;
| 07FF&lt;br /&gt;
| No Name Shown&lt;br /&gt;
|-&lt;br /&gt;
| 2048&lt;br /&gt;
| 0800&lt;br /&gt;
| Commodore Braunschweig&lt;br /&gt;
|-&lt;br /&gt;
| 2049&lt;br /&gt;
| 0801&lt;br /&gt;
| BSC&lt;br /&gt;
| Originally registered to Elaborate Bytes&lt;br /&gt;
|-&lt;br /&gt;
| 2050&lt;br /&gt;
| 0802&lt;br /&gt;
| Kronos/C Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2051&lt;br /&gt;
| 0803&lt;br /&gt;
| Spartanics&lt;br /&gt;
|-&lt;br /&gt;
| 2052&lt;br /&gt;
| 0804&lt;br /&gt;
| Jochheim Computer Tuning&lt;br /&gt;
|-&lt;br /&gt;
| 2053&lt;br /&gt;
| 0805&lt;br /&gt;
| Trans Data Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2054&lt;br /&gt;
| 0806&lt;br /&gt;
| Applied Systems &amp;amp;amp; Peripherals Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2055&lt;br /&gt;
| 0807&lt;br /&gt;
| Checkpoint Technologies&lt;br /&gt;
| Originally registered to Amiga Solutions&lt;br /&gt;
|-&lt;br /&gt;
| 2056&lt;br /&gt;
| 0808&lt;br /&gt;
| Adept Development&lt;br /&gt;
|-&lt;br /&gt;
| 2057&lt;br /&gt;
| 0809&lt;br /&gt;
| Advanced Computer Design&lt;br /&gt;
|-&lt;br /&gt;
| 2058&lt;br /&gt;
| 080A&lt;br /&gt;
| Sir Netics&lt;br /&gt;
|-&lt;br /&gt;
| 2059&lt;br /&gt;
| 080B&lt;br /&gt;
| Expert Services&lt;br /&gt;
|-&lt;br /&gt;
| 2060&lt;br /&gt;
| 080C&lt;br /&gt;
| Digital Art Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2061&lt;br /&gt;
| 080D&lt;br /&gt;
| Adept Development&lt;br /&gt;
|-&lt;br /&gt;
| 2062&lt;br /&gt;
| 080E&lt;br /&gt;
| Expansion Technologies (Expansion Systems)&lt;br /&gt;
|-&lt;br /&gt;
| 2063&lt;br /&gt;
| 080F&lt;br /&gt;
| Alphatech&lt;br /&gt;
|-&lt;br /&gt;
| 2064&lt;br /&gt;
| 0810&lt;br /&gt;
| Edotronik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2065&lt;br /&gt;
| 0811&lt;br /&gt;
| California Access/Synergy&lt;br /&gt;
| Originally registered to Logical Design Works&lt;br /&gt;
|-&lt;br /&gt;
| 2066&lt;br /&gt;
| 0812&lt;br /&gt;
| Bowden, Williams, Full &amp;amp; Assoc.&lt;br /&gt;
|-&lt;br /&gt;
| 2067&lt;br /&gt;
| 0813&lt;br /&gt;
| NES, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2068&lt;br /&gt;
| 0814&lt;br /&gt;
| Amdev&lt;br /&gt;
|-&lt;br /&gt;
| 2069&lt;br /&gt;
| 0815&lt;br /&gt;
| Big Brother Security Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2070&lt;br /&gt;
| 0816&lt;br /&gt;
| Active Circuits Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2071&lt;br /&gt;
| 0817&lt;br /&gt;
| ICD, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2072&lt;br /&gt;
| 0818&lt;br /&gt;
| Multi-Meg Electronique&lt;br /&gt;
|-&lt;br /&gt;
| 2073&lt;br /&gt;
| 0819&lt;br /&gt;
| Kupke Computertechnik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2074&lt;br /&gt;
| 081A&lt;br /&gt;
| The Checkered Ball&lt;br /&gt;
|-&lt;br /&gt;
| 2075&lt;br /&gt;
| 081B&lt;br /&gt;
| Hi Tension Computer Services Ltd. (UK)&lt;br /&gt;
|-&lt;br /&gt;
| 2076&lt;br /&gt;
| 081C&lt;br /&gt;
| Alfa Data&lt;br /&gt;
| Originally assigned to Elmtech Research, Ltd. (UK)&lt;br /&gt;
|-&lt;br /&gt;
| 2077&lt;br /&gt;
| 081D&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
| Originally registered to Clartscreen, Ltd. (UK)&lt;br /&gt;
|-&lt;br /&gt;
| 2078&lt;br /&gt;
| 081E&lt;br /&gt;
| Interworks&lt;br /&gt;
|-&lt;br /&gt;
| 2079&lt;br /&gt;
| 081F&lt;br /&gt;
| Galysh Enterprises&lt;br /&gt;
|-&lt;br /&gt;
| 2080&lt;br /&gt;
| 0820&lt;br /&gt;
| Hardital Synthesis&lt;br /&gt;
| Originally registered to Realtime Games Software Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2081&lt;br /&gt;
| 0821&lt;br /&gt;
| GBS&lt;br /&gt;
|-&lt;br /&gt;
| 2082&lt;br /&gt;
| 0822&lt;br /&gt;
| Circum Design Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2083&lt;br /&gt;
| 0823&lt;br /&gt;
| Alberta Micro Electronic Center&lt;br /&gt;
|-&lt;br /&gt;
| 2084&lt;br /&gt;
| 0824&lt;br /&gt;
| Bestech&lt;br /&gt;
|-&lt;br /&gt;
| 2085&lt;br /&gt;
| 0825&lt;br /&gt;
| Lasar Fantasy&lt;br /&gt;
|-&lt;br /&gt;
| 2086&lt;br /&gt;
| 0826&lt;br /&gt;
| Pulsar&lt;br /&gt;
|-&lt;br /&gt;
| 2087&lt;br /&gt;
| 0827&lt;br /&gt;
| Ivis&lt;br /&gt;
|-&lt;br /&gt;
| 2088&lt;br /&gt;
| 0828&lt;br /&gt;
| Applied Engineering&lt;br /&gt;
|-&lt;br /&gt;
| 2089&lt;br /&gt;
| 0829&lt;br /&gt;
| Solid-State Design &amp;amp;amp; Development&lt;br /&gt;
|-&lt;br /&gt;
| 2090&lt;br /&gt;
| 082A&lt;br /&gt;
| Vison Quest&lt;br /&gt;
|-&lt;br /&gt;
| 2091&lt;br /&gt;
| 082B&lt;br /&gt;
| Seaview Software&lt;br /&gt;
|-&lt;br /&gt;
| 2092&lt;br /&gt;
| 082C&lt;br /&gt;
| BSC&lt;br /&gt;
| Mistakenly used by ADS (Advanced Development Software)&lt;br /&gt;
|-&lt;br /&gt;
| 2093&lt;br /&gt;
| 082D&lt;br /&gt;
| Bernd Culenfeld&lt;br /&gt;
|-&lt;br /&gt;
| 2094&lt;br /&gt;
| 082E&lt;br /&gt;
| American Liquid Light&lt;br /&gt;
|-&lt;br /&gt;
| 2095&lt;br /&gt;
| 082F&lt;br /&gt;
| CEGITES&lt;br /&gt;
|-&lt;br /&gt;
| 2096&lt;br /&gt;
| 0830&lt;br /&gt;
| Quadlite Computers Ltd.&lt;br /&gt;
| Originally registered to EV Industries&lt;br /&gt;
|-&lt;br /&gt;
| 2097&lt;br /&gt;
| 0831&lt;br /&gt;
| Silicon Peace&lt;br /&gt;
|-&lt;br /&gt;
| 2098&lt;br /&gt;
| 0832&lt;br /&gt;
| Black Belt Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2099&lt;br /&gt;
| 0833&lt;br /&gt;
| Village Tronic&lt;br /&gt;
| Originally registerd to Steve Yaeger&lt;br /&gt;
|-&lt;br /&gt;
| 2100&lt;br /&gt;
| 0834&lt;br /&gt;
| ReadySoft&lt;br /&gt;
|-&lt;br /&gt;
| 2101&lt;br /&gt;
| 0835&lt;br /&gt;
| Phoenix Micro Technologies&lt;br /&gt;
|-&lt;br /&gt;
| 2102&lt;br /&gt;
| 0836&lt;br /&gt;
| Advanced Systems &amp;amp; Software&lt;br /&gt;
| Orignally assigned to Preferred Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2103&lt;br /&gt;
| 0837&lt;br /&gt;
| Rombo Productions&lt;br /&gt;
|-&lt;br /&gt;
| 2104&lt;br /&gt;
| 0838&lt;br /&gt;
| Impulse Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2105&lt;br /&gt;
| 0839&lt;br /&gt;
| Beta Unlimited&lt;br /&gt;
|-&lt;br /&gt;
| 2106&lt;br /&gt;
| 083A&lt;br /&gt;
| Memory Expansion System, Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2107&lt;br /&gt;
| 083B&lt;br /&gt;
| Vortex Computer Systems GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2108&lt;br /&gt;
| 083C&lt;br /&gt;
| Platypus Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2109&lt;br /&gt;
| 083D&lt;br /&gt;
| Gigatron OHG&lt;br /&gt;
|-&lt;br /&gt;
| 2110&lt;br /&gt;
| 083E&lt;br /&gt;
| PG Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2111&lt;br /&gt;
| 083F&lt;br /&gt;
| New Technologies Group&lt;br /&gt;
|-&lt;br /&gt;
| 2112&lt;br /&gt;
| 0840&lt;br /&gt;
| Interactive Video Systems (IVS)&lt;br /&gt;
| Pacific Peripherals&lt;br /&gt;
|-&lt;br /&gt;
| 2113&lt;br /&gt;
| 0841&lt;br /&gt;
| Vector&lt;br /&gt;
| Originally registered to H. K. Computer&lt;br /&gt;
|-&lt;br /&gt;
| 2114&lt;br /&gt;
| 0842&lt;br /&gt;
| Pacific Digital&lt;br /&gt;
| Originally registered to C. H. Helfrich Elektronik&lt;br /&gt;
|-&lt;br /&gt;
| 2115&lt;br /&gt;
| 0843&lt;br /&gt;
| Xanadu&lt;br /&gt;
|-&lt;br /&gt;
| 2116&lt;br /&gt;
| 0844&lt;br /&gt;
| Pacific Digital&lt;br /&gt;
| Originally registered to AMS&lt;br /&gt;
|-&lt;br /&gt;
| 2117&lt;br /&gt;
| 0845&lt;br /&gt;
| X-Pert&lt;br /&gt;
|-&lt;br /&gt;
| 2118&lt;br /&gt;
| 0846&lt;br /&gt;
| The Amiga Centre&lt;br /&gt;
|-&lt;br /&gt;
| 2119&lt;br /&gt;
| 0847&lt;br /&gt;
| Digital Pacific&lt;br /&gt;
|-&lt;br /&gt;
| 2120&lt;br /&gt;
| 0848&lt;br /&gt;
| Solid State Leisure&lt;br /&gt;
|-&lt;br /&gt;
| 2121&lt;br /&gt;
| 0849&lt;br /&gt;
| Hydra Systems&lt;br /&gt;
| Originally registered to Analog Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2122&lt;br /&gt;
| 084A&lt;br /&gt;
| Cumana&lt;br /&gt;
|-&lt;br /&gt;
| 2123&lt;br /&gt;
| 084B&lt;br /&gt;
| KAPS 2C Conception&lt;br /&gt;
|-&lt;br /&gt;
| 2124&lt;br /&gt;
| 084C&lt;br /&gt;
| Mike Mason&lt;br /&gt;
|-&lt;br /&gt;
| 2125&lt;br /&gt;
| 084D&lt;br /&gt;
| For Your Eyes&lt;br /&gt;
|-&lt;br /&gt;
| 2126&lt;br /&gt;
| 084E&lt;br /&gt;
| Volkmar Breitfeld Computersysteme&lt;br /&gt;
|-&lt;br /&gt;
| 2127&lt;br /&gt;
| 084F&lt;br /&gt;
| Sunrize Industries&lt;br /&gt;
|-&lt;br /&gt;
| 2128&lt;br /&gt;
| 0850&lt;br /&gt;
| Scott Advanced Micro Designs&lt;br /&gt;
|-&lt;br /&gt;
| 2129&lt;br /&gt;
| 0851&lt;br /&gt;
| Digital Micronics&lt;br /&gt;
|-&lt;br /&gt;
| 2130&lt;br /&gt;
| 0852&lt;br /&gt;
| Alfa-Laval&lt;br /&gt;
|-&lt;br /&gt;
| 2131&lt;br /&gt;
| 0853&lt;br /&gt;
| Multigros A/S&lt;br /&gt;
|-&lt;br /&gt;
| 2132&lt;br /&gt;
| 0854&lt;br /&gt;
| Archos&lt;br /&gt;
|-&lt;br /&gt;
| 2133&lt;br /&gt;
| 0855&lt;br /&gt;
| Icom Simulations&lt;br /&gt;
|-&lt;br /&gt;
| 2134&lt;br /&gt;
| 0856&lt;br /&gt;
| Commodore Test Engineering Group&lt;br /&gt;
|-&lt;br /&gt;
| 2135&lt;br /&gt;
| 0857&lt;br /&gt;
| Microcreations&lt;br /&gt;
|-&lt;br /&gt;
| 2136&lt;br /&gt;
| 0858&lt;br /&gt;
| Shoestring Productions&lt;br /&gt;
|-&lt;br /&gt;
| 2137&lt;br /&gt;
| 0859&lt;br /&gt;
| Faberushi&lt;br /&gt;
|-&lt;br /&gt;
| 2138&lt;br /&gt;
| 085A&lt;br /&gt;
| Evesham Micro Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2139&lt;br /&gt;
| 085B&lt;br /&gt;
| Panagolin Laser Software&lt;br /&gt;
|-&lt;br /&gt;
| 2140&lt;br /&gt;
| 085C&lt;br /&gt;
| Thomas Rudloff&lt;br /&gt;
|-&lt;br /&gt;
| 2141&lt;br /&gt;
| 085D&lt;br /&gt;
| Daniel Hohabir&lt;br /&gt;
|-&lt;br /&gt;
| 2142&lt;br /&gt;
| 085E&lt;br /&gt;
| GfxBase, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2143&lt;br /&gt;
| 085F&lt;br /&gt;
| Axellabs&lt;br /&gt;
|-&lt;br /&gt;
| 2144&lt;br /&gt;
| 0860&lt;br /&gt;
| Roctec Electronics Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2145&lt;br /&gt;
| 0861&lt;br /&gt;
| Omega Datentechnik&lt;br /&gt;
|-&lt;br /&gt;
| 2146&lt;br /&gt;
| 0862&lt;br /&gt;
| Atlantis&lt;br /&gt;
|-&lt;br /&gt;
| 2147&lt;br /&gt;
| 0863&lt;br /&gt;
| Skytec Computers&lt;br /&gt;
|-&lt;br /&gt;
| 2148&lt;br /&gt;
| 0864&lt;br /&gt;
| Protar Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2149&lt;br /&gt;
| 0865&lt;br /&gt;
| ACS&lt;br /&gt;
|-&lt;br /&gt;
| 2150&lt;br /&gt;
| 0866&lt;br /&gt;
| Software Results Enterprises&lt;br /&gt;
| Originally registered to University of Illinois&lt;br /&gt;
|-&lt;br /&gt;
| 2151&lt;br /&gt;
| 0867&lt;br /&gt;
| Infinity Systems Design Group&lt;br /&gt;
|-&lt;br /&gt;
| 2152&lt;br /&gt;
| 0868&lt;br /&gt;
| Trade It&lt;br /&gt;
|-&lt;br /&gt;
| 2153&lt;br /&gt;
| 0869&lt;br /&gt;
| Suntec, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2154&lt;br /&gt;
| 086A&lt;br /&gt;
| DJW Micro Systems&lt;br /&gt;
| Originally registered to Tritec Marketing&lt;br /&gt;
|-&lt;br /&gt;
| 2155&lt;br /&gt;
| 086B&lt;br /&gt;
| Power Computing Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2156&lt;br /&gt;
| 086C&lt;br /&gt;
| MacroSystems&lt;br /&gt;
|-&lt;br /&gt;
| 2157&lt;br /&gt;
| 086D&lt;br /&gt;
| Masoboshi GmbH (DCE)&lt;br /&gt;
|-&lt;br /&gt;
| 2158&lt;br /&gt;
| 086E&lt;br /&gt;
| HAL Software Hardware Handel&lt;br /&gt;
|-&lt;br /&gt;
| 2159&lt;br /&gt;
| 086F&lt;br /&gt;
| Mainhattan Data&lt;br /&gt;
| Originally registered to Michael Lamm Computersysteme&lt;br /&gt;
|-&lt;br /&gt;
| 2160&lt;br /&gt;
| 0870&lt;br /&gt;
| Digital Processing System&lt;br /&gt;
| Originally registered to bbdp Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2161&lt;br /&gt;
| 0871&lt;br /&gt;
| Blue Ribbon Soundworks&lt;br /&gt;
| Originally registered to Design Computer Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2162&lt;br /&gt;
| 0872&lt;br /&gt;
| XPert&lt;br /&gt;
| Originally registered to The Station&lt;br /&gt;
|-&lt;br /&gt;
| 2163&lt;br /&gt;
| 0873&lt;br /&gt;
| DelaComp&lt;br /&gt;
| Originally registered to Bryan Williams&lt;br /&gt;
|-&lt;br /&gt;
| 2164&lt;br /&gt;
| 0874&lt;br /&gt;
| Superformance Computer Engineering GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2165&lt;br /&gt;
| 0875&lt;br /&gt;
| Overland Engineering&lt;br /&gt;
|-&lt;br /&gt;
| 2166&lt;br /&gt;
| 0876&lt;br /&gt;
| Thomas Hamren&lt;br /&gt;
|-&lt;br /&gt;
| 2167&lt;br /&gt;
| 0877&lt;br /&gt;
| Village Tronic&lt;br /&gt;
|-&lt;br /&gt;
| 2168&lt;br /&gt;
| 0878&lt;br /&gt;
| Toolbox Design&lt;br /&gt;
|-&lt;br /&gt;
| 2169&lt;br /&gt;
| 0879&lt;br /&gt;
| Digital Processing System&lt;br /&gt;
|-&lt;br /&gt;
| 2170&lt;br /&gt;
| 087A&lt;br /&gt;
| Superformance&lt;br /&gt;
|-&lt;br /&gt;
| 2171&lt;br /&gt;
| 087B&lt;br /&gt;
| Utilities Unlimited&lt;br /&gt;
|-&lt;br /&gt;
| 2172&lt;br /&gt;
| 087C&lt;br /&gt;
| phase 5&lt;br /&gt;
|-&lt;br /&gt;
| 2173&lt;br /&gt;
| 087D&lt;br /&gt;
| Juergen Kommos&lt;br /&gt;
|-&lt;br /&gt;
| 2174&lt;br /&gt;
| 087E&lt;br /&gt;
| Electronic Design&lt;br /&gt;
|-&lt;br /&gt;
| 2175&lt;br /&gt;
| 087F&lt;br /&gt;
| James Cook University of North Queensland&lt;br /&gt;
|-&lt;br /&gt;
| 2176&lt;br /&gt;
| 0880&lt;br /&gt;
| AmiTrix Development&lt;br /&gt;
|-&lt;br /&gt;
| 2177&lt;br /&gt;
| 0881&lt;br /&gt;
| Ferranti&lt;br /&gt;
|-&lt;br /&gt;
| 2178&lt;br /&gt;
| 0882&lt;br /&gt;
| Leviathan Development&lt;br /&gt;
|-&lt;br /&gt;
| 2179&lt;br /&gt;
| 0883&lt;br /&gt;
| United Video Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2180&lt;br /&gt;
| 0884&lt;br /&gt;
| GPSoft Pty. Ltd.&lt;br /&gt;
| Originally registered to Juergen Kommos&lt;br /&gt;
|-&lt;br /&gt;
| 2181&lt;br /&gt;
| 0885&lt;br /&gt;
| ArMAX&lt;br /&gt;
| Oliver Bausch&lt;br /&gt;
|-&lt;br /&gt;
| 2182&lt;br /&gt;
| 0886&lt;br /&gt;
| CP Computer&lt;br /&gt;
|-&lt;br /&gt;
| 2183&lt;br /&gt;
| 0887&lt;br /&gt;
| AMOK - Amiga Module &amp;amp;amp; Oberon Klub&lt;br /&gt;
|-&lt;br /&gt;
| 2184&lt;br /&gt;
| 0888&lt;br /&gt;
| ITEK Neser &amp;amp;amp; Sieber GbR&lt;br /&gt;
|-&lt;br /&gt;
| 2185&lt;br /&gt;
| 0889&lt;br /&gt;
| Phillip C. Lello&lt;br /&gt;
|-&lt;br /&gt;
| 2186&lt;br /&gt;
| 088A&lt;br /&gt;
| Cyborg Design Services&lt;br /&gt;
|-&lt;br /&gt;
| 2187&lt;br /&gt;
| 088B&lt;br /&gt;
| G2 Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2188&lt;br /&gt;
| 088C&lt;br /&gt;
| Pro System Computersysteme&lt;br /&gt;
|-&lt;br /&gt;
| 2189&lt;br /&gt;
| 088D&lt;br /&gt;
| ZEUS Electronic&lt;br /&gt;
| Originally registered to MSPI (Markt &amp;amp;amp; Technik)&lt;br /&gt;
|-&lt;br /&gt;
| 2190&lt;br /&gt;
| 088E&lt;br /&gt;
| Altatech&lt;br /&gt;
|-&lt;br /&gt;
| 2191&lt;br /&gt;
| 088F&lt;br /&gt;
| NewTek&lt;br /&gt;
|-&lt;br /&gt;
| 2192&lt;br /&gt;
| 0890&lt;br /&gt;
| M-TEC Hardware Design&lt;br /&gt;
| Originally registered to Hardware Design Udo Neuroth&lt;br /&gt;
|-&lt;br /&gt;
| 2193&lt;br /&gt;
| 0891&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
| Originally registered to Viona Development&lt;br /&gt;
|-&lt;br /&gt;
| 2194&lt;br /&gt;
| 0892&lt;br /&gt;
| Amitek&lt;br /&gt;
| Originally assigned to Marpet Developments&lt;br /&gt;
|-&lt;br /&gt;
| 2195&lt;br /&gt;
| 0893&lt;br /&gt;
| Ingenieurbuero Helfrich&lt;br /&gt;
|-&lt;br /&gt;
| 2196&lt;br /&gt;
| 0894&lt;br /&gt;
| The Neo Group&lt;br /&gt;
|-&lt;br /&gt;
| 2197&lt;br /&gt;
| 0895&lt;br /&gt;
| Cyon&lt;br /&gt;
|-&lt;br /&gt;
| 2198&lt;br /&gt;
| 0896&lt;br /&gt;
| Bob Research Group&lt;br /&gt;
|-&lt;br /&gt;
| 2199&lt;br /&gt;
| 0897&lt;br /&gt;
| Richmond Sound Design Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2200&lt;br /&gt;
| 0898&lt;br /&gt;
| US Cybernetics&lt;br /&gt;
|-&lt;br /&gt;
| 2201&lt;br /&gt;
| 0899&lt;br /&gt;
| Fulvio Ieva&lt;br /&gt;
|-&lt;br /&gt;
| 2202&lt;br /&gt;
| 089A&lt;br /&gt;
| Silicon Studio&lt;br /&gt;
|-&lt;br /&gt;
| 2203&lt;br /&gt;
| 089B&lt;br /&gt;
| MacroSystems (USA)&lt;br /&gt;
| Was named Micro System Devices&lt;br /&gt;
|-&lt;br /&gt;
| 2204&lt;br /&gt;
| 089C&lt;br /&gt;
| Conspector Entertainment&lt;br /&gt;
|-&lt;br /&gt;
| 2205&lt;br /&gt;
| 089D&lt;br /&gt;
| Laserforum&lt;br /&gt;
|-&lt;br /&gt;
| 2206&lt;br /&gt;
| 089E&lt;br /&gt;
| Elbox Computer&lt;br /&gt;
| Mistakenly used by Index Information Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2207&lt;br /&gt;
| 089F&lt;br /&gt;
| Applied Magic Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2208&lt;br /&gt;
| 08A0&lt;br /&gt;
| SDL Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2560&lt;br /&gt;
| 0A00&lt;br /&gt;
| Harms&lt;br /&gt;
|-&lt;br /&gt;
| 2588&lt;br /&gt;
| 0A1C&lt;br /&gt;
| A1K.org Community&lt;br /&gt;
|-&lt;br /&gt;
| 2640&lt;br /&gt;
| 0A50&lt;br /&gt;
| Micronik&lt;br /&gt;
|-&lt;br /&gt;
| 3084&lt;br /&gt;
| 0C0C&lt;br /&gt;
| Team 4&lt;br /&gt;
|-&lt;br /&gt;
| 3643&lt;br /&gt;
| 0E3B&lt;br /&gt;
| E3B&lt;br /&gt;
| Michael Boehmer&lt;br /&gt;
|-&lt;br /&gt;
| 3855&lt;br /&gt;
| 0F0F&lt;br /&gt;
| Micronik&lt;br /&gt;
|-&lt;br /&gt;
| 4096&lt;br /&gt;
| 1000&lt;br /&gt;
| MegaMicro&lt;br /&gt;
|-&lt;br /&gt;
| 4110&lt;br /&gt;
| 100E&lt;br /&gt;
| DigiFeX&lt;br /&gt;
|-&lt;br /&gt;
| 4136&lt;br /&gt;
| 1028&lt;br /&gt;
| Imtronics/Memphis&lt;br /&gt;
|-&lt;br /&gt;
| 4149&lt;br /&gt;
| 1035&lt;br /&gt;
| PROTAR&lt;br /&gt;
|-&lt;br /&gt;
| 4369&lt;br /&gt;
| 1111&lt;br /&gt;
| Frank Strauß Elektronik&lt;br /&gt;
| Also used by Kupke&lt;br /&gt;
|-&lt;br /&gt;
| 4626&lt;br /&gt;
| 1212&lt;br /&gt;
| Individual Computers&lt;br /&gt;
|-&lt;br /&gt;
| 4648&lt;br /&gt;
| 1228&lt;br /&gt;
| Flesch Hornemann Computer Elec.&lt;br /&gt;
|-&lt;br /&gt;
| 4680&lt;br /&gt;
| 1248&lt;br /&gt;
| Kupke Computertechnik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 4711&lt;br /&gt;
| 1267&lt;br /&gt;
| RBM digitaltechnik&lt;br /&gt;
|-&lt;br /&gt;
| 4754&lt;br /&gt;
| 1292&lt;br /&gt;
| MacroSystems&lt;br /&gt;
|-&lt;br /&gt;
| 5000&lt;br /&gt;
| 1388&lt;br /&gt;
| ITH&lt;br /&gt;
|-&lt;br /&gt;
| 5001&lt;br /&gt;
| 1389&lt;br /&gt;
| VMC&lt;br /&gt;
|-&lt;br /&gt;
| 5010&lt;br /&gt;
| 1392&lt;br /&gt;
| Ambience Creation Technology&lt;br /&gt;
|-&lt;br /&gt;
| 5011&lt;br /&gt;
| 1393&lt;br /&gt;
| Creative Development&lt;br /&gt;
|-&lt;br /&gt;
| 5012&lt;br /&gt;
| 1394&lt;br /&gt;
| Georg Braun&lt;br /&gt;
|-&lt;br /&gt;
| 5013&lt;br /&gt;
| 1395&lt;br /&gt;
| Swedish User Group of Amiga&lt;br /&gt;
|-&lt;br /&gt;
| 5014&lt;br /&gt;
| 1396&lt;br /&gt;
| Jakub Bednarski&lt;br /&gt;
|-&lt;br /&gt;
| 5015&lt;br /&gt;
| 1397&lt;br /&gt;
| KryoFlux, Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 5016&lt;br /&gt;
| 1398&lt;br /&gt;
| Igor Majstorovic&lt;br /&gt;
|-&lt;br /&gt;
| 5017&lt;br /&gt;
| 1399&lt;br /&gt;
| Alastair M. Robinson&lt;br /&gt;
|-&lt;br /&gt;
| 5018&lt;br /&gt;
| 139A&lt;br /&gt;
| Austex Software&lt;br /&gt;
|-&lt;br /&gt;
| 5019&lt;br /&gt;
| 139B&lt;br /&gt;
| Sören Gust&lt;br /&gt;
|-&lt;br /&gt;
| 5020&lt;br /&gt;
| 139C&lt;br /&gt;
| Rok Krajnc&lt;br /&gt;
|-&lt;br /&gt;
| 5030&lt;br /&gt;
| 13A6&lt;br /&gt;
| Tim Tashpulatov&lt;br /&gt;
|-&lt;br /&gt;
| 5040&lt;br /&gt;
| 13B0&lt;br /&gt;
| 7-bit&lt;br /&gt;
|-&lt;br /&gt;
| 5050&lt;br /&gt;
| 13BA&lt;br /&gt;
| Sakura IT&lt;br /&gt;
|-&lt;br /&gt;
| 5060&lt;br /&gt;
| 13C4&lt;br /&gt;
| FPGAArcade&lt;br /&gt;
|-&lt;br /&gt;
| 5070&lt;br /&gt;
| 13CE&lt;br /&gt;
| CancerSoft Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 5080&lt;br /&gt;
| 13D8&lt;br /&gt;
| Stephen Leary&lt;br /&gt;
|-&lt;br /&gt;
| 5090&lt;br /&gt;
| 13E2&lt;br /&gt;
| DMA Softlab LLC&lt;br /&gt;
|-&lt;br /&gt;
| 5100&lt;br /&gt;
| 13EC&lt;br /&gt;
| Brookhouse Engineering&lt;br /&gt;
|-&lt;br /&gt;
| 5110&lt;br /&gt;
| 13F6&lt;br /&gt;
| Eduardo Arana&lt;br /&gt;
|-&lt;br /&gt;
| 5120&lt;br /&gt;
| 1400&lt;br /&gt;
| CS-LAB&lt;br /&gt;
|-&lt;br /&gt;
| 5130&lt;br /&gt;
| 140A&lt;br /&gt;
| Robert Miranda&lt;br /&gt;
|-&lt;br /&gt;
| 5140&lt;br /&gt;
| 1414&lt;br /&gt;
| RastPort&lt;br /&gt;
|-&lt;br /&gt;
| 5132&lt;br /&gt;
| 140C&lt;br /&gt;
| UAS Interface Ltd6&lt;br /&gt;
|-&lt;br /&gt;
| 5150&lt;br /&gt;
| 141E&lt;br /&gt;
| Amiga Kit&lt;br /&gt;
|-&lt;br /&gt;
| 5160&lt;br /&gt;
| 1428&lt;br /&gt;
| Central Texas Commodore User Group&lt;br /&gt;
|-&lt;br /&gt;
| 5170&lt;br /&gt;
| 1432&lt;br /&gt;
| Confusion Research Center&lt;br /&gt;
|-&lt;br /&gt;
| 5180&lt;br /&gt;
| 143C&lt;br /&gt;
| Solar Soyuz Zaibatsu&lt;br /&gt;
|-&lt;br /&gt;
| 5190&lt;br /&gt;
| 1446&lt;br /&gt;
| BooBip&lt;br /&gt;
|-&lt;br /&gt;
| 5191&lt;br /&gt;
| 1447&lt;br /&gt;
| Matthias Hampel&lt;br /&gt;
|-&lt;br /&gt;
| 5192&lt;br /&gt;
| 1448&lt;br /&gt;
| dec0de Consulting Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 5193&lt;br /&gt;
| 1449&lt;br /&gt;
| Puppy Concepts&lt;br /&gt;
|-&lt;br /&gt;
| 5194&lt;br /&gt;
| 144A&lt;br /&gt;
| Open Amiga Hardware Repository&lt;br /&gt;
|-&lt;br /&gt;
| 5195&lt;br /&gt;
| 144B&lt;br /&gt;
| Double H Tech&lt;br /&gt;
|-&lt;br /&gt;
| 5196&lt;br /&gt;
| 144C&lt;br /&gt;
| Retromatik&lt;br /&gt;
|-&lt;br /&gt;
| 5500&lt;br /&gt;
| 157C&lt;br /&gt;
| Inhouse Information&lt;br /&gt;
|-&lt;br /&gt;
| 5768&lt;br /&gt;
| 1688&lt;br /&gt;
| Bio Con&lt;br /&gt;
|-&lt;br /&gt;
| 6148&lt;br /&gt;
| 1804&lt;br /&gt;
| HK-Computer&lt;br /&gt;
|-&lt;br /&gt;
| 6502&lt;br /&gt;
| 1966&lt;br /&gt;
| Cloanto&lt;br /&gt;
|-&lt;br /&gt;
| 6520&lt;br /&gt;
| 1978&lt;br /&gt;
| Oliver Gantert&lt;br /&gt;
|-&lt;br /&gt;
| 7777&lt;br /&gt;
| 1E61&lt;br /&gt;
| Rafal Gabriel Chyla&lt;br /&gt;
|-&lt;br /&gt;
| 8215&lt;br /&gt;
| 2017&lt;br /&gt;
| Vortex&lt;br /&gt;
|-&lt;br /&gt;
| 8244&lt;br /&gt;
| 2034&lt;br /&gt;
| Spirit Technology&lt;br /&gt;
|-&lt;br /&gt;
| 8290&lt;br /&gt;
| 2062&lt;br /&gt;
| Expansion Systems&lt;br /&gt;
|-&lt;br /&gt;
| 8448&lt;br /&gt;
| 2100&lt;br /&gt;
| ReadySoft&lt;br /&gt;
|-&lt;br /&gt;
| 8512&lt;br /&gt;
| 2140&lt;br /&gt;
| Phase 5 Digital Products&lt;br /&gt;
|-&lt;br /&gt;
| 8553&lt;br /&gt;
| 2169&lt;br /&gt;
| Digital Processing Systems Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 8704&lt;br /&gt;
| 2200&lt;br /&gt;
| ACT Elektronik&lt;br /&gt;
|-&lt;br /&gt;
| 8738&lt;br /&gt;
| 2222&lt;br /&gt;
| ACT Elektronik&lt;br /&gt;
|-&lt;br /&gt;
| 9512&lt;br /&gt;
| 2528&lt;br /&gt;
| Tower Technologies&lt;br /&gt;
|-&lt;br /&gt;
| 10676&lt;br /&gt;
| 29B4&lt;br /&gt;
| Electronic Design&lt;br /&gt;
|-&lt;br /&gt;
| 14195&lt;br /&gt;
| 3773&lt;br /&gt;
| Media-net-Point&lt;br /&gt;
|-&lt;br /&gt;
| 14501&lt;br /&gt;
| 38A5&lt;br /&gt;
| Petsoff, Finland&lt;br /&gt;
|-&lt;br /&gt;
| 16375&lt;br /&gt;
| 3FF7&lt;br /&gt;
| Uwe Gerlach&lt;br /&gt;
|-&lt;br /&gt;
| 16707&lt;br /&gt;
| 4143&lt;br /&gt;
| Ateo Concepts&lt;br /&gt;
|-&lt;br /&gt;
| 16708&lt;br /&gt;
| 4144&lt;br /&gt;
| ALiENDESiGN&lt;br /&gt;
|-&lt;br /&gt;
| 16945&lt;br /&gt;
| 4231&lt;br /&gt;
| A.C.T.&lt;br /&gt;
|-&lt;br /&gt;
| 17740&lt;br /&gt;
| 454C&lt;br /&gt;
| HK-Computer (ELSAT)&lt;br /&gt;
|-&lt;br /&gt;
| 18260&lt;br /&gt;
| 4754&lt;br /&gt;
| MacroSystems (Germany)&lt;br /&gt;
|-&lt;br /&gt;
| 19796&lt;br /&gt;
| 4D54&lt;br /&gt;
| Markt &amp;amp; Technik&lt;br /&gt;
|-&lt;br /&gt;
| 22359&lt;br /&gt;
| 5757&lt;br /&gt;
| Markt &amp;amp; Technik&lt;br /&gt;
|-&lt;br /&gt;
| 26464&lt;br /&gt;
| 6760&lt;br /&gt;
| Combitec&lt;br /&gt;
|-&lt;br /&gt;
| 26470&lt;br /&gt;
| 6766&lt;br /&gt;
| Combitec&lt;br /&gt;
|-&lt;br /&gt;
| 28014&lt;br /&gt;
| 6D6E&lt;br /&gt;
| MNT Media and Technology UG&lt;br /&gt;
|-&lt;br /&gt;
| 32768&lt;br /&gt;
| 8000&lt;br /&gt;
| M.A.S.T.&lt;br /&gt;
|-&lt;br /&gt;
| 42240&lt;br /&gt;
| A500&lt;br /&gt;
| Aethreum Digital&lt;br /&gt;
|-&lt;br /&gt;
| 43437&lt;br /&gt;
| A9AD&lt;br /&gt;
| Reis-Ware&lt;br /&gt;
|-&lt;br /&gt;
| 43521&lt;br /&gt;
| AA01&lt;br /&gt;
| Cameron&lt;br /&gt;
|-&lt;br /&gt;
| 43537&lt;br /&gt;
| AA11&lt;br /&gt;
| Reis-Ware&lt;br /&gt;
|-&lt;br /&gt;
| 44359&lt;br /&gt;
| AD47&lt;br /&gt;
| Matay&lt;br /&gt;
|-&lt;br /&gt;
| 46504&lt;br /&gt;
| B5A8&lt;br /&gt;
| Phoenix&lt;br /&gt;
|-&lt;br /&gt;
| 48879&lt;br /&gt;
| BEEF&lt;br /&gt;
| Swiss Mountain Dog Products&lt;br /&gt;
|-&lt;br /&gt;
| 49160&lt;br /&gt;
| C008&lt;br /&gt;
| Combitec&lt;br /&gt;
|-&lt;br /&gt;
| 61453&lt;br /&gt;
| F00D&lt;br /&gt;
| Forefront Technologies Inc.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
For any changes/additions to this registry see [[#How_to_Obtain_a_Manufacturer_Number|How to Obtain a Manufacturer Number]]&lt;/div&gt;</summary>
		<author><name>Costel Mincea</name></author>
	</entry>
	<entry>
		<id>https://wiki.amigaos.net/w/index.php?title=Amiga_Hardware_Manufacturer_ID_Registry&amp;diff=12599</id>
		<title>Amiga Hardware Manufacturer ID Registry</title>
		<link rel="alternate" type="text/html" href="https://wiki.amigaos.net/w/index.php?title=Amiga_Hardware_Manufacturer_ID_Registry&amp;diff=12599"/>
		<updated>2026-09-08T10:31:25Z</updated>

		<summary type="html">&lt;p&gt;Costel Mincea: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
= How to Obtain a Manufacturer Number =&lt;br /&gt;
&lt;br /&gt;
Manufacturer&#039;s numbers are assigned by the AmigaOS development team. To obtain your unique manufacturer number send a support request to [mailto:support@hyperion-entertainment.com support@hyperion-entertainment.com] including these information:&lt;br /&gt;
&lt;br /&gt;
 1. The name of the company or person which the number is assigned to&lt;br /&gt;
 &lt;br /&gt;
 2. Postal address/contact address&lt;br /&gt;
 &lt;br /&gt;
 3. Name of the contact person, with a corresponding e-mail address&lt;br /&gt;
 &lt;br /&gt;
 4. A brief description of the kind of products you want to produce&lt;br /&gt;
&lt;br /&gt;
= Your Manufacturer Number =&lt;br /&gt;
&lt;br /&gt;
Attention hardware manufacturers. If you are developing a hardware expansion product for the Classic Amiga (e.g. 500, 2000, 3000) then you will need to obtain a special manufacturer ID number from the AmigaOS development team to identify your product. This manufacturer number is used by the Amiga to link your hardware with its driver software at boot time.&lt;br /&gt;
&lt;br /&gt;
Your manufacturer number is part of the special protocol that the Amiga uses to automatically configure all expansion devices on the bus without the user having to cut jumpers or adjust dip switches. This is called auto-config.&lt;br /&gt;
&lt;br /&gt;
At start-up time, the system first polls each board in the system and assigns the board its own address space. If it is a memory board, its RAM is linked into the memory free pool. Later in the boot sequence, after DOS is initialized, the binddrivers program is run. Binddrivers will search the directory SYS:Expansion for the drivers that go with the boards.&lt;br /&gt;
&lt;br /&gt;
To do this binddrivers looks in the Tool Type field of all icon files in SYS:Expansion. If the first seven bytes of the Tool Type field are &amp;quot;PRODUCT&amp;quot;, then this is an icon file for a driver.&lt;br /&gt;
&lt;br /&gt;
Binddrivers will then attempt to match the drivers it has found with the boards that were found earlier. This is where your manufacturer number comes in.&lt;br /&gt;
&lt;br /&gt;
Your manufacturer number goes in two places. First, it is burned in hex form into the PAL which is part of ALL auto-config expansion products. Second, it appears in ASCII in the Tool Type field of the icon file for your product&#039;s driver. By matching these two numbers, the Amiga can automatically configure your board and bind it&#039;s software driver into the system as well.&lt;br /&gt;
&lt;br /&gt;
The manufacturer&#039;s number is a 16-bit ID which appears in PAL offsets $10-$17. There is also an 8-bit product number which you assign. The product number is for uniquely identifying different products from the same vendor. The product number will appear in PAL offsets $04-$07. This gives you a total of 24 bits to identify each of your products.&lt;br /&gt;
&lt;br /&gt;
These 24 bits of information in the PAL which identify your product are matched against the information in the Tool Type field of all icon files in the SYS:Expansion drawer. For example, suppose you are manufacturer #1019. You have two products, #1 and #2 which both use the same driver. The icon for your driver for these two products would have a Tool Type set to &amp;quot;PRODUCT=1019/1|1019/2&amp;quot;. This means: I am an icon for a driver that works with product number 1 or 2 from manufacturer 1019, now bind me. Spaces are not legal. Here are two other examples:&lt;br /&gt;
&lt;br /&gt;
; PRODUCT=1208/11&lt;br /&gt;
: is the Tool Type for a driver for product 11 from manufacturer number 1208.&lt;br /&gt;
&lt;br /&gt;
; PRODUCT=1017&lt;br /&gt;
: is the Tool Type for a driver for any product from manufacturer number 1017.&lt;br /&gt;
&lt;br /&gt;
For an informal explanation of the auto-configuration process, see the chapter on Software Expansion Architecture from the 2nd Annual Amiga Developer&#039;s Conference Notes (available on ADCD 2.1). For the details of timing, power, the PAL equations and PAL address specifications and the expansion library documentation, see sections 3.1 to 3.3 of the A500/A2000 Technical Reference Manual. The original auto-config spec appears in the A1000 Schematics and Expansion Specification.&lt;br /&gt;
&lt;br /&gt;
The auto-config process makes the addition of expansion products to the system very easy. All the user has to do is put the board in any slot and copy the driver from the release disk to his own SYS:Expansion drawer. Everything else is automatic. There are no jumpers or dip switches to set. Best of all, you will get a lot less support calls asking how to make your product work with the XYZ-Corp-battery-backed-clock.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
&lt;br /&gt;
Some notes on hardware manufacturer ID assignment.&lt;br /&gt;
&lt;br /&gt;
* Manufacturer ID numbers are assigned free of charge.&lt;br /&gt;
* Please provide the following information when requesting an ID:&lt;br /&gt;
*# Name of the company or person&lt;br /&gt;
*# Postal address/contact address&lt;br /&gt;
*# Name of the contact person, with a corresponding e-mail address&lt;br /&gt;
*# A brief description of the kind of products you want to produce&lt;br /&gt;
* All ID numbers smaller than 5000 must be considered unsafe because no information exists on which numbers exactly were taken during the time Commodore, Inc. disintegrated.&lt;br /&gt;
* ID numbers in the range 8192 to 18841 must be considered unsafe because some hardware developers mistook the numbers assigned to them to be given in hexadecimal format. Hence 0x2000 = 8192 and 0x4999 = 18841.&lt;br /&gt;
&lt;br /&gt;
= Example code =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
/*-----------------------------------------------*/&lt;br /&gt;
/* Here is a short program which will tell you   */&lt;br /&gt;
/* about the expansion boards configured in your */&lt;br /&gt;
/* system without you opening up the machine.    */&lt;br /&gt;
/* Code by Bill Koester of CATS                  */&lt;br /&gt;
/*-----------------------------------------------*/&lt;br /&gt;
#include &amp;lt;libraries/configvars.h&amp;gt;&lt;br /&gt;
#include &amp;lt;libraries/expansion.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
struct ExpansionBase *ExpansionBase;&lt;br /&gt;
&lt;br /&gt;
void cleanup();&lt;br /&gt;
void printdev();&lt;br /&gt;
&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
   struct ConfigDev *MyConfigDev;&lt;br /&gt;
&lt;br /&gt;
   /*----------------------------------*/&lt;br /&gt;
   /* Open the expansion library,      */&lt;br /&gt;
   /* if there is a problem then exit  */&lt;br /&gt;
   /*----------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   ExpansionBase =(struct ExpansionBase *) OpenLibrary(EXPANSIONNAME,0);&lt;br /&gt;
   if(ExpansionBase==NULL)&lt;br /&gt;
   {&lt;br /&gt;
      printf(&amp;quot;Error opening expansion library!!\n&amp;quot;);&lt;br /&gt;
      cleanup();&lt;br /&gt;
      exit(0);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   /*--------------------------------------------*/&lt;br /&gt;
   /* Use FindConfigDev to get info on the first */&lt;br /&gt;
   /* expansion board on the list maintained by  */&lt;br /&gt;
   /* Exec.  If there are no expansion boards in */&lt;br /&gt;
   /* the system then exit.                      */&lt;br /&gt;
   /*--------------------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   MyConfigDev = NULL;&lt;br /&gt;
&lt;br /&gt;
  /*--------------------------------------------------*/&lt;br /&gt;
  /* FindConfigDev(oldConfigDev,manufacturer,product) */&lt;br /&gt;
  /* oldConfigDev = NULL for the top of the list      */&lt;br /&gt;
  /* manufacturer = -1 for any manufacturer           */&lt;br /&gt;
  /* product      = -1 for any product                */&lt;br /&gt;
  /*--------------------------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   MyConfigDev = FindConfigDev(NULL,-1,-1);&lt;br /&gt;
&lt;br /&gt;
   if(MyConfigDev==NULL)&lt;br /&gt;
   {&lt;br /&gt;
      printf(&amp;quot;No Configured Devices found!!\n&amp;quot;);&lt;br /&gt;
      cleanup();&lt;br /&gt;
      exit(0);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   printdev(MyConfigDev);&lt;br /&gt;
&lt;br /&gt;
   /*-----------------------------------*/&lt;br /&gt;
   /* OK, there is at least one board,  */&lt;br /&gt;
   /* so loop and get the entire list   */&lt;br /&gt;
   /* printing as we go with printdev() */&lt;br /&gt;
   /*-----------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   while(MyConfigDev = FindConfigDev(MyConfigDev,-1,-1))&lt;br /&gt;
   {&lt;br /&gt;
      printdev(MyConfigDev);&lt;br /&gt;
   }&lt;br /&gt;
   cleanup();&lt;br /&gt;
   return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*-------------------*/&lt;br /&gt;
/* Close up shop...  */&lt;br /&gt;
/*-------------------*/&lt;br /&gt;
void cleanup()&lt;br /&gt;
{&lt;br /&gt;
   if(ExpansionBase)&lt;br /&gt;
      CloseLibrary(ExpansionBase);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*----------------------------------*/&lt;br /&gt;
/* Print out the contents of the    */&lt;br /&gt;
/* dev structure for this expansion */&lt;br /&gt;
/* product.                         */&lt;br /&gt;
/*----------------------------------*/&lt;br /&gt;
&lt;br /&gt;
void printdev(dev)&lt;br /&gt;
struct ConfigDev *dev;&lt;br /&gt;
{&lt;br /&gt;
   char buff[200];&lt;br /&gt;
&lt;br /&gt;
   printf(&amp;quot;Flags          = &amp;quot;);&lt;br /&gt;
   if(dev-&amp;gt;cd_Flags==NULL)&lt;br /&gt;
      printf(&amp;quot;NULL  &amp;quot;);&lt;br /&gt;
   if(dev-&amp;gt;cd_Flags&amp;amp;CDF_SHUTUP)&lt;br /&gt;
      printf(&amp;quot;CDF_SHUTUP  &amp;quot;);&lt;br /&gt;
   if(dev-&amp;gt;cd_Flags&amp;amp;CDF_CONFIGME)&lt;br /&gt;
      printf(&amp;quot;CDF_CONFIGME  &amp;quot;);&lt;br /&gt;
   printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
   printf(&amp;quot;Board Address  = %x\n&amp;quot;,dev-&amp;gt;cd_BoardAddr);&lt;br /&gt;
   printf(&amp;quot;Board Size     = %d bytes\n&amp;quot;,dev-&amp;gt;cd_BoardSize);&lt;br /&gt;
   printf(&amp;quot;Slot  Address  = %d\n&amp;quot;,dev-&amp;gt;cd_SlotAddr);&lt;br /&gt;
   printf(&amp;quot;Slot  Size     = %d\n&amp;quot;,dev-&amp;gt;cd_SlotSize);&lt;br /&gt;
   printf(&amp;quot;Driver code at   %x\n&amp;quot;,dev-&amp;gt;cd_Driver);&lt;br /&gt;
&lt;br /&gt;
   printf(&amp;quot;er_Type         = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Type);&lt;br /&gt;
   printf(&amp;quot;er_Product      = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Product);&lt;br /&gt;
   printf(&amp;quot;er_Flags        = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Flags);&lt;br /&gt;
   printf(&amp;quot;er_Reserved03   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved03);&lt;br /&gt;
   printf(&amp;quot;er_Manufacturer = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Manufacturer);&lt;br /&gt;
   printf(&amp;quot;er_SerialNumber = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_SerialNumber);&lt;br /&gt;
   printf(&amp;quot;er_InitDiagVec  = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_InitDiagVec);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0c   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0c);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0d   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0d);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0e   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0e);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0f   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0f);&lt;br /&gt;
&lt;br /&gt;
   printf(&amp;quot;Hit Return to continue:\n&amp;quot;);&lt;br /&gt;
   gets(buff);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Registry =&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! ID (decimal)&lt;br /&gt;
! ID (hexadecimal)&lt;br /&gt;
! Manufacturer&lt;br /&gt;
! Notes&lt;br /&gt;
|-&lt;br /&gt;
| 1&lt;br /&gt;
| 0001&lt;br /&gt;
| Micronik&lt;br /&gt;
|-&lt;br /&gt;
| 211&lt;br /&gt;
| 00D3&lt;br /&gt;
| Pacific Peripherals/Profex&lt;br /&gt;
|-&lt;br /&gt;
| 221&lt;br /&gt;
| 00DD&lt;br /&gt;
| Kupke Computertechnik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 256&lt;br /&gt;
| 0100&lt;br /&gt;
| Memphis&lt;br /&gt;
| Originally registered to MacroSystems US&lt;br /&gt;
|-&lt;br /&gt;
| 512&lt;br /&gt;
| 0200&lt;br /&gt;
| 3-State Computertechnik&lt;br /&gt;
|-&lt;br /&gt;
| 513&lt;br /&gt;
| 0201&lt;br /&gt;
| Commodore (Braunschweig)&lt;br /&gt;
|-&lt;br /&gt;
| 514&lt;br /&gt;
| 0202&lt;br /&gt;
| Commodore (West Chester)&lt;br /&gt;
|-&lt;br /&gt;
| 515&lt;br /&gt;
| 0203&lt;br /&gt;
| Commodore (West Chester)&lt;br /&gt;
| Originally registered to Combitech/Macrosystem&lt;br /&gt;
|-&lt;br /&gt;
| 756&lt;br /&gt;
| 02F4&lt;br /&gt;
| Progressive Peripherals &amp;amp; Software&lt;br /&gt;
|-&lt;br /&gt;
| 767&lt;br /&gt;
| 02FF&lt;br /&gt;
| Kolff Computer Supplies&lt;br /&gt;
|-&lt;br /&gt;
| 1001&lt;br /&gt;
| 03E9&lt;br /&gt;
| Tecmar&lt;br /&gt;
|-&lt;br /&gt;
| 1002&lt;br /&gt;
| 03EA&lt;br /&gt;
| Telesys&lt;br /&gt;
|-&lt;br /&gt;
| 1003&lt;br /&gt;
| 03EB&lt;br /&gt;
| The Micro-Forge&lt;br /&gt;
|-&lt;br /&gt;
| 1004&lt;br /&gt;
| 03EC&lt;br /&gt;
| Kronos/C Ltd.&lt;br /&gt;
| Originally registered to Card Co. (Supra)&lt;br /&gt;
|-&lt;br /&gt;
| 1005&lt;br /&gt;
| 03ED&lt;br /&gt;
| A-Squared&lt;br /&gt;
|-&lt;br /&gt;
| 1006&lt;br /&gt;
| 03EE&lt;br /&gt;
| Comspec Communications&lt;br /&gt;
|-&lt;br /&gt;
| 1007&lt;br /&gt;
| 03EF&lt;br /&gt;
| HT Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 1008&lt;br /&gt;
| 03F0&lt;br /&gt;
| RDS Software&lt;br /&gt;
|-&lt;br /&gt;
| 1009&lt;br /&gt;
| 03F1&lt;br /&gt;
| Anakin Research&lt;br /&gt;
|-&lt;br /&gt;
| 1010&lt;br /&gt;
| 03F2&lt;br /&gt;
| MicroBotics&lt;br /&gt;
|-&lt;br /&gt;
| 1011&lt;br /&gt;
| 03F3&lt;br /&gt;
| Bob Krauth&lt;br /&gt;
|-&lt;br /&gt;
| 1012&lt;br /&gt;
| 03F4&lt;br /&gt;
| Access Associates (Alegra)&lt;br /&gt;
|-&lt;br /&gt;
| 1013&lt;br /&gt;
| 03F5&lt;br /&gt;
| Mini Comp Systems Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 1014&lt;br /&gt;
| 03F6&lt;br /&gt;
| Cypress Technology&lt;br /&gt;
|-&lt;br /&gt;
| 1015&lt;br /&gt;
| 03F7&lt;br /&gt;
| Fuller Computers&lt;br /&gt;
|-&lt;br /&gt;
| 1016&lt;br /&gt;
| 03F8&lt;br /&gt;
| Galaxy Computers&lt;br /&gt;
|-&lt;br /&gt;
| 1017&lt;br /&gt;
| 03F9&lt;br /&gt;
| ADA Research&lt;br /&gt;
|-&lt;br /&gt;
| 1018&lt;br /&gt;
| 03FA&lt;br /&gt;
| Computer Service Italia&lt;br /&gt;
|-&lt;br /&gt;
| 1019&lt;br /&gt;
| 03FB&lt;br /&gt;
| Amigo&lt;br /&gt;
|-&lt;br /&gt;
| 1020&lt;br /&gt;
| 03FC&lt;br /&gt;
| Micro-Solutions Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1021&lt;br /&gt;
| 03FD&lt;br /&gt;
| Stacar International&lt;br /&gt;
|-&lt;br /&gt;
| 1022&lt;br /&gt;
| 03FE&lt;br /&gt;
| Video Precisions&lt;br /&gt;
|-&lt;br /&gt;
| 1023&lt;br /&gt;
| 03FF&lt;br /&gt;
| ASDG, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1025&lt;br /&gt;
| 0401&lt;br /&gt;
| Ing. Buero Kalawsky&lt;br /&gt;
|-&lt;br /&gt;
| 1026&lt;br /&gt;
| 0402&lt;br /&gt;
| Computer Tuning&lt;br /&gt;
|-&lt;br /&gt;
| 1027&lt;br /&gt;
| 0403&lt;br /&gt;
| Interplan Unternehmensberatung&lt;br /&gt;
|-&lt;br /&gt;
| 1028&lt;br /&gt;
| 0404&lt;br /&gt;
| Imtronics/Memphis&lt;br /&gt;
| Originally registered to Peter Ohlich&lt;br /&gt;
|-&lt;br /&gt;
| 1030&lt;br /&gt;
| 0406&lt;br /&gt;
| Commodore (Lowell University)&lt;br /&gt;
| Originally registered to Productivity Center&lt;br /&gt;
|-&lt;br /&gt;
| 1041&lt;br /&gt;
| 0411&lt;br /&gt;
| Design Labs&lt;br /&gt;
|-&lt;br /&gt;
| 1042&lt;br /&gt;
| 0412&lt;br /&gt;
| MCS&lt;br /&gt;
|-&lt;br /&gt;
| 1043&lt;br /&gt;
| 0413&lt;br /&gt;
| B. J. Freeman&lt;br /&gt;
|-&lt;br /&gt;
| 1044&lt;br /&gt;
| 0414&lt;br /&gt;
| Side Effects Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1045&lt;br /&gt;
| 0415&lt;br /&gt;
| Oklahoma Personal Comp.&lt;br /&gt;
|-&lt;br /&gt;
| 1046&lt;br /&gt;
| 0416&lt;br /&gt;
| Advanced Micro Innovations&lt;br /&gt;
|-&lt;br /&gt;
| 1047&lt;br /&gt;
| 0417&lt;br /&gt;
| Industrial Support Services&lt;br /&gt;
|-&lt;br /&gt;
| 1048&lt;br /&gt;
| 0418&lt;br /&gt;
| Technisoft&lt;br /&gt;
|-&lt;br /&gt;
| 1049&lt;br /&gt;
| 0419&lt;br /&gt;
| Prolific, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1050&lt;br /&gt;
| 041A&lt;br /&gt;
| Softeam, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1051&lt;br /&gt;
| 041B&lt;br /&gt;
| GRC Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 1052&lt;br /&gt;
| 041C&lt;br /&gt;
| David Lai&lt;br /&gt;
|-&lt;br /&gt;
| 1053&lt;br /&gt;
| 041D&lt;br /&gt;
| Ameristar Technologies&lt;br /&gt;
|-&lt;br /&gt;
| 1054&lt;br /&gt;
| 041E&lt;br /&gt;
| Cline Refrigeration&lt;br /&gt;
|-&lt;br /&gt;
| 1055&lt;br /&gt;
| 041F&lt;br /&gt;
| Cardiac Pacemakers, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1056&lt;br /&gt;
| 0420&lt;br /&gt;
| Supra Corp. (Creative Microsystems)&lt;br /&gt;
|-&lt;br /&gt;
| 1057&lt;br /&gt;
| 0421&lt;br /&gt;
| Wayne Diener&lt;br /&gt;
|-&lt;br /&gt;
| 1058&lt;br /&gt;
| 0422&lt;br /&gt;
| Computer Systems Associates (CSA)&lt;br /&gt;
|-&lt;br /&gt;
| 1059&lt;br /&gt;
| 0423&lt;br /&gt;
| Trionix, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1060&lt;br /&gt;
| 0424&lt;br /&gt;
| David Lucas&lt;br /&gt;
|-&lt;br /&gt;
| 1061&lt;br /&gt;
| 0425&lt;br /&gt;
| Analog Precision&lt;br /&gt;
| Also assigned to D &amp;amp; L Distributing&lt;br /&gt;
|-&lt;br /&gt;
| 1267&lt;br /&gt;
| 04F3&lt;br /&gt;
| RBM Digitaltechnik&lt;br /&gt;
|-&lt;br /&gt;
| 1282&lt;br /&gt;
| 0502&lt;br /&gt;
| M-TEC Hardware Design&lt;br /&gt;
|-&lt;br /&gt;
| 1337&lt;br /&gt;
| 0539&lt;br /&gt;
| Thomas Stenzel (DaFR34K)&lt;br /&gt;
|-&lt;br /&gt;
| 1576&lt;br /&gt;
| 0628&lt;br /&gt;
| Boris Križma&lt;br /&gt;
|-&lt;br /&gt;
| 1761&lt;br /&gt;
| 06E1&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
|-&lt;br /&gt;
| 1803&lt;br /&gt;
| 070B&lt;br /&gt;
| UAE Amiga Emulator&lt;br /&gt;
|-&lt;br /&gt;
| 2002&lt;br /&gt;
| 07D2&lt;br /&gt;
| Mimetics Corp.&lt;br /&gt;
|-&lt;br /&gt;
| 2003&lt;br /&gt;
| 07D3&lt;br /&gt;
| ACDA&lt;br /&gt;
|-&lt;br /&gt;
| 2004&lt;br /&gt;
| 07D4&lt;br /&gt;
| Finn R. Jacobsen&lt;br /&gt;
|-&lt;br /&gt;
| 2005&lt;br /&gt;
| 07D5&lt;br /&gt;
| Elthen Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2006&lt;br /&gt;
| 07D6&lt;br /&gt;
| Nine Tiles Computer Systems Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2007&lt;br /&gt;
| 07D7&lt;br /&gt;
| Analog Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2008&lt;br /&gt;
| 07D8&lt;br /&gt;
| Bell &amp;amp;amp; Howell&lt;br /&gt;
|-&lt;br /&gt;
| 2009&lt;br /&gt;
| 07D9&lt;br /&gt;
| Roland Kochler&lt;br /&gt;
|-&lt;br /&gt;
| 2010&lt;br /&gt;
| 07DA&lt;br /&gt;
| Byte Corp.&lt;br /&gt;
|-&lt;br /&gt;
| 2011&lt;br /&gt;
| 07DB&lt;br /&gt;
| Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 2012&lt;br /&gt;
| 07DC&lt;br /&gt;
| DKB, Inc.&lt;br /&gt;
| Previously named Michigan Software&lt;br /&gt;
|-&lt;br /&gt;
| 2013&lt;br /&gt;
| 07DD&lt;br /&gt;
| Pacific Peripherals&lt;br /&gt;
|-&lt;br /&gt;
| 2014&lt;br /&gt;
| 07DE&lt;br /&gt;
| Sysaphus Software&lt;br /&gt;
|-&lt;br /&gt;
| 2015&lt;br /&gt;
| 07DF&lt;br /&gt;
| Digitronics&lt;br /&gt;
|-&lt;br /&gt;
| 2016&lt;br /&gt;
| 07E0&lt;br /&gt;
| Akron Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2017&lt;br /&gt;
| 07E1&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
|-&lt;br /&gt;
| 2018&lt;br /&gt;
| 07E2&lt;br /&gt;
| Calmos&lt;br /&gt;
|-&lt;br /&gt;
| 2019&lt;br /&gt;
| 07E3&lt;br /&gt;
| Dover Research&lt;br /&gt;
|-&lt;br /&gt;
| 2020&lt;br /&gt;
| 07E4&lt;br /&gt;
| David Krehbiel&lt;br /&gt;
|-&lt;br /&gt;
| 2021&lt;br /&gt;
| 07E5&lt;br /&gt;
| Synergy Peripheral Systems&lt;br /&gt;
| Also known as California Access&lt;br /&gt;
|-&lt;br /&gt;
| 2022&lt;br /&gt;
| 07E6&lt;br /&gt;
| Xetec&lt;br /&gt;
|-&lt;br /&gt;
| 2023&lt;br /&gt;
| 07E7&lt;br /&gt;
| Micron Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2024&lt;br /&gt;
| 07E8&lt;br /&gt;
| CH Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2025&lt;br /&gt;
| 07E9&lt;br /&gt;
| American Liquid Light&lt;br /&gt;
|-&lt;br /&gt;
| 2026&lt;br /&gt;
| 07EA&lt;br /&gt;
| Progressive Peripherals &amp;amp;amp; Software&lt;br /&gt;
| Also used by Ateo&lt;br /&gt;
|-&lt;br /&gt;
| 2027&lt;br /&gt;
| 07EB&lt;br /&gt;
| Wicat Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2028&lt;br /&gt;
| 07EC&lt;br /&gt;
| Applied Systems &amp;amp;amp; Peripherals&lt;br /&gt;
|-&lt;br /&gt;
| 2029&lt;br /&gt;
| 07ED&lt;br /&gt;
| Delaware Valley Software&lt;br /&gt;
|-&lt;br /&gt;
| 2030&lt;br /&gt;
| 07EE&lt;br /&gt;
| Palomax&lt;br /&gt;
|-&lt;br /&gt;
| 2031&lt;br /&gt;
| 07EF&lt;br /&gt;
| Incognito Software&lt;br /&gt;
|-&lt;br /&gt;
| 2032&lt;br /&gt;
| 07F0&lt;br /&gt;
| Jadesign&lt;br /&gt;
|-&lt;br /&gt;
| 2033&lt;br /&gt;
| 07F1&lt;br /&gt;
| BVR&lt;br /&gt;
|-&lt;br /&gt;
| 2034&lt;br /&gt;
| 07F2&lt;br /&gt;
| Spirit Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2035&lt;br /&gt;
| 07F3&lt;br /&gt;
| Spirit Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2036&lt;br /&gt;
| 07F4&lt;br /&gt;
| Atronic&lt;br /&gt;
|-&lt;br /&gt;
| 2037&lt;br /&gt;
| 07F5&lt;br /&gt;
| Scott Karlin&lt;br /&gt;
|-&lt;br /&gt;
| 2038&lt;br /&gt;
| 07F6&lt;br /&gt;
| Howitch&lt;br /&gt;
|-&lt;br /&gt;
| 2039&lt;br /&gt;
| 07F7&lt;br /&gt;
| Sullivan Brothers Visual Engineers&lt;br /&gt;
|-&lt;br /&gt;
| 2040&lt;br /&gt;
| 07F8&lt;br /&gt;
| G I T&lt;br /&gt;
|-&lt;br /&gt;
| 2041&lt;br /&gt;
| 07F9&lt;br /&gt;
| Amigo Business Computers&lt;br /&gt;
|-&lt;br /&gt;
| 2042&lt;br /&gt;
| 07FA&lt;br /&gt;
| Micro E Ab&lt;br /&gt;
|-&lt;br /&gt;
| 2043&lt;br /&gt;
| 07FB&lt;br /&gt;
| Ralph Kruse&lt;br /&gt;
|-&lt;br /&gt;
| 2044&lt;br /&gt;
| 07FC&lt;br /&gt;
| Clearpoint Research&lt;br /&gt;
|-&lt;br /&gt;
| 2045&lt;br /&gt;
| 07FD&lt;br /&gt;
| Kodiak&lt;br /&gt;
|-&lt;br /&gt;
| 2046&lt;br /&gt;
| 07FE&lt;br /&gt;
| BSC&lt;br /&gt;
| Originally registered to Phoenix Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2047&lt;br /&gt;
| 07FF&lt;br /&gt;
| No Name Shown&lt;br /&gt;
|-&lt;br /&gt;
| 2048&lt;br /&gt;
| 0800&lt;br /&gt;
| Commodore Braunschweig&lt;br /&gt;
|-&lt;br /&gt;
| 2049&lt;br /&gt;
| 0801&lt;br /&gt;
| BSC&lt;br /&gt;
| Originally registered to Elaborate Bytes&lt;br /&gt;
|-&lt;br /&gt;
| 2050&lt;br /&gt;
| 0802&lt;br /&gt;
| Kronos/C Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2051&lt;br /&gt;
| 0803&lt;br /&gt;
| Spartanics&lt;br /&gt;
|-&lt;br /&gt;
| 2052&lt;br /&gt;
| 0804&lt;br /&gt;
| Jochheim Computer Tuning&lt;br /&gt;
|-&lt;br /&gt;
| 2053&lt;br /&gt;
| 0805&lt;br /&gt;
| Trans Data Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2054&lt;br /&gt;
| 0806&lt;br /&gt;
| Applied Systems &amp;amp;amp; Peripherals Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2055&lt;br /&gt;
| 0807&lt;br /&gt;
| Checkpoint Technologies&lt;br /&gt;
| Originally registered to Amiga Solutions&lt;br /&gt;
|-&lt;br /&gt;
| 2056&lt;br /&gt;
| 0808&lt;br /&gt;
| Adept Development&lt;br /&gt;
|-&lt;br /&gt;
| 2057&lt;br /&gt;
| 0809&lt;br /&gt;
| Advanced Computer Design&lt;br /&gt;
|-&lt;br /&gt;
| 2058&lt;br /&gt;
| 080A&lt;br /&gt;
| Sir Netics&lt;br /&gt;
|-&lt;br /&gt;
| 2059&lt;br /&gt;
| 080B&lt;br /&gt;
| Expert Services&lt;br /&gt;
|-&lt;br /&gt;
| 2060&lt;br /&gt;
| 080C&lt;br /&gt;
| Digital Art Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2061&lt;br /&gt;
| 080D&lt;br /&gt;
| Adept Development&lt;br /&gt;
|-&lt;br /&gt;
| 2062&lt;br /&gt;
| 080E&lt;br /&gt;
| Expansion Technologies (Expansion Systems)&lt;br /&gt;
|-&lt;br /&gt;
| 2063&lt;br /&gt;
| 080F&lt;br /&gt;
| Alphatech&lt;br /&gt;
|-&lt;br /&gt;
| 2064&lt;br /&gt;
| 0810&lt;br /&gt;
| Edotronik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2065&lt;br /&gt;
| 0811&lt;br /&gt;
| California Access/Synergy&lt;br /&gt;
| Originally registered to Logical Design Works&lt;br /&gt;
|-&lt;br /&gt;
| 2066&lt;br /&gt;
| 0812&lt;br /&gt;
| Bowden, Williams, Full &amp;amp; Assoc.&lt;br /&gt;
|-&lt;br /&gt;
| 2067&lt;br /&gt;
| 0813&lt;br /&gt;
| NES, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2068&lt;br /&gt;
| 0814&lt;br /&gt;
| Amdev&lt;br /&gt;
|-&lt;br /&gt;
| 2069&lt;br /&gt;
| 0815&lt;br /&gt;
| Big Brother Security Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2070&lt;br /&gt;
| 0816&lt;br /&gt;
| Active Circuits Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2071&lt;br /&gt;
| 0817&lt;br /&gt;
| ICD, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2072&lt;br /&gt;
| 0818&lt;br /&gt;
| Multi-Meg Electronique&lt;br /&gt;
|-&lt;br /&gt;
| 2073&lt;br /&gt;
| 0819&lt;br /&gt;
| Kupke Computertechnik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2074&lt;br /&gt;
| 081A&lt;br /&gt;
| The Checkered Ball&lt;br /&gt;
|-&lt;br /&gt;
| 2075&lt;br /&gt;
| 081B&lt;br /&gt;
| Hi Tension Computer Services Ltd. (UK)&lt;br /&gt;
|-&lt;br /&gt;
| 2076&lt;br /&gt;
| 081C&lt;br /&gt;
| Alfa Data&lt;br /&gt;
| Originally assigned to Elmtech Research, Ltd. (UK)&lt;br /&gt;
|-&lt;br /&gt;
| 2077&lt;br /&gt;
| 081D&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
| Originally registered to Clartscreen, Ltd. (UK)&lt;br /&gt;
|-&lt;br /&gt;
| 2078&lt;br /&gt;
| 081E&lt;br /&gt;
| Interworks&lt;br /&gt;
|-&lt;br /&gt;
| 2079&lt;br /&gt;
| 081F&lt;br /&gt;
| Galysh Enterprises&lt;br /&gt;
|-&lt;br /&gt;
| 2080&lt;br /&gt;
| 0820&lt;br /&gt;
| Hardital Synthesis&lt;br /&gt;
| Originally registered to Realtime Games Software Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2081&lt;br /&gt;
| 0821&lt;br /&gt;
| GBS&lt;br /&gt;
|-&lt;br /&gt;
| 2082&lt;br /&gt;
| 0822&lt;br /&gt;
| Circum Design Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2083&lt;br /&gt;
| 0823&lt;br /&gt;
| Alberta Micro Electronic Center&lt;br /&gt;
|-&lt;br /&gt;
| 2084&lt;br /&gt;
| 0824&lt;br /&gt;
| Bestech&lt;br /&gt;
|-&lt;br /&gt;
| 2085&lt;br /&gt;
| 0825&lt;br /&gt;
| Lasar Fantasy&lt;br /&gt;
|-&lt;br /&gt;
| 2086&lt;br /&gt;
| 0826&lt;br /&gt;
| Pulsar&lt;br /&gt;
|-&lt;br /&gt;
| 2087&lt;br /&gt;
| 0827&lt;br /&gt;
| Ivis&lt;br /&gt;
|-&lt;br /&gt;
| 2088&lt;br /&gt;
| 0828&lt;br /&gt;
| Applied Engineering&lt;br /&gt;
|-&lt;br /&gt;
| 2089&lt;br /&gt;
| 0829&lt;br /&gt;
| Solid-State Design &amp;amp;amp; Development&lt;br /&gt;
|-&lt;br /&gt;
| 2090&lt;br /&gt;
| 082A&lt;br /&gt;
| Vison Quest&lt;br /&gt;
|-&lt;br /&gt;
| 2091&lt;br /&gt;
| 082B&lt;br /&gt;
| Seaview Software&lt;br /&gt;
|-&lt;br /&gt;
| 2092&lt;br /&gt;
| 082C&lt;br /&gt;
| BSC&lt;br /&gt;
| Mistakenly used by ADS (Advanced Development Software)&lt;br /&gt;
|-&lt;br /&gt;
| 2093&lt;br /&gt;
| 082D&lt;br /&gt;
| Bernd Culenfeld&lt;br /&gt;
|-&lt;br /&gt;
| 2094&lt;br /&gt;
| 082E&lt;br /&gt;
| American Liquid Light&lt;br /&gt;
|-&lt;br /&gt;
| 2095&lt;br /&gt;
| 082F&lt;br /&gt;
| CEGITES&lt;br /&gt;
|-&lt;br /&gt;
| 2096&lt;br /&gt;
| 0830&lt;br /&gt;
| Quadlite Computers Ltd.&lt;br /&gt;
| Originally registered to EV Industries&lt;br /&gt;
|-&lt;br /&gt;
| 2097&lt;br /&gt;
| 0831&lt;br /&gt;
| Silicon Peace&lt;br /&gt;
|-&lt;br /&gt;
| 2098&lt;br /&gt;
| 0832&lt;br /&gt;
| Black Belt Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2099&lt;br /&gt;
| 0833&lt;br /&gt;
| Village Tronic&lt;br /&gt;
| Originally registerd to Steve Yaeger&lt;br /&gt;
|-&lt;br /&gt;
| 2100&lt;br /&gt;
| 0834&lt;br /&gt;
| ReadySoft&lt;br /&gt;
|-&lt;br /&gt;
| 2101&lt;br /&gt;
| 0835&lt;br /&gt;
| Phoenix Micro Technologies&lt;br /&gt;
|-&lt;br /&gt;
| 2102&lt;br /&gt;
| 0836&lt;br /&gt;
| Advanced Systems &amp;amp; Software&lt;br /&gt;
| Orignally assigned to Preferred Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2103&lt;br /&gt;
| 0837&lt;br /&gt;
| Rombo Productions&lt;br /&gt;
|-&lt;br /&gt;
| 2104&lt;br /&gt;
| 0838&lt;br /&gt;
| Impulse Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2105&lt;br /&gt;
| 0839&lt;br /&gt;
| Beta Unlimited&lt;br /&gt;
|-&lt;br /&gt;
| 2106&lt;br /&gt;
| 083A&lt;br /&gt;
| Memory Expansion System, Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2107&lt;br /&gt;
| 083B&lt;br /&gt;
| Vortex Computer Systems GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2108&lt;br /&gt;
| 083C&lt;br /&gt;
| Platypus Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2109&lt;br /&gt;
| 083D&lt;br /&gt;
| Gigatron OHG&lt;br /&gt;
|-&lt;br /&gt;
| 2110&lt;br /&gt;
| 083E&lt;br /&gt;
| PG Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2111&lt;br /&gt;
| 083F&lt;br /&gt;
| New Technologies Group&lt;br /&gt;
|-&lt;br /&gt;
| 2112&lt;br /&gt;
| 0840&lt;br /&gt;
| Interactive Video Systems (IVS)&lt;br /&gt;
| Pacific Peripherals&lt;br /&gt;
|-&lt;br /&gt;
| 2113&lt;br /&gt;
| 0841&lt;br /&gt;
| Vector&lt;br /&gt;
| Originally registered to H. K. Computer&lt;br /&gt;
|-&lt;br /&gt;
| 2114&lt;br /&gt;
| 0842&lt;br /&gt;
| Pacific Digital&lt;br /&gt;
| Originally registered to C. H. Helfrich Elektronik&lt;br /&gt;
|-&lt;br /&gt;
| 2115&lt;br /&gt;
| 0843&lt;br /&gt;
| Xanadu&lt;br /&gt;
|-&lt;br /&gt;
| 2116&lt;br /&gt;
| 0844&lt;br /&gt;
| Pacific Digital&lt;br /&gt;
| Originally registered to AMS&lt;br /&gt;
|-&lt;br /&gt;
| 2117&lt;br /&gt;
| 0845&lt;br /&gt;
| X-Pert&lt;br /&gt;
|-&lt;br /&gt;
| 2118&lt;br /&gt;
| 0846&lt;br /&gt;
| The Amiga Centre&lt;br /&gt;
|-&lt;br /&gt;
| 2119&lt;br /&gt;
| 0847&lt;br /&gt;
| Digital Pacific&lt;br /&gt;
|-&lt;br /&gt;
| 2120&lt;br /&gt;
| 0848&lt;br /&gt;
| Solid State Leisure&lt;br /&gt;
|-&lt;br /&gt;
| 2121&lt;br /&gt;
| 0849&lt;br /&gt;
| Hydra Systems&lt;br /&gt;
| Originally registered to Analog Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2122&lt;br /&gt;
| 084A&lt;br /&gt;
| Cumana&lt;br /&gt;
|-&lt;br /&gt;
| 2123&lt;br /&gt;
| 084B&lt;br /&gt;
| KAPS 2C Conception&lt;br /&gt;
|-&lt;br /&gt;
| 2124&lt;br /&gt;
| 084C&lt;br /&gt;
| Mike Mason&lt;br /&gt;
|-&lt;br /&gt;
| 2125&lt;br /&gt;
| 084D&lt;br /&gt;
| For Your Eyes&lt;br /&gt;
|-&lt;br /&gt;
| 2126&lt;br /&gt;
| 084E&lt;br /&gt;
| Volkmar Breitfeld Computersysteme&lt;br /&gt;
|-&lt;br /&gt;
| 2127&lt;br /&gt;
| 084F&lt;br /&gt;
| Sunrize Industries&lt;br /&gt;
|-&lt;br /&gt;
| 2128&lt;br /&gt;
| 0850&lt;br /&gt;
| Scott Advanced Micro Designs&lt;br /&gt;
|-&lt;br /&gt;
| 2129&lt;br /&gt;
| 0851&lt;br /&gt;
| Digital Micronics&lt;br /&gt;
|-&lt;br /&gt;
| 2130&lt;br /&gt;
| 0852&lt;br /&gt;
| Alfa-Laval&lt;br /&gt;
|-&lt;br /&gt;
| 2131&lt;br /&gt;
| 0853&lt;br /&gt;
| Multigros A/S&lt;br /&gt;
|-&lt;br /&gt;
| 2132&lt;br /&gt;
| 0854&lt;br /&gt;
| Archos&lt;br /&gt;
|-&lt;br /&gt;
| 2133&lt;br /&gt;
| 0855&lt;br /&gt;
| Icom Simulations&lt;br /&gt;
|-&lt;br /&gt;
| 2134&lt;br /&gt;
| 0856&lt;br /&gt;
| Commodore Test Engineering Group&lt;br /&gt;
|-&lt;br /&gt;
| 2135&lt;br /&gt;
| 0857&lt;br /&gt;
| Microcreations&lt;br /&gt;
|-&lt;br /&gt;
| 2136&lt;br /&gt;
| 0858&lt;br /&gt;
| Shoestring Productions&lt;br /&gt;
|-&lt;br /&gt;
| 2137&lt;br /&gt;
| 0859&lt;br /&gt;
| Faberushi&lt;br /&gt;
|-&lt;br /&gt;
| 2138&lt;br /&gt;
| 085A&lt;br /&gt;
| Evesham Micro Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2139&lt;br /&gt;
| 085B&lt;br /&gt;
| Panagolin Laser Software&lt;br /&gt;
|-&lt;br /&gt;
| 2140&lt;br /&gt;
| 085C&lt;br /&gt;
| Thomas Rudloff&lt;br /&gt;
|-&lt;br /&gt;
| 2141&lt;br /&gt;
| 085D&lt;br /&gt;
| Daniel Hohabir&lt;br /&gt;
|-&lt;br /&gt;
| 2142&lt;br /&gt;
| 085E&lt;br /&gt;
| GfxBase, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2143&lt;br /&gt;
| 085F&lt;br /&gt;
| Axellabs&lt;br /&gt;
|-&lt;br /&gt;
| 2144&lt;br /&gt;
| 0860&lt;br /&gt;
| Roctec Electronics Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2145&lt;br /&gt;
| 0861&lt;br /&gt;
| Omega Datentechnik&lt;br /&gt;
|-&lt;br /&gt;
| 2146&lt;br /&gt;
| 0862&lt;br /&gt;
| Atlantis&lt;br /&gt;
|-&lt;br /&gt;
| 2147&lt;br /&gt;
| 0863&lt;br /&gt;
| Skytec Computers&lt;br /&gt;
|-&lt;br /&gt;
| 2148&lt;br /&gt;
| 0864&lt;br /&gt;
| Protar Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2149&lt;br /&gt;
| 0865&lt;br /&gt;
| ACS&lt;br /&gt;
|-&lt;br /&gt;
| 2150&lt;br /&gt;
| 0866&lt;br /&gt;
| Software Results Enterprises&lt;br /&gt;
| Originally registered to University of Illinois&lt;br /&gt;
|-&lt;br /&gt;
| 2151&lt;br /&gt;
| 0867&lt;br /&gt;
| Infinity Systems Design Group&lt;br /&gt;
|-&lt;br /&gt;
| 2152&lt;br /&gt;
| 0868&lt;br /&gt;
| Trade It&lt;br /&gt;
|-&lt;br /&gt;
| 2153&lt;br /&gt;
| 0869&lt;br /&gt;
| Suntec, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2154&lt;br /&gt;
| 086A&lt;br /&gt;
| DJW Micro Systems&lt;br /&gt;
| Originally registered to Tritec Marketing&lt;br /&gt;
|-&lt;br /&gt;
| 2155&lt;br /&gt;
| 086B&lt;br /&gt;
| Power Computing Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2156&lt;br /&gt;
| 086C&lt;br /&gt;
| MacroSystems&lt;br /&gt;
|-&lt;br /&gt;
| 2157&lt;br /&gt;
| 086D&lt;br /&gt;
| Masoboshi GmbH (DCE)&lt;br /&gt;
|-&lt;br /&gt;
| 2158&lt;br /&gt;
| 086E&lt;br /&gt;
| HAL Software Hardware Handel&lt;br /&gt;
|-&lt;br /&gt;
| 2159&lt;br /&gt;
| 086F&lt;br /&gt;
| Mainhattan Data&lt;br /&gt;
| Originally registered to Michael Lamm Computersysteme&lt;br /&gt;
|-&lt;br /&gt;
| 2160&lt;br /&gt;
| 0870&lt;br /&gt;
| Digital Processing System&lt;br /&gt;
| Originally registered to bbdp Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2161&lt;br /&gt;
| 0871&lt;br /&gt;
| Blue Ribbon Soundworks&lt;br /&gt;
| Originally registered to Design Computer Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2162&lt;br /&gt;
| 0872&lt;br /&gt;
| XPert&lt;br /&gt;
| Originally registered to The Station&lt;br /&gt;
|-&lt;br /&gt;
| 2163&lt;br /&gt;
| 0873&lt;br /&gt;
| DelaComp&lt;br /&gt;
| Originally registered to Bryan Williams&lt;br /&gt;
|-&lt;br /&gt;
| 2164&lt;br /&gt;
| 0874&lt;br /&gt;
| Superformance Computer Engineering GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2165&lt;br /&gt;
| 0875&lt;br /&gt;
| Overland Engineering&lt;br /&gt;
|-&lt;br /&gt;
| 2166&lt;br /&gt;
| 0876&lt;br /&gt;
| Thomas Hamren&lt;br /&gt;
|-&lt;br /&gt;
| 2167&lt;br /&gt;
| 0877&lt;br /&gt;
| Village Tronic&lt;br /&gt;
|-&lt;br /&gt;
| 2168&lt;br /&gt;
| 0878&lt;br /&gt;
| Toolbox Design&lt;br /&gt;
|-&lt;br /&gt;
| 2169&lt;br /&gt;
| 0879&lt;br /&gt;
| Digital Processing System&lt;br /&gt;
|-&lt;br /&gt;
| 2170&lt;br /&gt;
| 087A&lt;br /&gt;
| Superformance&lt;br /&gt;
|-&lt;br /&gt;
| 2171&lt;br /&gt;
| 087B&lt;br /&gt;
| Utilities Unlimited&lt;br /&gt;
|-&lt;br /&gt;
| 2172&lt;br /&gt;
| 087C&lt;br /&gt;
| phase 5&lt;br /&gt;
|-&lt;br /&gt;
| 2173&lt;br /&gt;
| 087D&lt;br /&gt;
| Juergen Kommos&lt;br /&gt;
|-&lt;br /&gt;
| 2174&lt;br /&gt;
| 087E&lt;br /&gt;
| Electronic Design&lt;br /&gt;
|-&lt;br /&gt;
| 2175&lt;br /&gt;
| 087F&lt;br /&gt;
| James Cook University of North Queensland&lt;br /&gt;
|-&lt;br /&gt;
| 2176&lt;br /&gt;
| 0880&lt;br /&gt;
| AmiTrix Development&lt;br /&gt;
|-&lt;br /&gt;
| 2177&lt;br /&gt;
| 0881&lt;br /&gt;
| Ferranti&lt;br /&gt;
|-&lt;br /&gt;
| 2178&lt;br /&gt;
| 0882&lt;br /&gt;
| Leviathan Development&lt;br /&gt;
|-&lt;br /&gt;
| 2179&lt;br /&gt;
| 0883&lt;br /&gt;
| United Video Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2180&lt;br /&gt;
| 0884&lt;br /&gt;
| GPSoft Pty. Ltd.&lt;br /&gt;
| Originally registered to Juergen Kommos&lt;br /&gt;
|-&lt;br /&gt;
| 2181&lt;br /&gt;
| 0885&lt;br /&gt;
| ArMAX&lt;br /&gt;
| Oliver Bausch&lt;br /&gt;
|-&lt;br /&gt;
| 2182&lt;br /&gt;
| 0886&lt;br /&gt;
| CP Computer&lt;br /&gt;
|-&lt;br /&gt;
| 2183&lt;br /&gt;
| 0887&lt;br /&gt;
| AMOK - Amiga Module &amp;amp;amp; Oberon Klub&lt;br /&gt;
|-&lt;br /&gt;
| 2184&lt;br /&gt;
| 0888&lt;br /&gt;
| ITEK Neser &amp;amp;amp; Sieber GbR&lt;br /&gt;
|-&lt;br /&gt;
| 2185&lt;br /&gt;
| 0889&lt;br /&gt;
| Phillip C. Lello&lt;br /&gt;
|-&lt;br /&gt;
| 2186&lt;br /&gt;
| 088A&lt;br /&gt;
| Cyborg Design Services&lt;br /&gt;
|-&lt;br /&gt;
| 2187&lt;br /&gt;
| 088B&lt;br /&gt;
| G2 Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2188&lt;br /&gt;
| 088C&lt;br /&gt;
| Pro System Computersysteme&lt;br /&gt;
|-&lt;br /&gt;
| 2189&lt;br /&gt;
| 088D&lt;br /&gt;
| ZEUS Electronic&lt;br /&gt;
| Originally registered to MSPI (Markt &amp;amp;amp; Technik)&lt;br /&gt;
|-&lt;br /&gt;
| 2190&lt;br /&gt;
| 088E&lt;br /&gt;
| Altatech&lt;br /&gt;
|-&lt;br /&gt;
| 2191&lt;br /&gt;
| 088F&lt;br /&gt;
| NewTek&lt;br /&gt;
|-&lt;br /&gt;
| 2192&lt;br /&gt;
| 0890&lt;br /&gt;
| M-TEC Hardware Design&lt;br /&gt;
| Originally registered to Hardware Design Udo Neuroth&lt;br /&gt;
|-&lt;br /&gt;
| 2193&lt;br /&gt;
| 0891&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
| Originally registered to Viona Development&lt;br /&gt;
|-&lt;br /&gt;
| 2194&lt;br /&gt;
| 0892&lt;br /&gt;
| Amitek&lt;br /&gt;
| Originally assigned to Marpet Developments&lt;br /&gt;
|-&lt;br /&gt;
| 2195&lt;br /&gt;
| 0893&lt;br /&gt;
| Ingenieurbuero Helfrich&lt;br /&gt;
|-&lt;br /&gt;
| 2196&lt;br /&gt;
| 0894&lt;br /&gt;
| The Neo Group&lt;br /&gt;
|-&lt;br /&gt;
| 2197&lt;br /&gt;
| 0895&lt;br /&gt;
| Cyon&lt;br /&gt;
|-&lt;br /&gt;
| 2198&lt;br /&gt;
| 0896&lt;br /&gt;
| Bob Research Group&lt;br /&gt;
|-&lt;br /&gt;
| 2199&lt;br /&gt;
| 0897&lt;br /&gt;
| Richmond Sound Design Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2200&lt;br /&gt;
| 0898&lt;br /&gt;
| US Cybernetics&lt;br /&gt;
|-&lt;br /&gt;
| 2201&lt;br /&gt;
| 0899&lt;br /&gt;
| Fulvio Ieva&lt;br /&gt;
|-&lt;br /&gt;
| 2202&lt;br /&gt;
| 089A&lt;br /&gt;
| Silicon Studio&lt;br /&gt;
|-&lt;br /&gt;
| 2203&lt;br /&gt;
| 089B&lt;br /&gt;
| MacroSystems (USA)&lt;br /&gt;
| Was named Micro System Devices&lt;br /&gt;
|-&lt;br /&gt;
| 2204&lt;br /&gt;
| 089C&lt;br /&gt;
| Conspector Entertainment&lt;br /&gt;
|-&lt;br /&gt;
| 2205&lt;br /&gt;
| 089D&lt;br /&gt;
| Laserforum&lt;br /&gt;
|-&lt;br /&gt;
| 2206&lt;br /&gt;
| 089E&lt;br /&gt;
| Elbox Computer&lt;br /&gt;
| Mistakenly used by Index Information Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2207&lt;br /&gt;
| 089F&lt;br /&gt;
| Applied Magic Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2208&lt;br /&gt;
| 08A0&lt;br /&gt;
| SDL Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2560&lt;br /&gt;
| 0A00&lt;br /&gt;
| Harms&lt;br /&gt;
|-&lt;br /&gt;
| 2588&lt;br /&gt;
| 0A1C&lt;br /&gt;
| A1K.org Community&lt;br /&gt;
|-&lt;br /&gt;
| 2640&lt;br /&gt;
| 0A50&lt;br /&gt;
| Micronik&lt;br /&gt;
|-&lt;br /&gt;
| 3084&lt;br /&gt;
| 0C0C&lt;br /&gt;
| Team 4&lt;br /&gt;
|-&lt;br /&gt;
| 3643&lt;br /&gt;
| 0E3B&lt;br /&gt;
| E3B&lt;br /&gt;
| Michael Boehmer&lt;br /&gt;
|-&lt;br /&gt;
| 3855&lt;br /&gt;
| 0F0F&lt;br /&gt;
| Micronik&lt;br /&gt;
|-&lt;br /&gt;
| 4096&lt;br /&gt;
| 1000&lt;br /&gt;
| MegaMicro&lt;br /&gt;
|-&lt;br /&gt;
| 4110&lt;br /&gt;
| 100E&lt;br /&gt;
| DigiFeX&lt;br /&gt;
|-&lt;br /&gt;
| 4136&lt;br /&gt;
| 1028&lt;br /&gt;
| Imtronics/Memphis&lt;br /&gt;
|-&lt;br /&gt;
| 4149&lt;br /&gt;
| 1035&lt;br /&gt;
| PROTAR&lt;br /&gt;
|-&lt;br /&gt;
| 4369&lt;br /&gt;
| 1111&lt;br /&gt;
| Frank Strauß Elektronik&lt;br /&gt;
| Also used by Kupke&lt;br /&gt;
|-&lt;br /&gt;
| 4626&lt;br /&gt;
| 1212&lt;br /&gt;
| Individual Computers&lt;br /&gt;
|-&lt;br /&gt;
| 4648&lt;br /&gt;
| 1228&lt;br /&gt;
| Flesch Hornemann Computer Elec.&lt;br /&gt;
|-&lt;br /&gt;
| 4680&lt;br /&gt;
| 1248&lt;br /&gt;
| Kupke Computertechnik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 4711&lt;br /&gt;
| 1267&lt;br /&gt;
| RBM digitaltechnik&lt;br /&gt;
|-&lt;br /&gt;
| 4754&lt;br /&gt;
| 1292&lt;br /&gt;
| MacroSystems&lt;br /&gt;
|-&lt;br /&gt;
| 5000&lt;br /&gt;
| 1388&lt;br /&gt;
| ITH&lt;br /&gt;
|-&lt;br /&gt;
| 5001&lt;br /&gt;
| 1389&lt;br /&gt;
| VMC&lt;br /&gt;
|-&lt;br /&gt;
| 5010&lt;br /&gt;
| 1392&lt;br /&gt;
| Ambience Creation Technology&lt;br /&gt;
|-&lt;br /&gt;
| 5011&lt;br /&gt;
| 1393&lt;br /&gt;
| Creative Development&lt;br /&gt;
|-&lt;br /&gt;
| 5012&lt;br /&gt;
| 1394&lt;br /&gt;
| Georg Braun&lt;br /&gt;
|-&lt;br /&gt;
| 5013&lt;br /&gt;
| 1395&lt;br /&gt;
| Swedish User Group of Amiga&lt;br /&gt;
|-&lt;br /&gt;
| 5014&lt;br /&gt;
| 1396&lt;br /&gt;
| Jakub Bednarski&lt;br /&gt;
|-&lt;br /&gt;
| 5015&lt;br /&gt;
| 1397&lt;br /&gt;
| KryoFlux, Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 5016&lt;br /&gt;
| 1398&lt;br /&gt;
| Igor Majstorovic&lt;br /&gt;
|-&lt;br /&gt;
| 5017&lt;br /&gt;
| 1399&lt;br /&gt;
| Alastair M. Robinson&lt;br /&gt;
|-&lt;br /&gt;
| 5018&lt;br /&gt;
| 139A&lt;br /&gt;
| Austex Software&lt;br /&gt;
|-&lt;br /&gt;
| 5019&lt;br /&gt;
| 139B&lt;br /&gt;
| Sören Gust&lt;br /&gt;
|-&lt;br /&gt;
| 5020&lt;br /&gt;
| 139C&lt;br /&gt;
| Rok Krajnc&lt;br /&gt;
|-&lt;br /&gt;
| 5030&lt;br /&gt;
| 13A6&lt;br /&gt;
| Tim Tashpulatov&lt;br /&gt;
|-&lt;br /&gt;
| 5040&lt;br /&gt;
| 13B0&lt;br /&gt;
| 7-bit&lt;br /&gt;
|-&lt;br /&gt;
| 5050&lt;br /&gt;
| 13BA&lt;br /&gt;
| Sakura IT&lt;br /&gt;
|-&lt;br /&gt;
| 5060&lt;br /&gt;
| 13C4&lt;br /&gt;
| FPGAArcade&lt;br /&gt;
|-&lt;br /&gt;
| 5070&lt;br /&gt;
| 13CE&lt;br /&gt;
| CancerSoft Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 5080&lt;br /&gt;
| 13D8&lt;br /&gt;
| Stephen Leary&lt;br /&gt;
|-&lt;br /&gt;
| 5090&lt;br /&gt;
| 13E2&lt;br /&gt;
| DMA Softlab LLC&lt;br /&gt;
|-&lt;br /&gt;
| 5100&lt;br /&gt;
| 13EC&lt;br /&gt;
| Brookhouse Engineering&lt;br /&gt;
|-&lt;br /&gt;
| 5110&lt;br /&gt;
| 13F6&lt;br /&gt;
| Eduardo Arana&lt;br /&gt;
|-&lt;br /&gt;
| 5120&lt;br /&gt;
| 1400&lt;br /&gt;
| CS-LAB&lt;br /&gt;
|-&lt;br /&gt;
| 5130&lt;br /&gt;
| 140A&lt;br /&gt;
| Robert Miranda&lt;br /&gt;
|-&lt;br /&gt;
| 5140&lt;br /&gt;
| 1414&lt;br /&gt;
| RastPort&lt;br /&gt;
|-&lt;br /&gt;
| 5132&lt;br /&gt;
| 140C&lt;br /&gt;
| UAS Interface Ltd6&lt;br /&gt;
|-&lt;br /&gt;
| 5150&lt;br /&gt;
| 141E&lt;br /&gt;
| Amiga Kit&lt;br /&gt;
|-&lt;br /&gt;
| 5160&lt;br /&gt;
| 1428&lt;br /&gt;
| Central Texas Commodore User Group&lt;br /&gt;
|-&lt;br /&gt;
| 5170&lt;br /&gt;
| 1432&lt;br /&gt;
| Confusion Research Center&lt;br /&gt;
|-&lt;br /&gt;
| 5180&lt;br /&gt;
| 143C&lt;br /&gt;
| Solar Soyuz Zaibatsu&lt;br /&gt;
|-&lt;br /&gt;
| 5190&lt;br /&gt;
| 1446&lt;br /&gt;
| BooBip&lt;br /&gt;
|-&lt;br /&gt;
| 5191&lt;br /&gt;
| 1447&lt;br /&gt;
| Matthias Hampel&lt;br /&gt;
|-&lt;br /&gt;
| 5192&lt;br /&gt;
| 1448&lt;br /&gt;
| dec0de Consulting Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 5193&lt;br /&gt;
| 1449&lt;br /&gt;
| Puppy Concepts&lt;br /&gt;
|-&lt;br /&gt;
| 5194&lt;br /&gt;
| 144A&lt;br /&gt;
| Open Amiga Hardware Repository&lt;br /&gt;
|-&lt;br /&gt;
| 5195&lt;br /&gt;
| 144B&lt;br /&gt;
| Double H Tech&lt;br /&gt;
|-&lt;br /&gt;
| 5196&lt;br /&gt;
| 144C&lt;br /&gt;
| Retromatik&lt;br /&gt;
|-&lt;br /&gt;
| 5500&lt;br /&gt;
| 157C&lt;br /&gt;
| Inhouse Information&lt;br /&gt;
|-&lt;br /&gt;
| 5768&lt;br /&gt;
| 1688&lt;br /&gt;
| Bio Con&lt;br /&gt;
|-&lt;br /&gt;
| 6148&lt;br /&gt;
| 1804&lt;br /&gt;
| HK-Computer&lt;br /&gt;
|-&lt;br /&gt;
| 6502&lt;br /&gt;
| 1966&lt;br /&gt;
| Cloanto&lt;br /&gt;
|-&lt;br /&gt;
| 6520&lt;br /&gt;
| 1978&lt;br /&gt;
| Oliver Gantert&lt;br /&gt;
|-&lt;br /&gt;
| 7777&lt;br /&gt;
| 1E61&lt;br /&gt;
| Rafal Gabriel Chyla&lt;br /&gt;
|-&lt;br /&gt;
| 8215&lt;br /&gt;
| 2017&lt;br /&gt;
| Vortex&lt;br /&gt;
|-&lt;br /&gt;
| 8244&lt;br /&gt;
| 2034&lt;br /&gt;
| Spirit Technology&lt;br /&gt;
|-&lt;br /&gt;
| 8290&lt;br /&gt;
| 2062&lt;br /&gt;
| Expansion Systems&lt;br /&gt;
|-&lt;br /&gt;
| 8448&lt;br /&gt;
| 2100&lt;br /&gt;
| ReadySoft&lt;br /&gt;
|-&lt;br /&gt;
| 8512&lt;br /&gt;
| 2140&lt;br /&gt;
| Phase 5 Digital Products&lt;br /&gt;
|-&lt;br /&gt;
| 8553&lt;br /&gt;
| 2169&lt;br /&gt;
| Digital Processing Systems Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 8704&lt;br /&gt;
| 2200&lt;br /&gt;
| ACT Elektronik&lt;br /&gt;
|-&lt;br /&gt;
| 8738&lt;br /&gt;
| 2222&lt;br /&gt;
| ACT Elektronik&lt;br /&gt;
|-&lt;br /&gt;
| 9512&lt;br /&gt;
| 2528&lt;br /&gt;
| Tower Technologies&lt;br /&gt;
|-&lt;br /&gt;
| 10676&lt;br /&gt;
| 29B4&lt;br /&gt;
| Electronic Design&lt;br /&gt;
|-&lt;br /&gt;
| 14195&lt;br /&gt;
| 3773&lt;br /&gt;
| Media-net-Point&lt;br /&gt;
|-&lt;br /&gt;
| 14501&lt;br /&gt;
| 38A5&lt;br /&gt;
| Petsoff, Finland&lt;br /&gt;
|-&lt;br /&gt;
| 16375&lt;br /&gt;
| 3FF7&lt;br /&gt;
| Uwe Gerlach&lt;br /&gt;
|-&lt;br /&gt;
| 16707&lt;br /&gt;
| 4143&lt;br /&gt;
| Ateo Concepts&lt;br /&gt;
|-&lt;br /&gt;
| 16708&lt;br /&gt;
| 4144&lt;br /&gt;
| ALiENDESiGN&lt;br /&gt;
|-&lt;br /&gt;
| 16945&lt;br /&gt;
| 4231&lt;br /&gt;
| A.C.T.&lt;br /&gt;
|-&lt;br /&gt;
| 17740&lt;br /&gt;
| 454C&lt;br /&gt;
| HK-Computer (ELSAT)&lt;br /&gt;
|-&lt;br /&gt;
| 18260&lt;br /&gt;
| 4754&lt;br /&gt;
| MacroSystems (Germany)&lt;br /&gt;
|-&lt;br /&gt;
| 19796&lt;br /&gt;
| 4D54&lt;br /&gt;
| Markt &amp;amp; Technik&lt;br /&gt;
|-&lt;br /&gt;
| 22359&lt;br /&gt;
| 5757&lt;br /&gt;
| Markt &amp;amp; Technik&lt;br /&gt;
|-&lt;br /&gt;
| 26464&lt;br /&gt;
| 6760&lt;br /&gt;
| Combitec&lt;br /&gt;
|-&lt;br /&gt;
| 26470&lt;br /&gt;
| 6766&lt;br /&gt;
| Combitec&lt;br /&gt;
|-&lt;br /&gt;
| 28014&lt;br /&gt;
| 6D6E&lt;br /&gt;
| MNT Media and Technology UG&lt;br /&gt;
|-&lt;br /&gt;
| 32768&lt;br /&gt;
| 8000&lt;br /&gt;
| M.A.S.T.&lt;br /&gt;
|-&lt;br /&gt;
| 42240&lt;br /&gt;
| A500&lt;br /&gt;
| Aethreum Digital&lt;br /&gt;
|-&lt;br /&gt;
| 43437&lt;br /&gt;
| A9AD&lt;br /&gt;
| Reis-Ware&lt;br /&gt;
|-&lt;br /&gt;
| 43521&lt;br /&gt;
| AA01&lt;br /&gt;
| Cameron&lt;br /&gt;
|-&lt;br /&gt;
| 43537&lt;br /&gt;
| AA11&lt;br /&gt;
| Reis-Ware&lt;br /&gt;
|-&lt;br /&gt;
| 44359&lt;br /&gt;
| AD47&lt;br /&gt;
| Matay&lt;br /&gt;
|-&lt;br /&gt;
| 46504&lt;br /&gt;
| B5A8&lt;br /&gt;
| Phoenix&lt;br /&gt;
|-&lt;br /&gt;
| 48879&lt;br /&gt;
| BEEF&lt;br /&gt;
| Swiss Mountain Dog Products&lt;br /&gt;
|-&lt;br /&gt;
| 49160&lt;br /&gt;
| C008&lt;br /&gt;
| Combitec&lt;br /&gt;
|-&lt;br /&gt;
| 61453&lt;br /&gt;
| F00D&lt;br /&gt;
| Forefront Technologies Inc.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
For any changes/additions to this registry see [[#How_to_Obtain_a_Manufacturer_Number|How to Obtain a Manufacturer Number]]&lt;/div&gt;</summary>
		<author><name>Costel Mincea</name></author>
	</entry>
	<entry>
		<id>https://wiki.amigaos.net/w/index.php?title=Amiga_Hardware_Manufacturer_ID_Registry&amp;diff=12598</id>
		<title>Amiga Hardware Manufacturer ID Registry</title>
		<link rel="alternate" type="text/html" href="https://wiki.amigaos.net/w/index.php?title=Amiga_Hardware_Manufacturer_ID_Registry&amp;diff=12598"/>
		<updated>2026-09-08T10:28:02Z</updated>

		<summary type="html">&lt;p&gt;Costel Mincea: /* How to Obtain a Manufacturer Number */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
= How to Obtain a Manufacturer Number =&lt;br /&gt;
&lt;br /&gt;
Manufacturer&#039;s numbers are assigned by the AmigaOS development team. To obtain your unique manufacturer number send a support request to [mailto:support@hyperion-entertainment.com support@hyperion-entertainment.com] including these information:&lt;br /&gt;
&lt;br /&gt;
 1. The name of the company or person which the number is assigned to&lt;br /&gt;
 &lt;br /&gt;
 2. Postal address/contact address&lt;br /&gt;
 &lt;br /&gt;
 3. Name of the contact person, with a corresponding e-mail address&lt;br /&gt;
 &lt;br /&gt;
 4. A brief description of the kind of products you want to produce&lt;br /&gt;
&lt;br /&gt;
= Your Manufacturer Number =&lt;br /&gt;
&lt;br /&gt;
Attention hardware manufacturers. If you are developing a hardware expansion product for the Classic Amiga (e.g. 500, 2000, 3000) then you will need to obtain a special manufacturer ID number from the AmigaOS development team to identify your product. This manufacturer number is used by the Amiga to link your hardware with its driver software at boot time.&lt;br /&gt;
&lt;br /&gt;
Your manufacturer number is part of the special protocol that the Amiga uses to automatically configure all expansion devices on the bus without the user having to cut jumpers or adjust dip switches. This is called auto-config.&lt;br /&gt;
&lt;br /&gt;
At start-up time, the system first polls each board in the system and assigns the board its own address space. If it is a memory board, its RAM is linked into the memory free pool. Later in the boot sequence, after DOS is initialized, the binddrivers program is run. Binddrivers will search the directory SYS:Expansion for the drivers that go with the boards.&lt;br /&gt;
&lt;br /&gt;
To do this binddrivers looks in the Tool Type field of all icon files in SYS:Expansion. If the first seven bytes of the Tool Type field are &amp;quot;PRODUCT&amp;quot;, then this is an icon file for a driver.&lt;br /&gt;
&lt;br /&gt;
Binddrivers will then attempt to match the drivers it has found with the boards that were found earlier. This is where your manufacturer number comes in.&lt;br /&gt;
&lt;br /&gt;
Your manufacturer number goes in two places. First, it is burned in hex form into the PAL which is part of ALL auto-config expansion products. Second, it appears in ASCII in the Tool Type field of the icon file for your product&#039;s driver. By matching these two numbers, the Amiga can automatically configure your board and bind it&#039;s software driver into the system as well.&lt;br /&gt;
&lt;br /&gt;
The manufacturer&#039;s number is a 16-bit ID which appears in PAL offsets $10-$17. There is also an 8-bit product number which you assign. The product number is for uniquely identifying different products from the same vendor. The product number will appear in PAL offsets $04-$07. This gives you a total of 24 bits to identify each of your products.&lt;br /&gt;
&lt;br /&gt;
These 24 bits of information in the PAL which identify your product are matched against the information in the Tool Type field of all icon files in the SYS:Expansion drawer. For example, suppose you are manufacturer #1019. You have two products, #1 and #2 which both use the same driver. The icon for your driver for these two products would have a Tool Type set to &amp;quot;PRODUCT=1019/1|1019/2&amp;quot;. This means: I am an icon for a driver that works with product number 1 or 2 from manufacturer 1019, now bind me. Spaces are not legal. Here are two other examples:&lt;br /&gt;
&lt;br /&gt;
; PRODUCT=1208/11&lt;br /&gt;
: is the Tool Type for a driver for product 11 from manufacturer number 1208.&lt;br /&gt;
&lt;br /&gt;
; PRODUCT=1017&lt;br /&gt;
: is the Tool Type for a driver for any product from manufacturer number 1017.&lt;br /&gt;
&lt;br /&gt;
For an informal explanation of the auto-configuration process, see the chapter on Software Expansion Architecture from the 2nd Annual Amiga Developer&#039;s Conference Notes (available on ADCD 2.1). For the details of timing, power, the PAL equations and PAL address specifications and the expansion library documentation, see sections 3.1 to 3.3 of the A500/A2000 Technical Reference Manual. The original auto-config spec appears in the A1000 Schematics and Expansion Specification.&lt;br /&gt;
&lt;br /&gt;
The auto-config process makes the addition of expansion products to the system very easy. All the user has to do is put the board in any slot and copy the driver from the release disk to his own SYS:Expansion drawer. Everything else is automatic. There are no jumpers or dip switches to set. Best of all, you will get a lot less support calls asking how to make your product work with the XYZ-Corp-battery-backed-clock.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
&lt;br /&gt;
Some notes on hardware manufacturer ID assignment.&lt;br /&gt;
&lt;br /&gt;
* Manufacturer ID numbers are assigned free of charge.&lt;br /&gt;
* Please provide the following information when requesting an ID:&lt;br /&gt;
*# Name of the company or person&lt;br /&gt;
*# Postal address/contact address&lt;br /&gt;
*# Name of the contact person, with a corresponding e-mail address&lt;br /&gt;
*# A brief description of the kind of products you want to produce&lt;br /&gt;
* All ID numbers smaller than 5000 must be considered unsafe because no information exists on which numbers exactly were taken during the time Commodore, Inc. disintegrated.&lt;br /&gt;
* ID numbers in the range 8192 to 18841 must be considered unsafe because some hardware developers mistook the numbers assigned to them to be given in hexadecimal format. Hence 0x2000 = 8192 and 0x4999 = 18841.&lt;br /&gt;
&lt;br /&gt;
= Example code =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
/*-----------------------------------------------*/&lt;br /&gt;
/* Here is a short program which will tell you   */&lt;br /&gt;
/* about the expansion boards configured in your */&lt;br /&gt;
/* system without you opening up the machine.    */&lt;br /&gt;
/* Code by Bill Koester of CATS                  */&lt;br /&gt;
/*-----------------------------------------------*/&lt;br /&gt;
#include &amp;lt;libraries/configvars.h&amp;gt;&lt;br /&gt;
#include &amp;lt;libraries/expansion.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
struct ExpansionBase *ExpansionBase;&lt;br /&gt;
&lt;br /&gt;
void cleanup();&lt;br /&gt;
void printdev();&lt;br /&gt;
&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
   struct ConfigDev *MyConfigDev;&lt;br /&gt;
&lt;br /&gt;
   /*----------------------------------*/&lt;br /&gt;
   /* Open the expansion library,      */&lt;br /&gt;
   /* if there is a problem then exit  */&lt;br /&gt;
   /*----------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   ExpansionBase =(struct ExpansionBase *) OpenLibrary(EXPANSIONNAME,0);&lt;br /&gt;
   if(ExpansionBase==NULL)&lt;br /&gt;
   {&lt;br /&gt;
      printf(&amp;quot;Error opening expansion library!!\n&amp;quot;);&lt;br /&gt;
      cleanup();&lt;br /&gt;
      exit(0);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   /*--------------------------------------------*/&lt;br /&gt;
   /* Use FindConfigDev to get info on the first */&lt;br /&gt;
   /* expansion board on the list maintained by  */&lt;br /&gt;
   /* Exec.  If there are no expansion boards in */&lt;br /&gt;
   /* the system then exit.                      */&lt;br /&gt;
   /*--------------------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   MyConfigDev = NULL;&lt;br /&gt;
&lt;br /&gt;
  /*--------------------------------------------------*/&lt;br /&gt;
  /* FindConfigDev(oldConfigDev,manufacturer,product) */&lt;br /&gt;
  /* oldConfigDev = NULL for the top of the list      */&lt;br /&gt;
  /* manufacturer = -1 for any manufacturer           */&lt;br /&gt;
  /* product      = -1 for any product                */&lt;br /&gt;
  /*--------------------------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   MyConfigDev = FindConfigDev(NULL,-1,-1);&lt;br /&gt;
&lt;br /&gt;
   if(MyConfigDev==NULL)&lt;br /&gt;
   {&lt;br /&gt;
      printf(&amp;quot;No Configured Devices found!!\n&amp;quot;);&lt;br /&gt;
      cleanup();&lt;br /&gt;
      exit(0);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   printdev(MyConfigDev);&lt;br /&gt;
&lt;br /&gt;
   /*-----------------------------------*/&lt;br /&gt;
   /* OK, there is at least one board,  */&lt;br /&gt;
   /* so loop and get the entire list   */&lt;br /&gt;
   /* printing as we go with printdev() */&lt;br /&gt;
   /*-----------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   while(MyConfigDev = FindConfigDev(MyConfigDev,-1,-1))&lt;br /&gt;
   {&lt;br /&gt;
      printdev(MyConfigDev);&lt;br /&gt;
   }&lt;br /&gt;
   cleanup();&lt;br /&gt;
   return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*-------------------*/&lt;br /&gt;
/* Close up shop...  */&lt;br /&gt;
/*-------------------*/&lt;br /&gt;
void cleanup()&lt;br /&gt;
{&lt;br /&gt;
   if(ExpansionBase)&lt;br /&gt;
      CloseLibrary(ExpansionBase);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*----------------------------------*/&lt;br /&gt;
/* Print out the contents of the    */&lt;br /&gt;
/* dev structure for this expansion */&lt;br /&gt;
/* product.                         */&lt;br /&gt;
/*----------------------------------*/&lt;br /&gt;
&lt;br /&gt;
void printdev(dev)&lt;br /&gt;
struct ConfigDev *dev;&lt;br /&gt;
{&lt;br /&gt;
   char buff[200];&lt;br /&gt;
&lt;br /&gt;
   printf(&amp;quot;Flags          = &amp;quot;);&lt;br /&gt;
   if(dev-&amp;gt;cd_Flags==NULL)&lt;br /&gt;
      printf(&amp;quot;NULL  &amp;quot;);&lt;br /&gt;
   if(dev-&amp;gt;cd_Flags&amp;amp;CDF_SHUTUP)&lt;br /&gt;
      printf(&amp;quot;CDF_SHUTUP  &amp;quot;);&lt;br /&gt;
   if(dev-&amp;gt;cd_Flags&amp;amp;CDF_CONFIGME)&lt;br /&gt;
      printf(&amp;quot;CDF_CONFIGME  &amp;quot;);&lt;br /&gt;
   printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
   printf(&amp;quot;Board Address  = %x\n&amp;quot;,dev-&amp;gt;cd_BoardAddr);&lt;br /&gt;
   printf(&amp;quot;Board Size     = %d bytes\n&amp;quot;,dev-&amp;gt;cd_BoardSize);&lt;br /&gt;
   printf(&amp;quot;Slot  Address  = %d\n&amp;quot;,dev-&amp;gt;cd_SlotAddr);&lt;br /&gt;
   printf(&amp;quot;Slot  Size     = %d\n&amp;quot;,dev-&amp;gt;cd_SlotSize);&lt;br /&gt;
   printf(&amp;quot;Driver code at   %x\n&amp;quot;,dev-&amp;gt;cd_Driver);&lt;br /&gt;
&lt;br /&gt;
   printf(&amp;quot;er_Type         = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Type);&lt;br /&gt;
   printf(&amp;quot;er_Product      = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Product);&lt;br /&gt;
   printf(&amp;quot;er_Flags        = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Flags);&lt;br /&gt;
   printf(&amp;quot;er_Reserved03   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved03);&lt;br /&gt;
   printf(&amp;quot;er_Manufacturer = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Manufacturer);&lt;br /&gt;
   printf(&amp;quot;er_SerialNumber = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_SerialNumber);&lt;br /&gt;
   printf(&amp;quot;er_InitDiagVec  = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_InitDiagVec);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0c   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0c);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0d   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0d);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0e   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0e);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0f   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0f);&lt;br /&gt;
&lt;br /&gt;
   printf(&amp;quot;Hit Return to continue:\n&amp;quot;);&lt;br /&gt;
   gets(buff);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Registry =&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! ID (decimal)&lt;br /&gt;
! ID (hexadecimal)&lt;br /&gt;
! Manufacturer&lt;br /&gt;
! Notes&lt;br /&gt;
|-&lt;br /&gt;
| 1&lt;br /&gt;
| 0001&lt;br /&gt;
| Micronik&lt;br /&gt;
|-&lt;br /&gt;
| 211&lt;br /&gt;
| 00D3&lt;br /&gt;
| Pacific Peripherals/Profex&lt;br /&gt;
|-&lt;br /&gt;
| 221&lt;br /&gt;
| 00DD&lt;br /&gt;
| Kupke Computertechnik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 256&lt;br /&gt;
| 0100&lt;br /&gt;
| Memphis&lt;br /&gt;
| Originally registered to MacroSystems US&lt;br /&gt;
|-&lt;br /&gt;
| 512&lt;br /&gt;
| 0200&lt;br /&gt;
| 3-State Computertechnik&lt;br /&gt;
|-&lt;br /&gt;
| 513&lt;br /&gt;
| 0201&lt;br /&gt;
| Commodore (Braunschweig)&lt;br /&gt;
|-&lt;br /&gt;
| 514&lt;br /&gt;
| 0202&lt;br /&gt;
| Commodore (West Chester)&lt;br /&gt;
|-&lt;br /&gt;
| 515&lt;br /&gt;
| 0203&lt;br /&gt;
| Commodore (West Chester)&lt;br /&gt;
| Originally registered to Combitech/Macrosystem&lt;br /&gt;
|-&lt;br /&gt;
| 756&lt;br /&gt;
| 02F4&lt;br /&gt;
| Progressive Peripherals &amp;amp; Software&lt;br /&gt;
|-&lt;br /&gt;
| 767&lt;br /&gt;
| 02FF&lt;br /&gt;
| Kolff Computer Supplies&lt;br /&gt;
|-&lt;br /&gt;
| 1001&lt;br /&gt;
| 03E9&lt;br /&gt;
| Tecmar&lt;br /&gt;
|-&lt;br /&gt;
| 1002&lt;br /&gt;
| 03EA&lt;br /&gt;
| Telesys&lt;br /&gt;
|-&lt;br /&gt;
| 1003&lt;br /&gt;
| 03EB&lt;br /&gt;
| The Micro-Forge&lt;br /&gt;
|-&lt;br /&gt;
| 1004&lt;br /&gt;
| 03EC&lt;br /&gt;
| Kronos/C Ltd.&lt;br /&gt;
| Originally registered to Card Co. (Supra)&lt;br /&gt;
|-&lt;br /&gt;
| 1005&lt;br /&gt;
| 03ED&lt;br /&gt;
| A-Squared&lt;br /&gt;
|-&lt;br /&gt;
| 1006&lt;br /&gt;
| 03EE&lt;br /&gt;
| Comspec Communications&lt;br /&gt;
|-&lt;br /&gt;
| 1007&lt;br /&gt;
| 03EF&lt;br /&gt;
| HT Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 1008&lt;br /&gt;
| 03F0&lt;br /&gt;
| RDS Software&lt;br /&gt;
|-&lt;br /&gt;
| 1009&lt;br /&gt;
| 03F1&lt;br /&gt;
| Anakin Research&lt;br /&gt;
|-&lt;br /&gt;
| 1010&lt;br /&gt;
| 03F2&lt;br /&gt;
| MicroBotics&lt;br /&gt;
|-&lt;br /&gt;
| 1011&lt;br /&gt;
| 03F3&lt;br /&gt;
| Bob Krauth&lt;br /&gt;
|-&lt;br /&gt;
| 1012&lt;br /&gt;
| 03F4&lt;br /&gt;
| Access Associates (Alegra)&lt;br /&gt;
|-&lt;br /&gt;
| 1013&lt;br /&gt;
| 03F5&lt;br /&gt;
| Mini Comp Systems Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 1014&lt;br /&gt;
| 03F6&lt;br /&gt;
| Cypress Technology&lt;br /&gt;
|-&lt;br /&gt;
| 1015&lt;br /&gt;
| 03F7&lt;br /&gt;
| Fuller Computers&lt;br /&gt;
|-&lt;br /&gt;
| 1016&lt;br /&gt;
| 03F8&lt;br /&gt;
| Galaxy Computers&lt;br /&gt;
|-&lt;br /&gt;
| 1017&lt;br /&gt;
| 03F9&lt;br /&gt;
| ADA Research&lt;br /&gt;
|-&lt;br /&gt;
| 1018&lt;br /&gt;
| 03FA&lt;br /&gt;
| Computer Service Italia&lt;br /&gt;
|-&lt;br /&gt;
| 1019&lt;br /&gt;
| 03FB&lt;br /&gt;
| Amigo&lt;br /&gt;
|-&lt;br /&gt;
| 1020&lt;br /&gt;
| 03FC&lt;br /&gt;
| Micro-Solutions Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1021&lt;br /&gt;
| 03FD&lt;br /&gt;
| Stacar International&lt;br /&gt;
|-&lt;br /&gt;
| 1022&lt;br /&gt;
| 03FE&lt;br /&gt;
| Video Precisions&lt;br /&gt;
|-&lt;br /&gt;
| 1023&lt;br /&gt;
| 03FF&lt;br /&gt;
| ASDG, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1025&lt;br /&gt;
| 0401&lt;br /&gt;
| Ing. Buero Kalawsky&lt;br /&gt;
|-&lt;br /&gt;
| 1026&lt;br /&gt;
| 0402&lt;br /&gt;
| Computer Tuning&lt;br /&gt;
|-&lt;br /&gt;
| 1027&lt;br /&gt;
| 0403&lt;br /&gt;
| Interplan Unternehmensberatung&lt;br /&gt;
|-&lt;br /&gt;
| 1028&lt;br /&gt;
| 0404&lt;br /&gt;
| Imtronics/Memphis&lt;br /&gt;
| Originally registered to Peter Ohlich&lt;br /&gt;
|-&lt;br /&gt;
| 1030&lt;br /&gt;
| 0406&lt;br /&gt;
| Commodore (Lowell University)&lt;br /&gt;
| Originally registered to Productivity Center&lt;br /&gt;
|-&lt;br /&gt;
| 1041&lt;br /&gt;
| 0411&lt;br /&gt;
| Design Labs&lt;br /&gt;
|-&lt;br /&gt;
| 1042&lt;br /&gt;
| 0412&lt;br /&gt;
| MCS&lt;br /&gt;
|-&lt;br /&gt;
| 1043&lt;br /&gt;
| 0413&lt;br /&gt;
| B. J. Freeman&lt;br /&gt;
|-&lt;br /&gt;
| 1044&lt;br /&gt;
| 0414&lt;br /&gt;
| Side Effects Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1045&lt;br /&gt;
| 0415&lt;br /&gt;
| Oklahoma Personal Comp.&lt;br /&gt;
|-&lt;br /&gt;
| 1046&lt;br /&gt;
| 0416&lt;br /&gt;
| Advanced Micro Innovations&lt;br /&gt;
|-&lt;br /&gt;
| 1047&lt;br /&gt;
| 0417&lt;br /&gt;
| Industrial Support Services&lt;br /&gt;
|-&lt;br /&gt;
| 1048&lt;br /&gt;
| 0418&lt;br /&gt;
| Technisoft&lt;br /&gt;
|-&lt;br /&gt;
| 1049&lt;br /&gt;
| 0419&lt;br /&gt;
| Prolific, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1050&lt;br /&gt;
| 041A&lt;br /&gt;
| Softeam, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1051&lt;br /&gt;
| 041B&lt;br /&gt;
| GRC Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 1052&lt;br /&gt;
| 041C&lt;br /&gt;
| David Lai&lt;br /&gt;
|-&lt;br /&gt;
| 1053&lt;br /&gt;
| 041D&lt;br /&gt;
| Ameristar Technologies&lt;br /&gt;
|-&lt;br /&gt;
| 1054&lt;br /&gt;
| 041E&lt;br /&gt;
| Cline Refrigeration&lt;br /&gt;
|-&lt;br /&gt;
| 1055&lt;br /&gt;
| 041F&lt;br /&gt;
| Cardiac Pacemakers, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1056&lt;br /&gt;
| 0420&lt;br /&gt;
| Supra Corp. (Creative Microsystems)&lt;br /&gt;
|-&lt;br /&gt;
| 1057&lt;br /&gt;
| 0421&lt;br /&gt;
| Wayne Diener&lt;br /&gt;
|-&lt;br /&gt;
| 1058&lt;br /&gt;
| 0422&lt;br /&gt;
| Computer Systems Associates (CSA)&lt;br /&gt;
|-&lt;br /&gt;
| 1059&lt;br /&gt;
| 0423&lt;br /&gt;
| Trionix, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1060&lt;br /&gt;
| 0424&lt;br /&gt;
| David Lucas&lt;br /&gt;
|-&lt;br /&gt;
| 1061&lt;br /&gt;
| 0425&lt;br /&gt;
| Analog Precision&lt;br /&gt;
| Also assigned to D &amp;amp; L Distributing&lt;br /&gt;
|-&lt;br /&gt;
| 1267&lt;br /&gt;
| 04F3&lt;br /&gt;
| RBM Digitaltechnik&lt;br /&gt;
|-&lt;br /&gt;
| 1282&lt;br /&gt;
| 0502&lt;br /&gt;
| M-TEC Hardware Design&lt;br /&gt;
|-&lt;br /&gt;
| 1337&lt;br /&gt;
| 0539&lt;br /&gt;
| Thomas Stenzel (DaFR34K)&lt;br /&gt;
|-&lt;br /&gt;
| 1576&lt;br /&gt;
| 0628&lt;br /&gt;
| Boris Križma&lt;br /&gt;
|-&lt;br /&gt;
| 1761&lt;br /&gt;
| 06E1&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
|-&lt;br /&gt;
| 1803&lt;br /&gt;
| 070B&lt;br /&gt;
| UAE Amiga Emulator&lt;br /&gt;
|-&lt;br /&gt;
| 2002&lt;br /&gt;
| 07D2&lt;br /&gt;
| Mimetics Corp.&lt;br /&gt;
|-&lt;br /&gt;
| 2003&lt;br /&gt;
| 07D3&lt;br /&gt;
| ACDA&lt;br /&gt;
|-&lt;br /&gt;
| 2004&lt;br /&gt;
| 07D4&lt;br /&gt;
| Finn R. Jacobsen&lt;br /&gt;
|-&lt;br /&gt;
| 2005&lt;br /&gt;
| 07D5&lt;br /&gt;
| Elthen Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2006&lt;br /&gt;
| 07D6&lt;br /&gt;
| Nine Tiles Computer Systems Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2007&lt;br /&gt;
| 07D7&lt;br /&gt;
| Analog Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2008&lt;br /&gt;
| 07D8&lt;br /&gt;
| Bell &amp;amp;amp; Howell&lt;br /&gt;
|-&lt;br /&gt;
| 2009&lt;br /&gt;
| 07D9&lt;br /&gt;
| Roland Kochler&lt;br /&gt;
|-&lt;br /&gt;
| 2010&lt;br /&gt;
| 07DA&lt;br /&gt;
| Byte Corp.&lt;br /&gt;
|-&lt;br /&gt;
| 2011&lt;br /&gt;
| 07DB&lt;br /&gt;
| Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 2012&lt;br /&gt;
| 07DC&lt;br /&gt;
| DKB, Inc.&lt;br /&gt;
| Previously named Michigan Software&lt;br /&gt;
|-&lt;br /&gt;
| 2013&lt;br /&gt;
| 07DD&lt;br /&gt;
| Pacific Peripherals&lt;br /&gt;
|-&lt;br /&gt;
| 2014&lt;br /&gt;
| 07DE&lt;br /&gt;
| Sysaphus Software&lt;br /&gt;
|-&lt;br /&gt;
| 2015&lt;br /&gt;
| 07DF&lt;br /&gt;
| Digitronics&lt;br /&gt;
|-&lt;br /&gt;
| 2016&lt;br /&gt;
| 07E0&lt;br /&gt;
| Akron Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2017&lt;br /&gt;
| 07E1&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
|-&lt;br /&gt;
| 2018&lt;br /&gt;
| 07E2&lt;br /&gt;
| Calmos&lt;br /&gt;
|-&lt;br /&gt;
| 2019&lt;br /&gt;
| 07E3&lt;br /&gt;
| Dover Research&lt;br /&gt;
|-&lt;br /&gt;
| 2020&lt;br /&gt;
| 07E4&lt;br /&gt;
| David Krehbiel&lt;br /&gt;
|-&lt;br /&gt;
| 2021&lt;br /&gt;
| 07E5&lt;br /&gt;
| Synergy Peripheral Systems&lt;br /&gt;
| Also known as California Access&lt;br /&gt;
|-&lt;br /&gt;
| 2022&lt;br /&gt;
| 07E6&lt;br /&gt;
| Xetec&lt;br /&gt;
|-&lt;br /&gt;
| 2023&lt;br /&gt;
| 07E7&lt;br /&gt;
| Micron Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2024&lt;br /&gt;
| 07E8&lt;br /&gt;
| CH Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2025&lt;br /&gt;
| 07E9&lt;br /&gt;
| American Liquid Light&lt;br /&gt;
|-&lt;br /&gt;
| 2026&lt;br /&gt;
| 07EA&lt;br /&gt;
| Progressive Peripherals &amp;amp;amp; Software&lt;br /&gt;
| Also used by Ateo&lt;br /&gt;
|-&lt;br /&gt;
| 2027&lt;br /&gt;
| 07EB&lt;br /&gt;
| Wicat Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2028&lt;br /&gt;
| 07EC&lt;br /&gt;
| Applied Systems &amp;amp;amp; Peripherals&lt;br /&gt;
|-&lt;br /&gt;
| 2029&lt;br /&gt;
| 07ED&lt;br /&gt;
| Delaware Valley Software&lt;br /&gt;
|-&lt;br /&gt;
| 2030&lt;br /&gt;
| 07EE&lt;br /&gt;
| Palomax&lt;br /&gt;
|-&lt;br /&gt;
| 2031&lt;br /&gt;
| 07EF&lt;br /&gt;
| Incognito Software&lt;br /&gt;
|-&lt;br /&gt;
| 2032&lt;br /&gt;
| 07F0&lt;br /&gt;
| Jadesign&lt;br /&gt;
|-&lt;br /&gt;
| 2033&lt;br /&gt;
| 07F1&lt;br /&gt;
| BVR&lt;br /&gt;
|-&lt;br /&gt;
| 2034&lt;br /&gt;
| 07F2&lt;br /&gt;
| Spirit Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2035&lt;br /&gt;
| 07F3&lt;br /&gt;
| Spirit Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2036&lt;br /&gt;
| 07F4&lt;br /&gt;
| Atronic&lt;br /&gt;
|-&lt;br /&gt;
| 2037&lt;br /&gt;
| 07F5&lt;br /&gt;
| Scott Karlin&lt;br /&gt;
|-&lt;br /&gt;
| 2038&lt;br /&gt;
| 07F6&lt;br /&gt;
| Howitch&lt;br /&gt;
|-&lt;br /&gt;
| 2039&lt;br /&gt;
| 07F7&lt;br /&gt;
| Sullivan Brothers Visual Engineers&lt;br /&gt;
|-&lt;br /&gt;
| 2040&lt;br /&gt;
| 07F8&lt;br /&gt;
| G I T&lt;br /&gt;
|-&lt;br /&gt;
| 2041&lt;br /&gt;
| 07F9&lt;br /&gt;
| Amigo Business Computers&lt;br /&gt;
|-&lt;br /&gt;
| 2042&lt;br /&gt;
| 07FA&lt;br /&gt;
| Micro E Ab&lt;br /&gt;
|-&lt;br /&gt;
| 2043&lt;br /&gt;
| 07FB&lt;br /&gt;
| Ralph Kruse&lt;br /&gt;
|-&lt;br /&gt;
| 2044&lt;br /&gt;
| 07FC&lt;br /&gt;
| Clearpoint Research&lt;br /&gt;
|-&lt;br /&gt;
| 2045&lt;br /&gt;
| 07FD&lt;br /&gt;
| Kodiak&lt;br /&gt;
|-&lt;br /&gt;
| 2046&lt;br /&gt;
| 07FE&lt;br /&gt;
| BSC&lt;br /&gt;
| Originally registered to Phoenix Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2047&lt;br /&gt;
| 07FF&lt;br /&gt;
| No Name Shown&lt;br /&gt;
|-&lt;br /&gt;
| 2048&lt;br /&gt;
| 0800&lt;br /&gt;
| Commodore Braunschweig&lt;br /&gt;
|-&lt;br /&gt;
| 2049&lt;br /&gt;
| 0801&lt;br /&gt;
| BSC&lt;br /&gt;
| Originally registered to Elaborate Bytes&lt;br /&gt;
|-&lt;br /&gt;
| 2050&lt;br /&gt;
| 0802&lt;br /&gt;
| Kronos/C Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2051&lt;br /&gt;
| 0803&lt;br /&gt;
| Spartanics&lt;br /&gt;
|-&lt;br /&gt;
| 2052&lt;br /&gt;
| 0804&lt;br /&gt;
| Jochheim Computer Tuning&lt;br /&gt;
|-&lt;br /&gt;
| 2053&lt;br /&gt;
| 0805&lt;br /&gt;
| Trans Data Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2054&lt;br /&gt;
| 0806&lt;br /&gt;
| Applied Systems &amp;amp;amp; Peripherals Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2055&lt;br /&gt;
| 0807&lt;br /&gt;
| Checkpoint Technologies&lt;br /&gt;
| Originally registered to Amiga Solutions&lt;br /&gt;
|-&lt;br /&gt;
| 2056&lt;br /&gt;
| 0808&lt;br /&gt;
| Adept Development&lt;br /&gt;
|-&lt;br /&gt;
| 2057&lt;br /&gt;
| 0809&lt;br /&gt;
| Advanced Computer Design&lt;br /&gt;
|-&lt;br /&gt;
| 2058&lt;br /&gt;
| 080A&lt;br /&gt;
| Sir Netics&lt;br /&gt;
|-&lt;br /&gt;
| 2059&lt;br /&gt;
| 080B&lt;br /&gt;
| Expert Services&lt;br /&gt;
|-&lt;br /&gt;
| 2060&lt;br /&gt;
| 080C&lt;br /&gt;
| Digital Art Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2061&lt;br /&gt;
| 080D&lt;br /&gt;
| Adept Development&lt;br /&gt;
|-&lt;br /&gt;
| 2062&lt;br /&gt;
| 080E&lt;br /&gt;
| Expansion Technologies (Expansion Systems)&lt;br /&gt;
|-&lt;br /&gt;
| 2063&lt;br /&gt;
| 080F&lt;br /&gt;
| Alphatech&lt;br /&gt;
|-&lt;br /&gt;
| 2064&lt;br /&gt;
| 0810&lt;br /&gt;
| Edotronik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2065&lt;br /&gt;
| 0811&lt;br /&gt;
| California Access/Synergy&lt;br /&gt;
| Originally registered to Logical Design Works&lt;br /&gt;
|-&lt;br /&gt;
| 2066&lt;br /&gt;
| 0812&lt;br /&gt;
| Bowden, Williams, Full &amp;amp; Assoc.&lt;br /&gt;
|-&lt;br /&gt;
| 2067&lt;br /&gt;
| 0813&lt;br /&gt;
| NES, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2068&lt;br /&gt;
| 0814&lt;br /&gt;
| Amdev&lt;br /&gt;
|-&lt;br /&gt;
| 2069&lt;br /&gt;
| 0815&lt;br /&gt;
| Big Brother Security Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2070&lt;br /&gt;
| 0816&lt;br /&gt;
| Active Circuits Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2071&lt;br /&gt;
| 0817&lt;br /&gt;
| ICD, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2072&lt;br /&gt;
| 0818&lt;br /&gt;
| Multi-Meg Electronique&lt;br /&gt;
|-&lt;br /&gt;
| 2073&lt;br /&gt;
| 0819&lt;br /&gt;
| Kupke Computertechnik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2074&lt;br /&gt;
| 081A&lt;br /&gt;
| The Checkered Ball&lt;br /&gt;
|-&lt;br /&gt;
| 2075&lt;br /&gt;
| 081B&lt;br /&gt;
| Hi Tension Computer Services Ltd. (UK)&lt;br /&gt;
|-&lt;br /&gt;
| 2076&lt;br /&gt;
| 081C&lt;br /&gt;
| Alfa Data&lt;br /&gt;
| Originally assigned to Elmtech Research, Ltd. (UK)&lt;br /&gt;
|-&lt;br /&gt;
| 2077&lt;br /&gt;
| 081D&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
| Originally registered to Clartscreen, Ltd. (UK)&lt;br /&gt;
|-&lt;br /&gt;
| 2078&lt;br /&gt;
| 081E&lt;br /&gt;
| Interworks&lt;br /&gt;
|-&lt;br /&gt;
| 2079&lt;br /&gt;
| 081F&lt;br /&gt;
| Galysh Enterprises&lt;br /&gt;
|-&lt;br /&gt;
| 2080&lt;br /&gt;
| 0820&lt;br /&gt;
| Hardital Synthesis&lt;br /&gt;
| Originally registered to Realtime Games Software Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2081&lt;br /&gt;
| 0821&lt;br /&gt;
| GBS&lt;br /&gt;
|-&lt;br /&gt;
| 2082&lt;br /&gt;
| 0822&lt;br /&gt;
| Circum Design Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2083&lt;br /&gt;
| 0823&lt;br /&gt;
| Alberta Micro Electronic Center&lt;br /&gt;
|-&lt;br /&gt;
| 2084&lt;br /&gt;
| 0824&lt;br /&gt;
| Bestech&lt;br /&gt;
|-&lt;br /&gt;
| 2085&lt;br /&gt;
| 0825&lt;br /&gt;
| Lasar Fantasy&lt;br /&gt;
|-&lt;br /&gt;
| 2086&lt;br /&gt;
| 0826&lt;br /&gt;
| Pulsar&lt;br /&gt;
|-&lt;br /&gt;
| 2087&lt;br /&gt;
| 0827&lt;br /&gt;
| Ivis&lt;br /&gt;
|-&lt;br /&gt;
| 2088&lt;br /&gt;
| 0828&lt;br /&gt;
| Applied Engineering&lt;br /&gt;
|-&lt;br /&gt;
| 2089&lt;br /&gt;
| 0829&lt;br /&gt;
| Solid-State Design &amp;amp;amp; Development&lt;br /&gt;
|-&lt;br /&gt;
| 2090&lt;br /&gt;
| 082A&lt;br /&gt;
| Vison Quest&lt;br /&gt;
|-&lt;br /&gt;
| 2091&lt;br /&gt;
| 082B&lt;br /&gt;
| Seaview Software&lt;br /&gt;
|-&lt;br /&gt;
| 2092&lt;br /&gt;
| 082C&lt;br /&gt;
| BSC&lt;br /&gt;
| Mistakenly used by ADS (Advanced Development Software)&lt;br /&gt;
|-&lt;br /&gt;
| 2093&lt;br /&gt;
| 082D&lt;br /&gt;
| Bernd Culenfeld&lt;br /&gt;
|-&lt;br /&gt;
| 2094&lt;br /&gt;
| 082E&lt;br /&gt;
| American Liquid Light&lt;br /&gt;
|-&lt;br /&gt;
| 2095&lt;br /&gt;
| 082F&lt;br /&gt;
| CEGITES&lt;br /&gt;
|-&lt;br /&gt;
| 2096&lt;br /&gt;
| 0830&lt;br /&gt;
| Quadlite Computers Ltd.&lt;br /&gt;
| Originally registered to EV Industries&lt;br /&gt;
|-&lt;br /&gt;
| 2097&lt;br /&gt;
| 0831&lt;br /&gt;
| Silicon Peace&lt;br /&gt;
|-&lt;br /&gt;
| 2098&lt;br /&gt;
| 0832&lt;br /&gt;
| Black Belt Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2099&lt;br /&gt;
| 0833&lt;br /&gt;
| Village Tronic&lt;br /&gt;
| Originally registerd to Steve Yaeger&lt;br /&gt;
|-&lt;br /&gt;
| 2100&lt;br /&gt;
| 0834&lt;br /&gt;
| ReadySoft&lt;br /&gt;
|-&lt;br /&gt;
| 2101&lt;br /&gt;
| 0835&lt;br /&gt;
| Phoenix Micro Technologies&lt;br /&gt;
|-&lt;br /&gt;
| 2102&lt;br /&gt;
| 0836&lt;br /&gt;
| Advanced Systems &amp;amp; Software&lt;br /&gt;
| Orignally assigned to Preferred Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2103&lt;br /&gt;
| 0837&lt;br /&gt;
| Rombo Productions&lt;br /&gt;
|-&lt;br /&gt;
| 2104&lt;br /&gt;
| 0838&lt;br /&gt;
| Impulse Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2105&lt;br /&gt;
| 0839&lt;br /&gt;
| Beta Unlimited&lt;br /&gt;
|-&lt;br /&gt;
| 2106&lt;br /&gt;
| 083A&lt;br /&gt;
| Memory Expansion System, Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2107&lt;br /&gt;
| 083B&lt;br /&gt;
| Vortex Computer Systems GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2108&lt;br /&gt;
| 083C&lt;br /&gt;
| Platypus Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2109&lt;br /&gt;
| 083D&lt;br /&gt;
| Gigatron OHG&lt;br /&gt;
|-&lt;br /&gt;
| 2110&lt;br /&gt;
| 083E&lt;br /&gt;
| PG Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2111&lt;br /&gt;
| 083F&lt;br /&gt;
| New Technologies Group&lt;br /&gt;
|-&lt;br /&gt;
| 2112&lt;br /&gt;
| 0840&lt;br /&gt;
| Interactive Video Systems (IVS)&lt;br /&gt;
| Pacific Peripherals&lt;br /&gt;
|-&lt;br /&gt;
| 2113&lt;br /&gt;
| 0841&lt;br /&gt;
| Vector&lt;br /&gt;
| Originally registered to H. K. Computer&lt;br /&gt;
|-&lt;br /&gt;
| 2114&lt;br /&gt;
| 0842&lt;br /&gt;
| Pacific Digital&lt;br /&gt;
| Originally registered to C. H. Helfrich Elektronik&lt;br /&gt;
|-&lt;br /&gt;
| 2115&lt;br /&gt;
| 0843&lt;br /&gt;
| Xanadu&lt;br /&gt;
|-&lt;br /&gt;
| 2116&lt;br /&gt;
| 0844&lt;br /&gt;
| Pacific Digital&lt;br /&gt;
| Originally registered to AMS&lt;br /&gt;
|-&lt;br /&gt;
| 2117&lt;br /&gt;
| 0845&lt;br /&gt;
| X-Pert&lt;br /&gt;
|-&lt;br /&gt;
| 2118&lt;br /&gt;
| 0846&lt;br /&gt;
| The Amiga Centre&lt;br /&gt;
|-&lt;br /&gt;
| 2119&lt;br /&gt;
| 0847&lt;br /&gt;
| Digital Pacific&lt;br /&gt;
|-&lt;br /&gt;
| 2120&lt;br /&gt;
| 0848&lt;br /&gt;
| Solid State Leisure&lt;br /&gt;
|-&lt;br /&gt;
| 2121&lt;br /&gt;
| 0849&lt;br /&gt;
| Hydra Systems&lt;br /&gt;
| Originally registered to Analog Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2122&lt;br /&gt;
| 084A&lt;br /&gt;
| Cumana&lt;br /&gt;
|-&lt;br /&gt;
| 2123&lt;br /&gt;
| 084B&lt;br /&gt;
| KAPS 2C Conception&lt;br /&gt;
|-&lt;br /&gt;
| 2124&lt;br /&gt;
| 084C&lt;br /&gt;
| Mike Mason&lt;br /&gt;
|-&lt;br /&gt;
| 2125&lt;br /&gt;
| 084D&lt;br /&gt;
| For Your Eyes&lt;br /&gt;
|-&lt;br /&gt;
| 2126&lt;br /&gt;
| 084E&lt;br /&gt;
| Volkmar Breitfeld Computersysteme&lt;br /&gt;
|-&lt;br /&gt;
| 2127&lt;br /&gt;
| 084F&lt;br /&gt;
| Sunrize Industries&lt;br /&gt;
|-&lt;br /&gt;
| 2128&lt;br /&gt;
| 0850&lt;br /&gt;
| Scott Advanced Micro Designs&lt;br /&gt;
|-&lt;br /&gt;
| 2129&lt;br /&gt;
| 0851&lt;br /&gt;
| Digital Micronics&lt;br /&gt;
|-&lt;br /&gt;
| 2130&lt;br /&gt;
| 0852&lt;br /&gt;
| Alfa-Laval&lt;br /&gt;
|-&lt;br /&gt;
| 2131&lt;br /&gt;
| 0853&lt;br /&gt;
| Multigros A/S&lt;br /&gt;
|-&lt;br /&gt;
| 2132&lt;br /&gt;
| 0854&lt;br /&gt;
| Archos&lt;br /&gt;
|-&lt;br /&gt;
| 2133&lt;br /&gt;
| 0855&lt;br /&gt;
| Icom Simulations&lt;br /&gt;
|-&lt;br /&gt;
| 2134&lt;br /&gt;
| 0856&lt;br /&gt;
| Commodore Test Engineering Group&lt;br /&gt;
|-&lt;br /&gt;
| 2135&lt;br /&gt;
| 0857&lt;br /&gt;
| Microcreations&lt;br /&gt;
|-&lt;br /&gt;
| 2136&lt;br /&gt;
| 0858&lt;br /&gt;
| Shoestring Productions&lt;br /&gt;
|-&lt;br /&gt;
| 2137&lt;br /&gt;
| 0859&lt;br /&gt;
| Faberushi&lt;br /&gt;
|-&lt;br /&gt;
| 2138&lt;br /&gt;
| 085A&lt;br /&gt;
| Evesham Micro Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2139&lt;br /&gt;
| 085B&lt;br /&gt;
| Panagolin Laser Software&lt;br /&gt;
|-&lt;br /&gt;
| 2140&lt;br /&gt;
| 085C&lt;br /&gt;
| Thomas Rudloff&lt;br /&gt;
|-&lt;br /&gt;
| 2141&lt;br /&gt;
| 085D&lt;br /&gt;
| Daniel Hohabir&lt;br /&gt;
|-&lt;br /&gt;
| 2142&lt;br /&gt;
| 085E&lt;br /&gt;
| GfxBase, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2143&lt;br /&gt;
| 085F&lt;br /&gt;
| Axellabs&lt;br /&gt;
|-&lt;br /&gt;
| 2144&lt;br /&gt;
| 0860&lt;br /&gt;
| Roctec Electronics Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2145&lt;br /&gt;
| 0861&lt;br /&gt;
| Omega Datentechnik&lt;br /&gt;
|-&lt;br /&gt;
| 2146&lt;br /&gt;
| 0862&lt;br /&gt;
| Atlantis&lt;br /&gt;
|-&lt;br /&gt;
| 2147&lt;br /&gt;
| 0863&lt;br /&gt;
| Skytec Computers&lt;br /&gt;
|-&lt;br /&gt;
| 2148&lt;br /&gt;
| 0864&lt;br /&gt;
| Protar Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2149&lt;br /&gt;
| 0865&lt;br /&gt;
| ACS&lt;br /&gt;
|-&lt;br /&gt;
| 2150&lt;br /&gt;
| 0866&lt;br /&gt;
| Software Results Enterprises&lt;br /&gt;
| Originally registered to University of Illinois&lt;br /&gt;
|-&lt;br /&gt;
| 2151&lt;br /&gt;
| 0867&lt;br /&gt;
| Infinity Systems Design Group&lt;br /&gt;
|-&lt;br /&gt;
| 2152&lt;br /&gt;
| 0868&lt;br /&gt;
| Trade It&lt;br /&gt;
|-&lt;br /&gt;
| 2153&lt;br /&gt;
| 0869&lt;br /&gt;
| Suntec, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2154&lt;br /&gt;
| 086A&lt;br /&gt;
| DJW Micro Systems&lt;br /&gt;
| Originally registered to Tritec Marketing&lt;br /&gt;
|-&lt;br /&gt;
| 2155&lt;br /&gt;
| 086B&lt;br /&gt;
| Power Computing Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2156&lt;br /&gt;
| 086C&lt;br /&gt;
| MacroSystems&lt;br /&gt;
|-&lt;br /&gt;
| 2157&lt;br /&gt;
| 086D&lt;br /&gt;
| Masoboshi GmbH (DCE)&lt;br /&gt;
|-&lt;br /&gt;
| 2158&lt;br /&gt;
| 086E&lt;br /&gt;
| HAL Software Hardware Handel&lt;br /&gt;
|-&lt;br /&gt;
| 2159&lt;br /&gt;
| 086F&lt;br /&gt;
| Mainhattan Data&lt;br /&gt;
| Originally registered to Michael Lamm Computersysteme&lt;br /&gt;
|-&lt;br /&gt;
| 2160&lt;br /&gt;
| 0870&lt;br /&gt;
| Digital Processing System&lt;br /&gt;
| Originally registered to bbdp Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2161&lt;br /&gt;
| 0871&lt;br /&gt;
| Blue Ribbon Soundworks&lt;br /&gt;
| Originally registered to Design Computer Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2162&lt;br /&gt;
| 0872&lt;br /&gt;
| XPert&lt;br /&gt;
| Originally registered to The Station&lt;br /&gt;
|-&lt;br /&gt;
| 2163&lt;br /&gt;
| 0873&lt;br /&gt;
| DelaComp&lt;br /&gt;
| Originally registered to Bryan Williams&lt;br /&gt;
|-&lt;br /&gt;
| 2164&lt;br /&gt;
| 0874&lt;br /&gt;
| Superformance Computer Engineering GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2165&lt;br /&gt;
| 0875&lt;br /&gt;
| Overland Engineering&lt;br /&gt;
|-&lt;br /&gt;
| 2166&lt;br /&gt;
| 0876&lt;br /&gt;
| Thomas Hamren&lt;br /&gt;
|-&lt;br /&gt;
| 2167&lt;br /&gt;
| 0877&lt;br /&gt;
| Village Tronic&lt;br /&gt;
|-&lt;br /&gt;
| 2168&lt;br /&gt;
| 0878&lt;br /&gt;
| Toolbox Design&lt;br /&gt;
|-&lt;br /&gt;
| 2169&lt;br /&gt;
| 0879&lt;br /&gt;
| Digital Processing System&lt;br /&gt;
|-&lt;br /&gt;
| 2170&lt;br /&gt;
| 087A&lt;br /&gt;
| Superformance&lt;br /&gt;
|-&lt;br /&gt;
| 2171&lt;br /&gt;
| 087B&lt;br /&gt;
| Utilities Unlimited&lt;br /&gt;
|-&lt;br /&gt;
| 2172&lt;br /&gt;
| 087C&lt;br /&gt;
| phase 5&lt;br /&gt;
|-&lt;br /&gt;
| 2173&lt;br /&gt;
| 087D&lt;br /&gt;
| Juergen Kommos&lt;br /&gt;
|-&lt;br /&gt;
| 2174&lt;br /&gt;
| 087E&lt;br /&gt;
| Electronic Design&lt;br /&gt;
|-&lt;br /&gt;
| 2175&lt;br /&gt;
| 087F&lt;br /&gt;
| James Cook University of North Queensland&lt;br /&gt;
|-&lt;br /&gt;
| 2176&lt;br /&gt;
| 0880&lt;br /&gt;
| AmiTrix Development&lt;br /&gt;
|-&lt;br /&gt;
| 2177&lt;br /&gt;
| 0881&lt;br /&gt;
| Ferranti&lt;br /&gt;
|-&lt;br /&gt;
| 2178&lt;br /&gt;
| 0882&lt;br /&gt;
| Leviathan Development&lt;br /&gt;
|-&lt;br /&gt;
| 2179&lt;br /&gt;
| 0883&lt;br /&gt;
| United Video Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2180&lt;br /&gt;
| 0884&lt;br /&gt;
| GPSoft Pty. Ltd.&lt;br /&gt;
| Originally registered to Juergen Kommos&lt;br /&gt;
|-&lt;br /&gt;
| 2181&lt;br /&gt;
| 0885&lt;br /&gt;
| ArMAX&lt;br /&gt;
| Oliver Bausch&lt;br /&gt;
|-&lt;br /&gt;
| 2182&lt;br /&gt;
| 0886&lt;br /&gt;
| CP Computer&lt;br /&gt;
|-&lt;br /&gt;
| 2183&lt;br /&gt;
| 0887&lt;br /&gt;
| AMOK - Amiga Module &amp;amp;amp; Oberon Klub&lt;br /&gt;
|-&lt;br /&gt;
| 2184&lt;br /&gt;
| 0888&lt;br /&gt;
| ITEK Neser &amp;amp;amp; Sieber GbR&lt;br /&gt;
|-&lt;br /&gt;
| 2185&lt;br /&gt;
| 0889&lt;br /&gt;
| Phillip C. Lello&lt;br /&gt;
|-&lt;br /&gt;
| 2186&lt;br /&gt;
| 088A&lt;br /&gt;
| Cyborg Design Services&lt;br /&gt;
|-&lt;br /&gt;
| 2187&lt;br /&gt;
| 088B&lt;br /&gt;
| G2 Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2188&lt;br /&gt;
| 088C&lt;br /&gt;
| Pro System Computersysteme&lt;br /&gt;
|-&lt;br /&gt;
| 2189&lt;br /&gt;
| 088D&lt;br /&gt;
| ZEUS Electronic&lt;br /&gt;
| Originally registered to MSPI (Markt &amp;amp;amp; Technik)&lt;br /&gt;
|-&lt;br /&gt;
| 2190&lt;br /&gt;
| 088E&lt;br /&gt;
| Altatech&lt;br /&gt;
|-&lt;br /&gt;
| 2191&lt;br /&gt;
| 088F&lt;br /&gt;
| NewTek&lt;br /&gt;
|-&lt;br /&gt;
| 2192&lt;br /&gt;
| 0890&lt;br /&gt;
| M-TEC Hardware Design&lt;br /&gt;
| Originally registered to Hardware Design Udo Neuroth&lt;br /&gt;
|-&lt;br /&gt;
| 2193&lt;br /&gt;
| 0891&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
| Originally registered to Viona Development&lt;br /&gt;
|-&lt;br /&gt;
| 2194&lt;br /&gt;
| 0892&lt;br /&gt;
| Amitek&lt;br /&gt;
| Originally assigned to Marpet Developments&lt;br /&gt;
|-&lt;br /&gt;
| 2195&lt;br /&gt;
| 0893&lt;br /&gt;
| Ingenieurbuero Helfrich&lt;br /&gt;
|-&lt;br /&gt;
| 2196&lt;br /&gt;
| 0894&lt;br /&gt;
| The Neo Group&lt;br /&gt;
|-&lt;br /&gt;
| 2197&lt;br /&gt;
| 0895&lt;br /&gt;
| Cyon&lt;br /&gt;
|-&lt;br /&gt;
| 2198&lt;br /&gt;
| 0896&lt;br /&gt;
| Bob Research Group&lt;br /&gt;
|-&lt;br /&gt;
| 2199&lt;br /&gt;
| 0897&lt;br /&gt;
| Richmond Sound Design Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2200&lt;br /&gt;
| 0898&lt;br /&gt;
| US Cybernetics&lt;br /&gt;
|-&lt;br /&gt;
| 2201&lt;br /&gt;
| 0899&lt;br /&gt;
| Fulvio Ieva&lt;br /&gt;
|-&lt;br /&gt;
| 2202&lt;br /&gt;
| 089A&lt;br /&gt;
| Silicon Studio&lt;br /&gt;
|-&lt;br /&gt;
| 2203&lt;br /&gt;
| 089B&lt;br /&gt;
| MacroSystems (USA)&lt;br /&gt;
| Was named Micro System Devices&lt;br /&gt;
|-&lt;br /&gt;
| 2204&lt;br /&gt;
| 089C&lt;br /&gt;
| Conspector Entertainment&lt;br /&gt;
|-&lt;br /&gt;
| 2205&lt;br /&gt;
| 089D&lt;br /&gt;
| Laserforum&lt;br /&gt;
|-&lt;br /&gt;
| 2206&lt;br /&gt;
| 089E&lt;br /&gt;
| Elbox Computer&lt;br /&gt;
| Mistakenly used by Index Information Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2207&lt;br /&gt;
| 089F&lt;br /&gt;
| Applied Magic Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2208&lt;br /&gt;
| 08A0&lt;br /&gt;
| SDL Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2560&lt;br /&gt;
| 0A00&lt;br /&gt;
| Harms&lt;br /&gt;
|-&lt;br /&gt;
| 2588&lt;br /&gt;
| 0A1C&lt;br /&gt;
| A1K.org Community&lt;br /&gt;
|-&lt;br /&gt;
| 2640&lt;br /&gt;
| 0A50&lt;br /&gt;
| Micronik&lt;br /&gt;
|-&lt;br /&gt;
| 3084&lt;br /&gt;
| 0C0C&lt;br /&gt;
| Team 4&lt;br /&gt;
|-&lt;br /&gt;
| 3643&lt;br /&gt;
| 0E3B&lt;br /&gt;
| E3B&lt;br /&gt;
| Michael Boehmer&lt;br /&gt;
|-&lt;br /&gt;
| 3855&lt;br /&gt;
| 0F0F&lt;br /&gt;
| Micronik&lt;br /&gt;
|-&lt;br /&gt;
| 4096&lt;br /&gt;
| 1000&lt;br /&gt;
| MegaMicro&lt;br /&gt;
|-&lt;br /&gt;
| 4110&lt;br /&gt;
| 100E&lt;br /&gt;
| DigiFeX&lt;br /&gt;
|-&lt;br /&gt;
| 4136&lt;br /&gt;
| 1028&lt;br /&gt;
| Imtronics/Memphis&lt;br /&gt;
|-&lt;br /&gt;
| 4149&lt;br /&gt;
| 1035&lt;br /&gt;
| PROTAR&lt;br /&gt;
|-&lt;br /&gt;
| 4369&lt;br /&gt;
| 1111&lt;br /&gt;
| Frank Strauß Elektronik&lt;br /&gt;
| Also used by Kupke&lt;br /&gt;
|-&lt;br /&gt;
| 4626&lt;br /&gt;
| 1212&lt;br /&gt;
| Individual Computers&lt;br /&gt;
|-&lt;br /&gt;
| 4648&lt;br /&gt;
| 1228&lt;br /&gt;
| Flesch Hornemann Computer Elec.&lt;br /&gt;
|-&lt;br /&gt;
| 4680&lt;br /&gt;
| 1248&lt;br /&gt;
| Kupke Computertechnik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 4711&lt;br /&gt;
| 1267&lt;br /&gt;
| RBM digitaltechnik&lt;br /&gt;
|-&lt;br /&gt;
| 4754&lt;br /&gt;
| 1292&lt;br /&gt;
| MacroSystems&lt;br /&gt;
|-&lt;br /&gt;
| 5000&lt;br /&gt;
| 1388&lt;br /&gt;
| ITH&lt;br /&gt;
|-&lt;br /&gt;
| 5001&lt;br /&gt;
| 1389&lt;br /&gt;
| VMC&lt;br /&gt;
|-&lt;br /&gt;
| 5010&lt;br /&gt;
| 1392&lt;br /&gt;
| Ambience Creation Technology&lt;br /&gt;
|-&lt;br /&gt;
| 5011&lt;br /&gt;
| 1393&lt;br /&gt;
| Creative Development&lt;br /&gt;
|-&lt;br /&gt;
| 5012&lt;br /&gt;
| 1394&lt;br /&gt;
| Georg Braun&lt;br /&gt;
|-&lt;br /&gt;
| 5013&lt;br /&gt;
| 1395&lt;br /&gt;
| Swedish User Group of Amiga&lt;br /&gt;
|-&lt;br /&gt;
| 5014&lt;br /&gt;
| 1396&lt;br /&gt;
| Jakub Bednarski&lt;br /&gt;
|-&lt;br /&gt;
| 5015&lt;br /&gt;
| 1397&lt;br /&gt;
| KryoFlux, Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 5016&lt;br /&gt;
| 1398&lt;br /&gt;
| Igor Majstorovic&lt;br /&gt;
|-&lt;br /&gt;
| 5017&lt;br /&gt;
| 1399&lt;br /&gt;
| Alastair M. Robinson&lt;br /&gt;
|-&lt;br /&gt;
| 5018&lt;br /&gt;
| 139A&lt;br /&gt;
| Austex Software&lt;br /&gt;
|-&lt;br /&gt;
| 5019&lt;br /&gt;
| 139B&lt;br /&gt;
| Sören Gust&lt;br /&gt;
|-&lt;br /&gt;
| 5020&lt;br /&gt;
| 139C&lt;br /&gt;
| Rok Krajnc&lt;br /&gt;
|-&lt;br /&gt;
| 5030&lt;br /&gt;
| 13A6&lt;br /&gt;
| Tim Tashpulatov&lt;br /&gt;
|-&lt;br /&gt;
| 5040&lt;br /&gt;
| 13B0&lt;br /&gt;
| 7-bit&lt;br /&gt;
|-&lt;br /&gt;
| 5050&lt;br /&gt;
| 13BA&lt;br /&gt;
| Sakura IT&lt;br /&gt;
|-&lt;br /&gt;
| 5060&lt;br /&gt;
| 13C4&lt;br /&gt;
| FPGAArcade&lt;br /&gt;
|-&lt;br /&gt;
| 5070&lt;br /&gt;
| 13CE&lt;br /&gt;
| CancerSoft Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 5080&lt;br /&gt;
| 13D8&lt;br /&gt;
| Stephen Leary&lt;br /&gt;
|-&lt;br /&gt;
| 5090&lt;br /&gt;
| 13E2&lt;br /&gt;
| DMA Softlab LLC&lt;br /&gt;
|-&lt;br /&gt;
| 5100&lt;br /&gt;
| 13EC&lt;br /&gt;
| Brookhouse Engineering&lt;br /&gt;
|-&lt;br /&gt;
| 5110&lt;br /&gt;
| 13F6&lt;br /&gt;
| Eduardo Arana&lt;br /&gt;
|-&lt;br /&gt;
| 5120&lt;br /&gt;
| 1400&lt;br /&gt;
| CS-LAB&lt;br /&gt;
|-&lt;br /&gt;
| 5130&lt;br /&gt;
| 140A&lt;br /&gt;
| Robert Miranda&lt;br /&gt;
|-&lt;br /&gt;
| 5140&lt;br /&gt;
| 1414&lt;br /&gt;
| RastPort&lt;br /&gt;
|-&lt;br /&gt;
| 5132&lt;br /&gt;
| 140C&lt;br /&gt;
| UAS Interface Ltd6&lt;br /&gt;
|-&lt;br /&gt;
| 5150&lt;br /&gt;
| 141E&lt;br /&gt;
| Amiga Kit&lt;br /&gt;
|-&lt;br /&gt;
| 5160&lt;br /&gt;
| 1428&lt;br /&gt;
| Central Texas Commodore User Group&lt;br /&gt;
|-&lt;br /&gt;
| 5170&lt;br /&gt;
| 1432&lt;br /&gt;
| Confusion Research Center&lt;br /&gt;
|-&lt;br /&gt;
| 5180&lt;br /&gt;
| 143C&lt;br /&gt;
| Solar Soyuz Zaibatsu&lt;br /&gt;
|-&lt;br /&gt;
| 5190&lt;br /&gt;
| 1446&lt;br /&gt;
| BooBip&lt;br /&gt;
|-&lt;br /&gt;
| 5191&lt;br /&gt;
| 1447&lt;br /&gt;
| Matthias Hampel&lt;br /&gt;
|-&lt;br /&gt;
| 5192&lt;br /&gt;
| 1448&lt;br /&gt;
| dec0de Consulting Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 5193&lt;br /&gt;
| 1449&lt;br /&gt;
| Puppy Concepts&lt;br /&gt;
|-&lt;br /&gt;
| 5194&lt;br /&gt;
| 144A&lt;br /&gt;
| Open Amiga Hardware Repository&lt;br /&gt;
|-&lt;br /&gt;
| 5195&lt;br /&gt;
| 144B&lt;br /&gt;
| Double H Tech&lt;br /&gt;
|-&lt;br /&gt;
| 5196&lt;br /&gt;
| 144C&lt;br /&gt;
| Retromatik&lt;br /&gt;
|-&lt;br /&gt;
| 5500&lt;br /&gt;
| 157C&lt;br /&gt;
| Inhouse Information&lt;br /&gt;
|-&lt;br /&gt;
| 5768&lt;br /&gt;
| 1688&lt;br /&gt;
| Bio Con&lt;br /&gt;
|-&lt;br /&gt;
| 6148&lt;br /&gt;
| 1804&lt;br /&gt;
| HK-Computer&lt;br /&gt;
|-&lt;br /&gt;
| 6502&lt;br /&gt;
| 1966&lt;br /&gt;
| Cloanto&lt;br /&gt;
|-&lt;br /&gt;
| 6520&lt;br /&gt;
| 1978&lt;br /&gt;
| Oliver Gantert&lt;br /&gt;
|-&lt;br /&gt;
| 7777&lt;br /&gt;
| 1E61&lt;br /&gt;
| Rafal Gabriel Chyla&lt;br /&gt;
|-&lt;br /&gt;
| 8215&lt;br /&gt;
| 2017&lt;br /&gt;
| Vortex&lt;br /&gt;
|-&lt;br /&gt;
| 8244&lt;br /&gt;
| 2034&lt;br /&gt;
| Spirit Technology&lt;br /&gt;
|-&lt;br /&gt;
| 8290&lt;br /&gt;
| 2062&lt;br /&gt;
| Expansion Systems&lt;br /&gt;
|-&lt;br /&gt;
| 8448&lt;br /&gt;
| 2100&lt;br /&gt;
| ReadySoft&lt;br /&gt;
|-&lt;br /&gt;
| 8512&lt;br /&gt;
| 2140&lt;br /&gt;
| Phase 5 Digital Products&lt;br /&gt;
|-&lt;br /&gt;
| 8553&lt;br /&gt;
| 2169&lt;br /&gt;
| Digital Processing Systems Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 8704&lt;br /&gt;
| 2200&lt;br /&gt;
| ACT Elektronik&lt;br /&gt;
|-&lt;br /&gt;
| 8738&lt;br /&gt;
| 2222&lt;br /&gt;
| ACT Elektronik&lt;br /&gt;
|-&lt;br /&gt;
| 9512&lt;br /&gt;
| 2528&lt;br /&gt;
| Tower Technologies&lt;br /&gt;
|-&lt;br /&gt;
| 10676&lt;br /&gt;
| 29B4&lt;br /&gt;
| Electronic Design&lt;br /&gt;
|-&lt;br /&gt;
| 14195&lt;br /&gt;
| 3773&lt;br /&gt;
| Media-net-Point&lt;br /&gt;
|-&lt;br /&gt;
| 14501&lt;br /&gt;
| 38A5&lt;br /&gt;
| Petsoff, Finland&lt;br /&gt;
|-&lt;br /&gt;
| 16375&lt;br /&gt;
| 3FF7&lt;br /&gt;
| Uwe Gerlach&lt;br /&gt;
|-&lt;br /&gt;
| 16707&lt;br /&gt;
| 4143&lt;br /&gt;
| Ateo Concepts&lt;br /&gt;
|-&lt;br /&gt;
| 16708&lt;br /&gt;
| 4144&lt;br /&gt;
| ALiENDESiGN&lt;br /&gt;
|-&lt;br /&gt;
| 16945&lt;br /&gt;
| 4231&lt;br /&gt;
| A.C.T.&lt;br /&gt;
|-&lt;br /&gt;
| 17740&lt;br /&gt;
| 454C&lt;br /&gt;
| HK-Computer (ELSAT)&lt;br /&gt;
|-&lt;br /&gt;
| 18260&lt;br /&gt;
| 4754&lt;br /&gt;
| MacroSystems (Germany)&lt;br /&gt;
|-&lt;br /&gt;
| 19796&lt;br /&gt;
| 4D54&lt;br /&gt;
| Markt &amp;amp; Technik&lt;br /&gt;
|-&lt;br /&gt;
| 22359&lt;br /&gt;
| 5757&lt;br /&gt;
| Markt &amp;amp; Technik&lt;br /&gt;
|-&lt;br /&gt;
| 26464&lt;br /&gt;
| 6760&lt;br /&gt;
| Combitec&lt;br /&gt;
|-&lt;br /&gt;
| 26470&lt;br /&gt;
| 6766&lt;br /&gt;
| Combitec&lt;br /&gt;
|-&lt;br /&gt;
| 28014&lt;br /&gt;
| 6D6E&lt;br /&gt;
| MNT Media and Technology UG&lt;br /&gt;
|-&lt;br /&gt;
| 32768&lt;br /&gt;
| 8000&lt;br /&gt;
| M.A.S.T.&lt;br /&gt;
|-&lt;br /&gt;
| 42240&lt;br /&gt;
| A500&lt;br /&gt;
| Aethreum Digital&lt;br /&gt;
|-&lt;br /&gt;
| 43437&lt;br /&gt;
| A9AD&lt;br /&gt;
| Reis-Ware&lt;br /&gt;
|-&lt;br /&gt;
| 43521&lt;br /&gt;
| AA01&lt;br /&gt;
| Cameron&lt;br /&gt;
|-&lt;br /&gt;
| 43537&lt;br /&gt;
| AA11&lt;br /&gt;
| Reis-Ware&lt;br /&gt;
|-&lt;br /&gt;
| 44359&lt;br /&gt;
| AD47&lt;br /&gt;
| Matay&lt;br /&gt;
|-&lt;br /&gt;
| 46504&lt;br /&gt;
| B5A8&lt;br /&gt;
| Phoenix&lt;br /&gt;
|-&lt;br /&gt;
| 48879&lt;br /&gt;
| BEEF&lt;br /&gt;
| Swiss Mountain Dog Products&lt;br /&gt;
|-&lt;br /&gt;
| 49160&lt;br /&gt;
| C008&lt;br /&gt;
| Combitec&lt;br /&gt;
|-&lt;br /&gt;
| 61453&lt;br /&gt;
| F00D&lt;br /&gt;
| Forefront Technologies Inc.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
For any changes/additions to this registry please send a support request to [mailto:support@hyperion-entertainment.com support@hyperion-entertainment.com].&lt;/div&gt;</summary>
		<author><name>Costel Mincea</name></author>
	</entry>
	<entry>
		<id>https://wiki.amigaos.net/w/index.php?title=Amiga_Hardware_Manufacturer_ID_Registry&amp;diff=12597</id>
		<title>Amiga Hardware Manufacturer ID Registry</title>
		<link rel="alternate" type="text/html" href="https://wiki.amigaos.net/w/index.php?title=Amiga_Hardware_Manufacturer_ID_Registry&amp;diff=12597"/>
		<updated>2026-09-08T10:27:48Z</updated>

		<summary type="html">&lt;p&gt;Costel Mincea: /* How to Obtain a Manufacturer Number */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
= How to Obtain a Manufacturer Number =&lt;br /&gt;
&lt;br /&gt;
Manufacturer&#039;s numbers are assigned by the AmigaOS development team. To obtain your unique manufacturer number send a support request to [mailto:support@hyperion-entertainment.com support@hyperion-entertainment.com] including these information:&lt;br /&gt;
&lt;br /&gt;
 1. The name of the company or person which the number is assigned to&lt;br /&gt;
 &lt;br /&gt;
 2. Postal address/contact address&lt;br /&gt;
 &lt;br /&gt;
 3. Name of the contact person, with a corresponding e-mail address&lt;br /&gt;
 &lt;br /&gt;
 4. A brief description of the kind of products you want to produce&lt;br /&gt;
&lt;br /&gt;
Be sure and include your name and the type of expansion product you are developing.&lt;br /&gt;
&lt;br /&gt;
= Your Manufacturer Number =&lt;br /&gt;
&lt;br /&gt;
Attention hardware manufacturers. If you are developing a hardware expansion product for the Classic Amiga (e.g. 500, 2000, 3000) then you will need to obtain a special manufacturer ID number from the AmigaOS development team to identify your product. This manufacturer number is used by the Amiga to link your hardware with its driver software at boot time.&lt;br /&gt;
&lt;br /&gt;
Your manufacturer number is part of the special protocol that the Amiga uses to automatically configure all expansion devices on the bus without the user having to cut jumpers or adjust dip switches. This is called auto-config.&lt;br /&gt;
&lt;br /&gt;
At start-up time, the system first polls each board in the system and assigns the board its own address space. If it is a memory board, its RAM is linked into the memory free pool. Later in the boot sequence, after DOS is initialized, the binddrivers program is run. Binddrivers will search the directory SYS:Expansion for the drivers that go with the boards.&lt;br /&gt;
&lt;br /&gt;
To do this binddrivers looks in the Tool Type field of all icon files in SYS:Expansion. If the first seven bytes of the Tool Type field are &amp;quot;PRODUCT&amp;quot;, then this is an icon file for a driver.&lt;br /&gt;
&lt;br /&gt;
Binddrivers will then attempt to match the drivers it has found with the boards that were found earlier. This is where your manufacturer number comes in.&lt;br /&gt;
&lt;br /&gt;
Your manufacturer number goes in two places. First, it is burned in hex form into the PAL which is part of ALL auto-config expansion products. Second, it appears in ASCII in the Tool Type field of the icon file for your product&#039;s driver. By matching these two numbers, the Amiga can automatically configure your board and bind it&#039;s software driver into the system as well.&lt;br /&gt;
&lt;br /&gt;
The manufacturer&#039;s number is a 16-bit ID which appears in PAL offsets $10-$17. There is also an 8-bit product number which you assign. The product number is for uniquely identifying different products from the same vendor. The product number will appear in PAL offsets $04-$07. This gives you a total of 24 bits to identify each of your products.&lt;br /&gt;
&lt;br /&gt;
These 24 bits of information in the PAL which identify your product are matched against the information in the Tool Type field of all icon files in the SYS:Expansion drawer. For example, suppose you are manufacturer #1019. You have two products, #1 and #2 which both use the same driver. The icon for your driver for these two products would have a Tool Type set to &amp;quot;PRODUCT=1019/1|1019/2&amp;quot;. This means: I am an icon for a driver that works with product number 1 or 2 from manufacturer 1019, now bind me. Spaces are not legal. Here are two other examples:&lt;br /&gt;
&lt;br /&gt;
; PRODUCT=1208/11&lt;br /&gt;
: is the Tool Type for a driver for product 11 from manufacturer number 1208.&lt;br /&gt;
&lt;br /&gt;
; PRODUCT=1017&lt;br /&gt;
: is the Tool Type for a driver for any product from manufacturer number 1017.&lt;br /&gt;
&lt;br /&gt;
For an informal explanation of the auto-configuration process, see the chapter on Software Expansion Architecture from the 2nd Annual Amiga Developer&#039;s Conference Notes (available on ADCD 2.1). For the details of timing, power, the PAL equations and PAL address specifications and the expansion library documentation, see sections 3.1 to 3.3 of the A500/A2000 Technical Reference Manual. The original auto-config spec appears in the A1000 Schematics and Expansion Specification.&lt;br /&gt;
&lt;br /&gt;
The auto-config process makes the addition of expansion products to the system very easy. All the user has to do is put the board in any slot and copy the driver from the release disk to his own SYS:Expansion drawer. Everything else is automatic. There are no jumpers or dip switches to set. Best of all, you will get a lot less support calls asking how to make your product work with the XYZ-Corp-battery-backed-clock.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
&lt;br /&gt;
Some notes on hardware manufacturer ID assignment.&lt;br /&gt;
&lt;br /&gt;
* Manufacturer ID numbers are assigned free of charge.&lt;br /&gt;
* Please provide the following information when requesting an ID:&lt;br /&gt;
*# Name of the company or person&lt;br /&gt;
*# Postal address/contact address&lt;br /&gt;
*# Name of the contact person, with a corresponding e-mail address&lt;br /&gt;
*# A brief description of the kind of products you want to produce&lt;br /&gt;
* All ID numbers smaller than 5000 must be considered unsafe because no information exists on which numbers exactly were taken during the time Commodore, Inc. disintegrated.&lt;br /&gt;
* ID numbers in the range 8192 to 18841 must be considered unsafe because some hardware developers mistook the numbers assigned to them to be given in hexadecimal format. Hence 0x2000 = 8192 and 0x4999 = 18841.&lt;br /&gt;
&lt;br /&gt;
= Example code =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
/*-----------------------------------------------*/&lt;br /&gt;
/* Here is a short program which will tell you   */&lt;br /&gt;
/* about the expansion boards configured in your */&lt;br /&gt;
/* system without you opening up the machine.    */&lt;br /&gt;
/* Code by Bill Koester of CATS                  */&lt;br /&gt;
/*-----------------------------------------------*/&lt;br /&gt;
#include &amp;lt;libraries/configvars.h&amp;gt;&lt;br /&gt;
#include &amp;lt;libraries/expansion.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
struct ExpansionBase *ExpansionBase;&lt;br /&gt;
&lt;br /&gt;
void cleanup();&lt;br /&gt;
void printdev();&lt;br /&gt;
&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
   struct ConfigDev *MyConfigDev;&lt;br /&gt;
&lt;br /&gt;
   /*----------------------------------*/&lt;br /&gt;
   /* Open the expansion library,      */&lt;br /&gt;
   /* if there is a problem then exit  */&lt;br /&gt;
   /*----------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   ExpansionBase =(struct ExpansionBase *) OpenLibrary(EXPANSIONNAME,0);&lt;br /&gt;
   if(ExpansionBase==NULL)&lt;br /&gt;
   {&lt;br /&gt;
      printf(&amp;quot;Error opening expansion library!!\n&amp;quot;);&lt;br /&gt;
      cleanup();&lt;br /&gt;
      exit(0);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   /*--------------------------------------------*/&lt;br /&gt;
   /* Use FindConfigDev to get info on the first */&lt;br /&gt;
   /* expansion board on the list maintained by  */&lt;br /&gt;
   /* Exec.  If there are no expansion boards in */&lt;br /&gt;
   /* the system then exit.                      */&lt;br /&gt;
   /*--------------------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   MyConfigDev = NULL;&lt;br /&gt;
&lt;br /&gt;
  /*--------------------------------------------------*/&lt;br /&gt;
  /* FindConfigDev(oldConfigDev,manufacturer,product) */&lt;br /&gt;
  /* oldConfigDev = NULL for the top of the list      */&lt;br /&gt;
  /* manufacturer = -1 for any manufacturer           */&lt;br /&gt;
  /* product      = -1 for any product                */&lt;br /&gt;
  /*--------------------------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   MyConfigDev = FindConfigDev(NULL,-1,-1);&lt;br /&gt;
&lt;br /&gt;
   if(MyConfigDev==NULL)&lt;br /&gt;
   {&lt;br /&gt;
      printf(&amp;quot;No Configured Devices found!!\n&amp;quot;);&lt;br /&gt;
      cleanup();&lt;br /&gt;
      exit(0);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   printdev(MyConfigDev);&lt;br /&gt;
&lt;br /&gt;
   /*-----------------------------------*/&lt;br /&gt;
   /* OK, there is at least one board,  */&lt;br /&gt;
   /* so loop and get the entire list   */&lt;br /&gt;
   /* printing as we go with printdev() */&lt;br /&gt;
   /*-----------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   while(MyConfigDev = FindConfigDev(MyConfigDev,-1,-1))&lt;br /&gt;
   {&lt;br /&gt;
      printdev(MyConfigDev);&lt;br /&gt;
   }&lt;br /&gt;
   cleanup();&lt;br /&gt;
   return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*-------------------*/&lt;br /&gt;
/* Close up shop...  */&lt;br /&gt;
/*-------------------*/&lt;br /&gt;
void cleanup()&lt;br /&gt;
{&lt;br /&gt;
   if(ExpansionBase)&lt;br /&gt;
      CloseLibrary(ExpansionBase);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*----------------------------------*/&lt;br /&gt;
/* Print out the contents of the    */&lt;br /&gt;
/* dev structure for this expansion */&lt;br /&gt;
/* product.                         */&lt;br /&gt;
/*----------------------------------*/&lt;br /&gt;
&lt;br /&gt;
void printdev(dev)&lt;br /&gt;
struct ConfigDev *dev;&lt;br /&gt;
{&lt;br /&gt;
   char buff[200];&lt;br /&gt;
&lt;br /&gt;
   printf(&amp;quot;Flags          = &amp;quot;);&lt;br /&gt;
   if(dev-&amp;gt;cd_Flags==NULL)&lt;br /&gt;
      printf(&amp;quot;NULL  &amp;quot;);&lt;br /&gt;
   if(dev-&amp;gt;cd_Flags&amp;amp;CDF_SHUTUP)&lt;br /&gt;
      printf(&amp;quot;CDF_SHUTUP  &amp;quot;);&lt;br /&gt;
   if(dev-&amp;gt;cd_Flags&amp;amp;CDF_CONFIGME)&lt;br /&gt;
      printf(&amp;quot;CDF_CONFIGME  &amp;quot;);&lt;br /&gt;
   printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
   printf(&amp;quot;Board Address  = %x\n&amp;quot;,dev-&amp;gt;cd_BoardAddr);&lt;br /&gt;
   printf(&amp;quot;Board Size     = %d bytes\n&amp;quot;,dev-&amp;gt;cd_BoardSize);&lt;br /&gt;
   printf(&amp;quot;Slot  Address  = %d\n&amp;quot;,dev-&amp;gt;cd_SlotAddr);&lt;br /&gt;
   printf(&amp;quot;Slot  Size     = %d\n&amp;quot;,dev-&amp;gt;cd_SlotSize);&lt;br /&gt;
   printf(&amp;quot;Driver code at   %x\n&amp;quot;,dev-&amp;gt;cd_Driver);&lt;br /&gt;
&lt;br /&gt;
   printf(&amp;quot;er_Type         = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Type);&lt;br /&gt;
   printf(&amp;quot;er_Product      = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Product);&lt;br /&gt;
   printf(&amp;quot;er_Flags        = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Flags);&lt;br /&gt;
   printf(&amp;quot;er_Reserved03   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved03);&lt;br /&gt;
   printf(&amp;quot;er_Manufacturer = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Manufacturer);&lt;br /&gt;
   printf(&amp;quot;er_SerialNumber = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_SerialNumber);&lt;br /&gt;
   printf(&amp;quot;er_InitDiagVec  = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_InitDiagVec);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0c   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0c);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0d   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0d);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0e   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0e);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0f   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0f);&lt;br /&gt;
&lt;br /&gt;
   printf(&amp;quot;Hit Return to continue:\n&amp;quot;);&lt;br /&gt;
   gets(buff);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Registry =&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! ID (decimal)&lt;br /&gt;
! ID (hexadecimal)&lt;br /&gt;
! Manufacturer&lt;br /&gt;
! Notes&lt;br /&gt;
|-&lt;br /&gt;
| 1&lt;br /&gt;
| 0001&lt;br /&gt;
| Micronik&lt;br /&gt;
|-&lt;br /&gt;
| 211&lt;br /&gt;
| 00D3&lt;br /&gt;
| Pacific Peripherals/Profex&lt;br /&gt;
|-&lt;br /&gt;
| 221&lt;br /&gt;
| 00DD&lt;br /&gt;
| Kupke Computertechnik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 256&lt;br /&gt;
| 0100&lt;br /&gt;
| Memphis&lt;br /&gt;
| Originally registered to MacroSystems US&lt;br /&gt;
|-&lt;br /&gt;
| 512&lt;br /&gt;
| 0200&lt;br /&gt;
| 3-State Computertechnik&lt;br /&gt;
|-&lt;br /&gt;
| 513&lt;br /&gt;
| 0201&lt;br /&gt;
| Commodore (Braunschweig)&lt;br /&gt;
|-&lt;br /&gt;
| 514&lt;br /&gt;
| 0202&lt;br /&gt;
| Commodore (West Chester)&lt;br /&gt;
|-&lt;br /&gt;
| 515&lt;br /&gt;
| 0203&lt;br /&gt;
| Commodore (West Chester)&lt;br /&gt;
| Originally registered to Combitech/Macrosystem&lt;br /&gt;
|-&lt;br /&gt;
| 756&lt;br /&gt;
| 02F4&lt;br /&gt;
| Progressive Peripherals &amp;amp; Software&lt;br /&gt;
|-&lt;br /&gt;
| 767&lt;br /&gt;
| 02FF&lt;br /&gt;
| Kolff Computer Supplies&lt;br /&gt;
|-&lt;br /&gt;
| 1001&lt;br /&gt;
| 03E9&lt;br /&gt;
| Tecmar&lt;br /&gt;
|-&lt;br /&gt;
| 1002&lt;br /&gt;
| 03EA&lt;br /&gt;
| Telesys&lt;br /&gt;
|-&lt;br /&gt;
| 1003&lt;br /&gt;
| 03EB&lt;br /&gt;
| The Micro-Forge&lt;br /&gt;
|-&lt;br /&gt;
| 1004&lt;br /&gt;
| 03EC&lt;br /&gt;
| Kronos/C Ltd.&lt;br /&gt;
| Originally registered to Card Co. (Supra)&lt;br /&gt;
|-&lt;br /&gt;
| 1005&lt;br /&gt;
| 03ED&lt;br /&gt;
| A-Squared&lt;br /&gt;
|-&lt;br /&gt;
| 1006&lt;br /&gt;
| 03EE&lt;br /&gt;
| Comspec Communications&lt;br /&gt;
|-&lt;br /&gt;
| 1007&lt;br /&gt;
| 03EF&lt;br /&gt;
| HT Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 1008&lt;br /&gt;
| 03F0&lt;br /&gt;
| RDS Software&lt;br /&gt;
|-&lt;br /&gt;
| 1009&lt;br /&gt;
| 03F1&lt;br /&gt;
| Anakin Research&lt;br /&gt;
|-&lt;br /&gt;
| 1010&lt;br /&gt;
| 03F2&lt;br /&gt;
| MicroBotics&lt;br /&gt;
|-&lt;br /&gt;
| 1011&lt;br /&gt;
| 03F3&lt;br /&gt;
| Bob Krauth&lt;br /&gt;
|-&lt;br /&gt;
| 1012&lt;br /&gt;
| 03F4&lt;br /&gt;
| Access Associates (Alegra)&lt;br /&gt;
|-&lt;br /&gt;
| 1013&lt;br /&gt;
| 03F5&lt;br /&gt;
| Mini Comp Systems Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 1014&lt;br /&gt;
| 03F6&lt;br /&gt;
| Cypress Technology&lt;br /&gt;
|-&lt;br /&gt;
| 1015&lt;br /&gt;
| 03F7&lt;br /&gt;
| Fuller Computers&lt;br /&gt;
|-&lt;br /&gt;
| 1016&lt;br /&gt;
| 03F8&lt;br /&gt;
| Galaxy Computers&lt;br /&gt;
|-&lt;br /&gt;
| 1017&lt;br /&gt;
| 03F9&lt;br /&gt;
| ADA Research&lt;br /&gt;
|-&lt;br /&gt;
| 1018&lt;br /&gt;
| 03FA&lt;br /&gt;
| Computer Service Italia&lt;br /&gt;
|-&lt;br /&gt;
| 1019&lt;br /&gt;
| 03FB&lt;br /&gt;
| Amigo&lt;br /&gt;
|-&lt;br /&gt;
| 1020&lt;br /&gt;
| 03FC&lt;br /&gt;
| Micro-Solutions Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1021&lt;br /&gt;
| 03FD&lt;br /&gt;
| Stacar International&lt;br /&gt;
|-&lt;br /&gt;
| 1022&lt;br /&gt;
| 03FE&lt;br /&gt;
| Video Precisions&lt;br /&gt;
|-&lt;br /&gt;
| 1023&lt;br /&gt;
| 03FF&lt;br /&gt;
| ASDG, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1025&lt;br /&gt;
| 0401&lt;br /&gt;
| Ing. Buero Kalawsky&lt;br /&gt;
|-&lt;br /&gt;
| 1026&lt;br /&gt;
| 0402&lt;br /&gt;
| Computer Tuning&lt;br /&gt;
|-&lt;br /&gt;
| 1027&lt;br /&gt;
| 0403&lt;br /&gt;
| Interplan Unternehmensberatung&lt;br /&gt;
|-&lt;br /&gt;
| 1028&lt;br /&gt;
| 0404&lt;br /&gt;
| Imtronics/Memphis&lt;br /&gt;
| Originally registered to Peter Ohlich&lt;br /&gt;
|-&lt;br /&gt;
| 1030&lt;br /&gt;
| 0406&lt;br /&gt;
| Commodore (Lowell University)&lt;br /&gt;
| Originally registered to Productivity Center&lt;br /&gt;
|-&lt;br /&gt;
| 1041&lt;br /&gt;
| 0411&lt;br /&gt;
| Design Labs&lt;br /&gt;
|-&lt;br /&gt;
| 1042&lt;br /&gt;
| 0412&lt;br /&gt;
| MCS&lt;br /&gt;
|-&lt;br /&gt;
| 1043&lt;br /&gt;
| 0413&lt;br /&gt;
| B. J. Freeman&lt;br /&gt;
|-&lt;br /&gt;
| 1044&lt;br /&gt;
| 0414&lt;br /&gt;
| Side Effects Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1045&lt;br /&gt;
| 0415&lt;br /&gt;
| Oklahoma Personal Comp.&lt;br /&gt;
|-&lt;br /&gt;
| 1046&lt;br /&gt;
| 0416&lt;br /&gt;
| Advanced Micro Innovations&lt;br /&gt;
|-&lt;br /&gt;
| 1047&lt;br /&gt;
| 0417&lt;br /&gt;
| Industrial Support Services&lt;br /&gt;
|-&lt;br /&gt;
| 1048&lt;br /&gt;
| 0418&lt;br /&gt;
| Technisoft&lt;br /&gt;
|-&lt;br /&gt;
| 1049&lt;br /&gt;
| 0419&lt;br /&gt;
| Prolific, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1050&lt;br /&gt;
| 041A&lt;br /&gt;
| Softeam, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1051&lt;br /&gt;
| 041B&lt;br /&gt;
| GRC Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 1052&lt;br /&gt;
| 041C&lt;br /&gt;
| David Lai&lt;br /&gt;
|-&lt;br /&gt;
| 1053&lt;br /&gt;
| 041D&lt;br /&gt;
| Ameristar Technologies&lt;br /&gt;
|-&lt;br /&gt;
| 1054&lt;br /&gt;
| 041E&lt;br /&gt;
| Cline Refrigeration&lt;br /&gt;
|-&lt;br /&gt;
| 1055&lt;br /&gt;
| 041F&lt;br /&gt;
| Cardiac Pacemakers, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1056&lt;br /&gt;
| 0420&lt;br /&gt;
| Supra Corp. (Creative Microsystems)&lt;br /&gt;
|-&lt;br /&gt;
| 1057&lt;br /&gt;
| 0421&lt;br /&gt;
| Wayne Diener&lt;br /&gt;
|-&lt;br /&gt;
| 1058&lt;br /&gt;
| 0422&lt;br /&gt;
| Computer Systems Associates (CSA)&lt;br /&gt;
|-&lt;br /&gt;
| 1059&lt;br /&gt;
| 0423&lt;br /&gt;
| Trionix, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1060&lt;br /&gt;
| 0424&lt;br /&gt;
| David Lucas&lt;br /&gt;
|-&lt;br /&gt;
| 1061&lt;br /&gt;
| 0425&lt;br /&gt;
| Analog Precision&lt;br /&gt;
| Also assigned to D &amp;amp; L Distributing&lt;br /&gt;
|-&lt;br /&gt;
| 1267&lt;br /&gt;
| 04F3&lt;br /&gt;
| RBM Digitaltechnik&lt;br /&gt;
|-&lt;br /&gt;
| 1282&lt;br /&gt;
| 0502&lt;br /&gt;
| M-TEC Hardware Design&lt;br /&gt;
|-&lt;br /&gt;
| 1337&lt;br /&gt;
| 0539&lt;br /&gt;
| Thomas Stenzel (DaFR34K)&lt;br /&gt;
|-&lt;br /&gt;
| 1576&lt;br /&gt;
| 0628&lt;br /&gt;
| Boris Križma&lt;br /&gt;
|-&lt;br /&gt;
| 1761&lt;br /&gt;
| 06E1&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
|-&lt;br /&gt;
| 1803&lt;br /&gt;
| 070B&lt;br /&gt;
| UAE Amiga Emulator&lt;br /&gt;
|-&lt;br /&gt;
| 2002&lt;br /&gt;
| 07D2&lt;br /&gt;
| Mimetics Corp.&lt;br /&gt;
|-&lt;br /&gt;
| 2003&lt;br /&gt;
| 07D3&lt;br /&gt;
| ACDA&lt;br /&gt;
|-&lt;br /&gt;
| 2004&lt;br /&gt;
| 07D4&lt;br /&gt;
| Finn R. Jacobsen&lt;br /&gt;
|-&lt;br /&gt;
| 2005&lt;br /&gt;
| 07D5&lt;br /&gt;
| Elthen Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2006&lt;br /&gt;
| 07D6&lt;br /&gt;
| Nine Tiles Computer Systems Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2007&lt;br /&gt;
| 07D7&lt;br /&gt;
| Analog Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2008&lt;br /&gt;
| 07D8&lt;br /&gt;
| Bell &amp;amp;amp; Howell&lt;br /&gt;
|-&lt;br /&gt;
| 2009&lt;br /&gt;
| 07D9&lt;br /&gt;
| Roland Kochler&lt;br /&gt;
|-&lt;br /&gt;
| 2010&lt;br /&gt;
| 07DA&lt;br /&gt;
| Byte Corp.&lt;br /&gt;
|-&lt;br /&gt;
| 2011&lt;br /&gt;
| 07DB&lt;br /&gt;
| Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 2012&lt;br /&gt;
| 07DC&lt;br /&gt;
| DKB, Inc.&lt;br /&gt;
| Previously named Michigan Software&lt;br /&gt;
|-&lt;br /&gt;
| 2013&lt;br /&gt;
| 07DD&lt;br /&gt;
| Pacific Peripherals&lt;br /&gt;
|-&lt;br /&gt;
| 2014&lt;br /&gt;
| 07DE&lt;br /&gt;
| Sysaphus Software&lt;br /&gt;
|-&lt;br /&gt;
| 2015&lt;br /&gt;
| 07DF&lt;br /&gt;
| Digitronics&lt;br /&gt;
|-&lt;br /&gt;
| 2016&lt;br /&gt;
| 07E0&lt;br /&gt;
| Akron Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2017&lt;br /&gt;
| 07E1&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
|-&lt;br /&gt;
| 2018&lt;br /&gt;
| 07E2&lt;br /&gt;
| Calmos&lt;br /&gt;
|-&lt;br /&gt;
| 2019&lt;br /&gt;
| 07E3&lt;br /&gt;
| Dover Research&lt;br /&gt;
|-&lt;br /&gt;
| 2020&lt;br /&gt;
| 07E4&lt;br /&gt;
| David Krehbiel&lt;br /&gt;
|-&lt;br /&gt;
| 2021&lt;br /&gt;
| 07E5&lt;br /&gt;
| Synergy Peripheral Systems&lt;br /&gt;
| Also known as California Access&lt;br /&gt;
|-&lt;br /&gt;
| 2022&lt;br /&gt;
| 07E6&lt;br /&gt;
| Xetec&lt;br /&gt;
|-&lt;br /&gt;
| 2023&lt;br /&gt;
| 07E7&lt;br /&gt;
| Micron Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2024&lt;br /&gt;
| 07E8&lt;br /&gt;
| CH Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2025&lt;br /&gt;
| 07E9&lt;br /&gt;
| American Liquid Light&lt;br /&gt;
|-&lt;br /&gt;
| 2026&lt;br /&gt;
| 07EA&lt;br /&gt;
| Progressive Peripherals &amp;amp;amp; Software&lt;br /&gt;
| Also used by Ateo&lt;br /&gt;
|-&lt;br /&gt;
| 2027&lt;br /&gt;
| 07EB&lt;br /&gt;
| Wicat Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2028&lt;br /&gt;
| 07EC&lt;br /&gt;
| Applied Systems &amp;amp;amp; Peripherals&lt;br /&gt;
|-&lt;br /&gt;
| 2029&lt;br /&gt;
| 07ED&lt;br /&gt;
| Delaware Valley Software&lt;br /&gt;
|-&lt;br /&gt;
| 2030&lt;br /&gt;
| 07EE&lt;br /&gt;
| Palomax&lt;br /&gt;
|-&lt;br /&gt;
| 2031&lt;br /&gt;
| 07EF&lt;br /&gt;
| Incognito Software&lt;br /&gt;
|-&lt;br /&gt;
| 2032&lt;br /&gt;
| 07F0&lt;br /&gt;
| Jadesign&lt;br /&gt;
|-&lt;br /&gt;
| 2033&lt;br /&gt;
| 07F1&lt;br /&gt;
| BVR&lt;br /&gt;
|-&lt;br /&gt;
| 2034&lt;br /&gt;
| 07F2&lt;br /&gt;
| Spirit Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2035&lt;br /&gt;
| 07F3&lt;br /&gt;
| Spirit Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2036&lt;br /&gt;
| 07F4&lt;br /&gt;
| Atronic&lt;br /&gt;
|-&lt;br /&gt;
| 2037&lt;br /&gt;
| 07F5&lt;br /&gt;
| Scott Karlin&lt;br /&gt;
|-&lt;br /&gt;
| 2038&lt;br /&gt;
| 07F6&lt;br /&gt;
| Howitch&lt;br /&gt;
|-&lt;br /&gt;
| 2039&lt;br /&gt;
| 07F7&lt;br /&gt;
| Sullivan Brothers Visual Engineers&lt;br /&gt;
|-&lt;br /&gt;
| 2040&lt;br /&gt;
| 07F8&lt;br /&gt;
| G I T&lt;br /&gt;
|-&lt;br /&gt;
| 2041&lt;br /&gt;
| 07F9&lt;br /&gt;
| Amigo Business Computers&lt;br /&gt;
|-&lt;br /&gt;
| 2042&lt;br /&gt;
| 07FA&lt;br /&gt;
| Micro E Ab&lt;br /&gt;
|-&lt;br /&gt;
| 2043&lt;br /&gt;
| 07FB&lt;br /&gt;
| Ralph Kruse&lt;br /&gt;
|-&lt;br /&gt;
| 2044&lt;br /&gt;
| 07FC&lt;br /&gt;
| Clearpoint Research&lt;br /&gt;
|-&lt;br /&gt;
| 2045&lt;br /&gt;
| 07FD&lt;br /&gt;
| Kodiak&lt;br /&gt;
|-&lt;br /&gt;
| 2046&lt;br /&gt;
| 07FE&lt;br /&gt;
| BSC&lt;br /&gt;
| Originally registered to Phoenix Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2047&lt;br /&gt;
| 07FF&lt;br /&gt;
| No Name Shown&lt;br /&gt;
|-&lt;br /&gt;
| 2048&lt;br /&gt;
| 0800&lt;br /&gt;
| Commodore Braunschweig&lt;br /&gt;
|-&lt;br /&gt;
| 2049&lt;br /&gt;
| 0801&lt;br /&gt;
| BSC&lt;br /&gt;
| Originally registered to Elaborate Bytes&lt;br /&gt;
|-&lt;br /&gt;
| 2050&lt;br /&gt;
| 0802&lt;br /&gt;
| Kronos/C Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2051&lt;br /&gt;
| 0803&lt;br /&gt;
| Spartanics&lt;br /&gt;
|-&lt;br /&gt;
| 2052&lt;br /&gt;
| 0804&lt;br /&gt;
| Jochheim Computer Tuning&lt;br /&gt;
|-&lt;br /&gt;
| 2053&lt;br /&gt;
| 0805&lt;br /&gt;
| Trans Data Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2054&lt;br /&gt;
| 0806&lt;br /&gt;
| Applied Systems &amp;amp;amp; Peripherals Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2055&lt;br /&gt;
| 0807&lt;br /&gt;
| Checkpoint Technologies&lt;br /&gt;
| Originally registered to Amiga Solutions&lt;br /&gt;
|-&lt;br /&gt;
| 2056&lt;br /&gt;
| 0808&lt;br /&gt;
| Adept Development&lt;br /&gt;
|-&lt;br /&gt;
| 2057&lt;br /&gt;
| 0809&lt;br /&gt;
| Advanced Computer Design&lt;br /&gt;
|-&lt;br /&gt;
| 2058&lt;br /&gt;
| 080A&lt;br /&gt;
| Sir Netics&lt;br /&gt;
|-&lt;br /&gt;
| 2059&lt;br /&gt;
| 080B&lt;br /&gt;
| Expert Services&lt;br /&gt;
|-&lt;br /&gt;
| 2060&lt;br /&gt;
| 080C&lt;br /&gt;
| Digital Art Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2061&lt;br /&gt;
| 080D&lt;br /&gt;
| Adept Development&lt;br /&gt;
|-&lt;br /&gt;
| 2062&lt;br /&gt;
| 080E&lt;br /&gt;
| Expansion Technologies (Expansion Systems)&lt;br /&gt;
|-&lt;br /&gt;
| 2063&lt;br /&gt;
| 080F&lt;br /&gt;
| Alphatech&lt;br /&gt;
|-&lt;br /&gt;
| 2064&lt;br /&gt;
| 0810&lt;br /&gt;
| Edotronik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2065&lt;br /&gt;
| 0811&lt;br /&gt;
| California Access/Synergy&lt;br /&gt;
| Originally registered to Logical Design Works&lt;br /&gt;
|-&lt;br /&gt;
| 2066&lt;br /&gt;
| 0812&lt;br /&gt;
| Bowden, Williams, Full &amp;amp; Assoc.&lt;br /&gt;
|-&lt;br /&gt;
| 2067&lt;br /&gt;
| 0813&lt;br /&gt;
| NES, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2068&lt;br /&gt;
| 0814&lt;br /&gt;
| Amdev&lt;br /&gt;
|-&lt;br /&gt;
| 2069&lt;br /&gt;
| 0815&lt;br /&gt;
| Big Brother Security Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2070&lt;br /&gt;
| 0816&lt;br /&gt;
| Active Circuits Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2071&lt;br /&gt;
| 0817&lt;br /&gt;
| ICD, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2072&lt;br /&gt;
| 0818&lt;br /&gt;
| Multi-Meg Electronique&lt;br /&gt;
|-&lt;br /&gt;
| 2073&lt;br /&gt;
| 0819&lt;br /&gt;
| Kupke Computertechnik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2074&lt;br /&gt;
| 081A&lt;br /&gt;
| The Checkered Ball&lt;br /&gt;
|-&lt;br /&gt;
| 2075&lt;br /&gt;
| 081B&lt;br /&gt;
| Hi Tension Computer Services Ltd. (UK)&lt;br /&gt;
|-&lt;br /&gt;
| 2076&lt;br /&gt;
| 081C&lt;br /&gt;
| Alfa Data&lt;br /&gt;
| Originally assigned to Elmtech Research, Ltd. (UK)&lt;br /&gt;
|-&lt;br /&gt;
| 2077&lt;br /&gt;
| 081D&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
| Originally registered to Clartscreen, Ltd. (UK)&lt;br /&gt;
|-&lt;br /&gt;
| 2078&lt;br /&gt;
| 081E&lt;br /&gt;
| Interworks&lt;br /&gt;
|-&lt;br /&gt;
| 2079&lt;br /&gt;
| 081F&lt;br /&gt;
| Galysh Enterprises&lt;br /&gt;
|-&lt;br /&gt;
| 2080&lt;br /&gt;
| 0820&lt;br /&gt;
| Hardital Synthesis&lt;br /&gt;
| Originally registered to Realtime Games Software Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2081&lt;br /&gt;
| 0821&lt;br /&gt;
| GBS&lt;br /&gt;
|-&lt;br /&gt;
| 2082&lt;br /&gt;
| 0822&lt;br /&gt;
| Circum Design Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2083&lt;br /&gt;
| 0823&lt;br /&gt;
| Alberta Micro Electronic Center&lt;br /&gt;
|-&lt;br /&gt;
| 2084&lt;br /&gt;
| 0824&lt;br /&gt;
| Bestech&lt;br /&gt;
|-&lt;br /&gt;
| 2085&lt;br /&gt;
| 0825&lt;br /&gt;
| Lasar Fantasy&lt;br /&gt;
|-&lt;br /&gt;
| 2086&lt;br /&gt;
| 0826&lt;br /&gt;
| Pulsar&lt;br /&gt;
|-&lt;br /&gt;
| 2087&lt;br /&gt;
| 0827&lt;br /&gt;
| Ivis&lt;br /&gt;
|-&lt;br /&gt;
| 2088&lt;br /&gt;
| 0828&lt;br /&gt;
| Applied Engineering&lt;br /&gt;
|-&lt;br /&gt;
| 2089&lt;br /&gt;
| 0829&lt;br /&gt;
| Solid-State Design &amp;amp;amp; Development&lt;br /&gt;
|-&lt;br /&gt;
| 2090&lt;br /&gt;
| 082A&lt;br /&gt;
| Vison Quest&lt;br /&gt;
|-&lt;br /&gt;
| 2091&lt;br /&gt;
| 082B&lt;br /&gt;
| Seaview Software&lt;br /&gt;
|-&lt;br /&gt;
| 2092&lt;br /&gt;
| 082C&lt;br /&gt;
| BSC&lt;br /&gt;
| Mistakenly used by ADS (Advanced Development Software)&lt;br /&gt;
|-&lt;br /&gt;
| 2093&lt;br /&gt;
| 082D&lt;br /&gt;
| Bernd Culenfeld&lt;br /&gt;
|-&lt;br /&gt;
| 2094&lt;br /&gt;
| 082E&lt;br /&gt;
| American Liquid Light&lt;br /&gt;
|-&lt;br /&gt;
| 2095&lt;br /&gt;
| 082F&lt;br /&gt;
| CEGITES&lt;br /&gt;
|-&lt;br /&gt;
| 2096&lt;br /&gt;
| 0830&lt;br /&gt;
| Quadlite Computers Ltd.&lt;br /&gt;
| Originally registered to EV Industries&lt;br /&gt;
|-&lt;br /&gt;
| 2097&lt;br /&gt;
| 0831&lt;br /&gt;
| Silicon Peace&lt;br /&gt;
|-&lt;br /&gt;
| 2098&lt;br /&gt;
| 0832&lt;br /&gt;
| Black Belt Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2099&lt;br /&gt;
| 0833&lt;br /&gt;
| Village Tronic&lt;br /&gt;
| Originally registerd to Steve Yaeger&lt;br /&gt;
|-&lt;br /&gt;
| 2100&lt;br /&gt;
| 0834&lt;br /&gt;
| ReadySoft&lt;br /&gt;
|-&lt;br /&gt;
| 2101&lt;br /&gt;
| 0835&lt;br /&gt;
| Phoenix Micro Technologies&lt;br /&gt;
|-&lt;br /&gt;
| 2102&lt;br /&gt;
| 0836&lt;br /&gt;
| Advanced Systems &amp;amp; Software&lt;br /&gt;
| Orignally assigned to Preferred Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2103&lt;br /&gt;
| 0837&lt;br /&gt;
| Rombo Productions&lt;br /&gt;
|-&lt;br /&gt;
| 2104&lt;br /&gt;
| 0838&lt;br /&gt;
| Impulse Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2105&lt;br /&gt;
| 0839&lt;br /&gt;
| Beta Unlimited&lt;br /&gt;
|-&lt;br /&gt;
| 2106&lt;br /&gt;
| 083A&lt;br /&gt;
| Memory Expansion System, Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2107&lt;br /&gt;
| 083B&lt;br /&gt;
| Vortex Computer Systems GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2108&lt;br /&gt;
| 083C&lt;br /&gt;
| Platypus Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2109&lt;br /&gt;
| 083D&lt;br /&gt;
| Gigatron OHG&lt;br /&gt;
|-&lt;br /&gt;
| 2110&lt;br /&gt;
| 083E&lt;br /&gt;
| PG Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2111&lt;br /&gt;
| 083F&lt;br /&gt;
| New Technologies Group&lt;br /&gt;
|-&lt;br /&gt;
| 2112&lt;br /&gt;
| 0840&lt;br /&gt;
| Interactive Video Systems (IVS)&lt;br /&gt;
| Pacific Peripherals&lt;br /&gt;
|-&lt;br /&gt;
| 2113&lt;br /&gt;
| 0841&lt;br /&gt;
| Vector&lt;br /&gt;
| Originally registered to H. K. Computer&lt;br /&gt;
|-&lt;br /&gt;
| 2114&lt;br /&gt;
| 0842&lt;br /&gt;
| Pacific Digital&lt;br /&gt;
| Originally registered to C. H. Helfrich Elektronik&lt;br /&gt;
|-&lt;br /&gt;
| 2115&lt;br /&gt;
| 0843&lt;br /&gt;
| Xanadu&lt;br /&gt;
|-&lt;br /&gt;
| 2116&lt;br /&gt;
| 0844&lt;br /&gt;
| Pacific Digital&lt;br /&gt;
| Originally registered to AMS&lt;br /&gt;
|-&lt;br /&gt;
| 2117&lt;br /&gt;
| 0845&lt;br /&gt;
| X-Pert&lt;br /&gt;
|-&lt;br /&gt;
| 2118&lt;br /&gt;
| 0846&lt;br /&gt;
| The Amiga Centre&lt;br /&gt;
|-&lt;br /&gt;
| 2119&lt;br /&gt;
| 0847&lt;br /&gt;
| Digital Pacific&lt;br /&gt;
|-&lt;br /&gt;
| 2120&lt;br /&gt;
| 0848&lt;br /&gt;
| Solid State Leisure&lt;br /&gt;
|-&lt;br /&gt;
| 2121&lt;br /&gt;
| 0849&lt;br /&gt;
| Hydra Systems&lt;br /&gt;
| Originally registered to Analog Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2122&lt;br /&gt;
| 084A&lt;br /&gt;
| Cumana&lt;br /&gt;
|-&lt;br /&gt;
| 2123&lt;br /&gt;
| 084B&lt;br /&gt;
| KAPS 2C Conception&lt;br /&gt;
|-&lt;br /&gt;
| 2124&lt;br /&gt;
| 084C&lt;br /&gt;
| Mike Mason&lt;br /&gt;
|-&lt;br /&gt;
| 2125&lt;br /&gt;
| 084D&lt;br /&gt;
| For Your Eyes&lt;br /&gt;
|-&lt;br /&gt;
| 2126&lt;br /&gt;
| 084E&lt;br /&gt;
| Volkmar Breitfeld Computersysteme&lt;br /&gt;
|-&lt;br /&gt;
| 2127&lt;br /&gt;
| 084F&lt;br /&gt;
| Sunrize Industries&lt;br /&gt;
|-&lt;br /&gt;
| 2128&lt;br /&gt;
| 0850&lt;br /&gt;
| Scott Advanced Micro Designs&lt;br /&gt;
|-&lt;br /&gt;
| 2129&lt;br /&gt;
| 0851&lt;br /&gt;
| Digital Micronics&lt;br /&gt;
|-&lt;br /&gt;
| 2130&lt;br /&gt;
| 0852&lt;br /&gt;
| Alfa-Laval&lt;br /&gt;
|-&lt;br /&gt;
| 2131&lt;br /&gt;
| 0853&lt;br /&gt;
| Multigros A/S&lt;br /&gt;
|-&lt;br /&gt;
| 2132&lt;br /&gt;
| 0854&lt;br /&gt;
| Archos&lt;br /&gt;
|-&lt;br /&gt;
| 2133&lt;br /&gt;
| 0855&lt;br /&gt;
| Icom Simulations&lt;br /&gt;
|-&lt;br /&gt;
| 2134&lt;br /&gt;
| 0856&lt;br /&gt;
| Commodore Test Engineering Group&lt;br /&gt;
|-&lt;br /&gt;
| 2135&lt;br /&gt;
| 0857&lt;br /&gt;
| Microcreations&lt;br /&gt;
|-&lt;br /&gt;
| 2136&lt;br /&gt;
| 0858&lt;br /&gt;
| Shoestring Productions&lt;br /&gt;
|-&lt;br /&gt;
| 2137&lt;br /&gt;
| 0859&lt;br /&gt;
| Faberushi&lt;br /&gt;
|-&lt;br /&gt;
| 2138&lt;br /&gt;
| 085A&lt;br /&gt;
| Evesham Micro Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2139&lt;br /&gt;
| 085B&lt;br /&gt;
| Panagolin Laser Software&lt;br /&gt;
|-&lt;br /&gt;
| 2140&lt;br /&gt;
| 085C&lt;br /&gt;
| Thomas Rudloff&lt;br /&gt;
|-&lt;br /&gt;
| 2141&lt;br /&gt;
| 085D&lt;br /&gt;
| Daniel Hohabir&lt;br /&gt;
|-&lt;br /&gt;
| 2142&lt;br /&gt;
| 085E&lt;br /&gt;
| GfxBase, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2143&lt;br /&gt;
| 085F&lt;br /&gt;
| Axellabs&lt;br /&gt;
|-&lt;br /&gt;
| 2144&lt;br /&gt;
| 0860&lt;br /&gt;
| Roctec Electronics Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2145&lt;br /&gt;
| 0861&lt;br /&gt;
| Omega Datentechnik&lt;br /&gt;
|-&lt;br /&gt;
| 2146&lt;br /&gt;
| 0862&lt;br /&gt;
| Atlantis&lt;br /&gt;
|-&lt;br /&gt;
| 2147&lt;br /&gt;
| 0863&lt;br /&gt;
| Skytec Computers&lt;br /&gt;
|-&lt;br /&gt;
| 2148&lt;br /&gt;
| 0864&lt;br /&gt;
| Protar Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2149&lt;br /&gt;
| 0865&lt;br /&gt;
| ACS&lt;br /&gt;
|-&lt;br /&gt;
| 2150&lt;br /&gt;
| 0866&lt;br /&gt;
| Software Results Enterprises&lt;br /&gt;
| Originally registered to University of Illinois&lt;br /&gt;
|-&lt;br /&gt;
| 2151&lt;br /&gt;
| 0867&lt;br /&gt;
| Infinity Systems Design Group&lt;br /&gt;
|-&lt;br /&gt;
| 2152&lt;br /&gt;
| 0868&lt;br /&gt;
| Trade It&lt;br /&gt;
|-&lt;br /&gt;
| 2153&lt;br /&gt;
| 0869&lt;br /&gt;
| Suntec, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2154&lt;br /&gt;
| 086A&lt;br /&gt;
| DJW Micro Systems&lt;br /&gt;
| Originally registered to Tritec Marketing&lt;br /&gt;
|-&lt;br /&gt;
| 2155&lt;br /&gt;
| 086B&lt;br /&gt;
| Power Computing Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2156&lt;br /&gt;
| 086C&lt;br /&gt;
| MacroSystems&lt;br /&gt;
|-&lt;br /&gt;
| 2157&lt;br /&gt;
| 086D&lt;br /&gt;
| Masoboshi GmbH (DCE)&lt;br /&gt;
|-&lt;br /&gt;
| 2158&lt;br /&gt;
| 086E&lt;br /&gt;
| HAL Software Hardware Handel&lt;br /&gt;
|-&lt;br /&gt;
| 2159&lt;br /&gt;
| 086F&lt;br /&gt;
| Mainhattan Data&lt;br /&gt;
| Originally registered to Michael Lamm Computersysteme&lt;br /&gt;
|-&lt;br /&gt;
| 2160&lt;br /&gt;
| 0870&lt;br /&gt;
| Digital Processing System&lt;br /&gt;
| Originally registered to bbdp Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2161&lt;br /&gt;
| 0871&lt;br /&gt;
| Blue Ribbon Soundworks&lt;br /&gt;
| Originally registered to Design Computer Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2162&lt;br /&gt;
| 0872&lt;br /&gt;
| XPert&lt;br /&gt;
| Originally registered to The Station&lt;br /&gt;
|-&lt;br /&gt;
| 2163&lt;br /&gt;
| 0873&lt;br /&gt;
| DelaComp&lt;br /&gt;
| Originally registered to Bryan Williams&lt;br /&gt;
|-&lt;br /&gt;
| 2164&lt;br /&gt;
| 0874&lt;br /&gt;
| Superformance Computer Engineering GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2165&lt;br /&gt;
| 0875&lt;br /&gt;
| Overland Engineering&lt;br /&gt;
|-&lt;br /&gt;
| 2166&lt;br /&gt;
| 0876&lt;br /&gt;
| Thomas Hamren&lt;br /&gt;
|-&lt;br /&gt;
| 2167&lt;br /&gt;
| 0877&lt;br /&gt;
| Village Tronic&lt;br /&gt;
|-&lt;br /&gt;
| 2168&lt;br /&gt;
| 0878&lt;br /&gt;
| Toolbox Design&lt;br /&gt;
|-&lt;br /&gt;
| 2169&lt;br /&gt;
| 0879&lt;br /&gt;
| Digital Processing System&lt;br /&gt;
|-&lt;br /&gt;
| 2170&lt;br /&gt;
| 087A&lt;br /&gt;
| Superformance&lt;br /&gt;
|-&lt;br /&gt;
| 2171&lt;br /&gt;
| 087B&lt;br /&gt;
| Utilities Unlimited&lt;br /&gt;
|-&lt;br /&gt;
| 2172&lt;br /&gt;
| 087C&lt;br /&gt;
| phase 5&lt;br /&gt;
|-&lt;br /&gt;
| 2173&lt;br /&gt;
| 087D&lt;br /&gt;
| Juergen Kommos&lt;br /&gt;
|-&lt;br /&gt;
| 2174&lt;br /&gt;
| 087E&lt;br /&gt;
| Electronic Design&lt;br /&gt;
|-&lt;br /&gt;
| 2175&lt;br /&gt;
| 087F&lt;br /&gt;
| James Cook University of North Queensland&lt;br /&gt;
|-&lt;br /&gt;
| 2176&lt;br /&gt;
| 0880&lt;br /&gt;
| AmiTrix Development&lt;br /&gt;
|-&lt;br /&gt;
| 2177&lt;br /&gt;
| 0881&lt;br /&gt;
| Ferranti&lt;br /&gt;
|-&lt;br /&gt;
| 2178&lt;br /&gt;
| 0882&lt;br /&gt;
| Leviathan Development&lt;br /&gt;
|-&lt;br /&gt;
| 2179&lt;br /&gt;
| 0883&lt;br /&gt;
| United Video Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2180&lt;br /&gt;
| 0884&lt;br /&gt;
| GPSoft Pty. Ltd.&lt;br /&gt;
| Originally registered to Juergen Kommos&lt;br /&gt;
|-&lt;br /&gt;
| 2181&lt;br /&gt;
| 0885&lt;br /&gt;
| ArMAX&lt;br /&gt;
| Oliver Bausch&lt;br /&gt;
|-&lt;br /&gt;
| 2182&lt;br /&gt;
| 0886&lt;br /&gt;
| CP Computer&lt;br /&gt;
|-&lt;br /&gt;
| 2183&lt;br /&gt;
| 0887&lt;br /&gt;
| AMOK - Amiga Module &amp;amp;amp; Oberon Klub&lt;br /&gt;
|-&lt;br /&gt;
| 2184&lt;br /&gt;
| 0888&lt;br /&gt;
| ITEK Neser &amp;amp;amp; Sieber GbR&lt;br /&gt;
|-&lt;br /&gt;
| 2185&lt;br /&gt;
| 0889&lt;br /&gt;
| Phillip C. Lello&lt;br /&gt;
|-&lt;br /&gt;
| 2186&lt;br /&gt;
| 088A&lt;br /&gt;
| Cyborg Design Services&lt;br /&gt;
|-&lt;br /&gt;
| 2187&lt;br /&gt;
| 088B&lt;br /&gt;
| G2 Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2188&lt;br /&gt;
| 088C&lt;br /&gt;
| Pro System Computersysteme&lt;br /&gt;
|-&lt;br /&gt;
| 2189&lt;br /&gt;
| 088D&lt;br /&gt;
| ZEUS Electronic&lt;br /&gt;
| Originally registered to MSPI (Markt &amp;amp;amp; Technik)&lt;br /&gt;
|-&lt;br /&gt;
| 2190&lt;br /&gt;
| 088E&lt;br /&gt;
| Altatech&lt;br /&gt;
|-&lt;br /&gt;
| 2191&lt;br /&gt;
| 088F&lt;br /&gt;
| NewTek&lt;br /&gt;
|-&lt;br /&gt;
| 2192&lt;br /&gt;
| 0890&lt;br /&gt;
| M-TEC Hardware Design&lt;br /&gt;
| Originally registered to Hardware Design Udo Neuroth&lt;br /&gt;
|-&lt;br /&gt;
| 2193&lt;br /&gt;
| 0891&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
| Originally registered to Viona Development&lt;br /&gt;
|-&lt;br /&gt;
| 2194&lt;br /&gt;
| 0892&lt;br /&gt;
| Amitek&lt;br /&gt;
| Originally assigned to Marpet Developments&lt;br /&gt;
|-&lt;br /&gt;
| 2195&lt;br /&gt;
| 0893&lt;br /&gt;
| Ingenieurbuero Helfrich&lt;br /&gt;
|-&lt;br /&gt;
| 2196&lt;br /&gt;
| 0894&lt;br /&gt;
| The Neo Group&lt;br /&gt;
|-&lt;br /&gt;
| 2197&lt;br /&gt;
| 0895&lt;br /&gt;
| Cyon&lt;br /&gt;
|-&lt;br /&gt;
| 2198&lt;br /&gt;
| 0896&lt;br /&gt;
| Bob Research Group&lt;br /&gt;
|-&lt;br /&gt;
| 2199&lt;br /&gt;
| 0897&lt;br /&gt;
| Richmond Sound Design Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2200&lt;br /&gt;
| 0898&lt;br /&gt;
| US Cybernetics&lt;br /&gt;
|-&lt;br /&gt;
| 2201&lt;br /&gt;
| 0899&lt;br /&gt;
| Fulvio Ieva&lt;br /&gt;
|-&lt;br /&gt;
| 2202&lt;br /&gt;
| 089A&lt;br /&gt;
| Silicon Studio&lt;br /&gt;
|-&lt;br /&gt;
| 2203&lt;br /&gt;
| 089B&lt;br /&gt;
| MacroSystems (USA)&lt;br /&gt;
| Was named Micro System Devices&lt;br /&gt;
|-&lt;br /&gt;
| 2204&lt;br /&gt;
| 089C&lt;br /&gt;
| Conspector Entertainment&lt;br /&gt;
|-&lt;br /&gt;
| 2205&lt;br /&gt;
| 089D&lt;br /&gt;
| Laserforum&lt;br /&gt;
|-&lt;br /&gt;
| 2206&lt;br /&gt;
| 089E&lt;br /&gt;
| Elbox Computer&lt;br /&gt;
| Mistakenly used by Index Information Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2207&lt;br /&gt;
| 089F&lt;br /&gt;
| Applied Magic Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2208&lt;br /&gt;
| 08A0&lt;br /&gt;
| SDL Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2560&lt;br /&gt;
| 0A00&lt;br /&gt;
| Harms&lt;br /&gt;
|-&lt;br /&gt;
| 2588&lt;br /&gt;
| 0A1C&lt;br /&gt;
| A1K.org Community&lt;br /&gt;
|-&lt;br /&gt;
| 2640&lt;br /&gt;
| 0A50&lt;br /&gt;
| Micronik&lt;br /&gt;
|-&lt;br /&gt;
| 3084&lt;br /&gt;
| 0C0C&lt;br /&gt;
| Team 4&lt;br /&gt;
|-&lt;br /&gt;
| 3643&lt;br /&gt;
| 0E3B&lt;br /&gt;
| E3B&lt;br /&gt;
| Michael Boehmer&lt;br /&gt;
|-&lt;br /&gt;
| 3855&lt;br /&gt;
| 0F0F&lt;br /&gt;
| Micronik&lt;br /&gt;
|-&lt;br /&gt;
| 4096&lt;br /&gt;
| 1000&lt;br /&gt;
| MegaMicro&lt;br /&gt;
|-&lt;br /&gt;
| 4110&lt;br /&gt;
| 100E&lt;br /&gt;
| DigiFeX&lt;br /&gt;
|-&lt;br /&gt;
| 4136&lt;br /&gt;
| 1028&lt;br /&gt;
| Imtronics/Memphis&lt;br /&gt;
|-&lt;br /&gt;
| 4149&lt;br /&gt;
| 1035&lt;br /&gt;
| PROTAR&lt;br /&gt;
|-&lt;br /&gt;
| 4369&lt;br /&gt;
| 1111&lt;br /&gt;
| Frank Strauß Elektronik&lt;br /&gt;
| Also used by Kupke&lt;br /&gt;
|-&lt;br /&gt;
| 4626&lt;br /&gt;
| 1212&lt;br /&gt;
| Individual Computers&lt;br /&gt;
|-&lt;br /&gt;
| 4648&lt;br /&gt;
| 1228&lt;br /&gt;
| Flesch Hornemann Computer Elec.&lt;br /&gt;
|-&lt;br /&gt;
| 4680&lt;br /&gt;
| 1248&lt;br /&gt;
| Kupke Computertechnik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 4711&lt;br /&gt;
| 1267&lt;br /&gt;
| RBM digitaltechnik&lt;br /&gt;
|-&lt;br /&gt;
| 4754&lt;br /&gt;
| 1292&lt;br /&gt;
| MacroSystems&lt;br /&gt;
|-&lt;br /&gt;
| 5000&lt;br /&gt;
| 1388&lt;br /&gt;
| ITH&lt;br /&gt;
|-&lt;br /&gt;
| 5001&lt;br /&gt;
| 1389&lt;br /&gt;
| VMC&lt;br /&gt;
|-&lt;br /&gt;
| 5010&lt;br /&gt;
| 1392&lt;br /&gt;
| Ambience Creation Technology&lt;br /&gt;
|-&lt;br /&gt;
| 5011&lt;br /&gt;
| 1393&lt;br /&gt;
| Creative Development&lt;br /&gt;
|-&lt;br /&gt;
| 5012&lt;br /&gt;
| 1394&lt;br /&gt;
| Georg Braun&lt;br /&gt;
|-&lt;br /&gt;
| 5013&lt;br /&gt;
| 1395&lt;br /&gt;
| Swedish User Group of Amiga&lt;br /&gt;
|-&lt;br /&gt;
| 5014&lt;br /&gt;
| 1396&lt;br /&gt;
| Jakub Bednarski&lt;br /&gt;
|-&lt;br /&gt;
| 5015&lt;br /&gt;
| 1397&lt;br /&gt;
| KryoFlux, Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 5016&lt;br /&gt;
| 1398&lt;br /&gt;
| Igor Majstorovic&lt;br /&gt;
|-&lt;br /&gt;
| 5017&lt;br /&gt;
| 1399&lt;br /&gt;
| Alastair M. Robinson&lt;br /&gt;
|-&lt;br /&gt;
| 5018&lt;br /&gt;
| 139A&lt;br /&gt;
| Austex Software&lt;br /&gt;
|-&lt;br /&gt;
| 5019&lt;br /&gt;
| 139B&lt;br /&gt;
| Sören Gust&lt;br /&gt;
|-&lt;br /&gt;
| 5020&lt;br /&gt;
| 139C&lt;br /&gt;
| Rok Krajnc&lt;br /&gt;
|-&lt;br /&gt;
| 5030&lt;br /&gt;
| 13A6&lt;br /&gt;
| Tim Tashpulatov&lt;br /&gt;
|-&lt;br /&gt;
| 5040&lt;br /&gt;
| 13B0&lt;br /&gt;
| 7-bit&lt;br /&gt;
|-&lt;br /&gt;
| 5050&lt;br /&gt;
| 13BA&lt;br /&gt;
| Sakura IT&lt;br /&gt;
|-&lt;br /&gt;
| 5060&lt;br /&gt;
| 13C4&lt;br /&gt;
| FPGAArcade&lt;br /&gt;
|-&lt;br /&gt;
| 5070&lt;br /&gt;
| 13CE&lt;br /&gt;
| CancerSoft Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 5080&lt;br /&gt;
| 13D8&lt;br /&gt;
| Stephen Leary&lt;br /&gt;
|-&lt;br /&gt;
| 5090&lt;br /&gt;
| 13E2&lt;br /&gt;
| DMA Softlab LLC&lt;br /&gt;
|-&lt;br /&gt;
| 5100&lt;br /&gt;
| 13EC&lt;br /&gt;
| Brookhouse Engineering&lt;br /&gt;
|-&lt;br /&gt;
| 5110&lt;br /&gt;
| 13F6&lt;br /&gt;
| Eduardo Arana&lt;br /&gt;
|-&lt;br /&gt;
| 5120&lt;br /&gt;
| 1400&lt;br /&gt;
| CS-LAB&lt;br /&gt;
|-&lt;br /&gt;
| 5130&lt;br /&gt;
| 140A&lt;br /&gt;
| Robert Miranda&lt;br /&gt;
|-&lt;br /&gt;
| 5140&lt;br /&gt;
| 1414&lt;br /&gt;
| RastPort&lt;br /&gt;
|-&lt;br /&gt;
| 5132&lt;br /&gt;
| 140C&lt;br /&gt;
| UAS Interface Ltd6&lt;br /&gt;
|-&lt;br /&gt;
| 5150&lt;br /&gt;
| 141E&lt;br /&gt;
| Amiga Kit&lt;br /&gt;
|-&lt;br /&gt;
| 5160&lt;br /&gt;
| 1428&lt;br /&gt;
| Central Texas Commodore User Group&lt;br /&gt;
|-&lt;br /&gt;
| 5170&lt;br /&gt;
| 1432&lt;br /&gt;
| Confusion Research Center&lt;br /&gt;
|-&lt;br /&gt;
| 5180&lt;br /&gt;
| 143C&lt;br /&gt;
| Solar Soyuz Zaibatsu&lt;br /&gt;
|-&lt;br /&gt;
| 5190&lt;br /&gt;
| 1446&lt;br /&gt;
| BooBip&lt;br /&gt;
|-&lt;br /&gt;
| 5191&lt;br /&gt;
| 1447&lt;br /&gt;
| Matthias Hampel&lt;br /&gt;
|-&lt;br /&gt;
| 5192&lt;br /&gt;
| 1448&lt;br /&gt;
| dec0de Consulting Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 5193&lt;br /&gt;
| 1449&lt;br /&gt;
| Puppy Concepts&lt;br /&gt;
|-&lt;br /&gt;
| 5194&lt;br /&gt;
| 144A&lt;br /&gt;
| Open Amiga Hardware Repository&lt;br /&gt;
|-&lt;br /&gt;
| 5195&lt;br /&gt;
| 144B&lt;br /&gt;
| Double H Tech&lt;br /&gt;
|-&lt;br /&gt;
| 5196&lt;br /&gt;
| 144C&lt;br /&gt;
| Retromatik&lt;br /&gt;
|-&lt;br /&gt;
| 5500&lt;br /&gt;
| 157C&lt;br /&gt;
| Inhouse Information&lt;br /&gt;
|-&lt;br /&gt;
| 5768&lt;br /&gt;
| 1688&lt;br /&gt;
| Bio Con&lt;br /&gt;
|-&lt;br /&gt;
| 6148&lt;br /&gt;
| 1804&lt;br /&gt;
| HK-Computer&lt;br /&gt;
|-&lt;br /&gt;
| 6502&lt;br /&gt;
| 1966&lt;br /&gt;
| Cloanto&lt;br /&gt;
|-&lt;br /&gt;
| 6520&lt;br /&gt;
| 1978&lt;br /&gt;
| Oliver Gantert&lt;br /&gt;
|-&lt;br /&gt;
| 7777&lt;br /&gt;
| 1E61&lt;br /&gt;
| Rafal Gabriel Chyla&lt;br /&gt;
|-&lt;br /&gt;
| 8215&lt;br /&gt;
| 2017&lt;br /&gt;
| Vortex&lt;br /&gt;
|-&lt;br /&gt;
| 8244&lt;br /&gt;
| 2034&lt;br /&gt;
| Spirit Technology&lt;br /&gt;
|-&lt;br /&gt;
| 8290&lt;br /&gt;
| 2062&lt;br /&gt;
| Expansion Systems&lt;br /&gt;
|-&lt;br /&gt;
| 8448&lt;br /&gt;
| 2100&lt;br /&gt;
| ReadySoft&lt;br /&gt;
|-&lt;br /&gt;
| 8512&lt;br /&gt;
| 2140&lt;br /&gt;
| Phase 5 Digital Products&lt;br /&gt;
|-&lt;br /&gt;
| 8553&lt;br /&gt;
| 2169&lt;br /&gt;
| Digital Processing Systems Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 8704&lt;br /&gt;
| 2200&lt;br /&gt;
| ACT Elektronik&lt;br /&gt;
|-&lt;br /&gt;
| 8738&lt;br /&gt;
| 2222&lt;br /&gt;
| ACT Elektronik&lt;br /&gt;
|-&lt;br /&gt;
| 9512&lt;br /&gt;
| 2528&lt;br /&gt;
| Tower Technologies&lt;br /&gt;
|-&lt;br /&gt;
| 10676&lt;br /&gt;
| 29B4&lt;br /&gt;
| Electronic Design&lt;br /&gt;
|-&lt;br /&gt;
| 14195&lt;br /&gt;
| 3773&lt;br /&gt;
| Media-net-Point&lt;br /&gt;
|-&lt;br /&gt;
| 14501&lt;br /&gt;
| 38A5&lt;br /&gt;
| Petsoff, Finland&lt;br /&gt;
|-&lt;br /&gt;
| 16375&lt;br /&gt;
| 3FF7&lt;br /&gt;
| Uwe Gerlach&lt;br /&gt;
|-&lt;br /&gt;
| 16707&lt;br /&gt;
| 4143&lt;br /&gt;
| Ateo Concepts&lt;br /&gt;
|-&lt;br /&gt;
| 16708&lt;br /&gt;
| 4144&lt;br /&gt;
| ALiENDESiGN&lt;br /&gt;
|-&lt;br /&gt;
| 16945&lt;br /&gt;
| 4231&lt;br /&gt;
| A.C.T.&lt;br /&gt;
|-&lt;br /&gt;
| 17740&lt;br /&gt;
| 454C&lt;br /&gt;
| HK-Computer (ELSAT)&lt;br /&gt;
|-&lt;br /&gt;
| 18260&lt;br /&gt;
| 4754&lt;br /&gt;
| MacroSystems (Germany)&lt;br /&gt;
|-&lt;br /&gt;
| 19796&lt;br /&gt;
| 4D54&lt;br /&gt;
| Markt &amp;amp; Technik&lt;br /&gt;
|-&lt;br /&gt;
| 22359&lt;br /&gt;
| 5757&lt;br /&gt;
| Markt &amp;amp; Technik&lt;br /&gt;
|-&lt;br /&gt;
| 26464&lt;br /&gt;
| 6760&lt;br /&gt;
| Combitec&lt;br /&gt;
|-&lt;br /&gt;
| 26470&lt;br /&gt;
| 6766&lt;br /&gt;
| Combitec&lt;br /&gt;
|-&lt;br /&gt;
| 28014&lt;br /&gt;
| 6D6E&lt;br /&gt;
| MNT Media and Technology UG&lt;br /&gt;
|-&lt;br /&gt;
| 32768&lt;br /&gt;
| 8000&lt;br /&gt;
| M.A.S.T.&lt;br /&gt;
|-&lt;br /&gt;
| 42240&lt;br /&gt;
| A500&lt;br /&gt;
| Aethreum Digital&lt;br /&gt;
|-&lt;br /&gt;
| 43437&lt;br /&gt;
| A9AD&lt;br /&gt;
| Reis-Ware&lt;br /&gt;
|-&lt;br /&gt;
| 43521&lt;br /&gt;
| AA01&lt;br /&gt;
| Cameron&lt;br /&gt;
|-&lt;br /&gt;
| 43537&lt;br /&gt;
| AA11&lt;br /&gt;
| Reis-Ware&lt;br /&gt;
|-&lt;br /&gt;
| 44359&lt;br /&gt;
| AD47&lt;br /&gt;
| Matay&lt;br /&gt;
|-&lt;br /&gt;
| 46504&lt;br /&gt;
| B5A8&lt;br /&gt;
| Phoenix&lt;br /&gt;
|-&lt;br /&gt;
| 48879&lt;br /&gt;
| BEEF&lt;br /&gt;
| Swiss Mountain Dog Products&lt;br /&gt;
|-&lt;br /&gt;
| 49160&lt;br /&gt;
| C008&lt;br /&gt;
| Combitec&lt;br /&gt;
|-&lt;br /&gt;
| 61453&lt;br /&gt;
| F00D&lt;br /&gt;
| Forefront Technologies Inc.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
For any changes/additions to this registry please send a support request to [mailto:support@hyperion-entertainment.com support@hyperion-entertainment.com].&lt;/div&gt;</summary>
		<author><name>Costel Mincea</name></author>
	</entry>
	<entry>
		<id>https://wiki.amigaos.net/w/index.php?title=Amiga_Hardware_Manufacturer_ID_Registry&amp;diff=12596</id>
		<title>Amiga Hardware Manufacturer ID Registry</title>
		<link rel="alternate" type="text/html" href="https://wiki.amigaos.net/w/index.php?title=Amiga_Hardware_Manufacturer_ID_Registry&amp;diff=12596"/>
		<updated>2026-09-08T10:18:26Z</updated>

		<summary type="html">&lt;p&gt;Costel Mincea: Added IDs 5190-5196&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
= How to Obtain a Manufacturer Number =&lt;br /&gt;
&lt;br /&gt;
Manufacturer&#039;s numbers are assigned by the AmigaOS development team. To obtain your unique manufacturer number send a support request to [mailto:support@hyperion-entertainment.com support@hyperion-entertainment.com].&lt;br /&gt;
&lt;br /&gt;
Be sure and include your name and the type of expansion product you are developing.&lt;br /&gt;
&lt;br /&gt;
= Your Manufacturer Number =&lt;br /&gt;
&lt;br /&gt;
Attention hardware manufacturers. If you are developing a hardware expansion product for the Classic Amiga (e.g. 500, 2000, 3000) then you will need to obtain a special manufacturer ID number from the AmigaOS development team to identify your product. This manufacturer number is used by the Amiga to link your hardware with its driver software at boot time.&lt;br /&gt;
&lt;br /&gt;
Your manufacturer number is part of the special protocol that the Amiga uses to automatically configure all expansion devices on the bus without the user having to cut jumpers or adjust dip switches. This is called auto-config.&lt;br /&gt;
&lt;br /&gt;
At start-up time, the system first polls each board in the system and assigns the board its own address space. If it is a memory board, its RAM is linked into the memory free pool. Later in the boot sequence, after DOS is initialized, the binddrivers program is run. Binddrivers will search the directory SYS:Expansion for the drivers that go with the boards.&lt;br /&gt;
&lt;br /&gt;
To do this binddrivers looks in the Tool Type field of all icon files in SYS:Expansion. If the first seven bytes of the Tool Type field are &amp;quot;PRODUCT&amp;quot;, then this is an icon file for a driver.&lt;br /&gt;
&lt;br /&gt;
Binddrivers will then attempt to match the drivers it has found with the boards that were found earlier. This is where your manufacturer number comes in.&lt;br /&gt;
&lt;br /&gt;
Your manufacturer number goes in two places. First, it is burned in hex form into the PAL which is part of ALL auto-config expansion products. Second, it appears in ASCII in the Tool Type field of the icon file for your product&#039;s driver. By matching these two numbers, the Amiga can automatically configure your board and bind it&#039;s software driver into the system as well.&lt;br /&gt;
&lt;br /&gt;
The manufacturer&#039;s number is a 16-bit ID which appears in PAL offsets $10-$17. There is also an 8-bit product number which you assign. The product number is for uniquely identifying different products from the same vendor. The product number will appear in PAL offsets $04-$07. This gives you a total of 24 bits to identify each of your products.&lt;br /&gt;
&lt;br /&gt;
These 24 bits of information in the PAL which identify your product are matched against the information in the Tool Type field of all icon files in the SYS:Expansion drawer. For example, suppose you are manufacturer #1019. You have two products, #1 and #2 which both use the same driver. The icon for your driver for these two products would have a Tool Type set to &amp;quot;PRODUCT=1019/1|1019/2&amp;quot;. This means: I am an icon for a driver that works with product number 1 or 2 from manufacturer 1019, now bind me. Spaces are not legal. Here are two other examples:&lt;br /&gt;
&lt;br /&gt;
; PRODUCT=1208/11&lt;br /&gt;
: is the Tool Type for a driver for product 11 from manufacturer number 1208.&lt;br /&gt;
&lt;br /&gt;
; PRODUCT=1017&lt;br /&gt;
: is the Tool Type for a driver for any product from manufacturer number 1017.&lt;br /&gt;
&lt;br /&gt;
For an informal explanation of the auto-configuration process, see the chapter on Software Expansion Architecture from the 2nd Annual Amiga Developer&#039;s Conference Notes (available on ADCD 2.1). For the details of timing, power, the PAL equations and PAL address specifications and the expansion library documentation, see sections 3.1 to 3.3 of the A500/A2000 Technical Reference Manual. The original auto-config spec appears in the A1000 Schematics and Expansion Specification.&lt;br /&gt;
&lt;br /&gt;
The auto-config process makes the addition of expansion products to the system very easy. All the user has to do is put the board in any slot and copy the driver from the release disk to his own SYS:Expansion drawer. Everything else is automatic. There are no jumpers or dip switches to set. Best of all, you will get a lot less support calls asking how to make your product work with the XYZ-Corp-battery-backed-clock.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
&lt;br /&gt;
Some notes on hardware manufacturer ID assignment.&lt;br /&gt;
&lt;br /&gt;
* Manufacturer ID numbers are assigned free of charge.&lt;br /&gt;
* Please provide the following information when requesting an ID:&lt;br /&gt;
*# Name of the company or person&lt;br /&gt;
*# Postal address/contact address&lt;br /&gt;
*# Name of the contact person, with a corresponding e-mail address&lt;br /&gt;
*# A brief description of the kind of products you want to produce&lt;br /&gt;
* All ID numbers smaller than 5000 must be considered unsafe because no information exists on which numbers exactly were taken during the time Commodore, Inc. disintegrated.&lt;br /&gt;
* ID numbers in the range 8192 to 18841 must be considered unsafe because some hardware developers mistook the numbers assigned to them to be given in hexadecimal format. Hence 0x2000 = 8192 and 0x4999 = 18841.&lt;br /&gt;
&lt;br /&gt;
= Example code =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
/*-----------------------------------------------*/&lt;br /&gt;
/* Here is a short program which will tell you   */&lt;br /&gt;
/* about the expansion boards configured in your */&lt;br /&gt;
/* system without you opening up the machine.    */&lt;br /&gt;
/* Code by Bill Koester of CATS                  */&lt;br /&gt;
/*-----------------------------------------------*/&lt;br /&gt;
#include &amp;lt;libraries/configvars.h&amp;gt;&lt;br /&gt;
#include &amp;lt;libraries/expansion.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
struct ExpansionBase *ExpansionBase;&lt;br /&gt;
&lt;br /&gt;
void cleanup();&lt;br /&gt;
void printdev();&lt;br /&gt;
&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
   struct ConfigDev *MyConfigDev;&lt;br /&gt;
&lt;br /&gt;
   /*----------------------------------*/&lt;br /&gt;
   /* Open the expansion library,      */&lt;br /&gt;
   /* if there is a problem then exit  */&lt;br /&gt;
   /*----------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   ExpansionBase =(struct ExpansionBase *) OpenLibrary(EXPANSIONNAME,0);&lt;br /&gt;
   if(ExpansionBase==NULL)&lt;br /&gt;
   {&lt;br /&gt;
      printf(&amp;quot;Error opening expansion library!!\n&amp;quot;);&lt;br /&gt;
      cleanup();&lt;br /&gt;
      exit(0);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   /*--------------------------------------------*/&lt;br /&gt;
   /* Use FindConfigDev to get info on the first */&lt;br /&gt;
   /* expansion board on the list maintained by  */&lt;br /&gt;
   /* Exec.  If there are no expansion boards in */&lt;br /&gt;
   /* the system then exit.                      */&lt;br /&gt;
   /*--------------------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   MyConfigDev = NULL;&lt;br /&gt;
&lt;br /&gt;
  /*--------------------------------------------------*/&lt;br /&gt;
  /* FindConfigDev(oldConfigDev,manufacturer,product) */&lt;br /&gt;
  /* oldConfigDev = NULL for the top of the list      */&lt;br /&gt;
  /* manufacturer = -1 for any manufacturer           */&lt;br /&gt;
  /* product      = -1 for any product                */&lt;br /&gt;
  /*--------------------------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   MyConfigDev = FindConfigDev(NULL,-1,-1);&lt;br /&gt;
&lt;br /&gt;
   if(MyConfigDev==NULL)&lt;br /&gt;
   {&lt;br /&gt;
      printf(&amp;quot;No Configured Devices found!!\n&amp;quot;);&lt;br /&gt;
      cleanup();&lt;br /&gt;
      exit(0);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   printdev(MyConfigDev);&lt;br /&gt;
&lt;br /&gt;
   /*-----------------------------------*/&lt;br /&gt;
   /* OK, there is at least one board,  */&lt;br /&gt;
   /* so loop and get the entire list   */&lt;br /&gt;
   /* printing as we go with printdev() */&lt;br /&gt;
   /*-----------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   while(MyConfigDev = FindConfigDev(MyConfigDev,-1,-1))&lt;br /&gt;
   {&lt;br /&gt;
      printdev(MyConfigDev);&lt;br /&gt;
   }&lt;br /&gt;
   cleanup();&lt;br /&gt;
   return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*-------------------*/&lt;br /&gt;
/* Close up shop...  */&lt;br /&gt;
/*-------------------*/&lt;br /&gt;
void cleanup()&lt;br /&gt;
{&lt;br /&gt;
   if(ExpansionBase)&lt;br /&gt;
      CloseLibrary(ExpansionBase);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*----------------------------------*/&lt;br /&gt;
/* Print out the contents of the    */&lt;br /&gt;
/* dev structure for this expansion */&lt;br /&gt;
/* product.                         */&lt;br /&gt;
/*----------------------------------*/&lt;br /&gt;
&lt;br /&gt;
void printdev(dev)&lt;br /&gt;
struct ConfigDev *dev;&lt;br /&gt;
{&lt;br /&gt;
   char buff[200];&lt;br /&gt;
&lt;br /&gt;
   printf(&amp;quot;Flags          = &amp;quot;);&lt;br /&gt;
   if(dev-&amp;gt;cd_Flags==NULL)&lt;br /&gt;
      printf(&amp;quot;NULL  &amp;quot;);&lt;br /&gt;
   if(dev-&amp;gt;cd_Flags&amp;amp;CDF_SHUTUP)&lt;br /&gt;
      printf(&amp;quot;CDF_SHUTUP  &amp;quot;);&lt;br /&gt;
   if(dev-&amp;gt;cd_Flags&amp;amp;CDF_CONFIGME)&lt;br /&gt;
      printf(&amp;quot;CDF_CONFIGME  &amp;quot;);&lt;br /&gt;
   printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
   printf(&amp;quot;Board Address  = %x\n&amp;quot;,dev-&amp;gt;cd_BoardAddr);&lt;br /&gt;
   printf(&amp;quot;Board Size     = %d bytes\n&amp;quot;,dev-&amp;gt;cd_BoardSize);&lt;br /&gt;
   printf(&amp;quot;Slot  Address  = %d\n&amp;quot;,dev-&amp;gt;cd_SlotAddr);&lt;br /&gt;
   printf(&amp;quot;Slot  Size     = %d\n&amp;quot;,dev-&amp;gt;cd_SlotSize);&lt;br /&gt;
   printf(&amp;quot;Driver code at   %x\n&amp;quot;,dev-&amp;gt;cd_Driver);&lt;br /&gt;
&lt;br /&gt;
   printf(&amp;quot;er_Type         = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Type);&lt;br /&gt;
   printf(&amp;quot;er_Product      = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Product);&lt;br /&gt;
   printf(&amp;quot;er_Flags        = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Flags);&lt;br /&gt;
   printf(&amp;quot;er_Reserved03   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved03);&lt;br /&gt;
   printf(&amp;quot;er_Manufacturer = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Manufacturer);&lt;br /&gt;
   printf(&amp;quot;er_SerialNumber = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_SerialNumber);&lt;br /&gt;
   printf(&amp;quot;er_InitDiagVec  = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_InitDiagVec);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0c   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0c);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0d   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0d);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0e   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0e);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0f   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0f);&lt;br /&gt;
&lt;br /&gt;
   printf(&amp;quot;Hit Return to continue:\n&amp;quot;);&lt;br /&gt;
   gets(buff);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Registry =&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! ID (decimal)&lt;br /&gt;
! ID (hexadecimal)&lt;br /&gt;
! Manufacturer&lt;br /&gt;
! Notes&lt;br /&gt;
|-&lt;br /&gt;
| 1&lt;br /&gt;
| 0001&lt;br /&gt;
| Micronik&lt;br /&gt;
|-&lt;br /&gt;
| 211&lt;br /&gt;
| 00D3&lt;br /&gt;
| Pacific Peripherals/Profex&lt;br /&gt;
|-&lt;br /&gt;
| 221&lt;br /&gt;
| 00DD&lt;br /&gt;
| Kupke Computertechnik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 256&lt;br /&gt;
| 0100&lt;br /&gt;
| Memphis&lt;br /&gt;
| Originally registered to MacroSystems US&lt;br /&gt;
|-&lt;br /&gt;
| 512&lt;br /&gt;
| 0200&lt;br /&gt;
| 3-State Computertechnik&lt;br /&gt;
|-&lt;br /&gt;
| 513&lt;br /&gt;
| 0201&lt;br /&gt;
| Commodore (Braunschweig)&lt;br /&gt;
|-&lt;br /&gt;
| 514&lt;br /&gt;
| 0202&lt;br /&gt;
| Commodore (West Chester)&lt;br /&gt;
|-&lt;br /&gt;
| 515&lt;br /&gt;
| 0203&lt;br /&gt;
| Commodore (West Chester)&lt;br /&gt;
| Originally registered to Combitech/Macrosystem&lt;br /&gt;
|-&lt;br /&gt;
| 756&lt;br /&gt;
| 02F4&lt;br /&gt;
| Progressive Peripherals &amp;amp; Software&lt;br /&gt;
|-&lt;br /&gt;
| 767&lt;br /&gt;
| 02FF&lt;br /&gt;
| Kolff Computer Supplies&lt;br /&gt;
|-&lt;br /&gt;
| 1001&lt;br /&gt;
| 03E9&lt;br /&gt;
| Tecmar&lt;br /&gt;
|-&lt;br /&gt;
| 1002&lt;br /&gt;
| 03EA&lt;br /&gt;
| Telesys&lt;br /&gt;
|-&lt;br /&gt;
| 1003&lt;br /&gt;
| 03EB&lt;br /&gt;
| The Micro-Forge&lt;br /&gt;
|-&lt;br /&gt;
| 1004&lt;br /&gt;
| 03EC&lt;br /&gt;
| Kronos/C Ltd.&lt;br /&gt;
| Originally registered to Card Co. (Supra)&lt;br /&gt;
|-&lt;br /&gt;
| 1005&lt;br /&gt;
| 03ED&lt;br /&gt;
| A-Squared&lt;br /&gt;
|-&lt;br /&gt;
| 1006&lt;br /&gt;
| 03EE&lt;br /&gt;
| Comspec Communications&lt;br /&gt;
|-&lt;br /&gt;
| 1007&lt;br /&gt;
| 03EF&lt;br /&gt;
| HT Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 1008&lt;br /&gt;
| 03F0&lt;br /&gt;
| RDS Software&lt;br /&gt;
|-&lt;br /&gt;
| 1009&lt;br /&gt;
| 03F1&lt;br /&gt;
| Anakin Research&lt;br /&gt;
|-&lt;br /&gt;
| 1010&lt;br /&gt;
| 03F2&lt;br /&gt;
| MicroBotics&lt;br /&gt;
|-&lt;br /&gt;
| 1011&lt;br /&gt;
| 03F3&lt;br /&gt;
| Bob Krauth&lt;br /&gt;
|-&lt;br /&gt;
| 1012&lt;br /&gt;
| 03F4&lt;br /&gt;
| Access Associates (Alegra)&lt;br /&gt;
|-&lt;br /&gt;
| 1013&lt;br /&gt;
| 03F5&lt;br /&gt;
| Mini Comp Systems Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 1014&lt;br /&gt;
| 03F6&lt;br /&gt;
| Cypress Technology&lt;br /&gt;
|-&lt;br /&gt;
| 1015&lt;br /&gt;
| 03F7&lt;br /&gt;
| Fuller Computers&lt;br /&gt;
|-&lt;br /&gt;
| 1016&lt;br /&gt;
| 03F8&lt;br /&gt;
| Galaxy Computers&lt;br /&gt;
|-&lt;br /&gt;
| 1017&lt;br /&gt;
| 03F9&lt;br /&gt;
| ADA Research&lt;br /&gt;
|-&lt;br /&gt;
| 1018&lt;br /&gt;
| 03FA&lt;br /&gt;
| Computer Service Italia&lt;br /&gt;
|-&lt;br /&gt;
| 1019&lt;br /&gt;
| 03FB&lt;br /&gt;
| Amigo&lt;br /&gt;
|-&lt;br /&gt;
| 1020&lt;br /&gt;
| 03FC&lt;br /&gt;
| Micro-Solutions Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1021&lt;br /&gt;
| 03FD&lt;br /&gt;
| Stacar International&lt;br /&gt;
|-&lt;br /&gt;
| 1022&lt;br /&gt;
| 03FE&lt;br /&gt;
| Video Precisions&lt;br /&gt;
|-&lt;br /&gt;
| 1023&lt;br /&gt;
| 03FF&lt;br /&gt;
| ASDG, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1025&lt;br /&gt;
| 0401&lt;br /&gt;
| Ing. Buero Kalawsky&lt;br /&gt;
|-&lt;br /&gt;
| 1026&lt;br /&gt;
| 0402&lt;br /&gt;
| Computer Tuning&lt;br /&gt;
|-&lt;br /&gt;
| 1027&lt;br /&gt;
| 0403&lt;br /&gt;
| Interplan Unternehmensberatung&lt;br /&gt;
|-&lt;br /&gt;
| 1028&lt;br /&gt;
| 0404&lt;br /&gt;
| Imtronics/Memphis&lt;br /&gt;
| Originally registered to Peter Ohlich&lt;br /&gt;
|-&lt;br /&gt;
| 1030&lt;br /&gt;
| 0406&lt;br /&gt;
| Commodore (Lowell University)&lt;br /&gt;
| Originally registered to Productivity Center&lt;br /&gt;
|-&lt;br /&gt;
| 1041&lt;br /&gt;
| 0411&lt;br /&gt;
| Design Labs&lt;br /&gt;
|-&lt;br /&gt;
| 1042&lt;br /&gt;
| 0412&lt;br /&gt;
| MCS&lt;br /&gt;
|-&lt;br /&gt;
| 1043&lt;br /&gt;
| 0413&lt;br /&gt;
| B. J. Freeman&lt;br /&gt;
|-&lt;br /&gt;
| 1044&lt;br /&gt;
| 0414&lt;br /&gt;
| Side Effects Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1045&lt;br /&gt;
| 0415&lt;br /&gt;
| Oklahoma Personal Comp.&lt;br /&gt;
|-&lt;br /&gt;
| 1046&lt;br /&gt;
| 0416&lt;br /&gt;
| Advanced Micro Innovations&lt;br /&gt;
|-&lt;br /&gt;
| 1047&lt;br /&gt;
| 0417&lt;br /&gt;
| Industrial Support Services&lt;br /&gt;
|-&lt;br /&gt;
| 1048&lt;br /&gt;
| 0418&lt;br /&gt;
| Technisoft&lt;br /&gt;
|-&lt;br /&gt;
| 1049&lt;br /&gt;
| 0419&lt;br /&gt;
| Prolific, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1050&lt;br /&gt;
| 041A&lt;br /&gt;
| Softeam, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1051&lt;br /&gt;
| 041B&lt;br /&gt;
| GRC Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 1052&lt;br /&gt;
| 041C&lt;br /&gt;
| David Lai&lt;br /&gt;
|-&lt;br /&gt;
| 1053&lt;br /&gt;
| 041D&lt;br /&gt;
| Ameristar Technologies&lt;br /&gt;
|-&lt;br /&gt;
| 1054&lt;br /&gt;
| 041E&lt;br /&gt;
| Cline Refrigeration&lt;br /&gt;
|-&lt;br /&gt;
| 1055&lt;br /&gt;
| 041F&lt;br /&gt;
| Cardiac Pacemakers, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1056&lt;br /&gt;
| 0420&lt;br /&gt;
| Supra Corp. (Creative Microsystems)&lt;br /&gt;
|-&lt;br /&gt;
| 1057&lt;br /&gt;
| 0421&lt;br /&gt;
| Wayne Diener&lt;br /&gt;
|-&lt;br /&gt;
| 1058&lt;br /&gt;
| 0422&lt;br /&gt;
| Computer Systems Associates (CSA)&lt;br /&gt;
|-&lt;br /&gt;
| 1059&lt;br /&gt;
| 0423&lt;br /&gt;
| Trionix, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1060&lt;br /&gt;
| 0424&lt;br /&gt;
| David Lucas&lt;br /&gt;
|-&lt;br /&gt;
| 1061&lt;br /&gt;
| 0425&lt;br /&gt;
| Analog Precision&lt;br /&gt;
| Also assigned to D &amp;amp; L Distributing&lt;br /&gt;
|-&lt;br /&gt;
| 1267&lt;br /&gt;
| 04F3&lt;br /&gt;
| RBM Digitaltechnik&lt;br /&gt;
|-&lt;br /&gt;
| 1282&lt;br /&gt;
| 0502&lt;br /&gt;
| M-TEC Hardware Design&lt;br /&gt;
|-&lt;br /&gt;
| 1337&lt;br /&gt;
| 0539&lt;br /&gt;
| Thomas Stenzel (DaFR34K)&lt;br /&gt;
|-&lt;br /&gt;
| 1576&lt;br /&gt;
| 0628&lt;br /&gt;
| Boris Križma&lt;br /&gt;
|-&lt;br /&gt;
| 1761&lt;br /&gt;
| 06E1&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
|-&lt;br /&gt;
| 1803&lt;br /&gt;
| 070B&lt;br /&gt;
| UAE Amiga Emulator&lt;br /&gt;
|-&lt;br /&gt;
| 2002&lt;br /&gt;
| 07D2&lt;br /&gt;
| Mimetics Corp.&lt;br /&gt;
|-&lt;br /&gt;
| 2003&lt;br /&gt;
| 07D3&lt;br /&gt;
| ACDA&lt;br /&gt;
|-&lt;br /&gt;
| 2004&lt;br /&gt;
| 07D4&lt;br /&gt;
| Finn R. Jacobsen&lt;br /&gt;
|-&lt;br /&gt;
| 2005&lt;br /&gt;
| 07D5&lt;br /&gt;
| Elthen Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2006&lt;br /&gt;
| 07D6&lt;br /&gt;
| Nine Tiles Computer Systems Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2007&lt;br /&gt;
| 07D7&lt;br /&gt;
| Analog Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2008&lt;br /&gt;
| 07D8&lt;br /&gt;
| Bell &amp;amp;amp; Howell&lt;br /&gt;
|-&lt;br /&gt;
| 2009&lt;br /&gt;
| 07D9&lt;br /&gt;
| Roland Kochler&lt;br /&gt;
|-&lt;br /&gt;
| 2010&lt;br /&gt;
| 07DA&lt;br /&gt;
| Byte Corp.&lt;br /&gt;
|-&lt;br /&gt;
| 2011&lt;br /&gt;
| 07DB&lt;br /&gt;
| Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 2012&lt;br /&gt;
| 07DC&lt;br /&gt;
| DKB, Inc.&lt;br /&gt;
| Previously named Michigan Software&lt;br /&gt;
|-&lt;br /&gt;
| 2013&lt;br /&gt;
| 07DD&lt;br /&gt;
| Pacific Peripherals&lt;br /&gt;
|-&lt;br /&gt;
| 2014&lt;br /&gt;
| 07DE&lt;br /&gt;
| Sysaphus Software&lt;br /&gt;
|-&lt;br /&gt;
| 2015&lt;br /&gt;
| 07DF&lt;br /&gt;
| Digitronics&lt;br /&gt;
|-&lt;br /&gt;
| 2016&lt;br /&gt;
| 07E0&lt;br /&gt;
| Akron Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2017&lt;br /&gt;
| 07E1&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
|-&lt;br /&gt;
| 2018&lt;br /&gt;
| 07E2&lt;br /&gt;
| Calmos&lt;br /&gt;
|-&lt;br /&gt;
| 2019&lt;br /&gt;
| 07E3&lt;br /&gt;
| Dover Research&lt;br /&gt;
|-&lt;br /&gt;
| 2020&lt;br /&gt;
| 07E4&lt;br /&gt;
| David Krehbiel&lt;br /&gt;
|-&lt;br /&gt;
| 2021&lt;br /&gt;
| 07E5&lt;br /&gt;
| Synergy Peripheral Systems&lt;br /&gt;
| Also known as California Access&lt;br /&gt;
|-&lt;br /&gt;
| 2022&lt;br /&gt;
| 07E6&lt;br /&gt;
| Xetec&lt;br /&gt;
|-&lt;br /&gt;
| 2023&lt;br /&gt;
| 07E7&lt;br /&gt;
| Micron Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2024&lt;br /&gt;
| 07E8&lt;br /&gt;
| CH Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2025&lt;br /&gt;
| 07E9&lt;br /&gt;
| American Liquid Light&lt;br /&gt;
|-&lt;br /&gt;
| 2026&lt;br /&gt;
| 07EA&lt;br /&gt;
| Progressive Peripherals &amp;amp;amp; Software&lt;br /&gt;
| Also used by Ateo&lt;br /&gt;
|-&lt;br /&gt;
| 2027&lt;br /&gt;
| 07EB&lt;br /&gt;
| Wicat Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2028&lt;br /&gt;
| 07EC&lt;br /&gt;
| Applied Systems &amp;amp;amp; Peripherals&lt;br /&gt;
|-&lt;br /&gt;
| 2029&lt;br /&gt;
| 07ED&lt;br /&gt;
| Delaware Valley Software&lt;br /&gt;
|-&lt;br /&gt;
| 2030&lt;br /&gt;
| 07EE&lt;br /&gt;
| Palomax&lt;br /&gt;
|-&lt;br /&gt;
| 2031&lt;br /&gt;
| 07EF&lt;br /&gt;
| Incognito Software&lt;br /&gt;
|-&lt;br /&gt;
| 2032&lt;br /&gt;
| 07F0&lt;br /&gt;
| Jadesign&lt;br /&gt;
|-&lt;br /&gt;
| 2033&lt;br /&gt;
| 07F1&lt;br /&gt;
| BVR&lt;br /&gt;
|-&lt;br /&gt;
| 2034&lt;br /&gt;
| 07F2&lt;br /&gt;
| Spirit Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2035&lt;br /&gt;
| 07F3&lt;br /&gt;
| Spirit Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2036&lt;br /&gt;
| 07F4&lt;br /&gt;
| Atronic&lt;br /&gt;
|-&lt;br /&gt;
| 2037&lt;br /&gt;
| 07F5&lt;br /&gt;
| Scott Karlin&lt;br /&gt;
|-&lt;br /&gt;
| 2038&lt;br /&gt;
| 07F6&lt;br /&gt;
| Howitch&lt;br /&gt;
|-&lt;br /&gt;
| 2039&lt;br /&gt;
| 07F7&lt;br /&gt;
| Sullivan Brothers Visual Engineers&lt;br /&gt;
|-&lt;br /&gt;
| 2040&lt;br /&gt;
| 07F8&lt;br /&gt;
| G I T&lt;br /&gt;
|-&lt;br /&gt;
| 2041&lt;br /&gt;
| 07F9&lt;br /&gt;
| Amigo Business Computers&lt;br /&gt;
|-&lt;br /&gt;
| 2042&lt;br /&gt;
| 07FA&lt;br /&gt;
| Micro E Ab&lt;br /&gt;
|-&lt;br /&gt;
| 2043&lt;br /&gt;
| 07FB&lt;br /&gt;
| Ralph Kruse&lt;br /&gt;
|-&lt;br /&gt;
| 2044&lt;br /&gt;
| 07FC&lt;br /&gt;
| Clearpoint Research&lt;br /&gt;
|-&lt;br /&gt;
| 2045&lt;br /&gt;
| 07FD&lt;br /&gt;
| Kodiak&lt;br /&gt;
|-&lt;br /&gt;
| 2046&lt;br /&gt;
| 07FE&lt;br /&gt;
| BSC&lt;br /&gt;
| Originally registered to Phoenix Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2047&lt;br /&gt;
| 07FF&lt;br /&gt;
| No Name Shown&lt;br /&gt;
|-&lt;br /&gt;
| 2048&lt;br /&gt;
| 0800&lt;br /&gt;
| Commodore Braunschweig&lt;br /&gt;
|-&lt;br /&gt;
| 2049&lt;br /&gt;
| 0801&lt;br /&gt;
| BSC&lt;br /&gt;
| Originally registered to Elaborate Bytes&lt;br /&gt;
|-&lt;br /&gt;
| 2050&lt;br /&gt;
| 0802&lt;br /&gt;
| Kronos/C Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2051&lt;br /&gt;
| 0803&lt;br /&gt;
| Spartanics&lt;br /&gt;
|-&lt;br /&gt;
| 2052&lt;br /&gt;
| 0804&lt;br /&gt;
| Jochheim Computer Tuning&lt;br /&gt;
|-&lt;br /&gt;
| 2053&lt;br /&gt;
| 0805&lt;br /&gt;
| Trans Data Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2054&lt;br /&gt;
| 0806&lt;br /&gt;
| Applied Systems &amp;amp;amp; Peripherals Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2055&lt;br /&gt;
| 0807&lt;br /&gt;
| Checkpoint Technologies&lt;br /&gt;
| Originally registered to Amiga Solutions&lt;br /&gt;
|-&lt;br /&gt;
| 2056&lt;br /&gt;
| 0808&lt;br /&gt;
| Adept Development&lt;br /&gt;
|-&lt;br /&gt;
| 2057&lt;br /&gt;
| 0809&lt;br /&gt;
| Advanced Computer Design&lt;br /&gt;
|-&lt;br /&gt;
| 2058&lt;br /&gt;
| 080A&lt;br /&gt;
| Sir Netics&lt;br /&gt;
|-&lt;br /&gt;
| 2059&lt;br /&gt;
| 080B&lt;br /&gt;
| Expert Services&lt;br /&gt;
|-&lt;br /&gt;
| 2060&lt;br /&gt;
| 080C&lt;br /&gt;
| Digital Art Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2061&lt;br /&gt;
| 080D&lt;br /&gt;
| Adept Development&lt;br /&gt;
|-&lt;br /&gt;
| 2062&lt;br /&gt;
| 080E&lt;br /&gt;
| Expansion Technologies (Expansion Systems)&lt;br /&gt;
|-&lt;br /&gt;
| 2063&lt;br /&gt;
| 080F&lt;br /&gt;
| Alphatech&lt;br /&gt;
|-&lt;br /&gt;
| 2064&lt;br /&gt;
| 0810&lt;br /&gt;
| Edotronik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2065&lt;br /&gt;
| 0811&lt;br /&gt;
| California Access/Synergy&lt;br /&gt;
| Originally registered to Logical Design Works&lt;br /&gt;
|-&lt;br /&gt;
| 2066&lt;br /&gt;
| 0812&lt;br /&gt;
| Bowden, Williams, Full &amp;amp; Assoc.&lt;br /&gt;
|-&lt;br /&gt;
| 2067&lt;br /&gt;
| 0813&lt;br /&gt;
| NES, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2068&lt;br /&gt;
| 0814&lt;br /&gt;
| Amdev&lt;br /&gt;
|-&lt;br /&gt;
| 2069&lt;br /&gt;
| 0815&lt;br /&gt;
| Big Brother Security Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2070&lt;br /&gt;
| 0816&lt;br /&gt;
| Active Circuits Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2071&lt;br /&gt;
| 0817&lt;br /&gt;
| ICD, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2072&lt;br /&gt;
| 0818&lt;br /&gt;
| Multi-Meg Electronique&lt;br /&gt;
|-&lt;br /&gt;
| 2073&lt;br /&gt;
| 0819&lt;br /&gt;
| Kupke Computertechnik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2074&lt;br /&gt;
| 081A&lt;br /&gt;
| The Checkered Ball&lt;br /&gt;
|-&lt;br /&gt;
| 2075&lt;br /&gt;
| 081B&lt;br /&gt;
| Hi Tension Computer Services Ltd. (UK)&lt;br /&gt;
|-&lt;br /&gt;
| 2076&lt;br /&gt;
| 081C&lt;br /&gt;
| Alfa Data&lt;br /&gt;
| Originally assigned to Elmtech Research, Ltd. (UK)&lt;br /&gt;
|-&lt;br /&gt;
| 2077&lt;br /&gt;
| 081D&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
| Originally registered to Clartscreen, Ltd. (UK)&lt;br /&gt;
|-&lt;br /&gt;
| 2078&lt;br /&gt;
| 081E&lt;br /&gt;
| Interworks&lt;br /&gt;
|-&lt;br /&gt;
| 2079&lt;br /&gt;
| 081F&lt;br /&gt;
| Galysh Enterprises&lt;br /&gt;
|-&lt;br /&gt;
| 2080&lt;br /&gt;
| 0820&lt;br /&gt;
| Hardital Synthesis&lt;br /&gt;
| Originally registered to Realtime Games Software Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2081&lt;br /&gt;
| 0821&lt;br /&gt;
| GBS&lt;br /&gt;
|-&lt;br /&gt;
| 2082&lt;br /&gt;
| 0822&lt;br /&gt;
| Circum Design Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2083&lt;br /&gt;
| 0823&lt;br /&gt;
| Alberta Micro Electronic Center&lt;br /&gt;
|-&lt;br /&gt;
| 2084&lt;br /&gt;
| 0824&lt;br /&gt;
| Bestech&lt;br /&gt;
|-&lt;br /&gt;
| 2085&lt;br /&gt;
| 0825&lt;br /&gt;
| Lasar Fantasy&lt;br /&gt;
|-&lt;br /&gt;
| 2086&lt;br /&gt;
| 0826&lt;br /&gt;
| Pulsar&lt;br /&gt;
|-&lt;br /&gt;
| 2087&lt;br /&gt;
| 0827&lt;br /&gt;
| Ivis&lt;br /&gt;
|-&lt;br /&gt;
| 2088&lt;br /&gt;
| 0828&lt;br /&gt;
| Applied Engineering&lt;br /&gt;
|-&lt;br /&gt;
| 2089&lt;br /&gt;
| 0829&lt;br /&gt;
| Solid-State Design &amp;amp;amp; Development&lt;br /&gt;
|-&lt;br /&gt;
| 2090&lt;br /&gt;
| 082A&lt;br /&gt;
| Vison Quest&lt;br /&gt;
|-&lt;br /&gt;
| 2091&lt;br /&gt;
| 082B&lt;br /&gt;
| Seaview Software&lt;br /&gt;
|-&lt;br /&gt;
| 2092&lt;br /&gt;
| 082C&lt;br /&gt;
| BSC&lt;br /&gt;
| Mistakenly used by ADS (Advanced Development Software)&lt;br /&gt;
|-&lt;br /&gt;
| 2093&lt;br /&gt;
| 082D&lt;br /&gt;
| Bernd Culenfeld&lt;br /&gt;
|-&lt;br /&gt;
| 2094&lt;br /&gt;
| 082E&lt;br /&gt;
| American Liquid Light&lt;br /&gt;
|-&lt;br /&gt;
| 2095&lt;br /&gt;
| 082F&lt;br /&gt;
| CEGITES&lt;br /&gt;
|-&lt;br /&gt;
| 2096&lt;br /&gt;
| 0830&lt;br /&gt;
| Quadlite Computers Ltd.&lt;br /&gt;
| Originally registered to EV Industries&lt;br /&gt;
|-&lt;br /&gt;
| 2097&lt;br /&gt;
| 0831&lt;br /&gt;
| Silicon Peace&lt;br /&gt;
|-&lt;br /&gt;
| 2098&lt;br /&gt;
| 0832&lt;br /&gt;
| Black Belt Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2099&lt;br /&gt;
| 0833&lt;br /&gt;
| Village Tronic&lt;br /&gt;
| Originally registerd to Steve Yaeger&lt;br /&gt;
|-&lt;br /&gt;
| 2100&lt;br /&gt;
| 0834&lt;br /&gt;
| ReadySoft&lt;br /&gt;
|-&lt;br /&gt;
| 2101&lt;br /&gt;
| 0835&lt;br /&gt;
| Phoenix Micro Technologies&lt;br /&gt;
|-&lt;br /&gt;
| 2102&lt;br /&gt;
| 0836&lt;br /&gt;
| Advanced Systems &amp;amp; Software&lt;br /&gt;
| Orignally assigned to Preferred Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2103&lt;br /&gt;
| 0837&lt;br /&gt;
| Rombo Productions&lt;br /&gt;
|-&lt;br /&gt;
| 2104&lt;br /&gt;
| 0838&lt;br /&gt;
| Impulse Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2105&lt;br /&gt;
| 0839&lt;br /&gt;
| Beta Unlimited&lt;br /&gt;
|-&lt;br /&gt;
| 2106&lt;br /&gt;
| 083A&lt;br /&gt;
| Memory Expansion System, Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2107&lt;br /&gt;
| 083B&lt;br /&gt;
| Vortex Computer Systems GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2108&lt;br /&gt;
| 083C&lt;br /&gt;
| Platypus Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2109&lt;br /&gt;
| 083D&lt;br /&gt;
| Gigatron OHG&lt;br /&gt;
|-&lt;br /&gt;
| 2110&lt;br /&gt;
| 083E&lt;br /&gt;
| PG Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2111&lt;br /&gt;
| 083F&lt;br /&gt;
| New Technologies Group&lt;br /&gt;
|-&lt;br /&gt;
| 2112&lt;br /&gt;
| 0840&lt;br /&gt;
| Interactive Video Systems (IVS)&lt;br /&gt;
| Pacific Peripherals&lt;br /&gt;
|-&lt;br /&gt;
| 2113&lt;br /&gt;
| 0841&lt;br /&gt;
| Vector&lt;br /&gt;
| Originally registered to H. K. Computer&lt;br /&gt;
|-&lt;br /&gt;
| 2114&lt;br /&gt;
| 0842&lt;br /&gt;
| Pacific Digital&lt;br /&gt;
| Originally registered to C. H. Helfrich Elektronik&lt;br /&gt;
|-&lt;br /&gt;
| 2115&lt;br /&gt;
| 0843&lt;br /&gt;
| Xanadu&lt;br /&gt;
|-&lt;br /&gt;
| 2116&lt;br /&gt;
| 0844&lt;br /&gt;
| Pacific Digital&lt;br /&gt;
| Originally registered to AMS&lt;br /&gt;
|-&lt;br /&gt;
| 2117&lt;br /&gt;
| 0845&lt;br /&gt;
| X-Pert&lt;br /&gt;
|-&lt;br /&gt;
| 2118&lt;br /&gt;
| 0846&lt;br /&gt;
| The Amiga Centre&lt;br /&gt;
|-&lt;br /&gt;
| 2119&lt;br /&gt;
| 0847&lt;br /&gt;
| Digital Pacific&lt;br /&gt;
|-&lt;br /&gt;
| 2120&lt;br /&gt;
| 0848&lt;br /&gt;
| Solid State Leisure&lt;br /&gt;
|-&lt;br /&gt;
| 2121&lt;br /&gt;
| 0849&lt;br /&gt;
| Hydra Systems&lt;br /&gt;
| Originally registered to Analog Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2122&lt;br /&gt;
| 084A&lt;br /&gt;
| Cumana&lt;br /&gt;
|-&lt;br /&gt;
| 2123&lt;br /&gt;
| 084B&lt;br /&gt;
| KAPS 2C Conception&lt;br /&gt;
|-&lt;br /&gt;
| 2124&lt;br /&gt;
| 084C&lt;br /&gt;
| Mike Mason&lt;br /&gt;
|-&lt;br /&gt;
| 2125&lt;br /&gt;
| 084D&lt;br /&gt;
| For Your Eyes&lt;br /&gt;
|-&lt;br /&gt;
| 2126&lt;br /&gt;
| 084E&lt;br /&gt;
| Volkmar Breitfeld Computersysteme&lt;br /&gt;
|-&lt;br /&gt;
| 2127&lt;br /&gt;
| 084F&lt;br /&gt;
| Sunrize Industries&lt;br /&gt;
|-&lt;br /&gt;
| 2128&lt;br /&gt;
| 0850&lt;br /&gt;
| Scott Advanced Micro Designs&lt;br /&gt;
|-&lt;br /&gt;
| 2129&lt;br /&gt;
| 0851&lt;br /&gt;
| Digital Micronics&lt;br /&gt;
|-&lt;br /&gt;
| 2130&lt;br /&gt;
| 0852&lt;br /&gt;
| Alfa-Laval&lt;br /&gt;
|-&lt;br /&gt;
| 2131&lt;br /&gt;
| 0853&lt;br /&gt;
| Multigros A/S&lt;br /&gt;
|-&lt;br /&gt;
| 2132&lt;br /&gt;
| 0854&lt;br /&gt;
| Archos&lt;br /&gt;
|-&lt;br /&gt;
| 2133&lt;br /&gt;
| 0855&lt;br /&gt;
| Icom Simulations&lt;br /&gt;
|-&lt;br /&gt;
| 2134&lt;br /&gt;
| 0856&lt;br /&gt;
| Commodore Test Engineering Group&lt;br /&gt;
|-&lt;br /&gt;
| 2135&lt;br /&gt;
| 0857&lt;br /&gt;
| Microcreations&lt;br /&gt;
|-&lt;br /&gt;
| 2136&lt;br /&gt;
| 0858&lt;br /&gt;
| Shoestring Productions&lt;br /&gt;
|-&lt;br /&gt;
| 2137&lt;br /&gt;
| 0859&lt;br /&gt;
| Faberushi&lt;br /&gt;
|-&lt;br /&gt;
| 2138&lt;br /&gt;
| 085A&lt;br /&gt;
| Evesham Micro Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2139&lt;br /&gt;
| 085B&lt;br /&gt;
| Panagolin Laser Software&lt;br /&gt;
|-&lt;br /&gt;
| 2140&lt;br /&gt;
| 085C&lt;br /&gt;
| Thomas Rudloff&lt;br /&gt;
|-&lt;br /&gt;
| 2141&lt;br /&gt;
| 085D&lt;br /&gt;
| Daniel Hohabir&lt;br /&gt;
|-&lt;br /&gt;
| 2142&lt;br /&gt;
| 085E&lt;br /&gt;
| GfxBase, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2143&lt;br /&gt;
| 085F&lt;br /&gt;
| Axellabs&lt;br /&gt;
|-&lt;br /&gt;
| 2144&lt;br /&gt;
| 0860&lt;br /&gt;
| Roctec Electronics Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2145&lt;br /&gt;
| 0861&lt;br /&gt;
| Omega Datentechnik&lt;br /&gt;
|-&lt;br /&gt;
| 2146&lt;br /&gt;
| 0862&lt;br /&gt;
| Atlantis&lt;br /&gt;
|-&lt;br /&gt;
| 2147&lt;br /&gt;
| 0863&lt;br /&gt;
| Skytec Computers&lt;br /&gt;
|-&lt;br /&gt;
| 2148&lt;br /&gt;
| 0864&lt;br /&gt;
| Protar Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2149&lt;br /&gt;
| 0865&lt;br /&gt;
| ACS&lt;br /&gt;
|-&lt;br /&gt;
| 2150&lt;br /&gt;
| 0866&lt;br /&gt;
| Software Results Enterprises&lt;br /&gt;
| Originally registered to University of Illinois&lt;br /&gt;
|-&lt;br /&gt;
| 2151&lt;br /&gt;
| 0867&lt;br /&gt;
| Infinity Systems Design Group&lt;br /&gt;
|-&lt;br /&gt;
| 2152&lt;br /&gt;
| 0868&lt;br /&gt;
| Trade It&lt;br /&gt;
|-&lt;br /&gt;
| 2153&lt;br /&gt;
| 0869&lt;br /&gt;
| Suntec, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2154&lt;br /&gt;
| 086A&lt;br /&gt;
| DJW Micro Systems&lt;br /&gt;
| Originally registered to Tritec Marketing&lt;br /&gt;
|-&lt;br /&gt;
| 2155&lt;br /&gt;
| 086B&lt;br /&gt;
| Power Computing Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2156&lt;br /&gt;
| 086C&lt;br /&gt;
| MacroSystems&lt;br /&gt;
|-&lt;br /&gt;
| 2157&lt;br /&gt;
| 086D&lt;br /&gt;
| Masoboshi GmbH (DCE)&lt;br /&gt;
|-&lt;br /&gt;
| 2158&lt;br /&gt;
| 086E&lt;br /&gt;
| HAL Software Hardware Handel&lt;br /&gt;
|-&lt;br /&gt;
| 2159&lt;br /&gt;
| 086F&lt;br /&gt;
| Mainhattan Data&lt;br /&gt;
| Originally registered to Michael Lamm Computersysteme&lt;br /&gt;
|-&lt;br /&gt;
| 2160&lt;br /&gt;
| 0870&lt;br /&gt;
| Digital Processing System&lt;br /&gt;
| Originally registered to bbdp Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2161&lt;br /&gt;
| 0871&lt;br /&gt;
| Blue Ribbon Soundworks&lt;br /&gt;
| Originally registered to Design Computer Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2162&lt;br /&gt;
| 0872&lt;br /&gt;
| XPert&lt;br /&gt;
| Originally registered to The Station&lt;br /&gt;
|-&lt;br /&gt;
| 2163&lt;br /&gt;
| 0873&lt;br /&gt;
| DelaComp&lt;br /&gt;
| Originally registered to Bryan Williams&lt;br /&gt;
|-&lt;br /&gt;
| 2164&lt;br /&gt;
| 0874&lt;br /&gt;
| Superformance Computer Engineering GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2165&lt;br /&gt;
| 0875&lt;br /&gt;
| Overland Engineering&lt;br /&gt;
|-&lt;br /&gt;
| 2166&lt;br /&gt;
| 0876&lt;br /&gt;
| Thomas Hamren&lt;br /&gt;
|-&lt;br /&gt;
| 2167&lt;br /&gt;
| 0877&lt;br /&gt;
| Village Tronic&lt;br /&gt;
|-&lt;br /&gt;
| 2168&lt;br /&gt;
| 0878&lt;br /&gt;
| Toolbox Design&lt;br /&gt;
|-&lt;br /&gt;
| 2169&lt;br /&gt;
| 0879&lt;br /&gt;
| Digital Processing System&lt;br /&gt;
|-&lt;br /&gt;
| 2170&lt;br /&gt;
| 087A&lt;br /&gt;
| Superformance&lt;br /&gt;
|-&lt;br /&gt;
| 2171&lt;br /&gt;
| 087B&lt;br /&gt;
| Utilities Unlimited&lt;br /&gt;
|-&lt;br /&gt;
| 2172&lt;br /&gt;
| 087C&lt;br /&gt;
| phase 5&lt;br /&gt;
|-&lt;br /&gt;
| 2173&lt;br /&gt;
| 087D&lt;br /&gt;
| Juergen Kommos&lt;br /&gt;
|-&lt;br /&gt;
| 2174&lt;br /&gt;
| 087E&lt;br /&gt;
| Electronic Design&lt;br /&gt;
|-&lt;br /&gt;
| 2175&lt;br /&gt;
| 087F&lt;br /&gt;
| James Cook University of North Queensland&lt;br /&gt;
|-&lt;br /&gt;
| 2176&lt;br /&gt;
| 0880&lt;br /&gt;
| AmiTrix Development&lt;br /&gt;
|-&lt;br /&gt;
| 2177&lt;br /&gt;
| 0881&lt;br /&gt;
| Ferranti&lt;br /&gt;
|-&lt;br /&gt;
| 2178&lt;br /&gt;
| 0882&lt;br /&gt;
| Leviathan Development&lt;br /&gt;
|-&lt;br /&gt;
| 2179&lt;br /&gt;
| 0883&lt;br /&gt;
| United Video Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2180&lt;br /&gt;
| 0884&lt;br /&gt;
| GPSoft Pty. Ltd.&lt;br /&gt;
| Originally registered to Juergen Kommos&lt;br /&gt;
|-&lt;br /&gt;
| 2181&lt;br /&gt;
| 0885&lt;br /&gt;
| ArMAX&lt;br /&gt;
| Oliver Bausch&lt;br /&gt;
|-&lt;br /&gt;
| 2182&lt;br /&gt;
| 0886&lt;br /&gt;
| CP Computer&lt;br /&gt;
|-&lt;br /&gt;
| 2183&lt;br /&gt;
| 0887&lt;br /&gt;
| AMOK - Amiga Module &amp;amp;amp; Oberon Klub&lt;br /&gt;
|-&lt;br /&gt;
| 2184&lt;br /&gt;
| 0888&lt;br /&gt;
| ITEK Neser &amp;amp;amp; Sieber GbR&lt;br /&gt;
|-&lt;br /&gt;
| 2185&lt;br /&gt;
| 0889&lt;br /&gt;
| Phillip C. Lello&lt;br /&gt;
|-&lt;br /&gt;
| 2186&lt;br /&gt;
| 088A&lt;br /&gt;
| Cyborg Design Services&lt;br /&gt;
|-&lt;br /&gt;
| 2187&lt;br /&gt;
| 088B&lt;br /&gt;
| G2 Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2188&lt;br /&gt;
| 088C&lt;br /&gt;
| Pro System Computersysteme&lt;br /&gt;
|-&lt;br /&gt;
| 2189&lt;br /&gt;
| 088D&lt;br /&gt;
| ZEUS Electronic&lt;br /&gt;
| Originally registered to MSPI (Markt &amp;amp;amp; Technik)&lt;br /&gt;
|-&lt;br /&gt;
| 2190&lt;br /&gt;
| 088E&lt;br /&gt;
| Altatech&lt;br /&gt;
|-&lt;br /&gt;
| 2191&lt;br /&gt;
| 088F&lt;br /&gt;
| NewTek&lt;br /&gt;
|-&lt;br /&gt;
| 2192&lt;br /&gt;
| 0890&lt;br /&gt;
| M-TEC Hardware Design&lt;br /&gt;
| Originally registered to Hardware Design Udo Neuroth&lt;br /&gt;
|-&lt;br /&gt;
| 2193&lt;br /&gt;
| 0891&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
| Originally registered to Viona Development&lt;br /&gt;
|-&lt;br /&gt;
| 2194&lt;br /&gt;
| 0892&lt;br /&gt;
| Amitek&lt;br /&gt;
| Originally assigned to Marpet Developments&lt;br /&gt;
|-&lt;br /&gt;
| 2195&lt;br /&gt;
| 0893&lt;br /&gt;
| Ingenieurbuero Helfrich&lt;br /&gt;
|-&lt;br /&gt;
| 2196&lt;br /&gt;
| 0894&lt;br /&gt;
| The Neo Group&lt;br /&gt;
|-&lt;br /&gt;
| 2197&lt;br /&gt;
| 0895&lt;br /&gt;
| Cyon&lt;br /&gt;
|-&lt;br /&gt;
| 2198&lt;br /&gt;
| 0896&lt;br /&gt;
| Bob Research Group&lt;br /&gt;
|-&lt;br /&gt;
| 2199&lt;br /&gt;
| 0897&lt;br /&gt;
| Richmond Sound Design Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2200&lt;br /&gt;
| 0898&lt;br /&gt;
| US Cybernetics&lt;br /&gt;
|-&lt;br /&gt;
| 2201&lt;br /&gt;
| 0899&lt;br /&gt;
| Fulvio Ieva&lt;br /&gt;
|-&lt;br /&gt;
| 2202&lt;br /&gt;
| 089A&lt;br /&gt;
| Silicon Studio&lt;br /&gt;
|-&lt;br /&gt;
| 2203&lt;br /&gt;
| 089B&lt;br /&gt;
| MacroSystems (USA)&lt;br /&gt;
| Was named Micro System Devices&lt;br /&gt;
|-&lt;br /&gt;
| 2204&lt;br /&gt;
| 089C&lt;br /&gt;
| Conspector Entertainment&lt;br /&gt;
|-&lt;br /&gt;
| 2205&lt;br /&gt;
| 089D&lt;br /&gt;
| Laserforum&lt;br /&gt;
|-&lt;br /&gt;
| 2206&lt;br /&gt;
| 089E&lt;br /&gt;
| Elbox Computer&lt;br /&gt;
| Mistakenly used by Index Information Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2207&lt;br /&gt;
| 089F&lt;br /&gt;
| Applied Magic Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2208&lt;br /&gt;
| 08A0&lt;br /&gt;
| SDL Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2560&lt;br /&gt;
| 0A00&lt;br /&gt;
| Harms&lt;br /&gt;
|-&lt;br /&gt;
| 2588&lt;br /&gt;
| 0A1C&lt;br /&gt;
| A1K.org Community&lt;br /&gt;
|-&lt;br /&gt;
| 2640&lt;br /&gt;
| 0A50&lt;br /&gt;
| Micronik&lt;br /&gt;
|-&lt;br /&gt;
| 3084&lt;br /&gt;
| 0C0C&lt;br /&gt;
| Team 4&lt;br /&gt;
|-&lt;br /&gt;
| 3643&lt;br /&gt;
| 0E3B&lt;br /&gt;
| E3B&lt;br /&gt;
| Michael Boehmer&lt;br /&gt;
|-&lt;br /&gt;
| 3855&lt;br /&gt;
| 0F0F&lt;br /&gt;
| Micronik&lt;br /&gt;
|-&lt;br /&gt;
| 4096&lt;br /&gt;
| 1000&lt;br /&gt;
| MegaMicro&lt;br /&gt;
|-&lt;br /&gt;
| 4110&lt;br /&gt;
| 100E&lt;br /&gt;
| DigiFeX&lt;br /&gt;
|-&lt;br /&gt;
| 4136&lt;br /&gt;
| 1028&lt;br /&gt;
| Imtronics/Memphis&lt;br /&gt;
|-&lt;br /&gt;
| 4149&lt;br /&gt;
| 1035&lt;br /&gt;
| PROTAR&lt;br /&gt;
|-&lt;br /&gt;
| 4369&lt;br /&gt;
| 1111&lt;br /&gt;
| Frank Strauß Elektronik&lt;br /&gt;
| Also used by Kupke&lt;br /&gt;
|-&lt;br /&gt;
| 4626&lt;br /&gt;
| 1212&lt;br /&gt;
| Individual Computers&lt;br /&gt;
|-&lt;br /&gt;
| 4648&lt;br /&gt;
| 1228&lt;br /&gt;
| Flesch Hornemann Computer Elec.&lt;br /&gt;
|-&lt;br /&gt;
| 4680&lt;br /&gt;
| 1248&lt;br /&gt;
| Kupke Computertechnik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 4711&lt;br /&gt;
| 1267&lt;br /&gt;
| RBM digitaltechnik&lt;br /&gt;
|-&lt;br /&gt;
| 4754&lt;br /&gt;
| 1292&lt;br /&gt;
| MacroSystems&lt;br /&gt;
|-&lt;br /&gt;
| 5000&lt;br /&gt;
| 1388&lt;br /&gt;
| ITH&lt;br /&gt;
|-&lt;br /&gt;
| 5001&lt;br /&gt;
| 1389&lt;br /&gt;
| VMC&lt;br /&gt;
|-&lt;br /&gt;
| 5010&lt;br /&gt;
| 1392&lt;br /&gt;
| Ambience Creation Technology&lt;br /&gt;
|-&lt;br /&gt;
| 5011&lt;br /&gt;
| 1393&lt;br /&gt;
| Creative Development&lt;br /&gt;
|-&lt;br /&gt;
| 5012&lt;br /&gt;
| 1394&lt;br /&gt;
| Georg Braun&lt;br /&gt;
|-&lt;br /&gt;
| 5013&lt;br /&gt;
| 1395&lt;br /&gt;
| Swedish User Group of Amiga&lt;br /&gt;
|-&lt;br /&gt;
| 5014&lt;br /&gt;
| 1396&lt;br /&gt;
| Jakub Bednarski&lt;br /&gt;
|-&lt;br /&gt;
| 5015&lt;br /&gt;
| 1397&lt;br /&gt;
| KryoFlux, Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 5016&lt;br /&gt;
| 1398&lt;br /&gt;
| Igor Majstorovic&lt;br /&gt;
|-&lt;br /&gt;
| 5017&lt;br /&gt;
| 1399&lt;br /&gt;
| Alastair M. Robinson&lt;br /&gt;
|-&lt;br /&gt;
| 5018&lt;br /&gt;
| 139A&lt;br /&gt;
| Austex Software&lt;br /&gt;
|-&lt;br /&gt;
| 5019&lt;br /&gt;
| 139B&lt;br /&gt;
| Sören Gust&lt;br /&gt;
|-&lt;br /&gt;
| 5020&lt;br /&gt;
| 139C&lt;br /&gt;
| Rok Krajnc&lt;br /&gt;
|-&lt;br /&gt;
| 5030&lt;br /&gt;
| 13A6&lt;br /&gt;
| Tim Tashpulatov&lt;br /&gt;
|-&lt;br /&gt;
| 5040&lt;br /&gt;
| 13B0&lt;br /&gt;
| 7-bit&lt;br /&gt;
|-&lt;br /&gt;
| 5050&lt;br /&gt;
| 13BA&lt;br /&gt;
| Sakura IT&lt;br /&gt;
|-&lt;br /&gt;
| 5060&lt;br /&gt;
| 13C4&lt;br /&gt;
| FPGAArcade&lt;br /&gt;
|-&lt;br /&gt;
| 5070&lt;br /&gt;
| 13CE&lt;br /&gt;
| CancerSoft Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 5080&lt;br /&gt;
| 13D8&lt;br /&gt;
| Stephen Leary&lt;br /&gt;
|-&lt;br /&gt;
| 5090&lt;br /&gt;
| 13E2&lt;br /&gt;
| DMA Softlab LLC&lt;br /&gt;
|-&lt;br /&gt;
| 5100&lt;br /&gt;
| 13EC&lt;br /&gt;
| Brookhouse Engineering&lt;br /&gt;
|-&lt;br /&gt;
| 5110&lt;br /&gt;
| 13F6&lt;br /&gt;
| Eduardo Arana&lt;br /&gt;
|-&lt;br /&gt;
| 5120&lt;br /&gt;
| 1400&lt;br /&gt;
| CS-LAB&lt;br /&gt;
|-&lt;br /&gt;
| 5130&lt;br /&gt;
| 140A&lt;br /&gt;
| Robert Miranda&lt;br /&gt;
|-&lt;br /&gt;
| 5140&lt;br /&gt;
| 1414&lt;br /&gt;
| RastPort&lt;br /&gt;
|-&lt;br /&gt;
| 5132&lt;br /&gt;
| 140C&lt;br /&gt;
| UAS Interface Ltd6&lt;br /&gt;
|-&lt;br /&gt;
| 5150&lt;br /&gt;
| 141E&lt;br /&gt;
| Amiga Kit&lt;br /&gt;
|-&lt;br /&gt;
| 5160&lt;br /&gt;
| 1428&lt;br /&gt;
| Central Texas Commodore User Group&lt;br /&gt;
|-&lt;br /&gt;
| 5170&lt;br /&gt;
| 1432&lt;br /&gt;
| Confusion Research Center&lt;br /&gt;
|-&lt;br /&gt;
| 5180&lt;br /&gt;
| 143C&lt;br /&gt;
| Solar Soyuz Zaibatsu&lt;br /&gt;
|-&lt;br /&gt;
| 5190&lt;br /&gt;
| 1446&lt;br /&gt;
| BooBip&lt;br /&gt;
|-&lt;br /&gt;
| 5191&lt;br /&gt;
| 1447&lt;br /&gt;
| Matthias Hampel&lt;br /&gt;
|-&lt;br /&gt;
| 5192&lt;br /&gt;
| 1448&lt;br /&gt;
| dec0de Consulting Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 5193&lt;br /&gt;
| 1449&lt;br /&gt;
| Puppy Concepts&lt;br /&gt;
|-&lt;br /&gt;
| 5194&lt;br /&gt;
| 144A&lt;br /&gt;
| Open Amiga Hardware Repository&lt;br /&gt;
|-&lt;br /&gt;
| 5195&lt;br /&gt;
| 144B&lt;br /&gt;
| Double H Tech&lt;br /&gt;
|-&lt;br /&gt;
| 5196&lt;br /&gt;
| 144C&lt;br /&gt;
| Retromatik&lt;br /&gt;
|-&lt;br /&gt;
| 5500&lt;br /&gt;
| 157C&lt;br /&gt;
| Inhouse Information&lt;br /&gt;
|-&lt;br /&gt;
| 5768&lt;br /&gt;
| 1688&lt;br /&gt;
| Bio Con&lt;br /&gt;
|-&lt;br /&gt;
| 6148&lt;br /&gt;
| 1804&lt;br /&gt;
| HK-Computer&lt;br /&gt;
|-&lt;br /&gt;
| 6502&lt;br /&gt;
| 1966&lt;br /&gt;
| Cloanto&lt;br /&gt;
|-&lt;br /&gt;
| 6520&lt;br /&gt;
| 1978&lt;br /&gt;
| Oliver Gantert&lt;br /&gt;
|-&lt;br /&gt;
| 7777&lt;br /&gt;
| 1E61&lt;br /&gt;
| Rafal Gabriel Chyla&lt;br /&gt;
|-&lt;br /&gt;
| 8215&lt;br /&gt;
| 2017&lt;br /&gt;
| Vortex&lt;br /&gt;
|-&lt;br /&gt;
| 8244&lt;br /&gt;
| 2034&lt;br /&gt;
| Spirit Technology&lt;br /&gt;
|-&lt;br /&gt;
| 8290&lt;br /&gt;
| 2062&lt;br /&gt;
| Expansion Systems&lt;br /&gt;
|-&lt;br /&gt;
| 8448&lt;br /&gt;
| 2100&lt;br /&gt;
| ReadySoft&lt;br /&gt;
|-&lt;br /&gt;
| 8512&lt;br /&gt;
| 2140&lt;br /&gt;
| Phase 5 Digital Products&lt;br /&gt;
|-&lt;br /&gt;
| 8553&lt;br /&gt;
| 2169&lt;br /&gt;
| Digital Processing Systems Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 8704&lt;br /&gt;
| 2200&lt;br /&gt;
| ACT Elektronik&lt;br /&gt;
|-&lt;br /&gt;
| 8738&lt;br /&gt;
| 2222&lt;br /&gt;
| ACT Elektronik&lt;br /&gt;
|-&lt;br /&gt;
| 9512&lt;br /&gt;
| 2528&lt;br /&gt;
| Tower Technologies&lt;br /&gt;
|-&lt;br /&gt;
| 10676&lt;br /&gt;
| 29B4&lt;br /&gt;
| Electronic Design&lt;br /&gt;
|-&lt;br /&gt;
| 14195&lt;br /&gt;
| 3773&lt;br /&gt;
| Media-net-Point&lt;br /&gt;
|-&lt;br /&gt;
| 14501&lt;br /&gt;
| 38A5&lt;br /&gt;
| Petsoff, Finland&lt;br /&gt;
|-&lt;br /&gt;
| 16375&lt;br /&gt;
| 3FF7&lt;br /&gt;
| Uwe Gerlach&lt;br /&gt;
|-&lt;br /&gt;
| 16707&lt;br /&gt;
| 4143&lt;br /&gt;
| Ateo Concepts&lt;br /&gt;
|-&lt;br /&gt;
| 16708&lt;br /&gt;
| 4144&lt;br /&gt;
| ALiENDESiGN&lt;br /&gt;
|-&lt;br /&gt;
| 16945&lt;br /&gt;
| 4231&lt;br /&gt;
| A.C.T.&lt;br /&gt;
|-&lt;br /&gt;
| 17740&lt;br /&gt;
| 454C&lt;br /&gt;
| HK-Computer (ELSAT)&lt;br /&gt;
|-&lt;br /&gt;
| 18260&lt;br /&gt;
| 4754&lt;br /&gt;
| MacroSystems (Germany)&lt;br /&gt;
|-&lt;br /&gt;
| 19796&lt;br /&gt;
| 4D54&lt;br /&gt;
| Markt &amp;amp; Technik&lt;br /&gt;
|-&lt;br /&gt;
| 22359&lt;br /&gt;
| 5757&lt;br /&gt;
| Markt &amp;amp; Technik&lt;br /&gt;
|-&lt;br /&gt;
| 26464&lt;br /&gt;
| 6760&lt;br /&gt;
| Combitec&lt;br /&gt;
|-&lt;br /&gt;
| 26470&lt;br /&gt;
| 6766&lt;br /&gt;
| Combitec&lt;br /&gt;
|-&lt;br /&gt;
| 28014&lt;br /&gt;
| 6D6E&lt;br /&gt;
| MNT Media and Technology UG&lt;br /&gt;
|-&lt;br /&gt;
| 32768&lt;br /&gt;
| 8000&lt;br /&gt;
| M.A.S.T.&lt;br /&gt;
|-&lt;br /&gt;
| 42240&lt;br /&gt;
| A500&lt;br /&gt;
| Aethreum Digital&lt;br /&gt;
|-&lt;br /&gt;
| 43437&lt;br /&gt;
| A9AD&lt;br /&gt;
| Reis-Ware&lt;br /&gt;
|-&lt;br /&gt;
| 43521&lt;br /&gt;
| AA01&lt;br /&gt;
| Cameron&lt;br /&gt;
|-&lt;br /&gt;
| 43537&lt;br /&gt;
| AA11&lt;br /&gt;
| Reis-Ware&lt;br /&gt;
|-&lt;br /&gt;
| 44359&lt;br /&gt;
| AD47&lt;br /&gt;
| Matay&lt;br /&gt;
|-&lt;br /&gt;
| 46504&lt;br /&gt;
| B5A8&lt;br /&gt;
| Phoenix&lt;br /&gt;
|-&lt;br /&gt;
| 48879&lt;br /&gt;
| BEEF&lt;br /&gt;
| Swiss Mountain Dog Products&lt;br /&gt;
|-&lt;br /&gt;
| 49160&lt;br /&gt;
| C008&lt;br /&gt;
| Combitec&lt;br /&gt;
|-&lt;br /&gt;
| 61453&lt;br /&gt;
| F00D&lt;br /&gt;
| Forefront Technologies Inc.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
For any changes/additions to this registry please send a support request to [mailto:support@hyperion-entertainment.com support@hyperion-entertainment.com].&lt;/div&gt;</summary>
		<author><name>Costel Mincea</name></author>
	</entry>
	<entry>
		<id>https://wiki.amigaos.net/w/index.php?title=Amiga_Hardware_Manufacturer_ID_Registry&amp;diff=12595</id>
		<title>Amiga Hardware Manufacturer ID Registry</title>
		<link rel="alternate" type="text/html" href="https://wiki.amigaos.net/w/index.php?title=Amiga_Hardware_Manufacturer_ID_Registry&amp;diff=12595"/>
		<updated>2026-09-08T10:11:48Z</updated>

		<summary type="html">&lt;p&gt;Costel Mincea: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
= How to Obtain a Manufacturer Number =&lt;br /&gt;
&lt;br /&gt;
Manufacturer&#039;s numbers are assigned by the AmigaOS development team. To obtain your unique manufacturer number send a support request to [mailto:support@hyperion-entertainment.com support@hyperion-entertainment.com].&lt;br /&gt;
&lt;br /&gt;
Be sure and include your name and the type of expansion product you are developing.&lt;br /&gt;
&lt;br /&gt;
= Your Manufacturer Number =&lt;br /&gt;
&lt;br /&gt;
Attention hardware manufacturers. If you are developing a hardware expansion product for the Classic Amiga (e.g. 500, 2000, 3000) then you will need to obtain a special manufacturer ID number from the AmigaOS development team to identify your product. This manufacturer number is used by the Amiga to link your hardware with its driver software at boot time.&lt;br /&gt;
&lt;br /&gt;
Your manufacturer number is part of the special protocol that the Amiga uses to automatically configure all expansion devices on the bus without the user having to cut jumpers or adjust dip switches. This is called auto-config.&lt;br /&gt;
&lt;br /&gt;
At start-up time, the system first polls each board in the system and assigns the board its own address space. If it is a memory board, its RAM is linked into the memory free pool. Later in the boot sequence, after DOS is initialized, the binddrivers program is run. Binddrivers will search the directory SYS:Expansion for the drivers that go with the boards.&lt;br /&gt;
&lt;br /&gt;
To do this binddrivers looks in the Tool Type field of all icon files in SYS:Expansion. If the first seven bytes of the Tool Type field are &amp;quot;PRODUCT&amp;quot;, then this is an icon file for a driver.&lt;br /&gt;
&lt;br /&gt;
Binddrivers will then attempt to match the drivers it has found with the boards that were found earlier. This is where your manufacturer number comes in.&lt;br /&gt;
&lt;br /&gt;
Your manufacturer number goes in two places. First, it is burned in hex form into the PAL which is part of ALL auto-config expansion products. Second, it appears in ASCII in the Tool Type field of the icon file for your product&#039;s driver. By matching these two numbers, the Amiga can automatically configure your board and bind it&#039;s software driver into the system as well.&lt;br /&gt;
&lt;br /&gt;
The manufacturer&#039;s number is a 16-bit ID which appears in PAL offsets $10-$17. There is also an 8-bit product number which you assign. The product number is for uniquely identifying different products from the same vendor. The product number will appear in PAL offsets $04-$07. This gives you a total of 24 bits to identify each of your products.&lt;br /&gt;
&lt;br /&gt;
These 24 bits of information in the PAL which identify your product are matched against the information in the Tool Type field of all icon files in the SYS:Expansion drawer. For example, suppose you are manufacturer #1019. You have two products, #1 and #2 which both use the same driver. The icon for your driver for these two products would have a Tool Type set to &amp;quot;PRODUCT=1019/1|1019/2&amp;quot;. This means: I am an icon for a driver that works with product number 1 or 2 from manufacturer 1019, now bind me. Spaces are not legal. Here are two other examples:&lt;br /&gt;
&lt;br /&gt;
; PRODUCT=1208/11&lt;br /&gt;
: is the Tool Type for a driver for product 11 from manufacturer number 1208.&lt;br /&gt;
&lt;br /&gt;
; PRODUCT=1017&lt;br /&gt;
: is the Tool Type for a driver for any product from manufacturer number 1017.&lt;br /&gt;
&lt;br /&gt;
For an informal explanation of the auto-configuration process, see the chapter on Software Expansion Architecture from the 2nd Annual Amiga Developer&#039;s Conference Notes (available on ADCD 2.1). For the details of timing, power, the PAL equations and PAL address specifications and the expansion library documentation, see sections 3.1 to 3.3 of the A500/A2000 Technical Reference Manual. The original auto-config spec appears in the A1000 Schematics and Expansion Specification.&lt;br /&gt;
&lt;br /&gt;
The auto-config process makes the addition of expansion products to the system very easy. All the user has to do is put the board in any slot and copy the driver from the release disk to his own SYS:Expansion drawer. Everything else is automatic. There are no jumpers or dip switches to set. Best of all, you will get a lot less support calls asking how to make your product work with the XYZ-Corp-battery-backed-clock.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
&lt;br /&gt;
Some notes on hardware manufacturer ID assignment.&lt;br /&gt;
&lt;br /&gt;
* Manufacturer ID numbers are assigned free of charge.&lt;br /&gt;
* Please provide the following information when requesting an ID:&lt;br /&gt;
*# Name of the company or person&lt;br /&gt;
*# Postal address/contact address&lt;br /&gt;
*# Name of the contact person, with a corresponding e-mail address&lt;br /&gt;
*# A brief description of the kind of products you want to produce&lt;br /&gt;
* All ID numbers smaller than 5000 must be considered unsafe because no information exists on which numbers exactly were taken during the time Commodore, Inc. disintegrated.&lt;br /&gt;
* ID numbers in the range 8192 to 18841 must be considered unsafe because some hardware developers mistook the numbers assigned to them to be given in hexadecimal format. Hence 0x2000 = 8192 and 0x4999 = 18841.&lt;br /&gt;
&lt;br /&gt;
= Example code =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
/*-----------------------------------------------*/&lt;br /&gt;
/* Here is a short program which will tell you   */&lt;br /&gt;
/* about the expansion boards configured in your */&lt;br /&gt;
/* system without you opening up the machine.    */&lt;br /&gt;
/* Code by Bill Koester of CATS                  */&lt;br /&gt;
/*-----------------------------------------------*/&lt;br /&gt;
#include &amp;lt;libraries/configvars.h&amp;gt;&lt;br /&gt;
#include &amp;lt;libraries/expansion.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
struct ExpansionBase *ExpansionBase;&lt;br /&gt;
&lt;br /&gt;
void cleanup();&lt;br /&gt;
void printdev();&lt;br /&gt;
&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
   struct ConfigDev *MyConfigDev;&lt;br /&gt;
&lt;br /&gt;
   /*----------------------------------*/&lt;br /&gt;
   /* Open the expansion library,      */&lt;br /&gt;
   /* if there is a problem then exit  */&lt;br /&gt;
   /*----------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   ExpansionBase =(struct ExpansionBase *) OpenLibrary(EXPANSIONNAME,0);&lt;br /&gt;
   if(ExpansionBase==NULL)&lt;br /&gt;
   {&lt;br /&gt;
      printf(&amp;quot;Error opening expansion library!!\n&amp;quot;);&lt;br /&gt;
      cleanup();&lt;br /&gt;
      exit(0);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   /*--------------------------------------------*/&lt;br /&gt;
   /* Use FindConfigDev to get info on the first */&lt;br /&gt;
   /* expansion board on the list maintained by  */&lt;br /&gt;
   /* Exec.  If there are no expansion boards in */&lt;br /&gt;
   /* the system then exit.                      */&lt;br /&gt;
   /*--------------------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   MyConfigDev = NULL;&lt;br /&gt;
&lt;br /&gt;
  /*--------------------------------------------------*/&lt;br /&gt;
  /* FindConfigDev(oldConfigDev,manufacturer,product) */&lt;br /&gt;
  /* oldConfigDev = NULL for the top of the list      */&lt;br /&gt;
  /* manufacturer = -1 for any manufacturer           */&lt;br /&gt;
  /* product      = -1 for any product                */&lt;br /&gt;
  /*--------------------------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   MyConfigDev = FindConfigDev(NULL,-1,-1);&lt;br /&gt;
&lt;br /&gt;
   if(MyConfigDev==NULL)&lt;br /&gt;
   {&lt;br /&gt;
      printf(&amp;quot;No Configured Devices found!!\n&amp;quot;);&lt;br /&gt;
      cleanup();&lt;br /&gt;
      exit(0);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   printdev(MyConfigDev);&lt;br /&gt;
&lt;br /&gt;
   /*-----------------------------------*/&lt;br /&gt;
   /* OK, there is at least one board,  */&lt;br /&gt;
   /* so loop and get the entire list   */&lt;br /&gt;
   /* printing as we go with printdev() */&lt;br /&gt;
   /*-----------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   while(MyConfigDev = FindConfigDev(MyConfigDev,-1,-1))&lt;br /&gt;
   {&lt;br /&gt;
      printdev(MyConfigDev);&lt;br /&gt;
   }&lt;br /&gt;
   cleanup();&lt;br /&gt;
   return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*-------------------*/&lt;br /&gt;
/* Close up shop...  */&lt;br /&gt;
/*-------------------*/&lt;br /&gt;
void cleanup()&lt;br /&gt;
{&lt;br /&gt;
   if(ExpansionBase)&lt;br /&gt;
      CloseLibrary(ExpansionBase);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*----------------------------------*/&lt;br /&gt;
/* Print out the contents of the    */&lt;br /&gt;
/* dev structure for this expansion */&lt;br /&gt;
/* product.                         */&lt;br /&gt;
/*----------------------------------*/&lt;br /&gt;
&lt;br /&gt;
void printdev(dev)&lt;br /&gt;
struct ConfigDev *dev;&lt;br /&gt;
{&lt;br /&gt;
   char buff[200];&lt;br /&gt;
&lt;br /&gt;
   printf(&amp;quot;Flags          = &amp;quot;);&lt;br /&gt;
   if(dev-&amp;gt;cd_Flags==NULL)&lt;br /&gt;
      printf(&amp;quot;NULL  &amp;quot;);&lt;br /&gt;
   if(dev-&amp;gt;cd_Flags&amp;amp;CDF_SHUTUP)&lt;br /&gt;
      printf(&amp;quot;CDF_SHUTUP  &amp;quot;);&lt;br /&gt;
   if(dev-&amp;gt;cd_Flags&amp;amp;CDF_CONFIGME)&lt;br /&gt;
      printf(&amp;quot;CDF_CONFIGME  &amp;quot;);&lt;br /&gt;
   printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
   printf(&amp;quot;Board Address  = %x\n&amp;quot;,dev-&amp;gt;cd_BoardAddr);&lt;br /&gt;
   printf(&amp;quot;Board Size     = %d bytes\n&amp;quot;,dev-&amp;gt;cd_BoardSize);&lt;br /&gt;
   printf(&amp;quot;Slot  Address  = %d\n&amp;quot;,dev-&amp;gt;cd_SlotAddr);&lt;br /&gt;
   printf(&amp;quot;Slot  Size     = %d\n&amp;quot;,dev-&amp;gt;cd_SlotSize);&lt;br /&gt;
   printf(&amp;quot;Driver code at   %x\n&amp;quot;,dev-&amp;gt;cd_Driver);&lt;br /&gt;
&lt;br /&gt;
   printf(&amp;quot;er_Type         = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Type);&lt;br /&gt;
   printf(&amp;quot;er_Product      = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Product);&lt;br /&gt;
   printf(&amp;quot;er_Flags        = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Flags);&lt;br /&gt;
   printf(&amp;quot;er_Reserved03   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved03);&lt;br /&gt;
   printf(&amp;quot;er_Manufacturer = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Manufacturer);&lt;br /&gt;
   printf(&amp;quot;er_SerialNumber = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_SerialNumber);&lt;br /&gt;
   printf(&amp;quot;er_InitDiagVec  = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_InitDiagVec);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0c   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0c);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0d   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0d);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0e   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0e);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0f   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0f);&lt;br /&gt;
&lt;br /&gt;
   printf(&amp;quot;Hit Return to continue:\n&amp;quot;);&lt;br /&gt;
   gets(buff);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Registry =&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! ID (decimal)&lt;br /&gt;
! ID (hexadecimal)&lt;br /&gt;
! Manufacturer&lt;br /&gt;
! Notes&lt;br /&gt;
|-&lt;br /&gt;
| 1&lt;br /&gt;
| 0001&lt;br /&gt;
| Micronik&lt;br /&gt;
|-&lt;br /&gt;
| 211&lt;br /&gt;
| 00D3&lt;br /&gt;
| Pacific Peripherals/Profex&lt;br /&gt;
|-&lt;br /&gt;
| 221&lt;br /&gt;
| 00DD&lt;br /&gt;
| Kupke Computertechnik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 256&lt;br /&gt;
| 0100&lt;br /&gt;
| Memphis&lt;br /&gt;
| Originally registered to MacroSystems US&lt;br /&gt;
|-&lt;br /&gt;
| 512&lt;br /&gt;
| 0200&lt;br /&gt;
| 3-State Computertechnik&lt;br /&gt;
|-&lt;br /&gt;
| 513&lt;br /&gt;
| 0201&lt;br /&gt;
| Commodore (Braunschweig)&lt;br /&gt;
|-&lt;br /&gt;
| 514&lt;br /&gt;
| 0202&lt;br /&gt;
| Commodore (West Chester)&lt;br /&gt;
|-&lt;br /&gt;
| 515&lt;br /&gt;
| 0203&lt;br /&gt;
| Commodore (West Chester)&lt;br /&gt;
| Originally registered to Combitech/Macrosystem&lt;br /&gt;
|-&lt;br /&gt;
| 756&lt;br /&gt;
| 02F4&lt;br /&gt;
| Progressive Peripherals &amp;amp; Software&lt;br /&gt;
|-&lt;br /&gt;
| 767&lt;br /&gt;
| 02FF&lt;br /&gt;
| Kolff Computer Supplies&lt;br /&gt;
|-&lt;br /&gt;
| 1001&lt;br /&gt;
| 03E9&lt;br /&gt;
| Tecmar&lt;br /&gt;
|-&lt;br /&gt;
| 1002&lt;br /&gt;
| 03EA&lt;br /&gt;
| Telesys&lt;br /&gt;
|-&lt;br /&gt;
| 1003&lt;br /&gt;
| 03EB&lt;br /&gt;
| The Micro-Forge&lt;br /&gt;
|-&lt;br /&gt;
| 1004&lt;br /&gt;
| 03EC&lt;br /&gt;
| Kronos/C Ltd.&lt;br /&gt;
| Originally registered to Card Co. (Supra)&lt;br /&gt;
|-&lt;br /&gt;
| 1005&lt;br /&gt;
| 03ED&lt;br /&gt;
| A-Squared&lt;br /&gt;
|-&lt;br /&gt;
| 1006&lt;br /&gt;
| 03EE&lt;br /&gt;
| Comspec Communications&lt;br /&gt;
|-&lt;br /&gt;
| 1007&lt;br /&gt;
| 03EF&lt;br /&gt;
| HT Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 1008&lt;br /&gt;
| 03F0&lt;br /&gt;
| RDS Software&lt;br /&gt;
|-&lt;br /&gt;
| 1009&lt;br /&gt;
| 03F1&lt;br /&gt;
| Anakin Research&lt;br /&gt;
|-&lt;br /&gt;
| 1010&lt;br /&gt;
| 03F2&lt;br /&gt;
| MicroBotics&lt;br /&gt;
|-&lt;br /&gt;
| 1011&lt;br /&gt;
| 03F3&lt;br /&gt;
| Bob Krauth&lt;br /&gt;
|-&lt;br /&gt;
| 1012&lt;br /&gt;
| 03F4&lt;br /&gt;
| Access Associates (Alegra)&lt;br /&gt;
|-&lt;br /&gt;
| 1013&lt;br /&gt;
| 03F5&lt;br /&gt;
| Mini Comp Systems Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 1014&lt;br /&gt;
| 03F6&lt;br /&gt;
| Cypress Technology&lt;br /&gt;
|-&lt;br /&gt;
| 1015&lt;br /&gt;
| 03F7&lt;br /&gt;
| Fuller Computers&lt;br /&gt;
|-&lt;br /&gt;
| 1016&lt;br /&gt;
| 03F8&lt;br /&gt;
| Galaxy Computers&lt;br /&gt;
|-&lt;br /&gt;
| 1017&lt;br /&gt;
| 03F9&lt;br /&gt;
| ADA Research&lt;br /&gt;
|-&lt;br /&gt;
| 1018&lt;br /&gt;
| 03FA&lt;br /&gt;
| Computer Service Italia&lt;br /&gt;
|-&lt;br /&gt;
| 1019&lt;br /&gt;
| 03FB&lt;br /&gt;
| Amigo&lt;br /&gt;
|-&lt;br /&gt;
| 1020&lt;br /&gt;
| 03FC&lt;br /&gt;
| Micro-Solutions Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1021&lt;br /&gt;
| 03FD&lt;br /&gt;
| Stacar International&lt;br /&gt;
|-&lt;br /&gt;
| 1022&lt;br /&gt;
| 03FE&lt;br /&gt;
| Video Precisions&lt;br /&gt;
|-&lt;br /&gt;
| 1023&lt;br /&gt;
| 03FF&lt;br /&gt;
| ASDG, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1025&lt;br /&gt;
| 0401&lt;br /&gt;
| Ing. Buero Kalawsky&lt;br /&gt;
|-&lt;br /&gt;
| 1026&lt;br /&gt;
| 0402&lt;br /&gt;
| Computer Tuning&lt;br /&gt;
|-&lt;br /&gt;
| 1027&lt;br /&gt;
| 0403&lt;br /&gt;
| Interplan Unternehmensberatung&lt;br /&gt;
|-&lt;br /&gt;
| 1028&lt;br /&gt;
| 0404&lt;br /&gt;
| Imtronics/Memphis&lt;br /&gt;
| Originally registered to Peter Ohlich&lt;br /&gt;
|-&lt;br /&gt;
| 1030&lt;br /&gt;
| 0406&lt;br /&gt;
| Commodore (Lowell University)&lt;br /&gt;
| Originally registered to Productivity Center&lt;br /&gt;
|-&lt;br /&gt;
| 1041&lt;br /&gt;
| 0411&lt;br /&gt;
| Design Labs&lt;br /&gt;
|-&lt;br /&gt;
| 1042&lt;br /&gt;
| 0412&lt;br /&gt;
| MCS&lt;br /&gt;
|-&lt;br /&gt;
| 1043&lt;br /&gt;
| 0413&lt;br /&gt;
| B. J. Freeman&lt;br /&gt;
|-&lt;br /&gt;
| 1044&lt;br /&gt;
| 0414&lt;br /&gt;
| Side Effects Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1045&lt;br /&gt;
| 0415&lt;br /&gt;
| Oklahoma Personal Comp.&lt;br /&gt;
|-&lt;br /&gt;
| 1046&lt;br /&gt;
| 0416&lt;br /&gt;
| Advanced Micro Innovations&lt;br /&gt;
|-&lt;br /&gt;
| 1047&lt;br /&gt;
| 0417&lt;br /&gt;
| Industrial Support Services&lt;br /&gt;
|-&lt;br /&gt;
| 1048&lt;br /&gt;
| 0418&lt;br /&gt;
| Technisoft&lt;br /&gt;
|-&lt;br /&gt;
| 1049&lt;br /&gt;
| 0419&lt;br /&gt;
| Prolific, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1050&lt;br /&gt;
| 041A&lt;br /&gt;
| Softeam, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1051&lt;br /&gt;
| 041B&lt;br /&gt;
| GRC Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 1052&lt;br /&gt;
| 041C&lt;br /&gt;
| David Lai&lt;br /&gt;
|-&lt;br /&gt;
| 1053&lt;br /&gt;
| 041D&lt;br /&gt;
| Ameristar Technologies&lt;br /&gt;
|-&lt;br /&gt;
| 1054&lt;br /&gt;
| 041E&lt;br /&gt;
| Cline Refrigeration&lt;br /&gt;
|-&lt;br /&gt;
| 1055&lt;br /&gt;
| 041F&lt;br /&gt;
| Cardiac Pacemakers, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1056&lt;br /&gt;
| 0420&lt;br /&gt;
| Supra Corp. (Creative Microsystems)&lt;br /&gt;
|-&lt;br /&gt;
| 1057&lt;br /&gt;
| 0421&lt;br /&gt;
| Wayne Diener&lt;br /&gt;
|-&lt;br /&gt;
| 1058&lt;br /&gt;
| 0422&lt;br /&gt;
| Computer Systems Associates (CSA)&lt;br /&gt;
|-&lt;br /&gt;
| 1059&lt;br /&gt;
| 0423&lt;br /&gt;
| Trionix, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1060&lt;br /&gt;
| 0424&lt;br /&gt;
| David Lucas&lt;br /&gt;
|-&lt;br /&gt;
| 1061&lt;br /&gt;
| 0425&lt;br /&gt;
| Analog Precision&lt;br /&gt;
| Also assigned to D &amp;amp; L Distributing&lt;br /&gt;
|-&lt;br /&gt;
| 1267&lt;br /&gt;
| 04F3&lt;br /&gt;
| RBM Digitaltechnik&lt;br /&gt;
|-&lt;br /&gt;
| 1282&lt;br /&gt;
| 0502&lt;br /&gt;
| M-TEC Hardware Design&lt;br /&gt;
|-&lt;br /&gt;
| 1337&lt;br /&gt;
| 0539&lt;br /&gt;
| Thomas Stenzel (DaFR34K)&lt;br /&gt;
|-&lt;br /&gt;
| 1576&lt;br /&gt;
| 0628&lt;br /&gt;
| Boris Križma&lt;br /&gt;
|-&lt;br /&gt;
| 1761&lt;br /&gt;
| 06E1&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
|-&lt;br /&gt;
| 1803&lt;br /&gt;
| 070B&lt;br /&gt;
| UAE Amiga Emulator&lt;br /&gt;
|-&lt;br /&gt;
| 2002&lt;br /&gt;
| 07D2&lt;br /&gt;
| Mimetics Corp.&lt;br /&gt;
|-&lt;br /&gt;
| 2003&lt;br /&gt;
| 07D3&lt;br /&gt;
| ACDA&lt;br /&gt;
|-&lt;br /&gt;
| 2004&lt;br /&gt;
| 07D4&lt;br /&gt;
| Finn R. Jacobsen&lt;br /&gt;
|-&lt;br /&gt;
| 2005&lt;br /&gt;
| 07D5&lt;br /&gt;
| Elthen Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2006&lt;br /&gt;
| 07D6&lt;br /&gt;
| Nine Tiles Computer Systems Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2007&lt;br /&gt;
| 07D7&lt;br /&gt;
| Analog Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2008&lt;br /&gt;
| 07D8&lt;br /&gt;
| Bell &amp;amp;amp; Howell&lt;br /&gt;
|-&lt;br /&gt;
| 2009&lt;br /&gt;
| 07D9&lt;br /&gt;
| Roland Kochler&lt;br /&gt;
|-&lt;br /&gt;
| 2010&lt;br /&gt;
| 07DA&lt;br /&gt;
| Byte Corp.&lt;br /&gt;
|-&lt;br /&gt;
| 2011&lt;br /&gt;
| 07DB&lt;br /&gt;
| Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 2012&lt;br /&gt;
| 07DC&lt;br /&gt;
| DKB, Inc.&lt;br /&gt;
| Previously named Michigan Software&lt;br /&gt;
|-&lt;br /&gt;
| 2013&lt;br /&gt;
| 07DD&lt;br /&gt;
| Pacific Peripherals&lt;br /&gt;
|-&lt;br /&gt;
| 2014&lt;br /&gt;
| 07DE&lt;br /&gt;
| Sysaphus Software&lt;br /&gt;
|-&lt;br /&gt;
| 2015&lt;br /&gt;
| 07DF&lt;br /&gt;
| Digitronics&lt;br /&gt;
|-&lt;br /&gt;
| 2016&lt;br /&gt;
| 07E0&lt;br /&gt;
| Akron Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2017&lt;br /&gt;
| 07E1&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
|-&lt;br /&gt;
| 2018&lt;br /&gt;
| 07E2&lt;br /&gt;
| Calmos&lt;br /&gt;
|-&lt;br /&gt;
| 2019&lt;br /&gt;
| 07E3&lt;br /&gt;
| Dover Research&lt;br /&gt;
|-&lt;br /&gt;
| 2020&lt;br /&gt;
| 07E4&lt;br /&gt;
| David Krehbiel&lt;br /&gt;
|-&lt;br /&gt;
| 2021&lt;br /&gt;
| 07E5&lt;br /&gt;
| Synergy Peripheral Systems&lt;br /&gt;
| Also known as California Access&lt;br /&gt;
|-&lt;br /&gt;
| 2022&lt;br /&gt;
| 07E6&lt;br /&gt;
| Xetec&lt;br /&gt;
|-&lt;br /&gt;
| 2023&lt;br /&gt;
| 07E7&lt;br /&gt;
| Micron Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2024&lt;br /&gt;
| 07E8&lt;br /&gt;
| CH Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2025&lt;br /&gt;
| 07E9&lt;br /&gt;
| American Liquid Light&lt;br /&gt;
|-&lt;br /&gt;
| 2026&lt;br /&gt;
| 07EA&lt;br /&gt;
| Progressive Peripherals &amp;amp;amp; Software&lt;br /&gt;
| Also used by Ateo&lt;br /&gt;
|-&lt;br /&gt;
| 2027&lt;br /&gt;
| 07EB&lt;br /&gt;
| Wicat Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2028&lt;br /&gt;
| 07EC&lt;br /&gt;
| Applied Systems &amp;amp;amp; Peripherals&lt;br /&gt;
|-&lt;br /&gt;
| 2029&lt;br /&gt;
| 07ED&lt;br /&gt;
| Delaware Valley Software&lt;br /&gt;
|-&lt;br /&gt;
| 2030&lt;br /&gt;
| 07EE&lt;br /&gt;
| Palomax&lt;br /&gt;
|-&lt;br /&gt;
| 2031&lt;br /&gt;
| 07EF&lt;br /&gt;
| Incognito Software&lt;br /&gt;
|-&lt;br /&gt;
| 2032&lt;br /&gt;
| 07F0&lt;br /&gt;
| Jadesign&lt;br /&gt;
|-&lt;br /&gt;
| 2033&lt;br /&gt;
| 07F1&lt;br /&gt;
| BVR&lt;br /&gt;
|-&lt;br /&gt;
| 2034&lt;br /&gt;
| 07F2&lt;br /&gt;
| Spirit Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2035&lt;br /&gt;
| 07F3&lt;br /&gt;
| Spirit Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2036&lt;br /&gt;
| 07F4&lt;br /&gt;
| Atronic&lt;br /&gt;
|-&lt;br /&gt;
| 2037&lt;br /&gt;
| 07F5&lt;br /&gt;
| Scott Karlin&lt;br /&gt;
|-&lt;br /&gt;
| 2038&lt;br /&gt;
| 07F6&lt;br /&gt;
| Howitch&lt;br /&gt;
|-&lt;br /&gt;
| 2039&lt;br /&gt;
| 07F7&lt;br /&gt;
| Sullivan Brothers Visual Engineers&lt;br /&gt;
|-&lt;br /&gt;
| 2040&lt;br /&gt;
| 07F8&lt;br /&gt;
| G I T&lt;br /&gt;
|-&lt;br /&gt;
| 2041&lt;br /&gt;
| 07F9&lt;br /&gt;
| Amigo Business Computers&lt;br /&gt;
|-&lt;br /&gt;
| 2042&lt;br /&gt;
| 07FA&lt;br /&gt;
| Micro E Ab&lt;br /&gt;
|-&lt;br /&gt;
| 2043&lt;br /&gt;
| 07FB&lt;br /&gt;
| Ralph Kruse&lt;br /&gt;
|-&lt;br /&gt;
| 2044&lt;br /&gt;
| 07FC&lt;br /&gt;
| Clearpoint Research&lt;br /&gt;
|-&lt;br /&gt;
| 2045&lt;br /&gt;
| 07FD&lt;br /&gt;
| Kodiak&lt;br /&gt;
|-&lt;br /&gt;
| 2046&lt;br /&gt;
| 07FE&lt;br /&gt;
| BSC&lt;br /&gt;
| Originally registered to Phoenix Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2047&lt;br /&gt;
| 07FF&lt;br /&gt;
| No Name Shown&lt;br /&gt;
|-&lt;br /&gt;
| 2048&lt;br /&gt;
| 0800&lt;br /&gt;
| Commodore Braunschweig&lt;br /&gt;
|-&lt;br /&gt;
| 2049&lt;br /&gt;
| 0801&lt;br /&gt;
| BSC&lt;br /&gt;
| Originally registered to Elaborate Bytes&lt;br /&gt;
|-&lt;br /&gt;
| 2050&lt;br /&gt;
| 0802&lt;br /&gt;
| Kronos/C Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2051&lt;br /&gt;
| 0803&lt;br /&gt;
| Spartanics&lt;br /&gt;
|-&lt;br /&gt;
| 2052&lt;br /&gt;
| 0804&lt;br /&gt;
| Jochheim Computer Tuning&lt;br /&gt;
|-&lt;br /&gt;
| 2053&lt;br /&gt;
| 0805&lt;br /&gt;
| Trans Data Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2054&lt;br /&gt;
| 0806&lt;br /&gt;
| Applied Systems &amp;amp;amp; Peripherals Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2055&lt;br /&gt;
| 0807&lt;br /&gt;
| Checkpoint Technologies&lt;br /&gt;
| Originally registered to Amiga Solutions&lt;br /&gt;
|-&lt;br /&gt;
| 2056&lt;br /&gt;
| 0808&lt;br /&gt;
| Adept Development&lt;br /&gt;
|-&lt;br /&gt;
| 2057&lt;br /&gt;
| 0809&lt;br /&gt;
| Advanced Computer Design&lt;br /&gt;
|-&lt;br /&gt;
| 2058&lt;br /&gt;
| 080A&lt;br /&gt;
| Sir Netics&lt;br /&gt;
|-&lt;br /&gt;
| 2059&lt;br /&gt;
| 080B&lt;br /&gt;
| Expert Services&lt;br /&gt;
|-&lt;br /&gt;
| 2060&lt;br /&gt;
| 080C&lt;br /&gt;
| Digital Art Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2061&lt;br /&gt;
| 080D&lt;br /&gt;
| Adept Development&lt;br /&gt;
|-&lt;br /&gt;
| 2062&lt;br /&gt;
| 080E&lt;br /&gt;
| Expansion Technologies (Expansion Systems)&lt;br /&gt;
|-&lt;br /&gt;
| 2063&lt;br /&gt;
| 080F&lt;br /&gt;
| Alphatech&lt;br /&gt;
|-&lt;br /&gt;
| 2064&lt;br /&gt;
| 0810&lt;br /&gt;
| Edotronik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2065&lt;br /&gt;
| 0811&lt;br /&gt;
| California Access/Synergy&lt;br /&gt;
| Originally registered to Logical Design Works&lt;br /&gt;
|-&lt;br /&gt;
| 2066&lt;br /&gt;
| 0812&lt;br /&gt;
| Bowden, Williams, Full &amp;amp; Assoc.&lt;br /&gt;
|-&lt;br /&gt;
| 2067&lt;br /&gt;
| 0813&lt;br /&gt;
| NES, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2068&lt;br /&gt;
| 0814&lt;br /&gt;
| Amdev&lt;br /&gt;
|-&lt;br /&gt;
| 2069&lt;br /&gt;
| 0815&lt;br /&gt;
| Big Brother Security Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2070&lt;br /&gt;
| 0816&lt;br /&gt;
| Active Circuits Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2071&lt;br /&gt;
| 0817&lt;br /&gt;
| ICD, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2072&lt;br /&gt;
| 0818&lt;br /&gt;
| Multi-Meg Electronique&lt;br /&gt;
|-&lt;br /&gt;
| 2073&lt;br /&gt;
| 0819&lt;br /&gt;
| Kupke Computertechnik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2074&lt;br /&gt;
| 081A&lt;br /&gt;
| The Checkered Ball&lt;br /&gt;
|-&lt;br /&gt;
| 2075&lt;br /&gt;
| 081B&lt;br /&gt;
| Hi Tension Computer Services Ltd. (UK)&lt;br /&gt;
|-&lt;br /&gt;
| 2076&lt;br /&gt;
| 081C&lt;br /&gt;
| Alfa Data&lt;br /&gt;
| Originally assigned to Elmtech Research, Ltd. (UK)&lt;br /&gt;
|-&lt;br /&gt;
| 2077&lt;br /&gt;
| 081D&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
| Originally registered to Clartscreen, Ltd. (UK)&lt;br /&gt;
|-&lt;br /&gt;
| 2078&lt;br /&gt;
| 081E&lt;br /&gt;
| Interworks&lt;br /&gt;
|-&lt;br /&gt;
| 2079&lt;br /&gt;
| 081F&lt;br /&gt;
| Galysh Enterprises&lt;br /&gt;
|-&lt;br /&gt;
| 2080&lt;br /&gt;
| 0820&lt;br /&gt;
| Hardital Synthesis&lt;br /&gt;
| Originally registered to Realtime Games Software Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2081&lt;br /&gt;
| 0821&lt;br /&gt;
| GBS&lt;br /&gt;
|-&lt;br /&gt;
| 2082&lt;br /&gt;
| 0822&lt;br /&gt;
| Circum Design Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2083&lt;br /&gt;
| 0823&lt;br /&gt;
| Alberta Micro Electronic Center&lt;br /&gt;
|-&lt;br /&gt;
| 2084&lt;br /&gt;
| 0824&lt;br /&gt;
| Bestech&lt;br /&gt;
|-&lt;br /&gt;
| 2085&lt;br /&gt;
| 0825&lt;br /&gt;
| Lasar Fantasy&lt;br /&gt;
|-&lt;br /&gt;
| 2086&lt;br /&gt;
| 0826&lt;br /&gt;
| Pulsar&lt;br /&gt;
|-&lt;br /&gt;
| 2087&lt;br /&gt;
| 0827&lt;br /&gt;
| Ivis&lt;br /&gt;
|-&lt;br /&gt;
| 2088&lt;br /&gt;
| 0828&lt;br /&gt;
| Applied Engineering&lt;br /&gt;
|-&lt;br /&gt;
| 2089&lt;br /&gt;
| 0829&lt;br /&gt;
| Solid-State Design &amp;amp;amp; Development&lt;br /&gt;
|-&lt;br /&gt;
| 2090&lt;br /&gt;
| 082A&lt;br /&gt;
| Vison Quest&lt;br /&gt;
|-&lt;br /&gt;
| 2091&lt;br /&gt;
| 082B&lt;br /&gt;
| Seaview Software&lt;br /&gt;
|-&lt;br /&gt;
| 2092&lt;br /&gt;
| 082C&lt;br /&gt;
| BSC&lt;br /&gt;
| Mistakenly used by ADS (Advanced Development Software)&lt;br /&gt;
|-&lt;br /&gt;
| 2093&lt;br /&gt;
| 082D&lt;br /&gt;
| Bernd Culenfeld&lt;br /&gt;
|-&lt;br /&gt;
| 2094&lt;br /&gt;
| 082E&lt;br /&gt;
| American Liquid Light&lt;br /&gt;
|-&lt;br /&gt;
| 2095&lt;br /&gt;
| 082F&lt;br /&gt;
| CEGITES&lt;br /&gt;
|-&lt;br /&gt;
| 2096&lt;br /&gt;
| 0830&lt;br /&gt;
| Quadlite Computers Ltd.&lt;br /&gt;
| Originally registered to EV Industries&lt;br /&gt;
|-&lt;br /&gt;
| 2097&lt;br /&gt;
| 0831&lt;br /&gt;
| Silicon Peace&lt;br /&gt;
|-&lt;br /&gt;
| 2098&lt;br /&gt;
| 0832&lt;br /&gt;
| Black Belt Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2099&lt;br /&gt;
| 0833&lt;br /&gt;
| Village Tronic&lt;br /&gt;
| Originally registerd to Steve Yaeger&lt;br /&gt;
|-&lt;br /&gt;
| 2100&lt;br /&gt;
| 0834&lt;br /&gt;
| ReadySoft&lt;br /&gt;
|-&lt;br /&gt;
| 2101&lt;br /&gt;
| 0835&lt;br /&gt;
| Phoenix Micro Technologies&lt;br /&gt;
|-&lt;br /&gt;
| 2102&lt;br /&gt;
| 0836&lt;br /&gt;
| Advanced Systems &amp;amp; Software&lt;br /&gt;
| Orignally assigned to Preferred Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2103&lt;br /&gt;
| 0837&lt;br /&gt;
| Rombo Productions&lt;br /&gt;
|-&lt;br /&gt;
| 2104&lt;br /&gt;
| 0838&lt;br /&gt;
| Impulse Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2105&lt;br /&gt;
| 0839&lt;br /&gt;
| Beta Unlimited&lt;br /&gt;
|-&lt;br /&gt;
| 2106&lt;br /&gt;
| 083A&lt;br /&gt;
| Memory Expansion System, Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2107&lt;br /&gt;
| 083B&lt;br /&gt;
| Vortex Computer Systems GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2108&lt;br /&gt;
| 083C&lt;br /&gt;
| Platypus Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2109&lt;br /&gt;
| 083D&lt;br /&gt;
| Gigatron OHG&lt;br /&gt;
|-&lt;br /&gt;
| 2110&lt;br /&gt;
| 083E&lt;br /&gt;
| PG Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2111&lt;br /&gt;
| 083F&lt;br /&gt;
| New Technologies Group&lt;br /&gt;
|-&lt;br /&gt;
| 2112&lt;br /&gt;
| 0840&lt;br /&gt;
| Interactive Video Systems (IVS)&lt;br /&gt;
| Pacific Peripherals&lt;br /&gt;
|-&lt;br /&gt;
| 2113&lt;br /&gt;
| 0841&lt;br /&gt;
| Vector&lt;br /&gt;
| Originally registered to H. K. Computer&lt;br /&gt;
|-&lt;br /&gt;
| 2114&lt;br /&gt;
| 0842&lt;br /&gt;
| Pacific Digital&lt;br /&gt;
| Originally registered to C. H. Helfrich Elektronik&lt;br /&gt;
|-&lt;br /&gt;
| 2115&lt;br /&gt;
| 0843&lt;br /&gt;
| Xanadu&lt;br /&gt;
|-&lt;br /&gt;
| 2116&lt;br /&gt;
| 0844&lt;br /&gt;
| Pacific Digital&lt;br /&gt;
| Originally registered to AMS&lt;br /&gt;
|-&lt;br /&gt;
| 2117&lt;br /&gt;
| 0845&lt;br /&gt;
| X-Pert&lt;br /&gt;
|-&lt;br /&gt;
| 2118&lt;br /&gt;
| 0846&lt;br /&gt;
| The Amiga Centre&lt;br /&gt;
|-&lt;br /&gt;
| 2119&lt;br /&gt;
| 0847&lt;br /&gt;
| Digital Pacific&lt;br /&gt;
|-&lt;br /&gt;
| 2120&lt;br /&gt;
| 0848&lt;br /&gt;
| Solid State Leisure&lt;br /&gt;
|-&lt;br /&gt;
| 2121&lt;br /&gt;
| 0849&lt;br /&gt;
| Hydra Systems&lt;br /&gt;
| Originally registered to Analog Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2122&lt;br /&gt;
| 084A&lt;br /&gt;
| Cumana&lt;br /&gt;
|-&lt;br /&gt;
| 2123&lt;br /&gt;
| 084B&lt;br /&gt;
| KAPS 2C Conception&lt;br /&gt;
|-&lt;br /&gt;
| 2124&lt;br /&gt;
| 084C&lt;br /&gt;
| Mike Mason&lt;br /&gt;
|-&lt;br /&gt;
| 2125&lt;br /&gt;
| 084D&lt;br /&gt;
| For Your Eyes&lt;br /&gt;
|-&lt;br /&gt;
| 2126&lt;br /&gt;
| 084E&lt;br /&gt;
| Volkmar Breitfeld Computersysteme&lt;br /&gt;
|-&lt;br /&gt;
| 2127&lt;br /&gt;
| 084F&lt;br /&gt;
| Sunrize Industries&lt;br /&gt;
|-&lt;br /&gt;
| 2128&lt;br /&gt;
| 0850&lt;br /&gt;
| Scott Advanced Micro Designs&lt;br /&gt;
|-&lt;br /&gt;
| 2129&lt;br /&gt;
| 0851&lt;br /&gt;
| Digital Micronics&lt;br /&gt;
|-&lt;br /&gt;
| 2130&lt;br /&gt;
| 0852&lt;br /&gt;
| Alfa-Laval&lt;br /&gt;
|-&lt;br /&gt;
| 2131&lt;br /&gt;
| 0853&lt;br /&gt;
| Multigros A/S&lt;br /&gt;
|-&lt;br /&gt;
| 2132&lt;br /&gt;
| 0854&lt;br /&gt;
| Archos&lt;br /&gt;
|-&lt;br /&gt;
| 2133&lt;br /&gt;
| 0855&lt;br /&gt;
| Icom Simulations&lt;br /&gt;
|-&lt;br /&gt;
| 2134&lt;br /&gt;
| 0856&lt;br /&gt;
| Commodore Test Engineering Group&lt;br /&gt;
|-&lt;br /&gt;
| 2135&lt;br /&gt;
| 0857&lt;br /&gt;
| Microcreations&lt;br /&gt;
|-&lt;br /&gt;
| 2136&lt;br /&gt;
| 0858&lt;br /&gt;
| Shoestring Productions&lt;br /&gt;
|-&lt;br /&gt;
| 2137&lt;br /&gt;
| 0859&lt;br /&gt;
| Faberushi&lt;br /&gt;
|-&lt;br /&gt;
| 2138&lt;br /&gt;
| 085A&lt;br /&gt;
| Evesham Micro Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2139&lt;br /&gt;
| 085B&lt;br /&gt;
| Panagolin Laser Software&lt;br /&gt;
|-&lt;br /&gt;
| 2140&lt;br /&gt;
| 085C&lt;br /&gt;
| Thomas Rudloff&lt;br /&gt;
|-&lt;br /&gt;
| 2141&lt;br /&gt;
| 085D&lt;br /&gt;
| Daniel Hohabir&lt;br /&gt;
|-&lt;br /&gt;
| 2142&lt;br /&gt;
| 085E&lt;br /&gt;
| GfxBase, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2143&lt;br /&gt;
| 085F&lt;br /&gt;
| Axellabs&lt;br /&gt;
|-&lt;br /&gt;
| 2144&lt;br /&gt;
| 0860&lt;br /&gt;
| Roctec Electronics Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2145&lt;br /&gt;
| 0861&lt;br /&gt;
| Omega Datentechnik&lt;br /&gt;
|-&lt;br /&gt;
| 2146&lt;br /&gt;
| 0862&lt;br /&gt;
| Atlantis&lt;br /&gt;
|-&lt;br /&gt;
| 2147&lt;br /&gt;
| 0863&lt;br /&gt;
| Skytec Computers&lt;br /&gt;
|-&lt;br /&gt;
| 2148&lt;br /&gt;
| 0864&lt;br /&gt;
| Protar Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2149&lt;br /&gt;
| 0865&lt;br /&gt;
| ACS&lt;br /&gt;
|-&lt;br /&gt;
| 2150&lt;br /&gt;
| 0866&lt;br /&gt;
| Software Results Enterprises&lt;br /&gt;
| Originally registered to University of Illinois&lt;br /&gt;
|-&lt;br /&gt;
| 2151&lt;br /&gt;
| 0867&lt;br /&gt;
| Infinity Systems Design Group&lt;br /&gt;
|-&lt;br /&gt;
| 2152&lt;br /&gt;
| 0868&lt;br /&gt;
| Trade It&lt;br /&gt;
|-&lt;br /&gt;
| 2153&lt;br /&gt;
| 0869&lt;br /&gt;
| Suntec, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2154&lt;br /&gt;
| 086A&lt;br /&gt;
| DJW Micro Systems&lt;br /&gt;
| Originally registered to Tritec Marketing&lt;br /&gt;
|-&lt;br /&gt;
| 2155&lt;br /&gt;
| 086B&lt;br /&gt;
| Power Computing Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2156&lt;br /&gt;
| 086C&lt;br /&gt;
| MacroSystems&lt;br /&gt;
|-&lt;br /&gt;
| 2157&lt;br /&gt;
| 086D&lt;br /&gt;
| Masoboshi GmbH (DCE)&lt;br /&gt;
|-&lt;br /&gt;
| 2158&lt;br /&gt;
| 086E&lt;br /&gt;
| HAL Software Hardware Handel&lt;br /&gt;
|-&lt;br /&gt;
| 2159&lt;br /&gt;
| 086F&lt;br /&gt;
| Mainhattan Data&lt;br /&gt;
| Originally registered to Michael Lamm Computersysteme&lt;br /&gt;
|-&lt;br /&gt;
| 2160&lt;br /&gt;
| 0870&lt;br /&gt;
| Digital Processing System&lt;br /&gt;
| Originally registered to bbdp Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2161&lt;br /&gt;
| 0871&lt;br /&gt;
| Blue Ribbon Soundworks&lt;br /&gt;
| Originally registered to Design Computer Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2162&lt;br /&gt;
| 0872&lt;br /&gt;
| XPert&lt;br /&gt;
| Originally registered to The Station&lt;br /&gt;
|-&lt;br /&gt;
| 2163&lt;br /&gt;
| 0873&lt;br /&gt;
| DelaComp&lt;br /&gt;
| Originally registered to Bryan Williams&lt;br /&gt;
|-&lt;br /&gt;
| 2164&lt;br /&gt;
| 0874&lt;br /&gt;
| Superformance Computer Engineering GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2165&lt;br /&gt;
| 0875&lt;br /&gt;
| Overland Engineering&lt;br /&gt;
|-&lt;br /&gt;
| 2166&lt;br /&gt;
| 0876&lt;br /&gt;
| Thomas Hamren&lt;br /&gt;
|-&lt;br /&gt;
| 2167&lt;br /&gt;
| 0877&lt;br /&gt;
| Village Tronic&lt;br /&gt;
|-&lt;br /&gt;
| 2168&lt;br /&gt;
| 0878&lt;br /&gt;
| Toolbox Design&lt;br /&gt;
|-&lt;br /&gt;
| 2169&lt;br /&gt;
| 0879&lt;br /&gt;
| Digital Processing System&lt;br /&gt;
|-&lt;br /&gt;
| 2170&lt;br /&gt;
| 087A&lt;br /&gt;
| Superformance&lt;br /&gt;
|-&lt;br /&gt;
| 2171&lt;br /&gt;
| 087B&lt;br /&gt;
| Utilities Unlimited&lt;br /&gt;
|-&lt;br /&gt;
| 2172&lt;br /&gt;
| 087C&lt;br /&gt;
| phase 5&lt;br /&gt;
|-&lt;br /&gt;
| 2173&lt;br /&gt;
| 087D&lt;br /&gt;
| Juergen Kommos&lt;br /&gt;
|-&lt;br /&gt;
| 2174&lt;br /&gt;
| 087E&lt;br /&gt;
| Electronic Design&lt;br /&gt;
|-&lt;br /&gt;
| 2175&lt;br /&gt;
| 087F&lt;br /&gt;
| James Cook University of North Queensland&lt;br /&gt;
|-&lt;br /&gt;
| 2176&lt;br /&gt;
| 0880&lt;br /&gt;
| AmiTrix Development&lt;br /&gt;
|-&lt;br /&gt;
| 2177&lt;br /&gt;
| 0881&lt;br /&gt;
| Ferranti&lt;br /&gt;
|-&lt;br /&gt;
| 2178&lt;br /&gt;
| 0882&lt;br /&gt;
| Leviathan Development&lt;br /&gt;
|-&lt;br /&gt;
| 2179&lt;br /&gt;
| 0883&lt;br /&gt;
| United Video Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2180&lt;br /&gt;
| 0884&lt;br /&gt;
| GPSoft Pty. Ltd.&lt;br /&gt;
| Originally registered to Juergen Kommos&lt;br /&gt;
|-&lt;br /&gt;
| 2181&lt;br /&gt;
| 0885&lt;br /&gt;
| ArMAX&lt;br /&gt;
| Oliver Bausch&lt;br /&gt;
|-&lt;br /&gt;
| 2182&lt;br /&gt;
| 0886&lt;br /&gt;
| CP Computer&lt;br /&gt;
|-&lt;br /&gt;
| 2183&lt;br /&gt;
| 0887&lt;br /&gt;
| AMOK - Amiga Module &amp;amp;amp; Oberon Klub&lt;br /&gt;
|-&lt;br /&gt;
| 2184&lt;br /&gt;
| 0888&lt;br /&gt;
| ITEK Neser &amp;amp;amp; Sieber GbR&lt;br /&gt;
|-&lt;br /&gt;
| 2185&lt;br /&gt;
| 0889&lt;br /&gt;
| Phillip C. Lello&lt;br /&gt;
|-&lt;br /&gt;
| 2186&lt;br /&gt;
| 088A&lt;br /&gt;
| Cyborg Design Services&lt;br /&gt;
|-&lt;br /&gt;
| 2187&lt;br /&gt;
| 088B&lt;br /&gt;
| G2 Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2188&lt;br /&gt;
| 088C&lt;br /&gt;
| Pro System Computersysteme&lt;br /&gt;
|-&lt;br /&gt;
| 2189&lt;br /&gt;
| 088D&lt;br /&gt;
| ZEUS Electronic&lt;br /&gt;
| Originally registered to MSPI (Markt &amp;amp;amp; Technik)&lt;br /&gt;
|-&lt;br /&gt;
| 2190&lt;br /&gt;
| 088E&lt;br /&gt;
| Altatech&lt;br /&gt;
|-&lt;br /&gt;
| 2191&lt;br /&gt;
| 088F&lt;br /&gt;
| NewTek&lt;br /&gt;
|-&lt;br /&gt;
| 2192&lt;br /&gt;
| 0890&lt;br /&gt;
| M-TEC Hardware Design&lt;br /&gt;
| Originally registered to Hardware Design Udo Neuroth&lt;br /&gt;
|-&lt;br /&gt;
| 2193&lt;br /&gt;
| 0891&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
| Originally registered to Viona Development&lt;br /&gt;
|-&lt;br /&gt;
| 2194&lt;br /&gt;
| 0892&lt;br /&gt;
| Amitek&lt;br /&gt;
| Originally assigned to Marpet Developments&lt;br /&gt;
|-&lt;br /&gt;
| 2195&lt;br /&gt;
| 0893&lt;br /&gt;
| Ingenieurbuero Helfrich&lt;br /&gt;
|-&lt;br /&gt;
| 2196&lt;br /&gt;
| 0894&lt;br /&gt;
| The Neo Group&lt;br /&gt;
|-&lt;br /&gt;
| 2197&lt;br /&gt;
| 0895&lt;br /&gt;
| Cyon&lt;br /&gt;
|-&lt;br /&gt;
| 2198&lt;br /&gt;
| 0896&lt;br /&gt;
| Bob Research Group&lt;br /&gt;
|-&lt;br /&gt;
| 2199&lt;br /&gt;
| 0897&lt;br /&gt;
| Richmond Sound Design Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2200&lt;br /&gt;
| 0898&lt;br /&gt;
| US Cybernetics&lt;br /&gt;
|-&lt;br /&gt;
| 2201&lt;br /&gt;
| 0899&lt;br /&gt;
| Fulvio Ieva&lt;br /&gt;
|-&lt;br /&gt;
| 2202&lt;br /&gt;
| 089A&lt;br /&gt;
| Silicon Studio&lt;br /&gt;
|-&lt;br /&gt;
| 2203&lt;br /&gt;
| 089B&lt;br /&gt;
| MacroSystems (USA)&lt;br /&gt;
| Was named Micro System Devices&lt;br /&gt;
|-&lt;br /&gt;
| 2204&lt;br /&gt;
| 089C&lt;br /&gt;
| Conspector Entertainment&lt;br /&gt;
|-&lt;br /&gt;
| 2205&lt;br /&gt;
| 089D&lt;br /&gt;
| Laserforum&lt;br /&gt;
|-&lt;br /&gt;
| 2206&lt;br /&gt;
| 089E&lt;br /&gt;
| Elbox Computer&lt;br /&gt;
| Mistakenly used by Index Information Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2207&lt;br /&gt;
| 089F&lt;br /&gt;
| Applied Magic Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2208&lt;br /&gt;
| 08A0&lt;br /&gt;
| SDL Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2560&lt;br /&gt;
| 0A00&lt;br /&gt;
| Harms&lt;br /&gt;
|-&lt;br /&gt;
| 2588&lt;br /&gt;
| 0A1C&lt;br /&gt;
| A1K.org Community&lt;br /&gt;
|-&lt;br /&gt;
| 2640&lt;br /&gt;
| 0A50&lt;br /&gt;
| Micronik&lt;br /&gt;
|-&lt;br /&gt;
| 3084&lt;br /&gt;
| 0C0C&lt;br /&gt;
| Team 4&lt;br /&gt;
|-&lt;br /&gt;
| 3643&lt;br /&gt;
| 0E3B&lt;br /&gt;
| E3B&lt;br /&gt;
| Michael Boehmer&lt;br /&gt;
|-&lt;br /&gt;
| 3855&lt;br /&gt;
| 0F0F&lt;br /&gt;
| Micronik&lt;br /&gt;
|-&lt;br /&gt;
| 4096&lt;br /&gt;
| 1000&lt;br /&gt;
| MegaMicro&lt;br /&gt;
|-&lt;br /&gt;
| 4110&lt;br /&gt;
| 100E&lt;br /&gt;
| DigiFeX&lt;br /&gt;
|-&lt;br /&gt;
| 4136&lt;br /&gt;
| 1028&lt;br /&gt;
| Imtronics/Memphis&lt;br /&gt;
|-&lt;br /&gt;
| 4149&lt;br /&gt;
| 1035&lt;br /&gt;
| PROTAR&lt;br /&gt;
|-&lt;br /&gt;
| 4369&lt;br /&gt;
| 1111&lt;br /&gt;
| Frank Strauß Elektronik&lt;br /&gt;
| Also used by Kupke&lt;br /&gt;
|-&lt;br /&gt;
| 4626&lt;br /&gt;
| 1212&lt;br /&gt;
| Individual Computers&lt;br /&gt;
|-&lt;br /&gt;
| 4648&lt;br /&gt;
| 1228&lt;br /&gt;
| Flesch Hornemann Computer Elec.&lt;br /&gt;
|-&lt;br /&gt;
| 4680&lt;br /&gt;
| 1248&lt;br /&gt;
| Kupke Computertechnik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 4711&lt;br /&gt;
| 1267&lt;br /&gt;
| RBM digitaltechnik&lt;br /&gt;
|-&lt;br /&gt;
| 4754&lt;br /&gt;
| 1292&lt;br /&gt;
| MacroSystems&lt;br /&gt;
|-&lt;br /&gt;
| 5000&lt;br /&gt;
| 1388&lt;br /&gt;
| ITH&lt;br /&gt;
|-&lt;br /&gt;
| 5001&lt;br /&gt;
| 1389&lt;br /&gt;
| VMC&lt;br /&gt;
|-&lt;br /&gt;
| 5010&lt;br /&gt;
| 1392&lt;br /&gt;
| Ambience Creation Technology&lt;br /&gt;
|-&lt;br /&gt;
| 5011&lt;br /&gt;
| 1393&lt;br /&gt;
| Creative Development&lt;br /&gt;
|-&lt;br /&gt;
| 5012&lt;br /&gt;
| 1394&lt;br /&gt;
| Georg Braun&lt;br /&gt;
|-&lt;br /&gt;
| 5013&lt;br /&gt;
| 1395&lt;br /&gt;
| Swedish User Group of Amiga&lt;br /&gt;
|-&lt;br /&gt;
| 5014&lt;br /&gt;
| 1396&lt;br /&gt;
| Jakub Bednarski&lt;br /&gt;
|-&lt;br /&gt;
| 5015&lt;br /&gt;
| 1397&lt;br /&gt;
| KryoFlux, Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 5016&lt;br /&gt;
| 1398&lt;br /&gt;
| Igor Majstorovic&lt;br /&gt;
|-&lt;br /&gt;
| 5017&lt;br /&gt;
| 1399&lt;br /&gt;
| Alastair M. Robinson&lt;br /&gt;
|-&lt;br /&gt;
| 5018&lt;br /&gt;
| 139A&lt;br /&gt;
| Austex Software&lt;br /&gt;
|-&lt;br /&gt;
| 5019&lt;br /&gt;
| 139B&lt;br /&gt;
| Sören Gust&lt;br /&gt;
|-&lt;br /&gt;
| 5020&lt;br /&gt;
| 139C&lt;br /&gt;
| Rok Krajnc&lt;br /&gt;
|-&lt;br /&gt;
| 5030&lt;br /&gt;
| 13A6&lt;br /&gt;
| Tim Tashpulatov&lt;br /&gt;
|-&lt;br /&gt;
| 5040&lt;br /&gt;
| 13B0&lt;br /&gt;
| 7-bit&lt;br /&gt;
|-&lt;br /&gt;
| 5050&lt;br /&gt;
| 13BA&lt;br /&gt;
| Sakura IT&lt;br /&gt;
|-&lt;br /&gt;
| 5060&lt;br /&gt;
| 13C4&lt;br /&gt;
| FPGAArcade&lt;br /&gt;
|-&lt;br /&gt;
| 5070&lt;br /&gt;
| 13CE&lt;br /&gt;
| CancerSoft Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 5080&lt;br /&gt;
| 13D8&lt;br /&gt;
| Stephen Leary&lt;br /&gt;
|-&lt;br /&gt;
| 5090&lt;br /&gt;
| 13E2&lt;br /&gt;
| DMA Softlab LLC&lt;br /&gt;
|-&lt;br /&gt;
| 5100&lt;br /&gt;
| 13EC&lt;br /&gt;
| Brookhouse Engineering&lt;br /&gt;
|-&lt;br /&gt;
| 5110&lt;br /&gt;
| 13F6&lt;br /&gt;
| Eduardo Arana&lt;br /&gt;
|-&lt;br /&gt;
| 5120&lt;br /&gt;
| 1400&lt;br /&gt;
| CS-LAB&lt;br /&gt;
|-&lt;br /&gt;
| 5130&lt;br /&gt;
| 140A&lt;br /&gt;
| Robert Miranda&lt;br /&gt;
|-&lt;br /&gt;
| 5140&lt;br /&gt;
| 1414&lt;br /&gt;
| RastPort&lt;br /&gt;
|-&lt;br /&gt;
| 5132&lt;br /&gt;
| 140C&lt;br /&gt;
| UAS Interface Ltd6&lt;br /&gt;
|-&lt;br /&gt;
| 5150&lt;br /&gt;
| 141E&lt;br /&gt;
| Amiga Kit&lt;br /&gt;
|-&lt;br /&gt;
| 5160&lt;br /&gt;
| 1428&lt;br /&gt;
| Central Texas Commodore User Group&lt;br /&gt;
|-&lt;br /&gt;
| 5170&lt;br /&gt;
| 1432&lt;br /&gt;
| Confusion Research Center&lt;br /&gt;
|-&lt;br /&gt;
| 5180&lt;br /&gt;
| 143C&lt;br /&gt;
| Solar Soyuz Zaibatsu&lt;br /&gt;
|-&lt;br /&gt;
| 5500&lt;br /&gt;
| 157C&lt;br /&gt;
| Inhouse Information&lt;br /&gt;
|-&lt;br /&gt;
| 5768&lt;br /&gt;
| 1688&lt;br /&gt;
| Bio Con&lt;br /&gt;
|-&lt;br /&gt;
| 6148&lt;br /&gt;
| 1804&lt;br /&gt;
| HK-Computer&lt;br /&gt;
|-&lt;br /&gt;
| 6502&lt;br /&gt;
| 1966&lt;br /&gt;
| Cloanto&lt;br /&gt;
|-&lt;br /&gt;
| 6520&lt;br /&gt;
| 1978&lt;br /&gt;
| Oliver Gantert&lt;br /&gt;
|-&lt;br /&gt;
| 7777&lt;br /&gt;
| 1E61&lt;br /&gt;
| Rafal Gabriel Chyla&lt;br /&gt;
|-&lt;br /&gt;
| 8215&lt;br /&gt;
| 2017&lt;br /&gt;
| Vortex&lt;br /&gt;
|-&lt;br /&gt;
| 8244&lt;br /&gt;
| 2034&lt;br /&gt;
| Spirit Technology&lt;br /&gt;
|-&lt;br /&gt;
| 8290&lt;br /&gt;
| 2062&lt;br /&gt;
| Expansion Systems&lt;br /&gt;
|-&lt;br /&gt;
| 8448&lt;br /&gt;
| 2100&lt;br /&gt;
| ReadySoft&lt;br /&gt;
|-&lt;br /&gt;
| 8512&lt;br /&gt;
| 2140&lt;br /&gt;
| Phase 5 Digital Products&lt;br /&gt;
|-&lt;br /&gt;
| 8553&lt;br /&gt;
| 2169&lt;br /&gt;
| Digital Processing Systems Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 8704&lt;br /&gt;
| 2200&lt;br /&gt;
| ACT Elektronik&lt;br /&gt;
|-&lt;br /&gt;
| 8738&lt;br /&gt;
| 2222&lt;br /&gt;
| ACT Elektronik&lt;br /&gt;
|-&lt;br /&gt;
| 9512&lt;br /&gt;
| 2528&lt;br /&gt;
| Tower Technologies&lt;br /&gt;
|-&lt;br /&gt;
| 10676&lt;br /&gt;
| 29B4&lt;br /&gt;
| Electronic Design&lt;br /&gt;
|-&lt;br /&gt;
| 14195&lt;br /&gt;
| 3773&lt;br /&gt;
| Media-net-Point&lt;br /&gt;
|-&lt;br /&gt;
| 14501&lt;br /&gt;
| 38A5&lt;br /&gt;
| Petsoff, Finland&lt;br /&gt;
|-&lt;br /&gt;
| 16375&lt;br /&gt;
| 3FF7&lt;br /&gt;
| Uwe Gerlach&lt;br /&gt;
|-&lt;br /&gt;
| 16707&lt;br /&gt;
| 4143&lt;br /&gt;
| Ateo Concepts&lt;br /&gt;
|-&lt;br /&gt;
| 16708&lt;br /&gt;
| 4144&lt;br /&gt;
| ALiENDESiGN&lt;br /&gt;
|-&lt;br /&gt;
| 16945&lt;br /&gt;
| 4231&lt;br /&gt;
| A.C.T.&lt;br /&gt;
|-&lt;br /&gt;
| 17740&lt;br /&gt;
| 454C&lt;br /&gt;
| HK-Computer (ELSAT)&lt;br /&gt;
|-&lt;br /&gt;
| 18260&lt;br /&gt;
| 4754&lt;br /&gt;
| MacroSystems (Germany)&lt;br /&gt;
|-&lt;br /&gt;
| 19796&lt;br /&gt;
| 4D54&lt;br /&gt;
| Markt &amp;amp; Technik&lt;br /&gt;
|-&lt;br /&gt;
| 22359&lt;br /&gt;
| 5757&lt;br /&gt;
| Markt &amp;amp; Technik&lt;br /&gt;
|-&lt;br /&gt;
| 26464&lt;br /&gt;
| 6760&lt;br /&gt;
| Combitec&lt;br /&gt;
|-&lt;br /&gt;
| 26470&lt;br /&gt;
| 6766&lt;br /&gt;
| Combitec&lt;br /&gt;
|-&lt;br /&gt;
| 28014&lt;br /&gt;
| 6D6E&lt;br /&gt;
| MNT Media and Technology UG&lt;br /&gt;
|-&lt;br /&gt;
| 32768&lt;br /&gt;
| 8000&lt;br /&gt;
| M.A.S.T.&lt;br /&gt;
|-&lt;br /&gt;
| 42240&lt;br /&gt;
| A500&lt;br /&gt;
| Aethreum Digital&lt;br /&gt;
|-&lt;br /&gt;
| 43437&lt;br /&gt;
| A9AD&lt;br /&gt;
| Reis-Ware&lt;br /&gt;
|-&lt;br /&gt;
| 43521&lt;br /&gt;
| AA01&lt;br /&gt;
| Cameron&lt;br /&gt;
|-&lt;br /&gt;
| 43537&lt;br /&gt;
| AA11&lt;br /&gt;
| Reis-Ware&lt;br /&gt;
|-&lt;br /&gt;
| 44359&lt;br /&gt;
| AD47&lt;br /&gt;
| Matay&lt;br /&gt;
|-&lt;br /&gt;
| 46504&lt;br /&gt;
| B5A8&lt;br /&gt;
| Phoenix&lt;br /&gt;
|-&lt;br /&gt;
| 48879&lt;br /&gt;
| BEEF&lt;br /&gt;
| Swiss Mountain Dog Products&lt;br /&gt;
|-&lt;br /&gt;
| 49160&lt;br /&gt;
| C008&lt;br /&gt;
| Combitec&lt;br /&gt;
|-&lt;br /&gt;
| 61453&lt;br /&gt;
| F00D&lt;br /&gt;
| Forefront Technologies Inc.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
For any changes/additions to this registry please send a support request to [mailto:support@hyperion-entertainment.com support@hyperion-entertainment.com].&lt;/div&gt;</summary>
		<author><name>Costel Mincea</name></author>
	</entry>
	<entry>
		<id>https://wiki.amigaos.net/w/index.php?title=Amiga_Hardware_Manufacturer_ID_Registry&amp;diff=12594</id>
		<title>Amiga Hardware Manufacturer ID Registry</title>
		<link rel="alternate" type="text/html" href="https://wiki.amigaos.net/w/index.php?title=Amiga_Hardware_Manufacturer_ID_Registry&amp;diff=12594"/>
		<updated>2026-09-08T09:38:33Z</updated>

		<summary type="html">&lt;p&gt;Costel Mincea: Added &amp;quot;Swiss Mountain Dog Products&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
= How to Obtain a Manufacturer Number =&lt;br /&gt;
&lt;br /&gt;
Manufacturer&#039;s numbers are assigned by the AmigaOS development team. To obtain your unique manufacturer number send a support request to [mailto:support@hyperion-entertainment.com support@hyperion-entertainment.com].&lt;br /&gt;
&lt;br /&gt;
Be sure and include your name and the type of expansion product you are developing.&lt;br /&gt;
&lt;br /&gt;
= Your Manufacturer Number =&lt;br /&gt;
&lt;br /&gt;
Attention hardware manufacturers. If you are developing a hardware expansion product for the Classic Amiga (e.g. 500, 2000, 3000) then you will need to obtain a special manufacturer ID number from the AmigaOS development team to identify your product. This manufacturer number is used by the Amiga to link your hardware with its driver software at boot time.&lt;br /&gt;
&lt;br /&gt;
Your manufacturer number is part of the special protocol that the Amiga uses to automatically configure all expansion devices on the bus without the user having to cut jumpers or adjust dip switches. This is called auto-config.&lt;br /&gt;
&lt;br /&gt;
At start-up time, the system first polls each board in the system and assigns the board its own address space. If it is a memory board, its RAM is linked into the memory free pool. Later in the boot sequence, after DOS is initialized, the binddrivers program is run. Binddrivers will search the directory SYS:Expansion for the drivers that go with the boards.&lt;br /&gt;
&lt;br /&gt;
To do this binddrivers looks in the Tool Type field of all icon files in SYS:Expansion. If the first seven bytes of the Tool Type field are &amp;quot;PRODUCT&amp;quot;, then this is an icon file for a driver.&lt;br /&gt;
&lt;br /&gt;
Binddrivers will then attempt to match the drivers it has found with the boards that were found earlier. This is where your manufacturer number comes in.&lt;br /&gt;
&lt;br /&gt;
Your manufacturer number goes in two places. First, it is burned in hex form into the PAL which is part of ALL auto-config expansion products. Second, it appears in ASCII in the Tool Type field of the icon file for your product&#039;s driver. By matching these two numbers, the Amiga can automatically configure your board and bind it&#039;s software driver into the system as well.&lt;br /&gt;
&lt;br /&gt;
The manufacturer&#039;s number is a 16-bit ID which appears in PAL offsets $10-$17. There is also an 8-bit product number which you assign. The product number is for uniquely identifying different products from the same vendor. The product number will appear in PAL offsets $04-$07. This gives you a total of 24 bits to identify each of your products.&lt;br /&gt;
&lt;br /&gt;
These 24 bits of information in the PAL which identify your product are matched against the information in the Tool Type field of all icon files in the SYS:Expansion drawer. For example, suppose you are manufacturer #1019. You have two products, #1 and #2 which both use the same driver. The icon for your driver for these two products would have a Tool Type set to &amp;quot;PRODUCT=1019/1|1019/2&amp;quot;. This means: I am an icon for a driver that works with product number 1 or 2 from manufacturer 1019, now bind me. Spaces are not legal. Here are two other examples:&lt;br /&gt;
&lt;br /&gt;
; PRODUCT=1208/11&lt;br /&gt;
: is the Tool Type for a driver for product 11 from manufacturer number 1208.&lt;br /&gt;
&lt;br /&gt;
; PRODUCT=1017&lt;br /&gt;
: is the Tool Type for a driver for any product from manufacturer number 1017.&lt;br /&gt;
&lt;br /&gt;
For an informal explanation of the auto-configuration process, see the chapter on Software Expansion Architecture from the 2nd Annual Amiga Developer&#039;s Conference Notes (available on ADCD 2.1). For the details of timing, power, the PAL equations and PAL address specifications and the expansion library documentation, see sections 3.1 to 3.3 of the A500/A2000 Technical Reference Manual. The original auto-config spec appears in the A1000 Schematics and Expansion Specification.&lt;br /&gt;
&lt;br /&gt;
The auto-config process makes the addition of expansion products to the system very easy. All the user has to do is put the board in any slot and copy the driver from the release disk to his own SYS:Expansion drawer. Everything else is automatic. There are no jumpers or dip switches to set. Best of all, you will get a lot less support calls asking how to make your product work with the XYZ-Corp-battery-backed-clock.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
&lt;br /&gt;
Some notes on hardware manufacturer ID assignment.&lt;br /&gt;
&lt;br /&gt;
* Manufacturer ID numbers are assigned free of charge.&lt;br /&gt;
* Please provide the following information when requesting an ID:&lt;br /&gt;
*# Name of the company or person&lt;br /&gt;
*# Postal address/contact address&lt;br /&gt;
*# Name of the contact person, with a corresponding e-mail address&lt;br /&gt;
*# A brief description of the kind of products you want to produce&lt;br /&gt;
* All ID numbers smaller than 5000 must be considered unsafe because no information exists on which numbers exactly were taken during the time Commodore, Inc. disintegrated.&lt;br /&gt;
* ID numbers in the range 8192 to 18841 must be considered unsafe because some hardware developers mistook the numbers assigned to them to be given in hexadecimal format. Hence 0x2000 = 8192 and 0x4999 = 18841.&lt;br /&gt;
&lt;br /&gt;
= Example code =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
/*-----------------------------------------------*/&lt;br /&gt;
/* Here is a short program which will tell you   */&lt;br /&gt;
/* about the expansion boards configured in your */&lt;br /&gt;
/* system without you opening up the machine.    */&lt;br /&gt;
/* Code by Bill Koester of CATS                  */&lt;br /&gt;
/*-----------------------------------------------*/&lt;br /&gt;
#include &amp;lt;libraries/configvars.h&amp;gt;&lt;br /&gt;
#include &amp;lt;libraries/expansion.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
struct ExpansionBase *ExpansionBase;&lt;br /&gt;
&lt;br /&gt;
void cleanup();&lt;br /&gt;
void printdev();&lt;br /&gt;
&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
   struct ConfigDev *MyConfigDev;&lt;br /&gt;
&lt;br /&gt;
   /*----------------------------------*/&lt;br /&gt;
   /* Open the expansion library,      */&lt;br /&gt;
   /* if there is a problem then exit  */&lt;br /&gt;
   /*----------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   ExpansionBase =(struct ExpansionBase *) OpenLibrary(EXPANSIONNAME,0);&lt;br /&gt;
   if(ExpansionBase==NULL)&lt;br /&gt;
   {&lt;br /&gt;
      printf(&amp;quot;Error opening expansion library!!\n&amp;quot;);&lt;br /&gt;
      cleanup();&lt;br /&gt;
      exit(0);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   /*--------------------------------------------*/&lt;br /&gt;
   /* Use FindConfigDev to get info on the first */&lt;br /&gt;
   /* expansion board on the list maintained by  */&lt;br /&gt;
   /* Exec.  If there are no expansion boards in */&lt;br /&gt;
   /* the system then exit.                      */&lt;br /&gt;
   /*--------------------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   MyConfigDev = NULL;&lt;br /&gt;
&lt;br /&gt;
  /*--------------------------------------------------*/&lt;br /&gt;
  /* FindConfigDev(oldConfigDev,manufacturer,product) */&lt;br /&gt;
  /* oldConfigDev = NULL for the top of the list      */&lt;br /&gt;
  /* manufacturer = -1 for any manufacturer           */&lt;br /&gt;
  /* product      = -1 for any product                */&lt;br /&gt;
  /*--------------------------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   MyConfigDev = FindConfigDev(NULL,-1,-1);&lt;br /&gt;
&lt;br /&gt;
   if(MyConfigDev==NULL)&lt;br /&gt;
   {&lt;br /&gt;
      printf(&amp;quot;No Configured Devices found!!\n&amp;quot;);&lt;br /&gt;
      cleanup();&lt;br /&gt;
      exit(0);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   printdev(MyConfigDev);&lt;br /&gt;
&lt;br /&gt;
   /*-----------------------------------*/&lt;br /&gt;
   /* OK, there is at least one board,  */&lt;br /&gt;
   /* so loop and get the entire list   */&lt;br /&gt;
   /* printing as we go with printdev() */&lt;br /&gt;
   /*-----------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   while(MyConfigDev = FindConfigDev(MyConfigDev,-1,-1))&lt;br /&gt;
   {&lt;br /&gt;
      printdev(MyConfigDev);&lt;br /&gt;
   }&lt;br /&gt;
   cleanup();&lt;br /&gt;
   return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*-------------------*/&lt;br /&gt;
/* Close up shop...  */&lt;br /&gt;
/*-------------------*/&lt;br /&gt;
void cleanup()&lt;br /&gt;
{&lt;br /&gt;
   if(ExpansionBase)&lt;br /&gt;
      CloseLibrary(ExpansionBase);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*----------------------------------*/&lt;br /&gt;
/* Print out the contents of the    */&lt;br /&gt;
/* dev structure for this expansion */&lt;br /&gt;
/* product.                         */&lt;br /&gt;
/*----------------------------------*/&lt;br /&gt;
&lt;br /&gt;
void printdev(dev)&lt;br /&gt;
struct ConfigDev *dev;&lt;br /&gt;
{&lt;br /&gt;
   char buff[200];&lt;br /&gt;
&lt;br /&gt;
   printf(&amp;quot;Flags          = &amp;quot;);&lt;br /&gt;
   if(dev-&amp;gt;cd_Flags==NULL)&lt;br /&gt;
      printf(&amp;quot;NULL  &amp;quot;);&lt;br /&gt;
   if(dev-&amp;gt;cd_Flags&amp;amp;CDF_SHUTUP)&lt;br /&gt;
      printf(&amp;quot;CDF_SHUTUP  &amp;quot;);&lt;br /&gt;
   if(dev-&amp;gt;cd_Flags&amp;amp;CDF_CONFIGME)&lt;br /&gt;
      printf(&amp;quot;CDF_CONFIGME  &amp;quot;);&lt;br /&gt;
   printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
   printf(&amp;quot;Board Address  = %x\n&amp;quot;,dev-&amp;gt;cd_BoardAddr);&lt;br /&gt;
   printf(&amp;quot;Board Size     = %d bytes\n&amp;quot;,dev-&amp;gt;cd_BoardSize);&lt;br /&gt;
   printf(&amp;quot;Slot  Address  = %d\n&amp;quot;,dev-&amp;gt;cd_SlotAddr);&lt;br /&gt;
   printf(&amp;quot;Slot  Size     = %d\n&amp;quot;,dev-&amp;gt;cd_SlotSize);&lt;br /&gt;
   printf(&amp;quot;Driver code at   %x\n&amp;quot;,dev-&amp;gt;cd_Driver);&lt;br /&gt;
&lt;br /&gt;
   printf(&amp;quot;er_Type         = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Type);&lt;br /&gt;
   printf(&amp;quot;er_Product      = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Product);&lt;br /&gt;
   printf(&amp;quot;er_Flags        = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Flags);&lt;br /&gt;
   printf(&amp;quot;er_Reserved03   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved03);&lt;br /&gt;
   printf(&amp;quot;er_Manufacturer = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Manufacturer);&lt;br /&gt;
   printf(&amp;quot;er_SerialNumber = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_SerialNumber);&lt;br /&gt;
   printf(&amp;quot;er_InitDiagVec  = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_InitDiagVec);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0c   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0c);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0d   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0d);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0e   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0e);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0f   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0f);&lt;br /&gt;
&lt;br /&gt;
   printf(&amp;quot;Hit Return to continue:\n&amp;quot;);&lt;br /&gt;
   gets(buff);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Registry =&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! ID (decimal)&lt;br /&gt;
! ID (hexadecimal)&lt;br /&gt;
! Manufacturer&lt;br /&gt;
! Notes&lt;br /&gt;
|-&lt;br /&gt;
| 1&lt;br /&gt;
| 0001&lt;br /&gt;
| Micronik&lt;br /&gt;
|-&lt;br /&gt;
| 211&lt;br /&gt;
| 00D3&lt;br /&gt;
| Pacific Peripherals/Profex&lt;br /&gt;
|-&lt;br /&gt;
| 221&lt;br /&gt;
| 00DD&lt;br /&gt;
| Kupke Computertechnik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 256&lt;br /&gt;
| 0100&lt;br /&gt;
| Memphis&lt;br /&gt;
| Originally registered to MacroSystems US&lt;br /&gt;
|-&lt;br /&gt;
| 512&lt;br /&gt;
| 0200&lt;br /&gt;
| 3-State Computertechnik&lt;br /&gt;
|-&lt;br /&gt;
| 513&lt;br /&gt;
| 0201&lt;br /&gt;
| Commodore (Braunschweig)&lt;br /&gt;
|-&lt;br /&gt;
| 514&lt;br /&gt;
| 0202&lt;br /&gt;
| Commodore (West Chester)&lt;br /&gt;
|-&lt;br /&gt;
| 515&lt;br /&gt;
| 0203&lt;br /&gt;
| Commodore (West Chester)&lt;br /&gt;
| Originally registered to Combitech/Macrosystem&lt;br /&gt;
|-&lt;br /&gt;
| 756&lt;br /&gt;
| 02F4&lt;br /&gt;
| Progressive Peripherals &amp;amp; Software&lt;br /&gt;
|-&lt;br /&gt;
| 767&lt;br /&gt;
| 02FF&lt;br /&gt;
| Kolff Computer Supplies&lt;br /&gt;
|-&lt;br /&gt;
| 1001&lt;br /&gt;
| 03E9&lt;br /&gt;
| Tecmar&lt;br /&gt;
|-&lt;br /&gt;
| 1002&lt;br /&gt;
| 03EA&lt;br /&gt;
| Telesys&lt;br /&gt;
|-&lt;br /&gt;
| 1003&lt;br /&gt;
| 03EB&lt;br /&gt;
| The Micro-Forge&lt;br /&gt;
|-&lt;br /&gt;
| 1004&lt;br /&gt;
| 03EC&lt;br /&gt;
| Kronos/C Ltd.&lt;br /&gt;
| Originally registered to Card Co. (Supra)&lt;br /&gt;
|-&lt;br /&gt;
| 1005&lt;br /&gt;
| 03ED&lt;br /&gt;
| A-Squared&lt;br /&gt;
|-&lt;br /&gt;
| 1006&lt;br /&gt;
| 03EE&lt;br /&gt;
| Comspec Communications&lt;br /&gt;
|-&lt;br /&gt;
| 1007&lt;br /&gt;
| 03EF&lt;br /&gt;
| HT Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 1008&lt;br /&gt;
| 03F0&lt;br /&gt;
| RDS Software&lt;br /&gt;
|-&lt;br /&gt;
| 1009&lt;br /&gt;
| 03F1&lt;br /&gt;
| Anakin Research&lt;br /&gt;
|-&lt;br /&gt;
| 1010&lt;br /&gt;
| 03F2&lt;br /&gt;
| MicroBotics&lt;br /&gt;
|-&lt;br /&gt;
| 1011&lt;br /&gt;
| 03F3&lt;br /&gt;
| Bob Krauth&lt;br /&gt;
|-&lt;br /&gt;
| 1012&lt;br /&gt;
| 03F4&lt;br /&gt;
| Access Associates (Alegra)&lt;br /&gt;
|-&lt;br /&gt;
| 1013&lt;br /&gt;
| 03F5&lt;br /&gt;
| Mini Comp Systems Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 1014&lt;br /&gt;
| 03F6&lt;br /&gt;
| Cypress Technology&lt;br /&gt;
|-&lt;br /&gt;
| 1015&lt;br /&gt;
| 03F7&lt;br /&gt;
| Fuller Computers&lt;br /&gt;
|-&lt;br /&gt;
| 1016&lt;br /&gt;
| 03F8&lt;br /&gt;
| Galaxy Computers&lt;br /&gt;
|-&lt;br /&gt;
| 1017&lt;br /&gt;
| 03F9&lt;br /&gt;
| ADA Research&lt;br /&gt;
|-&lt;br /&gt;
| 1018&lt;br /&gt;
| 03FA&lt;br /&gt;
| Computer Service Italia&lt;br /&gt;
|-&lt;br /&gt;
| 1019&lt;br /&gt;
| 03FB&lt;br /&gt;
| Amigo&lt;br /&gt;
|-&lt;br /&gt;
| 1020&lt;br /&gt;
| 03FC&lt;br /&gt;
| Micro-Solutions Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1021&lt;br /&gt;
| 03FD&lt;br /&gt;
| Stacar International&lt;br /&gt;
|-&lt;br /&gt;
| 1022&lt;br /&gt;
| 03FE&lt;br /&gt;
| Video Precisions&lt;br /&gt;
|-&lt;br /&gt;
| 1023&lt;br /&gt;
| 03FF&lt;br /&gt;
| ASDG, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1025&lt;br /&gt;
| 0401&lt;br /&gt;
| Ing. Buero Kalawsky&lt;br /&gt;
|-&lt;br /&gt;
| 1026&lt;br /&gt;
| 0402&lt;br /&gt;
| Computer Tuning&lt;br /&gt;
|-&lt;br /&gt;
| 1027&lt;br /&gt;
| 0403&lt;br /&gt;
| Interplan Unternehmensberatung&lt;br /&gt;
|-&lt;br /&gt;
| 1028&lt;br /&gt;
| 0404&lt;br /&gt;
| Imtronics/Memphis&lt;br /&gt;
| Originally registered to Peter Ohlich&lt;br /&gt;
|-&lt;br /&gt;
| 1030&lt;br /&gt;
| 0406&lt;br /&gt;
| Commodore (Lowell University)&lt;br /&gt;
| Originally registered to Productivity Center&lt;br /&gt;
|-&lt;br /&gt;
| 1041&lt;br /&gt;
| 0411&lt;br /&gt;
| Design Labs&lt;br /&gt;
|-&lt;br /&gt;
| 1042&lt;br /&gt;
| 0412&lt;br /&gt;
| MCS&lt;br /&gt;
|-&lt;br /&gt;
| 1043&lt;br /&gt;
| 0413&lt;br /&gt;
| B. J. Freeman&lt;br /&gt;
|-&lt;br /&gt;
| 1044&lt;br /&gt;
| 0414&lt;br /&gt;
| Side Effects Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1045&lt;br /&gt;
| 0415&lt;br /&gt;
| Oklahoma Personal Comp.&lt;br /&gt;
|-&lt;br /&gt;
| 1046&lt;br /&gt;
| 0416&lt;br /&gt;
| Advanced Micro Innovations&lt;br /&gt;
|-&lt;br /&gt;
| 1047&lt;br /&gt;
| 0417&lt;br /&gt;
| Industrial Support Services&lt;br /&gt;
|-&lt;br /&gt;
| 1048&lt;br /&gt;
| 0418&lt;br /&gt;
| Technisoft&lt;br /&gt;
|-&lt;br /&gt;
| 1049&lt;br /&gt;
| 0419&lt;br /&gt;
| Prolific, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1050&lt;br /&gt;
| 041A&lt;br /&gt;
| Softeam, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1051&lt;br /&gt;
| 041B&lt;br /&gt;
| GRC Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 1052&lt;br /&gt;
| 041C&lt;br /&gt;
| David Lai&lt;br /&gt;
|-&lt;br /&gt;
| 1053&lt;br /&gt;
| 041D&lt;br /&gt;
| Ameristar Technologies&lt;br /&gt;
|-&lt;br /&gt;
| 1054&lt;br /&gt;
| 041E&lt;br /&gt;
| Cline Refrigeration&lt;br /&gt;
|-&lt;br /&gt;
| 1055&lt;br /&gt;
| 041F&lt;br /&gt;
| Cardiac Pacemakers, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1056&lt;br /&gt;
| 0420&lt;br /&gt;
| Supra Corp. (Creative Microsystems)&lt;br /&gt;
|-&lt;br /&gt;
| 1057&lt;br /&gt;
| 0421&lt;br /&gt;
| Wayne Diener&lt;br /&gt;
|-&lt;br /&gt;
| 1058&lt;br /&gt;
| 0422&lt;br /&gt;
| Computer Systems Associates (CSA)&lt;br /&gt;
|-&lt;br /&gt;
| 1059&lt;br /&gt;
| 0423&lt;br /&gt;
| Trionix, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1060&lt;br /&gt;
| 0424&lt;br /&gt;
| David Lucas&lt;br /&gt;
|-&lt;br /&gt;
| 1061&lt;br /&gt;
| 0425&lt;br /&gt;
| Analog Precision&lt;br /&gt;
| Also assigned to D &amp;amp; L Distributing&lt;br /&gt;
|-&lt;br /&gt;
| 1267&lt;br /&gt;
| 04F3&lt;br /&gt;
| RBM Digitaltechnik&lt;br /&gt;
|-&lt;br /&gt;
| 1282&lt;br /&gt;
| 0502&lt;br /&gt;
| M-TEC Hardware Design&lt;br /&gt;
|-&lt;br /&gt;
| 1337&lt;br /&gt;
| 0539&lt;br /&gt;
| Thomas Stenzel (DaFR34K)&lt;br /&gt;
|-&lt;br /&gt;
| 1576&lt;br /&gt;
| 0628&lt;br /&gt;
| Boris Križma&lt;br /&gt;
|-&lt;br /&gt;
| 1761&lt;br /&gt;
| 06E1&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
|-&lt;br /&gt;
| 1803&lt;br /&gt;
| 070B&lt;br /&gt;
| UAE Amiga Emulator&lt;br /&gt;
|-&lt;br /&gt;
| 2002&lt;br /&gt;
| 07D2&lt;br /&gt;
| Mimetics Corp.&lt;br /&gt;
|-&lt;br /&gt;
| 2003&lt;br /&gt;
| 07D3&lt;br /&gt;
| ACDA&lt;br /&gt;
|-&lt;br /&gt;
| 2004&lt;br /&gt;
| 07D4&lt;br /&gt;
| Finn R. Jacobsen&lt;br /&gt;
|-&lt;br /&gt;
| 2005&lt;br /&gt;
| 07D5&lt;br /&gt;
| Elthen Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2006&lt;br /&gt;
| 07D6&lt;br /&gt;
| Nine Tiles Computer Systems Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2007&lt;br /&gt;
| 07D7&lt;br /&gt;
| Analog Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2008&lt;br /&gt;
| 07D8&lt;br /&gt;
| Bell &amp;amp;amp; Howell&lt;br /&gt;
|-&lt;br /&gt;
| 2009&lt;br /&gt;
| 07D9&lt;br /&gt;
| Roland Kochler&lt;br /&gt;
|-&lt;br /&gt;
| 2010&lt;br /&gt;
| 07DA&lt;br /&gt;
| Byte Corp.&lt;br /&gt;
|-&lt;br /&gt;
| 2011&lt;br /&gt;
| 07DB&lt;br /&gt;
| Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 2012&lt;br /&gt;
| 07DC&lt;br /&gt;
| DKB, Inc.&lt;br /&gt;
| Previously named Michigan Software&lt;br /&gt;
|-&lt;br /&gt;
| 2013&lt;br /&gt;
| 07DD&lt;br /&gt;
| Pacific Peripherals&lt;br /&gt;
|-&lt;br /&gt;
| 2014&lt;br /&gt;
| 07DE&lt;br /&gt;
| Sysaphus Software&lt;br /&gt;
|-&lt;br /&gt;
| 2015&lt;br /&gt;
| 07DF&lt;br /&gt;
| Digitronics&lt;br /&gt;
|-&lt;br /&gt;
| 2016&lt;br /&gt;
| 07E0&lt;br /&gt;
| Akron Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2017&lt;br /&gt;
| 07E1&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
|-&lt;br /&gt;
| 2018&lt;br /&gt;
| 07E2&lt;br /&gt;
| Calmos&lt;br /&gt;
|-&lt;br /&gt;
| 2019&lt;br /&gt;
| 07E3&lt;br /&gt;
| Dover Research&lt;br /&gt;
|-&lt;br /&gt;
| 2020&lt;br /&gt;
| 07E4&lt;br /&gt;
| David Krehbiel&lt;br /&gt;
|-&lt;br /&gt;
| 2021&lt;br /&gt;
| 07E5&lt;br /&gt;
| Synergy Peripheral Systems&lt;br /&gt;
| Also known as California Access&lt;br /&gt;
|-&lt;br /&gt;
| 2022&lt;br /&gt;
| 07E6&lt;br /&gt;
| Xetec&lt;br /&gt;
|-&lt;br /&gt;
| 2023&lt;br /&gt;
| 07E7&lt;br /&gt;
| Micron Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2024&lt;br /&gt;
| 07E8&lt;br /&gt;
| CH Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2025&lt;br /&gt;
| 07E9&lt;br /&gt;
| American Liquid Light&lt;br /&gt;
|-&lt;br /&gt;
| 2026&lt;br /&gt;
| 07EA&lt;br /&gt;
| Progressive Peripherals &amp;amp;amp; Software&lt;br /&gt;
| Also used by Ateo&lt;br /&gt;
|-&lt;br /&gt;
| 2027&lt;br /&gt;
| 07EB&lt;br /&gt;
| Wicat Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2028&lt;br /&gt;
| 07EC&lt;br /&gt;
| Applied Systems &amp;amp;amp; Peripherals&lt;br /&gt;
|-&lt;br /&gt;
| 2029&lt;br /&gt;
| 07ED&lt;br /&gt;
| Delaware Valley Software&lt;br /&gt;
|-&lt;br /&gt;
| 2030&lt;br /&gt;
| 07EE&lt;br /&gt;
| Palomax&lt;br /&gt;
|-&lt;br /&gt;
| 2031&lt;br /&gt;
| 07EF&lt;br /&gt;
| Incognito Software&lt;br /&gt;
|-&lt;br /&gt;
| 2032&lt;br /&gt;
| 07F0&lt;br /&gt;
| Jadesign&lt;br /&gt;
|-&lt;br /&gt;
| 2033&lt;br /&gt;
| 07F1&lt;br /&gt;
| BVR&lt;br /&gt;
|-&lt;br /&gt;
| 2034&lt;br /&gt;
| 07F2&lt;br /&gt;
| Spirit Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2035&lt;br /&gt;
| 07F3&lt;br /&gt;
| Spirit Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2036&lt;br /&gt;
| 07F4&lt;br /&gt;
| Atronic&lt;br /&gt;
|-&lt;br /&gt;
| 2037&lt;br /&gt;
| 07F5&lt;br /&gt;
| Scott Karlin&lt;br /&gt;
|-&lt;br /&gt;
| 2038&lt;br /&gt;
| 07F6&lt;br /&gt;
| Howitch&lt;br /&gt;
|-&lt;br /&gt;
| 2039&lt;br /&gt;
| 07F7&lt;br /&gt;
| Sullivan Brothers Visual Engineers&lt;br /&gt;
|-&lt;br /&gt;
| 2040&lt;br /&gt;
| 07F8&lt;br /&gt;
| G I T&lt;br /&gt;
|-&lt;br /&gt;
| 2041&lt;br /&gt;
| 07F9&lt;br /&gt;
| Amigo Business Computers&lt;br /&gt;
|-&lt;br /&gt;
| 2042&lt;br /&gt;
| 07FA&lt;br /&gt;
| Micro E Ab&lt;br /&gt;
|-&lt;br /&gt;
| 2043&lt;br /&gt;
| 07FB&lt;br /&gt;
| Ralph Kruse&lt;br /&gt;
|-&lt;br /&gt;
| 2044&lt;br /&gt;
| 07FC&lt;br /&gt;
| Clearpoint Research&lt;br /&gt;
|-&lt;br /&gt;
| 2045&lt;br /&gt;
| 07FD&lt;br /&gt;
| Kodiak&lt;br /&gt;
|-&lt;br /&gt;
| 2046&lt;br /&gt;
| 07FE&lt;br /&gt;
| BSC&lt;br /&gt;
| Originally registered to Phoenix Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2047&lt;br /&gt;
| 07FF&lt;br /&gt;
| No Name Shown&lt;br /&gt;
|-&lt;br /&gt;
| 2048&lt;br /&gt;
| 0800&lt;br /&gt;
| Commodore Braunschweig&lt;br /&gt;
|-&lt;br /&gt;
| 2049&lt;br /&gt;
| 0801&lt;br /&gt;
| BSC&lt;br /&gt;
| Originally registered to Elaborate Bytes&lt;br /&gt;
|-&lt;br /&gt;
| 2050&lt;br /&gt;
| 0802&lt;br /&gt;
| Kronos/C Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2051&lt;br /&gt;
| 0803&lt;br /&gt;
| Spartanics&lt;br /&gt;
|-&lt;br /&gt;
| 2052&lt;br /&gt;
| 0804&lt;br /&gt;
| Jochheim Computer Tuning&lt;br /&gt;
|-&lt;br /&gt;
| 2053&lt;br /&gt;
| 0805&lt;br /&gt;
| Trans Data Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2054&lt;br /&gt;
| 0806&lt;br /&gt;
| Applied Systems &amp;amp;amp; Peripherals Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2055&lt;br /&gt;
| 0807&lt;br /&gt;
| Checkpoint Technologies&lt;br /&gt;
| Originally registered to Amiga Solutions&lt;br /&gt;
|-&lt;br /&gt;
| 2056&lt;br /&gt;
| 0808&lt;br /&gt;
| Adept Development&lt;br /&gt;
|-&lt;br /&gt;
| 2057&lt;br /&gt;
| 0809&lt;br /&gt;
| Advanced Computer Design&lt;br /&gt;
|-&lt;br /&gt;
| 2058&lt;br /&gt;
| 080A&lt;br /&gt;
| Sir Netics&lt;br /&gt;
|-&lt;br /&gt;
| 2059&lt;br /&gt;
| 080B&lt;br /&gt;
| Expert Services&lt;br /&gt;
|-&lt;br /&gt;
| 2060&lt;br /&gt;
| 080C&lt;br /&gt;
| Digital Art Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2061&lt;br /&gt;
| 080D&lt;br /&gt;
| Adept Development&lt;br /&gt;
|-&lt;br /&gt;
| 2062&lt;br /&gt;
| 080E&lt;br /&gt;
| Expansion Technologies (Expansion Systems)&lt;br /&gt;
|-&lt;br /&gt;
| 2063&lt;br /&gt;
| 080F&lt;br /&gt;
| Alphatech&lt;br /&gt;
|-&lt;br /&gt;
| 2064&lt;br /&gt;
| 0810&lt;br /&gt;
| Edotronik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2065&lt;br /&gt;
| 0811&lt;br /&gt;
| California Access/Synergy&lt;br /&gt;
| Originally registered to Logical Design Works&lt;br /&gt;
|-&lt;br /&gt;
| 2066&lt;br /&gt;
| 0812&lt;br /&gt;
| Bowden, Williams, Full &amp;amp; Assoc.&lt;br /&gt;
|-&lt;br /&gt;
| 2067&lt;br /&gt;
| 0813&lt;br /&gt;
| NES, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2068&lt;br /&gt;
| 0814&lt;br /&gt;
| Amdev&lt;br /&gt;
|-&lt;br /&gt;
| 2069&lt;br /&gt;
| 0815&lt;br /&gt;
| Big Brother Security Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2070&lt;br /&gt;
| 0816&lt;br /&gt;
| Active Circuits Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2071&lt;br /&gt;
| 0817&lt;br /&gt;
| ICD, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2072&lt;br /&gt;
| 0818&lt;br /&gt;
| Multi-Meg Electronique&lt;br /&gt;
|-&lt;br /&gt;
| 2073&lt;br /&gt;
| 0819&lt;br /&gt;
| Kupke Computertechnik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2074&lt;br /&gt;
| 081A&lt;br /&gt;
| The Checkered Ball&lt;br /&gt;
|-&lt;br /&gt;
| 2075&lt;br /&gt;
| 081B&lt;br /&gt;
| Hi Tension Computer Services Ltd. (UK)&lt;br /&gt;
|-&lt;br /&gt;
| 2076&lt;br /&gt;
| 081C&lt;br /&gt;
| Alfa Data&lt;br /&gt;
| Originally assigned to Elmtech Research, Ltd. (UK)&lt;br /&gt;
|-&lt;br /&gt;
| 2077&lt;br /&gt;
| 081D&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
| Originally registered to Clartscreen, Ltd. (UK)&lt;br /&gt;
|-&lt;br /&gt;
| 2078&lt;br /&gt;
| 081E&lt;br /&gt;
| Interworks&lt;br /&gt;
|-&lt;br /&gt;
| 2079&lt;br /&gt;
| 081F&lt;br /&gt;
| Galysh Enterprises&lt;br /&gt;
|-&lt;br /&gt;
| 2080&lt;br /&gt;
| 0820&lt;br /&gt;
| Hardital Synthesis&lt;br /&gt;
| Originally registered to Realtime Games Software Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2081&lt;br /&gt;
| 0821&lt;br /&gt;
| GBS&lt;br /&gt;
|-&lt;br /&gt;
| 2082&lt;br /&gt;
| 0822&lt;br /&gt;
| Circum Design Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2083&lt;br /&gt;
| 0823&lt;br /&gt;
| Alberta Micro Electronic Center&lt;br /&gt;
|-&lt;br /&gt;
| 2084&lt;br /&gt;
| 0824&lt;br /&gt;
| Bestech&lt;br /&gt;
|-&lt;br /&gt;
| 2085&lt;br /&gt;
| 0825&lt;br /&gt;
| Lasar Fantasy&lt;br /&gt;
|-&lt;br /&gt;
| 2086&lt;br /&gt;
| 0826&lt;br /&gt;
| Pulsar&lt;br /&gt;
|-&lt;br /&gt;
| 2087&lt;br /&gt;
| 0827&lt;br /&gt;
| Ivis&lt;br /&gt;
|-&lt;br /&gt;
| 2088&lt;br /&gt;
| 0828&lt;br /&gt;
| Applied Engineering&lt;br /&gt;
|-&lt;br /&gt;
| 2089&lt;br /&gt;
| 0829&lt;br /&gt;
| Solid-State Design &amp;amp;amp; Development&lt;br /&gt;
|-&lt;br /&gt;
| 2090&lt;br /&gt;
| 082A&lt;br /&gt;
| Vison Quest&lt;br /&gt;
|-&lt;br /&gt;
| 2091&lt;br /&gt;
| 082B&lt;br /&gt;
| Seaview Software&lt;br /&gt;
|-&lt;br /&gt;
| 2092&lt;br /&gt;
| 082C&lt;br /&gt;
| BSC&lt;br /&gt;
| Mistakenly used by ADS (Advanced Development Software)&lt;br /&gt;
|-&lt;br /&gt;
| 2093&lt;br /&gt;
| 082D&lt;br /&gt;
| Bernd Culenfeld&lt;br /&gt;
|-&lt;br /&gt;
| 2094&lt;br /&gt;
| 082E&lt;br /&gt;
| American Liquid Light&lt;br /&gt;
|-&lt;br /&gt;
| 2095&lt;br /&gt;
| 082F&lt;br /&gt;
| CEGITES&lt;br /&gt;
|-&lt;br /&gt;
| 2096&lt;br /&gt;
| 0830&lt;br /&gt;
| Quadlite Computers Ltd.&lt;br /&gt;
| Originally registered to EV Industries&lt;br /&gt;
|-&lt;br /&gt;
| 2097&lt;br /&gt;
| 0831&lt;br /&gt;
| Silicon Peace&lt;br /&gt;
|-&lt;br /&gt;
| 2098&lt;br /&gt;
| 0832&lt;br /&gt;
| Black Belt Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2099&lt;br /&gt;
| 0833&lt;br /&gt;
| Village Tronic&lt;br /&gt;
| Originally registerd to Steve Yaeger&lt;br /&gt;
|-&lt;br /&gt;
| 2100&lt;br /&gt;
| 0834&lt;br /&gt;
| ReadySoft&lt;br /&gt;
|-&lt;br /&gt;
| 2101&lt;br /&gt;
| 0835&lt;br /&gt;
| Phoenix Micro Technologies&lt;br /&gt;
|-&lt;br /&gt;
| 2102&lt;br /&gt;
| 0836&lt;br /&gt;
| Advanced Systems &amp;amp; Software&lt;br /&gt;
| Orignally assigned to Preferred Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2103&lt;br /&gt;
| 0837&lt;br /&gt;
| Rombo Productions&lt;br /&gt;
|-&lt;br /&gt;
| 2104&lt;br /&gt;
| 0838&lt;br /&gt;
| Impulse Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2105&lt;br /&gt;
| 0839&lt;br /&gt;
| Beta Unlimited&lt;br /&gt;
|-&lt;br /&gt;
| 2106&lt;br /&gt;
| 083A&lt;br /&gt;
| Memory Expansion System, Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2107&lt;br /&gt;
| 083B&lt;br /&gt;
| Vortex Computer Systems GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2108&lt;br /&gt;
| 083C&lt;br /&gt;
| Platypus Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2109&lt;br /&gt;
| 083D&lt;br /&gt;
| Gigatron OHG&lt;br /&gt;
|-&lt;br /&gt;
| 2110&lt;br /&gt;
| 083E&lt;br /&gt;
| PG Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2111&lt;br /&gt;
| 083F&lt;br /&gt;
| New Technologies Group&lt;br /&gt;
|-&lt;br /&gt;
| 2112&lt;br /&gt;
| 0840&lt;br /&gt;
| Interactive Video Systems (IVS)&lt;br /&gt;
| Pacific Peripherals&lt;br /&gt;
|-&lt;br /&gt;
| 2113&lt;br /&gt;
| 0841&lt;br /&gt;
| Vector&lt;br /&gt;
| Originally registered to H. K. Computer&lt;br /&gt;
|-&lt;br /&gt;
| 2114&lt;br /&gt;
| 0842&lt;br /&gt;
| Pacific Digital&lt;br /&gt;
| Originally registered to C. H. Helfrich Elektronik&lt;br /&gt;
|-&lt;br /&gt;
| 2115&lt;br /&gt;
| 0843&lt;br /&gt;
| Xanadu&lt;br /&gt;
|-&lt;br /&gt;
| 2116&lt;br /&gt;
| 0844&lt;br /&gt;
| Pacific Digital&lt;br /&gt;
| Originally registered to AMS&lt;br /&gt;
|-&lt;br /&gt;
| 2117&lt;br /&gt;
| 0845&lt;br /&gt;
| X-Pert&lt;br /&gt;
|-&lt;br /&gt;
| 2118&lt;br /&gt;
| 0846&lt;br /&gt;
| The Amiga Centre&lt;br /&gt;
|-&lt;br /&gt;
| 2119&lt;br /&gt;
| 0847&lt;br /&gt;
| Digital Pacific&lt;br /&gt;
|-&lt;br /&gt;
| 2120&lt;br /&gt;
| 0848&lt;br /&gt;
| Solid State Leisure&lt;br /&gt;
|-&lt;br /&gt;
| 2121&lt;br /&gt;
| 0849&lt;br /&gt;
| Hydra Systems&lt;br /&gt;
| Originally registered to Analog Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2122&lt;br /&gt;
| 084A&lt;br /&gt;
| Cumana&lt;br /&gt;
|-&lt;br /&gt;
| 2123&lt;br /&gt;
| 084B&lt;br /&gt;
| KAPS 2C Conception&lt;br /&gt;
|-&lt;br /&gt;
| 2124&lt;br /&gt;
| 084C&lt;br /&gt;
| Mike Mason&lt;br /&gt;
|-&lt;br /&gt;
| 2125&lt;br /&gt;
| 084D&lt;br /&gt;
| For Your Eyes&lt;br /&gt;
|-&lt;br /&gt;
| 2126&lt;br /&gt;
| 084E&lt;br /&gt;
| Volkmar Breitfeld Computersysteme&lt;br /&gt;
|-&lt;br /&gt;
| 2127&lt;br /&gt;
| 084F&lt;br /&gt;
| Sunrize Industries&lt;br /&gt;
|-&lt;br /&gt;
| 2128&lt;br /&gt;
| 0850&lt;br /&gt;
| Scott Advanced Micro Designs&lt;br /&gt;
|-&lt;br /&gt;
| 2129&lt;br /&gt;
| 0851&lt;br /&gt;
| Digital Micronics&lt;br /&gt;
|-&lt;br /&gt;
| 2130&lt;br /&gt;
| 0852&lt;br /&gt;
| Alfa-Laval&lt;br /&gt;
|-&lt;br /&gt;
| 2131&lt;br /&gt;
| 0853&lt;br /&gt;
| Multigros A/S&lt;br /&gt;
|-&lt;br /&gt;
| 2132&lt;br /&gt;
| 0854&lt;br /&gt;
| Archos&lt;br /&gt;
|-&lt;br /&gt;
| 2133&lt;br /&gt;
| 0855&lt;br /&gt;
| Icom Simulations&lt;br /&gt;
|-&lt;br /&gt;
| 2134&lt;br /&gt;
| 0856&lt;br /&gt;
| Commodore Test Engineering Group&lt;br /&gt;
|-&lt;br /&gt;
| 2135&lt;br /&gt;
| 0857&lt;br /&gt;
| Microcreations&lt;br /&gt;
|-&lt;br /&gt;
| 2136&lt;br /&gt;
| 0858&lt;br /&gt;
| Shoestring Productions&lt;br /&gt;
|-&lt;br /&gt;
| 2137&lt;br /&gt;
| 0859&lt;br /&gt;
| Faberushi&lt;br /&gt;
|-&lt;br /&gt;
| 2138&lt;br /&gt;
| 085A&lt;br /&gt;
| Evesham Micro Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2139&lt;br /&gt;
| 085B&lt;br /&gt;
| Panagolin Laser Software&lt;br /&gt;
|-&lt;br /&gt;
| 2140&lt;br /&gt;
| 085C&lt;br /&gt;
| Thomas Rudloff&lt;br /&gt;
|-&lt;br /&gt;
| 2141&lt;br /&gt;
| 085D&lt;br /&gt;
| Daniel Hohabir&lt;br /&gt;
|-&lt;br /&gt;
| 2142&lt;br /&gt;
| 085E&lt;br /&gt;
| GfxBase, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2143&lt;br /&gt;
| 085F&lt;br /&gt;
| Axellabs&lt;br /&gt;
|-&lt;br /&gt;
| 2144&lt;br /&gt;
| 0860&lt;br /&gt;
| Roctec Electronics Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2145&lt;br /&gt;
| 0861&lt;br /&gt;
| Omega Datentechnik&lt;br /&gt;
|-&lt;br /&gt;
| 2146&lt;br /&gt;
| 0862&lt;br /&gt;
| Atlantis&lt;br /&gt;
|-&lt;br /&gt;
| 2147&lt;br /&gt;
| 0863&lt;br /&gt;
| Skytec Computers&lt;br /&gt;
|-&lt;br /&gt;
| 2148&lt;br /&gt;
| 0864&lt;br /&gt;
| Protar Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2149&lt;br /&gt;
| 0865&lt;br /&gt;
| ACS&lt;br /&gt;
|-&lt;br /&gt;
| 2150&lt;br /&gt;
| 0866&lt;br /&gt;
| Software Results Enterprises&lt;br /&gt;
| Originally registered to University of Illinois&lt;br /&gt;
|-&lt;br /&gt;
| 2151&lt;br /&gt;
| 0867&lt;br /&gt;
| Infinity Systems Design Group&lt;br /&gt;
|-&lt;br /&gt;
| 2152&lt;br /&gt;
| 0868&lt;br /&gt;
| Trade It&lt;br /&gt;
|-&lt;br /&gt;
| 2153&lt;br /&gt;
| 0869&lt;br /&gt;
| Suntec, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2154&lt;br /&gt;
| 086A&lt;br /&gt;
| DJW Micro Systems&lt;br /&gt;
| Originally registered to Tritec Marketing&lt;br /&gt;
|-&lt;br /&gt;
| 2155&lt;br /&gt;
| 086B&lt;br /&gt;
| Power Computing Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2156&lt;br /&gt;
| 086C&lt;br /&gt;
| MacroSystems&lt;br /&gt;
|-&lt;br /&gt;
| 2157&lt;br /&gt;
| 086D&lt;br /&gt;
| Masoboshi GmbH (DCE)&lt;br /&gt;
|-&lt;br /&gt;
| 2158&lt;br /&gt;
| 086E&lt;br /&gt;
| HAL Software Hardware Handel&lt;br /&gt;
|-&lt;br /&gt;
| 2159&lt;br /&gt;
| 086F&lt;br /&gt;
| Mainhattan Data&lt;br /&gt;
| Originally registered to Michael Lamm Computersysteme&lt;br /&gt;
|-&lt;br /&gt;
| 2160&lt;br /&gt;
| 0870&lt;br /&gt;
| Digital Processing System&lt;br /&gt;
| Originally registered to bbdp Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2161&lt;br /&gt;
| 0871&lt;br /&gt;
| Blue Ribbon Soundworks&lt;br /&gt;
| Originally registered to Design Computer Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2162&lt;br /&gt;
| 0872&lt;br /&gt;
| XPert&lt;br /&gt;
| Originally registered to The Station&lt;br /&gt;
|-&lt;br /&gt;
| 2163&lt;br /&gt;
| 0873&lt;br /&gt;
| DelaComp&lt;br /&gt;
| Originally registered to Bryan Williams&lt;br /&gt;
|-&lt;br /&gt;
| 2164&lt;br /&gt;
| 0874&lt;br /&gt;
| Superformance Computer Engineering GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2165&lt;br /&gt;
| 0875&lt;br /&gt;
| Overland Engineering&lt;br /&gt;
|-&lt;br /&gt;
| 2166&lt;br /&gt;
| 0876&lt;br /&gt;
| Thomas Hamren&lt;br /&gt;
|-&lt;br /&gt;
| 2167&lt;br /&gt;
| 0877&lt;br /&gt;
| Village Tronic&lt;br /&gt;
|-&lt;br /&gt;
| 2168&lt;br /&gt;
| 0878&lt;br /&gt;
| Toolbox Design&lt;br /&gt;
|-&lt;br /&gt;
| 2169&lt;br /&gt;
| 0879&lt;br /&gt;
| Digital Processing System&lt;br /&gt;
|-&lt;br /&gt;
| 2170&lt;br /&gt;
| 087A&lt;br /&gt;
| Superformance&lt;br /&gt;
|-&lt;br /&gt;
| 2171&lt;br /&gt;
| 087B&lt;br /&gt;
| Utilities Unlimited&lt;br /&gt;
|-&lt;br /&gt;
| 2172&lt;br /&gt;
| 087C&lt;br /&gt;
| phase 5&lt;br /&gt;
|-&lt;br /&gt;
| 2173&lt;br /&gt;
| 087D&lt;br /&gt;
| Juergen Kommos&lt;br /&gt;
|-&lt;br /&gt;
| 2174&lt;br /&gt;
| 087E&lt;br /&gt;
| Electronic Design&lt;br /&gt;
|-&lt;br /&gt;
| 2175&lt;br /&gt;
| 087F&lt;br /&gt;
| James Cook University of North Queensland&lt;br /&gt;
|-&lt;br /&gt;
| 2176&lt;br /&gt;
| 0880&lt;br /&gt;
| AmiTrix Development&lt;br /&gt;
|-&lt;br /&gt;
| 2177&lt;br /&gt;
| 0881&lt;br /&gt;
| Ferranti&lt;br /&gt;
|-&lt;br /&gt;
| 2178&lt;br /&gt;
| 0882&lt;br /&gt;
| Leviathan Development&lt;br /&gt;
|-&lt;br /&gt;
| 2179&lt;br /&gt;
| 0883&lt;br /&gt;
| United Video Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2180&lt;br /&gt;
| 0884&lt;br /&gt;
| GPSoft Pty. Ltd.&lt;br /&gt;
| Originally registered to Juergen Kommos&lt;br /&gt;
|-&lt;br /&gt;
| 2181&lt;br /&gt;
| 0885&lt;br /&gt;
| ArMAX&lt;br /&gt;
| Oliver Bausch&lt;br /&gt;
|-&lt;br /&gt;
| 2182&lt;br /&gt;
| 0886&lt;br /&gt;
| CP Computer&lt;br /&gt;
|-&lt;br /&gt;
| 2183&lt;br /&gt;
| 0887&lt;br /&gt;
| AMOK - Amiga Module &amp;amp;amp; Oberon Klub&lt;br /&gt;
|-&lt;br /&gt;
| 2184&lt;br /&gt;
| 0888&lt;br /&gt;
| ITEK Neser &amp;amp;amp; Sieber GbR&lt;br /&gt;
|-&lt;br /&gt;
| 2185&lt;br /&gt;
| 0889&lt;br /&gt;
| Phillip C. Lello&lt;br /&gt;
|-&lt;br /&gt;
| 2186&lt;br /&gt;
| 088A&lt;br /&gt;
| Cyborg Design Services&lt;br /&gt;
|-&lt;br /&gt;
| 2187&lt;br /&gt;
| 088B&lt;br /&gt;
| G2 Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2188&lt;br /&gt;
| 088C&lt;br /&gt;
| Pro System Computersysteme&lt;br /&gt;
|-&lt;br /&gt;
| 2189&lt;br /&gt;
| 088D&lt;br /&gt;
| ZEUS Electronic&lt;br /&gt;
| Originally registered to MSPI (Markt &amp;amp;amp; Technik)&lt;br /&gt;
|-&lt;br /&gt;
| 2190&lt;br /&gt;
| 088E&lt;br /&gt;
| Altatech&lt;br /&gt;
|-&lt;br /&gt;
| 2191&lt;br /&gt;
| 088F&lt;br /&gt;
| NewTek&lt;br /&gt;
|-&lt;br /&gt;
| 2192&lt;br /&gt;
| 0890&lt;br /&gt;
| M-TEC Hardware Design&lt;br /&gt;
| Originally registered to Hardware Design Udo Neuroth&lt;br /&gt;
|-&lt;br /&gt;
| 2193&lt;br /&gt;
| 0891&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
| Originally registered to Viona Development&lt;br /&gt;
|-&lt;br /&gt;
| 2194&lt;br /&gt;
| 0892&lt;br /&gt;
| Amitek&lt;br /&gt;
| Originally assigned to Marpet Developments&lt;br /&gt;
|-&lt;br /&gt;
| 2195&lt;br /&gt;
| 0893&lt;br /&gt;
| Ingenieurbuero Helfrich&lt;br /&gt;
|-&lt;br /&gt;
| 2196&lt;br /&gt;
| 0894&lt;br /&gt;
| The Neo Group&lt;br /&gt;
|-&lt;br /&gt;
| 2197&lt;br /&gt;
| 0895&lt;br /&gt;
| Cyon&lt;br /&gt;
|-&lt;br /&gt;
| 2198&lt;br /&gt;
| 0896&lt;br /&gt;
| Bob Research Group&lt;br /&gt;
|-&lt;br /&gt;
| 2199&lt;br /&gt;
| 0897&lt;br /&gt;
| Richmond Sound Design Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2200&lt;br /&gt;
| 0898&lt;br /&gt;
| US Cybernetics&lt;br /&gt;
|-&lt;br /&gt;
| 2201&lt;br /&gt;
| 0899&lt;br /&gt;
| Fulvio Ieva&lt;br /&gt;
|-&lt;br /&gt;
| 2202&lt;br /&gt;
| 089A&lt;br /&gt;
| Silicon Studio&lt;br /&gt;
|-&lt;br /&gt;
| 2203&lt;br /&gt;
| 089B&lt;br /&gt;
| MacroSystems (USA)&lt;br /&gt;
| Was named Micro System Devices&lt;br /&gt;
|-&lt;br /&gt;
| 2204&lt;br /&gt;
| 089C&lt;br /&gt;
| Conspector Entertainment&lt;br /&gt;
|-&lt;br /&gt;
| 2205&lt;br /&gt;
| 089D&lt;br /&gt;
| Laserforum&lt;br /&gt;
|-&lt;br /&gt;
| 2206&lt;br /&gt;
| 089E&lt;br /&gt;
| Elbox Computer&lt;br /&gt;
| Mistakenly used by Index Information Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2207&lt;br /&gt;
| 089F&lt;br /&gt;
| Applied Magic Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2208&lt;br /&gt;
| 08A0&lt;br /&gt;
| SDL Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2560&lt;br /&gt;
| 0A00&lt;br /&gt;
| Harms&lt;br /&gt;
|-&lt;br /&gt;
| 2588&lt;br /&gt;
| 0A1C&lt;br /&gt;
| A1K.org Community&lt;br /&gt;
|-&lt;br /&gt;
| 2640&lt;br /&gt;
| 0A50&lt;br /&gt;
| Micronik&lt;br /&gt;
|-&lt;br /&gt;
| 3084&lt;br /&gt;
| 0C0C&lt;br /&gt;
| Team 4&lt;br /&gt;
|-&lt;br /&gt;
| 3643&lt;br /&gt;
| 0E3B&lt;br /&gt;
| E3B&lt;br /&gt;
| Michael Boehmer&lt;br /&gt;
|-&lt;br /&gt;
| 3855&lt;br /&gt;
| 0F0F&lt;br /&gt;
| Micronik&lt;br /&gt;
|-&lt;br /&gt;
| 4096&lt;br /&gt;
| 1000&lt;br /&gt;
| MegaMicro&lt;br /&gt;
|-&lt;br /&gt;
| 4110&lt;br /&gt;
| 100E&lt;br /&gt;
| DigiFeX&lt;br /&gt;
|-&lt;br /&gt;
| 4136&lt;br /&gt;
| 1028&lt;br /&gt;
| Imtronics/Memphis&lt;br /&gt;
|-&lt;br /&gt;
| 4149&lt;br /&gt;
| 1035&lt;br /&gt;
| PROTAR&lt;br /&gt;
|-&lt;br /&gt;
| 4369&lt;br /&gt;
| 1111&lt;br /&gt;
| Frank Strauß Elektronik&lt;br /&gt;
| Also used by Kupke&lt;br /&gt;
|-&lt;br /&gt;
| 4626&lt;br /&gt;
| 1212&lt;br /&gt;
| Individual Computers&lt;br /&gt;
|-&lt;br /&gt;
| 4648&lt;br /&gt;
| 1228&lt;br /&gt;
| Flesch Hornemann Computer Elec.&lt;br /&gt;
|-&lt;br /&gt;
| 4680&lt;br /&gt;
| 1248&lt;br /&gt;
| Kupke Computertechnik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 4711&lt;br /&gt;
| 1267&lt;br /&gt;
| RBM digitaltechnik&lt;br /&gt;
|-&lt;br /&gt;
| 4754&lt;br /&gt;
| 1292&lt;br /&gt;
| MacroSystems&lt;br /&gt;
|-&lt;br /&gt;
| 5000&lt;br /&gt;
| 1388&lt;br /&gt;
| ITH&lt;br /&gt;
|-&lt;br /&gt;
| 5001&lt;br /&gt;
| 1389&lt;br /&gt;
| VMC&lt;br /&gt;
|-&lt;br /&gt;
| 5010&lt;br /&gt;
| 1392&lt;br /&gt;
| Ambience Creation Technology&lt;br /&gt;
|-&lt;br /&gt;
| 5011&lt;br /&gt;
| 1393&lt;br /&gt;
| Creative Development&lt;br /&gt;
|-&lt;br /&gt;
| 5012&lt;br /&gt;
| 1394&lt;br /&gt;
| Georg Braun&lt;br /&gt;
|-&lt;br /&gt;
| 5013&lt;br /&gt;
| 1395&lt;br /&gt;
| Swedish User Group of Amiga&lt;br /&gt;
|-&lt;br /&gt;
| 5014&lt;br /&gt;
| 1396&lt;br /&gt;
| Jakub Bednarski&lt;br /&gt;
|-&lt;br /&gt;
| 5015&lt;br /&gt;
| 1397&lt;br /&gt;
| KryoFlux, Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 5016&lt;br /&gt;
| 1398&lt;br /&gt;
| Igor Majstorovic&lt;br /&gt;
|-&lt;br /&gt;
| 5017&lt;br /&gt;
| 1399&lt;br /&gt;
| Alastair M. Robinson&lt;br /&gt;
|-&lt;br /&gt;
| 5018&lt;br /&gt;
| 139A&lt;br /&gt;
| Austex Software&lt;br /&gt;
|-&lt;br /&gt;
| 5019&lt;br /&gt;
| 139B&lt;br /&gt;
| Sören Gust&lt;br /&gt;
|-&lt;br /&gt;
| 5020&lt;br /&gt;
| 139C&lt;br /&gt;
| Rok Krajnc&lt;br /&gt;
|-&lt;br /&gt;
| 5030&lt;br /&gt;
| 13A6&lt;br /&gt;
| Tim Tashpulatov&lt;br /&gt;
|-&lt;br /&gt;
| 5040&lt;br /&gt;
| 13B0&lt;br /&gt;
| 7-bit&lt;br /&gt;
|-&lt;br /&gt;
| 5050&lt;br /&gt;
| 13BA&lt;br /&gt;
| Sakura IT&lt;br /&gt;
|-&lt;br /&gt;
| 5060&lt;br /&gt;
| 13C4&lt;br /&gt;
| FPGAArcade&lt;br /&gt;
|-&lt;br /&gt;
| 5070&lt;br /&gt;
| 13CE&lt;br /&gt;
| CancerSoft Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 5080&lt;br /&gt;
| 13D8&lt;br /&gt;
| Stephen Leary&lt;br /&gt;
|-&lt;br /&gt;
| 5090&lt;br /&gt;
| 13E2&lt;br /&gt;
| DMA Softlab LLC&lt;br /&gt;
|-&lt;br /&gt;
| 5100&lt;br /&gt;
| 13EC&lt;br /&gt;
| Brookhouse Engineering&lt;br /&gt;
|-&lt;br /&gt;
| 5110&lt;br /&gt;
| 13F6&lt;br /&gt;
| Eduardo Arana&lt;br /&gt;
|-&lt;br /&gt;
| 5120&lt;br /&gt;
| 1400&lt;br /&gt;
| CS-LAB&lt;br /&gt;
|-&lt;br /&gt;
| 5130&lt;br /&gt;
| 140A&lt;br /&gt;
| Robert Miranda&lt;br /&gt;
|-&lt;br /&gt;
| 5140&lt;br /&gt;
| 1414&lt;br /&gt;
| RastPort&lt;br /&gt;
|-&lt;br /&gt;
| 5132&lt;br /&gt;
| 140C&lt;br /&gt;
| UAS Interface Ltd6&lt;br /&gt;
|-&lt;br /&gt;
| 5150&lt;br /&gt;
| 141E&lt;br /&gt;
| Amiga Kit&lt;br /&gt;
|-&lt;br /&gt;
| 5160&lt;br /&gt;
| 1428&lt;br /&gt;
| Central Texas Commodore User Group&lt;br /&gt;
|-&lt;br /&gt;
| 5170&lt;br /&gt;
| 1432&lt;br /&gt;
| Confusion Research Center&lt;br /&gt;
|-&lt;br /&gt;
| 5180&lt;br /&gt;
| 143C&lt;br /&gt;
| Solar Soyuz Zaibatsu&lt;br /&gt;
|-&lt;br /&gt;
| 5500&lt;br /&gt;
| 157C&lt;br /&gt;
| Inhouse Information&lt;br /&gt;
|-&lt;br /&gt;
| 5768&lt;br /&gt;
| 1688&lt;br /&gt;
| Bio Con&lt;br /&gt;
|-&lt;br /&gt;
| 6148&lt;br /&gt;
| 1804&lt;br /&gt;
| HK-Computer&lt;br /&gt;
|-&lt;br /&gt;
| 6502&lt;br /&gt;
| 1966&lt;br /&gt;
| Cloanto&lt;br /&gt;
|-&lt;br /&gt;
| 6520&lt;br /&gt;
| 1978&lt;br /&gt;
| Oliver Gantert&lt;br /&gt;
|-&lt;br /&gt;
| 7777&lt;br /&gt;
| 1E61&lt;br /&gt;
| Rafal Gabriel Chyla&lt;br /&gt;
|-&lt;br /&gt;
| 8215&lt;br /&gt;
| 2017&lt;br /&gt;
| Vortex&lt;br /&gt;
|-&lt;br /&gt;
| 8244&lt;br /&gt;
| 2034&lt;br /&gt;
| Spirit Technology&lt;br /&gt;
|-&lt;br /&gt;
| 8290&lt;br /&gt;
| 2062&lt;br /&gt;
| Expansion Systems&lt;br /&gt;
|-&lt;br /&gt;
| 8448&lt;br /&gt;
| 2100&lt;br /&gt;
| ReadySoft&lt;br /&gt;
|-&lt;br /&gt;
| 8512&lt;br /&gt;
| 2140&lt;br /&gt;
| Phase 5 Digital Products&lt;br /&gt;
|-&lt;br /&gt;
| 8553&lt;br /&gt;
| 2169&lt;br /&gt;
| Digital Processing Systems Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 8704&lt;br /&gt;
| 2200&lt;br /&gt;
| ACT Elektronik&lt;br /&gt;
|-&lt;br /&gt;
| 8738&lt;br /&gt;
| 2222&lt;br /&gt;
| ACT Elektronik&lt;br /&gt;
|-&lt;br /&gt;
| 9512&lt;br /&gt;
| 2528&lt;br /&gt;
| Tower Technologies&lt;br /&gt;
|-&lt;br /&gt;
| 10676&lt;br /&gt;
| 29B4&lt;br /&gt;
| Electronic Design&lt;br /&gt;
|-&lt;br /&gt;
| 14195&lt;br /&gt;
| 3773&lt;br /&gt;
| Media-net-Point&lt;br /&gt;
|-&lt;br /&gt;
| 14501&lt;br /&gt;
| 38A5&lt;br /&gt;
| Petsoff, Finland&lt;br /&gt;
|-&lt;br /&gt;
| 16375&lt;br /&gt;
| 3FF7&lt;br /&gt;
| Uwe Gerlach&lt;br /&gt;
|-&lt;br /&gt;
| 16707&lt;br /&gt;
| 4143&lt;br /&gt;
| Ateo Concepts&lt;br /&gt;
|-&lt;br /&gt;
| 16708&lt;br /&gt;
| 4144&lt;br /&gt;
| ALiENDESiGN&lt;br /&gt;
|-&lt;br /&gt;
| 16945&lt;br /&gt;
| 4231&lt;br /&gt;
| A.C.T.&lt;br /&gt;
|-&lt;br /&gt;
| 17740&lt;br /&gt;
| 454C&lt;br /&gt;
| HK-Computer (ELSAT)&lt;br /&gt;
|-&lt;br /&gt;
| 18260&lt;br /&gt;
| 4754&lt;br /&gt;
| MacroSystems (Germany)&lt;br /&gt;
|-&lt;br /&gt;
| 19796&lt;br /&gt;
| 4D54&lt;br /&gt;
| Markt &amp;amp; Technik&lt;br /&gt;
|-&lt;br /&gt;
| 22359&lt;br /&gt;
| 5757&lt;br /&gt;
| Markt &amp;amp; Technik&lt;br /&gt;
|-&lt;br /&gt;
| 26464&lt;br /&gt;
| 6760&lt;br /&gt;
| Combitec&lt;br /&gt;
|-&lt;br /&gt;
| 26470&lt;br /&gt;
| 6766&lt;br /&gt;
| Combitec&lt;br /&gt;
|-&lt;br /&gt;
| 28014&lt;br /&gt;
| 6D6E&lt;br /&gt;
| MNT Media and Technology UG&lt;br /&gt;
|-&lt;br /&gt;
| 32768&lt;br /&gt;
| 8000&lt;br /&gt;
| M.A.S.T.&lt;br /&gt;
|-&lt;br /&gt;
| 42240&lt;br /&gt;
| A500&lt;br /&gt;
| Aethreum Digital&lt;br /&gt;
|-&lt;br /&gt;
| 43437&lt;br /&gt;
| A9AD&lt;br /&gt;
| Reis-Ware&lt;br /&gt;
|-&lt;br /&gt;
| 43521&lt;br /&gt;
| AA01&lt;br /&gt;
| Cameron&lt;br /&gt;
|-&lt;br /&gt;
| 43537&lt;br /&gt;
| AA11&lt;br /&gt;
| Reis-Ware&lt;br /&gt;
|-&lt;br /&gt;
| 44359&lt;br /&gt;
| AD47&lt;br /&gt;
| Matay&lt;br /&gt;
|-&lt;br /&gt;
| 46504&lt;br /&gt;
| B5A8&lt;br /&gt;
| Phoenix&lt;br /&gt;
|-&lt;br /&gt;
| 48879&lt;br /&gt;
| BEEF&lt;br /&gt;
| Swiss Mountain Dog Products&lt;br /&gt;
|-&lt;br /&gt;
| 49160&lt;br /&gt;
| C008&lt;br /&gt;
| Combitec&lt;br /&gt;
|-&lt;br /&gt;
| 61453&lt;br /&gt;
| F00D&lt;br /&gt;
| Forefront Technologies Inc.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
For any changes/additions to this registry please use the [http://www.amigaos.net/contact AmigaOS web site contact form].&lt;/div&gt;</summary>
		<author><name>Costel Mincea</name></author>
	</entry>
	<entry>
		<id>https://wiki.amigaos.net/w/index.php?title=SANA-II_Revision_7&amp;diff=12593</id>
		<title>SANA-II Revision 7</title>
		<link rel="alternate" type="text/html" href="https://wiki.amigaos.net/w/index.php?title=SANA-II_Revision_7&amp;diff=12593"/>
		<updated>2026-09-02T11:09:43Z</updated>

		<summary type="html">&lt;p&gt;Costel Mincea: /* S2_DEVICEQUERY */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{WIP}}&lt;br /&gt;
= SANA-II Network Device Driver Specification =&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;SANA-II Network Device Driver Specification&amp;quot; is a standard for an Amiga software interface between networking hardware and network protocol stacks (or for software tools such as network monitors). A network protocol stack is a layer of software that network applications use to address particular processes on remote machines and to send data reliably in spite of hardware errors. There are several common network protocol stacks including &#039;&#039;TCP/IP&#039;&#039;, &#039;&#039;OSI&#039;&#039;, &#039;&#039;AppleTalk&#039;&#039;, &#039;&#039;DECNet&#039;&#039; and &#039;&#039;Novell&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
SANA-II device drivers are intended to allow multiple network protocol stacks running on the same machine to share one network device. For example, the TCP/IP and AppleTalk protocol stacks could both run on the same machine over one ethernet board. The device drivers are also intended to allow network protocol stacks to be written in a hardware-independent fashion so that a different version of each protocol stack doesn&#039;t have to be written for each networking hardware device.&lt;br /&gt;
&lt;br /&gt;
The standard does not address the writing of network applications. Application writers must not use SANA-II Device Drivers directly. Network applications must use the API provided by the network protocol software the application supports. The Amiga standard network API for TCP/IP is provided via the bsdsocket.library which is a part of Roadshow.&lt;br /&gt;
&lt;br /&gt;
To write a SANA-II device driver, you will need to be familiar with the specification documents for the hardware you are writing to and with the &amp;quot;SANA-II Network Device Driver Specification&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
To write a network protocol stack which will use SANA-II device drivers, you should have general familiarity with common network hardware and must be very familiar with the &amp;quot;SANA-II Network Device Driver Specification&amp;quot; as well as the specification for the protocol you are developing. If you are creating a new protocol, you must obtain a protocol type number for any hardware on which your protocol will be used.&lt;br /&gt;
&lt;br /&gt;
This version of the specification is final. Any new version of the standard (i.e., to add new features) is planned to be backward compatible. No SANA-II device driver or software utilizing those drivers should be written to any earlier version of the specification.&lt;br /&gt;
&lt;br /&gt;
Distribution of this version of the standard is unlimited. Anyone may write Amiga software which implements a SANA-II network device driver or which calls a SANA-II network device driver without restriction and may freely distribute such software that they have written.&lt;br /&gt;
&lt;br /&gt;
It is important to try to test each SANA-II device driver against all software which uses SANA-II devices. Available example programs are valuable in initial testing. The Amiga Networking Group is interested in receiving evaluation and/or beta test copies of all Amiga networking hardware, SANA-II device drivers and software which uses SANA-II devices. However, we make no assurances regarding any testing which we may or may not perform with such evaluation copies.&lt;br /&gt;
&lt;br /&gt;
The SANA-II standard caters to both Motorola 68000 platforms and PowerPC platforms.&lt;br /&gt;
&lt;br /&gt;
Please feel free to comment. You can contact the AmigaOS development team through the [http://www.amigaos.net/contact AmigaOS contact form].&lt;br /&gt;
&lt;br /&gt;
= Driver Form =&lt;br /&gt;
&lt;br /&gt;
SANA-II device drivers are Amiga Exec device drivers. They use an extended IORequest structure and a number of extended commands for tallying network statistics, sending broadcasts and multicasts, network addressing and the handling of unexpected packets. The SDK includes information on how to construct an Exec device.&lt;br /&gt;
&lt;br /&gt;
= Opening a SANA-II Device =&lt;br /&gt;
&lt;br /&gt;
As when opening any other Exec device, on the call to OpenDevice() a SANA-II device receives an IORequest structure which the device initializes for the opener&#039;s use. The opener must copy this structure if it desires to use multiple asynchronous requests. The SANA-II IORequest is defined as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct IOSana2Req&lt;br /&gt;
{&lt;br /&gt;
  struct IORequest ios2_Req;&lt;br /&gt;
  ULONG ios2_WireError;&lt;br /&gt;
  ULONG ios2_PacketType;&lt;br /&gt;
  UBYTE ios2_SrcAddr[SANA2_MAX_ADDR_BYTES];&lt;br /&gt;
  UBYTE ios2_DstAddr[SANA2_MAX_ADDR_BYTES];&lt;br /&gt;
  ULONG ios2_DataLength;&lt;br /&gt;
  APTR ios2_Data;&lt;br /&gt;
  APTR ios2_StatData;&lt;br /&gt;
  APTR ios2_BufferManagement;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; ios2_Req&lt;br /&gt;
: A standard Exec device IORequest.&lt;br /&gt;
; ios2_WireError&lt;br /&gt;
: A more specific device code which may be set when there is an io_Error. See &amp;amp;lt;devices/sana2.h&amp;amp;gt; for the defined WireErrors.&lt;br /&gt;
; ios2_PacketType&lt;br /&gt;
: The type of packet requested. See the section on &amp;quot;Packet Types&amp;quot;.&lt;br /&gt;
; ios2_SrcAddr&lt;br /&gt;
: The device fills in this field with the interface (network hardware) address of the source of the packet that satisfied a read command. The bytes used to hold the address will be left justified but the bit layout is dependent on the particular type of network.&lt;br /&gt;
; ios2_DstAddr&lt;br /&gt;
: Before the device user sends a packet, it fills this with the interface destination address of the packet. On receives, the device fills this with the interface destination address. Other commands may use this field differently (see the &amp;quot;SANA-II network device driver Autodocs&amp;quot; in the SDK). The bytes used to hold the address will be left justified but the bit layout is dependent on the particular type of network.&lt;br /&gt;
; ios2_DataLength&lt;br /&gt;
: The device user initializes this field with the amount of data available in the Data buffer before passing the IOSana2Req to the device. The device fills in this field with the size of the packet data as it was sent on the wire. This does not include the header and trailer information. Depending on the network type and protocol type, the driver may have to calculate this value. This is generally used only for reads and writes (including broadcast and multicast).&lt;br /&gt;
; ios2_Data&lt;br /&gt;
: A pointer to some abstract data structure containing packet data. &#039;&#039;Drivers may not directly manipulate or examine anything pointed to by Data!&#039;&#039; This is generally used only for reads and writes (including broadcast and multicast).&lt;br /&gt;
&lt;br /&gt;
; ios2_StatData&lt;br /&gt;
: Pointer to a structure in which to place a snapshot of device statistics. The data area must be long word aligned. This is only used on calls to the statistics commands.&lt;br /&gt;
&lt;br /&gt;
; ios2_BufferManagement&lt;br /&gt;
: The opener places a pointer to a tag list in this field before calling OpenDevice(). Functions pointed to in the tag list are called by the device when processing IORequests from the opener. When returned from OpenDevice(), this field contains a pointer to driver-private information used to access these functions. See &amp;quot;Buffer Management&amp;quot; below for more details.&lt;br /&gt;
&lt;br /&gt;
: Note that the &amp;lt;tt&amp;gt;ios2_BufferManagement&amp;lt;/tt&amp;gt; field provided by the driver on &amp;lt;tt&amp;gt;OpenDevice()&amp;lt;/tt&amp;gt; time in conjunction with &amp;lt;tt&amp;gt;io_Device&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;io_Unit&amp;lt;/tt&amp;gt; is the unique identifier for all requests coming from this protocol stack until &amp;lt;tt&amp;gt;CloseDevice()&amp;lt;/tt&amp;gt;. The driver must not ever change the &amp;lt;tt&amp;gt;ios2_BufferManagement&amp;lt;/tt&amp;gt; field for a protocol stack at run time, even if &amp;lt;tt&amp;gt;S2_SANAHOOK&amp;lt;/tt&amp;gt; is called to request extended features.&lt;br /&gt;
&lt;br /&gt;
The flags used with the device on OpenDevice() are (SANA2OPB_xxx):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Name&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| SANA2OPB_MINE&lt;br /&gt;
| Exclusive access to the unit requested.&lt;br /&gt;
|-&lt;br /&gt;
| SANA2OPB_PROM&lt;br /&gt;
| Promiscuous mode requested. Hardware which supports promiscuous mode allows all packets sent over the wire to be captured whether or not they are addressed to this node.&amp;lt;/br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;Note:&#039;&#039;&#039; Promiscuous mode requires exclusive opening of the device.&#039;&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The flags used during I/O requests are (SANA2IOB_xxx):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Name&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| SANA2IOB_RAW&lt;br /&gt;
| Raw packet read/write requested. Raw packets should include the entire data-link layer packet. Devices with the same hardware device number should have the same raw packet format.&lt;br /&gt;
|-&lt;br /&gt;
| SANA2IOB_BCAST&lt;br /&gt;
| Broadcast packet (received).&lt;br /&gt;
|-&lt;br /&gt;
| SANA2IOB_MCAST&lt;br /&gt;
| Multicast packet (received).&lt;br /&gt;
|-&lt;br /&gt;
| SANA2IOB_QUICK&lt;br /&gt;
| Quick IO requested.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Buffer Management =&lt;br /&gt;
&lt;br /&gt;
Unlike most other Exec Device drivers, SANA-II drivers have no internal buffers. Instead, they read/write to/from an abstract data structure allocated by the driver user. The driver accesses these buffers only via functions that the driver user provides to the driver. The driver user must provide two functions: one copies data to the abstract data structure and one copies data from the abstract data structure. The driver user can therefore choose the data structure used for buffer management by both the driver and driver user in order to have efficient memory and CPU usage overall.&lt;br /&gt;
&lt;br /&gt;
The IOSana2Req contains a pointer to data and the length of said data. A driver is not allowed to make assumptions about how the data is stored. The driver cannot directly manipulate or examine the buffer in any manner. The driver can only access the buffer by calling the functions provided by the driver user.&lt;br /&gt;
&lt;br /&gt;
Before calling OpenDevice(), the driver user points ios2_BufferManagement to a list of tags (defined in &amp;amp;lt;devices/sana2.h&amp;amp;gt;) which include pointers to the buffer management functions required by the driver (defined below). The driver will fail to open if the driver user does not supply all of the required functions. If the device opens successfully, the driver sets ios2_BufferManagement to a value which this opener must use in all future calls to the driver. This &amp;quot;magic cookie&amp;quot; is used from then on to access these functions (a &amp;quot;magic cookie&amp;quot; is a value which one software entity passes to another but which is only meaningful to one of the software entities). The driver user may not use the &amp;quot;magic cookie&amp;quot; in any way--it is for the driver to do with as it wishes. The driver could in theory choose to just copy the tag list to driver-owned memory and then parse the list for every IORequest, but it is much more efficient for the driver to create some sort of table of functions and to point ios2_BufferManagement to that table.&lt;br /&gt;
&lt;br /&gt;
Another recommendation for the ``magic cookie`` is to use it to maintain a separate packet read queue for each device opener. This would allow multiple protocol stacks that all wish to receive the same packet type to work together without having to &amp;quot;know&amp;quot; about each other as &#039;&#039;Envoy&#039;&#039; and &#039;&#039;AS225&#039;&#039; do right now. What does multiple protocol stack support mean? Basically this means that each opener gets all the packets necessary. If a packet comes in that fills a request for more than one opener of the device, all of them will get a copy of the packet. This feature should never be left out of a device design. If it is missing, the usefulness of the device is severely limited.&lt;br /&gt;
&lt;br /&gt;
In order to help system load, a packet filter callback allows protocol stacks to reject packets that are known to not be useful. &#039;&#039;Envoy&#039;&#039;&#039;s nipc.library (for example) could be modified to reject TCP packets (as it never uses them).&lt;br /&gt;
&lt;br /&gt;
The specification currently defines the following tags for the OpenDevice() ios2_BufferManagement tag list:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Copy data from network interface to protocol stack buffer&lt;br /&gt;
! Tag&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| S2_CopyToBuff (mandatory)&lt;br /&gt;
| This is a pointer to a function which conforms to the CopyToBuff Autodoc.&lt;br /&gt;
|-&lt;br /&gt;
| S2_CopyToBuff16 (optional)&lt;br /&gt;
| Copy to a 16 bit aligned buffer using 16 bit data words.&lt;br /&gt;
|-&lt;br /&gt;
| S2_CopyToBuff32 (optional)&lt;br /&gt;
| Copy to a 32 bit aligned buffer using 32 bit data words.&lt;br /&gt;
|-&lt;br /&gt;
| S2_DMACopyToBuff32 (optional)&lt;br /&gt;
| Perform a DMA copy to a 32 bit aligned contiguous buffer using 32 bit data words.&lt;br /&gt;
|-&lt;br /&gt;
| S2_DMACopyToBuff64 (optional)&lt;br /&gt;
| Perform a DMA copy to a 64 bit aligned contiguous buffer using 64 bit data words.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Copy data from protocol stack buffer to network interface&lt;br /&gt;
! Tag&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| S2_CopyFromBuff (mandatory)&lt;br /&gt;
| This is a pointer to a function which conforms to the CopyFromBuff Autodoc.&lt;br /&gt;
|-&lt;br /&gt;
| S2_CopyFromBuff16 (optional)&lt;br /&gt;
| Copy from a 16 bit aligned buffer using 16 bit data words.&lt;br /&gt;
|-&lt;br /&gt;
| S2_CopyFromBuff32 (optional)&lt;br /&gt;
| Copy from a 32 bit aligned buffer using 32 bit data words.&lt;br /&gt;
|-&lt;br /&gt;
| S2_DMACopyFromBuff32 (optional)&lt;br /&gt;
| Perform a DMA copy from a 32 bit aligned contiguous buffer using 32 bit data words.&lt;br /&gt;
|-&lt;br /&gt;
| S2_DMACopyFromBuff64 (optional)&lt;br /&gt;
| Perform a DMA copy from a 64 bit aligned contiguous buffer using 64 bit data words.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Filter data before protocol stack buffer&lt;br /&gt;
! Tag&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| S2_PacketFilter (optional)&lt;br /&gt;
| This is a pointer to a standard Hook to be called before S2_CopyToBuff is done. See the PacketFilter Autodoc for more information.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Logging messages from the driver&lt;br /&gt;
! Tag&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| S2_Log (optional)&lt;br /&gt;
| This is a pointer to a standard Hook to be called when the driver logs events.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Better buffer management ==&lt;br /&gt;
&lt;br /&gt;
The mandatory buffer management callbacks may not be very efficient for certain types of hardware. They also do not allow driver DMA access.&lt;br /&gt;
&lt;br /&gt;
All the new features are completely optional and do not collide with existing features. They may be used only when the protocol stack asks for them on opening a driver.&lt;br /&gt;
&lt;br /&gt;
The enhancements consist of several new tags that may be specified by a protocol stack on OpenDevice() to offer certain data transfer options. It is up to the device driver to chose which callbacks to use at what time. These tags are advisory only and may be ignored by the driver for any data buffer at any time:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| S2_CopyToBuff16&lt;br /&gt;
|-&lt;br /&gt;
| S2_CopyFromBuff16&lt;br /&gt;
|-&lt;br /&gt;
| S2_CopyToBuff32&lt;br /&gt;
|-&lt;br /&gt;
| S2_CopyFromBuff32&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
These are optional callbacks presented to the device with the same calling interface as for S2_CopyToBuff or S2_CopyFromBuff, respectively. The difference to the original callbacks is the required and guaranteed transfer size and alignment for accessing the device&#039;s buffer for a single piece of a data of either 16 or 32 bits, a data word. The copy function called may only use 16/32 bit aligned read/write commands of 16/32 bits at once to transfer the data words, respectively. If the buffer data length is not a multiple of the required data word transfer size, the last data word transfer may contain garbage padding in either transfer direction.&lt;br /&gt;
&lt;br /&gt;
The following tags have been added to support direct writes into hardware buffers that do not allow arbitrarily sized or aligned accesses:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| S2_DMACopyToBuff32&lt;br /&gt;
|-&lt;br /&gt;
| S2_DMACopyFromBuff32&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If the protocol stack wants to optionally enhance data transfer efficiency with DMA supporting devices, it may pass any of these optional tags to the device on OpenDevice().&lt;br /&gt;
&lt;br /&gt;
If the device driver supports DMA, it may call the respective callback with the abstract magic cookie ios2_Data in register A0. The callback may return NULL in D0. In this case, the driver may not use DMA for this buffer. Alternatively, the callback may return the address of the actual data buffer in D0, if it has these characteristics:&lt;br /&gt;
&lt;br /&gt;
* The buffer is in contiguous memory. Depending on the intended data direction, it shall be readable or writable.&lt;br /&gt;
* The buffer is aligned on a 32 bit boundary.&lt;br /&gt;
* The buffer size shall be a multiple of 32 bit and it is at least = ios2_DataLength.&lt;br /&gt;
* It is up to the driver to decide if it can use DMA for this buffer and it shall fall back to the standard CPU callbacks if necessary. The data transfer method actually used by the driver will not be known in advance by the protocol stack.&lt;br /&gt;
&lt;br /&gt;
The following tags have been added to allow for 64 bit aligned PCI DMA accesses to take place:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| S2_DMACopyToBuff64&lt;br /&gt;
|-&lt;br /&gt;
| S2_DMACopyFromBuff64&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
These two callbacks are identical in operation to the &amp;lt;tt&amp;gt;S2_DMACopyToBuff32&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2_DMACopyFromBuff32&amp;lt;/tt&amp;gt; callbacks. The difference is in that the memory region DMA is to take place in must be aligned to a 64 bit boundary and must be large enough to hold data that is a multiple of 64 bits in size.&lt;br /&gt;
&lt;br /&gt;
== Best buffer management ==&lt;br /&gt;
&lt;br /&gt;
The SANA-II driver interface is intended to transform data between the hardware layer and the link layer, to be used by networking software such as TCP/IP stacks. This transformation is performed by callback functions which are supplied by the networking software at the time the device driver is opened. The device driver then invokes these functions later in order to transfer data received and data to be sent.&lt;br /&gt;
&lt;br /&gt;
The function parameters used by these callbacks are passed in 68000 registers for the lowest overhead. The problem with 68000 register parameters is that on the PowerPC platform, this form of parameter passing may require the use of emulation code. This is costly and may incur a severe performance penalty. It is an even greater problem if PowerPC native networking software is calling PowerPC native networking driver software and the other way round. In both cases the runtime environment will have to enter emulation mode, return to to PowerPC native execution, dip into emulation mode and return to native PowerPC execution. It would be much better if the chain of execution would stay in PowerPC mode all the time.&lt;br /&gt;
&lt;br /&gt;
Alternatively, if a hook function is used, the operating system may be able to decide whether the function to be invoked needs emulating or called directly. The &amp;lt;tt&amp;gt;Hook&amp;lt;/tt&amp;gt; effectively works as an abstraction which makes the function invocation platform independent.&lt;br /&gt;
&lt;br /&gt;
The following standard wraps the copying and logging functions into the standardized &amp;lt;tt&amp;gt;Hook&amp;lt;/tt&amp;gt; interface.&lt;br /&gt;
&lt;br /&gt;
==== The hook function ====&lt;br /&gt;
&lt;br /&gt;
The hook function itself is invoked with the following parameters:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
   result = hook_function(hook, sana2req, sana2hookmsg)&lt;br /&gt;
&lt;br /&gt;
   ULONG hook_function(struct Hook *hook,&lt;br /&gt;
                       struct IOSana2Req *sana2req,&lt;br /&gt;
                       struct SANA2HookMsg *sana2hookmsg);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the result is not necessarily of type &amp;lt;tt&amp;gt;ULONG&amp;lt;/tt&amp;gt;. It is a 32 bit value, which can be a boolean result code (for &amp;lt;tt&amp;gt;CopyFromBuff&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;CopyToBuff&amp;lt;/tt&amp;gt; and their like) or a pointer to a memory address (for &amp;lt;tt&amp;gt;DMACopyToBuff&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DMACopyFromBuff&amp;lt;/tt&amp;gt; and their like).&lt;br /&gt;
&lt;br /&gt;
=== Data structures ===&lt;br /&gt;
&lt;br /&gt;
The following hook messages are to be used:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct SANA2HookMsg&lt;br /&gt;
{&lt;br /&gt;
  ULONG shm_Method;&lt;br /&gt;
  ULONG shm_MsgSize;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this data structure the &amp;lt;tt&amp;gt;shm_Method&amp;lt;/tt&amp;gt; field would indicate the task to be performed. This can be a request to copy data or to store a log message. The &amp;lt;tt&amp;gt;shm_MsgSize&amp;lt;/tt&amp;gt; field tells you how large the data structure is for future enhancements which may cause the data structure to grow.&lt;br /&gt;
&lt;br /&gt;
==== Copying operations ====&lt;br /&gt;
&lt;br /&gt;
For copying operations the message is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct SANA2CopyHookMsg&lt;br /&gt;
{&lt;br /&gt;
  ULONG schm_Method;&lt;br /&gt;
  ULONG schm_MsgSize;&lt;br /&gt;
&lt;br /&gt;
  APTR  schm_To;&lt;br /&gt;
  APTR  schm_From;&lt;br /&gt;
  ULONG schm_Size;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The structure members are as follows:&lt;br /&gt;
&lt;br /&gt;
; schm_Method&lt;br /&gt;
: This must be one &amp;lt;tt&amp;gt;S2_CopyToBuff&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;S2_CopyFromBuff&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;S2_CopyToBuff16&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;S2_CopyFromBuff16&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;S2_CopyToBuff32&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;S2_CopyFromBuff32&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;S2_DMACopyToBuff32&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;S2_DMACopyFromBuff32&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;S2_DMACopyToBuff64&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;S2_DMACopyFromBuff64&amp;lt;/tt&amp;gt; to identify the function to be performed.&lt;br /&gt;
&lt;br /&gt;
; schm_MsgSize&lt;br /&gt;
: Size of this message data structure in bytes. This must be &amp;amp;gt;= 20 for this message type.&lt;br /&gt;
: The driver shall set &amp;lt;tt&amp;gt;schm_MsgSize&amp;lt;/tt&amp;gt; always correctly to be compliant. The protocol stack shall use this field to validate the message and to reject/ignore bad messages via a &amp;lt;tt&amp;gt;FALSE&amp;lt;/tt&amp;gt; hook function return value. For DMA related hooks, a &amp;lt;tt&amp;gt;FALSE&amp;lt;/tt&amp;gt; return value is equivalent to a &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; pointer.&lt;br /&gt;
&lt;br /&gt;
; schm_To&lt;br /&gt;
: Equivalent to the &amp;lt;tt&amp;gt;to&amp;lt;/tt&amp;gt; parameter of the &amp;lt;tt&amp;gt;CopyFromBuff&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;CopyToBuff&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;DMACopyToBuff&amp;lt;/tt&amp;gt; functions.&lt;br /&gt;
&lt;br /&gt;
; schm_From&lt;br /&gt;
: Equivalent to the &amp;lt;tt&amp;gt;from&amp;lt;/tt&amp;gt; parameter of the &amp;lt;tt&amp;gt;CopyFromBuff&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;CopyToBuff&amp;lt;/tt&amp;gt; functions.&lt;br /&gt;
&lt;br /&gt;
; schm_Size&lt;br /&gt;
: Equivalent to the &amp;lt;tt&amp;gt;n&amp;lt;/tt&amp;gt; parameter of the &amp;lt;tt&amp;gt;CopyFromBuff&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;CopyToBuff&amp;lt;/tt&amp;gt;, functions.&lt;br /&gt;
&lt;br /&gt;
==== Logging operations ====&lt;br /&gt;
&lt;br /&gt;
For logging operations the message is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct SANA2LogHookMsg&lt;br /&gt;
{&lt;br /&gt;
  ULONG  slhm_Method;&lt;br /&gt;
  ULONG  slhm_MsgSize;&lt;br /&gt;
&lt;br /&gt;
  ULONG  slhm_Priority;&lt;br /&gt;
  STRPTR slhm_Name;&lt;br /&gt;
  STRPTR slhm_Message;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The structure members would be used as follows:&lt;br /&gt;
&lt;br /&gt;
; slhm_Method&lt;br /&gt;
: This must be &amp;lt;tt&amp;gt;S2_Log&amp;lt;/tt&amp;gt;, as defined in the SANA-IIR4 specification.&lt;br /&gt;
&lt;br /&gt;
; slhm_MsgSize&lt;br /&gt;
: Size of this message data structure in bytes. This must be &amp;amp;gt;= 20 for this message type.&lt;br /&gt;
: The driver shall set &amp;lt;tt&amp;gt;slhm_MsgSize&amp;lt;/tt&amp;gt; always correctly to be compliant. The protocol stack shall use this field to validate the message and to reject/ignore bad messages via a &amp;lt;tt&amp;gt;FALSE&amp;lt;/tt&amp;gt; hook function return value. For DMA related hooks, a &amp;lt;tt&amp;gt;FALSE&amp;lt;/tt&amp;gt; return value is equivalent to a &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; pointer.&lt;br /&gt;
&lt;br /&gt;
; slhm_Priority&lt;br /&gt;
: The smaller this value, the more important the message to be logged or displayed. The following priority levels are defined (similar to the Unix syslog() mechanism):&lt;br /&gt;
:{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| S2LOG_Emergency || A panic condition.&lt;br /&gt;
|-&lt;br /&gt;
| S2LOG_Alert || A condition that should be corrected immediately.&lt;br /&gt;
|-&lt;br /&gt;
| S2LOG_Critical || Critical conditions.&lt;br /&gt;
|-&lt;br /&gt;
| S2LOG_Error || A plain error.&lt;br /&gt;
|-&lt;br /&gt;
| S2LOG_Warning || A warning message.&lt;br /&gt;
|-&lt;br /&gt;
| S2LOG_Notice || Conditions that are not error conditions, but should possibly be handled specially.&lt;br /&gt;
|-&lt;br /&gt;
| S2LOG_Information || An informational message.&lt;br /&gt;
|-&lt;br /&gt;
| S2LOG_Debug || Messages that contain information normally of use only when debugging.&lt;br /&gt;
|}&lt;br /&gt;
: Only these priority values may be used by a driver. It is suggested that a driver is configurable to generate different types of messages or not, e.g., a driver may be configured to only emit &amp;lt;tt&amp;gt;S2LOG_Emergency&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2LOG_Debug&amp;lt;/tt&amp;gt; messages&lt;br /&gt;
&lt;br /&gt;
; slhm_Name&lt;br /&gt;
: Pointer to a &amp;lt;tt&amp;gt;NUL&amp;lt;/tt&amp;gt;-terminated string which identifies the source of this message. This can be &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; in which case the OS device name of the driver shall be used by the protocol stack.&lt;br /&gt;
&lt;br /&gt;
; slhm_Message&lt;br /&gt;
: Pointer to a &amp;lt;tt&amp;gt;NUL&amp;lt;/tt&amp;gt;-terminated string which contains the log message. The text should not contain any formatting characters such as line feeds or carriage returns. The &amp;lt;tt&amp;gt;slhm_Message&amp;lt;/tt&amp;gt; member must never be &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt;.&lt;br /&gt;
: All message texts shall preferably be formatted in the current user&#039;s locale. If that is not possible, the english language shall be used. &amp;lt;tt&amp;gt;slhm_Name&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;slhm_Message&amp;lt;/tt&amp;gt; shall only contain printable characters.&lt;br /&gt;
&lt;br /&gt;
=== Application and driver software use of the new functions ===&lt;br /&gt;
&lt;br /&gt;
Since plenty of software exists which uses the &#039;traditional&#039; &amp;lt;tt&amp;gt;TagItem&amp;lt;/tt&amp;gt; list provided at &amp;lt;tt&amp;gt;OpenDevice()&amp;lt;/tt&amp;gt; time, drivers must always examine these parameters and not expect a &amp;lt;tt&amp;gt;S2_SANA2HOOK&amp;lt;/tt&amp;gt; command to be sent later.&lt;br /&gt;
&lt;br /&gt;
If the new &amp;lt;tt&amp;gt;Hook&amp;lt;/tt&amp;gt;-based callback functions are used then the driver must invoke the Hooks via &amp;lt;tt&amp;gt;utility.library/CallHookPkt&amp;lt;/tt&amp;gt;. It must never invoke the hook functions through local assembly language stubs or the &amp;lt;tt&amp;gt;amiga.lib/CallHook&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;amiga.lib/CallHookA&amp;lt;/tt&amp;gt; functions.&lt;br /&gt;
&lt;br /&gt;
=== Caveats ===&lt;br /&gt;
&lt;br /&gt;
The functionality above suggests that one could do entirely without the &amp;lt;tt&amp;gt;TagItem&amp;lt;/tt&amp;gt; list passed in at &amp;lt;tt&amp;gt;OpenDevice()&amp;lt;/tt&amp;gt; time. However, at this time it is hard to tell how existing driver software will react to empty &amp;lt;tt&amp;gt;TagItem&amp;lt;/tt&amp;gt; lists or even a NULL pointer in the &amp;lt;tt&amp;gt;IOSana2Req-&amp;amp;gt;ios2_BufferManagement&amp;lt;/tt&amp;gt; field. It is therefore important to always provide for a &amp;lt;tt&amp;gt;TagItem&amp;lt;/tt&amp;gt; list which includes proper (i.e. they must point to working functions and may not be &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt;) function pointers for the &amp;lt;tt&amp;gt;S2_CopyToBuff&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2_CopyFromBuff&amp;lt;/tt&amp;gt; tags. Once the device has been opened successfully, the next step is to try and install the copy &amp;lt;tt&amp;gt;Hook&amp;lt;/tt&amp;gt; through the proposed &amp;lt;tt&amp;gt;S2_SANA2HOOK&amp;lt;/tt&amp;gt; command. If the command fails, the application can still expect that the &amp;lt;tt&amp;gt;S2_CopyToBuff&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2_CopyFromBuff&amp;lt;/tt&amp;gt; tags supplied at &amp;lt;tt&amp;gt;OpenDevice()&amp;lt;/tt&amp;gt; time will work.&lt;br /&gt;
&lt;br /&gt;
== Packet filtering ==&lt;br /&gt;
&lt;br /&gt;
With the original &amp;quot;SANA-II Network Device Driver Specification&amp;quot;, a protocol stack could open a device and ask for certain packet types. It got all the packets that matched this type. As it turned out, this could be mighty inefficient if there were packets that the protocol stack did not use at all. These would go into read processing of the protocol stack and waste CPU time even though they could have been easily identified on arrival.&lt;br /&gt;
&lt;br /&gt;
== Driver event logging ==&lt;br /&gt;
&lt;br /&gt;
A driver may want to report an important event for the user to see. Adding a log message to a file or opening a window to display a message in may not be the optimum approach as the user may be unaware of the context into which the message belongs. It may be advisable for the driver to use the message reporting and logging facilities used by the client software that uses its services, such as a TCP/IP stack. The &amp;lt;tt&amp;gt;S2_Log&amp;lt;/tt&amp;gt; callback hook is intended to provide for such a link.&lt;br /&gt;
&lt;br /&gt;
If present, the driver must use this callback hook rather than whatever logging methods it implements itself. Note that unlike the other SANA-II callbacks, this is a regular hook, as to be invoked using &amp;lt;tt&amp;gt;utility.library&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;CallHookPkt()&amp;lt;/tt&amp;gt;. The hook function is invoked using the following parameters:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
log_hook_function(hook, reserved, message)&lt;br /&gt;
&lt;br /&gt;
void log_hook_function(struct hook * hook,APTR reserved,&lt;br /&gt;
                       struct S2LogMessage * message);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;reserved&amp;lt;/tt&amp;gt; parameter &#039;&#039;&#039;must&#039;&#039;&#039; be set to &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt;. The &amp;lt;tt&amp;gt;S2LogMessage&amp;lt;/tt&amp;gt; structure passed as the third parameter looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct S2LogMessage&lt;br /&gt;
{&lt;br /&gt;
   LONG   s2lm_Size;&lt;br /&gt;
   ULONG  s2lm_Priority;&lt;br /&gt;
   STRPTR s2lm_Name;&lt;br /&gt;
   STRPTR s2lm_Message;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The individual structure members serve the following functions:&lt;br /&gt;
&lt;br /&gt;
; s2lm_Size&lt;br /&gt;
: Size of the &amp;lt;tt&amp;gt;S2LogMessage&amp;lt;/tt&amp;gt; structure, in bytes. The idea is to extend this data structure in the future, and the size stored in here tells you how long the structure is. The size &#039;&#039;&#039;must&#039;&#039;&#039; always be &amp;amp;gt;= 16.&lt;br /&gt;
&lt;br /&gt;
;s2lm_Priority&lt;br /&gt;
: The smaller this value, the more important the message to be logged or displayed. The following priority levels are defined (similar to the Unix &amp;lt;tt&amp;gt;syslog()&amp;lt;/tt&amp;gt; mechanism):&lt;br /&gt;
:{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| S2LOG_Emergency || A panic condition.&lt;br /&gt;
|-&lt;br /&gt;
| S2LOG_Alert || A condition that should be corrected immediately.&lt;br /&gt;
|-&lt;br /&gt;
| S2LOG_Critical || Critical conditions.&lt;br /&gt;
|-&lt;br /&gt;
| S2LOG_Error || A plain error.&lt;br /&gt;
|-&lt;br /&gt;
| S2LOG_Warning || A warning message.&lt;br /&gt;
|-&lt;br /&gt;
| S2LOG_Notice || Conditions that are not error conditions, but should possibly be handled specially.&lt;br /&gt;
|-&lt;br /&gt;
| S2LOG_Information || An informational message.&lt;br /&gt;
|-&lt;br /&gt;
| S2LOG_Debug || Messages that contain information normally of use only when debugging.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
; s2lm_Name&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Pointer to a &amp;lt;tt&amp;gt;NUL&amp;lt;/tt&amp;gt;-terminated string which identifies the source of this message. This can be &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; in which case the name is treated as being unknown.&lt;br /&gt;
&lt;br /&gt;
; s2lm_Message&lt;br /&gt;
: Pointer to a &amp;lt;tt&amp;gt;NUL&amp;lt;/tt&amp;gt;-terminated string which contains the log message. The text should not contain any formatting characters such as line feeds or carriage returns. The &amp;lt;tt&amp;gt;s2lm_Message&amp;lt;/tt&amp;gt; member &#039;&#039;&#039;must never&#039;&#039;&#039; be &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
All error messages issued by the device driver should use the current system locale wherever this is possible. The purpose of an error message is, after all, to assist the user in recovering from the error. Which may be difficult if the user does not even know the language in which the message is written.&lt;br /&gt;
&lt;br /&gt;
The log message string is valid until the log hook function returns. If the driver needs to retain the message any longer, it must make a copy of it.&lt;br /&gt;
&lt;br /&gt;
Since the client software into which the log hook calls may have to allocate memory to hold and display the log message, the log hook &#039;&#039;&#039;must not&#039;&#039;&#039; be called from interrupt code. The log hook shall not &amp;lt;tt&amp;gt;Wait()&amp;lt;/tt&amp;gt; and it shall assume only a &amp;lt;tt&amp;gt;Task&amp;lt;/tt&amp;gt; calling context of unknown priority. &amp;lt;tt&amp;gt;dos.library&amp;lt;/tt&amp;gt; functions may not be called. Also, stack space is provided only to call &amp;lt;tt&amp;gt;exec.library&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;utility.library&amp;lt;/tt&amp;gt; functions. The callback shall not place excessive data on the stack. Stack space should be considered limited and the callback should be designed to be fast and short.&lt;br /&gt;
&lt;br /&gt;
This hook is installed at &amp;lt;tt&amp;gt;OpenDevice()&amp;lt;/tt&amp;gt; time, which means that the hook is used for the unit that was opened, and not just for the I/O request it was opened with. The hook must remain installed until the I/O request that installed it is eventually used to close the device. When this happens, the device should fall back to use no log hook at all. No nesting is permitted or required.&lt;br /&gt;
&lt;br /&gt;
= Packet Type =&lt;br /&gt;
&lt;br /&gt;
Network frames always have a type field associated with them. These type fields vary in length, position and meaning by frame type (frame types generally correspond one-to-one with hardware types, but see &amp;quot;Ethernet Packet Types&amp;quot; below). The meanings of the type numbers are always carefully defined and every type number is registered with some official body. Do not use a type number which is not registered for any standard hardware you use or in a manner inconsistent with that registration.&lt;br /&gt;
&lt;br /&gt;
The type field allows the SANA-II device driver to fulfill CMD_READs based on the type of packet the driver user wants. Multiple protocols can therefore run over the same wire using the same driver without stepping on each other&#039;s toes.&lt;br /&gt;
&lt;br /&gt;
Packet types are specified as a long word. Unfortunately, the type field means different things on different wires. Driver users must allow their software to be configured with a SANA-II device name, unit number and the type number(s) used by the protocol stack with each device. This way, if new hardware becomes available, a hardware manufacturer can supply a listing of type assignments to configure pre-existing software.&lt;br /&gt;
&lt;br /&gt;
== Ethernet Packet Types ==&lt;br /&gt;
&lt;br /&gt;
Ethernet has a special problem with packet types. Two types of ethernet frames can be sent over the same wire: ethernet and 802.3. These frames differ in that the Type field of an ethernet frame is the Length field of an 802.3 frame. This creates a problem in that demultiplexing incoming packets can be cumbersome and inefficient, as well as requiring driver users to be aware of the frame type used.&lt;br /&gt;
&lt;br /&gt;
All 802.3 frames have numbers less than 1500 in the Type field. The only frames with numbers less than 1500 in the type field are 802.3 frames. SANA-II ethernet drivers abnormally return packets contained in ethernet frames when the requested Type falls within the 802.3 range-if the Type requested is within the 802.3 range, the driver returns the next packet contained within an 802.3 frame, regardless of the type specified for the packet within the 802.3 frame. This requires that there be no more than one driver user requesting 802.3 packets and that it do its own interpretation of the frames.&lt;br /&gt;
&lt;br /&gt;
== ARCNET Frames ==&lt;br /&gt;
&lt;br /&gt;
ARCNET also has a special problem with framing. ARCNET frames consist of a hardware header and a software header. The software header is in the data area of the hardware packet, and includes at least the protocol ID.&lt;br /&gt;
&lt;br /&gt;
There are two types of software header. Old-style ARCNET software headers consist entirely of a one or two byte protocol ID. New ARCNET software headers (defined in RFC 1201 and in the paper &amp;quot;ARCNET Packet Header Definition Standard&amp;quot;, Novell, Inc., 1989) include more information. They allow more efficient use of ARCNET through data link layer fragmentation and reassembly (ARCNET has a small Maximum Transmission Unit) and allow sending any size packet up to the MTU (rather than requiring that packets of size 253, 254 and 255 be padded to at least 256 bytes).&lt;br /&gt;
&lt;br /&gt;
SANA-II device drivers for ARCNET should implement the old ARCNET packet headers. Driver users which wish to interoperate with platforms using the new software headers must add the new fields to the data to be sent and must process it for incoming data. A SANA-II driver which implemented the data link layer fragmentation internally (and advertised a large MTU) could be more efficient than requiring the driver user to do it. This would make driver writing more difficult and reduce interoperability, but if there is ever a demand for that extra performance, a new hardware type may be assigned by Amiga for SANA-II ARCNET device drivers which implement the new framing.&lt;br /&gt;
&lt;br /&gt;
= Addressing =&lt;br /&gt;
&lt;br /&gt;
In the SANA-II standard, network hardware addresses are stored in an array of &#039;&#039;n&#039;&#039; bytes. No meaning is ascribed by the standard to the contents of the array.&lt;br /&gt;
&lt;br /&gt;
In case there exists a network which does not have an address field consisting of a number of bits not divisible by eight, add pad bits at the end of the bit stream. For example, if an address is ten bits long it will be stored like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
98765432 10PPPPPP&lt;br /&gt;
BYTE 0   BYTE 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where the numerals are bit numbers and &amp;quot;P&amp;quot; is a pad (ignored) bit.&lt;br /&gt;
&lt;br /&gt;
Driver users which do not implement the bit shifting necessary to use a network with such addressing (if one exists) should at least check the number of significant bits in the address field (returned from the device&#039;s S2_DEVICEQUERY function) to make sure that it is evenly divisible by eight.&lt;br /&gt;
&lt;br /&gt;
Driver users will map hardware addresses to protocol addresses in a protocol and hardware dependent manner, as described by the relevant standards (i.e., RFC 826 for TCP/IP over Ethernet, RFC 1201 or RFC 1051 for TCP/IP over ARCNET). Some protocols will always use the same mapping on all hardware, but other protocols will have particular address mapping schemes for some particular hardware and a reasonable default for other (unknown) hardware.&lt;br /&gt;
&lt;br /&gt;
Some SANA-II devices will have &amp;quot;hardware addresses&amp;quot; which aren&#039;t really hardware addresses. As an example, consider &#039;&#039;PPP&#039;&#039; (Point-to-Point Protocol). PPP is a standard for transmitting IP packets over a serial line. It uses IP addresses negotiated during the establishment of a connection. In a SANA-II driver implementation of PPP, the driver would negotiate the address at S2_CONFIGINTERFACE. Thus, the address in SrcAddr returned by the device on an S2_CONFIGINTERFACE (or in a subsequent S2_GETSTATIONADDRESS) will be a protocol address, not a true hardware address.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; Some hardware always uses a ROM hardware address. Other hardware which has a ROM address or is configurable with DIP switches may be overridden by software. Some hardware always dynamically allocates a new hardware address at initialization. See &amp;quot;Configuration&amp;quot; for details on how this is handled by driver writers and by driver users.&lt;br /&gt;
&lt;br /&gt;
= Hardware Type =&lt;br /&gt;
&lt;br /&gt;
The HardwareType returned by the device&#039;s S2_DEVICEQUERY function is necessary for those protocols whose standards require different behavior on different hardware. It is also useful for determining appropriate packet type numbers to use with the device. The HardwareType values already issued for standard network hardware are the same as those in RFC 1060 (assigned numbers). Hardware developers implementing networks without a SANA-II hardware number must contact the AmigaOS development team to have a new hardware type number assigned. Driver users should all have reasonable defaults which can be used for hardware with which they are not familiar.&lt;br /&gt;
&lt;br /&gt;
= Errors =&lt;br /&gt;
&lt;br /&gt;
The SANA-II extended IORequest structure (struct IOSana2Req) includes both the ios2_Error and ios2_WireError fields. Driver users must always check IOSana2Reqs on return for an error in ios2_Error. ios2_Error will be zero if no error occurred, otherwise it will contain a value from &amp;amp;lt;exec/errors.h&amp;amp;gt; or &amp;amp;lt;devices/sana2.h&amp;amp;gt;. If there was an error, there may be more specific information in ios2_WireError. Drivers are required to fill in the WireError if there is an applicable error code.&lt;br /&gt;
&lt;br /&gt;
Error codes are #define&#039;d in the &amp;quot;defined errors&amp;quot; sections of the file &amp;amp;lt;devices/sana2.h&amp;amp;gt;:&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! IOSana2Req S2io_Error field&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| S2ERR_NO_RESOURCES&lt;br /&gt;
| Insufficient resources available.&lt;br /&gt;
|-&lt;br /&gt;
| S2ERR_BAD_ARGUMENT&lt;br /&gt;
| Noticeably bad argument.&lt;br /&gt;
|-&lt;br /&gt;
| S2ERR_BAD_STATE&lt;br /&gt;
| Command inappropriate for current state.&lt;br /&gt;
|-&lt;br /&gt;
| S2ERR_BAD_ADDRESS&lt;br /&gt;
| Noticeably bad address.&lt;br /&gt;
|-&lt;br /&gt;
| S2ERR_MTU_EXCEEDED&lt;br /&gt;
| Write data too large.&lt;br /&gt;
|-&lt;br /&gt;
| S2ERR_NOT_SUPPORTED&lt;br /&gt;
| Command is not supported by this driver. This is similar to IOERR_NOCMD as defined in &amp;amp;lt;exec/errors.h&amp;amp;gt; but S2ERR_NOT_SUPPORTED indicates that the requested command is a valid SANA-II command and that the driver does not support it because the hardware is incapable of supporting it (e.g., S2_MULTICAST). Note that IOERR_NOCMD is still valid for reasons other than a lack of hardware support (i.e., commands which are no-ops in a SANA-II driver).&lt;br /&gt;
|-&lt;br /&gt;
| S2ERR_SOFTWARE&lt;br /&gt;
| Software error of some kind.&lt;br /&gt;
|-&lt;br /&gt;
| S2ERR_OUTOFSERVICE&lt;br /&gt;
| When a hardware device is taken off-line, any pending requests are returned with this error.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
See also the standard errors in &amp;amp;lt;exec/errors.h&amp;amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! IOSana2Req S2io_WireError field&lt;br /&gt;
! Description&lt;br /&gt;
! Value&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_NOT_CONFIGURED&lt;br /&gt;
| Command requires unit to be configured.&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_UNIT_ONLINE&lt;br /&gt;
| Command requires that the unit be off-line.&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_UNIT_OFFLINE&lt;br /&gt;
| Command requires that the unit be on-line.&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_ALREADY_TRACKED&lt;br /&gt;
| Protocol is already being tracked.&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_NOT_TRACKED&lt;br /&gt;
| Protocol is not being tracked.&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_BUFF_ERROR&lt;br /&gt;
| Buffer management function returned an error.&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_SRC_ADDRESS&lt;br /&gt;
| Problem with the source address field.&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_DST_ADDRESS&lt;br /&gt;
| Problem with destination address field.&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_BAD_BROADCAST&lt;br /&gt;
| Problem with an attempt to broadcast.&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_BAD_MULTICAST&lt;br /&gt;
| Problem with an attempt to multicast.&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_MULTICAST_FULL&lt;br /&gt;
| Multicast address list full.&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_BAD_EVENT&lt;br /&gt;
| Event specified is unknown.&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_BAD_STATDATA&lt;br /&gt;
| The ios2_StatData pointer or the data it points to failed a sanity check.&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_IS_CONFIGURED&lt;br /&gt;
| Attempt to reconfigure the unit.&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_NULL_POINTER&lt;br /&gt;
| A NULL pointer was detected in one of the arguments. S2ERR_BAD_ARGUMENT should always be the S2ERR.&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_UNIT_DISCONNECTED&lt;br /&gt;
| This error code is a counterpart to &amp;lt;tt&amp;gt;S2WERR_UNIT_OFFLINE&amp;lt;/tt&amp;gt;. It indicates that the associated command could not be executed because the link layer is not connected.&lt;br /&gt;
| 19&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_UNIT_CONNECTED&lt;br /&gt;
| This error code is a counterpart to &amp;lt;tt&amp;gt;S2WERR_UNIT_ONLINE&amp;lt;/tt&amp;gt;. It indicates that the associated command could not be executed because the link layer is already connected.&lt;br /&gt;
| 20&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_INVALID_OPTION&lt;br /&gt;
| This error code indicates that an option, such as passed by the &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt; command, is not acceptable. The option&#039;s value may be out of range or may not match the syntax specifications. To indicate which option that may be, a different mechanism &#039;&#039;&#039;must&#039;&#039;&#039; be used; a simple indication that something was wrong is &#039;&#039;&#039;not sufficient&#039;&#039;&#039;.&lt;br /&gt;
| 21&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_MISSING_OPTION&lt;br /&gt;
| This error code indicates that a mandatory option, such as passed by the &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt; command, is not present. To indicate which option that may be, a different mechanism &#039;&#039;&#039;must&#039;&#039;&#039; be used; a simple indication that something was wrong is &#039;&#039;&#039;not sufficient&#039;&#039;&#039;.&lt;br /&gt;
| 22&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_AUTHENTICATION_FAILED&lt;br /&gt;
| Some drivers run protocols that require them to authenticate to a server. That process may fail. This wire error code is to indicate this fact.&lt;br /&gt;
| 23&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Standard Commands =&lt;br /&gt;
&lt;br /&gt;
See the &amp;quot;SANA-II network device driver Autodocs&amp;quot; for full details on each of the SANA-II device commands. Extended commands are explained in the sections below.&lt;br /&gt;
&lt;br /&gt;
Many of the Exec device standard commands are no-ops in SANA-II devices, but this may not always be the case. For example, CMD_RESET might someday be used for dynamically reconfiguring hardware. This should present no compatibility problems for properly written drivers.&lt;br /&gt;
&lt;br /&gt;
== Broadcast and Multicast ==&lt;br /&gt;
&lt;br /&gt;
Some hardware supports broadcast and/or multicast. A broadcast is a packet sent to all other machines. A multicast is a packet sent to a set of machines. Drivers for hardware which does not allow broadcast or multicast will return ios2_Error S2ERR_NOT_SUPPORTED as appropriate.&lt;br /&gt;
&lt;br /&gt;
To send a broadcast, use S2_BROADCAST instead of CMD_WRITE. Broadcasts are received just like any other packets (using a CMD_READ for the appropriate packet type).&lt;br /&gt;
&lt;br /&gt;
To send a multicast, use S2_MULTICAST instead of CMD_WRITE. The device keeps a list of addresses that want to receive multicasts. You add a receiver&#039;s address to this list by using S2_ADDMULTICASTADDRESS. The receiver then posts a CMD_READ for the type of packet to be received. Some SANA-II devices which support multicast may have a limit on the number of addresses that can simultaneously wait for packets. Always check for an S2WERR_MULTICAST_FULL error return when adding a multicast address.&lt;br /&gt;
&lt;br /&gt;
Note that when the device adds a multicast address, it is usually added for all users of the device, not just the driver user which called S2_ADDMULTICASTADDRESS. In other words, received multicast packets will fill a read request of the appropriate type regardless of whether the requesting driver user is the same one which added the multicast address.&lt;br /&gt;
&lt;br /&gt;
In general, driver users should not care how received packets were sent (normally or broadcast/multicast), only that it was received. If a driver user really must know, however, it can check for SANA2IOB_BCAST and/or SANA2IOB_MCAST in the ios2_Flags field.&lt;br /&gt;
&lt;br /&gt;
Drivers should keep a count for the number of opens on a multicast address so that they don&#039;t actually remove it until it has been S2_DELMULTICASTADDRESS&#039;d as many times as it has been S2_ADDMULTICASTADDRESS&#039;d.&lt;br /&gt;
&lt;br /&gt;
== Stats ==&lt;br /&gt;
&lt;br /&gt;
There are many statistics which may be very important to someone trying to debug, tune or optimize a protocol stack, as well as to the end user who may need to tune parameters or investigate a problem. Some of these statistics can only be kept by the SANA-II driver, thus there are several required and optional statistics and commands for this purpose.&lt;br /&gt;
&lt;br /&gt;
S2_TRACKTYPE tells the device driver to gather statistics for a particular packet type. S2_UNTRACKTYPE tells it to stop (keeping statistics by type causes the driver to use additional resources). S2_GETTYPESTATS returns any statistics accumulated by the driver for a type being tracked (stats are lost when a type is S2_UNTRACKTYPE&#039;d). Drivers are required to implement the functionality of type tracking. The stats are returned in a struct Sana2PacketTypeStats:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct Sana2PacketTypeStats&lt;br /&gt;
{&lt;br /&gt;
  ULONG PacketsSent;&lt;br /&gt;
  ULONG PacketsReceived;&lt;br /&gt;
  ULONG BytesSent;&lt;br /&gt;
  ULONG BytesReceived;&lt;br /&gt;
  ULONG PacketsDropped;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; PacketsSent&lt;br /&gt;
: Number of packets of a particular type sent.&lt;br /&gt;
; PacketsReceived&lt;br /&gt;
: Number of packets of a particular type that satisfied a read command.&lt;br /&gt;
; BytesSent&lt;br /&gt;
: Number of bytes of data sent in packets of a particular type.&lt;br /&gt;
; BytesReceived&lt;br /&gt;
: Number of bytes of data of a particular packet type that satisfied a read command.&lt;br /&gt;
; PacketsDropped&lt;br /&gt;
: Number of packets of a particular type that were received while there were no pending reads of that packet type.&lt;br /&gt;
&lt;br /&gt;
returns global statistics kept by the driver. Drivers are required to keep all applicable statistics. Since all are applicable to most hardware, most drivers will maintain all statistics. The stats are returned in a struct Sana2DeviceStats:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct Sana2DeviceStats&lt;br /&gt;
{&lt;br /&gt;
  ULONG PacketsReceived;&lt;br /&gt;
  ULONG PacketsSent;&lt;br /&gt;
  ULONG BadData;&lt;br /&gt;
  ULONG Overruns;&lt;br /&gt;
  ULONG UnknownTypesReceived;&lt;br /&gt;
  ULONG Reconfigurations;&lt;br /&gt;
  struct timeval LastStart;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; PacketsReceived&lt;br /&gt;
: Number of packets that this unit has received.&lt;br /&gt;
; PacketsSent&lt;br /&gt;
: Number of packets that this unit has sent.&lt;br /&gt;
; BadData&lt;br /&gt;
: Number of bad packets received (i.e., hardware CRC failed).&lt;br /&gt;
; Overruns&lt;br /&gt;
: Number of packets dropped due to insufficient resources available in the network interface.&lt;br /&gt;
; UnknownTypeReceived&lt;br /&gt;
: Number of packets received that had no pending read command with the appropriate packet type.&lt;br /&gt;
; Reconfigurations&lt;br /&gt;
: Number of network reconfigurations since this unit was last configured.&lt;br /&gt;
; LastStart&lt;br /&gt;
: The time when this unit last went on-line.&lt;br /&gt;
&lt;br /&gt;
returns any special statistics kept by a particular driver. Each new wire type will have a set of documented, required statistics for that wire type and a standard set of optional statistics for that wire type (optional because they might not be available from all hardware). The data returned by S2_GETSPECIALSTATS will require wire-specific interpretation. See &amp;amp;lt;devices/sana2specialstats.h&amp;amp;gt; on page devices&amp;lt;sub&amp;gt;s&amp;lt;/sub&amp;gt;ana2specialstats&amp;lt;sub&amp;gt;p&amp;lt;/sub&amp;gt;age for currently defined special statistics. The statistics are returned in the following structures:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct Sana2SpecialStatRecord&lt;br /&gt;
{&lt;br /&gt;
  ULONG Type;&lt;br /&gt;
  ULONG Count;&lt;br /&gt;
  char * String;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; Type&lt;br /&gt;
: Statistic identifier.&lt;br /&gt;
; Count&lt;br /&gt;
: Statistic itself.&lt;br /&gt;
; String&lt;br /&gt;
: An identifying, null-terminated string for the statistic. Should be plain ASCII with no formatting characters.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct Sana2SpecialStatHeader&lt;br /&gt;
{&lt;br /&gt;
  ULONG RecordCountMax;&lt;br /&gt;
  ULONG RecordCountSupplied;&lt;br /&gt;
  struct Sana2SpecialStatRecord[RecordCountMax];&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; RecordCountMax&lt;br /&gt;
: There is space for this many records into which statistics may be placed.&lt;br /&gt;
; RecordCountSupplied&lt;br /&gt;
: Number of statistic records supplied.&lt;br /&gt;
&lt;br /&gt;
is not, strictly speaking, a statistical function. It is a request to read any packet of a type for which there is no outstanding CMD_READ. S2_READORPHAN might be used in the same manner as many statistics, though, such as to determine what packet types are causing overruns, etc.&lt;br /&gt;
&lt;br /&gt;
== Configuration ==&lt;br /&gt;
&lt;br /&gt;
The device driver needs to configure the hardware before using it. The driver user must know some network hardware parameters (hardware address and MTU, for example) when using it. These commands address those needs.&lt;br /&gt;
&lt;br /&gt;
When a driver user is initialized, it should try to S2_CONFIGINTERFACE even though an interface can only be configured once and someone else may have done it. Before you call S2_CONFIGINTERFACE, first call S2_GETSTATIONADDRESS to determine the factory address (if any). Also provide for user-override of the factory address (that address may be optional and the user may need to override it). When S2_CONFIGINTERFACE returns, check the ios2_SrcAddr for the actual address the hardware has been configured with. This is because some hardware (or serial line standards such as PPP) always dynamically allocates an address at initialization.&lt;br /&gt;
&lt;br /&gt;
Driver users will want to use S2_DEVICEQUERY to determine the MTU and other characteristics of the network. The structure returned from S2_DEVICEQUERY is defined as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct Sana2DeviceQuery&lt;br /&gt;
{&lt;br /&gt;
    /*&lt;br /&gt;
    ** Standard information&lt;br /&gt;
    */&lt;br /&gt;
    ULONG SizeAvailable;    /* bytes available */&lt;br /&gt;
    ULONG SizeSupplied;     /* bytes supplied */&lt;br /&gt;
    LONG  DevQueryFormat;   /* this is type 0 */&lt;br /&gt;
    LONG  DeviceLevel;      /* this document is level 0 */&lt;br /&gt;
&lt;br /&gt;
    /*&lt;br /&gt;
    ** Common information&lt;br /&gt;
    */&lt;br /&gt;
    UWORD AddrFieldSize;    /* address size in bits */&lt;br /&gt;
    ULONG MTU;              /* maximum packet data size */&lt;br /&gt;
    LONG  BPS;              /* line rate (bits/sec) */&lt;br /&gt;
    LONG  HardwareType;     /* what the wire is */&lt;br /&gt;
    ULONG RawMTU;           /* maximum raw packet data size */&lt;br /&gt;
&lt;br /&gt;
    /*&lt;br /&gt;
    ** Format specific information&lt;br /&gt;
    */&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; SizeAvailable&lt;br /&gt;
: Size, in bytes, of the space available in which to place device information. This includes both size fields.&lt;br /&gt;
; SizeSupplied&lt;br /&gt;
: Size, in bytes, of the data supplied.&lt;br /&gt;
; DevQueryFormat&lt;br /&gt;
: The format defined here is format 0.&lt;br /&gt;
; DeviceLevel&lt;br /&gt;
: This spec defines level 0.&lt;br /&gt;
; AddrFieldSize&lt;br /&gt;
: The number of bits in an interface address.&lt;br /&gt;
; MTU&lt;br /&gt;
: Maximum Transmission Unit, the size, in bytes, of the maximum packet size, not including header and trailer information.&lt;br /&gt;
; BPS&lt;br /&gt;
: Best guess at the raw line rate for this network in bits per second.&lt;br /&gt;
&lt;br /&gt;
; HardwareType&lt;br /&gt;
: Specifies the type of network hardware the driver controls.&lt;br /&gt;
&lt;br /&gt;
; RawMTU&lt;br /&gt;
: The &amp;lt;tt&amp;gt;RawMTU&amp;lt;/tt&amp;gt; member is new as of SANA-II Revision 4. Devices which do not know and support this structure member may fill in the &amp;lt;tt&amp;gt;Sana2DeviceQuery&amp;lt;/tt&amp;gt; structure only up to and including the &amp;lt;tt&amp;gt;HardwareType&amp;lt;/tt&amp;gt; member.&lt;br /&gt;
&lt;br /&gt;
: In this context &#039;raw&#039; means the number of bytes that are available for reading and writing when using the &amp;lt;tt&amp;gt;SANA2IOB_RAW&amp;lt;/tt&amp;gt; flag with a &amp;lt;tt&amp;gt;CMD_READ&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;CMD_WRITE&amp;lt;/tt&amp;gt; request on a device that supports these access methods. Currently, software developers can only make assumptions on how many bytes might comprise the &#039;raw&#039; MTU by checking the &amp;lt;tt&amp;gt;Sana2DeviceQuery.HardwareType&amp;lt;/tt&amp;gt; member and hoping that the driver supports raw &amp;lt;tt&amp;gt;CMD_READ&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;CMD_WRITE&amp;lt;/tt&amp;gt; access.&lt;br /&gt;
&lt;br /&gt;
: Devices which know and support the &amp;lt;tt&amp;gt;RawMTU&amp;lt;/tt&amp;gt; member must fill it with a well-defined value. For Amiga Ethernet drivers, that value would be 1514, which is the standard MTU value of 1500 bytes plus the size of the Ethernet frame header, as per RFC894 (six bytes for the destination address, six bytes for the source address and two bytes for the frame type; the eight byte preamble and the terminating four byte CRC value are typically not under the control of the driver). Drivers which do not support raw read or write access must set the &amp;lt;tt&amp;gt;RawMTU&amp;lt;/tt&amp;gt; member to zero.&lt;br /&gt;
&lt;br /&gt;
: If the &amp;lt;tt&amp;gt;RawMTU&amp;lt;/tt&amp;gt; member is not provided, all bets are off and the application software must fall back to making estimates based upon the hardware type and the raw frame types it wishes to read and write. Ultimatively, the driver itself must decide whether it can accept raw read and write commands (or has to reject them with &amp;lt;tt&amp;gt;S2ERR_NOT_SUPPORTED&amp;lt;/tt&amp;gt;) and whether the raw packet size is still covered by the underlying hardware MTU (or must be rejected with &amp;lt;tt&amp;gt;S2ERR_MTU_EXCEEDED&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
: A word of warning: a little testing with various Ethernet hardware drivers has revealed that the A2065 driver &amp;lt;tt&amp;gt;a2065.device&amp;lt;/tt&amp;gt; does not handle the &amp;lt;tt&amp;gt;S2_DEVICEQUERY&amp;lt;/tt&amp;gt; command properly if the &amp;lt;tt&amp;gt;Sana2DeviceQuery&amp;lt;/tt&amp;gt; structure provided is larger than 30 bytes. In other words, the command will fail if the proposed &amp;lt;tt&amp;gt;RawMTU&amp;lt;/tt&amp;gt; member is present in the query data structure to be filled in.&lt;br /&gt;
&lt;br /&gt;
== On-line ==&lt;br /&gt;
&lt;br /&gt;
In order to run hardware tests on an otherwise live system, the S2_OFFLINE command allows the SANA-II device driver to be &amp;quot;turned off&amp;quot; until the tests are complete and an S2_ONLINE is sent to the driver. S2_ONLINE causes the interface to re-configure and re-initialize. Any packets destined for the hardware while the device is off-line will be lost. All pending and new requests to the driver shall be returned with S2ERR_OUTOFSERVICE when a device is off-line.&lt;br /&gt;
&lt;br /&gt;
All driver users must understand that any IO request may return with S2ERR_OUTOFSERVICE because the driver is off-line (any other program may call S2_OFFLINE to make it so). In such an event, the driver will usually want to wait until the unit comes back on-line (for the program which called S2_OFFLINE to call S2_ONLINE). It may do this by calling S2_ONEVENT to wait for S2EVENT_ONLINE. S2_ONEVENT allows the driver user to wait on various events.&lt;br /&gt;
&lt;br /&gt;
A driver must track events, but may not distinguish between some types of events. Drivers return S2_ONEVENT with S2ERR_NOT_SUPPORTED and S2WERR_BAD_EVENT for unsupported events. One error may cause more than one event (see below). Errors which seem to have been caused by a malformed or unusual request should not generally trigger an event.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Event type&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| S2EVENT_ERROR&lt;br /&gt;
| Return when any error occurs.&lt;br /&gt;
|-&lt;br /&gt;
| S2EVENT_TX&lt;br /&gt;
| Return on any transmit error (always an error).&lt;br /&gt;
|-&lt;br /&gt;
| S2EVENT_RX&lt;br /&gt;
| Return on any receive error (always an error).&lt;br /&gt;
|-&lt;br /&gt;
| S2EVENT_ONLINE&lt;br /&gt;
| Return when unit goes on-line or return immediately if unit is already on-line (not an error).&lt;br /&gt;
|-&lt;br /&gt;
| S2EVENT_OFFLINE&lt;br /&gt;
| Return when unit goes off-line or return immediately if unit is already off-line (not an error.)&lt;br /&gt;
|-&lt;br /&gt;
| S2EVENT_BUFF&lt;br /&gt;
| Return on any buffer management function error (always an error).&lt;br /&gt;
|-&lt;br /&gt;
| S2EVENT_HARDWARE&lt;br /&gt;
| Return when any hardware error occurs (always an error, may be a S2EVENT_TX or S2EVENT_RX, too).&lt;br /&gt;
|-&lt;br /&gt;
| S2EVENT_SOFTWARE&lt;br /&gt;
| Return when any software error occurs (always an error, may be a S2EVENT_TX or S2EVENT_RX, too).&lt;br /&gt;
|-&lt;br /&gt;
| S2EVENT_CONFIGCHANGED&lt;br /&gt;
| Return when client-visible configuration information changes (not an error).&lt;br /&gt;
|-&lt;br /&gt;
| S2EVENT_CONNECT&lt;br /&gt;
| Return when the driver has successfully established a link layer connection (not an error).&lt;br /&gt;
|-&lt;br /&gt;
| S2EVENT_DISCONNECT &lt;br /&gt;
| Return when the driver has closed the link layer connection previously established by the S2_CONNECT command (not an error).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== S2EVENT_CONFIGCHANGED ===&lt;br /&gt;
&lt;br /&gt;
For drivers such as those which implement the &amp;lt;tt&amp;gt;S2_GETPEERADDRESS&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2_GETDNSADDRESS&amp;lt;/tt&amp;gt; commands it is vital that such changes can take place and be noticed by the client software. For this purpose a new event type is introduced, to be used with the SANA-II &amp;lt;tt&amp;gt;S2_ONEVENT&amp;lt;/tt&amp;gt; command, using the following definition:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;#define S2EVENT_CONFIGCHANGED (1L&amp;amp;lt;&amp;amp;lt;8)&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This event should be triggered whenever client-visible configuration information changes, as can be queried via the &amp;lt;tt&amp;gt;S2_DEVICEQUERY&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;S2_GETSTATIONADDRESS&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;S2_GETSPECIALSTATS&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;S2_GETGLOBALSTATS&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;S2_GETPEERADDRESS&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2_GETDNSADDRESS&amp;lt;/tt&amp;gt; commands. Here is a short list of what could change:&lt;br /&gt;
&lt;br /&gt;
# S2_DEVICEQUERY: &amp;lt;tt&amp;gt;AddrFieldSize&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;MTU&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;BPS&amp;lt;/tt&amp;gt;&lt;br /&gt;
# S2_GETSTATIONADDRESS: &amp;lt;tt&amp;gt;ios2_SrcAddr&amp;lt;/tt&amp;gt;&lt;br /&gt;
# S2_GETGLOBALSTATS: &amp;lt;tt&amp;gt;Reconfigurations&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;LastStart&amp;lt;/tt&amp;gt;&lt;br /&gt;
# S2_GETPEERADDRESS: &amp;lt;tt&amp;gt;ios2_SrcAddr&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ios2_DstAddr&amp;lt;/tt&amp;gt;&lt;br /&gt;
# S2_GETDNSADDRESS: &amp;lt;tt&amp;gt;ios2_SrcAddr&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ios2_DstAddr&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The purpose of this event &#039;&#039;&#039;is not&#039;&#039;&#039; to post a notification whenever another byte or event counter has changed so that a monitoring program may update its display. The purpose &#039;&#039;&#039;is&#039;&#039;&#039; to convey to the client software that an important device configuration option has changed and that it is supposed to react and adapt to it. For example, a TCP/IP stack may, upon learning that a device&#039;s IP address has changed, rebuild its routing table.&lt;br /&gt;
&lt;br /&gt;
Since the &amp;lt;tt&amp;gt;S2EVENT_CONFIGCHANGED&amp;lt;/tt&amp;gt; event may arrive at any time and does not indicate what exactly has changed, application software should query the information it expects to change during its life time, and keep a copy of it around for later reference. When the &amp;lt;tt&amp;gt;S2EVENT_CONFIGCHANGED&amp;lt;/tt&amp;gt; event arrives, it can compare the contents of the copy against the current state of affairs and act according to the differences it finds.&lt;br /&gt;
&lt;br /&gt;
=== S2EVENT_CONNECT ===&lt;br /&gt;
&lt;br /&gt;
This event is a counterpart to &amp;lt;tt&amp;gt;S2EVENT_ONLINE&amp;lt;/tt&amp;gt;, and is associated with the &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt; command. It has the following semantics:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;#define S2EVENT_CONNECT (1L&amp;amp;lt;&amp;amp;lt;9) /* Driver has opened session */&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The event is to be sent when the driver has successfully established a link layer connection.&lt;br /&gt;
&lt;br /&gt;
=== S2EVENT_DISCONNECT ===&lt;br /&gt;
&lt;br /&gt;
This event is a counterpart to &amp;lt;tt&amp;gt;S2EVENT_OFFLINE&amp;lt;/tt&amp;gt;, and is associated with the &amp;lt;tt&amp;gt;S2_DISCONNECT&amp;lt;/tt&amp;gt; command. It has the following semantics:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;#define S2EVENT_DISCONNECT (1L&amp;amp;lt;&amp;amp;lt;10) /* Driver has closed session */&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The event is to be sent when the driver has closed the link layer connection previously established by the &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt; command.&lt;br /&gt;
&lt;br /&gt;
== S2_ONLINE and S2_OFFLINE ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2_DISCONNECT&amp;lt;/tt&amp;gt; commands are somewhat related to the &amp;lt;tt&amp;gt;S2_ONLINE&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2_OFFLINE&amp;lt;/tt&amp;gt; commands. How this relation works out shall be explained below. Note that the following text assumes that both the &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;S2_DISCONNECT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2_ONLINE&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;S2_OFFLINE&amp;lt;/tt&amp;gt; command pairs are implemented.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt; implies &amp;lt;tt&amp;gt;S2_ONLINE&amp;lt;/tt&amp;gt; and, if successful, may report &amp;lt;tt&amp;gt;S2EVENT_ONLINE&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2EVENT_CONNECT&amp;lt;/tt&amp;gt; events. If the unit is currently disconnected, but still online, only the &amp;lt;tt&amp;gt;S2EVENT_CONNECT&amp;lt;/tt&amp;gt; event shall be sent. Invoking the &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt; command on a driver which is already connected must be rejected with &amp;lt;tt&amp;gt;ios2_Req.io_Error=S2ERR_BAD_STATE&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;ios2_WireError=S2WERR_UNIT_CONNECTED&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;S2_DISCONNECT&amp;lt;/tt&amp;gt; implies &amp;lt;tt&amp;gt;S2_OFFLINE&amp;lt;/tt&amp;gt; and, if successful, may report &amp;lt;tt&amp;gt;S2EVENT_OFFLINE&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2EVENT_DISCONNECT&amp;lt;/tt&amp;gt; events. If the unit is currently connected and offline, then only the &amp;lt;tt&amp;gt;S2EVENT_DISCONNECT&amp;lt;/tt&amp;gt; event shall be sent. Invoking the &amp;lt;tt&amp;gt;S2_DISCONNECT&amp;lt;/tt&amp;gt; command on a driver which is already disconnected must be rejected with &amp;lt;tt&amp;gt;ios2_Req.io_Error=S2ERR_BAD_STATE&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;ios2_WireError=S2WERR_UNIT_DISCONNECTED&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;S2_OFFLINE&amp;lt;/tt&amp;gt; may be used after the &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt; has successfully connected the unit. In this case the driver will release control over the link layer and report the &amp;lt;tt&amp;gt;S2EVENT_OFFLINE&amp;lt;/tt&amp;gt; event. The connection established using the &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt; will, however, persist.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;S2_ONLINE&amp;lt;/tt&amp;gt; may be used after &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt; has successfully connected the unit and the &amp;lt;tt&amp;gt;S2_OFFLINE&amp;lt;/tt&amp;gt; was used. In this case the driver will again try to obtain control over the link layer and report the &amp;lt;tt&amp;gt;S2EVENT_ONLINE&amp;lt;/tt&amp;gt; event if successful.&lt;br /&gt;
&lt;br /&gt;
If the &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt; command was never successfully executed, then the commands &amp;lt;tt&amp;gt;S2_ONLINE&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2_OFFLINE&amp;lt;/tt&amp;gt; must be rejected with &amp;lt;tt&amp;gt;ios2_Req.io_Error=S2ERR_BAD_STATE&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;ios2_WireError=S2WERR_UNIT_DISCONNECTED&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Wireless (IEEE 802.11) ==&lt;br /&gt;
&lt;br /&gt;
Several new commands have been added to the SANA-II API to facilitate use of IEEE 802.11 wireless network devices in client and ad-hoc modes. The new commands are split into two overlapping sets. One set needs to be implemented by drivers for Soft-MAC wireless devices, while the other is implemented for Hard-MAC devices.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Soft-MAC commands&lt;br /&gt;
|-&lt;br /&gt;
| S2_SETOPTIONS&lt;br /&gt;
|-&lt;br /&gt;
| S2_SETKEY&lt;br /&gt;
|-&lt;br /&gt;
| S2_WRITEMGMT&lt;br /&gt;
|-&lt;br /&gt;
| S2_READMGMT&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Hard-MAC commands&lt;br /&gt;
|-&lt;br /&gt;
| S2_SETOPTIONS&lt;br /&gt;
|-&lt;br /&gt;
| S2_SETKEY&lt;br /&gt;
|-&lt;br /&gt;
| S2_GETNETWORKS&lt;br /&gt;
|-&lt;br /&gt;
| S2_GETNETWORKINFO&lt;br /&gt;
|-&lt;br /&gt;
| S2_GETSIGNALQUALITY&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== sana2wireless.h ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
#ifndef DEVICES_SANA2WIRELESS_H&lt;br /&gt;
#define DEVICES_SANA2WIRELESS_H&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;exec/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;utility/tagitem.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/* Constants */&lt;br /&gt;
/* ========= */&lt;br /&gt;
&lt;br /&gt;
/* Tags to get and set information */&lt;br /&gt;
&lt;br /&gt;
#define S2INFO_SSID           (TAG_USER + 0)&lt;br /&gt;
#define S2INFO_BSSID          (TAG_USER + 1)&lt;br /&gt;
#define S2INFO_AuthTypes      (TAG_USER + 2)&lt;br /&gt;
#define S2INFO_AssocID        (TAG_USER + 3)&lt;br /&gt;
#define S2INFO_Encryption     (TAG_USER + 4)&lt;br /&gt;
#define S2INFO_PortType       (TAG_USER + 5)&lt;br /&gt;
#define S2INFO_BeaconInterval (TAG_USER + 6)&lt;br /&gt;
#define S2INFO_Channel        (TAG_USER + 7)&lt;br /&gt;
#define S2INFO_Signal         (TAG_USER + 8)&lt;br /&gt;
#define S2INFO_Noise          (TAG_USER + 9)&lt;br /&gt;
#define S2INFO_Capabilities   (TAG_USER + 10)&lt;br /&gt;
#define S2INFO_InfoElements   (TAG_USER + 11)&lt;br /&gt;
#define S2INFO_WPAInfo        (TAG_USER + 12)&lt;br /&gt;
#define S2INFO_Band           (TAG_USER + 13)&lt;br /&gt;
#define S2INFO_DefaultKeyNo   (TAG_USER + 14)&lt;br /&gt;
&lt;br /&gt;
/* Wireless Commands */&lt;br /&gt;
&lt;br /&gt;
#define S2_GETSIGNALQUALITY 0xc010&lt;br /&gt;
#define S2_GETNETWORKS      0xc011&lt;br /&gt;
#define S2_SETOPTIONS       0xc012&lt;br /&gt;
#define S2_SETKEY           0xc013&lt;br /&gt;
#define S2_GETNETWORKINFO   0xc014&lt;br /&gt;
#define S2_READMGMT         0xc015&lt;br /&gt;
#define S2_WRITEMGMT        0xc016&lt;br /&gt;
#define S2_GETRADIOBANDS    0xc017&lt;br /&gt;
&lt;br /&gt;
/* Encryption types */&lt;br /&gt;
&lt;br /&gt;
#define S2ENC_NONE 0&lt;br /&gt;
#define S2ENC_WEP  1&lt;br /&gt;
#define S2ENC_TKIP 2&lt;br /&gt;
#define S2ENC_CCMP 3&lt;br /&gt;
&lt;br /&gt;
/* Radio modes */&lt;br /&gt;
&lt;br /&gt;
#define S2BAND_A 0&lt;br /&gt;
#define S2BAND_B 1&lt;br /&gt;
#define S2BAND_G 2&lt;br /&gt;
#define S2BAND_N 3&lt;br /&gt;
&lt;br /&gt;
/* Network topologies */&lt;br /&gt;
&lt;br /&gt;
#define S2PORT_MANAGED 7&lt;br /&gt;
#define S2PORT_ADHOC   8&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/* Structures */&lt;br /&gt;
/* ========== */&lt;br /&gt;
&lt;br /&gt;
/* Structure for returning signal quality */&lt;br /&gt;
&lt;br /&gt;
struct Sana2SignalQuality&lt;br /&gt;
{&lt;br /&gt;
   LONG SignalLevel;   /* signal level in dBm */&lt;br /&gt;
   LONG NoiseLevel;   /* noise level in dBm */&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Driver requirements =&lt;br /&gt;
&lt;br /&gt;
This section is an attempt to clarify parts of the specification and to lay down a few rules that every SANA-II driver must follow.&lt;br /&gt;
&lt;br /&gt;
* A driver that does not use a broadcast medium, such as Ethernet, must not implement the &amp;lt;tt&amp;gt;S2_BROADCAST&amp;lt;/tt&amp;gt; command. Likewise, if no multicast mechanism is supported, the &amp;lt;tt&amp;gt;S2_MULTICAST&amp;lt;/tt&amp;gt; must not be implemented either.&lt;br /&gt;
&lt;br /&gt;
* SANA-II standard commands which the driver does not implement must be rejected with the &amp;lt;tt&amp;gt;IOERR_NOCMD&amp;lt;/tt&amp;gt; error code. Commands that are implemented, but which cannot perform the requested services, must be rejected with the &amp;lt;tt&amp;gt;S2ERR_NOT_SUPPORTED&amp;lt;/tt&amp;gt; error code. The difference between the two cases is in when the decision is made whether a command can be handled or not. Which commands should return &amp;lt;tt&amp;gt;IOERR_NOCMD&amp;lt;/tt&amp;gt; is decided upon at the time the driver is designed and implemented. At this stage the implementer knows for sure which capabilities the driver will have and which it will not have. Commands which the driver will never be able to execute will be made to return the &amp;lt;tt&amp;gt;IOERR_NOCMD&amp;lt;/tt&amp;gt; error code. If the decision whether a command can be executed is made only at run time, by evaluating the conditions under which a command can be executed, then the error code &amp;lt;tt&amp;gt;S2ERR_NOT_SUPPORTED&amp;lt;/tt&amp;gt; should be returned in case of failure.&lt;br /&gt;
&lt;br /&gt;
* It must be possible to open the driver with an ordinary &amp;lt;tt&amp;gt;struct IOStdReq&amp;lt;/tt&amp;gt;. This is necessary for the NewStyleDevices query command to work. In the command dispatcher, the driver must verify that all SANA-II commands are invoked with a proper size &amp;lt;tt&amp;gt;struct IOSana2Req&amp;lt;/tt&amp;gt; I/O request. If the I/O request is shorter (as can be verified by looking at the embedded Message&#039;s &amp;lt;tt&amp;gt;mn_Length&amp;lt;/tt&amp;gt; member), the command must be rejected with &amp;lt;tt&amp;gt;ios2_Req.io_Error=IOERR_BADLENGTH&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* A driver must implement the NewStyleDevices &amp;lt;tt&amp;gt;NSCMD_DEVICEQUERY&amp;lt;/tt&amp;gt; command, in conformance with the NSD specification 1.6 or newer. The motivation for this is to have a mechanism available for probing the capabilities of the driver, and the supported command set can provide for vital clues. In this context, the absence of the &amp;lt;tt&amp;gt;S2_BROADCAST&amp;lt;/tt&amp;gt; command would suggest that the driver cannot send or receive broadcast messages.&lt;br /&gt;
&lt;br /&gt;
* A driver that does not allow its station address to be set with the &amp;lt;tt&amp;gt;S2_CONFIGINTERFACE&amp;lt;/tt&amp;gt; command may silently ignore the command (returning it without setting an error condition) and even pretend that it can be configured more than once.&lt;br /&gt;
&lt;br /&gt;
* In response to the &amp;lt;tt&amp;gt;S2_DEVICEQUERY&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;S2_GETSPECIALSTATS&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2_GETGLOBALSTATS&amp;lt;/tt&amp;gt; commands a driver may return information that is not entirely correct if it has to go online before it can provide for the correct data. For example, the maximum transmission unit for PPP is a number in the range of [1..1500] which is negotiated during the protocol configuration process. It is unlikely that numbers greater than 1500 will be used, yet it is still not impossible. Since the actual number will be known only after the driver has configured the protocol, the MTU value returned before the session was opened can differ from the MTU value valid after it has been opened. A driver should therefore attempt to return &#039;safe&#039; defaults in place of information that is unavailable at the time it is queried. The &#039;safe&#039; values shall be set up to allow the driver to work even if the protocol stack is not aware of later changes to those values. Beware of zero-length buffer sizes or time intervals that may cause client software to perform zero-length memory allocations or divisions by zero.&lt;br /&gt;
&lt;br /&gt;
* SANA-II assigns packet type numbers according to the underlying transport media. For example, Ethernet uses packet type 2048 for IP frames. No such packet type definition exists for PPP yet, which is why this standard proposes to assign packet type 31 for IP packets transmitted via PPP. To simplify client software configuration, drivers may treat packet type 2048 as equivalent to the packet number associated with IP frames. This association is permitted only if it does not introduce ambiguity. For example, this association would not be permitted if the driver would receive and transmit IP packets in two different frame types or if the driver already associates packet type 2048 with non-IP packets.&lt;br /&gt;
&lt;br /&gt;
= Driver Installation =&lt;br /&gt;
&lt;br /&gt;
The standard system location for SANA-II network device driver is in a directory called &amp;amp;quot;Networks&amp;amp;quot; which exists in the &amp;amp;quot;DEVS:&amp;amp;quot; directory.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
DEVS:Networks/eth3com.device&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the official location for the drivers. It may be necessary for your install program/script to create this directory if it doesn&#039;t exist in a user&#039;s system.&lt;br /&gt;
&lt;br /&gt;
= Unresolved Issues =&lt;br /&gt;
&lt;br /&gt;
* Unfortunately, it isn&#039;t possible to completely isolate network protocols from the hardware they run on. Hardware types and addressing both remain somewhat hardware-dependent in spite of our efforts. See the &amp;quot;Packet Type&amp;quot; section for an explanation of how packet types are handled and why protocols cannot be isolated from them. See the &amp;quot;Addressing&amp;quot; section for an explanation of how addressing is handled any why protocols cannot be isolated from it.&lt;br /&gt;
&lt;br /&gt;
* Additionally, there are at least two cases where a hardware type has multiple framing methods in use (ethernet/802.3 and arcnet/(Novell) &amp;quot;ARCNET Packet Header Definition Standard&amp;quot;). In both cases, software which must interoperate with other platforms on this hardware may need to be aware of the distinctions and may have to do extra processing in order to use the appropriate frame type. See the sections on &amp;quot;Ethernet Packet Types&amp;quot; and on &amp;quot;ARCNET frames&amp;quot; for more details.&lt;br /&gt;
&lt;br /&gt;
* Protocols like PPP can provide both for IPv4 and IPv6 addresses that should be used by the local client, the peer or any of the domain name servers. While the two addressing families are interoperable, there is a problem in how the driver should report them. Can you assume 128 bit addresses and encapsulate 32 bit addresses in them? If so, how do you make sure that the address format is unambiguous?&lt;br /&gt;
&lt;br /&gt;
* Currently, only the device&#039;s hardware type provides a clue as to what packet type responds to which protocol transported via the link. For Ethernet, IP packets are encapsulated in type 2048 frames, PPP encapsulates IP packets in type 31 frames, Arcnet can use type 240 or 212. Matching a protocol with a frame type is not an easy process which could be handled more elegantly.&lt;br /&gt;
&lt;br /&gt;
* How to extend the &amp;lt;tt&amp;gt;Sana2DeviceQuery&amp;lt;/tt&amp;gt; structure in the future? The current layout separates standard, common and format specific information, but there is no hint as to where which each section starts and where the next begins. Now that there is a proposal to add a new field to the common section, how would you add fields to the format specific section?&lt;br /&gt;
&lt;br /&gt;
= SANA-II network device driver Autodocs =&lt;br /&gt;
&lt;br /&gt;
== AbortIO ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        AbortIO -- Remove an existing device request.&lt;br /&gt;
&lt;br /&gt;
   SYNOPSIS&lt;br /&gt;
        error = AbortIO(Sana2Req)&lt;br /&gt;
        D0              A1&lt;br /&gt;
&lt;br /&gt;
        LONG AbortIO(struct IOSana2Req *);&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This is an exec.library call.&lt;br /&gt;
&lt;br /&gt;
        This function aborts an ioRequest. If the request is active, it may or&lt;br /&gt;
        may not be aborted. If the request is queued it is removed. The&lt;br /&gt;
        request will be returned in the same way as if it had normally&lt;br /&gt;
        completed.  You must WaitIO() after AbortIO() for the request to&lt;br /&gt;
        return.&lt;br /&gt;
&lt;br /&gt;
   INPUTS&lt;br /&gt;
        Sana2Req        - Sana2Req to be aborted.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        error           - Zero if the request was aborted, non-zero otherwise.&lt;br /&gt;
                          io_Error in Sana2Req will be set to IOERR_ABORTED&lt;br /&gt;
                          if it was aborted.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        exec.library/AbortIO(), exec.library/WaitIO()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== CloseDevice ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        CloseDevice -- Close the device.&lt;br /&gt;
&lt;br /&gt;
   SYNOPSIS&lt;br /&gt;
        CloseDevice(Sana2Req)&lt;br /&gt;
                    A1&lt;br /&gt;
&lt;br /&gt;
        void CloseDevice(struct IOSana2Req *);&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This function is called by exec.library CloseDevice().&lt;br /&gt;
&lt;br /&gt;
        This function performs whatever cleanup is required at device closes.&lt;br /&gt;
&lt;br /&gt;
        Note that all IORequests MUST be complete before closing. If any are&lt;br /&gt;
        pending, your program must AbortIO() then WaitIO() each outstanding&lt;br /&gt;
        IORequest to complete them.&lt;br /&gt;
&lt;br /&gt;
   INPUTS&lt;br /&gt;
        Sana2Req        - Pointer to IOSana2Req initialized by OpenDevice().&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        exec.library/CloseDevice(), exec.library/OpenDevice()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== CMD_CLEAR ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        CMD_CLEAR -- Clear internal network interface read buffers.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        There are no device internal buffers, so CMD_CLEAR does not apply to&lt;br /&gt;
        this class of device.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - CMD_CLEAR.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - IOERR_NOCMD.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== CMD_FLUSH ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        CMD_FLUSH -- Clear all queued I/O requests for the SANA-II device.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command aborts all I/O requests in both the read and write&lt;br /&gt;
        request queues of the device.  All pending I/O requests are&lt;br /&gt;
        returned with an error message (IOERR_ABORTED).  CMD_FLUSH does not&lt;br /&gt;
        affect active requests.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - CMD_FLUSH.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - Zero if successful; non-zero otherwise.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== CMD_INVALID ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        CMD_INVALID -- Return with error IOERR_NOCMD.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command causes device driver to reply with an error IOERR_NOCMD&lt;br /&gt;
        as defined in &amp;amp;lt;exec/errors.h&amp;amp;gt; indicating the command is not supported.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - CMD_INVALID.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - IOERR_NOCMD.&lt;br /&gt;
&lt;br /&gt;
   BUGS&lt;br /&gt;
        Not known to be useful.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== CMD_READ ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        CMD_READ -- Get a packet from the network.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        Get the next packet available of the requested packet type. The data&lt;br /&gt;
        copied (via a call to the requestor-provided CopyToBuffer function)&lt;br /&gt;
        into ios2_Data is normally the Data Link Layer packet data only. If&lt;br /&gt;
        bit SANA2IOB_RAW is set in ios2_Flags, then the entire physical frame&lt;br /&gt;
        will be returned.&lt;br /&gt;
&lt;br /&gt;
        Unlike most Exec devices, SANA-II device drivers do not have internal&lt;br /&gt;
        buffers.  If you wish to read data from a SANA-II device you should&lt;br /&gt;
        have multiple CMD_READ requests pending at any given time.  The&lt;br /&gt;
        functions provided by you the requestor will be used for any incoming&lt;br /&gt;
        packets of the type you&#039;ve requested.  If no read requests are&lt;br /&gt;
        outstanding for a type which comes in and no read_orphan requests are&lt;br /&gt;
        outstanding, the packet will be lost.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - CMD_READ&lt;br /&gt;
        ios2_Flags      - Supported flags are:&lt;br /&gt;
                            SANA2IOB_RAW&lt;br /&gt;
                            SANA2IOB_QUICK&lt;br /&gt;
        ios2_PacketType - Packet type desired.&lt;br /&gt;
        ios2_Data       - Abstract data structure to hold packet data.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - Zero if successful; non-zero otherwise.&lt;br /&gt;
        ios2_WireError  - More specific error number.&lt;br /&gt;
        ios2_Flags      - The following flags may be returned:&lt;br /&gt;
                            SANA2IOB_RAW&lt;br /&gt;
                            SANA2IOB_BCAST&lt;br /&gt;
                            SANA2IOB_MCAST&lt;br /&gt;
        ios2_SrcAddr    - Source interface address of packet.&lt;br /&gt;
        ios2_DstAddr    - Destination interface address of packet.&lt;br /&gt;
        ios2_DataLength - Length of packet data.&lt;br /&gt;
        ios2_Data       - Abstract data structure which packet data is&lt;br /&gt;
                          contained in.&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        The driver may not directly examine or modify anything pointed to by&lt;br /&gt;
        ios2_Data.  It *must* use the requester-provided functions to access&lt;br /&gt;
        this data.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        S2_READORPHAN, CMD_WRITE, any_protocol/CopyToBuffer&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== CMD_RESET ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        CMD_RESET -- Reset the network interface to initialized state.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        Currently, SANA-II devices can only be configured once (with&lt;br /&gt;
        CMD_CONFIGINTERFACE) and cannot be re-configured, hence,&lt;br /&gt;
        CMD_RESET does not apply to this class of device.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - CMD_RESET.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - IOERR_NOCMD.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== CMD_START ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        CMD_START -- Restart device operation.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        There is no way for the driver to keep queuing requests without&lt;br /&gt;
        servicing them, so CMD_STOP does not apply to this class of device.&lt;br /&gt;
        S2_OFFLINE and S2_ONLINE do perform a similar function to CMD_STOP&lt;br /&gt;
        and CMD_START&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - CMD_START.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - IOERR_NOCMD.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        S2_ONLINE, S2_OFFLINE&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== CMD_STOP ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        CMD_STOP -- Pause device operation.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        There is no way for the driver to keep queuing requests without&lt;br /&gt;
        servicing them, so CMD_STOP does not apply to this class of device.&lt;br /&gt;
        S2_OFFLINE and S2_ONLINE do perform a similar function to CMD_STOP&lt;br /&gt;
        and CMD_START&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - CMD_STOP.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - IOERR_NOCMD.&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        S2_ONLINE, S2_OFFLINE&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== CMD_UPDATE ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        CMD_UPDATE -- Force packets out to device.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        Since there are no device internal buffers, CMD_UPDATE does not&lt;br /&gt;
        apply to this class of device.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - CMD_UPDATE.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - IOERR_NOCMD.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== CMD_WRITE ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        CMD_WRITE -- Send packet to the network.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command causes the packet to be sent to the specified network&lt;br /&gt;
        interface. Normally, appropriate packet header and trailer information&lt;br /&gt;
        will be added to the packet data when it is sent.  If bit SANA2IOB_RAW&lt;br /&gt;
        is set in io_Flags, then the ios2_Data is assumed to contain an entire&lt;br /&gt;
        physical frame and will be sent (copied to the wire via&lt;br /&gt;
        CopyFromBuffer() unmodified.&lt;br /&gt;
&lt;br /&gt;
        Note that the device should not check to see if the destination&lt;br /&gt;
        address is on the local hardware.  Network protocols should realize&lt;br /&gt;
        that the packet has a local destination long before it gets to a&lt;br /&gt;
        SANA-II driver.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - CMD_WRITE.&lt;br /&gt;
        ios2_Flags      - Supported flags are:&lt;br /&gt;
                            SANA2IOB_RAW&lt;br /&gt;
                            SANA2IOB_QUICK&lt;br /&gt;
        ios2_PacketType - Packet type to send.&lt;br /&gt;
        ios2_DstAddr    - Destination interface address for this packet.&lt;br /&gt;
        ios2_DataLength - Length of the Data to be sent.&lt;br /&gt;
        ios2_Data       - Abstract data structure which packet data is&lt;br /&gt;
                          contained in.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - Zero if successful; non-zero otherwise.&lt;br /&gt;
        ios2_WireError  - More specific error number.&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        The driver may not directly examine or modify anything pointed to by&lt;br /&gt;
        ios2_Data.  It *must* use the requester-provided functions to access&lt;br /&gt;
        this data.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        CMD_READ, S2_BROADCAST, S2_MULTICAST, any_protocol/CopyFromBuffer&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== OpenDevice ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        Open -- Request an opening of the network device.&lt;br /&gt;
&lt;br /&gt;
   SYNOPSIS&lt;br /&gt;
        error = OpenDevice(unit, IOSana2Req, flags)&lt;br /&gt;
        D0                 D0    A1          D1&lt;br /&gt;
&lt;br /&gt;
        BYTE OpenDevice(ULONG, struct IOSana2Req *, ULONG);&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This function is called by exec.library OpenDevice().&lt;br /&gt;
&lt;br /&gt;
        This function performs whatever initialization is required per&lt;br /&gt;
        device open and initializes the Sana2Req for use by the&lt;br /&gt;
        device.&lt;br /&gt;
&lt;br /&gt;
   INPUTS&lt;br /&gt;
        unit            - Device unit to open.&lt;br /&gt;
        Sana2Req        - Pointer to IOSana2Req structure to be initialized by&lt;br /&gt;
                          the sana2.device.&lt;br /&gt;
        flags           - Supported flags are:&lt;br /&gt;
                                SANA2OPB_MINE&lt;br /&gt;
                                SANA2OPB_PROM&lt;br /&gt;
        ios2_BufferManagement   - A pointer to a tag list containing&lt;br /&gt;
                                  pointers to buffer management functions.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        error           - same as io_Error&lt;br /&gt;
        io_Error        - Zero if successful; non-zero otherwise.&lt;br /&gt;
        io_Device       - A pointer to whatever device will handle the calls&lt;br /&gt;
                          for this unit.  This pointer may be different&lt;br /&gt;
                          depending on what unit is requested.&lt;br /&gt;
        ios2_BufferManagement   - A pointer to device internal information&lt;br /&gt;
                                  used to call buffer management functions.&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        A SANA-II device must reject all open requests with a request&lt;br /&gt;
        structure that is too short, e.g. an IOStdReq. A simple check of the&lt;br /&gt;
        mn_Length field in the Message part of the request is needed to make&lt;br /&gt;
        sure that a device does not dereference invalid data due to a wrong&lt;br /&gt;
        device configuration.&lt;br /&gt;
&lt;br /&gt;
        A SANA-II device may open if no buffer management tags are provided to&lt;br /&gt;
        make the configuration process and obtaining statistics easier. Buffer&lt;br /&gt;
        management tags with a NULL value must be treated as not specified.&lt;br /&gt;
        The device shall fail requests gracefully depending on the missing&lt;br /&gt;
        tags in this case. Any malfunction is not acceptable.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        exec.library/OpenDevice(), exec.library/CloseDevice()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_ADDMULTICASTADDRESS ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_ADDMULTICASTADDRESS -- Enable an interface multicast address.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command causes the device driver to enable multicast packet&lt;br /&gt;
        reception for the requested address.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - S2_ADDMULTICASTADDRESS.&lt;br /&gt;
        ios2_SrcAddr    - Multicast address to enable.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - Zero if successful; non-zero otherwise.&lt;br /&gt;
        ios2_WireError  - More specific error number.&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        Multicast addresses are added globally -- anyone using the device&lt;br /&gt;
        may receive packets as a result of any multicast address which has&lt;br /&gt;
        been added for the device.&lt;br /&gt;
&lt;br /&gt;
        Since multicast addresses are not &amp;amp;quot;bound&amp;amp;quot; to a particular packet type,&lt;br /&gt;
        each enabled multicast address has an &amp;amp;quot;enabled&amp;amp;quot; count associated with&lt;br /&gt;
        it so that if two protocols add the same multicast address and later&lt;br /&gt;
        one removes it, it is still enabled until the second removes it.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        S2_MULTICAST, S2_DELMULTICASTADDRESS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_BROADCAST ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_BROADCAST -- Broadcast a packet on network.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command works the same as CMD_WRITE except that it also performs&lt;br /&gt;
        whatever special processing of the packet is required to do a&lt;br /&gt;
        broadcast send. The actual broadcast mechanism is neccessarily&lt;br /&gt;
        network/interface/device specific.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - S2_BROADCAST.&lt;br /&gt;
        ios2_Flags      - Supported flags are:&lt;br /&gt;
                                SANA2IOB_RAW&lt;br /&gt;
                                SANA2IOB_QUICK&lt;br /&gt;
        ios2_PacketType - Packet type to send.&lt;br /&gt;
        ios2_DataLength - Length of the Data to be sent.&lt;br /&gt;
        ios2_Data       - Abstract data structure which packet data is&lt;br /&gt;
                          contained in.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_DstAddr    - The contents of this field are to be&lt;br /&gt;
                          considered trash upon return of the IOReq.&lt;br /&gt;
        ios2_Error      - Zero if successful; non-zero otherwise.&lt;br /&gt;
                          This command can fail for many reasons and&lt;br /&gt;
                          is not supported by all networks and/or&lt;br /&gt;
                          network interfaces.&lt;br /&gt;
        ios2_WireError  - More specific error number.&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        The DstAddr field may be trashed by the driver because this function&lt;br /&gt;
        may be implemented by filling DstAddr with a broadcast address and&lt;br /&gt;
        internally calling CMD_WRITE.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        CMD_WRITE, S2_MULTICAST&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_CONFIGINTERFACE ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_CONFIGINTERFACE -- Configure the network interface.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command causes the device driver to initialize the interface&lt;br /&gt;
        hardware and to set the network interface address to the address in&lt;br /&gt;
        ios2_SrcAddr. This command can only be executed once and, if&lt;br /&gt;
        successful, will leave the driver and network interface fully&lt;br /&gt;
        operational and the network interface in ios2_SrcAddr.&lt;br /&gt;
&lt;br /&gt;
        To set the interface address to the factory address, the network&lt;br /&gt;
        management software must use GetStationAddress first and then call&lt;br /&gt;
        ConfigInterface with the result. If there is no factory address then&lt;br /&gt;
        the network software must pick an address to use.&lt;br /&gt;
&lt;br /&gt;
        Until this command is executed the device will not listen for any&lt;br /&gt;
        packets on the hardware.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - S2_CONFIGINTERFACE.&lt;br /&gt;
        ios2_Flags      - Supported flags are:&lt;br /&gt;
                                SANA2IOB_QUICK&lt;br /&gt;
        ios2_SrcAddr    - Address for this interface.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - Zero if successful; non-zero otherwise.&lt;br /&gt;
        ios2_WireError  - More specific error number.&lt;br /&gt;
        ios2_SrcAddr    - Address of this interface as configured.&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        Some networks have the interfaces choose a currently unused interface&lt;br /&gt;
        address each time the interface is initialized. The caller must check&lt;br /&gt;
        ios2_SrcAddr for the actual interface address after configuring the&lt;br /&gt;
        interface.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        S2_GETSTATIONADDRESS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_CONNECT ==&lt;br /&gt;
&lt;br /&gt;
The driver model specified by the SANA-II standard really only covers networking hardware well. Software-only drivers, such as for dial-up networking, are, well, somehow mentioned in the standard, but they don&#039;t receive much attention. In particular, this means that a networking driver is assumed to be practically always attached to its link layer and no provisions exist to specify what kind of link layer that might be and how it might be accessed. This small oversight can probably be explained by the fact that at the time the SANA-II standard was adopted, dial-up networking had not yet gained the prominence it has today.&lt;br /&gt;
&lt;br /&gt;
To bridge this gap, I propose a new command which will make a driver connect to its link layer and go online, which uses the following data structure:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct Sana2Connection&lt;br /&gt;
{&lt;br /&gt;
   ULONG          s2c_Size;&lt;br /&gt;
   struct MinList s2c_Options;&lt;br /&gt;
   struct Hook    s2c_ErrorHook;&lt;br /&gt;
   struct Hook    s2c_ConnectHook;&lt;br /&gt;
   struct Hook    s2c_DisconnectHook;&lt;br /&gt;
   STRPTR         s2c_Login;&lt;br /&gt;
   STRPTR         s2c_Password;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The individual structure members have the following purposes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2c_Size&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The size of the entire data structure is stored here. This value &#039;&#039;&#039;must&#039;&#039;&#039; be &amp;amp;gt;= 84. Smaller values &#039;&#039;&#039;must&#039;&#039;&#039; be rejected with &amp;lt;tt&amp;gt;ios2_Req.io_Error&amp;lt;/tt&amp;gt;=&amp;lt;tt&amp;gt;IOERR_BADLENGTH&amp;lt;/tt&amp;gt;. The purpose of &amp;lt;tt&amp;gt;s2c_Size&amp;lt;/tt&amp;gt; is to allow for future expansion during which the structure may grow in size.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2c_Options&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This list contains options, to be used during the connection process. Each node has the following format:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct Sana2ConnectionOption&lt;br /&gt;
{&lt;br /&gt;
   struct MinNode s2co_MinNode;&lt;br /&gt;
   STRPTR         s2co_Name;&lt;br /&gt;
   STRPTR         s2co_Value;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;s2co_Name&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;s2co_Value&amp;lt;/tt&amp;gt; entries point to &amp;lt;tt&amp;gt;NUL&amp;lt;/tt&amp;gt;-terminated strings, which contain the name and the value of a parameter. &#039;&#039;Note that for numeric values, the respective number will be encoded in a text string.&#039;&#039; A number of parameters are reserved, which are [[#s2c_options|listed later]] in this text.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2c_ErrorHook&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This hook is called whenever an error message is to be reported during the connection/disconnection process. The hook function is invoked using the following parameters:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;error_hook_func(hook,reserved,message);&lt;br /&gt;
&lt;br /&gt;
VOID error_hook_func(struct Hook *hook,APTR reserved,&lt;br /&gt;
                     STRPTR message);&amp;lt;/pre&amp;gt;&lt;br /&gt;
The &amp;lt;tt&amp;gt;reserved&amp;lt;/tt&amp;gt; parameter &#039;&#039;&#039;must&#039;&#039;&#039; be &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt;. The &amp;lt;tt&amp;gt;message&amp;lt;/tt&amp;gt; parameter points to a &amp;lt;tt&amp;gt;NUL&amp;lt;/tt&amp;gt;-terminated string. It &#039;&#039;&#039;must not&#039;&#039;&#039; be &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Because the hook function may have to allocate memory, it &#039;&#039;&#039;must not&#039;&#039;&#039; be called from interrupt code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2c_ConnectHook&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This hook is called when the link level device has been set up, but further initializations are necessary, such as telling a modem to dial out. The hook function is invoked with the following parameters:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
success = connect_hook_func(hook,reserved,s2cm);&lt;br /&gt;
&lt;br /&gt;
BOOL connect_hook_func(struct Hook *hook,APTR reserved,&lt;br /&gt;
                       struct Sana2ConnectionMessage *s2cm);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;reserved&amp;lt;/tt&amp;gt; parameter &#039;&#039;&#039;must&#039;&#039;&#039; be &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt;. The &amp;lt;tt&amp;gt;s2cm&amp;lt;/tt&amp;gt; parameter points to a data structure, as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct Sana2ConnectionMessage&lt;br /&gt;
{&lt;br /&gt;
   ULONG                    s2cm_Size;&lt;br /&gt;
   struct Sana2Connection * s2cm_Connection;&lt;br /&gt;
   struct IORequest *       s2cm_Request[2];&lt;br /&gt;
   LONG                     s2cm_RequestType;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this structure, the members have the following purposes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2cm_Size&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The size of this data structure; it &#039;&#039;&#039;must&#039;&#039;&#039; be at least 20 bytes in size. The purpose of &amp;lt;tt&amp;gt;s2cm_Size&amp;lt;/tt&amp;gt; is to allow for future expansion, which may cause the size of this structure to grow.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2cm_Connection&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This points back to the &amp;lt;tt&amp;gt;Sana2Connection&amp;lt;/tt&amp;gt; structure which the hook that was invoked with the &amp;lt;tt&amp;gt;Sana2ConnectionMessage&amp;lt;/tt&amp;gt; is embedded in.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2cm_Request&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here you will find two I/O requests which can be used for reading and writing data to the link layer. These pointers &#039;&#039;&#039;must not&#039;&#039;&#039; be &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; and they &#039;&#039;&#039;must&#039;&#039;&#039; refer to different I/O requests, it is not permitted to pass the same request twice.&lt;br /&gt;
&lt;br /&gt;
The dialer can use these requests for communicating with the modem, but it is also permitted to clone these requests by creating new I/O requests of the same size, copying the original contents and filling in different reply ports.&lt;br /&gt;
&lt;br /&gt;
There is a danger in that the hook code may not receive the right kind of I/O request, which is why the &amp;lt;tt&amp;gt;s2cm_RequestType&amp;lt;/tt&amp;gt; field identifies the kind of device the requests were created for.&lt;br /&gt;
&lt;br /&gt;
When the hook function returns, it &#039;&#039;&#039;must&#039;&#039;&#039; make sure that none of the I/O requests are still pending, i.e. asynchronous I/O &#039;&#039;&#039;must&#039;&#039;&#039; have been stopped.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2cm_RequestType&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This identifies the type of device the I/O requests passed in &amp;lt;tt&amp;gt;s2cm_Request&amp;lt;/tt&amp;gt; were created for. Possible values for this entry come from the New Style Device specification, e.g. &amp;lt;tt&amp;gt;NSDEVTYPE_SERIAL&amp;lt;/tt&amp;gt; for a &amp;lt;tt&amp;gt;serial.device&amp;lt;/tt&amp;gt;-like device or &amp;lt;tt&amp;gt;NSDEVTYPE_SANA2&amp;lt;/tt&amp;gt; for a networking driver.&lt;br /&gt;
&lt;br /&gt;
The hook function &#039;&#039;&#039;must&#039;&#039;&#039; return &amp;lt;tt&amp;gt;TRUE&amp;lt;/tt&amp;gt; if the connection could be established, and &amp;lt;tt&amp;gt;FALSE&amp;lt;/tt&amp;gt; otherwise. Note that it is &#039;&#039;not&#039;&#039; sufficient to just return &amp;lt;tt&amp;gt;FALSE&amp;lt;/tt&amp;gt; in case of failure. Your code &#039;&#039;&#039;must&#039;&#039;&#039; have called the &amp;lt;tt&amp;gt;s2c_ErrorHook&amp;lt;/tt&amp;gt; with an explanation why things went wrong first.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2c_DisconnectHook&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This hook is called by &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt; when the connection could not be established (the &amp;lt;tt&amp;gt;s2c_ConnectHook&amp;lt;/tt&amp;gt; returned &amp;lt;tt&amp;gt;FALSE&amp;lt;/tt&amp;gt;), or by &amp;lt;tt&amp;gt;S2_DISCONNECT&amp;lt;/tt&amp;gt;, shortly before the link level device is to be closed. The hook function is invoked with the following parameters:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
disconnect_hook_func(hook,reserved,s2cm);&lt;br /&gt;
&lt;br /&gt;
VOID disconnect_hook_func(struct Hook *hook,APTR reserved,&lt;br /&gt;
                          struct Sana2ConnectionMessage *s2cm);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;reserved&amp;lt;/tt&amp;gt; parameter &#039;&#039;&#039;must&#039;&#039;&#039; be &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt;. The &amp;lt;tt&amp;gt;s2cm&amp;lt;/tt&amp;gt; parameter points to a data structure, as was described for the &amp;lt;tt&amp;gt;s2c_ConnectHook&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2c_Login&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2c_Password&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The purpose of these entries is to transport the authentication information the protocol may require. These entries are either &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; or contain pointers to &amp;lt;tt&amp;gt;NUL&amp;lt;/tt&amp;gt;-terminated strings. If &amp;lt;tt&amp;gt;s2c_Login&amp;lt;/tt&amp;gt; is &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt;, then both login and password &#039;&#039;&#039;must&#039;&#039;&#039; be assumed to be empty. If &amp;lt;tt&amp;gt;s2c_Login&amp;lt;/tt&amp;gt; is not &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;s2c_Password&amp;lt;/tt&amp;gt; is &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt;, then the password &#039;&#039;&#039;must&#039;&#039;&#039; be assumed to be empty.&lt;br /&gt;
&lt;br /&gt;
The list of options in &amp;lt;tt&amp;gt;s2c_Options&amp;lt;/tt&amp;gt; supplies the necessary information on how the driver is to connect to the link layer. Each node contains an option, which bears a name and contains a value. This pair is what I call a &#039;&#039;parameter&#039;&#039;. A number of parameter names are reserved, as will be listed below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp&amp;lt;/tt&amp;gt;.async.device&lt;br /&gt;
&lt;br /&gt;
Name of device driver to use for asynchronous PPP.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;serial.device&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp&amp;lt;/tt&amp;gt;.async.unit&lt;br /&gt;
&lt;br /&gt;
Device unit number to use for asynchronous PPP.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp&amp;lt;/tt&amp;gt;.async.speed&lt;br /&gt;
&lt;br /&gt;
Transmission speed to use for asynchronous PPP in bits per second.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;115200&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.async.buffersize&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Receive buffer size for asynchronous PPP.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;50000&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.async.checkcarrier&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whether the carrier signal of the link layer should be tested or not. This can be either 0 (do not test) or 1 (test the carrier signal).&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.async.rtscts&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whether or not hardware handshaking should be used by the link layer. This can be either &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; (off) or &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; (on).&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.async.shared&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whether or not the link layer device should be opened in shared mode. This can be either &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; (off) or &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; (on).&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.async.nullmodem&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whether or not the link layer is a direct connection, such as a nullmodem. This can be either &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; (off) or &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; (on).&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.async.eof&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whether or not the underlying serial device driver&#039;s &#039;EOF mode&#039; should be enabled. This can be either &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; (off) or &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; (on).&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.async.readrequests&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Number of read requests to be used for asynchronous PPP.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;16&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.async.writerequests&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Number of write requests to be used for asynchronous PPP.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;16&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.async.accm&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Asynchronous control character map, expressed as a hexadecimal value.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;$000A0000&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.async.pfc&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whether or not protocol field compression should be used. This can be either &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; (off) or &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; (on).&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.async.aacfc&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whether or not address and control field compression should be used. This can be either &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; (off) or &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; (on).&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.async.vjhc&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whether or not Van Jacobson header compression should be used. This can be either &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; (off) or &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; (on).&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.async.ignorefcs&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whether or not frame check sequences should be ignored upon reception. This can be either &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; (off) or &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; (on).&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.async.initialize&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The modem initialization command, with embedded control sequences, if possible.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;AT\r&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.async.dial&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The modem dial command, with embedded control sequences, if possible.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;ATD12345\r&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.async.dialtimeout&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The dial timeout, i.e. the number of seconds to wait after the dial command has been sent for the modem to establish a connection.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;60&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.async.hangup&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The modem hangup command, with embedded control sequences, if possible.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;ATH0\r&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.idletimeout&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Number of seconds the local host may remain idle, i.e. send no data to the peer, before a watchdog timeout elapses and proceeds to verify that the line is still operational.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;30&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.localaddress&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The IP address to assign to the local host, as part of the PPP negotiation process. This must be given in dotted decimal notation (RFC1700).&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;1.2.3.4&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.remoteaddress&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The IP address to assume for the peer, as part of the PPP negotiation process. This must be given in dotted decimal notation (RFC1700).&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;1.2.3.4&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.dns1address&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The IP address to be used by the primary domain name server, as part of the PPP negotiation process. This must be given in dotted decimal notation (RFC1700).&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;1.2.3.4&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.dns2address&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The IP address to be used by the secondary domain name server, as part of the PPP negotiation process. This must be given in dotted decimal notation (RFC1700).&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;1.2.3.4&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.maxfail&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The maximum number of negative configuration acknowledgements to be sent before the PPP negotiation process switches to reject those options.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;5&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.maxterm&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The maximum number of termination requests to be sent before the respective PPP network or link protocol gives up.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;2&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.maxconfig&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The maximum number of configuration requests to be sent before the respective PPP network or link protocol gives up.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;10&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.timeout&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The number of seconds that have to pass before the respective PPP network or link protocol will retry to do whatever didn&#039;t work during the last attempt.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;3&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.mtu&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The maximum transmission unit to use.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;1500&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.peeridletimeout&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Number of seconds the peer may remain idle, i.e. send no data to the local host, before a watchdog timeout elapses and proceeds to verify that the line is still operational.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;30&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.rejectpap&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whether or not the Password Authentication Protocol should be accepted, if offered by the peer. This can be either &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; (accept) or &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; (reject).&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.sendid&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A flag which controls whether the local host should send LCP identification packets or not. This can be either &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; (off) or &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; (on).&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.pap.timeout&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The Password Authentication Protocol requires that the server answers to the client&#039;s request to log in. The server may be unable to respond immediately, which means that the client will have to repeat its request. A short delay should separate each request sent, such as three seconds.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;3&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.pap.retry&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the client does not manage to authenticate with the server immediately, it may resend the authentication request several times. But the attempts have to stop eventually, such as after having resent the message ten times.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;10&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.dummyremoteaddress&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whether or not the PPP driver should make up an IP address if the peer refuses to state its own IP address.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;logfile&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The name of a log file to create. If the file already exists, then new data should be appended to it.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;t:logfile&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;logoptions&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A list of options which control what exactly should be logged.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.ethernet.device&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Name of device driver to use for PPPoE (PPP over Ethernet).&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;a2065.device&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.ethernet.unit&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Device unit number to use for PPPoE.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.ethernet.raw&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whether or not raw link layer frames should be constructed for transmission or not. This can be either &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; (off) or &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; (on).&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.ethernet.bypass&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whether or not the IP packet transmission and reception should bypass several copying steps. This can be either &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; (off) or &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; (on).&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.ethernet.readpackets&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The number of read requests to queue for the link layer.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;16&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.ethernet.writepackets&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The number of write requests to queue for the link layer.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;16&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.ethernet.service&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The name of the PPPoE service to request.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;?&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.ethernet.ac&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The name of the PPPoE access concentrator to request.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;?&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.ethernet.connecttimeout&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The number of seconds to wait for the PPPoE server to allow a session to be opened.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;3&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
While this list of parameters may suggest that the command described above can be used solely with the PPP protocol, do not let that put you off. This list is merely the starting point, but it is not set in stone that it cannot be extended.&lt;br /&gt;
&lt;br /&gt;
The names of the parameters are not case sensitive. As the names suggest, the name space itself is hierarchic in construction, i.e. everything related to the PPP protocol bears a name starting with the letters &#039;ppp&#039; with the dot &#039;.&#039; separating the individual items. By this rule, ppp.async refers to options that concern asynchronous PPP and ppp.ethernet to options that concern PPP over Ethernet wire.&lt;br /&gt;
&lt;br /&gt;
To add your own parameter, register it with the maintainer of the SANA-II standard or prefix its name with the letters &#039;x-&#039;. For example, to use your own kind of &#039;ppp.ethernet.connecttimeout&#039; parameter, change the name of the last component like this: ppp.ethernet.x-connecttimeout. No officially-registered parameter will ever begin with the prefix &#039;x-&#039;.&lt;br /&gt;
&lt;br /&gt;
The command should work as follows:&lt;br /&gt;
&lt;br /&gt;
# The client must set up the &amp;lt;tt&amp;gt;Sana2Connection&amp;lt;/tt&amp;gt; data structure, initialize the &amp;lt;tt&amp;gt;s2c_Size&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;s2c_Options&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;s2c_ErrorHook&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;s2c_ConnectHook&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;s2c_DisconnectHook&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;s2c_Login&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;s2c_Password&amp;lt;/tt&amp;gt; fields.&lt;br /&gt;
# The connection options must be filled in, which means that nodes containing the respective information must be stored in the &amp;lt;tt&amp;gt;s2c_Options&amp;lt;/tt&amp;gt; list. The client must make sure that the syntax of the parameters conforms to the specifications described above.&lt;br /&gt;
# A pointer to the &amp;lt;tt&amp;gt;Sana2Connection&amp;lt;/tt&amp;gt; data structure is placed in the &amp;lt;tt&amp;gt;ios2_Data&amp;lt;/tt&amp;gt; member of an &amp;lt;tt&amp;gt;IOSana2Req&amp;lt;/tt&amp;gt;, the command is set to &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt; and the request is sent via &amp;lt;tt&amp;gt;DoIO()&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;SendIO()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
# The driver receives the request and begins to examine the contents of the &amp;lt;tt&amp;gt;s2c_Options&amp;lt;/tt&amp;gt; list, as provided in the data structure pointed to by the &amp;lt;tt&amp;gt;ios2_Data&amp;lt;/tt&amp;gt; member of the request. Unknown options are ignored, options whose values do not conform to the syntax specification are rejected; this is done by calling the &amp;lt;tt&amp;gt;s2c_ErrorHook&amp;lt;/tt&amp;gt; with an error message referring to the option in question and by returning the &amp;lt;tt&amp;gt;IOSana2Req&amp;lt;/tt&amp;gt; with an error code of &amp;lt;tt&amp;gt;S2ERR_BAD_ARGUMENT&amp;lt;/tt&amp;gt; and wire error code of &amp;lt;tt&amp;gt;S2WERR_INVALID_OPTION&amp;lt;/tt&amp;gt;.&lt;br /&gt;
# If the options are all in good order, the driver proceeds to verify that all mandatory options are provided. If this is not the case, the &amp;lt;tt&amp;gt;s2c_ErrorHook&amp;lt;/tt&amp;gt; is called with an error message referring to the option in question and the &amp;lt;tt&amp;gt;IOSana2Req&amp;lt;/tt&amp;gt; is returned with an error code of &amp;lt;tt&amp;gt;S2ERR_BAD_ARGUMENT&amp;lt;/tt&amp;gt; and wire error code of &amp;lt;tt&amp;gt;S2WERR_MISSING_OPTION&amp;lt;/tt&amp;gt;.&lt;br /&gt;
# The driver proceeds to do its local initialization, which involves opening the link layer device, etc. If this initialization fails, the &amp;lt;tt&amp;gt;s2c_ErrorHook&amp;lt;/tt&amp;gt; is called with an error message referring to the problem and the &amp;lt;tt&amp;gt;IOSana2Req&amp;lt;/tt&amp;gt; is returned with an appropriate error code.&lt;br /&gt;
# When the initialization has finished, the driver may invoke the &amp;lt;tt&amp;gt;s2c_ConnectHook&amp;lt;/tt&amp;gt; callback. Some drivers may require this, such as asynchronous PPP, some may not, such as PPPoE. The purpose of the hook function is to give the client a chance to perform modem initializations and connect to the peer. If the &amp;lt;tt&amp;gt;s2c_ConnectHook&amp;lt;/tt&amp;gt; cannot perform its duties, it has to invoke the &amp;lt;tt&amp;gt;s2c_ErrorHook&amp;lt;/tt&amp;gt; with an error message and eventually return &amp;lt;tt&amp;gt;FALSE&amp;lt;/tt&amp;gt;. If &amp;lt;tt&amp;gt;FALSE&amp;lt;/tt&amp;gt; is returned, the driver must invoke the &amp;lt;tt&amp;gt;s2c_DisconnectHook&amp;lt;/tt&amp;gt;, reverse any initializations it had made and eventually returned the &amp;lt;tt&amp;gt;IOSana2Req&amp;lt;/tt&amp;gt; with an appropriate error code. If the &amp;lt;tt&amp;gt;s2c_ConnectHook&amp;lt;/tt&amp;gt; returned &amp;lt;tt&amp;gt;TRUE&amp;lt;/tt&amp;gt;, then the driver must proceed with the actions that require that the link layer is operational. A protocol negotiation may follow, which, if successful, will make the driver return the &amp;lt;tt&amp;gt;IOSana2Req&amp;lt;/tt&amp;gt; with an error code of zero, indicating success. If successful, the SANA-II events &amp;lt;tt&amp;gt;S2EVENT_CONNECT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2EVENT_ONLINE&amp;lt;/tt&amp;gt; must be sent.&lt;br /&gt;
# The command will eventually return, but the client &#039;&#039;&#039;must not&#039;&#039;&#039; release the memory allocated for the &amp;lt;tt&amp;gt;Sana2Connection&amp;lt;/tt&amp;gt; structure and the option nodes in the &amp;lt;tt&amp;gt;s2c_Options&amp;lt;/tt&amp;gt; list. This is because the driver may have to invoke the &amp;lt;tt&amp;gt;s2c_DisconnectHook&amp;lt;/tt&amp;gt; hook due to the connection shutting down on its own accord.&lt;br /&gt;
&lt;br /&gt;
The connect and disconnect hook functions &#039;&#039;&#039;must not&#039;&#039;&#039; be called from interrupt code. For each hook only a &amp;lt;tt&amp;gt;Task&amp;lt;/tt&amp;gt; calling context of unknown priority must be assumed. Also, stack space is provided only to call &amp;lt;tt&amp;gt;exec.library&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;utility.library&amp;lt;/tt&amp;gt; functions. The callback shall not place excessive data on the stack. Stack space should be considered limited.&lt;br /&gt;
&lt;br /&gt;
I propose a command with the following semantics:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_CONNECT -- Establish a link layer connection and go&lt;br /&gt;
            online.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command is for use by networking devices which require&lt;br /&gt;
        a special link layer device to transmit their data, such as&lt;br /&gt;
        an asynchronous serial line and need to know about the&lt;br /&gt;
        configuration parameters necessary to open the connection.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command          - S2_CONNECT&lt;br /&gt;
        ios2_Data             - Pointer to Sana2Connection structure&lt;br /&gt;
        ios2_BufferManagement - Magic cookie as returned when opening the&lt;br /&gt;
                                driver with a struct IOSana2Req&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Req.io_Error - Zero if successful; non-zero otherwise&lt;br /&gt;
        ios2_WireError    - More specific error number&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        If successful, this command implies S2_ONLINE, i.e. the&lt;br /&gt;
        link layer is allocated and used by the driver.&lt;br /&gt;
&lt;br /&gt;
        The contents of the Sana2Connection structure must be valid&lt;br /&gt;
        until the connection is eventually shut down. The driver will&lt;br /&gt;
        need to cache it, so it must not be deallocated or otherwise&lt;br /&gt;
        modified.&lt;br /&gt;
&lt;br /&gt;
        Note that S2_ONLINE does not necessarily imply S2_CONNECT, if&lt;br /&gt;
        the S2_CONNECT command is listed as supported by the driver via&lt;br /&gt;
        NSCMD_DEVICEQUERY. If S2_CONNECT is not listed as supported,&lt;br /&gt;
        S2_ONLINE obviously implies connect functionality.&lt;br /&gt;
&lt;br /&gt;
        S2_CONNECT/S2_DISCONNECT do not nest.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        S2_DISCONNECT&amp;lt;/pre&amp;gt;&lt;br /&gt;
I propose that the following command number should be assigned:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;#define S2_CONNECT 0xC005&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_DELMULTICASTADDRESS ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_DELMULTICASTADDRESS -- Disable an interface multicast address.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command causes device driver to disable multicast packet&lt;br /&gt;
        reception for the requested address.&lt;br /&gt;
&lt;br /&gt;
        It is an error to disable a multicast address that is not enabled.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - S2_DELMULTICASTADDRESS&lt;br /&gt;
        ios2_SrcAddr    - Multicast address to disable.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - Zero if successful; non-zero otherwise.&lt;br /&gt;
        ios2_WireError  - More specific error number.&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        Multicast addresses are added globally -- anyone using the device&lt;br /&gt;
        may receive packets as a result of any multicast address which has&lt;br /&gt;
        been added for the device.&lt;br /&gt;
&lt;br /&gt;
        Since multicast addresses are not &amp;amp;quot;bound&amp;amp;quot; to a particular packet type,&lt;br /&gt;
        each enabled multicast address has an &amp;amp;quot;enabled&amp;amp;quot; count associated with&lt;br /&gt;
        it so that if two protocols add the same multicast address and later&lt;br /&gt;
        one removes it, it is still enabled until the second removes it.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        S2_ADDMULTICASTADDRESS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_DEVICEQUERY ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_DEVICEQUERY -- Return parameters for this network interface.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command causes the device driver to report information about the&lt;br /&gt;
        device. Up to SizeAvailable bytes of the information is copied&lt;br /&gt;
        into a buffer pointed to by ios2_StatData. The format of the data is&lt;br /&gt;
        as follows:&lt;br /&gt;
&lt;br /&gt;
            struct Sana2DeviceQuery&lt;br /&gt;
            {&lt;br /&gt;
            /*&lt;br /&gt;
            ** Standard information&lt;br /&gt;
            */&lt;br /&gt;
                ULONG SizeAvailble; /* bytes available */&lt;br /&gt;
                ULONG SizeSupplied; /* bytes supplied */&lt;br /&gt;
                ULONG DevQueryFormat;   /* this is type 0 */&lt;br /&gt;
                ULONG DeviceLevel;      /* this document is level 0 */&lt;br /&gt;
&lt;br /&gt;
            /*&lt;br /&gt;
            ** Common information&lt;br /&gt;
            */&lt;br /&gt;
                UWORD AddrFieldSize;    /* address size in bits */&lt;br /&gt;
                ULONG MTU;              /* maximum packet data size */&lt;br /&gt;
                ULONG bps;              /* line rate (bits/sec) */&lt;br /&gt;
                ULONG HardwareType;     /* what the wire is */&lt;br /&gt;
                ULONG RawMTU;           /* maximum raw packet data size */&lt;br /&gt;
&lt;br /&gt;
            /*&lt;br /&gt;
            ** Format specific information&lt;br /&gt;
            */&lt;br /&gt;
            };&lt;br /&gt;
&lt;br /&gt;
        The SizeAvailable specifies the number of bytes that the caller&lt;br /&gt;
        is prepared to accomodate, including the standard information fields.&lt;br /&gt;
&lt;br /&gt;
        SizeSupplied is the number of bytes actually supplied,&lt;br /&gt;
        including the standard information fields, which will not exceed&lt;br /&gt;
        SizeAvailable.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - S2_DEVICEQUERY.&lt;br /&gt;
        ios2_StatData   - Pointer to Sana2DeviceQuery structure to fill in.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - Zero if successful; non-zero otherwise.&lt;br /&gt;
        ios2_WireError  - More specific error number.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_DISCONNECT ==&lt;br /&gt;
&lt;br /&gt;
This command complements &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt; in that it tears down a connection. It uses the same &amp;lt;tt&amp;gt;Sana2Connection&amp;lt;/tt&amp;gt; structure and hooks, but most of these members are ignored.&lt;br /&gt;
&lt;br /&gt;
The command should work as follows:&lt;br /&gt;
&lt;br /&gt;
# The client must set up the &amp;lt;tt&amp;gt;Sana2Connection&amp;lt;/tt&amp;gt; data structure, initialize the &amp;lt;tt&amp;gt;s2c_Size&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;s2c_Options&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;s2c_ErrorHook&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;s2c_ConnectHook&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;s2c_DisconnectHook&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;s2c_Login&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;s2c_Password&amp;lt;/tt&amp;gt; fields. The &amp;lt;tt&amp;gt;s2c_Options&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;s2c_ConnectHook&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;s2c_Login&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;s2c_Password&amp;lt;/tt&amp;gt; fields will be ignored, but the client should play things safe.&lt;br /&gt;
# A pointer to the &amp;lt;tt&amp;gt;Sana2Connection&amp;lt;/tt&amp;gt; data structure is placed in the &amp;lt;tt&amp;gt;ios2_Data&amp;lt;/tt&amp;gt; member of an &amp;lt;tt&amp;gt;IOSana2Req&amp;lt;/tt&amp;gt;, the command is set to &amp;lt;tt&amp;gt;S2_DISCONNECT&amp;lt;/tt&amp;gt; and the request is sent via &amp;lt;tt&amp;gt;DoIO()&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;SendIO()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
# The driver receives the request and proceeds to reverse the steps that previously allowed it to establish a connection. This includes telling the peer to shut down the link, but it does not include cleaning up the link layer device access, i.e. no I/O requests used for accessing a modem may be shut down yet.&lt;br /&gt;
# The &amp;lt;tt&amp;gt;s2c_DisconnectHook&amp;lt;/tt&amp;gt; may be invoked with the proper parameters. Some drivers, such as for asynchronous PPP, will need the hook to tell the modem to hang up the line. Some drivers, such as for PPPoE, may not need this hook and thus ignore it.&lt;br /&gt;
# The initialization is reversed completely, all resources allocated when the connection was previously opened are released. The &amp;lt;tt&amp;gt;IOSana2Req&amp;lt;/tt&amp;gt; is returned with an error code of zero, indicating success. The SANA-II event &amp;lt;tt&amp;gt;S2EVENT_DISCONNECT&amp;lt;/tt&amp;gt; must be sent, and, if necessary, &amp;lt;tt&amp;gt;S2EVENT_OFFLINE&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The connect and disconnect hook functions must not be called from interrupt code. For each hook only a &amp;lt;tt&amp;gt;Task&amp;lt;/tt&amp;gt; calling context of unknown priority must be assumed. Also, stack space is provided only to call &amp;lt;tt&amp;gt;exec.library&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;utility.library&amp;lt;/tt&amp;gt; functions. The callback shall not place excessive data on the stack. Stack space should be considered limited.&lt;br /&gt;
&lt;br /&gt;
I propose a command with the following semantics:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_DISCONNECT -- Go offline and close a link layer connection&lt;br /&gt;
            previously established with S2_CONNECT.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command complements the S2_CONNECT command in that it&lt;br /&gt;
        reverses the steps taken to establish a link layer connection.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command          - S2_DISCONNECT&lt;br /&gt;
        ios2_Data             - Pointer to Sana2Connection structure&lt;br /&gt;
        ios2_BufferManagement - Magic cookie as returned when opening the&lt;br /&gt;
                                driver with a struct IOSana2Req&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Req.io_Error - Zero if successful; non-zero otherwise&lt;br /&gt;
        ios2_WireError    - More specific error number&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        If successful, this command implies S2_OFFLINE, i.e. the&lt;br /&gt;
        link layer is deallocated.&lt;br /&gt;
&lt;br /&gt;
        The driver must ignore the S2_DISCONNECT command and&lt;br /&gt;
        recover gracefully if the S2_CONNECT was never sent or&lt;br /&gt;
        returned with an error.&lt;br /&gt;
&lt;br /&gt;
        The contents of the Sana2Connection structure are valid only&lt;br /&gt;
        until the device driver has processed the command and returned&lt;br /&gt;
        the IOSana2Req. Any data the driver may need to retain beyond&lt;br /&gt;
        that point of time must be copied.&lt;br /&gt;
&lt;br /&gt;
        Once the S2_DISCONNECT command has returned, it is safe to dispose&lt;br /&gt;
        of the Sana2Connection structure provided at S2_CONNECT time.&lt;br /&gt;
&lt;br /&gt;
        Note that S2_OFFLINE does not necessarily imply S2_DISCONNECT, if&lt;br /&gt;
        the S2_DISCONNECT command is listed as supported by the driver via&lt;br /&gt;
        NSCMD_DEVICEQUERY. If S2_DISCONNECT is not listed as supported,&lt;br /&gt;
        S2_OFFLINE obviously implies disconnect functionality.&lt;br /&gt;
&lt;br /&gt;
        S2_CONNECT/S2_DISCONNECT do not nest.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        S2_CONNECT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
I propose that the following command number should be assigned:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;#define S2_DISCONNECT 0xC006&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_GETDNSADDRESS ==&lt;br /&gt;
&lt;br /&gt;
The PPP negotiation process may produce information on which domain name and NetBIOS name servers are available to the client. I think that it is doubtful that the availability of NetBIOS name servers will be useful for Amiga software (let alone whether NetBIOS name resolution has a future), which is why I suggest that a SANA-II command for returning only the domain name servers is introduced.&lt;br /&gt;
&lt;br /&gt;
I propose a command with the following semantics:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_GETDNSADDRESS -- Obtain the addresses of the primary&lt;br /&gt;
           and secondary domain name servers.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        Obtain the addresses of the domain name servers available to the&lt;br /&gt;
        client using this driver&#039;s address.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command          - S2_GETDNSADDRESS&lt;br /&gt;
        ios2_Flags            - Supported flags are:&lt;br /&gt;
                                SANA2IOB_QUICK&lt;br /&gt;
        ios2_BufferManagement - Magic cookie as returned when opening the&lt;br /&gt;
                                driver with a struct IOSana2Req&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Req.io_Error - Zero if successful; non-zero otherwise&lt;br /&gt;
        ios2_WireError    - More specific error number&lt;br /&gt;
        ios2_SrcAddr      - Address of primary domain name server&lt;br /&gt;
        ios2_DstAddr      - Address of secondary domain name server&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        The size of the address returned by S2_GETPEERADDRESS must not be&lt;br /&gt;
        different from the size as returned by the S2_DEVICEQUERY command. For&lt;br /&gt;
        example, if a 32 bit IPv4 address was advertized, the driver must not&lt;br /&gt;
        return a 128 bit IPv6 address instead.&lt;br /&gt;
&lt;br /&gt;
        If the driver is unable to return the primary domain name server&lt;br /&gt;
        address (ios2_SrcAddr) or the secondary domain name server address&lt;br /&gt;
        (ios2_DstAddr) it must fill the respective address fields with zeroes.&lt;br /&gt;
        It is legal for a driver to respond to the S2_GETDNSADDRESS command&lt;br /&gt;
        with two zero addresses (both ios2_SrcAddr and ios2_DstAddr filled&lt;br /&gt;
        with zeroes).&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
I propose that the following command number should be assigned:&lt;br /&gt;
&amp;lt;tt&amp;gt;#define S2_GETDNSADDRESS 0xC003&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This command may be useful beyond the typical application (PPP) described above.&lt;br /&gt;
&lt;br /&gt;
== S2_GETEXTENDEDGLOBALSTATS ==&lt;br /&gt;
&lt;br /&gt;
There already exists a SANA-II command for querying global device statistics (&amp;lt;tt&amp;gt;S2_GETGLOBALSTATS&amp;lt;/tt&amp;gt;) which should be common to all kinds of networking devices. Statistics that are particular to a certain device type are intended to be returned through the &amp;lt;tt&amp;gt;S2_GETSPECIALSTATS&amp;lt;/tt&amp;gt; command. I feel that these mechanisms both fail to cater well enough for dial-up or session-oriented networking applications such as PPP or PPPoE. Since the data structure used by &amp;lt;tt&amp;gt;S2_GETGLOBALSTATS&amp;lt;/tt&amp;gt; is of a fixed size and not intended to accomodate for new fields, I propose to introduce a new command which uses a different data structure, as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct Sana2ExtDeviceStats&lt;br /&gt;
{&lt;br /&gt;
   ULONG          s2xds_Length;&lt;br /&gt;
   ULONG          s2xds_Actual;&lt;br /&gt;
&lt;br /&gt;
   S2QUAD         s2xds_PacketsReceived;&lt;br /&gt;
   S2QUAD         s2xds_PacketsSent;&lt;br /&gt;
   S2QUAD         s2xds_BadData;&lt;br /&gt;
   S2QUAD         s2xds_Overruns;&lt;br /&gt;
   S2QUAD         s2xds_UnknownTypesReceived;&lt;br /&gt;
   S2QUAD         s2xds_Reconfigurations;&lt;br /&gt;
   struct timeval s2xds_LastStart;&lt;br /&gt;
&lt;br /&gt;
   struct timeval s2xds_LastConnected;&lt;br /&gt;
   struct timeval s2xds_LastDisconnected;&lt;br /&gt;
   struct timeval s2xds_TimeConnected;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Before I proceed to explain what purposes the individual members serve, a few words on the &amp;lt;tt&amp;gt;S2QUAD&amp;lt;/tt&amp;gt; type, which is defined as follows:&lt;br /&gt;
&amp;lt;tt&amp;gt;typedef struct { ULONG s2q_High; ULONG s2q_Low; } S2QUAD;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In other words, the &amp;lt;tt&amp;gt;S2QUAD&amp;lt;/tt&amp;gt; type stands for an unsigned 64 bit big endian integer, as expressed in ISO &#039;C&#039; terms.&lt;br /&gt;
&lt;br /&gt;
The structure members have the following purposes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2xds_Length&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the size of the data structure to be filled in and should be initialized by the caller to &amp;lt;tt&amp;gt;sizeof(struct Sana2ExtDeviceStats)&amp;lt;/tt&amp;gt;. Smaller values are permitted, but these &#039;&#039;&#039;must not&#039;&#039;&#039; be smaller than 8 (which covers the &amp;lt;tt&amp;gt;s2xds_Length&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;s2xds_Actual&amp;lt;/tt&amp;gt; members). A driver which finds an &amp;lt;tt&amp;gt;s2xds_Length&amp;lt;/tt&amp;gt; &amp;amp;lt; 8 &#039;&#039;&#039;must&#039;&#039;&#039; treat this as an error and reject the command with &amp;lt;tt&amp;gt;ios2_Req.io_Error&amp;lt;/tt&amp;gt;=&amp;lt;tt&amp;gt;IOERR_BADLENGTH&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2xds_Actual&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The size of the data structure filled with information. This member is initialized by the driver and &#039;&#039;&#039;must&#039;&#039;&#039; be &amp;amp;lt;= &amp;lt;tt&amp;gt;s2xds_Length&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2xds_PacketsReceived&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Number of packets that this unit has received. This is a 64 bit integer.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2xds_PacketsSent&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Number of packets that this unit has sent. This is a 64 bit integer.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2xds_BadData&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Number of bad packets received (i.e., hardware CRC failed). This is a 64 bit integer.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2xds_Overruns&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Number of packets dropped due to insufficient resources available in the network interface. This is a 64 bit integer.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2xds_UnknownTypesReceived&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Number of packets received that had no pending read command with the appropriate packet type. This is a 64 bit integer.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2xds_Reconfigurations&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Number of network reconfigurations since this unit was last configured. This is a 64 bit integer.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2xds_LastStart&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The time when this unit last went on-line.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2xds_LastConnected&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The time when this unit last established a connection. For dial-up connections, this should be the time when the underlying serial line started to accumulate costs. &amp;lt;tt&amp;gt;s2xds_LastConnected&amp;lt;/tt&amp;gt; &#039;&#039;&#039;must&#039;&#039;&#039; be set to zero if the unit never managed to make a connection.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2xds_LastDisconnected&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The time when this unit last shut down a connection. For dial-up connections, this should be the time when the underlying serial line stopped accumulating costs, e.g. when the modem&#039;s carrier signal was lost. &amp;lt;tt&amp;gt;s2xds_LastDisconnected&amp;lt;/tt&amp;gt; &#039;&#039;&#039;must&#039;&#039;&#039; be set to zero if the unit never disconnected.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2xds_TimeConnected&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The time this unit has been connected. For dial-up connections this should be the time between now and when the underlying serial line started accumulating costs.&lt;br /&gt;
&lt;br /&gt;
If this unit is not currently connected, then &amp;lt;tt&amp;gt;s2xds_TimeConnected&amp;lt;/tt&amp;gt; &#039;&#039;&#039;must&#039;&#039;&#039; be set to zero. This means in particular that when the connection is lost, &amp;lt;tt&amp;gt;s2xds_TimeConnected&amp;lt;/tt&amp;gt; &#039;&#039;&#039;must&#039;&#039;&#039; be immediately set to zero and &amp;lt;tt&amp;gt;s2xds_LastDisconnected&amp;lt;/tt&amp;gt; &#039;&#039;&#039;must&#039;&#039;&#039; be filled in so that client software can query how long the unit was connected by subtracting &amp;lt;tt&amp;gt;s2xds_LastConnected&amp;lt;/tt&amp;gt; from &amp;lt;tt&amp;gt;s2xds_LastDisconnected&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
If this unit is currently connected, &amp;lt;tt&amp;gt;s2xds_TimeConnected&amp;lt;/tt&amp;gt; &#039;&#039;&#039;must never&#039;&#039;&#039; be zero; if necessary, set &amp;lt;tt&amp;gt;s2xds_TimeConnected.tv_secs=0&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;s2xds_TimeConnected.tv_micros=1&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
If &amp;lt;tt&amp;gt;s2xds_TimeConnected&amp;lt;/tt&amp;gt; is zero, check &amp;lt;tt&amp;gt;s2xds_LastConnected&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;s2xds_LastDisconnected&amp;lt;/tt&amp;gt;; if the latter two are not zero, you can calculate the previous connection time by subtracting &amp;lt;tt&amp;gt;s2xds_LastConnected&amp;lt;/tt&amp;gt; from &amp;lt;tt&amp;gt;s2xds_LastDisconnected&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The layout and semantics used by the &amp;lt;tt&amp;gt;Sana2ExtDeviceStats&amp;lt;/tt&amp;gt; data structure suggest that there is a difference between the underlying networking media (the link layer) and the state of the protocol that is running on top of it. With drivers for networking hardware such as Ethernet there was no difference between these two, but for protocols like SLIP, PPP or PPPoE there is a difference. The difference is in that a session or connection may exist for a certain time whereas the protocol running inside that session may be switched &#039;online&#039; later. The primary purpose of the &amp;lt;tt&amp;gt;s2xds_LastConnected&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;s2xds_LastDisconnected&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;s2xds_TimeConnected&amp;lt;/tt&amp;gt; fields is to allow for cost accounting and traffic monitoring (so that, for example, a driver may be disconnected after it has been idle for a while) to be written.&lt;br /&gt;
&lt;br /&gt;
I propose a command with the following semantics:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_GETEXTENDEDGLOBALSTATS -- Get interface accumulated statistics;&lt;br /&gt;
           updated version.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command causes the device driver to retrieve various global&lt;br /&gt;
        runtime statistics for this network interface. The format of the data&lt;br /&gt;
        returned is as follows:&lt;br /&gt;
&lt;br /&gt;
           struct Sana2ExtDeviceStats&lt;br /&gt;
           {&lt;br /&gt;
              ULONG s2xds_Length;&lt;br /&gt;
              ULONG s2xds_Actual;&lt;br /&gt;
&lt;br /&gt;
              S2QUAD s2xds_PacketsReceived;&lt;br /&gt;
              S2QUAD s2xds_PacketsSent;&lt;br /&gt;
              S2QUAD s2xds_BadData;&lt;br /&gt;
              S2QUAD s2xds_Overruns;&lt;br /&gt;
              S2QUAD s2xds_UnknownTypesReceived;&lt;br /&gt;
              S2QUAD s2xds_Reconfigurations;&lt;br /&gt;
              struct timeval s2xds_LastStart;&lt;br /&gt;
&lt;br /&gt;
              struct timeval s2xds_LastConnected;&lt;br /&gt;
              struct timeval s2xds_LastDisconnected;&lt;br /&gt;
              struct timeval s2xds_TimeConnected;&lt;br /&gt;
           };&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command          - S2_GETEXTENDEDGLOBALSTATS&lt;br /&gt;
        ios2_StatData         - Pointer to Sana2ExtDeviceStats structure&lt;br /&gt;
                                to fill in&lt;br /&gt;
        ios2_BufferManagement - Magic cookie as returned when opening the&lt;br /&gt;
                                driver with a struct IOSana2Req&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Req.io_Error - Zero if successful; non-zero otherwise&lt;br /&gt;
        ios2_WireError    - More specific error number&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
I propose that the following command number should be assigned:&lt;br /&gt;
&amp;lt;tt&amp;gt;#define S2_GETEXTENDEDGLOBALSTATS 0xC004&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_GETGLOBALSTATS ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        GetGlobalStats -- Get interface accumulated statistics.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command causes the device driver to retrieve various global&lt;br /&gt;
        runtime statistics for this network interface. The format of the&lt;br /&gt;
        data returned is as follows:&lt;br /&gt;
&lt;br /&gt;
            struct Sana2DeviceStats&lt;br /&gt;
            {&lt;br /&gt;
                ULONG PacketsReceived;&lt;br /&gt;
                ULONG PacketsSent;&lt;br /&gt;
                ULONG BadData;&lt;br /&gt;
                ULONG Overruns;&lt;br /&gt;
                ULONG UnknownTypesReceived;&lt;br /&gt;
                ULONG Reconfigurations;&lt;br /&gt;
                timeval LastStart;&lt;br /&gt;
            };&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - S2_GETGLOBALSTATS.&lt;br /&gt;
        ios2_StatData   - Pointer to Sana2DeviceStats structure to fill.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - Zero if successful; non-zero otherwise.&lt;br /&gt;
        ios2_WireError  - More specific error number.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        S2_GETSPECIALSTATS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_GETNETWORKINFO ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
	S2_GETNETWORKINFO -- Get information on current network.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
	This command provides information on the status of the currently&lt;br /&gt;
	used network. If this command completes successfully, ios2_StatData&lt;br /&gt;
	will contain a pointer to a tag list that contains information on&lt;br /&gt;
	the network. The S2INFO_#? tags used are defined in the&lt;br /&gt;
	devices/sana2wireless.h include file.&lt;br /&gt;
&lt;br /&gt;
	The returned taglist is allocated from the supplied memory pool.&lt;br /&gt;
	To discard the results of this command, the entire memory pool&lt;br /&gt;
	should be destroyed.&lt;br /&gt;
&lt;br /&gt;
   INPUTS&lt;br /&gt;
	ios2_Data - Pointer to an Exec memory pool.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
	ios2_Data - Remains unchanged.&lt;br /&gt;
	ios2_StatData - Pointer to a tag list.&lt;br /&gt;
	io_Error - Zero if successful; non-zero otherwise.&lt;br /&gt;
	ios2_WireError - More specific error code.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_GETNETWORKS ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
	S2_GETNETWORKS -- Scan for available networks.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
	This command supplies details of available networks. If the scan&lt;br /&gt;
	should be limited to one specific network, the S2INFO_SSID tag&lt;br /&gt;
	should specify its name.&lt;br /&gt;
&lt;br /&gt;
	If this command completes successfully, ios2_StatData will contain&lt;br /&gt;
	an array of pointers to tag lists, each of which contains&lt;br /&gt;
	information on a single network. The device will set ios2_DataLength&lt;br /&gt;
	to the number of elements in this array.&lt;br /&gt;
&lt;br /&gt;
	The returned taglists are allocated from the supplied memory pool.&lt;br /&gt;
	To discard the results of this command, the entire memory pool&lt;br /&gt;
	should be destroyed.&lt;br /&gt;
&lt;br /&gt;
	The S2INFO_#? tags used with this command are defined in the&lt;br /&gt;
	devices/sana2wireless.h include file.&lt;br /&gt;
&lt;br /&gt;
   INPUTS&lt;br /&gt;
	ios2_Data - Pointer to an Exec memory pool.&lt;br /&gt;
	ios2_StatData - Pointer to taglist that specifies parameters to use.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
	ios2_DataLength - Number of tag lists returned.&lt;br /&gt;
	ios2_Data - Remains unchanged.&lt;br /&gt;
	ios2_StatData - Pointer to an array of tag lists.&lt;br /&gt;
	io_Error - Zero if successful; non-zero otherwise.&lt;br /&gt;
	ios2_WireError - More specific error code.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_GETPEERADDRESS ==&lt;br /&gt;
&lt;br /&gt;
As part of the negotiation process, the PPP protocol can return the addresses used by the peer (the other side of the point-to-point connection PPP establishes; typically a dial-in server) and assigned to the client establishing the connection. The SANA-II standard does not provide for a mechanism to return such information. Existing drivers therefore had to resort to other means, such as by setting global environment variables containing this information.&lt;br /&gt;
&lt;br /&gt;
I propose a command with the following semantics:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_GETPEERADDRESS -- Obtain the addresses used by the peer&lt;br /&gt;
           (server) and the client of a point-to-point connection.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        Obtain the address used by the peer of a point-to-point connection and&lt;br /&gt;
        the address assigned to the local driver.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command          - S2_GETPEERADDRESS&lt;br /&gt;
        ios2_Flags            - Supported flags are:&lt;br /&gt;
                                SANA2IOB_QUICK&lt;br /&gt;
        ios2_BufferManagement - Magic cookie as returned when opening the&lt;br /&gt;
                                driver with a struct IOSana2Req&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Req.io_Error - Zero if successful; non-zero otherwise&lt;br /&gt;
        ios2_WireError    - More specific error number&lt;br /&gt;
        ios2_SrcAddr      - Address assigned to the local driver&lt;br /&gt;
        ios2_DstAddr      - Address used by the peer&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        The size of the address returned by S2_GETPEERADDRESS must not be&lt;br /&gt;
        different from the size returned by the S2_DEVICEQUERY command. For&lt;br /&gt;
        example, if a 32 bit IPv4 address was advertized, the driver must not&lt;br /&gt;
        return a 128 bit IPv6 address instead.&lt;br /&gt;
&lt;br /&gt;
        If the driver is unable to return the local driver address&lt;br /&gt;
        (ios2_SrcAddr) or the peer&#039;s address (ios2_DstAddr) it must fill the&lt;br /&gt;
        respective address fields with zeroes. It is legal for a driver to&lt;br /&gt;
        respond to the S2_GETPEERADDRESS command with two zero addresses (both&lt;br /&gt;
        ios2_SrcAddr and ios2_DstAddr filled with zeroes).&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
I propose that the following command number should be assigned:&lt;br /&gt;
&amp;lt;tt&amp;gt;#define S2_GETPEERADDRESS 0xC002&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This command may be useful beyond the typical application (PPP) described above.&lt;br /&gt;
&lt;br /&gt;
== S2_GETSIGNALQUALITY ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
	S2_GETSIGNALQUALITY -- Get signal quality statistics.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
	This command fills in the supplied Sana2SignalQuality structure with&lt;br /&gt;
	current signal and noise levels. The unit for these figures is dBm.&lt;br /&gt;
	Typically, they are negative values.&lt;br /&gt;
&lt;br /&gt;
   INPUTS&lt;br /&gt;
	ios2_StatData - Pointer to Sana2SignalQuality structure.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
	io_Error - Zero if successful; non-zero otherwise.&lt;br /&gt;
	ios2_WireError - More specific error code.&lt;br /&gt;
	ios2_StatData - Pointer to filled Sana2SignalQuality structure.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_GETSPECIALSTATS ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_GETSPECIALSTATS -- Get network type specific statistics.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This function returns statistics which are specific to the type of&lt;br /&gt;
        network medium this driver controls. For example, this command could&lt;br /&gt;
        return statistics common to all Ethernets which are not common to all&lt;br /&gt;
        network mediums in general.&lt;br /&gt;
&lt;br /&gt;
        The supplied Sana2SpecialStatData structure is given below:&lt;br /&gt;
&lt;br /&gt;
            struct Sana2SpecialStatData&lt;br /&gt;
            {&lt;br /&gt;
                ULONG RecordCountMax;&lt;br /&gt;
                ULONG RecordCountSupplied;&lt;br /&gt;
                struct Sana2StatRecord[RecordCountMax];&lt;br /&gt;
            };&lt;br /&gt;
&lt;br /&gt;
        The format of the data returned is:&lt;br /&gt;
&lt;br /&gt;
            struct Sana2StatRecord&lt;br /&gt;
            {&lt;br /&gt;
                ULONG Type;     /* Amiga registered */&lt;br /&gt;
                LONG Count;     /* the stat itself */&lt;br /&gt;
                char *String;   /* null terminated */&lt;br /&gt;
            };&lt;br /&gt;
&lt;br /&gt;
        The RecordCountMax field specifies the number of records that the&lt;br /&gt;
        caller is prepared to accomodate.&lt;br /&gt;
&lt;br /&gt;
        RecordCountSupplied is the number of record actually supplied which&lt;br /&gt;
        will not exceed RecordCountMax.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - S2_GETSPECIALSTATS.&lt;br /&gt;
        ios2_StatData   - Pointer to a Sana2SpecialStatData structure to fill.&lt;br /&gt;
                          RecordCountMax must be initialized.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - Zero if successful; non-zero otherwise.&lt;br /&gt;
        ios2_WireError  - More specific error number.&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        Amiga will maintain registered statistic Types.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        S2_GETGLOBALSTATS, &amp;amp;lt;devices/sana2specialstats.h&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_GETSTATIONADDRESS ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_GETSTATIONADDRESS -- Get default and interface address.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command causes the device driver to copy the current interface&lt;br /&gt;
        address into ios2_SrcAddr, and to copy the factory default station&lt;br /&gt;
        address (if any) into ios2_DstAddr.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - S2_GETSTATIONADDRESS.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - Zero if successful; non-zero otherwise.&lt;br /&gt;
        ios2_WireError  - More specific error number.&lt;br /&gt;
        ios2_SrcAddr    - Current interface address.&lt;br /&gt;
        ios2_DstAddr    - Default interface address (if any).&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        S2_CONFIGINTERFACE&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_GETTYPESTATS ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_GETTYPESTATS -- Get accumulated type specific statistics.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command causes the device driver to retrieve various packet type&lt;br /&gt;
        specific runtime statistics for this network interface. The format of&lt;br /&gt;
        the data returned is as follows:&lt;br /&gt;
&lt;br /&gt;
            struct Sana2TypeStatData&lt;br /&gt;
            {&lt;br /&gt;
                LONG PacketsSent;&lt;br /&gt;
                LONG PacketsReceived;&lt;br /&gt;
                LONG BytesSent;&lt;br /&gt;
                LONG BytesReceived;&lt;br /&gt;
                LONG PacketsDropped;&lt;br /&gt;
            };&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - S2_GETTYPESTATS.&lt;br /&gt;
        ios2_PacketType - Packet type of interest.&lt;br /&gt;
        ios2_StatData   - Pointer to TypeStatData structure to fill in.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - Zero if successful; non-zero otherwise.&lt;br /&gt;
        ios2_WireError  - More specific error number.&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        Statistics for a particular packet type are only available while that&lt;br /&gt;
        packet type is being ``tracked&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        S2_TRACKTYPE, S2_UNTRACKTYPE&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_MULTICAST ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_MULTICAST -- Multicast a packet on network.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command works the same as CMD_WRITE except that it also performs&lt;br /&gt;
        whatever special processing of the packet is required to do a&lt;br /&gt;
        multicast send. The actual multicast mechanism is neccessarily&lt;br /&gt;
        network/interface/device specific.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - S2_MULTICAST.&lt;br /&gt;
        ios2_Flags      - Supported flags are:&lt;br /&gt;
                                SANA2IOB_RAW&lt;br /&gt;
                                SANA2IOB_QUICK&lt;br /&gt;
        ios2_PacketType - Packet type to send.&lt;br /&gt;
        ios2_DstAddr    - Destination interface address for this packet.&lt;br /&gt;
        ios2_DataLength - Length of the Data to be sent.&lt;br /&gt;
        ios2_Data       - Abstract data structure which packet data is&lt;br /&gt;
                          contained in.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - Zero if successful; non-zero otherwise.&lt;br /&gt;
                          This command can fail for many reasons and&lt;br /&gt;
                          is not supported by all networks and/or&lt;br /&gt;
                          network interfaces.&lt;br /&gt;
        ios2_WireError  - More specific error number.&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        The address supplied in ios2_DstAddr will be sanity checked (if&lt;br /&gt;
        possible) by the driver. If the supplied address fails this sanity&lt;br /&gt;
        check, the multicast request will fail immediately with ios2_Error&lt;br /&gt;
        set to S2WERR_BAD_MULTICAST.&lt;br /&gt;
&lt;br /&gt;
        Another Amiga will not receive a multicast packet unless it has had&lt;br /&gt;
        the particular multicast address being used S2_ADDMULTICASTADRESS&#039;d.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        CMD_WRITE, S2_BROADCAST, S2_ADDMULTICASTADDRESS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_OFFLINE ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_OFFLINE -- Remove interface from service.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command removes a network interface from service.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - S2_OFFLINE.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - Zero if successful; non-zero otherwise.&lt;br /&gt;
        ios2_WireError  - More specific error number.&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        Aborts all pending reads and writes with ios2_Error set to&lt;br /&gt;
        S2ERR_OUTOFSERVICE.&lt;br /&gt;
&lt;br /&gt;
        While the interface is offline, all read, writes and any other&lt;br /&gt;
        command that touches interface hardware will be rejected with&lt;br /&gt;
        ios2_Error set to S2ERR_OUTOFSERVICE.&lt;br /&gt;
&lt;br /&gt;
        This command is intended to permit a network interface to be&lt;br /&gt;
        tested on an otherwise live system.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        S2_ONLINE&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_ONEVENT ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_ONEVENT -- Return when specified event occures.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command returns when a particular event condition has occured&lt;br /&gt;
        on the network or this network interface.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - S2_ONEVENT.&lt;br /&gt;
        ios2_Flags      - Supported flags are:&lt;br /&gt;
                                SANA2IOB_QUICK&lt;br /&gt;
        ios2_WireError  - Mask of event(s) to wait for&lt;br /&gt;
                          (from &amp;amp;lt;devices/sana2.h&amp;amp;gt;).&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - Zero if successful; non-zero otherwise.&lt;br /&gt;
        ios2_WireError  - Mask of events that occured.&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        If this device driver does not understand the specified event&lt;br /&gt;
        condition(s) then the command returns immediately with&lt;br /&gt;
        ios2_Req.io_Error set to S2_ERR_NOT_SUPPORTED and ios2_WireError&lt;br /&gt;
        S2WERR_BAD_EVENT.  A successful return will have ios2_Error set to&lt;br /&gt;
        zero ios2_WireError set to the event number.&lt;br /&gt;
&lt;br /&gt;
        All pending requests for a particular event will be returned when&lt;br /&gt;
        that event occurs.&lt;br /&gt;
&lt;br /&gt;
        All event types that cover a particular condition are returned when&lt;br /&gt;
        that condition occures. For instance, if an error is returned by&lt;br /&gt;
        a buffer management function during receive processing, events of&lt;br /&gt;
        types S2EVENT_ERROR, S2EVENT_RX and S2EVENT_BUFF would be returned if&lt;br /&gt;
        pending.&lt;br /&gt;
&lt;br /&gt;
        Types ONLINE and OFFLINE return immediately if the device is&lt;br /&gt;
        already in the state to be waited for.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_ONLINE ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_ONLINE -- Put a network interface back in service.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command places an offline network interface back into service.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - S2_ONLINE.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - Zero if successful; non-zero otherwise.&lt;br /&gt;
        ios2_WireError  - More specific error number.&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        This command is responsible for putting the network interface&lt;br /&gt;
        hardware back into a known state (as close as possible to the&lt;br /&gt;
        state before S2_OFFLINE) and resets the unit global and special&lt;br /&gt;
        statistics.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        S2_OFFLINE&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_READMGMT ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
	S2_READMGMT -- Read a management frame.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
	Reads a raw IEEE 802.11 management frame from the device. The buffer&lt;br /&gt;
	management mechanism used is simpler than that used for data&lt;br /&gt;
	packets (e.g. with CMD_READ): a buffer pointer and a length value&lt;br /&gt;
	are passed to the device.&lt;br /&gt;
&lt;br /&gt;
	As with CMDREAD/S2_READORPHAN, multiple S2_READMGMT requests can&lt;br /&gt;
	(and should) be queued concurrently to ensure no incoming frames are&lt;br /&gt;
	missed.&lt;br /&gt;
&lt;br /&gt;
   INPUTS&lt;br /&gt;
	ios2_DataLength - size of frame buffer.&lt;br /&gt;
	ios2_Data - pointer to a frame buffer.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
	io_Error - Zero if successful; non-zero otherwise.&lt;br /&gt;
	ios2_WireError - More specific error code.&lt;br /&gt;
	ios2_DataLength - actual size of received frame.&lt;br /&gt;
	ios2_Data - pointer to the filled frame buffer.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_READORPHAN ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_READORPHAN -- Get a packet for which there is no reader.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        Get the next packet available that does not satisfy any then-pending&lt;br /&gt;
        CMD_READ requests. The data returned in the ios2_Data structure is&lt;br /&gt;
        normally the Data Link Layer packet type field and the packet data. If&lt;br /&gt;
        bit SANA2IOB_RAW is set in ios2_Flags, then the entire Data Link Layer&lt;br /&gt;
        packet, including both header and trailer information, will be&lt;br /&gt;
        returned.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - CMD_READORPHAN.&lt;br /&gt;
        ios2_Flags      - Supported flags are:&lt;br /&gt;
                                SANA2IOB_RAW&lt;br /&gt;
                                SANA2IOB_QUICK&lt;br /&gt;
        ios2_DataLength - Length of the Data to be sent.&lt;br /&gt;
        ios2_Data       - Abstract data structure which packet data is&lt;br /&gt;
                          contained in.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - Zero if successful; non-zero otherwise.&lt;br /&gt;
        ios2_WireError  - More specific error number.&lt;br /&gt;
        ios2_Flags      - The following flags may be returned:&lt;br /&gt;
                                SANA2IOB_RAW&lt;br /&gt;
                                SANA2IOB_BCAST&lt;br /&gt;
                                SANA2IOB_MCAST&lt;br /&gt;
        ios2_SrcAddr    - Source interface address of packet.&lt;br /&gt;
        ios2_DstAddr    - Destination interface address of packet.&lt;br /&gt;
        ios2_DataLength - Length of the Data to be sent.&lt;br /&gt;
        ios2_Data       - Abstract data structure which packet data is&lt;br /&gt;
                          contained in.&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        This is intended for debugging and management tools.  Protocols should&lt;br /&gt;
        not use this.&lt;br /&gt;
&lt;br /&gt;
        As with 802.3 packets on an ethernet, to determine which protocol&lt;br /&gt;
        family the returned packet belongs to you may have to specify&lt;br /&gt;
        SANA2IOB_RAW to get the entire data link layer wrapper (which is where&lt;br /&gt;
        the protocol type may be kept). Notice this necessarily means that&lt;br /&gt;
        this cannot be done in a network interface independent fashion.  The&lt;br /&gt;
        driver will, however, fill in the PacketType field to the best of its&lt;br /&gt;
        ability.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        CMD_READ, CMD_WRITE&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_SAMPLE_THROUGHPUT ==&lt;br /&gt;
&lt;br /&gt;
The SANA-II standard already allows for statistics to be returned on the amount of data that has passed through a driver. Unfortunately, that information is not very accurate in that no information is provided on the time span in which the data was accumulated. Such information would be helpful in trying to determine as accurately as possible how large the data throughput actually is. I therefore propose a new command which can be used to obtain that information, which uses the following data structure:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct Sana2ThroughputStats&lt;br /&gt;
{&lt;br /&gt;
   ULONG          s2ts_Length;&lt;br /&gt;
   ULONG          s2ts_Actual;&lt;br /&gt;
&lt;br /&gt;
   struct Task *  s2ts_NotifyTask;&lt;br /&gt;
   ULONG          s2ts_NotifyMask;&lt;br /&gt;
&lt;br /&gt;
   struct timeval s2ts_StartTime;&lt;br /&gt;
   struct timeval s2ts_EndTime;&lt;br /&gt;
   S2QUAD         s2ts_BytesSent;&lt;br /&gt;
   S2QUAD         s2ts_BytesReceived;&lt;br /&gt;
   S2QUAD         s2ts_Updates;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Before I proceed to explain what purposes the individual members serve, a few words on the &amp;lt;tt&amp;gt;S2QUAD&amp;lt;/tt&amp;gt; type, which is defined as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;typedef struct { ULONG s2q_High; ULONG s2q_Low; } S2QUAD;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In other words, the &amp;lt;tt&amp;gt;S2QUAD&amp;lt;/tt&amp;gt; type stands for an unsigned 64 bit big endian integer, as expressed in ISO &#039;C&#039; terms.&lt;br /&gt;
&lt;br /&gt;
The structure members have the following purposes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2ts_Length&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the size of the data structure to be filled in and should be initialized by the caller to &amp;lt;tt&amp;gt;sizeof(struct Sana2ThroughputStats)&amp;lt;/tt&amp;gt;. Smaller values are permitted, but these must not be smaller than 8 (which covers the &amp;lt;tt&amp;gt;s2ts_Length&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;s2ts_Actual&amp;lt;/tt&amp;gt; members). A driver which finds an &amp;lt;tt&amp;gt;s2ts_Length&amp;lt;/tt&amp;gt; &amp;amp;lt; 8 must treat this as an error and reject the command with &amp;lt;tt&amp;gt;ios2_Req.io_Error&amp;lt;/tt&amp;gt;=&amp;lt;tt&amp;gt;IOERR_BADLENGTH&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2ts_Actual&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The size of the data structure filled with information. This member is initialized by the driver and must be &amp;amp;lt;= &amp;lt;tt&amp;gt;s2ts_Length&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2ts_NotifyTask&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;Task&amp;lt;/tt&amp;gt; to notify whenever the contents of this data structure change. This must be &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; if no notification is desired.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; This feature should be used carefully, as so much data may arrive that the driver will almost be constantly signalling this &amp;lt;tt&amp;gt;Task&amp;lt;/tt&amp;gt; that a change has taken place.&lt;br /&gt;
&lt;br /&gt;
It is recommend that periodic polling be used, such as to update displays of a link monitoring program.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2ts_NotifyMask&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The signal mask to use for notifying the &amp;lt;tt&amp;gt;Task&amp;lt;/tt&amp;gt; whose address is found in &amp;lt;tt&amp;gt;s2ts_NotifyTask&amp;lt;/tt&amp;gt; (via &amp;lt;tt&amp;gt;Signal(s2ts-&amp;amp;gt;s2ts_NotifyTask,s2ts-&amp;amp;gt;s2ts_NotifyMask);&amp;lt;/tt&amp;gt;). This must be zero if no notification is desired.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2ts_StartTime&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The time when the driver started to fill in this data structure.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2ts_EndTime&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The time when the driver last updated the contents of this data structure.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2ts_BytesSent&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Total number of bytes sent since the driver started to fill in this data structure. This is a 64 bit integer.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2ts_BytesReceived&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Total number of bytes received since the driver started to fill in this data structure. This is a 64 bit integer.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2ts_Updates&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Number of times the driver has updated this data structure. This value will increase with every change. This is a 64 bit integer.&lt;br /&gt;
&lt;br /&gt;
A driver implementing this command should take care to update the members &amp;lt;tt&amp;gt;s2ts_EndTime&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;s2ts_BytesSent&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;s2ts_BytesReceived&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;s2ts_Updates&amp;lt;/tt&amp;gt; atomically each time changes are made.&lt;br /&gt;
&lt;br /&gt;
I propose a command with the following semantics:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_SAMPLE_THROUGHPUT -- Obtain accurate information on&lt;br /&gt;
           driver data throughput.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command installs a data structure which is updated every time&lt;br /&gt;
        data is sent or received by the driver.&lt;br /&gt;
&lt;br /&gt;
        This command must be sent via SendIO() or BeginIO(); until&lt;br /&gt;
        the associated I/O request is recalled using AbortIO(), the&lt;br /&gt;
        device unit will continue to update the Sana2ThroughputStats&lt;br /&gt;
        structure in real time.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command          - S2_SAMPLE_THROUGHPUT&lt;br /&gt;
        ios2_StatData         - Pointer to Sana2ThroughputStats structure&lt;br /&gt;
                                to fill in&lt;br /&gt;
        ios2_BufferManagement - Magic cookie as returned when opening the&lt;br /&gt;
                                driver with a struct IOSana2Req&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Req.io_Error - Zero if successful; non-zero otherwise&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        If this device driver does not understand this command,&lt;br /&gt;
        it will immediately return the IOSana2Req with&lt;br /&gt;
        ios2_Req.io_Error set to IOERR_NOCMD. Otherwise, the request will&lt;br /&gt;
        remain queued until it is removed with AbortIO() later.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
I propose that the following command number should be assigned:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;#define S2_SAMPLE_THROUGHPUT 0xC007&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_SANA2HOOK ==&lt;br /&gt;
&lt;br /&gt;
The &#039;traditional&#039; copy call-back functions are installed at &amp;lt;tt&amp;gt;OpenDevice()&amp;lt;/tt&amp;gt; time, and they are found in a &amp;lt;tt&amp;gt;TagItem&amp;lt;/tt&amp;gt; list which is passed along with the &amp;lt;tt&amp;gt;IOSana2Req&amp;lt;/tt&amp;gt;. For the new &amp;lt;tt&amp;gt;Hook&amp;lt;/tt&amp;gt;-based call-back functionality, I propose to introduce a new command. This command would take care of installing one single &amp;lt;tt&amp;gt;Hook&amp;lt;/tt&amp;gt; which will be invoked with the parameters described in section 3.1. The hook function can key off the &amp;lt;tt&amp;gt;SANA2HookMsg-&amp;amp;gt;schm_Method&amp;lt;/tt&amp;gt; field to figure out which function should be performed. Once the &amp;lt;tt&amp;gt;Hook&amp;lt;/tt&amp;gt; is installed via the command as follows, the driver shall ignore any and all tags passed to it during &amp;lt;tt&amp;gt;OpenDevice()&amp;lt;/tt&amp;gt; time.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_SANA2HOOK -- Install a Hook to perform operations such as copying,&lt;br /&gt;
                        overriding the call-back functions installed at&lt;br /&gt;
                        OpenDevice() time.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        The S2_SANA2HOOK command is to replace the &#039;traditional&#039; call-back&lt;br /&gt;
        functions installed through the TagItem list found in the&lt;br /&gt;
        IOSana2Req-&amp;amp;gt;ios2_BufferManagement field. Instead of assigning a&lt;br /&gt;
        function pointer for each copying function, all operations are&lt;br /&gt;
        to be performed through a Hook. This is intended to make the&lt;br /&gt;
        interface more portable and less dependant on a certain hardware&lt;br /&gt;
        architecture.&lt;br /&gt;
&lt;br /&gt;
        The hook message and the hook data structures allow for more than&lt;br /&gt;
        copying to be done.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - S2_SANA2HOOK&lt;br /&gt;
        ios2_Data       - Points to a struct Sana2Hook, which looks&lt;br /&gt;
                          like this:&lt;br /&gt;
&lt;br /&gt;
                             struct Sana2Hook&lt;br /&gt;
                             {&lt;br /&gt;
                                struct Hook s2h_Hook;&lt;br /&gt;
                                Tag *       s2h_Methods;&lt;br /&gt;
                             };&lt;br /&gt;
&lt;br /&gt;
                          The structure fields have the following purposes:&lt;br /&gt;
&lt;br /&gt;
                             s2h_Hook&lt;br /&gt;
                                A standard Hook structure, ready to be&lt;br /&gt;
                                called. Once installed, the complete Hook&lt;br /&gt;
                                structure including its Node structure is&lt;br /&gt;
                                off limits! The s2h_Hook remains installed&lt;br /&gt;
                                until CloseDevice().&lt;br /&gt;
&lt;br /&gt;
                             s2h_Methods&lt;br /&gt;
                                Points to a table of Tag values, each&lt;br /&gt;
                                identifying a copy method supported&lt;br /&gt;
                                (S2_CopyToBuff, S2_CopyFromBuff,&lt;br /&gt;
                                S2_CopyToBuff16, S2_CopyFromBuff16,&lt;br /&gt;
                                S2_CopyToBuff32, S2_CopyFromBuff32,&lt;br /&gt;
                                S2_DMACopyToBuff32, S2_DMACopyFromBuff32,&lt;br /&gt;
                                S2_DMACopyToBuff64 or S2_DMACopyFromBuff64)&lt;br /&gt;
                                or the logging facility (S2_Log).&lt;br /&gt;
                                The table must be terminated by TAG_END.&lt;br /&gt;
&lt;br /&gt;
                                The driver will check the table and&lt;br /&gt;
                                verify that the mandatory S2_CopyToBuff&lt;br /&gt;
                                and S2_CopyFromBuff commands are present.&lt;br /&gt;
                                Additional functionality is used as&lt;br /&gt;
                                available if the driver supports it.&lt;br /&gt;
&lt;br /&gt;
        ios2_DataLength - Must be &amp;amp;gt;= 20, which is the default length of&lt;br /&gt;
                          the Sana2Hook structure. This may grow in&lt;br /&gt;
                          the future, and larger values for ios2_DataLength&lt;br /&gt;
                          may indicate additional functionality associated&lt;br /&gt;
                          with the Sana2Hook.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - IOERR_NOCMD if this command is not supported&lt;br /&gt;
                          by the driver.&lt;br /&gt;
&lt;br /&gt;
                          IOERR_BADLENGTH if IOSana2Req-&amp;amp;gt;ios2_DataLength&lt;br /&gt;
                          is &amp;amp;lt; 20.&lt;br /&gt;
&lt;br /&gt;
                          IOERR_UNITBUSY if the Hook was already&lt;br /&gt;
                          installed or if any of the CMD_READ, CMD_WRITE,&lt;br /&gt;
                          S2_MULTICAST or S2_BROADCAST have already been&lt;br /&gt;
                          invoked.&lt;br /&gt;
&lt;br /&gt;
                          S2WERR_FUNCTIONS_MISSING if the table pointed&lt;br /&gt;
                          to by Sana2Hook-&amp;amp;gt;s2h_Methods does not&lt;br /&gt;
                          include the S2_CopyToBuff and S2_CopyFromBuff&lt;br /&gt;
                          tags.&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        The S2_SANA2HOOK command shall be invoked right after OpenDevice()&lt;br /&gt;
        as very first command.&lt;br /&gt;
&lt;br /&gt;
        When the command has been executed, the driver must use the&lt;br /&gt;
        newly installed Hook for all its copying or logging and cease to&lt;br /&gt;
        use the call-back functions provided at OpenDevice() time.&lt;br /&gt;
&lt;br /&gt;
        The contents of the Sana2Hook structure, as passed to the&lt;br /&gt;
        driver, must not be modified. This includes the MinNode&lt;br /&gt;
        at the beginning of the Hook structure which the driver may&lt;br /&gt;
        need to use for its own purposes.&lt;br /&gt;
&lt;br /&gt;
        The table pointed to by Sana2Hook-&amp;amp;gt;s2h_Methods must&lt;br /&gt;
        include at least the S2_CopyToBuff and S2_CopyFromBuff tags.&lt;br /&gt;
        It must be valid until CloseDevice() is called.&lt;br /&gt;
&lt;br /&gt;
        This field is to be treated as private by a protocol stack.&lt;br /&gt;
        IOSana2Req structures may be duplicated by copying&lt;br /&gt;
        ios2_BufferManagement, io_Device, and io_Unit.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The new command value is defined as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   #define S2_SANA2HOOK 0xC008&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The new error code is defined as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   #define S2WERR_FUNCTIONS_MISSING 24 /* mandatory copy functions are missing */&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_SETKEY ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
	S2_SETKEY -- Set an encryption key.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
	Sets one of the encryption keys for the device. Note that&lt;br /&gt;
	ios2_StatData, if used, points to a byte array representing the RX&lt;br /&gt;
	RX counter value.&lt;br /&gt;
&lt;br /&gt;
   INPUTS&lt;br /&gt;
	ios2_WireError - Key index.&lt;br /&gt;
	ios2_PacketType - Encryption type (e.g. S2ENC_WEP).&lt;br /&gt;
	ios2_DataLength - Key length.&lt;br /&gt;
	ios2_Data - Key.&lt;br /&gt;
	ios2_StatData - RX counter number (NULL if unused).&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
	io_Error - Zero if successful; non-zero otherwise.&lt;br /&gt;
	ios2_WireError - More specific error code.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_SETOPTIONS ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
	S2_SETOPTIONS -- Set network options.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
	Set various parameters for the network interface. This command&lt;br /&gt;
	should be called before going online to set any essential parameters&lt;br /&gt;
	not covered elsewhere. The S2INFO_#? tags used are defined in the&lt;br /&gt;
	devices/sana2wireless.h include file.&lt;br /&gt;
&lt;br /&gt;
   INPUTS&lt;br /&gt;
	ios2_Data - Pointer to a taglist that specifies parameters to use.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
	io_Error - Zero if successful; non-zero otherwise.&lt;br /&gt;
	ios2_WireError - More specific error code.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_TRACKTYPE ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_TRACKTYPE -- Accumulate statistics about a packet type.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command causes the device driver to accumulate statistics about&lt;br /&gt;
        a particular packet type. Packet type statistics, for the particular&lt;br /&gt;
        packet type, are zeroed by this command.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - S2_TRACKTYPE.&lt;br /&gt;
        ios2_PacketType - Packet type of interest.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - Zero if successful; non-zero otherwise.&lt;br /&gt;
        ios2_WireError  - More specific error number.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        S2_UNTRACKTYPE, S2_GETTYPESTATS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_UNTRACKTYPE ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_UNTRACKTYPE -- End statistics about a packet type.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command causes the device driver to stop accumulating&lt;br /&gt;
        statistics about a particular packet type.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - S2_UNTRACKTYPE.&lt;br /&gt;
        ios2_PacketType - Packet type of interest.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - Zero if successful; non-zero otherwise.&lt;br /&gt;
        ios2_WireError  - More specific error number.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        S2_TRACKTYPE, S2_GETTYPESTATS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_WRITEMGMT ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
	S2_WRITEMGMT -- Write a management frame.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
	Writes a raw IEEE 802.11 management frame to the device. The buffer&lt;br /&gt;
	management mechanism used is simpler than that used for data&lt;br /&gt;
	packets (e.g. with CMD_WRITE): a buffer pointer and a length value&lt;br /&gt;
	are passed to the device.&lt;br /&gt;
&lt;br /&gt;
   INPUTS&lt;br /&gt;
	ios2_DataLength - full frame length.&lt;br /&gt;
	ios2_Data - pointer to a complete IEEE 802.11 management frame.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
	io_Error - Zero if successful; non-zero otherwise.&lt;br /&gt;
	ios2_WireError - More specific error code.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Callback mechanisms =&lt;br /&gt;
&lt;br /&gt;
== CopyFromBuff ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        CopyFromBuff -- Copy n bytes from an abstract data structure.&lt;br /&gt;
&lt;br /&gt;
   SYNOPSIS&lt;br /&gt;
        success = CopyFromBuff(to, from, n)&lt;br /&gt;
        d0                     a0  a1    d0&lt;br /&gt;
&lt;br /&gt;
        BOOL CopyToBuff(VOID *, VOID *, ULONG);&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This function copies &#039;n&#039; bytes of data in the abstract data structure&lt;br /&gt;
        pointed to by &#039;from&#039; into the contigous memory pointed to by &#039;to&#039;.&lt;br /&gt;
        &#039;to&#039; must contain at least &#039;n&#039; bytes of usable memory or innocent&lt;br /&gt;
        memory will be overwritten.&lt;br /&gt;
&lt;br /&gt;
   INPUTS&lt;br /&gt;
        to              - pointer to contiguous memory to copy to.&lt;br /&gt;
        from            - pointer to abstract structure to copy from.&lt;br /&gt;
        n               - number of bytes to copy.&lt;br /&gt;
&lt;br /&gt;
   RESULT&lt;br /&gt;
        success         - TRUE if operation was successful, else FALSE.&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        This function must be callable from interrupts.  In particular, this&lt;br /&gt;
        means that this function may not directly or indirectly call any&lt;br /&gt;
        system memory functions (since those functions rely on Forbid() to&lt;br /&gt;
        protect themselves) and that  you must not compile this function&lt;br /&gt;
        with stack checking enabled.  See the Exec Interrupts&lt;br /&gt;
        chapter for more details on what is legal in a routine called from&lt;br /&gt;
        an interrupt handler.&lt;br /&gt;
&lt;br /&gt;
        &#039;C&#039; programmers should not compile with stack checking (option &#039;-v&#039;&lt;br /&gt;
        in SAS) and should geta4() or __saveds.&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== CopyToBuff ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        CopyToBuff -- Copy n bytes to an abstract data structure.&lt;br /&gt;
&lt;br /&gt;
   SYNOPSIS&lt;br /&gt;
        success = CopyToBuff(to, from, n)&lt;br /&gt;
        d0                   a0  a1    d0&lt;br /&gt;
&lt;br /&gt;
        BOOL CopyToBuff(VOID *, VOID *, ULONG);&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This function first does any initialization and/or allocation&lt;br /&gt;
        required to prepare the abstract data structure pointed at by &#039;to&#039;&lt;br /&gt;
        to be filled with &#039;n&#039; bytes of data from &#039;from&#039;.  It then executes&lt;br /&gt;
        the copy operation.&lt;br /&gt;
&lt;br /&gt;
        If, for example, there is not enough memory available to prepare&lt;br /&gt;
        the abstract data structure, the call is failed and FALSE is returned.&lt;br /&gt;
&lt;br /&gt;
        The buffer management scheme should be such that any memory needed&lt;br /&gt;
        to fulfill CopyToBuff() calls is already allocated from the system&lt;br /&gt;
        before the call to CopyToBuff() is made.&lt;br /&gt;
&lt;br /&gt;
   INPUTS&lt;br /&gt;
        to              - pointer to abstract structure to copy to.&lt;br /&gt;
        from            - pointer to contiguous memory to copy from.&lt;br /&gt;
        n               - number of bytes to copy.&lt;br /&gt;
&lt;br /&gt;
   RESULT&lt;br /&gt;
        success         - TRUE if operation was successful, else FALSE.&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        This function must be callable from interrupts.  In particular, this&lt;br /&gt;
        means that this function may not directly or indirectly call any&lt;br /&gt;
        system memory functions (since those functions rely on Forbid() to&lt;br /&gt;
        protect themselves) and that you must not compile this function&lt;br /&gt;
        with stack checking enabled.  See the Exec Interrupts&lt;br /&gt;
        chapter for more details on what is legal in a routine called from&lt;br /&gt;
        an interrupt handler.&lt;br /&gt;
&lt;br /&gt;
        &#039;C&#039; programmers should not compile with stack checking (option &#039;-v&#039;&lt;br /&gt;
        in SAS) and should geta4() or __saveds.&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== PacketFilter ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        PacketFilter -- Perform filtering operation on CMD_READ&#039;s.&lt;br /&gt;
&lt;br /&gt;
   SYNOPSIS&lt;br /&gt;
        keep = PacketFilter(hook, ios2, data)&lt;br /&gt;
        d0                   a0    a2    a1&lt;br /&gt;
&lt;br /&gt;
        BOOL PacketFilter(struct Hook *, struct IOSana2Req *, APTR);&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This function (if supplied by a protocol stack) may be used to&lt;br /&gt;
        reject packets before they are copied into a protocol stack&#039;s&lt;br /&gt;
        internal buffers.&lt;br /&gt;
&lt;br /&gt;
        The IOSana2Req structure should be set up to look (almost) exactly&lt;br /&gt;
        as it would if it was successfully returned for the current packet.&lt;br /&gt;
        Specifically, the fields that should be set up correctly are:&lt;br /&gt;
&lt;br /&gt;
        ios2-&amp;amp;gt;ios2_DataLength&lt;br /&gt;
        ios2-&amp;amp;gt;ios2_SrcAddr&lt;br /&gt;
        ios2-&amp;amp;gt;ios2_DstAddr&lt;br /&gt;
&lt;br /&gt;
       The &amp;amp;quot;data&amp;amp;quot; pointer must point to the beginning of the packet data&lt;br /&gt;
        that is stored in contiguous memory.  The data should NOT include&lt;br /&gt;
        any hardware specific headers (unless of course the CMD_READ&lt;br /&gt;
        request wanted RAW packets).&lt;br /&gt;
&lt;br /&gt;
   INPUTS&lt;br /&gt;
        hook            - pointer to the Hook originally supplied during&lt;br /&gt;
                          OpenDevice().&lt;br /&gt;
        ios2            - The IOSana2Req CMD_READ request that will be used&lt;br /&gt;
                          (the &amp;amp;quot;object&amp;amp;quot; of the Hook call).&lt;br /&gt;
        data            - The packet data (the &amp;amp;quot;message&amp;amp;quot; of the Hook call).&lt;br /&gt;
&lt;br /&gt;
   RESULT&lt;br /&gt;
        success         - TRUE if the driver should provide the packet to&lt;br /&gt;
                          the protocol stack, FALSE if the packet should be&lt;br /&gt;
                          ignored.&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        This function must be callable from interrupts.  In particular, this  &lt;br /&gt;
        means that this function may not directly or indirectly call any&lt;br /&gt;
        system memory functions (since those functions rely on Forbid() to&lt;br /&gt;
        protect themselves) and that  you must not compile this function&lt;br /&gt;
        with stack checking enabled.  See the Exec Interrupts&lt;br /&gt;
        chapter for more details on what is legal in a routine called from&lt;br /&gt;
        an interrupt handler.&lt;br /&gt;
&lt;br /&gt;
        &#039;C&#039; programmers should not compile with stack checking (option &#039;-v&#039;&lt;br /&gt;
        in SAS) and should geta4() or __saveds.&lt;br /&gt;
&lt;br /&gt;
        What does packet filtering do? With the original ``SANA-II Network&lt;br /&gt;
        Device Driver Specification&#039;&#039;, a protocol stack could open a device&lt;br /&gt;
        and ask for certain packet types. It got all the packets that matched&lt;br /&gt;
        this type. As it turned out, this could be mighty inefficient if there&lt;br /&gt;
        were packets that the protocol stack did not use at all. These would&lt;br /&gt;
        go into read processing of the protocol stack and waste CPU time even&lt;br /&gt;
        though they could have been easily identified on arrival.&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Ethernet description =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#define S2WireType_Ethernet             1&lt;br /&gt;
&lt;br /&gt;
ios2_DataLength:&lt;br /&gt;
        valid ethernet packets have 64 to 1500 bytes of data.&lt;br /&gt;
&lt;br /&gt;
Address format:&lt;br /&gt;
        Ethernet addresses consist of 47 bits of address information and&lt;br /&gt;
        a 1 bit multicast flag. The standard for expressing ethernet&lt;br /&gt;
        addresses is as 6 bytes (octets) in the order in which the bytes&lt;br /&gt;
        are transmitted with the low-order bits in a byte transmitted&lt;br /&gt;
        first. The multicast flag bit is the least-significant bit of the&lt;br /&gt;
        first byte.&lt;br /&gt;
&lt;br /&gt;
        Ethernet addresses in a Sana2IOReq occupy the first 6 bytes of&lt;br /&gt;
        an address field in transmission order with the low-order bits in&lt;br /&gt;
        a byte transmitted first.&lt;br /&gt;
&lt;br /&gt;
Station Address:&lt;br /&gt;
        Each ethernet board must have a unique ethernet hardware address.&lt;br /&gt;
        Drivers will override any attempt to set the address to anything&lt;br /&gt;
        other than the ROM address.&lt;br /&gt;
&lt;br /&gt;
Raw reads and writes:&lt;br /&gt;
        6 bytes of destination address,&lt;br /&gt;
        6 bytes of source address,&lt;br /&gt;
        2 bytes of type,&lt;br /&gt;
        64 to 1500 bytes of data&lt;br /&gt;
        (followed by 4 byte CRC value covering all of the above&lt;br /&gt;
         which is hardware generated and checked, hence not included&lt;br /&gt;
         in even raw packets)&lt;br /&gt;
&lt;br /&gt;
Multicast:      Supported&lt;br /&gt;
&lt;br /&gt;
Broadcast:      Supported&lt;br /&gt;
&lt;br /&gt;
Promiscuous:    Supported&lt;br /&gt;
&lt;br /&gt;
Packet Type Numbers for Ethernet are assigned by:&lt;br /&gt;
&lt;br /&gt;
        Xerox Corporation&lt;br /&gt;
        Xerox Systems Institute&lt;br /&gt;
        475 Oakmead Parkway, Sunnyvale, CA 94086&lt;br /&gt;
        Attn: Ms. Fonda Pallone&lt;br /&gt;
        (408) 737-4652&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Some Common Packet Type Numbers:&lt;br /&gt;
&lt;br /&gt;
      decimal  Hex        Description&lt;br /&gt;
      -------  ---        -----------&lt;br /&gt;
         000   0000-05DC  IEEE 802.3 Length Field&lt;br /&gt;
        2048   0800       TCP/IP -- IP&lt;br /&gt;
        2054   0806       TCP/IP -- ARP&lt;br /&gt;
       32821   8035       TCP/IP -- RARP&lt;br /&gt;
       32923   809B       Appletalk&lt;br /&gt;
       33011   80F3       AppleTalk AARP (Kinetics)&lt;br /&gt;
       33100   814C       SNMP&lt;br /&gt;
       33079   8137-8138  Novell, Inc.&amp;lt;/pre&amp;gt;&lt;br /&gt;
= ARCNET description =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;S2WireType_Arcnet       7&lt;br /&gt;
&lt;br /&gt;
ios2_DataLength:&lt;br /&gt;
        506 byte MTU (because of the possibility of two byte Types).&lt;br /&gt;
        Packets of size 254, 255, or 256 bytes are padded to 257 bytes before&lt;br /&gt;
        transmition.&lt;br /&gt;
&lt;br /&gt;
Station Address:&lt;br /&gt;
        ARCNET hardware may have addresses set with jumpers, DIP switches&lt;br /&gt;
        or software.  Different drivers may therefore behave differently&lt;br /&gt;
        with S2_CONFIGINTERFACE.&lt;br /&gt;
&lt;br /&gt;
        Hardware addresses should be assigned by users from highest to lowest&lt;br /&gt;
        because there is some efficiency gained in the token passing scheme&lt;br /&gt;
        this way.  For example, on a three node network, hardware numbers 254,&lt;br /&gt;
        253 and 252 should be used rather than 1, 2 and 3.&lt;br /&gt;
&lt;br /&gt;
Raw reads and writes:&lt;br /&gt;
        Short Packets (1-253 bytes)&lt;br /&gt;
                Destination Address             (1 byte)&lt;br /&gt;
                Source Address                  (1 byte)&lt;br /&gt;
                Count (256-N-Type length)       (1 byte)&lt;br /&gt;
                Padding                         (to byte number Count)&lt;br /&gt;
                Type                            (1 or 2 bytes)&lt;br /&gt;
                Data                            (N bytes)&lt;br /&gt;
&lt;br /&gt;
        Long Packets (257-506 bytes)&lt;br /&gt;
                Destination Address             (1 byte)&lt;br /&gt;
                Source Address                  (1 byte)&lt;br /&gt;
                zero                            (1 byte)&lt;br /&gt;
                Count (512-N-Type length)       (1 byte)&lt;br /&gt;
                Padding                         (to byte number Count)&lt;br /&gt;
                Type                            (1 or 2 bytes)&lt;br /&gt;
                Data                            (N bytes)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Multicast:      Not Supported&lt;br /&gt;
&lt;br /&gt;
Broadcast:      Supported&lt;br /&gt;
&lt;br /&gt;
Promiscuous:    Generally Not Supported&lt;br /&gt;
&lt;br /&gt;
Packet Type Numbers for ARCNET are assigned by:&lt;br /&gt;
        Datapoint Corporation&lt;br /&gt;
&lt;br /&gt;
Some Common Packet Type Numbers&lt;br /&gt;
&lt;br /&gt;
        decimal  hex    description&lt;br /&gt;
        -------  ---    -----------&lt;br /&gt;
        221      DD     AppleTalk&lt;br /&gt;
        240      F0     TCP/IP -- IP   (RFC 1051)&lt;br /&gt;
        241      F1     TCP/IP -- ARP  (RFC 1051)&lt;br /&gt;
        212      F0     TCP/IP    IP   (RFC 1201, proposed)&lt;br /&gt;
        213      F1     TCP/IP -- ARP  (RFC 1201, proposed)&lt;br /&gt;
        214      D6     TCP/IP -- RARP (RFC 1201, proposed)&lt;br /&gt;
        247      F7     Banyan Vines&lt;br /&gt;
        250      FA     Novell IPX&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Authors =&lt;br /&gt;
&lt;br /&gt;
== Revision 2 &amp;amp; 3 ==&lt;br /&gt;
&lt;br /&gt;
Copyright © 1992-2000 Amiga, Inc. All Rights Reserved&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Amiga is a registered trademark of Amiga, Inc. Ethernet is a trademark of Xerox Corporation. ARCNET is a trademark of Datapoint Corporation. DECNet is a trademark of Digital Equipment Corporation. AppleTalk is a trademark of Apple Computer, Inc.&lt;br /&gt;
&lt;br /&gt;
== Revision 4 ==&lt;br /&gt;
&lt;br /&gt;
Extending the SANA-II network driver specification&amp;lt;br /&amp;gt;&lt;br /&gt;
by Olaf Barthel&lt;br /&gt;
&lt;br /&gt;
(Last updated 02-Mar-2003)&lt;br /&gt;
&lt;br /&gt;
== Revision 5 ==&lt;br /&gt;
&lt;br /&gt;
Hook-based callback function extensions for SANA-II (SANA-IIR5) &amp;lt;br /&amp;gt;&lt;br /&gt;
by Olaf Barthel and Heinz Wrobel&lt;br /&gt;
&lt;br /&gt;
== Revision 6 ==&lt;br /&gt;
&lt;br /&gt;
SANA-II IEEE 802.11 wireless API &amp;lt;br/&amp;gt;&lt;br /&gt;
by Neil Cafferkey&lt;br /&gt;
&lt;br /&gt;
= Acknowledgments =&lt;br /&gt;
&lt;br /&gt;
== Revision 2 &amp;amp; 3 ==&lt;br /&gt;
&lt;br /&gt;
Many people and companies have contributed to the &amp;quot;SANA-II Network Device Driver Specification&amp;quot;. The original SANA-II Autodocs and includes were put together by Ray Brand, Perry Kivolowitz (ASDG) and Martin Hunt. Those original documents evolved to their current state and grew to include this document at the hands of Dale Larson and Greg Miller. Brian Jackson and John Orr provided valuable editing. Randell Jesup has provided sage advice on several occasions. The buffer management callback mechanism was his idea. Dale Luck (GfxBase) and Rick Spanbauer (Ameristar Technologies) have provided valuable comments throughout the process. Nicolas Benezan (ADONIS) provided many detailed and useful comments on weaknesses in late drafts of the specification. The enhancements for better buffer management, clarifications and notes for device implementers were added to the specification by Heinz Wrobel whilst consulting for Amiga Technologies GmbH, yielding revision 3.0 of the specification.&lt;br /&gt;
&lt;br /&gt;
Thanks to all the above and the numerous others who have contributed with their comments, questions and discussions.&lt;br /&gt;
&lt;br /&gt;
= Changes =&lt;br /&gt;
&lt;br /&gt;
== Revision 4 ==&lt;br /&gt;
&lt;br /&gt;
Changes since 24-Dec-2002:&lt;br /&gt;
&lt;br /&gt;
* The &amp;lt;tt&amp;gt;Sana2Connection&amp;lt;/tt&amp;gt; data structure used by the &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt; command now must remain valid until the &amp;lt;tt&amp;gt;S2_DISCONNECT&amp;lt;/tt&amp;gt; command is sent (see [[#2.4|section 2.4]]).&lt;br /&gt;
&lt;br /&gt;
Changes since 01-May-2002:&lt;br /&gt;
&lt;br /&gt;
* Added the &amp;lt;tt&amp;gt;ppp.async.readrequests&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;ppp.async.eof&amp;lt;/tt&amp;gt; configuration keywords.&lt;br /&gt;
&lt;br /&gt;
Changes since 04-Jan-2002:&lt;br /&gt;
&lt;br /&gt;
* Added the &amp;lt;tt&amp;gt;ppp.dummyremoteaddress&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;ppp.ethernet.ac&amp;lt;/tt&amp;gt; configuration keywords.&lt;br /&gt;
&lt;br /&gt;
Changes since 10-Dec-2001:&lt;br /&gt;
&lt;br /&gt;
* Converted to HTML format.&lt;br /&gt;
* Added the &amp;lt;tt&amp;gt;&amp;amp;lt;devices/sana2.h&amp;amp;gt;&amp;lt;/tt&amp;gt; header file to the appendix.&lt;br /&gt;
* The memory alignment for the &amp;lt;tt&amp;gt;S2_DMACopyToBuff64&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2_DMACopyFromBuff64&amp;lt;/tt&amp;gt; hooks refers to bits and not to bytes.&lt;br /&gt;
&lt;br /&gt;
Changes since 19-Nov-2001:&lt;br /&gt;
&lt;br /&gt;
* Added to the list of reserved configuration keywords (&amp;lt;tt&amp;gt;ppp.idletimeout&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ppp.peeridletimeout&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ppp.sendid&amp;lt;/tt&amp;gt;).&lt;br /&gt;
* Renamed the fields of the &amp;lt;tt&amp;gt;Sana2ExtDeviceStats&amp;lt;/tt&amp;gt; structure.&lt;br /&gt;
* Clarified that the &amp;lt;tt&amp;gt;S2QUAD&amp;lt;/tt&amp;gt; type is a big endian integer.&lt;br /&gt;
* More clarifications for the &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;S2_DISCONNECT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2_ONLINE&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;S2_OFFLINE&amp;lt;/tt&amp;gt; commands.&lt;br /&gt;
* Updated the discussion of the &amp;lt;tt&amp;gt;Sana2DeviceQuery.RawMTU&amp;lt;/tt&amp;gt; field, clarifying what is included in the the Ethernet &amp;lt;tt&amp;gt;RawMTU&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* Updated the &amp;lt;tt&amp;gt;&amp;amp;lt;devices/sana2.h&amp;amp;gt;&amp;lt;/tt&amp;gt; header file. Note that there is no equivalent &amp;lt;tt&amp;gt;&amp;amp;quot;devices/sana2.i&amp;amp;quot;&amp;lt;/tt&amp;gt; header file yet.&lt;br /&gt;
&lt;br /&gt;
Changes since 12-Nov-2001:&lt;br /&gt;
&lt;br /&gt;
* Changed the command numbers of &amp;lt;tt&amp;gt;S2_GETPEERADDRESS&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;S2_GETDNSADDRESS&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;S2_GETEXTENDEDGLOBALSTATS&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;S2_DISCONNECT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2_SAMPLE_THROUGHPUT&amp;lt;/tt&amp;gt; to be NSD-compliant. Also assigned a new number to the &amp;lt;tt&amp;gt;S2_SAMPLE_THROUGHPUT &amp;lt;/tt&amp;gt; command.&lt;br /&gt;
* Added section 4 (&amp;amp;quot;Extensions for existing commands&amp;amp;quot;).&lt;br /&gt;
* Added the last paragraph to section 9, relating to the future extension of the &amp;lt;tt&amp;gt;Sana2DeviceQuery&amp;lt;/tt&amp;gt; structure.&lt;br /&gt;
&lt;br /&gt;
Changes since 03-Nov-2001:&lt;br /&gt;
&lt;br /&gt;
* Renamed &amp;lt;tt&amp;gt;S2_GETNEWGLOBALSTATS&amp;lt;/tt&amp;gt; to &amp;lt;tt&amp;gt;S2_GETEXTENDEDGLOBALSTATS&amp;lt;/tt&amp;gt; (see [[#2.3|section 2.3]]).&lt;br /&gt;
* The &amp;lt;tt&amp;gt;S2_GETEXTENDEDGLOBALSTATS&amp;lt;/tt&amp;gt; now uses 64 bit quantities for the &amp;lt;tt&amp;gt;s2xds_PacketsReceived&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;s2xds_PacketsSent&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;s2xds_BadData&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;s2xds_Overruns&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;s2xds_UnknownTypesReceived&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;s2xds_Reconfigurations&amp;lt;/tt&amp;gt; counters.&lt;br /&gt;
* In section 2.6 the &amp;lt;tt&amp;gt;S2_SAMPLE_THROUGHPUT&amp;lt;/tt&amp;gt; command was modified to use 64 bit integers for all members of the &amp;lt;tt&amp;gt;Sana2ThroughputStats&amp;lt;/tt&amp;gt; structure.&lt;br /&gt;
* All proposed commands are now listed with their numeric IDs.&lt;br /&gt;
* The command autodocs specifically mention the &amp;lt;tt&amp;gt;ios2_BufferManagement&amp;lt;/tt&amp;gt; field.&lt;br /&gt;
* All references to &amp;lt;tt&amp;gt;ios2_Error&amp;lt;/tt&amp;gt; have been replaced with &amp;lt;tt&amp;gt;ios2_Req.io_Error&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* In section 7 the use of the &amp;lt;tt&amp;gt;IOERR_NOCMD&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;S2ERR_NOT_SUPPORTED&amp;lt;/tt&amp;gt; error codes is clarified.&lt;br /&gt;
* Section 7 takes a more detailed look at safe default values returned by the query commands.&lt;br /&gt;
* Inserted section 3 (&amp;amp;quot;Annotations for existing commands&amp;amp;quot;).&lt;br /&gt;
* The &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2_DISCONNECT&amp;lt;/tt&amp;gt; commands now specifically mention the life time of the data they have to deal with.&lt;br /&gt;
&lt;br /&gt;
Changes since 14-Oct-2001:&lt;br /&gt;
&lt;br /&gt;
* Added &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2_DISCONNECT&amp;lt;/tt&amp;gt; commands.&lt;br /&gt;
* Added &amp;lt;tt&amp;gt;S2EVENT_CONNECT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2EVENT_DISCONNECT&amp;lt;/tt&amp;gt; events.&lt;br /&gt;
* Added section 4 (&amp;amp;quot;New wire error codes&amp;amp;quot;).&lt;br /&gt;
* In section 5.2 the originally proposed log callback function has been wrapped into a standard Hook structure.&lt;br /&gt;
* Removed item on &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;S2_DISCONNECT&amp;lt;/tt&amp;gt; from section 7 (&amp;amp;quot;Unsolved problems&amp;amp;quot;).&lt;br /&gt;
* Added section 8 (&amp;amp;quot;Changes&amp;amp;quot;).&lt;br /&gt;
&lt;br /&gt;
== Revision 5 ==&lt;br /&gt;
&lt;br /&gt;
22-Mar-2004:&lt;br /&gt;
&lt;br /&gt;
* Conversion to HTML&lt;br /&gt;
&lt;br /&gt;
21-Jan-2004:&lt;br /&gt;
&lt;br /&gt;
* Added clarifications for &amp;lt;tt&amp;gt;schm_MsgSize&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;slhm_MsgSize&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;slhm_Priority&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;slhm_Name&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;slhm_Message&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;s2h_Hook&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* Updated the &amp;lt;tt&amp;gt;S2_SANA2HOOK&amp;lt;/tt&amp;gt; documentation.&lt;br /&gt;
* Shortened section 4.&lt;br /&gt;
* Updated section 5.&lt;br /&gt;
&lt;br /&gt;
30-Nov-2003:&lt;br /&gt;
&lt;br /&gt;
* Extended the applicability of the &amp;lt;tt&amp;gt;Hook&amp;lt;/tt&amp;gt; to logging.&lt;br /&gt;
* Renamed &amp;lt;tt&amp;gt;S2_COPYHOOK&amp;lt;/tt&amp;gt; to &amp;lt;tt&amp;gt;S2_SANA2HOOK&amp;lt;/tt&amp;gt;, which matches the extended scope it should cover.&lt;br /&gt;
* The message passed to the &amp;lt;tt&amp;gt;Hook&amp;lt;/tt&amp;gt; now includes a size field which holds the size of the message, expressed in bytes.&lt;br /&gt;
&lt;br /&gt;
06-Oct-2003:&lt;br /&gt;
&lt;br /&gt;
* Replaced the list of new tag items with a single &amp;lt;tt&amp;gt;Hook&amp;lt;/tt&amp;gt;, which is installed through a new command.&lt;br /&gt;
* Added &amp;amp;quot;Caveats&amp;amp;quot; and &amp;amp;quot;Changes&amp;amp;quot; sections&lt;br /&gt;
* Removed the documentation for the originally proposed &amp;lt;tt&amp;gt;TagItem&amp;lt;/tt&amp;gt; (sections 3.2.1 through 3.2.10)&lt;br /&gt;
&lt;br /&gt;
= History =&lt;br /&gt;
&lt;br /&gt;
== Revision 2 and 3 ==&lt;br /&gt;
&lt;br /&gt;
This standard has undergone several drafts with long periods for comment from developers and the Amiga community at large. These drafts include a UseNet release which was also distributed on the Fish Disks in June, 1991 (as well as published in the &#039;91 DevCon notes), and the November 7 Draft for Final Comment and Approval distributed via Bix, ADSP and UseNet. There were also several intermediate drafts with more limited distribution.&lt;br /&gt;
&lt;br /&gt;
== Revision 4 ==&lt;br /&gt;
&lt;br /&gt;
(Olaf Barthel)&lt;br /&gt;
&lt;br /&gt;
I&#039;ve been working on a TCP/IP stack and PPP drivers to go with them for a while and found that there were some things that SANA-II did specifically not address, and which ought to be covered by it. In other areas clarification was needed. Also, discussions I had with Harald Frank suggested that the extensions made by Heinz Wrobel and Stefan Sticht in the SANA-IIR3 specification could need extending.&lt;/div&gt;</summary>
		<author><name>Costel Mincea</name></author>
	</entry>
	<entry>
		<id>https://wiki.amigaos.net/w/index.php?title=SANA-II_Revision_7&amp;diff=12592</id>
		<title>SANA-II Revision 7</title>
		<link rel="alternate" type="text/html" href="https://wiki.amigaos.net/w/index.php?title=SANA-II_Revision_7&amp;diff=12592"/>
		<updated>2026-09-02T11:08:47Z</updated>

		<summary type="html">&lt;p&gt;Costel Mincea: /* S2_DEVICEQUERY */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{WIP}}&lt;br /&gt;
= SANA-II Network Device Driver Specification =&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;SANA-II Network Device Driver Specification&amp;quot; is a standard for an Amiga software interface between networking hardware and network protocol stacks (or for software tools such as network monitors). A network protocol stack is a layer of software that network applications use to address particular processes on remote machines and to send data reliably in spite of hardware errors. There are several common network protocol stacks including &#039;&#039;TCP/IP&#039;&#039;, &#039;&#039;OSI&#039;&#039;, &#039;&#039;AppleTalk&#039;&#039;, &#039;&#039;DECNet&#039;&#039; and &#039;&#039;Novell&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
SANA-II device drivers are intended to allow multiple network protocol stacks running on the same machine to share one network device. For example, the TCP/IP and AppleTalk protocol stacks could both run on the same machine over one ethernet board. The device drivers are also intended to allow network protocol stacks to be written in a hardware-independent fashion so that a different version of each protocol stack doesn&#039;t have to be written for each networking hardware device.&lt;br /&gt;
&lt;br /&gt;
The standard does not address the writing of network applications. Application writers must not use SANA-II Device Drivers directly. Network applications must use the API provided by the network protocol software the application supports. The Amiga standard network API for TCP/IP is provided via the bsdsocket.library which is a part of Roadshow.&lt;br /&gt;
&lt;br /&gt;
To write a SANA-II device driver, you will need to be familiar with the specification documents for the hardware you are writing to and with the &amp;quot;SANA-II Network Device Driver Specification&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
To write a network protocol stack which will use SANA-II device drivers, you should have general familiarity with common network hardware and must be very familiar with the &amp;quot;SANA-II Network Device Driver Specification&amp;quot; as well as the specification for the protocol you are developing. If you are creating a new protocol, you must obtain a protocol type number for any hardware on which your protocol will be used.&lt;br /&gt;
&lt;br /&gt;
This version of the specification is final. Any new version of the standard (i.e., to add new features) is planned to be backward compatible. No SANA-II device driver or software utilizing those drivers should be written to any earlier version of the specification.&lt;br /&gt;
&lt;br /&gt;
Distribution of this version of the standard is unlimited. Anyone may write Amiga software which implements a SANA-II network device driver or which calls a SANA-II network device driver without restriction and may freely distribute such software that they have written.&lt;br /&gt;
&lt;br /&gt;
It is important to try to test each SANA-II device driver against all software which uses SANA-II devices. Available example programs are valuable in initial testing. The Amiga Networking Group is interested in receiving evaluation and/or beta test copies of all Amiga networking hardware, SANA-II device drivers and software which uses SANA-II devices. However, we make no assurances regarding any testing which we may or may not perform with such evaluation copies.&lt;br /&gt;
&lt;br /&gt;
The SANA-II standard caters to both Motorola 68000 platforms and PowerPC platforms.&lt;br /&gt;
&lt;br /&gt;
Please feel free to comment. You can contact the AmigaOS development team through the [http://www.amigaos.net/contact AmigaOS contact form].&lt;br /&gt;
&lt;br /&gt;
= Driver Form =&lt;br /&gt;
&lt;br /&gt;
SANA-II device drivers are Amiga Exec device drivers. They use an extended IORequest structure and a number of extended commands for tallying network statistics, sending broadcasts and multicasts, network addressing and the handling of unexpected packets. The SDK includes information on how to construct an Exec device.&lt;br /&gt;
&lt;br /&gt;
= Opening a SANA-II Device =&lt;br /&gt;
&lt;br /&gt;
As when opening any other Exec device, on the call to OpenDevice() a SANA-II device receives an IORequest structure which the device initializes for the opener&#039;s use. The opener must copy this structure if it desires to use multiple asynchronous requests. The SANA-II IORequest is defined as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct IOSana2Req&lt;br /&gt;
{&lt;br /&gt;
  struct IORequest ios2_Req;&lt;br /&gt;
  ULONG ios2_WireError;&lt;br /&gt;
  ULONG ios2_PacketType;&lt;br /&gt;
  UBYTE ios2_SrcAddr[SANA2_MAX_ADDR_BYTES];&lt;br /&gt;
  UBYTE ios2_DstAddr[SANA2_MAX_ADDR_BYTES];&lt;br /&gt;
  ULONG ios2_DataLength;&lt;br /&gt;
  APTR ios2_Data;&lt;br /&gt;
  APTR ios2_StatData;&lt;br /&gt;
  APTR ios2_BufferManagement;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; ios2_Req&lt;br /&gt;
: A standard Exec device IORequest.&lt;br /&gt;
; ios2_WireError&lt;br /&gt;
: A more specific device code which may be set when there is an io_Error. See &amp;amp;lt;devices/sana2.h&amp;amp;gt; for the defined WireErrors.&lt;br /&gt;
; ios2_PacketType&lt;br /&gt;
: The type of packet requested. See the section on &amp;quot;Packet Types&amp;quot;.&lt;br /&gt;
; ios2_SrcAddr&lt;br /&gt;
: The device fills in this field with the interface (network hardware) address of the source of the packet that satisfied a read command. The bytes used to hold the address will be left justified but the bit layout is dependent on the particular type of network.&lt;br /&gt;
; ios2_DstAddr&lt;br /&gt;
: Before the device user sends a packet, it fills this with the interface destination address of the packet. On receives, the device fills this with the interface destination address. Other commands may use this field differently (see the &amp;quot;SANA-II network device driver Autodocs&amp;quot; in the SDK). The bytes used to hold the address will be left justified but the bit layout is dependent on the particular type of network.&lt;br /&gt;
; ios2_DataLength&lt;br /&gt;
: The device user initializes this field with the amount of data available in the Data buffer before passing the IOSana2Req to the device. The device fills in this field with the size of the packet data as it was sent on the wire. This does not include the header and trailer information. Depending on the network type and protocol type, the driver may have to calculate this value. This is generally used only for reads and writes (including broadcast and multicast).&lt;br /&gt;
; ios2_Data&lt;br /&gt;
: A pointer to some abstract data structure containing packet data. &#039;&#039;Drivers may not directly manipulate or examine anything pointed to by Data!&#039;&#039; This is generally used only for reads and writes (including broadcast and multicast).&lt;br /&gt;
&lt;br /&gt;
; ios2_StatData&lt;br /&gt;
: Pointer to a structure in which to place a snapshot of device statistics. The data area must be long word aligned. This is only used on calls to the statistics commands.&lt;br /&gt;
&lt;br /&gt;
; ios2_BufferManagement&lt;br /&gt;
: The opener places a pointer to a tag list in this field before calling OpenDevice(). Functions pointed to in the tag list are called by the device when processing IORequests from the opener. When returned from OpenDevice(), this field contains a pointer to driver-private information used to access these functions. See &amp;quot;Buffer Management&amp;quot; below for more details.&lt;br /&gt;
&lt;br /&gt;
: Note that the &amp;lt;tt&amp;gt;ios2_BufferManagement&amp;lt;/tt&amp;gt; field provided by the driver on &amp;lt;tt&amp;gt;OpenDevice()&amp;lt;/tt&amp;gt; time in conjunction with &amp;lt;tt&amp;gt;io_Device&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;io_Unit&amp;lt;/tt&amp;gt; is the unique identifier for all requests coming from this protocol stack until &amp;lt;tt&amp;gt;CloseDevice()&amp;lt;/tt&amp;gt;. The driver must not ever change the &amp;lt;tt&amp;gt;ios2_BufferManagement&amp;lt;/tt&amp;gt; field for a protocol stack at run time, even if &amp;lt;tt&amp;gt;S2_SANAHOOK&amp;lt;/tt&amp;gt; is called to request extended features.&lt;br /&gt;
&lt;br /&gt;
The flags used with the device on OpenDevice() are (SANA2OPB_xxx):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Name&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| SANA2OPB_MINE&lt;br /&gt;
| Exclusive access to the unit requested.&lt;br /&gt;
|-&lt;br /&gt;
| SANA2OPB_PROM&lt;br /&gt;
| Promiscuous mode requested. Hardware which supports promiscuous mode allows all packets sent over the wire to be captured whether or not they are addressed to this node.&amp;lt;/br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;Note:&#039;&#039;&#039; Promiscuous mode requires exclusive opening of the device.&#039;&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The flags used during I/O requests are (SANA2IOB_xxx):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Name&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| SANA2IOB_RAW&lt;br /&gt;
| Raw packet read/write requested. Raw packets should include the entire data-link layer packet. Devices with the same hardware device number should have the same raw packet format.&lt;br /&gt;
|-&lt;br /&gt;
| SANA2IOB_BCAST&lt;br /&gt;
| Broadcast packet (received).&lt;br /&gt;
|-&lt;br /&gt;
| SANA2IOB_MCAST&lt;br /&gt;
| Multicast packet (received).&lt;br /&gt;
|-&lt;br /&gt;
| SANA2IOB_QUICK&lt;br /&gt;
| Quick IO requested.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Buffer Management =&lt;br /&gt;
&lt;br /&gt;
Unlike most other Exec Device drivers, SANA-II drivers have no internal buffers. Instead, they read/write to/from an abstract data structure allocated by the driver user. The driver accesses these buffers only via functions that the driver user provides to the driver. The driver user must provide two functions: one copies data to the abstract data structure and one copies data from the abstract data structure. The driver user can therefore choose the data structure used for buffer management by both the driver and driver user in order to have efficient memory and CPU usage overall.&lt;br /&gt;
&lt;br /&gt;
The IOSana2Req contains a pointer to data and the length of said data. A driver is not allowed to make assumptions about how the data is stored. The driver cannot directly manipulate or examine the buffer in any manner. The driver can only access the buffer by calling the functions provided by the driver user.&lt;br /&gt;
&lt;br /&gt;
Before calling OpenDevice(), the driver user points ios2_BufferManagement to a list of tags (defined in &amp;amp;lt;devices/sana2.h&amp;amp;gt;) which include pointers to the buffer management functions required by the driver (defined below). The driver will fail to open if the driver user does not supply all of the required functions. If the device opens successfully, the driver sets ios2_BufferManagement to a value which this opener must use in all future calls to the driver. This &amp;quot;magic cookie&amp;quot; is used from then on to access these functions (a &amp;quot;magic cookie&amp;quot; is a value which one software entity passes to another but which is only meaningful to one of the software entities). The driver user may not use the &amp;quot;magic cookie&amp;quot; in any way--it is for the driver to do with as it wishes. The driver could in theory choose to just copy the tag list to driver-owned memory and then parse the list for every IORequest, but it is much more efficient for the driver to create some sort of table of functions and to point ios2_BufferManagement to that table.&lt;br /&gt;
&lt;br /&gt;
Another recommendation for the ``magic cookie`` is to use it to maintain a separate packet read queue for each device opener. This would allow multiple protocol stacks that all wish to receive the same packet type to work together without having to &amp;quot;know&amp;quot; about each other as &#039;&#039;Envoy&#039;&#039; and &#039;&#039;AS225&#039;&#039; do right now. What does multiple protocol stack support mean? Basically this means that each opener gets all the packets necessary. If a packet comes in that fills a request for more than one opener of the device, all of them will get a copy of the packet. This feature should never be left out of a device design. If it is missing, the usefulness of the device is severely limited.&lt;br /&gt;
&lt;br /&gt;
In order to help system load, a packet filter callback allows protocol stacks to reject packets that are known to not be useful. &#039;&#039;Envoy&#039;&#039;&#039;s nipc.library (for example) could be modified to reject TCP packets (as it never uses them).&lt;br /&gt;
&lt;br /&gt;
The specification currently defines the following tags for the OpenDevice() ios2_BufferManagement tag list:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Copy data from network interface to protocol stack buffer&lt;br /&gt;
! Tag&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| S2_CopyToBuff (mandatory)&lt;br /&gt;
| This is a pointer to a function which conforms to the CopyToBuff Autodoc.&lt;br /&gt;
|-&lt;br /&gt;
| S2_CopyToBuff16 (optional)&lt;br /&gt;
| Copy to a 16 bit aligned buffer using 16 bit data words.&lt;br /&gt;
|-&lt;br /&gt;
| S2_CopyToBuff32 (optional)&lt;br /&gt;
| Copy to a 32 bit aligned buffer using 32 bit data words.&lt;br /&gt;
|-&lt;br /&gt;
| S2_DMACopyToBuff32 (optional)&lt;br /&gt;
| Perform a DMA copy to a 32 bit aligned contiguous buffer using 32 bit data words.&lt;br /&gt;
|-&lt;br /&gt;
| S2_DMACopyToBuff64 (optional)&lt;br /&gt;
| Perform a DMA copy to a 64 bit aligned contiguous buffer using 64 bit data words.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Copy data from protocol stack buffer to network interface&lt;br /&gt;
! Tag&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| S2_CopyFromBuff (mandatory)&lt;br /&gt;
| This is a pointer to a function which conforms to the CopyFromBuff Autodoc.&lt;br /&gt;
|-&lt;br /&gt;
| S2_CopyFromBuff16 (optional)&lt;br /&gt;
| Copy from a 16 bit aligned buffer using 16 bit data words.&lt;br /&gt;
|-&lt;br /&gt;
| S2_CopyFromBuff32 (optional)&lt;br /&gt;
| Copy from a 32 bit aligned buffer using 32 bit data words.&lt;br /&gt;
|-&lt;br /&gt;
| S2_DMACopyFromBuff32 (optional)&lt;br /&gt;
| Perform a DMA copy from a 32 bit aligned contiguous buffer using 32 bit data words.&lt;br /&gt;
|-&lt;br /&gt;
| S2_DMACopyFromBuff64 (optional)&lt;br /&gt;
| Perform a DMA copy from a 64 bit aligned contiguous buffer using 64 bit data words.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Filter data before protocol stack buffer&lt;br /&gt;
! Tag&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| S2_PacketFilter (optional)&lt;br /&gt;
| This is a pointer to a standard Hook to be called before S2_CopyToBuff is done. See the PacketFilter Autodoc for more information.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Logging messages from the driver&lt;br /&gt;
! Tag&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| S2_Log (optional)&lt;br /&gt;
| This is a pointer to a standard Hook to be called when the driver logs events.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Better buffer management ==&lt;br /&gt;
&lt;br /&gt;
The mandatory buffer management callbacks may not be very efficient for certain types of hardware. They also do not allow driver DMA access.&lt;br /&gt;
&lt;br /&gt;
All the new features are completely optional and do not collide with existing features. They may be used only when the protocol stack asks for them on opening a driver.&lt;br /&gt;
&lt;br /&gt;
The enhancements consist of several new tags that may be specified by a protocol stack on OpenDevice() to offer certain data transfer options. It is up to the device driver to chose which callbacks to use at what time. These tags are advisory only and may be ignored by the driver for any data buffer at any time:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| S2_CopyToBuff16&lt;br /&gt;
|-&lt;br /&gt;
| S2_CopyFromBuff16&lt;br /&gt;
|-&lt;br /&gt;
| S2_CopyToBuff32&lt;br /&gt;
|-&lt;br /&gt;
| S2_CopyFromBuff32&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
These are optional callbacks presented to the device with the same calling interface as for S2_CopyToBuff or S2_CopyFromBuff, respectively. The difference to the original callbacks is the required and guaranteed transfer size and alignment for accessing the device&#039;s buffer for a single piece of a data of either 16 or 32 bits, a data word. The copy function called may only use 16/32 bit aligned read/write commands of 16/32 bits at once to transfer the data words, respectively. If the buffer data length is not a multiple of the required data word transfer size, the last data word transfer may contain garbage padding in either transfer direction.&lt;br /&gt;
&lt;br /&gt;
The following tags have been added to support direct writes into hardware buffers that do not allow arbitrarily sized or aligned accesses:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| S2_DMACopyToBuff32&lt;br /&gt;
|-&lt;br /&gt;
| S2_DMACopyFromBuff32&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If the protocol stack wants to optionally enhance data transfer efficiency with DMA supporting devices, it may pass any of these optional tags to the device on OpenDevice().&lt;br /&gt;
&lt;br /&gt;
If the device driver supports DMA, it may call the respective callback with the abstract magic cookie ios2_Data in register A0. The callback may return NULL in D0. In this case, the driver may not use DMA for this buffer. Alternatively, the callback may return the address of the actual data buffer in D0, if it has these characteristics:&lt;br /&gt;
&lt;br /&gt;
* The buffer is in contiguous memory. Depending on the intended data direction, it shall be readable or writable.&lt;br /&gt;
* The buffer is aligned on a 32 bit boundary.&lt;br /&gt;
* The buffer size shall be a multiple of 32 bit and it is at least = ios2_DataLength.&lt;br /&gt;
* It is up to the driver to decide if it can use DMA for this buffer and it shall fall back to the standard CPU callbacks if necessary. The data transfer method actually used by the driver will not be known in advance by the protocol stack.&lt;br /&gt;
&lt;br /&gt;
The following tags have been added to allow for 64 bit aligned PCI DMA accesses to take place:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| S2_DMACopyToBuff64&lt;br /&gt;
|-&lt;br /&gt;
| S2_DMACopyFromBuff64&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
These two callbacks are identical in operation to the &amp;lt;tt&amp;gt;S2_DMACopyToBuff32&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2_DMACopyFromBuff32&amp;lt;/tt&amp;gt; callbacks. The difference is in that the memory region DMA is to take place in must be aligned to a 64 bit boundary and must be large enough to hold data that is a multiple of 64 bits in size.&lt;br /&gt;
&lt;br /&gt;
== Best buffer management ==&lt;br /&gt;
&lt;br /&gt;
The SANA-II driver interface is intended to transform data between the hardware layer and the link layer, to be used by networking software such as TCP/IP stacks. This transformation is performed by callback functions which are supplied by the networking software at the time the device driver is opened. The device driver then invokes these functions later in order to transfer data received and data to be sent.&lt;br /&gt;
&lt;br /&gt;
The function parameters used by these callbacks are passed in 68000 registers for the lowest overhead. The problem with 68000 register parameters is that on the PowerPC platform, this form of parameter passing may require the use of emulation code. This is costly and may incur a severe performance penalty. It is an even greater problem if PowerPC native networking software is calling PowerPC native networking driver software and the other way round. In both cases the runtime environment will have to enter emulation mode, return to to PowerPC native execution, dip into emulation mode and return to native PowerPC execution. It would be much better if the chain of execution would stay in PowerPC mode all the time.&lt;br /&gt;
&lt;br /&gt;
Alternatively, if a hook function is used, the operating system may be able to decide whether the function to be invoked needs emulating or called directly. The &amp;lt;tt&amp;gt;Hook&amp;lt;/tt&amp;gt; effectively works as an abstraction which makes the function invocation platform independent.&lt;br /&gt;
&lt;br /&gt;
The following standard wraps the copying and logging functions into the standardized &amp;lt;tt&amp;gt;Hook&amp;lt;/tt&amp;gt; interface.&lt;br /&gt;
&lt;br /&gt;
==== The hook function ====&lt;br /&gt;
&lt;br /&gt;
The hook function itself is invoked with the following parameters:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
   result = hook_function(hook, sana2req, sana2hookmsg)&lt;br /&gt;
&lt;br /&gt;
   ULONG hook_function(struct Hook *hook,&lt;br /&gt;
                       struct IOSana2Req *sana2req,&lt;br /&gt;
                       struct SANA2HookMsg *sana2hookmsg);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the result is not necessarily of type &amp;lt;tt&amp;gt;ULONG&amp;lt;/tt&amp;gt;. It is a 32 bit value, which can be a boolean result code (for &amp;lt;tt&amp;gt;CopyFromBuff&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;CopyToBuff&amp;lt;/tt&amp;gt; and their like) or a pointer to a memory address (for &amp;lt;tt&amp;gt;DMACopyToBuff&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DMACopyFromBuff&amp;lt;/tt&amp;gt; and their like).&lt;br /&gt;
&lt;br /&gt;
=== Data structures ===&lt;br /&gt;
&lt;br /&gt;
The following hook messages are to be used:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct SANA2HookMsg&lt;br /&gt;
{&lt;br /&gt;
  ULONG shm_Method;&lt;br /&gt;
  ULONG shm_MsgSize;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this data structure the &amp;lt;tt&amp;gt;shm_Method&amp;lt;/tt&amp;gt; field would indicate the task to be performed. This can be a request to copy data or to store a log message. The &amp;lt;tt&amp;gt;shm_MsgSize&amp;lt;/tt&amp;gt; field tells you how large the data structure is for future enhancements which may cause the data structure to grow.&lt;br /&gt;
&lt;br /&gt;
==== Copying operations ====&lt;br /&gt;
&lt;br /&gt;
For copying operations the message is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct SANA2CopyHookMsg&lt;br /&gt;
{&lt;br /&gt;
  ULONG schm_Method;&lt;br /&gt;
  ULONG schm_MsgSize;&lt;br /&gt;
&lt;br /&gt;
  APTR  schm_To;&lt;br /&gt;
  APTR  schm_From;&lt;br /&gt;
  ULONG schm_Size;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The structure members are as follows:&lt;br /&gt;
&lt;br /&gt;
; schm_Method&lt;br /&gt;
: This must be one &amp;lt;tt&amp;gt;S2_CopyToBuff&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;S2_CopyFromBuff&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;S2_CopyToBuff16&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;S2_CopyFromBuff16&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;S2_CopyToBuff32&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;S2_CopyFromBuff32&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;S2_DMACopyToBuff32&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;S2_DMACopyFromBuff32&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;S2_DMACopyToBuff64&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;S2_DMACopyFromBuff64&amp;lt;/tt&amp;gt; to identify the function to be performed.&lt;br /&gt;
&lt;br /&gt;
; schm_MsgSize&lt;br /&gt;
: Size of this message data structure in bytes. This must be &amp;amp;gt;= 20 for this message type.&lt;br /&gt;
: The driver shall set &amp;lt;tt&amp;gt;schm_MsgSize&amp;lt;/tt&amp;gt; always correctly to be compliant. The protocol stack shall use this field to validate the message and to reject/ignore bad messages via a &amp;lt;tt&amp;gt;FALSE&amp;lt;/tt&amp;gt; hook function return value. For DMA related hooks, a &amp;lt;tt&amp;gt;FALSE&amp;lt;/tt&amp;gt; return value is equivalent to a &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; pointer.&lt;br /&gt;
&lt;br /&gt;
; schm_To&lt;br /&gt;
: Equivalent to the &amp;lt;tt&amp;gt;to&amp;lt;/tt&amp;gt; parameter of the &amp;lt;tt&amp;gt;CopyFromBuff&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;CopyToBuff&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;DMACopyToBuff&amp;lt;/tt&amp;gt; functions.&lt;br /&gt;
&lt;br /&gt;
; schm_From&lt;br /&gt;
: Equivalent to the &amp;lt;tt&amp;gt;from&amp;lt;/tt&amp;gt; parameter of the &amp;lt;tt&amp;gt;CopyFromBuff&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;CopyToBuff&amp;lt;/tt&amp;gt; functions.&lt;br /&gt;
&lt;br /&gt;
; schm_Size&lt;br /&gt;
: Equivalent to the &amp;lt;tt&amp;gt;n&amp;lt;/tt&amp;gt; parameter of the &amp;lt;tt&amp;gt;CopyFromBuff&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;CopyToBuff&amp;lt;/tt&amp;gt;, functions.&lt;br /&gt;
&lt;br /&gt;
==== Logging operations ====&lt;br /&gt;
&lt;br /&gt;
For logging operations the message is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct SANA2LogHookMsg&lt;br /&gt;
{&lt;br /&gt;
  ULONG  slhm_Method;&lt;br /&gt;
  ULONG  slhm_MsgSize;&lt;br /&gt;
&lt;br /&gt;
  ULONG  slhm_Priority;&lt;br /&gt;
  STRPTR slhm_Name;&lt;br /&gt;
  STRPTR slhm_Message;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The structure members would be used as follows:&lt;br /&gt;
&lt;br /&gt;
; slhm_Method&lt;br /&gt;
: This must be &amp;lt;tt&amp;gt;S2_Log&amp;lt;/tt&amp;gt;, as defined in the SANA-IIR4 specification.&lt;br /&gt;
&lt;br /&gt;
; slhm_MsgSize&lt;br /&gt;
: Size of this message data structure in bytes. This must be &amp;amp;gt;= 20 for this message type.&lt;br /&gt;
: The driver shall set &amp;lt;tt&amp;gt;slhm_MsgSize&amp;lt;/tt&amp;gt; always correctly to be compliant. The protocol stack shall use this field to validate the message and to reject/ignore bad messages via a &amp;lt;tt&amp;gt;FALSE&amp;lt;/tt&amp;gt; hook function return value. For DMA related hooks, a &amp;lt;tt&amp;gt;FALSE&amp;lt;/tt&amp;gt; return value is equivalent to a &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; pointer.&lt;br /&gt;
&lt;br /&gt;
; slhm_Priority&lt;br /&gt;
: The smaller this value, the more important the message to be logged or displayed. The following priority levels are defined (similar to the Unix syslog() mechanism):&lt;br /&gt;
:{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| S2LOG_Emergency || A panic condition.&lt;br /&gt;
|-&lt;br /&gt;
| S2LOG_Alert || A condition that should be corrected immediately.&lt;br /&gt;
|-&lt;br /&gt;
| S2LOG_Critical || Critical conditions.&lt;br /&gt;
|-&lt;br /&gt;
| S2LOG_Error || A plain error.&lt;br /&gt;
|-&lt;br /&gt;
| S2LOG_Warning || A warning message.&lt;br /&gt;
|-&lt;br /&gt;
| S2LOG_Notice || Conditions that are not error conditions, but should possibly be handled specially.&lt;br /&gt;
|-&lt;br /&gt;
| S2LOG_Information || An informational message.&lt;br /&gt;
|-&lt;br /&gt;
| S2LOG_Debug || Messages that contain information normally of use only when debugging.&lt;br /&gt;
|}&lt;br /&gt;
: Only these priority values may be used by a driver. It is suggested that a driver is configurable to generate different types of messages or not, e.g., a driver may be configured to only emit &amp;lt;tt&amp;gt;S2LOG_Emergency&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2LOG_Debug&amp;lt;/tt&amp;gt; messages&lt;br /&gt;
&lt;br /&gt;
; slhm_Name&lt;br /&gt;
: Pointer to a &amp;lt;tt&amp;gt;NUL&amp;lt;/tt&amp;gt;-terminated string which identifies the source of this message. This can be &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; in which case the OS device name of the driver shall be used by the protocol stack.&lt;br /&gt;
&lt;br /&gt;
; slhm_Message&lt;br /&gt;
: Pointer to a &amp;lt;tt&amp;gt;NUL&amp;lt;/tt&amp;gt;-terminated string which contains the log message. The text should not contain any formatting characters such as line feeds or carriage returns. The &amp;lt;tt&amp;gt;slhm_Message&amp;lt;/tt&amp;gt; member must never be &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt;.&lt;br /&gt;
: All message texts shall preferably be formatted in the current user&#039;s locale. If that is not possible, the english language shall be used. &amp;lt;tt&amp;gt;slhm_Name&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;slhm_Message&amp;lt;/tt&amp;gt; shall only contain printable characters.&lt;br /&gt;
&lt;br /&gt;
=== Application and driver software use of the new functions ===&lt;br /&gt;
&lt;br /&gt;
Since plenty of software exists which uses the &#039;traditional&#039; &amp;lt;tt&amp;gt;TagItem&amp;lt;/tt&amp;gt; list provided at &amp;lt;tt&amp;gt;OpenDevice()&amp;lt;/tt&amp;gt; time, drivers must always examine these parameters and not expect a &amp;lt;tt&amp;gt;S2_SANA2HOOK&amp;lt;/tt&amp;gt; command to be sent later.&lt;br /&gt;
&lt;br /&gt;
If the new &amp;lt;tt&amp;gt;Hook&amp;lt;/tt&amp;gt;-based callback functions are used then the driver must invoke the Hooks via &amp;lt;tt&amp;gt;utility.library/CallHookPkt&amp;lt;/tt&amp;gt;. It must never invoke the hook functions through local assembly language stubs or the &amp;lt;tt&amp;gt;amiga.lib/CallHook&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;amiga.lib/CallHookA&amp;lt;/tt&amp;gt; functions.&lt;br /&gt;
&lt;br /&gt;
=== Caveats ===&lt;br /&gt;
&lt;br /&gt;
The functionality above suggests that one could do entirely without the &amp;lt;tt&amp;gt;TagItem&amp;lt;/tt&amp;gt; list passed in at &amp;lt;tt&amp;gt;OpenDevice()&amp;lt;/tt&amp;gt; time. However, at this time it is hard to tell how existing driver software will react to empty &amp;lt;tt&amp;gt;TagItem&amp;lt;/tt&amp;gt; lists or even a NULL pointer in the &amp;lt;tt&amp;gt;IOSana2Req-&amp;amp;gt;ios2_BufferManagement&amp;lt;/tt&amp;gt; field. It is therefore important to always provide for a &amp;lt;tt&amp;gt;TagItem&amp;lt;/tt&amp;gt; list which includes proper (i.e. they must point to working functions and may not be &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt;) function pointers for the &amp;lt;tt&amp;gt;S2_CopyToBuff&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2_CopyFromBuff&amp;lt;/tt&amp;gt; tags. Once the device has been opened successfully, the next step is to try and install the copy &amp;lt;tt&amp;gt;Hook&amp;lt;/tt&amp;gt; through the proposed &amp;lt;tt&amp;gt;S2_SANA2HOOK&amp;lt;/tt&amp;gt; command. If the command fails, the application can still expect that the &amp;lt;tt&amp;gt;S2_CopyToBuff&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2_CopyFromBuff&amp;lt;/tt&amp;gt; tags supplied at &amp;lt;tt&amp;gt;OpenDevice()&amp;lt;/tt&amp;gt; time will work.&lt;br /&gt;
&lt;br /&gt;
== Packet filtering ==&lt;br /&gt;
&lt;br /&gt;
With the original &amp;quot;SANA-II Network Device Driver Specification&amp;quot;, a protocol stack could open a device and ask for certain packet types. It got all the packets that matched this type. As it turned out, this could be mighty inefficient if there were packets that the protocol stack did not use at all. These would go into read processing of the protocol stack and waste CPU time even though they could have been easily identified on arrival.&lt;br /&gt;
&lt;br /&gt;
== Driver event logging ==&lt;br /&gt;
&lt;br /&gt;
A driver may want to report an important event for the user to see. Adding a log message to a file or opening a window to display a message in may not be the optimum approach as the user may be unaware of the context into which the message belongs. It may be advisable for the driver to use the message reporting and logging facilities used by the client software that uses its services, such as a TCP/IP stack. The &amp;lt;tt&amp;gt;S2_Log&amp;lt;/tt&amp;gt; callback hook is intended to provide for such a link.&lt;br /&gt;
&lt;br /&gt;
If present, the driver must use this callback hook rather than whatever logging methods it implements itself. Note that unlike the other SANA-II callbacks, this is a regular hook, as to be invoked using &amp;lt;tt&amp;gt;utility.library&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;CallHookPkt()&amp;lt;/tt&amp;gt;. The hook function is invoked using the following parameters:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
log_hook_function(hook, reserved, message)&lt;br /&gt;
&lt;br /&gt;
void log_hook_function(struct hook * hook,APTR reserved,&lt;br /&gt;
                       struct S2LogMessage * message);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;reserved&amp;lt;/tt&amp;gt; parameter &#039;&#039;&#039;must&#039;&#039;&#039; be set to &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt;. The &amp;lt;tt&amp;gt;S2LogMessage&amp;lt;/tt&amp;gt; structure passed as the third parameter looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct S2LogMessage&lt;br /&gt;
{&lt;br /&gt;
   LONG   s2lm_Size;&lt;br /&gt;
   ULONG  s2lm_Priority;&lt;br /&gt;
   STRPTR s2lm_Name;&lt;br /&gt;
   STRPTR s2lm_Message;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The individual structure members serve the following functions:&lt;br /&gt;
&lt;br /&gt;
; s2lm_Size&lt;br /&gt;
: Size of the &amp;lt;tt&amp;gt;S2LogMessage&amp;lt;/tt&amp;gt; structure, in bytes. The idea is to extend this data structure in the future, and the size stored in here tells you how long the structure is. The size &#039;&#039;&#039;must&#039;&#039;&#039; always be &amp;amp;gt;= 16.&lt;br /&gt;
&lt;br /&gt;
;s2lm_Priority&lt;br /&gt;
: The smaller this value, the more important the message to be logged or displayed. The following priority levels are defined (similar to the Unix &amp;lt;tt&amp;gt;syslog()&amp;lt;/tt&amp;gt; mechanism):&lt;br /&gt;
:{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| S2LOG_Emergency || A panic condition.&lt;br /&gt;
|-&lt;br /&gt;
| S2LOG_Alert || A condition that should be corrected immediately.&lt;br /&gt;
|-&lt;br /&gt;
| S2LOG_Critical || Critical conditions.&lt;br /&gt;
|-&lt;br /&gt;
| S2LOG_Error || A plain error.&lt;br /&gt;
|-&lt;br /&gt;
| S2LOG_Warning || A warning message.&lt;br /&gt;
|-&lt;br /&gt;
| S2LOG_Notice || Conditions that are not error conditions, but should possibly be handled specially.&lt;br /&gt;
|-&lt;br /&gt;
| S2LOG_Information || An informational message.&lt;br /&gt;
|-&lt;br /&gt;
| S2LOG_Debug || Messages that contain information normally of use only when debugging.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
; s2lm_Name&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Pointer to a &amp;lt;tt&amp;gt;NUL&amp;lt;/tt&amp;gt;-terminated string which identifies the source of this message. This can be &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; in which case the name is treated as being unknown.&lt;br /&gt;
&lt;br /&gt;
; s2lm_Message&lt;br /&gt;
: Pointer to a &amp;lt;tt&amp;gt;NUL&amp;lt;/tt&amp;gt;-terminated string which contains the log message. The text should not contain any formatting characters such as line feeds or carriage returns. The &amp;lt;tt&amp;gt;s2lm_Message&amp;lt;/tt&amp;gt; member &#039;&#039;&#039;must never&#039;&#039;&#039; be &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
All error messages issued by the device driver should use the current system locale wherever this is possible. The purpose of an error message is, after all, to assist the user in recovering from the error. Which may be difficult if the user does not even know the language in which the message is written.&lt;br /&gt;
&lt;br /&gt;
The log message string is valid until the log hook function returns. If the driver needs to retain the message any longer, it must make a copy of it.&lt;br /&gt;
&lt;br /&gt;
Since the client software into which the log hook calls may have to allocate memory to hold and display the log message, the log hook &#039;&#039;&#039;must not&#039;&#039;&#039; be called from interrupt code. The log hook shall not &amp;lt;tt&amp;gt;Wait()&amp;lt;/tt&amp;gt; and it shall assume only a &amp;lt;tt&amp;gt;Task&amp;lt;/tt&amp;gt; calling context of unknown priority. &amp;lt;tt&amp;gt;dos.library&amp;lt;/tt&amp;gt; functions may not be called. Also, stack space is provided only to call &amp;lt;tt&amp;gt;exec.library&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;utility.library&amp;lt;/tt&amp;gt; functions. The callback shall not place excessive data on the stack. Stack space should be considered limited and the callback should be designed to be fast and short.&lt;br /&gt;
&lt;br /&gt;
This hook is installed at &amp;lt;tt&amp;gt;OpenDevice()&amp;lt;/tt&amp;gt; time, which means that the hook is used for the unit that was opened, and not just for the I/O request it was opened with. The hook must remain installed until the I/O request that installed it is eventually used to close the device. When this happens, the device should fall back to use no log hook at all. No nesting is permitted or required.&lt;br /&gt;
&lt;br /&gt;
= Packet Type =&lt;br /&gt;
&lt;br /&gt;
Network frames always have a type field associated with them. These type fields vary in length, position and meaning by frame type (frame types generally correspond one-to-one with hardware types, but see &amp;quot;Ethernet Packet Types&amp;quot; below). The meanings of the type numbers are always carefully defined and every type number is registered with some official body. Do not use a type number which is not registered for any standard hardware you use or in a manner inconsistent with that registration.&lt;br /&gt;
&lt;br /&gt;
The type field allows the SANA-II device driver to fulfill CMD_READs based on the type of packet the driver user wants. Multiple protocols can therefore run over the same wire using the same driver without stepping on each other&#039;s toes.&lt;br /&gt;
&lt;br /&gt;
Packet types are specified as a long word. Unfortunately, the type field means different things on different wires. Driver users must allow their software to be configured with a SANA-II device name, unit number and the type number(s) used by the protocol stack with each device. This way, if new hardware becomes available, a hardware manufacturer can supply a listing of type assignments to configure pre-existing software.&lt;br /&gt;
&lt;br /&gt;
== Ethernet Packet Types ==&lt;br /&gt;
&lt;br /&gt;
Ethernet has a special problem with packet types. Two types of ethernet frames can be sent over the same wire: ethernet and 802.3. These frames differ in that the Type field of an ethernet frame is the Length field of an 802.3 frame. This creates a problem in that demultiplexing incoming packets can be cumbersome and inefficient, as well as requiring driver users to be aware of the frame type used.&lt;br /&gt;
&lt;br /&gt;
All 802.3 frames have numbers less than 1500 in the Type field. The only frames with numbers less than 1500 in the type field are 802.3 frames. SANA-II ethernet drivers abnormally return packets contained in ethernet frames when the requested Type falls within the 802.3 range-if the Type requested is within the 802.3 range, the driver returns the next packet contained within an 802.3 frame, regardless of the type specified for the packet within the 802.3 frame. This requires that there be no more than one driver user requesting 802.3 packets and that it do its own interpretation of the frames.&lt;br /&gt;
&lt;br /&gt;
== ARCNET Frames ==&lt;br /&gt;
&lt;br /&gt;
ARCNET also has a special problem with framing. ARCNET frames consist of a hardware header and a software header. The software header is in the data area of the hardware packet, and includes at least the protocol ID.&lt;br /&gt;
&lt;br /&gt;
There are two types of software header. Old-style ARCNET software headers consist entirely of a one or two byte protocol ID. New ARCNET software headers (defined in RFC 1201 and in the paper &amp;quot;ARCNET Packet Header Definition Standard&amp;quot;, Novell, Inc., 1989) include more information. They allow more efficient use of ARCNET through data link layer fragmentation and reassembly (ARCNET has a small Maximum Transmission Unit) and allow sending any size packet up to the MTU (rather than requiring that packets of size 253, 254 and 255 be padded to at least 256 bytes).&lt;br /&gt;
&lt;br /&gt;
SANA-II device drivers for ARCNET should implement the old ARCNET packet headers. Driver users which wish to interoperate with platforms using the new software headers must add the new fields to the data to be sent and must process it for incoming data. A SANA-II driver which implemented the data link layer fragmentation internally (and advertised a large MTU) could be more efficient than requiring the driver user to do it. This would make driver writing more difficult and reduce interoperability, but if there is ever a demand for that extra performance, a new hardware type may be assigned by Amiga for SANA-II ARCNET device drivers which implement the new framing.&lt;br /&gt;
&lt;br /&gt;
= Addressing =&lt;br /&gt;
&lt;br /&gt;
In the SANA-II standard, network hardware addresses are stored in an array of &#039;&#039;n&#039;&#039; bytes. No meaning is ascribed by the standard to the contents of the array.&lt;br /&gt;
&lt;br /&gt;
In case there exists a network which does not have an address field consisting of a number of bits not divisible by eight, add pad bits at the end of the bit stream. For example, if an address is ten bits long it will be stored like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
98765432 10PPPPPP&lt;br /&gt;
BYTE 0   BYTE 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where the numerals are bit numbers and &amp;quot;P&amp;quot; is a pad (ignored) bit.&lt;br /&gt;
&lt;br /&gt;
Driver users which do not implement the bit shifting necessary to use a network with such addressing (if one exists) should at least check the number of significant bits in the address field (returned from the device&#039;s S2_DEVICEQUERY function) to make sure that it is evenly divisible by eight.&lt;br /&gt;
&lt;br /&gt;
Driver users will map hardware addresses to protocol addresses in a protocol and hardware dependent manner, as described by the relevant standards (i.e., RFC 826 for TCP/IP over Ethernet, RFC 1201 or RFC 1051 for TCP/IP over ARCNET). Some protocols will always use the same mapping on all hardware, but other protocols will have particular address mapping schemes for some particular hardware and a reasonable default for other (unknown) hardware.&lt;br /&gt;
&lt;br /&gt;
Some SANA-II devices will have &amp;quot;hardware addresses&amp;quot; which aren&#039;t really hardware addresses. As an example, consider &#039;&#039;PPP&#039;&#039; (Point-to-Point Protocol). PPP is a standard for transmitting IP packets over a serial line. It uses IP addresses negotiated during the establishment of a connection. In a SANA-II driver implementation of PPP, the driver would negotiate the address at S2_CONFIGINTERFACE. Thus, the address in SrcAddr returned by the device on an S2_CONFIGINTERFACE (or in a subsequent S2_GETSTATIONADDRESS) will be a protocol address, not a true hardware address.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; Some hardware always uses a ROM hardware address. Other hardware which has a ROM address or is configurable with DIP switches may be overridden by software. Some hardware always dynamically allocates a new hardware address at initialization. See &amp;quot;Configuration&amp;quot; for details on how this is handled by driver writers and by driver users.&lt;br /&gt;
&lt;br /&gt;
= Hardware Type =&lt;br /&gt;
&lt;br /&gt;
The HardwareType returned by the device&#039;s S2_DEVICEQUERY function is necessary for those protocols whose standards require different behavior on different hardware. It is also useful for determining appropriate packet type numbers to use with the device. The HardwareType values already issued for standard network hardware are the same as those in RFC 1060 (assigned numbers). Hardware developers implementing networks without a SANA-II hardware number must contact the AmigaOS development team to have a new hardware type number assigned. Driver users should all have reasonable defaults which can be used for hardware with which they are not familiar.&lt;br /&gt;
&lt;br /&gt;
= Errors =&lt;br /&gt;
&lt;br /&gt;
The SANA-II extended IORequest structure (struct IOSana2Req) includes both the ios2_Error and ios2_WireError fields. Driver users must always check IOSana2Reqs on return for an error in ios2_Error. ios2_Error will be zero if no error occurred, otherwise it will contain a value from &amp;amp;lt;exec/errors.h&amp;amp;gt; or &amp;amp;lt;devices/sana2.h&amp;amp;gt;. If there was an error, there may be more specific information in ios2_WireError. Drivers are required to fill in the WireError if there is an applicable error code.&lt;br /&gt;
&lt;br /&gt;
Error codes are #define&#039;d in the &amp;quot;defined errors&amp;quot; sections of the file &amp;amp;lt;devices/sana2.h&amp;amp;gt;:&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! IOSana2Req S2io_Error field&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| S2ERR_NO_RESOURCES&lt;br /&gt;
| Insufficient resources available.&lt;br /&gt;
|-&lt;br /&gt;
| S2ERR_BAD_ARGUMENT&lt;br /&gt;
| Noticeably bad argument.&lt;br /&gt;
|-&lt;br /&gt;
| S2ERR_BAD_STATE&lt;br /&gt;
| Command inappropriate for current state.&lt;br /&gt;
|-&lt;br /&gt;
| S2ERR_BAD_ADDRESS&lt;br /&gt;
| Noticeably bad address.&lt;br /&gt;
|-&lt;br /&gt;
| S2ERR_MTU_EXCEEDED&lt;br /&gt;
| Write data too large.&lt;br /&gt;
|-&lt;br /&gt;
| S2ERR_NOT_SUPPORTED&lt;br /&gt;
| Command is not supported by this driver. This is similar to IOERR_NOCMD as defined in &amp;amp;lt;exec/errors.h&amp;amp;gt; but S2ERR_NOT_SUPPORTED indicates that the requested command is a valid SANA-II command and that the driver does not support it because the hardware is incapable of supporting it (e.g., S2_MULTICAST). Note that IOERR_NOCMD is still valid for reasons other than a lack of hardware support (i.e., commands which are no-ops in a SANA-II driver).&lt;br /&gt;
|-&lt;br /&gt;
| S2ERR_SOFTWARE&lt;br /&gt;
| Software error of some kind.&lt;br /&gt;
|-&lt;br /&gt;
| S2ERR_OUTOFSERVICE&lt;br /&gt;
| When a hardware device is taken off-line, any pending requests are returned with this error.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
See also the standard errors in &amp;amp;lt;exec/errors.h&amp;amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! IOSana2Req S2io_WireError field&lt;br /&gt;
! Description&lt;br /&gt;
! Value&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_NOT_CONFIGURED&lt;br /&gt;
| Command requires unit to be configured.&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_UNIT_ONLINE&lt;br /&gt;
| Command requires that the unit be off-line.&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_UNIT_OFFLINE&lt;br /&gt;
| Command requires that the unit be on-line.&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_ALREADY_TRACKED&lt;br /&gt;
| Protocol is already being tracked.&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_NOT_TRACKED&lt;br /&gt;
| Protocol is not being tracked.&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_BUFF_ERROR&lt;br /&gt;
| Buffer management function returned an error.&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_SRC_ADDRESS&lt;br /&gt;
| Problem with the source address field.&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_DST_ADDRESS&lt;br /&gt;
| Problem with destination address field.&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_BAD_BROADCAST&lt;br /&gt;
| Problem with an attempt to broadcast.&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_BAD_MULTICAST&lt;br /&gt;
| Problem with an attempt to multicast.&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_MULTICAST_FULL&lt;br /&gt;
| Multicast address list full.&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_BAD_EVENT&lt;br /&gt;
| Event specified is unknown.&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_BAD_STATDATA&lt;br /&gt;
| The ios2_StatData pointer or the data it points to failed a sanity check.&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_IS_CONFIGURED&lt;br /&gt;
| Attempt to reconfigure the unit.&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_NULL_POINTER&lt;br /&gt;
| A NULL pointer was detected in one of the arguments. S2ERR_BAD_ARGUMENT should always be the S2ERR.&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_UNIT_DISCONNECTED&lt;br /&gt;
| This error code is a counterpart to &amp;lt;tt&amp;gt;S2WERR_UNIT_OFFLINE&amp;lt;/tt&amp;gt;. It indicates that the associated command could not be executed because the link layer is not connected.&lt;br /&gt;
| 19&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_UNIT_CONNECTED&lt;br /&gt;
| This error code is a counterpart to &amp;lt;tt&amp;gt;S2WERR_UNIT_ONLINE&amp;lt;/tt&amp;gt;. It indicates that the associated command could not be executed because the link layer is already connected.&lt;br /&gt;
| 20&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_INVALID_OPTION&lt;br /&gt;
| This error code indicates that an option, such as passed by the &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt; command, is not acceptable. The option&#039;s value may be out of range or may not match the syntax specifications. To indicate which option that may be, a different mechanism &#039;&#039;&#039;must&#039;&#039;&#039; be used; a simple indication that something was wrong is &#039;&#039;&#039;not sufficient&#039;&#039;&#039;.&lt;br /&gt;
| 21&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_MISSING_OPTION&lt;br /&gt;
| This error code indicates that a mandatory option, such as passed by the &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt; command, is not present. To indicate which option that may be, a different mechanism &#039;&#039;&#039;must&#039;&#039;&#039; be used; a simple indication that something was wrong is &#039;&#039;&#039;not sufficient&#039;&#039;&#039;.&lt;br /&gt;
| 22&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_AUTHENTICATION_FAILED&lt;br /&gt;
| Some drivers run protocols that require them to authenticate to a server. That process may fail. This wire error code is to indicate this fact.&lt;br /&gt;
| 23&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Standard Commands =&lt;br /&gt;
&lt;br /&gt;
See the &amp;quot;SANA-II network device driver Autodocs&amp;quot; for full details on each of the SANA-II device commands. Extended commands are explained in the sections below.&lt;br /&gt;
&lt;br /&gt;
Many of the Exec device standard commands are no-ops in SANA-II devices, but this may not always be the case. For example, CMD_RESET might someday be used for dynamically reconfiguring hardware. This should present no compatibility problems for properly written drivers.&lt;br /&gt;
&lt;br /&gt;
== Broadcast and Multicast ==&lt;br /&gt;
&lt;br /&gt;
Some hardware supports broadcast and/or multicast. A broadcast is a packet sent to all other machines. A multicast is a packet sent to a set of machines. Drivers for hardware which does not allow broadcast or multicast will return ios2_Error S2ERR_NOT_SUPPORTED as appropriate.&lt;br /&gt;
&lt;br /&gt;
To send a broadcast, use S2_BROADCAST instead of CMD_WRITE. Broadcasts are received just like any other packets (using a CMD_READ for the appropriate packet type).&lt;br /&gt;
&lt;br /&gt;
To send a multicast, use S2_MULTICAST instead of CMD_WRITE. The device keeps a list of addresses that want to receive multicasts. You add a receiver&#039;s address to this list by using S2_ADDMULTICASTADDRESS. The receiver then posts a CMD_READ for the type of packet to be received. Some SANA-II devices which support multicast may have a limit on the number of addresses that can simultaneously wait for packets. Always check for an S2WERR_MULTICAST_FULL error return when adding a multicast address.&lt;br /&gt;
&lt;br /&gt;
Note that when the device adds a multicast address, it is usually added for all users of the device, not just the driver user which called S2_ADDMULTICASTADDRESS. In other words, received multicast packets will fill a read request of the appropriate type regardless of whether the requesting driver user is the same one which added the multicast address.&lt;br /&gt;
&lt;br /&gt;
In general, driver users should not care how received packets were sent (normally or broadcast/multicast), only that it was received. If a driver user really must know, however, it can check for SANA2IOB_BCAST and/or SANA2IOB_MCAST in the ios2_Flags field.&lt;br /&gt;
&lt;br /&gt;
Drivers should keep a count for the number of opens on a multicast address so that they don&#039;t actually remove it until it has been S2_DELMULTICASTADDRESS&#039;d as many times as it has been S2_ADDMULTICASTADDRESS&#039;d.&lt;br /&gt;
&lt;br /&gt;
== Stats ==&lt;br /&gt;
&lt;br /&gt;
There are many statistics which may be very important to someone trying to debug, tune or optimize a protocol stack, as well as to the end user who may need to tune parameters or investigate a problem. Some of these statistics can only be kept by the SANA-II driver, thus there are several required and optional statistics and commands for this purpose.&lt;br /&gt;
&lt;br /&gt;
S2_TRACKTYPE tells the device driver to gather statistics for a particular packet type. S2_UNTRACKTYPE tells it to stop (keeping statistics by type causes the driver to use additional resources). S2_GETTYPESTATS returns any statistics accumulated by the driver for a type being tracked (stats are lost when a type is S2_UNTRACKTYPE&#039;d). Drivers are required to implement the functionality of type tracking. The stats are returned in a struct Sana2PacketTypeStats:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct Sana2PacketTypeStats&lt;br /&gt;
{&lt;br /&gt;
  ULONG PacketsSent;&lt;br /&gt;
  ULONG PacketsReceived;&lt;br /&gt;
  ULONG BytesSent;&lt;br /&gt;
  ULONG BytesReceived;&lt;br /&gt;
  ULONG PacketsDropped;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; PacketsSent&lt;br /&gt;
: Number of packets of a particular type sent.&lt;br /&gt;
; PacketsReceived&lt;br /&gt;
: Number of packets of a particular type that satisfied a read command.&lt;br /&gt;
; BytesSent&lt;br /&gt;
: Number of bytes of data sent in packets of a particular type.&lt;br /&gt;
; BytesReceived&lt;br /&gt;
: Number of bytes of data of a particular packet type that satisfied a read command.&lt;br /&gt;
; PacketsDropped&lt;br /&gt;
: Number of packets of a particular type that were received while there were no pending reads of that packet type.&lt;br /&gt;
&lt;br /&gt;
returns global statistics kept by the driver. Drivers are required to keep all applicable statistics. Since all are applicable to most hardware, most drivers will maintain all statistics. The stats are returned in a struct Sana2DeviceStats:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct Sana2DeviceStats&lt;br /&gt;
{&lt;br /&gt;
  ULONG PacketsReceived;&lt;br /&gt;
  ULONG PacketsSent;&lt;br /&gt;
  ULONG BadData;&lt;br /&gt;
  ULONG Overruns;&lt;br /&gt;
  ULONG UnknownTypesReceived;&lt;br /&gt;
  ULONG Reconfigurations;&lt;br /&gt;
  struct timeval LastStart;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; PacketsReceived&lt;br /&gt;
: Number of packets that this unit has received.&lt;br /&gt;
; PacketsSent&lt;br /&gt;
: Number of packets that this unit has sent.&lt;br /&gt;
; BadData&lt;br /&gt;
: Number of bad packets received (i.e., hardware CRC failed).&lt;br /&gt;
; Overruns&lt;br /&gt;
: Number of packets dropped due to insufficient resources available in the network interface.&lt;br /&gt;
; UnknownTypeReceived&lt;br /&gt;
: Number of packets received that had no pending read command with the appropriate packet type.&lt;br /&gt;
; Reconfigurations&lt;br /&gt;
: Number of network reconfigurations since this unit was last configured.&lt;br /&gt;
; LastStart&lt;br /&gt;
: The time when this unit last went on-line.&lt;br /&gt;
&lt;br /&gt;
returns any special statistics kept by a particular driver. Each new wire type will have a set of documented, required statistics for that wire type and a standard set of optional statistics for that wire type (optional because they might not be available from all hardware). The data returned by S2_GETSPECIALSTATS will require wire-specific interpretation. See &amp;amp;lt;devices/sana2specialstats.h&amp;amp;gt; on page devices&amp;lt;sub&amp;gt;s&amp;lt;/sub&amp;gt;ana2specialstats&amp;lt;sub&amp;gt;p&amp;lt;/sub&amp;gt;age for currently defined special statistics. The statistics are returned in the following structures:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct Sana2SpecialStatRecord&lt;br /&gt;
{&lt;br /&gt;
  ULONG Type;&lt;br /&gt;
  ULONG Count;&lt;br /&gt;
  char * String;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; Type&lt;br /&gt;
: Statistic identifier.&lt;br /&gt;
; Count&lt;br /&gt;
: Statistic itself.&lt;br /&gt;
; String&lt;br /&gt;
: An identifying, null-terminated string for the statistic. Should be plain ASCII with no formatting characters.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct Sana2SpecialStatHeader&lt;br /&gt;
{&lt;br /&gt;
  ULONG RecordCountMax;&lt;br /&gt;
  ULONG RecordCountSupplied;&lt;br /&gt;
  struct Sana2SpecialStatRecord[RecordCountMax];&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; RecordCountMax&lt;br /&gt;
: There is space for this many records into which statistics may be placed.&lt;br /&gt;
; RecordCountSupplied&lt;br /&gt;
: Number of statistic records supplied.&lt;br /&gt;
&lt;br /&gt;
is not, strictly speaking, a statistical function. It is a request to read any packet of a type for which there is no outstanding CMD_READ. S2_READORPHAN might be used in the same manner as many statistics, though, such as to determine what packet types are causing overruns, etc.&lt;br /&gt;
&lt;br /&gt;
== Configuration ==&lt;br /&gt;
&lt;br /&gt;
The device driver needs to configure the hardware before using it. The driver user must know some network hardware parameters (hardware address and MTU, for example) when using it. These commands address those needs.&lt;br /&gt;
&lt;br /&gt;
When a driver user is initialized, it should try to S2_CONFIGINTERFACE even though an interface can only be configured once and someone else may have done it. Before you call S2_CONFIGINTERFACE, first call S2_GETSTATIONADDRESS to determine the factory address (if any). Also provide for user-override of the factory address (that address may be optional and the user may need to override it). When S2_CONFIGINTERFACE returns, check the ios2_SrcAddr for the actual address the hardware has been configured with. This is because some hardware (or serial line standards such as PPP) always dynamically allocates an address at initialization.&lt;br /&gt;
&lt;br /&gt;
Driver users will want to use S2_DEVICEQUERY to determine the MTU and other characteristics of the network. The structure returned from S2_DEVICEQUERY is defined as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct Sana2DeviceQuery&lt;br /&gt;
{&lt;br /&gt;
    /*&lt;br /&gt;
    ** Standard information&lt;br /&gt;
    */&lt;br /&gt;
    ULONG SizeAvailable;    /* bytes available */&lt;br /&gt;
    ULONG SizeSupplied;     /* bytes supplied */&lt;br /&gt;
    LONG  DevQueryFormat;   /* this is type 0 */&lt;br /&gt;
    LONG  DeviceLevel;      /* this document is level 0 */&lt;br /&gt;
&lt;br /&gt;
    /*&lt;br /&gt;
    ** Common information&lt;br /&gt;
    */&lt;br /&gt;
    UWORD AddrFieldSize;    /* address size in bits */&lt;br /&gt;
    ULONG MTU;              /* maximum packet data size */&lt;br /&gt;
    LONG  BPS;              /* line rate (bits/sec) */&lt;br /&gt;
    LONG  HardwareType;     /* what the wire is */&lt;br /&gt;
    ULONG RawMTU;           /* maximum raw packet data size */&lt;br /&gt;
&lt;br /&gt;
    /*&lt;br /&gt;
    ** Format specific information&lt;br /&gt;
    */&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; SizeAvailable&lt;br /&gt;
: Size, in bytes, of the space available in which to place device information. This includes both size fields.&lt;br /&gt;
; SizeSupplied&lt;br /&gt;
: Size, in bytes, of the data supplied.&lt;br /&gt;
; DevQueryFormat&lt;br /&gt;
: The format defined here is format 0.&lt;br /&gt;
; DeviceLevel&lt;br /&gt;
: This spec defines level 0.&lt;br /&gt;
; AddrFieldSize&lt;br /&gt;
: The number of bits in an interface address.&lt;br /&gt;
; MTU&lt;br /&gt;
: Maximum Transmission Unit, the size, in bytes, of the maximum packet size, not including header and trailer information.&lt;br /&gt;
; BPS&lt;br /&gt;
: Best guess at the raw line rate for this network in bits per second.&lt;br /&gt;
&lt;br /&gt;
; HardwareType&lt;br /&gt;
: Specifies the type of network hardware the driver controls.&lt;br /&gt;
&lt;br /&gt;
; RawMTU&lt;br /&gt;
: The &amp;lt;tt&amp;gt;RawMTU&amp;lt;/tt&amp;gt; member is new as of SANA-II Revision 4. Devices which do not know and support this structure member may fill in the &amp;lt;tt&amp;gt;Sana2DeviceQuery&amp;lt;/tt&amp;gt; structure only up to and including the &amp;lt;tt&amp;gt;HardwareType&amp;lt;/tt&amp;gt; member.&lt;br /&gt;
&lt;br /&gt;
: In this context &#039;raw&#039; means the number of bytes that are available for reading and writing when using the &amp;lt;tt&amp;gt;SANA2IOB_RAW&amp;lt;/tt&amp;gt; flag with a &amp;lt;tt&amp;gt;CMD_READ&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;CMD_WRITE&amp;lt;/tt&amp;gt; request on a device that supports these access methods. Currently, software developers can only make assumptions on how many bytes might comprise the &#039;raw&#039; MTU by checking the &amp;lt;tt&amp;gt;Sana2DeviceQuery.HardwareType&amp;lt;/tt&amp;gt; member and hoping that the driver supports raw &amp;lt;tt&amp;gt;CMD_READ&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;CMD_WRITE&amp;lt;/tt&amp;gt; access.&lt;br /&gt;
&lt;br /&gt;
: Devices which know and support the &amp;lt;tt&amp;gt;RawMTU&amp;lt;/tt&amp;gt; member must fill it with a well-defined value. For Amiga Ethernet drivers, that value would be 1514, which is the standard MTU value of 1500 bytes plus the size of the Ethernet frame header, as per RFC894 (six bytes for the destination address, six bytes for the source address and two bytes for the frame type; the eight byte preamble and the terminating four byte CRC value are typically not under the control of the driver). Drivers which do not support raw read or write access must set the &amp;lt;tt&amp;gt;RawMTU&amp;lt;/tt&amp;gt; member to zero.&lt;br /&gt;
&lt;br /&gt;
: If the &amp;lt;tt&amp;gt;RawMTU&amp;lt;/tt&amp;gt; member is not provided, all bets are off and the application software must fall back to making estimates based upon the hardware type and the raw frame types it wishes to read and write. Ultimatively, the driver itself must decide whether it can accept raw read and write commands (or has to reject them with &amp;lt;tt&amp;gt;S2ERR_NOT_SUPPORTED&amp;lt;/tt&amp;gt;) and whether the raw packet size is still covered by the underlying hardware MTU (or must be rejected with &amp;lt;tt&amp;gt;S2ERR_MTU_EXCEEDED&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
: A word of warning: a little testing with various Ethernet hardware drivers has revealed that the A2065 driver &amp;lt;tt&amp;gt;a2065.device&amp;lt;/tt&amp;gt; does not handle the &amp;lt;tt&amp;gt;S2_DEVICEQUERY&amp;lt;/tt&amp;gt; command properly if the &amp;lt;tt&amp;gt;Sana2DeviceQuery&amp;lt;/tt&amp;gt; structure provided is larger than 30 bytes. In other words, the command will fail if the proposed &amp;lt;tt&amp;gt;RawMTU&amp;lt;/tt&amp;gt; member is present in the query data structure to be filled in.&lt;br /&gt;
&lt;br /&gt;
== On-line ==&lt;br /&gt;
&lt;br /&gt;
In order to run hardware tests on an otherwise live system, the S2_OFFLINE command allows the SANA-II device driver to be &amp;quot;turned off&amp;quot; until the tests are complete and an S2_ONLINE is sent to the driver. S2_ONLINE causes the interface to re-configure and re-initialize. Any packets destined for the hardware while the device is off-line will be lost. All pending and new requests to the driver shall be returned with S2ERR_OUTOFSERVICE when a device is off-line.&lt;br /&gt;
&lt;br /&gt;
All driver users must understand that any IO request may return with S2ERR_OUTOFSERVICE because the driver is off-line (any other program may call S2_OFFLINE to make it so). In such an event, the driver will usually want to wait until the unit comes back on-line (for the program which called S2_OFFLINE to call S2_ONLINE). It may do this by calling S2_ONEVENT to wait for S2EVENT_ONLINE. S2_ONEVENT allows the driver user to wait on various events.&lt;br /&gt;
&lt;br /&gt;
A driver must track events, but may not distinguish between some types of events. Drivers return S2_ONEVENT with S2ERR_NOT_SUPPORTED and S2WERR_BAD_EVENT for unsupported events. One error may cause more than one event (see below). Errors which seem to have been caused by a malformed or unusual request should not generally trigger an event.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Event type&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| S2EVENT_ERROR&lt;br /&gt;
| Return when any error occurs.&lt;br /&gt;
|-&lt;br /&gt;
| S2EVENT_TX&lt;br /&gt;
| Return on any transmit error (always an error).&lt;br /&gt;
|-&lt;br /&gt;
| S2EVENT_RX&lt;br /&gt;
| Return on any receive error (always an error).&lt;br /&gt;
|-&lt;br /&gt;
| S2EVENT_ONLINE&lt;br /&gt;
| Return when unit goes on-line or return immediately if unit is already on-line (not an error).&lt;br /&gt;
|-&lt;br /&gt;
| S2EVENT_OFFLINE&lt;br /&gt;
| Return when unit goes off-line or return immediately if unit is already off-line (not an error.)&lt;br /&gt;
|-&lt;br /&gt;
| S2EVENT_BUFF&lt;br /&gt;
| Return on any buffer management function error (always an error).&lt;br /&gt;
|-&lt;br /&gt;
| S2EVENT_HARDWARE&lt;br /&gt;
| Return when any hardware error occurs (always an error, may be a S2EVENT_TX or S2EVENT_RX, too).&lt;br /&gt;
|-&lt;br /&gt;
| S2EVENT_SOFTWARE&lt;br /&gt;
| Return when any software error occurs (always an error, may be a S2EVENT_TX or S2EVENT_RX, too).&lt;br /&gt;
|-&lt;br /&gt;
| S2EVENT_CONFIGCHANGED&lt;br /&gt;
| Return when client-visible configuration information changes (not an error).&lt;br /&gt;
|-&lt;br /&gt;
| S2EVENT_CONNECT&lt;br /&gt;
| Return when the driver has successfully established a link layer connection (not an error).&lt;br /&gt;
|-&lt;br /&gt;
| S2EVENT_DISCONNECT &lt;br /&gt;
| Return when the driver has closed the link layer connection previously established by the S2_CONNECT command (not an error).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== S2EVENT_CONFIGCHANGED ===&lt;br /&gt;
&lt;br /&gt;
For drivers such as those which implement the &amp;lt;tt&amp;gt;S2_GETPEERADDRESS&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2_GETDNSADDRESS&amp;lt;/tt&amp;gt; commands it is vital that such changes can take place and be noticed by the client software. For this purpose a new event type is introduced, to be used with the SANA-II &amp;lt;tt&amp;gt;S2_ONEVENT&amp;lt;/tt&amp;gt; command, using the following definition:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;#define S2EVENT_CONFIGCHANGED (1L&amp;amp;lt;&amp;amp;lt;8)&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This event should be triggered whenever client-visible configuration information changes, as can be queried via the &amp;lt;tt&amp;gt;S2_DEVICEQUERY&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;S2_GETSTATIONADDRESS&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;S2_GETSPECIALSTATS&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;S2_GETGLOBALSTATS&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;S2_GETPEERADDRESS&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2_GETDNSADDRESS&amp;lt;/tt&amp;gt; commands. Here is a short list of what could change:&lt;br /&gt;
&lt;br /&gt;
# S2_DEVICEQUERY: &amp;lt;tt&amp;gt;AddrFieldSize&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;MTU&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;BPS&amp;lt;/tt&amp;gt;&lt;br /&gt;
# S2_GETSTATIONADDRESS: &amp;lt;tt&amp;gt;ios2_SrcAddr&amp;lt;/tt&amp;gt;&lt;br /&gt;
# S2_GETGLOBALSTATS: &amp;lt;tt&amp;gt;Reconfigurations&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;LastStart&amp;lt;/tt&amp;gt;&lt;br /&gt;
# S2_GETPEERADDRESS: &amp;lt;tt&amp;gt;ios2_SrcAddr&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ios2_DstAddr&amp;lt;/tt&amp;gt;&lt;br /&gt;
# S2_GETDNSADDRESS: &amp;lt;tt&amp;gt;ios2_SrcAddr&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ios2_DstAddr&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The purpose of this event &#039;&#039;&#039;is not&#039;&#039;&#039; to post a notification whenever another byte or event counter has changed so that a monitoring program may update its display. The purpose &#039;&#039;&#039;is&#039;&#039;&#039; to convey to the client software that an important device configuration option has changed and that it is supposed to react and adapt to it. For example, a TCP/IP stack may, upon learning that a device&#039;s IP address has changed, rebuild its routing table.&lt;br /&gt;
&lt;br /&gt;
Since the &amp;lt;tt&amp;gt;S2EVENT_CONFIGCHANGED&amp;lt;/tt&amp;gt; event may arrive at any time and does not indicate what exactly has changed, application software should query the information it expects to change during its life time, and keep a copy of it around for later reference. When the &amp;lt;tt&amp;gt;S2EVENT_CONFIGCHANGED&amp;lt;/tt&amp;gt; event arrives, it can compare the contents of the copy against the current state of affairs and act according to the differences it finds.&lt;br /&gt;
&lt;br /&gt;
=== S2EVENT_CONNECT ===&lt;br /&gt;
&lt;br /&gt;
This event is a counterpart to &amp;lt;tt&amp;gt;S2EVENT_ONLINE&amp;lt;/tt&amp;gt;, and is associated with the &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt; command. It has the following semantics:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;#define S2EVENT_CONNECT (1L&amp;amp;lt;&amp;amp;lt;9) /* Driver has opened session */&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The event is to be sent when the driver has successfully established a link layer connection.&lt;br /&gt;
&lt;br /&gt;
=== S2EVENT_DISCONNECT ===&lt;br /&gt;
&lt;br /&gt;
This event is a counterpart to &amp;lt;tt&amp;gt;S2EVENT_OFFLINE&amp;lt;/tt&amp;gt;, and is associated with the &amp;lt;tt&amp;gt;S2_DISCONNECT&amp;lt;/tt&amp;gt; command. It has the following semantics:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;#define S2EVENT_DISCONNECT (1L&amp;amp;lt;&amp;amp;lt;10) /* Driver has closed session */&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The event is to be sent when the driver has closed the link layer connection previously established by the &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt; command.&lt;br /&gt;
&lt;br /&gt;
== S2_ONLINE and S2_OFFLINE ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2_DISCONNECT&amp;lt;/tt&amp;gt; commands are somewhat related to the &amp;lt;tt&amp;gt;S2_ONLINE&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2_OFFLINE&amp;lt;/tt&amp;gt; commands. How this relation works out shall be explained below. Note that the following text assumes that both the &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;S2_DISCONNECT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2_ONLINE&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;S2_OFFLINE&amp;lt;/tt&amp;gt; command pairs are implemented.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt; implies &amp;lt;tt&amp;gt;S2_ONLINE&amp;lt;/tt&amp;gt; and, if successful, may report &amp;lt;tt&amp;gt;S2EVENT_ONLINE&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2EVENT_CONNECT&amp;lt;/tt&amp;gt; events. If the unit is currently disconnected, but still online, only the &amp;lt;tt&amp;gt;S2EVENT_CONNECT&amp;lt;/tt&amp;gt; event shall be sent. Invoking the &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt; command on a driver which is already connected must be rejected with &amp;lt;tt&amp;gt;ios2_Req.io_Error=S2ERR_BAD_STATE&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;ios2_WireError=S2WERR_UNIT_CONNECTED&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;S2_DISCONNECT&amp;lt;/tt&amp;gt; implies &amp;lt;tt&amp;gt;S2_OFFLINE&amp;lt;/tt&amp;gt; and, if successful, may report &amp;lt;tt&amp;gt;S2EVENT_OFFLINE&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2EVENT_DISCONNECT&amp;lt;/tt&amp;gt; events. If the unit is currently connected and offline, then only the &amp;lt;tt&amp;gt;S2EVENT_DISCONNECT&amp;lt;/tt&amp;gt; event shall be sent. Invoking the &amp;lt;tt&amp;gt;S2_DISCONNECT&amp;lt;/tt&amp;gt; command on a driver which is already disconnected must be rejected with &amp;lt;tt&amp;gt;ios2_Req.io_Error=S2ERR_BAD_STATE&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;ios2_WireError=S2WERR_UNIT_DISCONNECTED&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;S2_OFFLINE&amp;lt;/tt&amp;gt; may be used after the &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt; has successfully connected the unit. In this case the driver will release control over the link layer and report the &amp;lt;tt&amp;gt;S2EVENT_OFFLINE&amp;lt;/tt&amp;gt; event. The connection established using the &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt; will, however, persist.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;S2_ONLINE&amp;lt;/tt&amp;gt; may be used after &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt; has successfully connected the unit and the &amp;lt;tt&amp;gt;S2_OFFLINE&amp;lt;/tt&amp;gt; was used. In this case the driver will again try to obtain control over the link layer and report the &amp;lt;tt&amp;gt;S2EVENT_ONLINE&amp;lt;/tt&amp;gt; event if successful.&lt;br /&gt;
&lt;br /&gt;
If the &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt; command was never successfully executed, then the commands &amp;lt;tt&amp;gt;S2_ONLINE&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2_OFFLINE&amp;lt;/tt&amp;gt; must be rejected with &amp;lt;tt&amp;gt;ios2_Req.io_Error=S2ERR_BAD_STATE&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;ios2_WireError=S2WERR_UNIT_DISCONNECTED&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Wireless (IEEE 802.11) ==&lt;br /&gt;
&lt;br /&gt;
Several new commands have been added to the SANA-II API to facilitate use of IEEE 802.11 wireless network devices in client and ad-hoc modes. The new commands are split into two overlapping sets. One set needs to be implemented by drivers for Soft-MAC wireless devices, while the other is implemented for Hard-MAC devices.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Soft-MAC commands&lt;br /&gt;
|-&lt;br /&gt;
| S2_SETOPTIONS&lt;br /&gt;
|-&lt;br /&gt;
| S2_SETKEY&lt;br /&gt;
|-&lt;br /&gt;
| S2_WRITEMGMT&lt;br /&gt;
|-&lt;br /&gt;
| S2_READMGMT&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Hard-MAC commands&lt;br /&gt;
|-&lt;br /&gt;
| S2_SETOPTIONS&lt;br /&gt;
|-&lt;br /&gt;
| S2_SETKEY&lt;br /&gt;
|-&lt;br /&gt;
| S2_GETNETWORKS&lt;br /&gt;
|-&lt;br /&gt;
| S2_GETNETWORKINFO&lt;br /&gt;
|-&lt;br /&gt;
| S2_GETSIGNALQUALITY&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== sana2wireless.h ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
#ifndef DEVICES_SANA2WIRELESS_H&lt;br /&gt;
#define DEVICES_SANA2WIRELESS_H&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;exec/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;utility/tagitem.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/* Constants */&lt;br /&gt;
/* ========= */&lt;br /&gt;
&lt;br /&gt;
/* Tags to get and set information */&lt;br /&gt;
&lt;br /&gt;
#define S2INFO_SSID           (TAG_USER + 0)&lt;br /&gt;
#define S2INFO_BSSID          (TAG_USER + 1)&lt;br /&gt;
#define S2INFO_AuthTypes      (TAG_USER + 2)&lt;br /&gt;
#define S2INFO_AssocID        (TAG_USER + 3)&lt;br /&gt;
#define S2INFO_Encryption     (TAG_USER + 4)&lt;br /&gt;
#define S2INFO_PortType       (TAG_USER + 5)&lt;br /&gt;
#define S2INFO_BeaconInterval (TAG_USER + 6)&lt;br /&gt;
#define S2INFO_Channel        (TAG_USER + 7)&lt;br /&gt;
#define S2INFO_Signal         (TAG_USER + 8)&lt;br /&gt;
#define S2INFO_Noise          (TAG_USER + 9)&lt;br /&gt;
#define S2INFO_Capabilities   (TAG_USER + 10)&lt;br /&gt;
#define S2INFO_InfoElements   (TAG_USER + 11)&lt;br /&gt;
#define S2INFO_WPAInfo        (TAG_USER + 12)&lt;br /&gt;
#define S2INFO_Band           (TAG_USER + 13)&lt;br /&gt;
#define S2INFO_DefaultKeyNo   (TAG_USER + 14)&lt;br /&gt;
&lt;br /&gt;
/* Wireless Commands */&lt;br /&gt;
&lt;br /&gt;
#define S2_GETSIGNALQUALITY 0xc010&lt;br /&gt;
#define S2_GETNETWORKS      0xc011&lt;br /&gt;
#define S2_SETOPTIONS       0xc012&lt;br /&gt;
#define S2_SETKEY           0xc013&lt;br /&gt;
#define S2_GETNETWORKINFO   0xc014&lt;br /&gt;
#define S2_READMGMT         0xc015&lt;br /&gt;
#define S2_WRITEMGMT        0xc016&lt;br /&gt;
#define S2_GETRADIOBANDS    0xc017&lt;br /&gt;
&lt;br /&gt;
/* Encryption types */&lt;br /&gt;
&lt;br /&gt;
#define S2ENC_NONE 0&lt;br /&gt;
#define S2ENC_WEP  1&lt;br /&gt;
#define S2ENC_TKIP 2&lt;br /&gt;
#define S2ENC_CCMP 3&lt;br /&gt;
&lt;br /&gt;
/* Radio modes */&lt;br /&gt;
&lt;br /&gt;
#define S2BAND_A 0&lt;br /&gt;
#define S2BAND_B 1&lt;br /&gt;
#define S2BAND_G 2&lt;br /&gt;
#define S2BAND_N 3&lt;br /&gt;
&lt;br /&gt;
/* Network topologies */&lt;br /&gt;
&lt;br /&gt;
#define S2PORT_MANAGED 7&lt;br /&gt;
#define S2PORT_ADHOC   8&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/* Structures */&lt;br /&gt;
/* ========== */&lt;br /&gt;
&lt;br /&gt;
/* Structure for returning signal quality */&lt;br /&gt;
&lt;br /&gt;
struct Sana2SignalQuality&lt;br /&gt;
{&lt;br /&gt;
   LONG SignalLevel;   /* signal level in dBm */&lt;br /&gt;
   LONG NoiseLevel;   /* noise level in dBm */&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Driver requirements =&lt;br /&gt;
&lt;br /&gt;
This section is an attempt to clarify parts of the specification and to lay down a few rules that every SANA-II driver must follow.&lt;br /&gt;
&lt;br /&gt;
* A driver that does not use a broadcast medium, such as Ethernet, must not implement the &amp;lt;tt&amp;gt;S2_BROADCAST&amp;lt;/tt&amp;gt; command. Likewise, if no multicast mechanism is supported, the &amp;lt;tt&amp;gt;S2_MULTICAST&amp;lt;/tt&amp;gt; must not be implemented either.&lt;br /&gt;
&lt;br /&gt;
* SANA-II standard commands which the driver does not implement must be rejected with the &amp;lt;tt&amp;gt;IOERR_NOCMD&amp;lt;/tt&amp;gt; error code. Commands that are implemented, but which cannot perform the requested services, must be rejected with the &amp;lt;tt&amp;gt;S2ERR_NOT_SUPPORTED&amp;lt;/tt&amp;gt; error code. The difference between the two cases is in when the decision is made whether a command can be handled or not. Which commands should return &amp;lt;tt&amp;gt;IOERR_NOCMD&amp;lt;/tt&amp;gt; is decided upon at the time the driver is designed and implemented. At this stage the implementer knows for sure which capabilities the driver will have and which it will not have. Commands which the driver will never be able to execute will be made to return the &amp;lt;tt&amp;gt;IOERR_NOCMD&amp;lt;/tt&amp;gt; error code. If the decision whether a command can be executed is made only at run time, by evaluating the conditions under which a command can be executed, then the error code &amp;lt;tt&amp;gt;S2ERR_NOT_SUPPORTED&amp;lt;/tt&amp;gt; should be returned in case of failure.&lt;br /&gt;
&lt;br /&gt;
* It must be possible to open the driver with an ordinary &amp;lt;tt&amp;gt;struct IOStdReq&amp;lt;/tt&amp;gt;. This is necessary for the NewStyleDevices query command to work. In the command dispatcher, the driver must verify that all SANA-II commands are invoked with a proper size &amp;lt;tt&amp;gt;struct IOSana2Req&amp;lt;/tt&amp;gt; I/O request. If the I/O request is shorter (as can be verified by looking at the embedded Message&#039;s &amp;lt;tt&amp;gt;mn_Length&amp;lt;/tt&amp;gt; member), the command must be rejected with &amp;lt;tt&amp;gt;ios2_Req.io_Error=IOERR_BADLENGTH&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* A driver must implement the NewStyleDevices &amp;lt;tt&amp;gt;NSCMD_DEVICEQUERY&amp;lt;/tt&amp;gt; command, in conformance with the NSD specification 1.6 or newer. The motivation for this is to have a mechanism available for probing the capabilities of the driver, and the supported command set can provide for vital clues. In this context, the absence of the &amp;lt;tt&amp;gt;S2_BROADCAST&amp;lt;/tt&amp;gt; command would suggest that the driver cannot send or receive broadcast messages.&lt;br /&gt;
&lt;br /&gt;
* A driver that does not allow its station address to be set with the &amp;lt;tt&amp;gt;S2_CONFIGINTERFACE&amp;lt;/tt&amp;gt; command may silently ignore the command (returning it without setting an error condition) and even pretend that it can be configured more than once.&lt;br /&gt;
&lt;br /&gt;
* In response to the &amp;lt;tt&amp;gt;S2_DEVICEQUERY&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;S2_GETSPECIALSTATS&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2_GETGLOBALSTATS&amp;lt;/tt&amp;gt; commands a driver may return information that is not entirely correct if it has to go online before it can provide for the correct data. For example, the maximum transmission unit for PPP is a number in the range of [1..1500] which is negotiated during the protocol configuration process. It is unlikely that numbers greater than 1500 will be used, yet it is still not impossible. Since the actual number will be known only after the driver has configured the protocol, the MTU value returned before the session was opened can differ from the MTU value valid after it has been opened. A driver should therefore attempt to return &#039;safe&#039; defaults in place of information that is unavailable at the time it is queried. The &#039;safe&#039; values shall be set up to allow the driver to work even if the protocol stack is not aware of later changes to those values. Beware of zero-length buffer sizes or time intervals that may cause client software to perform zero-length memory allocations or divisions by zero.&lt;br /&gt;
&lt;br /&gt;
* SANA-II assigns packet type numbers according to the underlying transport media. For example, Ethernet uses packet type 2048 for IP frames. No such packet type definition exists for PPP yet, which is why this standard proposes to assign packet type 31 for IP packets transmitted via PPP. To simplify client software configuration, drivers may treat packet type 2048 as equivalent to the packet number associated with IP frames. This association is permitted only if it does not introduce ambiguity. For example, this association would not be permitted if the driver would receive and transmit IP packets in two different frame types or if the driver already associates packet type 2048 with non-IP packets.&lt;br /&gt;
&lt;br /&gt;
= Driver Installation =&lt;br /&gt;
&lt;br /&gt;
The standard system location for SANA-II network device driver is in a directory called &amp;amp;quot;Networks&amp;amp;quot; which exists in the &amp;amp;quot;DEVS:&amp;amp;quot; directory.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
DEVS:Networks/eth3com.device&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the official location for the drivers. It may be necessary for your install program/script to create this directory if it doesn&#039;t exist in a user&#039;s system.&lt;br /&gt;
&lt;br /&gt;
= Unresolved Issues =&lt;br /&gt;
&lt;br /&gt;
* Unfortunately, it isn&#039;t possible to completely isolate network protocols from the hardware they run on. Hardware types and addressing both remain somewhat hardware-dependent in spite of our efforts. See the &amp;quot;Packet Type&amp;quot; section for an explanation of how packet types are handled and why protocols cannot be isolated from them. See the &amp;quot;Addressing&amp;quot; section for an explanation of how addressing is handled any why protocols cannot be isolated from it.&lt;br /&gt;
&lt;br /&gt;
* Additionally, there are at least two cases where a hardware type has multiple framing methods in use (ethernet/802.3 and arcnet/(Novell) &amp;quot;ARCNET Packet Header Definition Standard&amp;quot;). In both cases, software which must interoperate with other platforms on this hardware may need to be aware of the distinctions and may have to do extra processing in order to use the appropriate frame type. See the sections on &amp;quot;Ethernet Packet Types&amp;quot; and on &amp;quot;ARCNET frames&amp;quot; for more details.&lt;br /&gt;
&lt;br /&gt;
* Protocols like PPP can provide both for IPv4 and IPv6 addresses that should be used by the local client, the peer or any of the domain name servers. While the two addressing families are interoperable, there is a problem in how the driver should report them. Can you assume 128 bit addresses and encapsulate 32 bit addresses in them? If so, how do you make sure that the address format is unambiguous?&lt;br /&gt;
&lt;br /&gt;
* Currently, only the device&#039;s hardware type provides a clue as to what packet type responds to which protocol transported via the link. For Ethernet, IP packets are encapsulated in type 2048 frames, PPP encapsulates IP packets in type 31 frames, Arcnet can use type 240 or 212. Matching a protocol with a frame type is not an easy process which could be handled more elegantly.&lt;br /&gt;
&lt;br /&gt;
* How to extend the &amp;lt;tt&amp;gt;Sana2DeviceQuery&amp;lt;/tt&amp;gt; structure in the future? The current layout separates standard, common and format specific information, but there is no hint as to where which each section starts and where the next begins. Now that there is a proposal to add a new field to the common section, how would you add fields to the format specific section?&lt;br /&gt;
&lt;br /&gt;
= SANA-II network device driver Autodocs =&lt;br /&gt;
&lt;br /&gt;
== AbortIO ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        AbortIO -- Remove an existing device request.&lt;br /&gt;
&lt;br /&gt;
   SYNOPSIS&lt;br /&gt;
        error = AbortIO(Sana2Req)&lt;br /&gt;
        D0              A1&lt;br /&gt;
&lt;br /&gt;
        LONG AbortIO(struct IOSana2Req *);&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This is an exec.library call.&lt;br /&gt;
&lt;br /&gt;
        This function aborts an ioRequest. If the request is active, it may or&lt;br /&gt;
        may not be aborted. If the request is queued it is removed. The&lt;br /&gt;
        request will be returned in the same way as if it had normally&lt;br /&gt;
        completed.  You must WaitIO() after AbortIO() for the request to&lt;br /&gt;
        return.&lt;br /&gt;
&lt;br /&gt;
   INPUTS&lt;br /&gt;
        Sana2Req        - Sana2Req to be aborted.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        error           - Zero if the request was aborted, non-zero otherwise.&lt;br /&gt;
                          io_Error in Sana2Req will be set to IOERR_ABORTED&lt;br /&gt;
                          if it was aborted.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        exec.library/AbortIO(), exec.library/WaitIO()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== CloseDevice ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        CloseDevice -- Close the device.&lt;br /&gt;
&lt;br /&gt;
   SYNOPSIS&lt;br /&gt;
        CloseDevice(Sana2Req)&lt;br /&gt;
                    A1&lt;br /&gt;
&lt;br /&gt;
        void CloseDevice(struct IOSana2Req *);&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This function is called by exec.library CloseDevice().&lt;br /&gt;
&lt;br /&gt;
        This function performs whatever cleanup is required at device closes.&lt;br /&gt;
&lt;br /&gt;
        Note that all IORequests MUST be complete before closing. If any are&lt;br /&gt;
        pending, your program must AbortIO() then WaitIO() each outstanding&lt;br /&gt;
        IORequest to complete them.&lt;br /&gt;
&lt;br /&gt;
   INPUTS&lt;br /&gt;
        Sana2Req        - Pointer to IOSana2Req initialized by OpenDevice().&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        exec.library/CloseDevice(), exec.library/OpenDevice()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== CMD_CLEAR ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        CMD_CLEAR -- Clear internal network interface read buffers.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        There are no device internal buffers, so CMD_CLEAR does not apply to&lt;br /&gt;
        this class of device.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - CMD_CLEAR.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - IOERR_NOCMD.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== CMD_FLUSH ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        CMD_FLUSH -- Clear all queued I/O requests for the SANA-II device.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command aborts all I/O requests in both the read and write&lt;br /&gt;
        request queues of the device.  All pending I/O requests are&lt;br /&gt;
        returned with an error message (IOERR_ABORTED).  CMD_FLUSH does not&lt;br /&gt;
        affect active requests.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - CMD_FLUSH.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - Zero if successful; non-zero otherwise.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== CMD_INVALID ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        CMD_INVALID -- Return with error IOERR_NOCMD.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command causes device driver to reply with an error IOERR_NOCMD&lt;br /&gt;
        as defined in &amp;amp;lt;exec/errors.h&amp;amp;gt; indicating the command is not supported.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - CMD_INVALID.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - IOERR_NOCMD.&lt;br /&gt;
&lt;br /&gt;
   BUGS&lt;br /&gt;
        Not known to be useful.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== CMD_READ ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        CMD_READ -- Get a packet from the network.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        Get the next packet available of the requested packet type. The data&lt;br /&gt;
        copied (via a call to the requestor-provided CopyToBuffer function)&lt;br /&gt;
        into ios2_Data is normally the Data Link Layer packet data only. If&lt;br /&gt;
        bit SANA2IOB_RAW is set in ios2_Flags, then the entire physical frame&lt;br /&gt;
        will be returned.&lt;br /&gt;
&lt;br /&gt;
        Unlike most Exec devices, SANA-II device drivers do not have internal&lt;br /&gt;
        buffers.  If you wish to read data from a SANA-II device you should&lt;br /&gt;
        have multiple CMD_READ requests pending at any given time.  The&lt;br /&gt;
        functions provided by you the requestor will be used for any incoming&lt;br /&gt;
        packets of the type you&#039;ve requested.  If no read requests are&lt;br /&gt;
        outstanding for a type which comes in and no read_orphan requests are&lt;br /&gt;
        outstanding, the packet will be lost.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - CMD_READ&lt;br /&gt;
        ios2_Flags      - Supported flags are:&lt;br /&gt;
                            SANA2IOB_RAW&lt;br /&gt;
                            SANA2IOB_QUICK&lt;br /&gt;
        ios2_PacketType - Packet type desired.&lt;br /&gt;
        ios2_Data       - Abstract data structure to hold packet data.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - Zero if successful; non-zero otherwise.&lt;br /&gt;
        ios2_WireError  - More specific error number.&lt;br /&gt;
        ios2_Flags      - The following flags may be returned:&lt;br /&gt;
                            SANA2IOB_RAW&lt;br /&gt;
                            SANA2IOB_BCAST&lt;br /&gt;
                            SANA2IOB_MCAST&lt;br /&gt;
        ios2_SrcAddr    - Source interface address of packet.&lt;br /&gt;
        ios2_DstAddr    - Destination interface address of packet.&lt;br /&gt;
        ios2_DataLength - Length of packet data.&lt;br /&gt;
        ios2_Data       - Abstract data structure which packet data is&lt;br /&gt;
                          contained in.&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        The driver may not directly examine or modify anything pointed to by&lt;br /&gt;
        ios2_Data.  It *must* use the requester-provided functions to access&lt;br /&gt;
        this data.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        S2_READORPHAN, CMD_WRITE, any_protocol/CopyToBuffer&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== CMD_RESET ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        CMD_RESET -- Reset the network interface to initialized state.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        Currently, SANA-II devices can only be configured once (with&lt;br /&gt;
        CMD_CONFIGINTERFACE) and cannot be re-configured, hence,&lt;br /&gt;
        CMD_RESET does not apply to this class of device.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - CMD_RESET.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - IOERR_NOCMD.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== CMD_START ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        CMD_START -- Restart device operation.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        There is no way for the driver to keep queuing requests without&lt;br /&gt;
        servicing them, so CMD_STOP does not apply to this class of device.&lt;br /&gt;
        S2_OFFLINE and S2_ONLINE do perform a similar function to CMD_STOP&lt;br /&gt;
        and CMD_START&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - CMD_START.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - IOERR_NOCMD.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        S2_ONLINE, S2_OFFLINE&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== CMD_STOP ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        CMD_STOP -- Pause device operation.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        There is no way for the driver to keep queuing requests without&lt;br /&gt;
        servicing them, so CMD_STOP does not apply to this class of device.&lt;br /&gt;
        S2_OFFLINE and S2_ONLINE do perform a similar function to CMD_STOP&lt;br /&gt;
        and CMD_START&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - CMD_STOP.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - IOERR_NOCMD.&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        S2_ONLINE, S2_OFFLINE&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== CMD_UPDATE ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        CMD_UPDATE -- Force packets out to device.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        Since there are no device internal buffers, CMD_UPDATE does not&lt;br /&gt;
        apply to this class of device.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - CMD_UPDATE.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - IOERR_NOCMD.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== CMD_WRITE ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        CMD_WRITE -- Send packet to the network.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command causes the packet to be sent to the specified network&lt;br /&gt;
        interface. Normally, appropriate packet header and trailer information&lt;br /&gt;
        will be added to the packet data when it is sent.  If bit SANA2IOB_RAW&lt;br /&gt;
        is set in io_Flags, then the ios2_Data is assumed to contain an entire&lt;br /&gt;
        physical frame and will be sent (copied to the wire via&lt;br /&gt;
        CopyFromBuffer() unmodified.&lt;br /&gt;
&lt;br /&gt;
        Note that the device should not check to see if the destination&lt;br /&gt;
        address is on the local hardware.  Network protocols should realize&lt;br /&gt;
        that the packet has a local destination long before it gets to a&lt;br /&gt;
        SANA-II driver.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - CMD_WRITE.&lt;br /&gt;
        ios2_Flags      - Supported flags are:&lt;br /&gt;
                            SANA2IOB_RAW&lt;br /&gt;
                            SANA2IOB_QUICK&lt;br /&gt;
        ios2_PacketType - Packet type to send.&lt;br /&gt;
        ios2_DstAddr    - Destination interface address for this packet.&lt;br /&gt;
        ios2_DataLength - Length of the Data to be sent.&lt;br /&gt;
        ios2_Data       - Abstract data structure which packet data is&lt;br /&gt;
                          contained in.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - Zero if successful; non-zero otherwise.&lt;br /&gt;
        ios2_WireError  - More specific error number.&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        The driver may not directly examine or modify anything pointed to by&lt;br /&gt;
        ios2_Data.  It *must* use the requester-provided functions to access&lt;br /&gt;
        this data.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        CMD_READ, S2_BROADCAST, S2_MULTICAST, any_protocol/CopyFromBuffer&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== OpenDevice ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        Open -- Request an opening of the network device.&lt;br /&gt;
&lt;br /&gt;
   SYNOPSIS&lt;br /&gt;
        error = OpenDevice(unit, IOSana2Req, flags)&lt;br /&gt;
        D0                 D0    A1          D1&lt;br /&gt;
&lt;br /&gt;
        BYTE OpenDevice(ULONG, struct IOSana2Req *, ULONG);&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This function is called by exec.library OpenDevice().&lt;br /&gt;
&lt;br /&gt;
        This function performs whatever initialization is required per&lt;br /&gt;
        device open and initializes the Sana2Req for use by the&lt;br /&gt;
        device.&lt;br /&gt;
&lt;br /&gt;
   INPUTS&lt;br /&gt;
        unit            - Device unit to open.&lt;br /&gt;
        Sana2Req        - Pointer to IOSana2Req structure to be initialized by&lt;br /&gt;
                          the sana2.device.&lt;br /&gt;
        flags           - Supported flags are:&lt;br /&gt;
                                SANA2OPB_MINE&lt;br /&gt;
                                SANA2OPB_PROM&lt;br /&gt;
        ios2_BufferManagement   - A pointer to a tag list containing&lt;br /&gt;
                                  pointers to buffer management functions.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        error           - same as io_Error&lt;br /&gt;
        io_Error        - Zero if successful; non-zero otherwise.&lt;br /&gt;
        io_Device       - A pointer to whatever device will handle the calls&lt;br /&gt;
                          for this unit.  This pointer may be different&lt;br /&gt;
                          depending on what unit is requested.&lt;br /&gt;
        ios2_BufferManagement   - A pointer to device internal information&lt;br /&gt;
                                  used to call buffer management functions.&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        A SANA-II device must reject all open requests with a request&lt;br /&gt;
        structure that is too short, e.g. an IOStdReq. A simple check of the&lt;br /&gt;
        mn_Length field in the Message part of the request is needed to make&lt;br /&gt;
        sure that a device does not dereference invalid data due to a wrong&lt;br /&gt;
        device configuration.&lt;br /&gt;
&lt;br /&gt;
        A SANA-II device may open if no buffer management tags are provided to&lt;br /&gt;
        make the configuration process and obtaining statistics easier. Buffer&lt;br /&gt;
        management tags with a NULL value must be treated as not specified.&lt;br /&gt;
        The device shall fail requests gracefully depending on the missing&lt;br /&gt;
        tags in this case. Any malfunction is not acceptable.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        exec.library/OpenDevice(), exec.library/CloseDevice()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_ADDMULTICASTADDRESS ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_ADDMULTICASTADDRESS -- Enable an interface multicast address.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command causes the device driver to enable multicast packet&lt;br /&gt;
        reception for the requested address.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - S2_ADDMULTICASTADDRESS.&lt;br /&gt;
        ios2_SrcAddr    - Multicast address to enable.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - Zero if successful; non-zero otherwise.&lt;br /&gt;
        ios2_WireError  - More specific error number.&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        Multicast addresses are added globally -- anyone using the device&lt;br /&gt;
        may receive packets as a result of any multicast address which has&lt;br /&gt;
        been added for the device.&lt;br /&gt;
&lt;br /&gt;
        Since multicast addresses are not &amp;amp;quot;bound&amp;amp;quot; to a particular packet type,&lt;br /&gt;
        each enabled multicast address has an &amp;amp;quot;enabled&amp;amp;quot; count associated with&lt;br /&gt;
        it so that if two protocols add the same multicast address and later&lt;br /&gt;
        one removes it, it is still enabled until the second removes it.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        S2_MULTICAST, S2_DELMULTICASTADDRESS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_BROADCAST ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_BROADCAST -- Broadcast a packet on network.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command works the same as CMD_WRITE except that it also performs&lt;br /&gt;
        whatever special processing of the packet is required to do a&lt;br /&gt;
        broadcast send. The actual broadcast mechanism is neccessarily&lt;br /&gt;
        network/interface/device specific.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - S2_BROADCAST.&lt;br /&gt;
        ios2_Flags      - Supported flags are:&lt;br /&gt;
                                SANA2IOB_RAW&lt;br /&gt;
                                SANA2IOB_QUICK&lt;br /&gt;
        ios2_PacketType - Packet type to send.&lt;br /&gt;
        ios2_DataLength - Length of the Data to be sent.&lt;br /&gt;
        ios2_Data       - Abstract data structure which packet data is&lt;br /&gt;
                          contained in.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_DstAddr    - The contents of this field are to be&lt;br /&gt;
                          considered trash upon return of the IOReq.&lt;br /&gt;
        ios2_Error      - Zero if successful; non-zero otherwise.&lt;br /&gt;
                          This command can fail for many reasons and&lt;br /&gt;
                          is not supported by all networks and/or&lt;br /&gt;
                          network interfaces.&lt;br /&gt;
        ios2_WireError  - More specific error number.&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        The DstAddr field may be trashed by the driver because this function&lt;br /&gt;
        may be implemented by filling DstAddr with a broadcast address and&lt;br /&gt;
        internally calling CMD_WRITE.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        CMD_WRITE, S2_MULTICAST&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_CONFIGINTERFACE ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_CONFIGINTERFACE -- Configure the network interface.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command causes the device driver to initialize the interface&lt;br /&gt;
        hardware and to set the network interface address to the address in&lt;br /&gt;
        ios2_SrcAddr. This command can only be executed once and, if&lt;br /&gt;
        successful, will leave the driver and network interface fully&lt;br /&gt;
        operational and the network interface in ios2_SrcAddr.&lt;br /&gt;
&lt;br /&gt;
        To set the interface address to the factory address, the network&lt;br /&gt;
        management software must use GetStationAddress first and then call&lt;br /&gt;
        ConfigInterface with the result. If there is no factory address then&lt;br /&gt;
        the network software must pick an address to use.&lt;br /&gt;
&lt;br /&gt;
        Until this command is executed the device will not listen for any&lt;br /&gt;
        packets on the hardware.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - S2_CONFIGINTERFACE.&lt;br /&gt;
        ios2_Flags      - Supported flags are:&lt;br /&gt;
                                SANA2IOB_QUICK&lt;br /&gt;
        ios2_SrcAddr    - Address for this interface.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - Zero if successful; non-zero otherwise.&lt;br /&gt;
        ios2_WireError  - More specific error number.&lt;br /&gt;
        ios2_SrcAddr    - Address of this interface as configured.&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        Some networks have the interfaces choose a currently unused interface&lt;br /&gt;
        address each time the interface is initialized. The caller must check&lt;br /&gt;
        ios2_SrcAddr for the actual interface address after configuring the&lt;br /&gt;
        interface.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        S2_GETSTATIONADDRESS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_CONNECT ==&lt;br /&gt;
&lt;br /&gt;
The driver model specified by the SANA-II standard really only covers networking hardware well. Software-only drivers, such as for dial-up networking, are, well, somehow mentioned in the standard, but they don&#039;t receive much attention. In particular, this means that a networking driver is assumed to be practically always attached to its link layer and no provisions exist to specify what kind of link layer that might be and how it might be accessed. This small oversight can probably be explained by the fact that at the time the SANA-II standard was adopted, dial-up networking had not yet gained the prominence it has today.&lt;br /&gt;
&lt;br /&gt;
To bridge this gap, I propose a new command which will make a driver connect to its link layer and go online, which uses the following data structure:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct Sana2Connection&lt;br /&gt;
{&lt;br /&gt;
   ULONG          s2c_Size;&lt;br /&gt;
   struct MinList s2c_Options;&lt;br /&gt;
   struct Hook    s2c_ErrorHook;&lt;br /&gt;
   struct Hook    s2c_ConnectHook;&lt;br /&gt;
   struct Hook    s2c_DisconnectHook;&lt;br /&gt;
   STRPTR         s2c_Login;&lt;br /&gt;
   STRPTR         s2c_Password;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The individual structure members have the following purposes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2c_Size&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The size of the entire data structure is stored here. This value &#039;&#039;&#039;must&#039;&#039;&#039; be &amp;amp;gt;= 84. Smaller values &#039;&#039;&#039;must&#039;&#039;&#039; be rejected with &amp;lt;tt&amp;gt;ios2_Req.io_Error&amp;lt;/tt&amp;gt;=&amp;lt;tt&amp;gt;IOERR_BADLENGTH&amp;lt;/tt&amp;gt;. The purpose of &amp;lt;tt&amp;gt;s2c_Size&amp;lt;/tt&amp;gt; is to allow for future expansion during which the structure may grow in size.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2c_Options&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This list contains options, to be used during the connection process. Each node has the following format:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct Sana2ConnectionOption&lt;br /&gt;
{&lt;br /&gt;
   struct MinNode s2co_MinNode;&lt;br /&gt;
   STRPTR         s2co_Name;&lt;br /&gt;
   STRPTR         s2co_Value;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;s2co_Name&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;s2co_Value&amp;lt;/tt&amp;gt; entries point to &amp;lt;tt&amp;gt;NUL&amp;lt;/tt&amp;gt;-terminated strings, which contain the name and the value of a parameter. &#039;&#039;Note that for numeric values, the respective number will be encoded in a text string.&#039;&#039; A number of parameters are reserved, which are [[#s2c_options|listed later]] in this text.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2c_ErrorHook&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This hook is called whenever an error message is to be reported during the connection/disconnection process. The hook function is invoked using the following parameters:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;error_hook_func(hook,reserved,message);&lt;br /&gt;
&lt;br /&gt;
VOID error_hook_func(struct Hook *hook,APTR reserved,&lt;br /&gt;
                     STRPTR message);&amp;lt;/pre&amp;gt;&lt;br /&gt;
The &amp;lt;tt&amp;gt;reserved&amp;lt;/tt&amp;gt; parameter &#039;&#039;&#039;must&#039;&#039;&#039; be &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt;. The &amp;lt;tt&amp;gt;message&amp;lt;/tt&amp;gt; parameter points to a &amp;lt;tt&amp;gt;NUL&amp;lt;/tt&amp;gt;-terminated string. It &#039;&#039;&#039;must not&#039;&#039;&#039; be &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Because the hook function may have to allocate memory, it &#039;&#039;&#039;must not&#039;&#039;&#039; be called from interrupt code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2c_ConnectHook&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This hook is called when the link level device has been set up, but further initializations are necessary, such as telling a modem to dial out. The hook function is invoked with the following parameters:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
success = connect_hook_func(hook,reserved,s2cm);&lt;br /&gt;
&lt;br /&gt;
BOOL connect_hook_func(struct Hook *hook,APTR reserved,&lt;br /&gt;
                       struct Sana2ConnectionMessage *s2cm);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;reserved&amp;lt;/tt&amp;gt; parameter &#039;&#039;&#039;must&#039;&#039;&#039; be &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt;. The &amp;lt;tt&amp;gt;s2cm&amp;lt;/tt&amp;gt; parameter points to a data structure, as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct Sana2ConnectionMessage&lt;br /&gt;
{&lt;br /&gt;
   ULONG                    s2cm_Size;&lt;br /&gt;
   struct Sana2Connection * s2cm_Connection;&lt;br /&gt;
   struct IORequest *       s2cm_Request[2];&lt;br /&gt;
   LONG                     s2cm_RequestType;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this structure, the members have the following purposes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2cm_Size&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The size of this data structure; it &#039;&#039;&#039;must&#039;&#039;&#039; be at least 20 bytes in size. The purpose of &amp;lt;tt&amp;gt;s2cm_Size&amp;lt;/tt&amp;gt; is to allow for future expansion, which may cause the size of this structure to grow.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2cm_Connection&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This points back to the &amp;lt;tt&amp;gt;Sana2Connection&amp;lt;/tt&amp;gt; structure which the hook that was invoked with the &amp;lt;tt&amp;gt;Sana2ConnectionMessage&amp;lt;/tt&amp;gt; is embedded in.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2cm_Request&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here you will find two I/O requests which can be used for reading and writing data to the link layer. These pointers &#039;&#039;&#039;must not&#039;&#039;&#039; be &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; and they &#039;&#039;&#039;must&#039;&#039;&#039; refer to different I/O requests, it is not permitted to pass the same request twice.&lt;br /&gt;
&lt;br /&gt;
The dialer can use these requests for communicating with the modem, but it is also permitted to clone these requests by creating new I/O requests of the same size, copying the original contents and filling in different reply ports.&lt;br /&gt;
&lt;br /&gt;
There is a danger in that the hook code may not receive the right kind of I/O request, which is why the &amp;lt;tt&amp;gt;s2cm_RequestType&amp;lt;/tt&amp;gt; field identifies the kind of device the requests were created for.&lt;br /&gt;
&lt;br /&gt;
When the hook function returns, it &#039;&#039;&#039;must&#039;&#039;&#039; make sure that none of the I/O requests are still pending, i.e. asynchronous I/O &#039;&#039;&#039;must&#039;&#039;&#039; have been stopped.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2cm_RequestType&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This identifies the type of device the I/O requests passed in &amp;lt;tt&amp;gt;s2cm_Request&amp;lt;/tt&amp;gt; were created for. Possible values for this entry come from the New Style Device specification, e.g. &amp;lt;tt&amp;gt;NSDEVTYPE_SERIAL&amp;lt;/tt&amp;gt; for a &amp;lt;tt&amp;gt;serial.device&amp;lt;/tt&amp;gt;-like device or &amp;lt;tt&amp;gt;NSDEVTYPE_SANA2&amp;lt;/tt&amp;gt; for a networking driver.&lt;br /&gt;
&lt;br /&gt;
The hook function &#039;&#039;&#039;must&#039;&#039;&#039; return &amp;lt;tt&amp;gt;TRUE&amp;lt;/tt&amp;gt; if the connection could be established, and &amp;lt;tt&amp;gt;FALSE&amp;lt;/tt&amp;gt; otherwise. Note that it is &#039;&#039;not&#039;&#039; sufficient to just return &amp;lt;tt&amp;gt;FALSE&amp;lt;/tt&amp;gt; in case of failure. Your code &#039;&#039;&#039;must&#039;&#039;&#039; have called the &amp;lt;tt&amp;gt;s2c_ErrorHook&amp;lt;/tt&amp;gt; with an explanation why things went wrong first.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2c_DisconnectHook&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This hook is called by &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt; when the connection could not be established (the &amp;lt;tt&amp;gt;s2c_ConnectHook&amp;lt;/tt&amp;gt; returned &amp;lt;tt&amp;gt;FALSE&amp;lt;/tt&amp;gt;), or by &amp;lt;tt&amp;gt;S2_DISCONNECT&amp;lt;/tt&amp;gt;, shortly before the link level device is to be closed. The hook function is invoked with the following parameters:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
disconnect_hook_func(hook,reserved,s2cm);&lt;br /&gt;
&lt;br /&gt;
VOID disconnect_hook_func(struct Hook *hook,APTR reserved,&lt;br /&gt;
                          struct Sana2ConnectionMessage *s2cm);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;reserved&amp;lt;/tt&amp;gt; parameter &#039;&#039;&#039;must&#039;&#039;&#039; be &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt;. The &amp;lt;tt&amp;gt;s2cm&amp;lt;/tt&amp;gt; parameter points to a data structure, as was described for the &amp;lt;tt&amp;gt;s2c_ConnectHook&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2c_Login&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2c_Password&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The purpose of these entries is to transport the authentication information the protocol may require. These entries are either &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; or contain pointers to &amp;lt;tt&amp;gt;NUL&amp;lt;/tt&amp;gt;-terminated strings. If &amp;lt;tt&amp;gt;s2c_Login&amp;lt;/tt&amp;gt; is &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt;, then both login and password &#039;&#039;&#039;must&#039;&#039;&#039; be assumed to be empty. If &amp;lt;tt&amp;gt;s2c_Login&amp;lt;/tt&amp;gt; is not &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;s2c_Password&amp;lt;/tt&amp;gt; is &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt;, then the password &#039;&#039;&#039;must&#039;&#039;&#039; be assumed to be empty.&lt;br /&gt;
&lt;br /&gt;
The list of options in &amp;lt;tt&amp;gt;s2c_Options&amp;lt;/tt&amp;gt; supplies the necessary information on how the driver is to connect to the link layer. Each node contains an option, which bears a name and contains a value. This pair is what I call a &#039;&#039;parameter&#039;&#039;. A number of parameter names are reserved, as will be listed below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp&amp;lt;/tt&amp;gt;.async.device&lt;br /&gt;
&lt;br /&gt;
Name of device driver to use for asynchronous PPP.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;serial.device&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp&amp;lt;/tt&amp;gt;.async.unit&lt;br /&gt;
&lt;br /&gt;
Device unit number to use for asynchronous PPP.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp&amp;lt;/tt&amp;gt;.async.speed&lt;br /&gt;
&lt;br /&gt;
Transmission speed to use for asynchronous PPP in bits per second.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;115200&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.async.buffersize&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Receive buffer size for asynchronous PPP.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;50000&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.async.checkcarrier&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whether the carrier signal of the link layer should be tested or not. This can be either 0 (do not test) or 1 (test the carrier signal).&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.async.rtscts&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whether or not hardware handshaking should be used by the link layer. This can be either &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; (off) or &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; (on).&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.async.shared&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whether or not the link layer device should be opened in shared mode. This can be either &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; (off) or &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; (on).&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.async.nullmodem&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whether or not the link layer is a direct connection, such as a nullmodem. This can be either &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; (off) or &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; (on).&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.async.eof&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whether or not the underlying serial device driver&#039;s &#039;EOF mode&#039; should be enabled. This can be either &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; (off) or &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; (on).&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.async.readrequests&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Number of read requests to be used for asynchronous PPP.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;16&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.async.writerequests&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Number of write requests to be used for asynchronous PPP.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;16&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.async.accm&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Asynchronous control character map, expressed as a hexadecimal value.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;$000A0000&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.async.pfc&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whether or not protocol field compression should be used. This can be either &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; (off) or &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; (on).&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.async.aacfc&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whether or not address and control field compression should be used. This can be either &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; (off) or &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; (on).&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.async.vjhc&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whether or not Van Jacobson header compression should be used. This can be either &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; (off) or &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; (on).&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.async.ignorefcs&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whether or not frame check sequences should be ignored upon reception. This can be either &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; (off) or &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; (on).&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.async.initialize&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The modem initialization command, with embedded control sequences, if possible.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;AT\r&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.async.dial&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The modem dial command, with embedded control sequences, if possible.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;ATD12345\r&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.async.dialtimeout&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The dial timeout, i.e. the number of seconds to wait after the dial command has been sent for the modem to establish a connection.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;60&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.async.hangup&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The modem hangup command, with embedded control sequences, if possible.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;ATH0\r&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.idletimeout&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Number of seconds the local host may remain idle, i.e. send no data to the peer, before a watchdog timeout elapses and proceeds to verify that the line is still operational.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;30&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.localaddress&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The IP address to assign to the local host, as part of the PPP negotiation process. This must be given in dotted decimal notation (RFC1700).&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;1.2.3.4&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.remoteaddress&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The IP address to assume for the peer, as part of the PPP negotiation process. This must be given in dotted decimal notation (RFC1700).&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;1.2.3.4&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.dns1address&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The IP address to be used by the primary domain name server, as part of the PPP negotiation process. This must be given in dotted decimal notation (RFC1700).&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;1.2.3.4&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.dns2address&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The IP address to be used by the secondary domain name server, as part of the PPP negotiation process. This must be given in dotted decimal notation (RFC1700).&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;1.2.3.4&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.maxfail&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The maximum number of negative configuration acknowledgements to be sent before the PPP negotiation process switches to reject those options.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;5&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.maxterm&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The maximum number of termination requests to be sent before the respective PPP network or link protocol gives up.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;2&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.maxconfig&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The maximum number of configuration requests to be sent before the respective PPP network or link protocol gives up.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;10&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.timeout&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The number of seconds that have to pass before the respective PPP network or link protocol will retry to do whatever didn&#039;t work during the last attempt.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;3&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.mtu&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The maximum transmission unit to use.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;1500&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.peeridletimeout&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Number of seconds the peer may remain idle, i.e. send no data to the local host, before a watchdog timeout elapses and proceeds to verify that the line is still operational.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;30&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.rejectpap&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whether or not the Password Authentication Protocol should be accepted, if offered by the peer. This can be either &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; (accept) or &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; (reject).&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.sendid&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A flag which controls whether the local host should send LCP identification packets or not. This can be either &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; (off) or &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; (on).&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.pap.timeout&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The Password Authentication Protocol requires that the server answers to the client&#039;s request to log in. The server may be unable to respond immediately, which means that the client will have to repeat its request. A short delay should separate each request sent, such as three seconds.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;3&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.pap.retry&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the client does not manage to authenticate with the server immediately, it may resend the authentication request several times. But the attempts have to stop eventually, such as after having resent the message ten times.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;10&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.dummyremoteaddress&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whether or not the PPP driver should make up an IP address if the peer refuses to state its own IP address.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;logfile&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The name of a log file to create. If the file already exists, then new data should be appended to it.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;t:logfile&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;logoptions&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A list of options which control what exactly should be logged.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.ethernet.device&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Name of device driver to use for PPPoE (PPP over Ethernet).&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;a2065.device&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.ethernet.unit&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Device unit number to use for PPPoE.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.ethernet.raw&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whether or not raw link layer frames should be constructed for transmission or not. This can be either &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; (off) or &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; (on).&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.ethernet.bypass&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whether or not the IP packet transmission and reception should bypass several copying steps. This can be either &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; (off) or &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; (on).&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.ethernet.readpackets&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The number of read requests to queue for the link layer.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;16&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.ethernet.writepackets&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The number of write requests to queue for the link layer.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;16&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.ethernet.service&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The name of the PPPoE service to request.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;?&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.ethernet.ac&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The name of the PPPoE access concentrator to request.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;?&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.ethernet.connecttimeout&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The number of seconds to wait for the PPPoE server to allow a session to be opened.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;3&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
While this list of parameters may suggest that the command described above can be used solely with the PPP protocol, do not let that put you off. This list is merely the starting point, but it is not set in stone that it cannot be extended.&lt;br /&gt;
&lt;br /&gt;
The names of the parameters are not case sensitive. As the names suggest, the name space itself is hierarchic in construction, i.e. everything related to the PPP protocol bears a name starting with the letters &#039;ppp&#039; with the dot &#039;.&#039; separating the individual items. By this rule, ppp.async refers to options that concern asynchronous PPP and ppp.ethernet to options that concern PPP over Ethernet wire.&lt;br /&gt;
&lt;br /&gt;
To add your own parameter, register it with the maintainer of the SANA-II standard or prefix its name with the letters &#039;x-&#039;. For example, to use your own kind of &#039;ppp.ethernet.connecttimeout&#039; parameter, change the name of the last component like this: ppp.ethernet.x-connecttimeout. No officially-registered parameter will ever begin with the prefix &#039;x-&#039;.&lt;br /&gt;
&lt;br /&gt;
The command should work as follows:&lt;br /&gt;
&lt;br /&gt;
# The client must set up the &amp;lt;tt&amp;gt;Sana2Connection&amp;lt;/tt&amp;gt; data structure, initialize the &amp;lt;tt&amp;gt;s2c_Size&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;s2c_Options&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;s2c_ErrorHook&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;s2c_ConnectHook&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;s2c_DisconnectHook&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;s2c_Login&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;s2c_Password&amp;lt;/tt&amp;gt; fields.&lt;br /&gt;
# The connection options must be filled in, which means that nodes containing the respective information must be stored in the &amp;lt;tt&amp;gt;s2c_Options&amp;lt;/tt&amp;gt; list. The client must make sure that the syntax of the parameters conforms to the specifications described above.&lt;br /&gt;
# A pointer to the &amp;lt;tt&amp;gt;Sana2Connection&amp;lt;/tt&amp;gt; data structure is placed in the &amp;lt;tt&amp;gt;ios2_Data&amp;lt;/tt&amp;gt; member of an &amp;lt;tt&amp;gt;IOSana2Req&amp;lt;/tt&amp;gt;, the command is set to &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt; and the request is sent via &amp;lt;tt&amp;gt;DoIO()&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;SendIO()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
# The driver receives the request and begins to examine the contents of the &amp;lt;tt&amp;gt;s2c_Options&amp;lt;/tt&amp;gt; list, as provided in the data structure pointed to by the &amp;lt;tt&amp;gt;ios2_Data&amp;lt;/tt&amp;gt; member of the request. Unknown options are ignored, options whose values do not conform to the syntax specification are rejected; this is done by calling the &amp;lt;tt&amp;gt;s2c_ErrorHook&amp;lt;/tt&amp;gt; with an error message referring to the option in question and by returning the &amp;lt;tt&amp;gt;IOSana2Req&amp;lt;/tt&amp;gt; with an error code of &amp;lt;tt&amp;gt;S2ERR_BAD_ARGUMENT&amp;lt;/tt&amp;gt; and wire error code of &amp;lt;tt&amp;gt;S2WERR_INVALID_OPTION&amp;lt;/tt&amp;gt;.&lt;br /&gt;
# If the options are all in good order, the driver proceeds to verify that all mandatory options are provided. If this is not the case, the &amp;lt;tt&amp;gt;s2c_ErrorHook&amp;lt;/tt&amp;gt; is called with an error message referring to the option in question and the &amp;lt;tt&amp;gt;IOSana2Req&amp;lt;/tt&amp;gt; is returned with an error code of &amp;lt;tt&amp;gt;S2ERR_BAD_ARGUMENT&amp;lt;/tt&amp;gt; and wire error code of &amp;lt;tt&amp;gt;S2WERR_MISSING_OPTION&amp;lt;/tt&amp;gt;.&lt;br /&gt;
# The driver proceeds to do its local initialization, which involves opening the link layer device, etc. If this initialization fails, the &amp;lt;tt&amp;gt;s2c_ErrorHook&amp;lt;/tt&amp;gt; is called with an error message referring to the problem and the &amp;lt;tt&amp;gt;IOSana2Req&amp;lt;/tt&amp;gt; is returned with an appropriate error code.&lt;br /&gt;
# When the initialization has finished, the driver may invoke the &amp;lt;tt&amp;gt;s2c_ConnectHook&amp;lt;/tt&amp;gt; callback. Some drivers may require this, such as asynchronous PPP, some may not, such as PPPoE. The purpose of the hook function is to give the client a chance to perform modem initializations and connect to the peer. If the &amp;lt;tt&amp;gt;s2c_ConnectHook&amp;lt;/tt&amp;gt; cannot perform its duties, it has to invoke the &amp;lt;tt&amp;gt;s2c_ErrorHook&amp;lt;/tt&amp;gt; with an error message and eventually return &amp;lt;tt&amp;gt;FALSE&amp;lt;/tt&amp;gt;. If &amp;lt;tt&amp;gt;FALSE&amp;lt;/tt&amp;gt; is returned, the driver must invoke the &amp;lt;tt&amp;gt;s2c_DisconnectHook&amp;lt;/tt&amp;gt;, reverse any initializations it had made and eventually returned the &amp;lt;tt&amp;gt;IOSana2Req&amp;lt;/tt&amp;gt; with an appropriate error code. If the &amp;lt;tt&amp;gt;s2c_ConnectHook&amp;lt;/tt&amp;gt; returned &amp;lt;tt&amp;gt;TRUE&amp;lt;/tt&amp;gt;, then the driver must proceed with the actions that require that the link layer is operational. A protocol negotiation may follow, which, if successful, will make the driver return the &amp;lt;tt&amp;gt;IOSana2Req&amp;lt;/tt&amp;gt; with an error code of zero, indicating success. If successful, the SANA-II events &amp;lt;tt&amp;gt;S2EVENT_CONNECT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2EVENT_ONLINE&amp;lt;/tt&amp;gt; must be sent.&lt;br /&gt;
# The command will eventually return, but the client &#039;&#039;&#039;must not&#039;&#039;&#039; release the memory allocated for the &amp;lt;tt&amp;gt;Sana2Connection&amp;lt;/tt&amp;gt; structure and the option nodes in the &amp;lt;tt&amp;gt;s2c_Options&amp;lt;/tt&amp;gt; list. This is because the driver may have to invoke the &amp;lt;tt&amp;gt;s2c_DisconnectHook&amp;lt;/tt&amp;gt; hook due to the connection shutting down on its own accord.&lt;br /&gt;
&lt;br /&gt;
The connect and disconnect hook functions &#039;&#039;&#039;must not&#039;&#039;&#039; be called from interrupt code. For each hook only a &amp;lt;tt&amp;gt;Task&amp;lt;/tt&amp;gt; calling context of unknown priority must be assumed. Also, stack space is provided only to call &amp;lt;tt&amp;gt;exec.library&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;utility.library&amp;lt;/tt&amp;gt; functions. The callback shall not place excessive data on the stack. Stack space should be considered limited.&lt;br /&gt;
&lt;br /&gt;
I propose a command with the following semantics:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_CONNECT -- Establish a link layer connection and go&lt;br /&gt;
            online.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command is for use by networking devices which require&lt;br /&gt;
        a special link layer device to transmit their data, such as&lt;br /&gt;
        an asynchronous serial line and need to know about the&lt;br /&gt;
        configuration parameters necessary to open the connection.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command          - S2_CONNECT&lt;br /&gt;
        ios2_Data             - Pointer to Sana2Connection structure&lt;br /&gt;
        ios2_BufferManagement - Magic cookie as returned when opening the&lt;br /&gt;
                                driver with a struct IOSana2Req&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Req.io_Error - Zero if successful; non-zero otherwise&lt;br /&gt;
        ios2_WireError    - More specific error number&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        If successful, this command implies S2_ONLINE, i.e. the&lt;br /&gt;
        link layer is allocated and used by the driver.&lt;br /&gt;
&lt;br /&gt;
        The contents of the Sana2Connection structure must be valid&lt;br /&gt;
        until the connection is eventually shut down. The driver will&lt;br /&gt;
        need to cache it, so it must not be deallocated or otherwise&lt;br /&gt;
        modified.&lt;br /&gt;
&lt;br /&gt;
        Note that S2_ONLINE does not necessarily imply S2_CONNECT, if&lt;br /&gt;
        the S2_CONNECT command is listed as supported by the driver via&lt;br /&gt;
        NSCMD_DEVICEQUERY. If S2_CONNECT is not listed as supported,&lt;br /&gt;
        S2_ONLINE obviously implies connect functionality.&lt;br /&gt;
&lt;br /&gt;
        S2_CONNECT/S2_DISCONNECT do not nest.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        S2_DISCONNECT&amp;lt;/pre&amp;gt;&lt;br /&gt;
I propose that the following command number should be assigned:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;#define S2_CONNECT 0xC005&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_DELMULTICASTADDRESS ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_DELMULTICASTADDRESS -- Disable an interface multicast address.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command causes device driver to disable multicast packet&lt;br /&gt;
        reception for the requested address.&lt;br /&gt;
&lt;br /&gt;
        It is an error to disable a multicast address that is not enabled.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - S2_DELMULTICASTADDRESS&lt;br /&gt;
        ios2_SrcAddr    - Multicast address to disable.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - Zero if successful; non-zero otherwise.&lt;br /&gt;
        ios2_WireError  - More specific error number.&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        Multicast addresses are added globally -- anyone using the device&lt;br /&gt;
        may receive packets as a result of any multicast address which has&lt;br /&gt;
        been added for the device.&lt;br /&gt;
&lt;br /&gt;
        Since multicast addresses are not &amp;amp;quot;bound&amp;amp;quot; to a particular packet type,&lt;br /&gt;
        each enabled multicast address has an &amp;amp;quot;enabled&amp;amp;quot; count associated with&lt;br /&gt;
        it so that if two protocols add the same multicast address and later&lt;br /&gt;
        one removes it, it is still enabled until the second removes it.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        S2_ADDMULTICASTADDRESS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_DEVICEQUERY ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_DEVICEQUERY -- Return parameters for this network interface.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command causes the device driver to report information about the&lt;br /&gt;
        device. Up to SizeAvailable bytes of the information is copied&lt;br /&gt;
        into a buffer pointed to by ios2_StatData. The format of the data is&lt;br /&gt;
        as follows:&lt;br /&gt;
&lt;br /&gt;
            struct Sana2DeviceQuery&lt;br /&gt;
            {&lt;br /&gt;
            /*&lt;br /&gt;
            ** Standard information&lt;br /&gt;
            */&lt;br /&gt;
                ULONG SizeAvailble; /* bytes available */&lt;br /&gt;
                ULONG SizeSupplied; /* bytes supplied */&lt;br /&gt;
                ULONG DevQueryFormat;   /* this is type 0 */&lt;br /&gt;
                ULONG DeviceLevel;      /* this document is level 0 */&lt;br /&gt;
&lt;br /&gt;
            /*&lt;br /&gt;
            ** Common information&lt;br /&gt;
            */&lt;br /&gt;
                UWORD AddrFieldSize;    /* address size in bits */&lt;br /&gt;
                ULONG MTU;              /* maximum packet data size */&lt;br /&gt;
                ULONG bps;              /* line rate (bits/sec) */&lt;br /&gt;
                ULONG HardwareType;     /* what the wire is */&lt;br /&gt;
                ULONG RawMTU;           /* maximum raw packet data size */&lt;br /&gt;
&lt;br /&gt;
            /*&lt;br /&gt;
            ** Format specific information&lt;br /&gt;
            */&lt;br /&gt;
            };&lt;br /&gt;
&lt;br /&gt;
        The SizeAvailable specifies the number of bytes that the caller&lt;br /&gt;
        is prepared to accomodate, including the standard information fields.&lt;br /&gt;
&lt;br /&gt;
        SizeSupplied is the number of bytes actually supplied,&lt;br /&gt;
        including the standard information fields, which will not exceed&lt;br /&gt;
        SizeAvailable.&lt;br /&gt;
&lt;br /&gt;
        &amp;amp;lt;devices/sana2.h&amp;amp;gt; includes constants for these values.  If your&lt;br /&gt;
        hardware does not have a number assigned to it, you must contact&lt;br /&gt;
        the AmigaOS development team to get a hardware number.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - S2_DEVICEQUERY.&lt;br /&gt;
        ios2_StatData   - Pointer to Sana2DeviceQuery structure to fill in.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - Zero if successful; non-zero otherwise.&lt;br /&gt;
        ios2_WireError  - More specific error number.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_DISCONNECT ==&lt;br /&gt;
&lt;br /&gt;
This command complements &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt; in that it tears down a connection. It uses the same &amp;lt;tt&amp;gt;Sana2Connection&amp;lt;/tt&amp;gt; structure and hooks, but most of these members are ignored.&lt;br /&gt;
&lt;br /&gt;
The command should work as follows:&lt;br /&gt;
&lt;br /&gt;
# The client must set up the &amp;lt;tt&amp;gt;Sana2Connection&amp;lt;/tt&amp;gt; data structure, initialize the &amp;lt;tt&amp;gt;s2c_Size&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;s2c_Options&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;s2c_ErrorHook&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;s2c_ConnectHook&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;s2c_DisconnectHook&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;s2c_Login&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;s2c_Password&amp;lt;/tt&amp;gt; fields. The &amp;lt;tt&amp;gt;s2c_Options&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;s2c_ConnectHook&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;s2c_Login&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;s2c_Password&amp;lt;/tt&amp;gt; fields will be ignored, but the client should play things safe.&lt;br /&gt;
# A pointer to the &amp;lt;tt&amp;gt;Sana2Connection&amp;lt;/tt&amp;gt; data structure is placed in the &amp;lt;tt&amp;gt;ios2_Data&amp;lt;/tt&amp;gt; member of an &amp;lt;tt&amp;gt;IOSana2Req&amp;lt;/tt&amp;gt;, the command is set to &amp;lt;tt&amp;gt;S2_DISCONNECT&amp;lt;/tt&amp;gt; and the request is sent via &amp;lt;tt&amp;gt;DoIO()&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;SendIO()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
# The driver receives the request and proceeds to reverse the steps that previously allowed it to establish a connection. This includes telling the peer to shut down the link, but it does not include cleaning up the link layer device access, i.e. no I/O requests used for accessing a modem may be shut down yet.&lt;br /&gt;
# The &amp;lt;tt&amp;gt;s2c_DisconnectHook&amp;lt;/tt&amp;gt; may be invoked with the proper parameters. Some drivers, such as for asynchronous PPP, will need the hook to tell the modem to hang up the line. Some drivers, such as for PPPoE, may not need this hook and thus ignore it.&lt;br /&gt;
# The initialization is reversed completely, all resources allocated when the connection was previously opened are released. The &amp;lt;tt&amp;gt;IOSana2Req&amp;lt;/tt&amp;gt; is returned with an error code of zero, indicating success. The SANA-II event &amp;lt;tt&amp;gt;S2EVENT_DISCONNECT&amp;lt;/tt&amp;gt; must be sent, and, if necessary, &amp;lt;tt&amp;gt;S2EVENT_OFFLINE&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The connect and disconnect hook functions must not be called from interrupt code. For each hook only a &amp;lt;tt&amp;gt;Task&amp;lt;/tt&amp;gt; calling context of unknown priority must be assumed. Also, stack space is provided only to call &amp;lt;tt&amp;gt;exec.library&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;utility.library&amp;lt;/tt&amp;gt; functions. The callback shall not place excessive data on the stack. Stack space should be considered limited.&lt;br /&gt;
&lt;br /&gt;
I propose a command with the following semantics:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_DISCONNECT -- Go offline and close a link layer connection&lt;br /&gt;
            previously established with S2_CONNECT.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command complements the S2_CONNECT command in that it&lt;br /&gt;
        reverses the steps taken to establish a link layer connection.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command          - S2_DISCONNECT&lt;br /&gt;
        ios2_Data             - Pointer to Sana2Connection structure&lt;br /&gt;
        ios2_BufferManagement - Magic cookie as returned when opening the&lt;br /&gt;
                                driver with a struct IOSana2Req&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Req.io_Error - Zero if successful; non-zero otherwise&lt;br /&gt;
        ios2_WireError    - More specific error number&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        If successful, this command implies S2_OFFLINE, i.e. the&lt;br /&gt;
        link layer is deallocated.&lt;br /&gt;
&lt;br /&gt;
        The driver must ignore the S2_DISCONNECT command and&lt;br /&gt;
        recover gracefully if the S2_CONNECT was never sent or&lt;br /&gt;
        returned with an error.&lt;br /&gt;
&lt;br /&gt;
        The contents of the Sana2Connection structure are valid only&lt;br /&gt;
        until the device driver has processed the command and returned&lt;br /&gt;
        the IOSana2Req. Any data the driver may need to retain beyond&lt;br /&gt;
        that point of time must be copied.&lt;br /&gt;
&lt;br /&gt;
        Once the S2_DISCONNECT command has returned, it is safe to dispose&lt;br /&gt;
        of the Sana2Connection structure provided at S2_CONNECT time.&lt;br /&gt;
&lt;br /&gt;
        Note that S2_OFFLINE does not necessarily imply S2_DISCONNECT, if&lt;br /&gt;
        the S2_DISCONNECT command is listed as supported by the driver via&lt;br /&gt;
        NSCMD_DEVICEQUERY. If S2_DISCONNECT is not listed as supported,&lt;br /&gt;
        S2_OFFLINE obviously implies disconnect functionality.&lt;br /&gt;
&lt;br /&gt;
        S2_CONNECT/S2_DISCONNECT do not nest.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        S2_CONNECT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
I propose that the following command number should be assigned:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;#define S2_DISCONNECT 0xC006&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_GETDNSADDRESS ==&lt;br /&gt;
&lt;br /&gt;
The PPP negotiation process may produce information on which domain name and NetBIOS name servers are available to the client. I think that it is doubtful that the availability of NetBIOS name servers will be useful for Amiga software (let alone whether NetBIOS name resolution has a future), which is why I suggest that a SANA-II command for returning only the domain name servers is introduced.&lt;br /&gt;
&lt;br /&gt;
I propose a command with the following semantics:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_GETDNSADDRESS -- Obtain the addresses of the primary&lt;br /&gt;
           and secondary domain name servers.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        Obtain the addresses of the domain name servers available to the&lt;br /&gt;
        client using this driver&#039;s address.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command          - S2_GETDNSADDRESS&lt;br /&gt;
        ios2_Flags            - Supported flags are:&lt;br /&gt;
                                SANA2IOB_QUICK&lt;br /&gt;
        ios2_BufferManagement - Magic cookie as returned when opening the&lt;br /&gt;
                                driver with a struct IOSana2Req&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Req.io_Error - Zero if successful; non-zero otherwise&lt;br /&gt;
        ios2_WireError    - More specific error number&lt;br /&gt;
        ios2_SrcAddr      - Address of primary domain name server&lt;br /&gt;
        ios2_DstAddr      - Address of secondary domain name server&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        The size of the address returned by S2_GETPEERADDRESS must not be&lt;br /&gt;
        different from the size as returned by the S2_DEVICEQUERY command. For&lt;br /&gt;
        example, if a 32 bit IPv4 address was advertized, the driver must not&lt;br /&gt;
        return a 128 bit IPv6 address instead.&lt;br /&gt;
&lt;br /&gt;
        If the driver is unable to return the primary domain name server&lt;br /&gt;
        address (ios2_SrcAddr) or the secondary domain name server address&lt;br /&gt;
        (ios2_DstAddr) it must fill the respective address fields with zeroes.&lt;br /&gt;
        It is legal for a driver to respond to the S2_GETDNSADDRESS command&lt;br /&gt;
        with two zero addresses (both ios2_SrcAddr and ios2_DstAddr filled&lt;br /&gt;
        with zeroes).&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
I propose that the following command number should be assigned:&lt;br /&gt;
&amp;lt;tt&amp;gt;#define S2_GETDNSADDRESS 0xC003&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This command may be useful beyond the typical application (PPP) described above.&lt;br /&gt;
&lt;br /&gt;
== S2_GETEXTENDEDGLOBALSTATS ==&lt;br /&gt;
&lt;br /&gt;
There already exists a SANA-II command for querying global device statistics (&amp;lt;tt&amp;gt;S2_GETGLOBALSTATS&amp;lt;/tt&amp;gt;) which should be common to all kinds of networking devices. Statistics that are particular to a certain device type are intended to be returned through the &amp;lt;tt&amp;gt;S2_GETSPECIALSTATS&amp;lt;/tt&amp;gt; command. I feel that these mechanisms both fail to cater well enough for dial-up or session-oriented networking applications such as PPP or PPPoE. Since the data structure used by &amp;lt;tt&amp;gt;S2_GETGLOBALSTATS&amp;lt;/tt&amp;gt; is of a fixed size and not intended to accomodate for new fields, I propose to introduce a new command which uses a different data structure, as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct Sana2ExtDeviceStats&lt;br /&gt;
{&lt;br /&gt;
   ULONG          s2xds_Length;&lt;br /&gt;
   ULONG          s2xds_Actual;&lt;br /&gt;
&lt;br /&gt;
   S2QUAD         s2xds_PacketsReceived;&lt;br /&gt;
   S2QUAD         s2xds_PacketsSent;&lt;br /&gt;
   S2QUAD         s2xds_BadData;&lt;br /&gt;
   S2QUAD         s2xds_Overruns;&lt;br /&gt;
   S2QUAD         s2xds_UnknownTypesReceived;&lt;br /&gt;
   S2QUAD         s2xds_Reconfigurations;&lt;br /&gt;
   struct timeval s2xds_LastStart;&lt;br /&gt;
&lt;br /&gt;
   struct timeval s2xds_LastConnected;&lt;br /&gt;
   struct timeval s2xds_LastDisconnected;&lt;br /&gt;
   struct timeval s2xds_TimeConnected;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Before I proceed to explain what purposes the individual members serve, a few words on the &amp;lt;tt&amp;gt;S2QUAD&amp;lt;/tt&amp;gt; type, which is defined as follows:&lt;br /&gt;
&amp;lt;tt&amp;gt;typedef struct { ULONG s2q_High; ULONG s2q_Low; } S2QUAD;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In other words, the &amp;lt;tt&amp;gt;S2QUAD&amp;lt;/tt&amp;gt; type stands for an unsigned 64 bit big endian integer, as expressed in ISO &#039;C&#039; terms.&lt;br /&gt;
&lt;br /&gt;
The structure members have the following purposes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2xds_Length&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the size of the data structure to be filled in and should be initialized by the caller to &amp;lt;tt&amp;gt;sizeof(struct Sana2ExtDeviceStats)&amp;lt;/tt&amp;gt;. Smaller values are permitted, but these &#039;&#039;&#039;must not&#039;&#039;&#039; be smaller than 8 (which covers the &amp;lt;tt&amp;gt;s2xds_Length&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;s2xds_Actual&amp;lt;/tt&amp;gt; members). A driver which finds an &amp;lt;tt&amp;gt;s2xds_Length&amp;lt;/tt&amp;gt; &amp;amp;lt; 8 &#039;&#039;&#039;must&#039;&#039;&#039; treat this as an error and reject the command with &amp;lt;tt&amp;gt;ios2_Req.io_Error&amp;lt;/tt&amp;gt;=&amp;lt;tt&amp;gt;IOERR_BADLENGTH&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2xds_Actual&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The size of the data structure filled with information. This member is initialized by the driver and &#039;&#039;&#039;must&#039;&#039;&#039; be &amp;amp;lt;= &amp;lt;tt&amp;gt;s2xds_Length&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2xds_PacketsReceived&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Number of packets that this unit has received. This is a 64 bit integer.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2xds_PacketsSent&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Number of packets that this unit has sent. This is a 64 bit integer.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2xds_BadData&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Number of bad packets received (i.e., hardware CRC failed). This is a 64 bit integer.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2xds_Overruns&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Number of packets dropped due to insufficient resources available in the network interface. This is a 64 bit integer.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2xds_UnknownTypesReceived&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Number of packets received that had no pending read command with the appropriate packet type. This is a 64 bit integer.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2xds_Reconfigurations&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Number of network reconfigurations since this unit was last configured. This is a 64 bit integer.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2xds_LastStart&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The time when this unit last went on-line.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2xds_LastConnected&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The time when this unit last established a connection. For dial-up connections, this should be the time when the underlying serial line started to accumulate costs. &amp;lt;tt&amp;gt;s2xds_LastConnected&amp;lt;/tt&amp;gt; &#039;&#039;&#039;must&#039;&#039;&#039; be set to zero if the unit never managed to make a connection.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2xds_LastDisconnected&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The time when this unit last shut down a connection. For dial-up connections, this should be the time when the underlying serial line stopped accumulating costs, e.g. when the modem&#039;s carrier signal was lost. &amp;lt;tt&amp;gt;s2xds_LastDisconnected&amp;lt;/tt&amp;gt; &#039;&#039;&#039;must&#039;&#039;&#039; be set to zero if the unit never disconnected.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2xds_TimeConnected&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The time this unit has been connected. For dial-up connections this should be the time between now and when the underlying serial line started accumulating costs.&lt;br /&gt;
&lt;br /&gt;
If this unit is not currently connected, then &amp;lt;tt&amp;gt;s2xds_TimeConnected&amp;lt;/tt&amp;gt; &#039;&#039;&#039;must&#039;&#039;&#039; be set to zero. This means in particular that when the connection is lost, &amp;lt;tt&amp;gt;s2xds_TimeConnected&amp;lt;/tt&amp;gt; &#039;&#039;&#039;must&#039;&#039;&#039; be immediately set to zero and &amp;lt;tt&amp;gt;s2xds_LastDisconnected&amp;lt;/tt&amp;gt; &#039;&#039;&#039;must&#039;&#039;&#039; be filled in so that client software can query how long the unit was connected by subtracting &amp;lt;tt&amp;gt;s2xds_LastConnected&amp;lt;/tt&amp;gt; from &amp;lt;tt&amp;gt;s2xds_LastDisconnected&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
If this unit is currently connected, &amp;lt;tt&amp;gt;s2xds_TimeConnected&amp;lt;/tt&amp;gt; &#039;&#039;&#039;must never&#039;&#039;&#039; be zero; if necessary, set &amp;lt;tt&amp;gt;s2xds_TimeConnected.tv_secs=0&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;s2xds_TimeConnected.tv_micros=1&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
If &amp;lt;tt&amp;gt;s2xds_TimeConnected&amp;lt;/tt&amp;gt; is zero, check &amp;lt;tt&amp;gt;s2xds_LastConnected&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;s2xds_LastDisconnected&amp;lt;/tt&amp;gt;; if the latter two are not zero, you can calculate the previous connection time by subtracting &amp;lt;tt&amp;gt;s2xds_LastConnected&amp;lt;/tt&amp;gt; from &amp;lt;tt&amp;gt;s2xds_LastDisconnected&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The layout and semantics used by the &amp;lt;tt&amp;gt;Sana2ExtDeviceStats&amp;lt;/tt&amp;gt; data structure suggest that there is a difference between the underlying networking media (the link layer) and the state of the protocol that is running on top of it. With drivers for networking hardware such as Ethernet there was no difference between these two, but for protocols like SLIP, PPP or PPPoE there is a difference. The difference is in that a session or connection may exist for a certain time whereas the protocol running inside that session may be switched &#039;online&#039; later. The primary purpose of the &amp;lt;tt&amp;gt;s2xds_LastConnected&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;s2xds_LastDisconnected&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;s2xds_TimeConnected&amp;lt;/tt&amp;gt; fields is to allow for cost accounting and traffic monitoring (so that, for example, a driver may be disconnected after it has been idle for a while) to be written.&lt;br /&gt;
&lt;br /&gt;
I propose a command with the following semantics:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_GETEXTENDEDGLOBALSTATS -- Get interface accumulated statistics;&lt;br /&gt;
           updated version.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command causes the device driver to retrieve various global&lt;br /&gt;
        runtime statistics for this network interface. The format of the data&lt;br /&gt;
        returned is as follows:&lt;br /&gt;
&lt;br /&gt;
           struct Sana2ExtDeviceStats&lt;br /&gt;
           {&lt;br /&gt;
              ULONG s2xds_Length;&lt;br /&gt;
              ULONG s2xds_Actual;&lt;br /&gt;
&lt;br /&gt;
              S2QUAD s2xds_PacketsReceived;&lt;br /&gt;
              S2QUAD s2xds_PacketsSent;&lt;br /&gt;
              S2QUAD s2xds_BadData;&lt;br /&gt;
              S2QUAD s2xds_Overruns;&lt;br /&gt;
              S2QUAD s2xds_UnknownTypesReceived;&lt;br /&gt;
              S2QUAD s2xds_Reconfigurations;&lt;br /&gt;
              struct timeval s2xds_LastStart;&lt;br /&gt;
&lt;br /&gt;
              struct timeval s2xds_LastConnected;&lt;br /&gt;
              struct timeval s2xds_LastDisconnected;&lt;br /&gt;
              struct timeval s2xds_TimeConnected;&lt;br /&gt;
           };&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command          - S2_GETEXTENDEDGLOBALSTATS&lt;br /&gt;
        ios2_StatData         - Pointer to Sana2ExtDeviceStats structure&lt;br /&gt;
                                to fill in&lt;br /&gt;
        ios2_BufferManagement - Magic cookie as returned when opening the&lt;br /&gt;
                                driver with a struct IOSana2Req&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Req.io_Error - Zero if successful; non-zero otherwise&lt;br /&gt;
        ios2_WireError    - More specific error number&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
I propose that the following command number should be assigned:&lt;br /&gt;
&amp;lt;tt&amp;gt;#define S2_GETEXTENDEDGLOBALSTATS 0xC004&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_GETGLOBALSTATS ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        GetGlobalStats -- Get interface accumulated statistics.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command causes the device driver to retrieve various global&lt;br /&gt;
        runtime statistics for this network interface. The format of the&lt;br /&gt;
        data returned is as follows:&lt;br /&gt;
&lt;br /&gt;
            struct Sana2DeviceStats&lt;br /&gt;
            {&lt;br /&gt;
                ULONG PacketsReceived;&lt;br /&gt;
                ULONG PacketsSent;&lt;br /&gt;
                ULONG BadData;&lt;br /&gt;
                ULONG Overruns;&lt;br /&gt;
                ULONG UnknownTypesReceived;&lt;br /&gt;
                ULONG Reconfigurations;&lt;br /&gt;
                timeval LastStart;&lt;br /&gt;
            };&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - S2_GETGLOBALSTATS.&lt;br /&gt;
        ios2_StatData   - Pointer to Sana2DeviceStats structure to fill.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - Zero if successful; non-zero otherwise.&lt;br /&gt;
        ios2_WireError  - More specific error number.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        S2_GETSPECIALSTATS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_GETNETWORKINFO ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
	S2_GETNETWORKINFO -- Get information on current network.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
	This command provides information on the status of the currently&lt;br /&gt;
	used network. If this command completes successfully, ios2_StatData&lt;br /&gt;
	will contain a pointer to a tag list that contains information on&lt;br /&gt;
	the network. The S2INFO_#? tags used are defined in the&lt;br /&gt;
	devices/sana2wireless.h include file.&lt;br /&gt;
&lt;br /&gt;
	The returned taglist is allocated from the supplied memory pool.&lt;br /&gt;
	To discard the results of this command, the entire memory pool&lt;br /&gt;
	should be destroyed.&lt;br /&gt;
&lt;br /&gt;
   INPUTS&lt;br /&gt;
	ios2_Data - Pointer to an Exec memory pool.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
	ios2_Data - Remains unchanged.&lt;br /&gt;
	ios2_StatData - Pointer to a tag list.&lt;br /&gt;
	io_Error - Zero if successful; non-zero otherwise.&lt;br /&gt;
	ios2_WireError - More specific error code.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_GETNETWORKS ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
	S2_GETNETWORKS -- Scan for available networks.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
	This command supplies details of available networks. If the scan&lt;br /&gt;
	should be limited to one specific network, the S2INFO_SSID tag&lt;br /&gt;
	should specify its name.&lt;br /&gt;
&lt;br /&gt;
	If this command completes successfully, ios2_StatData will contain&lt;br /&gt;
	an array of pointers to tag lists, each of which contains&lt;br /&gt;
	information on a single network. The device will set ios2_DataLength&lt;br /&gt;
	to the number of elements in this array.&lt;br /&gt;
&lt;br /&gt;
	The returned taglists are allocated from the supplied memory pool.&lt;br /&gt;
	To discard the results of this command, the entire memory pool&lt;br /&gt;
	should be destroyed.&lt;br /&gt;
&lt;br /&gt;
	The S2INFO_#? tags used with this command are defined in the&lt;br /&gt;
	devices/sana2wireless.h include file.&lt;br /&gt;
&lt;br /&gt;
   INPUTS&lt;br /&gt;
	ios2_Data - Pointer to an Exec memory pool.&lt;br /&gt;
	ios2_StatData - Pointer to taglist that specifies parameters to use.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
	ios2_DataLength - Number of tag lists returned.&lt;br /&gt;
	ios2_Data - Remains unchanged.&lt;br /&gt;
	ios2_StatData - Pointer to an array of tag lists.&lt;br /&gt;
	io_Error - Zero if successful; non-zero otherwise.&lt;br /&gt;
	ios2_WireError - More specific error code.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_GETPEERADDRESS ==&lt;br /&gt;
&lt;br /&gt;
As part of the negotiation process, the PPP protocol can return the addresses used by the peer (the other side of the point-to-point connection PPP establishes; typically a dial-in server) and assigned to the client establishing the connection. The SANA-II standard does not provide for a mechanism to return such information. Existing drivers therefore had to resort to other means, such as by setting global environment variables containing this information.&lt;br /&gt;
&lt;br /&gt;
I propose a command with the following semantics:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_GETPEERADDRESS -- Obtain the addresses used by the peer&lt;br /&gt;
           (server) and the client of a point-to-point connection.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        Obtain the address used by the peer of a point-to-point connection and&lt;br /&gt;
        the address assigned to the local driver.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command          - S2_GETPEERADDRESS&lt;br /&gt;
        ios2_Flags            - Supported flags are:&lt;br /&gt;
                                SANA2IOB_QUICK&lt;br /&gt;
        ios2_BufferManagement - Magic cookie as returned when opening the&lt;br /&gt;
                                driver with a struct IOSana2Req&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Req.io_Error - Zero if successful; non-zero otherwise&lt;br /&gt;
        ios2_WireError    - More specific error number&lt;br /&gt;
        ios2_SrcAddr      - Address assigned to the local driver&lt;br /&gt;
        ios2_DstAddr      - Address used by the peer&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        The size of the address returned by S2_GETPEERADDRESS must not be&lt;br /&gt;
        different from the size returned by the S2_DEVICEQUERY command. For&lt;br /&gt;
        example, if a 32 bit IPv4 address was advertized, the driver must not&lt;br /&gt;
        return a 128 bit IPv6 address instead.&lt;br /&gt;
&lt;br /&gt;
        If the driver is unable to return the local driver address&lt;br /&gt;
        (ios2_SrcAddr) or the peer&#039;s address (ios2_DstAddr) it must fill the&lt;br /&gt;
        respective address fields with zeroes. It is legal for a driver to&lt;br /&gt;
        respond to the S2_GETPEERADDRESS command with two zero addresses (both&lt;br /&gt;
        ios2_SrcAddr and ios2_DstAddr filled with zeroes).&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
I propose that the following command number should be assigned:&lt;br /&gt;
&amp;lt;tt&amp;gt;#define S2_GETPEERADDRESS 0xC002&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This command may be useful beyond the typical application (PPP) described above.&lt;br /&gt;
&lt;br /&gt;
== S2_GETSIGNALQUALITY ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
	S2_GETSIGNALQUALITY -- Get signal quality statistics.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
	This command fills in the supplied Sana2SignalQuality structure with&lt;br /&gt;
	current signal and noise levels. The unit for these figures is dBm.&lt;br /&gt;
	Typically, they are negative values.&lt;br /&gt;
&lt;br /&gt;
   INPUTS&lt;br /&gt;
	ios2_StatData - Pointer to Sana2SignalQuality structure.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
	io_Error - Zero if successful; non-zero otherwise.&lt;br /&gt;
	ios2_WireError - More specific error code.&lt;br /&gt;
	ios2_StatData - Pointer to filled Sana2SignalQuality structure.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_GETSPECIALSTATS ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_GETSPECIALSTATS -- Get network type specific statistics.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This function returns statistics which are specific to the type of&lt;br /&gt;
        network medium this driver controls. For example, this command could&lt;br /&gt;
        return statistics common to all Ethernets which are not common to all&lt;br /&gt;
        network mediums in general.&lt;br /&gt;
&lt;br /&gt;
        The supplied Sana2SpecialStatData structure is given below:&lt;br /&gt;
&lt;br /&gt;
            struct Sana2SpecialStatData&lt;br /&gt;
            {&lt;br /&gt;
                ULONG RecordCountMax;&lt;br /&gt;
                ULONG RecordCountSupplied;&lt;br /&gt;
                struct Sana2StatRecord[RecordCountMax];&lt;br /&gt;
            };&lt;br /&gt;
&lt;br /&gt;
        The format of the data returned is:&lt;br /&gt;
&lt;br /&gt;
            struct Sana2StatRecord&lt;br /&gt;
            {&lt;br /&gt;
                ULONG Type;     /* Amiga registered */&lt;br /&gt;
                LONG Count;     /* the stat itself */&lt;br /&gt;
                char *String;   /* null terminated */&lt;br /&gt;
            };&lt;br /&gt;
&lt;br /&gt;
        The RecordCountMax field specifies the number of records that the&lt;br /&gt;
        caller is prepared to accomodate.&lt;br /&gt;
&lt;br /&gt;
        RecordCountSupplied is the number of record actually supplied which&lt;br /&gt;
        will not exceed RecordCountMax.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - S2_GETSPECIALSTATS.&lt;br /&gt;
        ios2_StatData   - Pointer to a Sana2SpecialStatData structure to fill.&lt;br /&gt;
                          RecordCountMax must be initialized.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - Zero if successful; non-zero otherwise.&lt;br /&gt;
        ios2_WireError  - More specific error number.&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        Amiga will maintain registered statistic Types.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        S2_GETGLOBALSTATS, &amp;amp;lt;devices/sana2specialstats.h&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_GETSTATIONADDRESS ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_GETSTATIONADDRESS -- Get default and interface address.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command causes the device driver to copy the current interface&lt;br /&gt;
        address into ios2_SrcAddr, and to copy the factory default station&lt;br /&gt;
        address (if any) into ios2_DstAddr.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - S2_GETSTATIONADDRESS.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - Zero if successful; non-zero otherwise.&lt;br /&gt;
        ios2_WireError  - More specific error number.&lt;br /&gt;
        ios2_SrcAddr    - Current interface address.&lt;br /&gt;
        ios2_DstAddr    - Default interface address (if any).&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        S2_CONFIGINTERFACE&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_GETTYPESTATS ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_GETTYPESTATS -- Get accumulated type specific statistics.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command causes the device driver to retrieve various packet type&lt;br /&gt;
        specific runtime statistics for this network interface. The format of&lt;br /&gt;
        the data returned is as follows:&lt;br /&gt;
&lt;br /&gt;
            struct Sana2TypeStatData&lt;br /&gt;
            {&lt;br /&gt;
                LONG PacketsSent;&lt;br /&gt;
                LONG PacketsReceived;&lt;br /&gt;
                LONG BytesSent;&lt;br /&gt;
                LONG BytesReceived;&lt;br /&gt;
                LONG PacketsDropped;&lt;br /&gt;
            };&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - S2_GETTYPESTATS.&lt;br /&gt;
        ios2_PacketType - Packet type of interest.&lt;br /&gt;
        ios2_StatData   - Pointer to TypeStatData structure to fill in.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - Zero if successful; non-zero otherwise.&lt;br /&gt;
        ios2_WireError  - More specific error number.&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        Statistics for a particular packet type are only available while that&lt;br /&gt;
        packet type is being ``tracked&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        S2_TRACKTYPE, S2_UNTRACKTYPE&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_MULTICAST ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_MULTICAST -- Multicast a packet on network.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command works the same as CMD_WRITE except that it also performs&lt;br /&gt;
        whatever special processing of the packet is required to do a&lt;br /&gt;
        multicast send. The actual multicast mechanism is neccessarily&lt;br /&gt;
        network/interface/device specific.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - S2_MULTICAST.&lt;br /&gt;
        ios2_Flags      - Supported flags are:&lt;br /&gt;
                                SANA2IOB_RAW&lt;br /&gt;
                                SANA2IOB_QUICK&lt;br /&gt;
        ios2_PacketType - Packet type to send.&lt;br /&gt;
        ios2_DstAddr    - Destination interface address for this packet.&lt;br /&gt;
        ios2_DataLength - Length of the Data to be sent.&lt;br /&gt;
        ios2_Data       - Abstract data structure which packet data is&lt;br /&gt;
                          contained in.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - Zero if successful; non-zero otherwise.&lt;br /&gt;
                          This command can fail for many reasons and&lt;br /&gt;
                          is not supported by all networks and/or&lt;br /&gt;
                          network interfaces.&lt;br /&gt;
        ios2_WireError  - More specific error number.&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        The address supplied in ios2_DstAddr will be sanity checked (if&lt;br /&gt;
        possible) by the driver. If the supplied address fails this sanity&lt;br /&gt;
        check, the multicast request will fail immediately with ios2_Error&lt;br /&gt;
        set to S2WERR_BAD_MULTICAST.&lt;br /&gt;
&lt;br /&gt;
        Another Amiga will not receive a multicast packet unless it has had&lt;br /&gt;
        the particular multicast address being used S2_ADDMULTICASTADRESS&#039;d.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        CMD_WRITE, S2_BROADCAST, S2_ADDMULTICASTADDRESS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_OFFLINE ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_OFFLINE -- Remove interface from service.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command removes a network interface from service.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - S2_OFFLINE.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - Zero if successful; non-zero otherwise.&lt;br /&gt;
        ios2_WireError  - More specific error number.&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        Aborts all pending reads and writes with ios2_Error set to&lt;br /&gt;
        S2ERR_OUTOFSERVICE.&lt;br /&gt;
&lt;br /&gt;
        While the interface is offline, all read, writes and any other&lt;br /&gt;
        command that touches interface hardware will be rejected with&lt;br /&gt;
        ios2_Error set to S2ERR_OUTOFSERVICE.&lt;br /&gt;
&lt;br /&gt;
        This command is intended to permit a network interface to be&lt;br /&gt;
        tested on an otherwise live system.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        S2_ONLINE&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_ONEVENT ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_ONEVENT -- Return when specified event occures.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command returns when a particular event condition has occured&lt;br /&gt;
        on the network or this network interface.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - S2_ONEVENT.&lt;br /&gt;
        ios2_Flags      - Supported flags are:&lt;br /&gt;
                                SANA2IOB_QUICK&lt;br /&gt;
        ios2_WireError  - Mask of event(s) to wait for&lt;br /&gt;
                          (from &amp;amp;lt;devices/sana2.h&amp;amp;gt;).&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - Zero if successful; non-zero otherwise.&lt;br /&gt;
        ios2_WireError  - Mask of events that occured.&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        If this device driver does not understand the specified event&lt;br /&gt;
        condition(s) then the command returns immediately with&lt;br /&gt;
        ios2_Req.io_Error set to S2_ERR_NOT_SUPPORTED and ios2_WireError&lt;br /&gt;
        S2WERR_BAD_EVENT.  A successful return will have ios2_Error set to&lt;br /&gt;
        zero ios2_WireError set to the event number.&lt;br /&gt;
&lt;br /&gt;
        All pending requests for a particular event will be returned when&lt;br /&gt;
        that event occurs.&lt;br /&gt;
&lt;br /&gt;
        All event types that cover a particular condition are returned when&lt;br /&gt;
        that condition occures. For instance, if an error is returned by&lt;br /&gt;
        a buffer management function during receive processing, events of&lt;br /&gt;
        types S2EVENT_ERROR, S2EVENT_RX and S2EVENT_BUFF would be returned if&lt;br /&gt;
        pending.&lt;br /&gt;
&lt;br /&gt;
        Types ONLINE and OFFLINE return immediately if the device is&lt;br /&gt;
        already in the state to be waited for.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_ONLINE ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_ONLINE -- Put a network interface back in service.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command places an offline network interface back into service.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - S2_ONLINE.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - Zero if successful; non-zero otherwise.&lt;br /&gt;
        ios2_WireError  - More specific error number.&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        This command is responsible for putting the network interface&lt;br /&gt;
        hardware back into a known state (as close as possible to the&lt;br /&gt;
        state before S2_OFFLINE) and resets the unit global and special&lt;br /&gt;
        statistics.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        S2_OFFLINE&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_READMGMT ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
	S2_READMGMT -- Read a management frame.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
	Reads a raw IEEE 802.11 management frame from the device. The buffer&lt;br /&gt;
	management mechanism used is simpler than that used for data&lt;br /&gt;
	packets (e.g. with CMD_READ): a buffer pointer and a length value&lt;br /&gt;
	are passed to the device.&lt;br /&gt;
&lt;br /&gt;
	As with CMDREAD/S2_READORPHAN, multiple S2_READMGMT requests can&lt;br /&gt;
	(and should) be queued concurrently to ensure no incoming frames are&lt;br /&gt;
	missed.&lt;br /&gt;
&lt;br /&gt;
   INPUTS&lt;br /&gt;
	ios2_DataLength - size of frame buffer.&lt;br /&gt;
	ios2_Data - pointer to a frame buffer.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
	io_Error - Zero if successful; non-zero otherwise.&lt;br /&gt;
	ios2_WireError - More specific error code.&lt;br /&gt;
	ios2_DataLength - actual size of received frame.&lt;br /&gt;
	ios2_Data - pointer to the filled frame buffer.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_READORPHAN ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_READORPHAN -- Get a packet for which there is no reader.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        Get the next packet available that does not satisfy any then-pending&lt;br /&gt;
        CMD_READ requests. The data returned in the ios2_Data structure is&lt;br /&gt;
        normally the Data Link Layer packet type field and the packet data. If&lt;br /&gt;
        bit SANA2IOB_RAW is set in ios2_Flags, then the entire Data Link Layer&lt;br /&gt;
        packet, including both header and trailer information, will be&lt;br /&gt;
        returned.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - CMD_READORPHAN.&lt;br /&gt;
        ios2_Flags      - Supported flags are:&lt;br /&gt;
                                SANA2IOB_RAW&lt;br /&gt;
                                SANA2IOB_QUICK&lt;br /&gt;
        ios2_DataLength - Length of the Data to be sent.&lt;br /&gt;
        ios2_Data       - Abstract data structure which packet data is&lt;br /&gt;
                          contained in.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - Zero if successful; non-zero otherwise.&lt;br /&gt;
        ios2_WireError  - More specific error number.&lt;br /&gt;
        ios2_Flags      - The following flags may be returned:&lt;br /&gt;
                                SANA2IOB_RAW&lt;br /&gt;
                                SANA2IOB_BCAST&lt;br /&gt;
                                SANA2IOB_MCAST&lt;br /&gt;
        ios2_SrcAddr    - Source interface address of packet.&lt;br /&gt;
        ios2_DstAddr    - Destination interface address of packet.&lt;br /&gt;
        ios2_DataLength - Length of the Data to be sent.&lt;br /&gt;
        ios2_Data       - Abstract data structure which packet data is&lt;br /&gt;
                          contained in.&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        This is intended for debugging and management tools.  Protocols should&lt;br /&gt;
        not use this.&lt;br /&gt;
&lt;br /&gt;
        As with 802.3 packets on an ethernet, to determine which protocol&lt;br /&gt;
        family the returned packet belongs to you may have to specify&lt;br /&gt;
        SANA2IOB_RAW to get the entire data link layer wrapper (which is where&lt;br /&gt;
        the protocol type may be kept). Notice this necessarily means that&lt;br /&gt;
        this cannot be done in a network interface independent fashion.  The&lt;br /&gt;
        driver will, however, fill in the PacketType field to the best of its&lt;br /&gt;
        ability.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        CMD_READ, CMD_WRITE&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_SAMPLE_THROUGHPUT ==&lt;br /&gt;
&lt;br /&gt;
The SANA-II standard already allows for statistics to be returned on the amount of data that has passed through a driver. Unfortunately, that information is not very accurate in that no information is provided on the time span in which the data was accumulated. Such information would be helpful in trying to determine as accurately as possible how large the data throughput actually is. I therefore propose a new command which can be used to obtain that information, which uses the following data structure:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct Sana2ThroughputStats&lt;br /&gt;
{&lt;br /&gt;
   ULONG          s2ts_Length;&lt;br /&gt;
   ULONG          s2ts_Actual;&lt;br /&gt;
&lt;br /&gt;
   struct Task *  s2ts_NotifyTask;&lt;br /&gt;
   ULONG          s2ts_NotifyMask;&lt;br /&gt;
&lt;br /&gt;
   struct timeval s2ts_StartTime;&lt;br /&gt;
   struct timeval s2ts_EndTime;&lt;br /&gt;
   S2QUAD         s2ts_BytesSent;&lt;br /&gt;
   S2QUAD         s2ts_BytesReceived;&lt;br /&gt;
   S2QUAD         s2ts_Updates;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Before I proceed to explain what purposes the individual members serve, a few words on the &amp;lt;tt&amp;gt;S2QUAD&amp;lt;/tt&amp;gt; type, which is defined as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;typedef struct { ULONG s2q_High; ULONG s2q_Low; } S2QUAD;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In other words, the &amp;lt;tt&amp;gt;S2QUAD&amp;lt;/tt&amp;gt; type stands for an unsigned 64 bit big endian integer, as expressed in ISO &#039;C&#039; terms.&lt;br /&gt;
&lt;br /&gt;
The structure members have the following purposes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2ts_Length&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the size of the data structure to be filled in and should be initialized by the caller to &amp;lt;tt&amp;gt;sizeof(struct Sana2ThroughputStats)&amp;lt;/tt&amp;gt;. Smaller values are permitted, but these must not be smaller than 8 (which covers the &amp;lt;tt&amp;gt;s2ts_Length&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;s2ts_Actual&amp;lt;/tt&amp;gt; members). A driver which finds an &amp;lt;tt&amp;gt;s2ts_Length&amp;lt;/tt&amp;gt; &amp;amp;lt; 8 must treat this as an error and reject the command with &amp;lt;tt&amp;gt;ios2_Req.io_Error&amp;lt;/tt&amp;gt;=&amp;lt;tt&amp;gt;IOERR_BADLENGTH&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2ts_Actual&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The size of the data structure filled with information. This member is initialized by the driver and must be &amp;amp;lt;= &amp;lt;tt&amp;gt;s2ts_Length&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2ts_NotifyTask&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;Task&amp;lt;/tt&amp;gt; to notify whenever the contents of this data structure change. This must be &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; if no notification is desired.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; This feature should be used carefully, as so much data may arrive that the driver will almost be constantly signalling this &amp;lt;tt&amp;gt;Task&amp;lt;/tt&amp;gt; that a change has taken place.&lt;br /&gt;
&lt;br /&gt;
It is recommend that periodic polling be used, such as to update displays of a link monitoring program.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2ts_NotifyMask&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The signal mask to use for notifying the &amp;lt;tt&amp;gt;Task&amp;lt;/tt&amp;gt; whose address is found in &amp;lt;tt&amp;gt;s2ts_NotifyTask&amp;lt;/tt&amp;gt; (via &amp;lt;tt&amp;gt;Signal(s2ts-&amp;amp;gt;s2ts_NotifyTask,s2ts-&amp;amp;gt;s2ts_NotifyMask);&amp;lt;/tt&amp;gt;). This must be zero if no notification is desired.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2ts_StartTime&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The time when the driver started to fill in this data structure.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2ts_EndTime&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The time when the driver last updated the contents of this data structure.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2ts_BytesSent&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Total number of bytes sent since the driver started to fill in this data structure. This is a 64 bit integer.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2ts_BytesReceived&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Total number of bytes received since the driver started to fill in this data structure. This is a 64 bit integer.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2ts_Updates&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Number of times the driver has updated this data structure. This value will increase with every change. This is a 64 bit integer.&lt;br /&gt;
&lt;br /&gt;
A driver implementing this command should take care to update the members &amp;lt;tt&amp;gt;s2ts_EndTime&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;s2ts_BytesSent&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;s2ts_BytesReceived&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;s2ts_Updates&amp;lt;/tt&amp;gt; atomically each time changes are made.&lt;br /&gt;
&lt;br /&gt;
I propose a command with the following semantics:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_SAMPLE_THROUGHPUT -- Obtain accurate information on&lt;br /&gt;
           driver data throughput.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command installs a data structure which is updated every time&lt;br /&gt;
        data is sent or received by the driver.&lt;br /&gt;
&lt;br /&gt;
        This command must be sent via SendIO() or BeginIO(); until&lt;br /&gt;
        the associated I/O request is recalled using AbortIO(), the&lt;br /&gt;
        device unit will continue to update the Sana2ThroughputStats&lt;br /&gt;
        structure in real time.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command          - S2_SAMPLE_THROUGHPUT&lt;br /&gt;
        ios2_StatData         - Pointer to Sana2ThroughputStats structure&lt;br /&gt;
                                to fill in&lt;br /&gt;
        ios2_BufferManagement - Magic cookie as returned when opening the&lt;br /&gt;
                                driver with a struct IOSana2Req&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Req.io_Error - Zero if successful; non-zero otherwise&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        If this device driver does not understand this command,&lt;br /&gt;
        it will immediately return the IOSana2Req with&lt;br /&gt;
        ios2_Req.io_Error set to IOERR_NOCMD. Otherwise, the request will&lt;br /&gt;
        remain queued until it is removed with AbortIO() later.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
I propose that the following command number should be assigned:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;#define S2_SAMPLE_THROUGHPUT 0xC007&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_SANA2HOOK ==&lt;br /&gt;
&lt;br /&gt;
The &#039;traditional&#039; copy call-back functions are installed at &amp;lt;tt&amp;gt;OpenDevice()&amp;lt;/tt&amp;gt; time, and they are found in a &amp;lt;tt&amp;gt;TagItem&amp;lt;/tt&amp;gt; list which is passed along with the &amp;lt;tt&amp;gt;IOSana2Req&amp;lt;/tt&amp;gt;. For the new &amp;lt;tt&amp;gt;Hook&amp;lt;/tt&amp;gt;-based call-back functionality, I propose to introduce a new command. This command would take care of installing one single &amp;lt;tt&amp;gt;Hook&amp;lt;/tt&amp;gt; which will be invoked with the parameters described in section 3.1. The hook function can key off the &amp;lt;tt&amp;gt;SANA2HookMsg-&amp;amp;gt;schm_Method&amp;lt;/tt&amp;gt; field to figure out which function should be performed. Once the &amp;lt;tt&amp;gt;Hook&amp;lt;/tt&amp;gt; is installed via the command as follows, the driver shall ignore any and all tags passed to it during &amp;lt;tt&amp;gt;OpenDevice()&amp;lt;/tt&amp;gt; time.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_SANA2HOOK -- Install a Hook to perform operations such as copying,&lt;br /&gt;
                        overriding the call-back functions installed at&lt;br /&gt;
                        OpenDevice() time.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        The S2_SANA2HOOK command is to replace the &#039;traditional&#039; call-back&lt;br /&gt;
        functions installed through the TagItem list found in the&lt;br /&gt;
        IOSana2Req-&amp;amp;gt;ios2_BufferManagement field. Instead of assigning a&lt;br /&gt;
        function pointer for each copying function, all operations are&lt;br /&gt;
        to be performed through a Hook. This is intended to make the&lt;br /&gt;
        interface more portable and less dependant on a certain hardware&lt;br /&gt;
        architecture.&lt;br /&gt;
&lt;br /&gt;
        The hook message and the hook data structures allow for more than&lt;br /&gt;
        copying to be done.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - S2_SANA2HOOK&lt;br /&gt;
        ios2_Data       - Points to a struct Sana2Hook, which looks&lt;br /&gt;
                          like this:&lt;br /&gt;
&lt;br /&gt;
                             struct Sana2Hook&lt;br /&gt;
                             {&lt;br /&gt;
                                struct Hook s2h_Hook;&lt;br /&gt;
                                Tag *       s2h_Methods;&lt;br /&gt;
                             };&lt;br /&gt;
&lt;br /&gt;
                          The structure fields have the following purposes:&lt;br /&gt;
&lt;br /&gt;
                             s2h_Hook&lt;br /&gt;
                                A standard Hook structure, ready to be&lt;br /&gt;
                                called. Once installed, the complete Hook&lt;br /&gt;
                                structure including its Node structure is&lt;br /&gt;
                                off limits! The s2h_Hook remains installed&lt;br /&gt;
                                until CloseDevice().&lt;br /&gt;
&lt;br /&gt;
                             s2h_Methods&lt;br /&gt;
                                Points to a table of Tag values, each&lt;br /&gt;
                                identifying a copy method supported&lt;br /&gt;
                                (S2_CopyToBuff, S2_CopyFromBuff,&lt;br /&gt;
                                S2_CopyToBuff16, S2_CopyFromBuff16,&lt;br /&gt;
                                S2_CopyToBuff32, S2_CopyFromBuff32,&lt;br /&gt;
                                S2_DMACopyToBuff32, S2_DMACopyFromBuff32,&lt;br /&gt;
                                S2_DMACopyToBuff64 or S2_DMACopyFromBuff64)&lt;br /&gt;
                                or the logging facility (S2_Log).&lt;br /&gt;
                                The table must be terminated by TAG_END.&lt;br /&gt;
&lt;br /&gt;
                                The driver will check the table and&lt;br /&gt;
                                verify that the mandatory S2_CopyToBuff&lt;br /&gt;
                                and S2_CopyFromBuff commands are present.&lt;br /&gt;
                                Additional functionality is used as&lt;br /&gt;
                                available if the driver supports it.&lt;br /&gt;
&lt;br /&gt;
        ios2_DataLength - Must be &amp;amp;gt;= 20, which is the default length of&lt;br /&gt;
                          the Sana2Hook structure. This may grow in&lt;br /&gt;
                          the future, and larger values for ios2_DataLength&lt;br /&gt;
                          may indicate additional functionality associated&lt;br /&gt;
                          with the Sana2Hook.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - IOERR_NOCMD if this command is not supported&lt;br /&gt;
                          by the driver.&lt;br /&gt;
&lt;br /&gt;
                          IOERR_BADLENGTH if IOSana2Req-&amp;amp;gt;ios2_DataLength&lt;br /&gt;
                          is &amp;amp;lt; 20.&lt;br /&gt;
&lt;br /&gt;
                          IOERR_UNITBUSY if the Hook was already&lt;br /&gt;
                          installed or if any of the CMD_READ, CMD_WRITE,&lt;br /&gt;
                          S2_MULTICAST or S2_BROADCAST have already been&lt;br /&gt;
                          invoked.&lt;br /&gt;
&lt;br /&gt;
                          S2WERR_FUNCTIONS_MISSING if the table pointed&lt;br /&gt;
                          to by Sana2Hook-&amp;amp;gt;s2h_Methods does not&lt;br /&gt;
                          include the S2_CopyToBuff and S2_CopyFromBuff&lt;br /&gt;
                          tags.&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        The S2_SANA2HOOK command shall be invoked right after OpenDevice()&lt;br /&gt;
        as very first command.&lt;br /&gt;
&lt;br /&gt;
        When the command has been executed, the driver must use the&lt;br /&gt;
        newly installed Hook for all its copying or logging and cease to&lt;br /&gt;
        use the call-back functions provided at OpenDevice() time.&lt;br /&gt;
&lt;br /&gt;
        The contents of the Sana2Hook structure, as passed to the&lt;br /&gt;
        driver, must not be modified. This includes the MinNode&lt;br /&gt;
        at the beginning of the Hook structure which the driver may&lt;br /&gt;
        need to use for its own purposes.&lt;br /&gt;
&lt;br /&gt;
        The table pointed to by Sana2Hook-&amp;amp;gt;s2h_Methods must&lt;br /&gt;
        include at least the S2_CopyToBuff and S2_CopyFromBuff tags.&lt;br /&gt;
        It must be valid until CloseDevice() is called.&lt;br /&gt;
&lt;br /&gt;
        This field is to be treated as private by a protocol stack.&lt;br /&gt;
        IOSana2Req structures may be duplicated by copying&lt;br /&gt;
        ios2_BufferManagement, io_Device, and io_Unit.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The new command value is defined as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   #define S2_SANA2HOOK 0xC008&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The new error code is defined as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   #define S2WERR_FUNCTIONS_MISSING 24 /* mandatory copy functions are missing */&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_SETKEY ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
	S2_SETKEY -- Set an encryption key.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
	Sets one of the encryption keys for the device. Note that&lt;br /&gt;
	ios2_StatData, if used, points to a byte array representing the RX&lt;br /&gt;
	RX counter value.&lt;br /&gt;
&lt;br /&gt;
   INPUTS&lt;br /&gt;
	ios2_WireError - Key index.&lt;br /&gt;
	ios2_PacketType - Encryption type (e.g. S2ENC_WEP).&lt;br /&gt;
	ios2_DataLength - Key length.&lt;br /&gt;
	ios2_Data - Key.&lt;br /&gt;
	ios2_StatData - RX counter number (NULL if unused).&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
	io_Error - Zero if successful; non-zero otherwise.&lt;br /&gt;
	ios2_WireError - More specific error code.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_SETOPTIONS ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
	S2_SETOPTIONS -- Set network options.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
	Set various parameters for the network interface. This command&lt;br /&gt;
	should be called before going online to set any essential parameters&lt;br /&gt;
	not covered elsewhere. The S2INFO_#? tags used are defined in the&lt;br /&gt;
	devices/sana2wireless.h include file.&lt;br /&gt;
&lt;br /&gt;
   INPUTS&lt;br /&gt;
	ios2_Data - Pointer to a taglist that specifies parameters to use.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
	io_Error - Zero if successful; non-zero otherwise.&lt;br /&gt;
	ios2_WireError - More specific error code.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_TRACKTYPE ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_TRACKTYPE -- Accumulate statistics about a packet type.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command causes the device driver to accumulate statistics about&lt;br /&gt;
        a particular packet type. Packet type statistics, for the particular&lt;br /&gt;
        packet type, are zeroed by this command.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - S2_TRACKTYPE.&lt;br /&gt;
        ios2_PacketType - Packet type of interest.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - Zero if successful; non-zero otherwise.&lt;br /&gt;
        ios2_WireError  - More specific error number.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        S2_UNTRACKTYPE, S2_GETTYPESTATS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_UNTRACKTYPE ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_UNTRACKTYPE -- End statistics about a packet type.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command causes the device driver to stop accumulating&lt;br /&gt;
        statistics about a particular packet type.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - S2_UNTRACKTYPE.&lt;br /&gt;
        ios2_PacketType - Packet type of interest.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - Zero if successful; non-zero otherwise.&lt;br /&gt;
        ios2_WireError  - More specific error number.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        S2_TRACKTYPE, S2_GETTYPESTATS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_WRITEMGMT ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
	S2_WRITEMGMT -- Write a management frame.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
	Writes a raw IEEE 802.11 management frame to the device. The buffer&lt;br /&gt;
	management mechanism used is simpler than that used for data&lt;br /&gt;
	packets (e.g. with CMD_WRITE): a buffer pointer and a length value&lt;br /&gt;
	are passed to the device.&lt;br /&gt;
&lt;br /&gt;
   INPUTS&lt;br /&gt;
	ios2_DataLength - full frame length.&lt;br /&gt;
	ios2_Data - pointer to a complete IEEE 802.11 management frame.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
	io_Error - Zero if successful; non-zero otherwise.&lt;br /&gt;
	ios2_WireError - More specific error code.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Callback mechanisms =&lt;br /&gt;
&lt;br /&gt;
== CopyFromBuff ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        CopyFromBuff -- Copy n bytes from an abstract data structure.&lt;br /&gt;
&lt;br /&gt;
   SYNOPSIS&lt;br /&gt;
        success = CopyFromBuff(to, from, n)&lt;br /&gt;
        d0                     a0  a1    d0&lt;br /&gt;
&lt;br /&gt;
        BOOL CopyToBuff(VOID *, VOID *, ULONG);&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This function copies &#039;n&#039; bytes of data in the abstract data structure&lt;br /&gt;
        pointed to by &#039;from&#039; into the contigous memory pointed to by &#039;to&#039;.&lt;br /&gt;
        &#039;to&#039; must contain at least &#039;n&#039; bytes of usable memory or innocent&lt;br /&gt;
        memory will be overwritten.&lt;br /&gt;
&lt;br /&gt;
   INPUTS&lt;br /&gt;
        to              - pointer to contiguous memory to copy to.&lt;br /&gt;
        from            - pointer to abstract structure to copy from.&lt;br /&gt;
        n               - number of bytes to copy.&lt;br /&gt;
&lt;br /&gt;
   RESULT&lt;br /&gt;
        success         - TRUE if operation was successful, else FALSE.&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        This function must be callable from interrupts.  In particular, this&lt;br /&gt;
        means that this function may not directly or indirectly call any&lt;br /&gt;
        system memory functions (since those functions rely on Forbid() to&lt;br /&gt;
        protect themselves) and that  you must not compile this function&lt;br /&gt;
        with stack checking enabled.  See the Exec Interrupts&lt;br /&gt;
        chapter for more details on what is legal in a routine called from&lt;br /&gt;
        an interrupt handler.&lt;br /&gt;
&lt;br /&gt;
        &#039;C&#039; programmers should not compile with stack checking (option &#039;-v&#039;&lt;br /&gt;
        in SAS) and should geta4() or __saveds.&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== CopyToBuff ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        CopyToBuff -- Copy n bytes to an abstract data structure.&lt;br /&gt;
&lt;br /&gt;
   SYNOPSIS&lt;br /&gt;
        success = CopyToBuff(to, from, n)&lt;br /&gt;
        d0                   a0  a1    d0&lt;br /&gt;
&lt;br /&gt;
        BOOL CopyToBuff(VOID *, VOID *, ULONG);&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This function first does any initialization and/or allocation&lt;br /&gt;
        required to prepare the abstract data structure pointed at by &#039;to&#039;&lt;br /&gt;
        to be filled with &#039;n&#039; bytes of data from &#039;from&#039;.  It then executes&lt;br /&gt;
        the copy operation.&lt;br /&gt;
&lt;br /&gt;
        If, for example, there is not enough memory available to prepare&lt;br /&gt;
        the abstract data structure, the call is failed and FALSE is returned.&lt;br /&gt;
&lt;br /&gt;
        The buffer management scheme should be such that any memory needed&lt;br /&gt;
        to fulfill CopyToBuff() calls is already allocated from the system&lt;br /&gt;
        before the call to CopyToBuff() is made.&lt;br /&gt;
&lt;br /&gt;
   INPUTS&lt;br /&gt;
        to              - pointer to abstract structure to copy to.&lt;br /&gt;
        from            - pointer to contiguous memory to copy from.&lt;br /&gt;
        n               - number of bytes to copy.&lt;br /&gt;
&lt;br /&gt;
   RESULT&lt;br /&gt;
        success         - TRUE if operation was successful, else FALSE.&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        This function must be callable from interrupts.  In particular, this&lt;br /&gt;
        means that this function may not directly or indirectly call any&lt;br /&gt;
        system memory functions (since those functions rely on Forbid() to&lt;br /&gt;
        protect themselves) and that you must not compile this function&lt;br /&gt;
        with stack checking enabled.  See the Exec Interrupts&lt;br /&gt;
        chapter for more details on what is legal in a routine called from&lt;br /&gt;
        an interrupt handler.&lt;br /&gt;
&lt;br /&gt;
        &#039;C&#039; programmers should not compile with stack checking (option &#039;-v&#039;&lt;br /&gt;
        in SAS) and should geta4() or __saveds.&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== PacketFilter ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        PacketFilter -- Perform filtering operation on CMD_READ&#039;s.&lt;br /&gt;
&lt;br /&gt;
   SYNOPSIS&lt;br /&gt;
        keep = PacketFilter(hook, ios2, data)&lt;br /&gt;
        d0                   a0    a2    a1&lt;br /&gt;
&lt;br /&gt;
        BOOL PacketFilter(struct Hook *, struct IOSana2Req *, APTR);&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This function (if supplied by a protocol stack) may be used to&lt;br /&gt;
        reject packets before they are copied into a protocol stack&#039;s&lt;br /&gt;
        internal buffers.&lt;br /&gt;
&lt;br /&gt;
        The IOSana2Req structure should be set up to look (almost) exactly&lt;br /&gt;
        as it would if it was successfully returned for the current packet.&lt;br /&gt;
        Specifically, the fields that should be set up correctly are:&lt;br /&gt;
&lt;br /&gt;
        ios2-&amp;amp;gt;ios2_DataLength&lt;br /&gt;
        ios2-&amp;amp;gt;ios2_SrcAddr&lt;br /&gt;
        ios2-&amp;amp;gt;ios2_DstAddr&lt;br /&gt;
&lt;br /&gt;
       The &amp;amp;quot;data&amp;amp;quot; pointer must point to the beginning of the packet data&lt;br /&gt;
        that is stored in contiguous memory.  The data should NOT include&lt;br /&gt;
        any hardware specific headers (unless of course the CMD_READ&lt;br /&gt;
        request wanted RAW packets).&lt;br /&gt;
&lt;br /&gt;
   INPUTS&lt;br /&gt;
        hook            - pointer to the Hook originally supplied during&lt;br /&gt;
                          OpenDevice().&lt;br /&gt;
        ios2            - The IOSana2Req CMD_READ request that will be used&lt;br /&gt;
                          (the &amp;amp;quot;object&amp;amp;quot; of the Hook call).&lt;br /&gt;
        data            - The packet data (the &amp;amp;quot;message&amp;amp;quot; of the Hook call).&lt;br /&gt;
&lt;br /&gt;
   RESULT&lt;br /&gt;
        success         - TRUE if the driver should provide the packet to&lt;br /&gt;
                          the protocol stack, FALSE if the packet should be&lt;br /&gt;
                          ignored.&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        This function must be callable from interrupts.  In particular, this  &lt;br /&gt;
        means that this function may not directly or indirectly call any&lt;br /&gt;
        system memory functions (since those functions rely on Forbid() to&lt;br /&gt;
        protect themselves) and that  you must not compile this function&lt;br /&gt;
        with stack checking enabled.  See the Exec Interrupts&lt;br /&gt;
        chapter for more details on what is legal in a routine called from&lt;br /&gt;
        an interrupt handler.&lt;br /&gt;
&lt;br /&gt;
        &#039;C&#039; programmers should not compile with stack checking (option &#039;-v&#039;&lt;br /&gt;
        in SAS) and should geta4() or __saveds.&lt;br /&gt;
&lt;br /&gt;
        What does packet filtering do? With the original ``SANA-II Network&lt;br /&gt;
        Device Driver Specification&#039;&#039;, a protocol stack could open a device&lt;br /&gt;
        and ask for certain packet types. It got all the packets that matched&lt;br /&gt;
        this type. As it turned out, this could be mighty inefficient if there&lt;br /&gt;
        were packets that the protocol stack did not use at all. These would&lt;br /&gt;
        go into read processing of the protocol stack and waste CPU time even&lt;br /&gt;
        though they could have been easily identified on arrival.&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Ethernet description =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#define S2WireType_Ethernet             1&lt;br /&gt;
&lt;br /&gt;
ios2_DataLength:&lt;br /&gt;
        valid ethernet packets have 64 to 1500 bytes of data.&lt;br /&gt;
&lt;br /&gt;
Address format:&lt;br /&gt;
        Ethernet addresses consist of 47 bits of address information and&lt;br /&gt;
        a 1 bit multicast flag. The standard for expressing ethernet&lt;br /&gt;
        addresses is as 6 bytes (octets) in the order in which the bytes&lt;br /&gt;
        are transmitted with the low-order bits in a byte transmitted&lt;br /&gt;
        first. The multicast flag bit is the least-significant bit of the&lt;br /&gt;
        first byte.&lt;br /&gt;
&lt;br /&gt;
        Ethernet addresses in a Sana2IOReq occupy the first 6 bytes of&lt;br /&gt;
        an address field in transmission order with the low-order bits in&lt;br /&gt;
        a byte transmitted first.&lt;br /&gt;
&lt;br /&gt;
Station Address:&lt;br /&gt;
        Each ethernet board must have a unique ethernet hardware address.&lt;br /&gt;
        Drivers will override any attempt to set the address to anything&lt;br /&gt;
        other than the ROM address.&lt;br /&gt;
&lt;br /&gt;
Raw reads and writes:&lt;br /&gt;
        6 bytes of destination address,&lt;br /&gt;
        6 bytes of source address,&lt;br /&gt;
        2 bytes of type,&lt;br /&gt;
        64 to 1500 bytes of data&lt;br /&gt;
        (followed by 4 byte CRC value covering all of the above&lt;br /&gt;
         which is hardware generated and checked, hence not included&lt;br /&gt;
         in even raw packets)&lt;br /&gt;
&lt;br /&gt;
Multicast:      Supported&lt;br /&gt;
&lt;br /&gt;
Broadcast:      Supported&lt;br /&gt;
&lt;br /&gt;
Promiscuous:    Supported&lt;br /&gt;
&lt;br /&gt;
Packet Type Numbers for Ethernet are assigned by:&lt;br /&gt;
&lt;br /&gt;
        Xerox Corporation&lt;br /&gt;
        Xerox Systems Institute&lt;br /&gt;
        475 Oakmead Parkway, Sunnyvale, CA 94086&lt;br /&gt;
        Attn: Ms. Fonda Pallone&lt;br /&gt;
        (408) 737-4652&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Some Common Packet Type Numbers:&lt;br /&gt;
&lt;br /&gt;
      decimal  Hex        Description&lt;br /&gt;
      -------  ---        -----------&lt;br /&gt;
         000   0000-05DC  IEEE 802.3 Length Field&lt;br /&gt;
        2048   0800       TCP/IP -- IP&lt;br /&gt;
        2054   0806       TCP/IP -- ARP&lt;br /&gt;
       32821   8035       TCP/IP -- RARP&lt;br /&gt;
       32923   809B       Appletalk&lt;br /&gt;
       33011   80F3       AppleTalk AARP (Kinetics)&lt;br /&gt;
       33100   814C       SNMP&lt;br /&gt;
       33079   8137-8138  Novell, Inc.&amp;lt;/pre&amp;gt;&lt;br /&gt;
= ARCNET description =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;S2WireType_Arcnet       7&lt;br /&gt;
&lt;br /&gt;
ios2_DataLength:&lt;br /&gt;
        506 byte MTU (because of the possibility of two byte Types).&lt;br /&gt;
        Packets of size 254, 255, or 256 bytes are padded to 257 bytes before&lt;br /&gt;
        transmition.&lt;br /&gt;
&lt;br /&gt;
Station Address:&lt;br /&gt;
        ARCNET hardware may have addresses set with jumpers, DIP switches&lt;br /&gt;
        or software.  Different drivers may therefore behave differently&lt;br /&gt;
        with S2_CONFIGINTERFACE.&lt;br /&gt;
&lt;br /&gt;
        Hardware addresses should be assigned by users from highest to lowest&lt;br /&gt;
        because there is some efficiency gained in the token passing scheme&lt;br /&gt;
        this way.  For example, on a three node network, hardware numbers 254,&lt;br /&gt;
        253 and 252 should be used rather than 1, 2 and 3.&lt;br /&gt;
&lt;br /&gt;
Raw reads and writes:&lt;br /&gt;
        Short Packets (1-253 bytes)&lt;br /&gt;
                Destination Address             (1 byte)&lt;br /&gt;
                Source Address                  (1 byte)&lt;br /&gt;
                Count (256-N-Type length)       (1 byte)&lt;br /&gt;
                Padding                         (to byte number Count)&lt;br /&gt;
                Type                            (1 or 2 bytes)&lt;br /&gt;
                Data                            (N bytes)&lt;br /&gt;
&lt;br /&gt;
        Long Packets (257-506 bytes)&lt;br /&gt;
                Destination Address             (1 byte)&lt;br /&gt;
                Source Address                  (1 byte)&lt;br /&gt;
                zero                            (1 byte)&lt;br /&gt;
                Count (512-N-Type length)       (1 byte)&lt;br /&gt;
                Padding                         (to byte number Count)&lt;br /&gt;
                Type                            (1 or 2 bytes)&lt;br /&gt;
                Data                            (N bytes)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Multicast:      Not Supported&lt;br /&gt;
&lt;br /&gt;
Broadcast:      Supported&lt;br /&gt;
&lt;br /&gt;
Promiscuous:    Generally Not Supported&lt;br /&gt;
&lt;br /&gt;
Packet Type Numbers for ARCNET are assigned by:&lt;br /&gt;
        Datapoint Corporation&lt;br /&gt;
&lt;br /&gt;
Some Common Packet Type Numbers&lt;br /&gt;
&lt;br /&gt;
        decimal  hex    description&lt;br /&gt;
        -------  ---    -----------&lt;br /&gt;
        221      DD     AppleTalk&lt;br /&gt;
        240      F0     TCP/IP -- IP   (RFC 1051)&lt;br /&gt;
        241      F1     TCP/IP -- ARP  (RFC 1051)&lt;br /&gt;
        212      F0     TCP/IP    IP   (RFC 1201, proposed)&lt;br /&gt;
        213      F1     TCP/IP -- ARP  (RFC 1201, proposed)&lt;br /&gt;
        214      D6     TCP/IP -- RARP (RFC 1201, proposed)&lt;br /&gt;
        247      F7     Banyan Vines&lt;br /&gt;
        250      FA     Novell IPX&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Authors =&lt;br /&gt;
&lt;br /&gt;
== Revision 2 &amp;amp; 3 ==&lt;br /&gt;
&lt;br /&gt;
Copyright © 1992-2000 Amiga, Inc. All Rights Reserved&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Amiga is a registered trademark of Amiga, Inc. Ethernet is a trademark of Xerox Corporation. ARCNET is a trademark of Datapoint Corporation. DECNet is a trademark of Digital Equipment Corporation. AppleTalk is a trademark of Apple Computer, Inc.&lt;br /&gt;
&lt;br /&gt;
== Revision 4 ==&lt;br /&gt;
&lt;br /&gt;
Extending the SANA-II network driver specification&amp;lt;br /&amp;gt;&lt;br /&gt;
by Olaf Barthel&lt;br /&gt;
&lt;br /&gt;
(Last updated 02-Mar-2003)&lt;br /&gt;
&lt;br /&gt;
== Revision 5 ==&lt;br /&gt;
&lt;br /&gt;
Hook-based callback function extensions for SANA-II (SANA-IIR5) &amp;lt;br /&amp;gt;&lt;br /&gt;
by Olaf Barthel and Heinz Wrobel&lt;br /&gt;
&lt;br /&gt;
== Revision 6 ==&lt;br /&gt;
&lt;br /&gt;
SANA-II IEEE 802.11 wireless API &amp;lt;br/&amp;gt;&lt;br /&gt;
by Neil Cafferkey&lt;br /&gt;
&lt;br /&gt;
= Acknowledgments =&lt;br /&gt;
&lt;br /&gt;
== Revision 2 &amp;amp; 3 ==&lt;br /&gt;
&lt;br /&gt;
Many people and companies have contributed to the &amp;quot;SANA-II Network Device Driver Specification&amp;quot;. The original SANA-II Autodocs and includes were put together by Ray Brand, Perry Kivolowitz (ASDG) and Martin Hunt. Those original documents evolved to their current state and grew to include this document at the hands of Dale Larson and Greg Miller. Brian Jackson and John Orr provided valuable editing. Randell Jesup has provided sage advice on several occasions. The buffer management callback mechanism was his idea. Dale Luck (GfxBase) and Rick Spanbauer (Ameristar Technologies) have provided valuable comments throughout the process. Nicolas Benezan (ADONIS) provided many detailed and useful comments on weaknesses in late drafts of the specification. The enhancements for better buffer management, clarifications and notes for device implementers were added to the specification by Heinz Wrobel whilst consulting for Amiga Technologies GmbH, yielding revision 3.0 of the specification.&lt;br /&gt;
&lt;br /&gt;
Thanks to all the above and the numerous others who have contributed with their comments, questions and discussions.&lt;br /&gt;
&lt;br /&gt;
= Changes =&lt;br /&gt;
&lt;br /&gt;
== Revision 4 ==&lt;br /&gt;
&lt;br /&gt;
Changes since 24-Dec-2002:&lt;br /&gt;
&lt;br /&gt;
* The &amp;lt;tt&amp;gt;Sana2Connection&amp;lt;/tt&amp;gt; data structure used by the &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt; command now must remain valid until the &amp;lt;tt&amp;gt;S2_DISCONNECT&amp;lt;/tt&amp;gt; command is sent (see [[#2.4|section 2.4]]).&lt;br /&gt;
&lt;br /&gt;
Changes since 01-May-2002:&lt;br /&gt;
&lt;br /&gt;
* Added the &amp;lt;tt&amp;gt;ppp.async.readrequests&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;ppp.async.eof&amp;lt;/tt&amp;gt; configuration keywords.&lt;br /&gt;
&lt;br /&gt;
Changes since 04-Jan-2002:&lt;br /&gt;
&lt;br /&gt;
* Added the &amp;lt;tt&amp;gt;ppp.dummyremoteaddress&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;ppp.ethernet.ac&amp;lt;/tt&amp;gt; configuration keywords.&lt;br /&gt;
&lt;br /&gt;
Changes since 10-Dec-2001:&lt;br /&gt;
&lt;br /&gt;
* Converted to HTML format.&lt;br /&gt;
* Added the &amp;lt;tt&amp;gt;&amp;amp;lt;devices/sana2.h&amp;amp;gt;&amp;lt;/tt&amp;gt; header file to the appendix.&lt;br /&gt;
* The memory alignment for the &amp;lt;tt&amp;gt;S2_DMACopyToBuff64&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2_DMACopyFromBuff64&amp;lt;/tt&amp;gt; hooks refers to bits and not to bytes.&lt;br /&gt;
&lt;br /&gt;
Changes since 19-Nov-2001:&lt;br /&gt;
&lt;br /&gt;
* Added to the list of reserved configuration keywords (&amp;lt;tt&amp;gt;ppp.idletimeout&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ppp.peeridletimeout&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ppp.sendid&amp;lt;/tt&amp;gt;).&lt;br /&gt;
* Renamed the fields of the &amp;lt;tt&amp;gt;Sana2ExtDeviceStats&amp;lt;/tt&amp;gt; structure.&lt;br /&gt;
* Clarified that the &amp;lt;tt&amp;gt;S2QUAD&amp;lt;/tt&amp;gt; type is a big endian integer.&lt;br /&gt;
* More clarifications for the &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;S2_DISCONNECT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2_ONLINE&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;S2_OFFLINE&amp;lt;/tt&amp;gt; commands.&lt;br /&gt;
* Updated the discussion of the &amp;lt;tt&amp;gt;Sana2DeviceQuery.RawMTU&amp;lt;/tt&amp;gt; field, clarifying what is included in the the Ethernet &amp;lt;tt&amp;gt;RawMTU&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* Updated the &amp;lt;tt&amp;gt;&amp;amp;lt;devices/sana2.h&amp;amp;gt;&amp;lt;/tt&amp;gt; header file. Note that there is no equivalent &amp;lt;tt&amp;gt;&amp;amp;quot;devices/sana2.i&amp;amp;quot;&amp;lt;/tt&amp;gt; header file yet.&lt;br /&gt;
&lt;br /&gt;
Changes since 12-Nov-2001:&lt;br /&gt;
&lt;br /&gt;
* Changed the command numbers of &amp;lt;tt&amp;gt;S2_GETPEERADDRESS&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;S2_GETDNSADDRESS&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;S2_GETEXTENDEDGLOBALSTATS&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;S2_DISCONNECT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2_SAMPLE_THROUGHPUT&amp;lt;/tt&amp;gt; to be NSD-compliant. Also assigned a new number to the &amp;lt;tt&amp;gt;S2_SAMPLE_THROUGHPUT &amp;lt;/tt&amp;gt; command.&lt;br /&gt;
* Added section 4 (&amp;amp;quot;Extensions for existing commands&amp;amp;quot;).&lt;br /&gt;
* Added the last paragraph to section 9, relating to the future extension of the &amp;lt;tt&amp;gt;Sana2DeviceQuery&amp;lt;/tt&amp;gt; structure.&lt;br /&gt;
&lt;br /&gt;
Changes since 03-Nov-2001:&lt;br /&gt;
&lt;br /&gt;
* Renamed &amp;lt;tt&amp;gt;S2_GETNEWGLOBALSTATS&amp;lt;/tt&amp;gt; to &amp;lt;tt&amp;gt;S2_GETEXTENDEDGLOBALSTATS&amp;lt;/tt&amp;gt; (see [[#2.3|section 2.3]]).&lt;br /&gt;
* The &amp;lt;tt&amp;gt;S2_GETEXTENDEDGLOBALSTATS&amp;lt;/tt&amp;gt; now uses 64 bit quantities for the &amp;lt;tt&amp;gt;s2xds_PacketsReceived&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;s2xds_PacketsSent&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;s2xds_BadData&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;s2xds_Overruns&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;s2xds_UnknownTypesReceived&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;s2xds_Reconfigurations&amp;lt;/tt&amp;gt; counters.&lt;br /&gt;
* In section 2.6 the &amp;lt;tt&amp;gt;S2_SAMPLE_THROUGHPUT&amp;lt;/tt&amp;gt; command was modified to use 64 bit integers for all members of the &amp;lt;tt&amp;gt;Sana2ThroughputStats&amp;lt;/tt&amp;gt; structure.&lt;br /&gt;
* All proposed commands are now listed with their numeric IDs.&lt;br /&gt;
* The command autodocs specifically mention the &amp;lt;tt&amp;gt;ios2_BufferManagement&amp;lt;/tt&amp;gt; field.&lt;br /&gt;
* All references to &amp;lt;tt&amp;gt;ios2_Error&amp;lt;/tt&amp;gt; have been replaced with &amp;lt;tt&amp;gt;ios2_Req.io_Error&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* In section 7 the use of the &amp;lt;tt&amp;gt;IOERR_NOCMD&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;S2ERR_NOT_SUPPORTED&amp;lt;/tt&amp;gt; error codes is clarified.&lt;br /&gt;
* Section 7 takes a more detailed look at safe default values returned by the query commands.&lt;br /&gt;
* Inserted section 3 (&amp;amp;quot;Annotations for existing commands&amp;amp;quot;).&lt;br /&gt;
* The &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2_DISCONNECT&amp;lt;/tt&amp;gt; commands now specifically mention the life time of the data they have to deal with.&lt;br /&gt;
&lt;br /&gt;
Changes since 14-Oct-2001:&lt;br /&gt;
&lt;br /&gt;
* Added &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2_DISCONNECT&amp;lt;/tt&amp;gt; commands.&lt;br /&gt;
* Added &amp;lt;tt&amp;gt;S2EVENT_CONNECT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2EVENT_DISCONNECT&amp;lt;/tt&amp;gt; events.&lt;br /&gt;
* Added section 4 (&amp;amp;quot;New wire error codes&amp;amp;quot;).&lt;br /&gt;
* In section 5.2 the originally proposed log callback function has been wrapped into a standard Hook structure.&lt;br /&gt;
* Removed item on &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;S2_DISCONNECT&amp;lt;/tt&amp;gt; from section 7 (&amp;amp;quot;Unsolved problems&amp;amp;quot;).&lt;br /&gt;
* Added section 8 (&amp;amp;quot;Changes&amp;amp;quot;).&lt;br /&gt;
&lt;br /&gt;
== Revision 5 ==&lt;br /&gt;
&lt;br /&gt;
22-Mar-2004:&lt;br /&gt;
&lt;br /&gt;
* Conversion to HTML&lt;br /&gt;
&lt;br /&gt;
21-Jan-2004:&lt;br /&gt;
&lt;br /&gt;
* Added clarifications for &amp;lt;tt&amp;gt;schm_MsgSize&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;slhm_MsgSize&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;slhm_Priority&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;slhm_Name&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;slhm_Message&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;s2h_Hook&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* Updated the &amp;lt;tt&amp;gt;S2_SANA2HOOK&amp;lt;/tt&amp;gt; documentation.&lt;br /&gt;
* Shortened section 4.&lt;br /&gt;
* Updated section 5.&lt;br /&gt;
&lt;br /&gt;
30-Nov-2003:&lt;br /&gt;
&lt;br /&gt;
* Extended the applicability of the &amp;lt;tt&amp;gt;Hook&amp;lt;/tt&amp;gt; to logging.&lt;br /&gt;
* Renamed &amp;lt;tt&amp;gt;S2_COPYHOOK&amp;lt;/tt&amp;gt; to &amp;lt;tt&amp;gt;S2_SANA2HOOK&amp;lt;/tt&amp;gt;, which matches the extended scope it should cover.&lt;br /&gt;
* The message passed to the &amp;lt;tt&amp;gt;Hook&amp;lt;/tt&amp;gt; now includes a size field which holds the size of the message, expressed in bytes.&lt;br /&gt;
&lt;br /&gt;
06-Oct-2003:&lt;br /&gt;
&lt;br /&gt;
* Replaced the list of new tag items with a single &amp;lt;tt&amp;gt;Hook&amp;lt;/tt&amp;gt;, which is installed through a new command.&lt;br /&gt;
* Added &amp;amp;quot;Caveats&amp;amp;quot; and &amp;amp;quot;Changes&amp;amp;quot; sections&lt;br /&gt;
* Removed the documentation for the originally proposed &amp;lt;tt&amp;gt;TagItem&amp;lt;/tt&amp;gt; (sections 3.2.1 through 3.2.10)&lt;br /&gt;
&lt;br /&gt;
= History =&lt;br /&gt;
&lt;br /&gt;
== Revision 2 and 3 ==&lt;br /&gt;
&lt;br /&gt;
This standard has undergone several drafts with long periods for comment from developers and the Amiga community at large. These drafts include a UseNet release which was also distributed on the Fish Disks in June, 1991 (as well as published in the &#039;91 DevCon notes), and the November 7 Draft for Final Comment and Approval distributed via Bix, ADSP and UseNet. There were also several intermediate drafts with more limited distribution.&lt;br /&gt;
&lt;br /&gt;
== Revision 4 ==&lt;br /&gt;
&lt;br /&gt;
(Olaf Barthel)&lt;br /&gt;
&lt;br /&gt;
I&#039;ve been working on a TCP/IP stack and PPP drivers to go with them for a while and found that there were some things that SANA-II did specifically not address, and which ought to be covered by it. In other areas clarification was needed. Also, discussions I had with Harald Frank suggested that the extensions made by Heinz Wrobel and Stefan Sticht in the SANA-IIR3 specification could need extending.&lt;/div&gt;</summary>
		<author><name>Costel Mincea</name></author>
	</entry>
	<entry>
		<id>https://wiki.amigaos.net/w/index.php?title=Autodocs:Main&amp;diff=12591</id>
		<title>Autodocs:Main</title>
		<link rel="alternate" type="text/html" href="https://wiki.amigaos.net/w/index.php?title=Autodocs:Main&amp;diff=12591"/>
		<updated>2026-06-09T17:01:45Z</updated>

		<summary type="html">&lt;p&gt;Costel Mincea: Updated to SDK 54.24 AutoDocs&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The autodocs are included in the latest [[SDK_FAQ|AmigaOS SDK]] (download from [https://www.hyperion-entertainment.com/index.php/downloads?view=files&amp;amp;parent=30 Hyperion Entertainment]) and are also available as text files below:&lt;br /&gt;
&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/a1floppy.doc.txt a1floppy.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/a1serial_dev.doc.txt a1serial_dev.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/acpires.doc.txt acpires.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/AI_Driver.doc.txt AI_Driver.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/amigaguide.doc.txt amigaguide.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/amigaguide_dtc.doc.txt amigaguide_dtc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/AmigaInput.doc.txt AmigaInput.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/amiga_lib.doc.txt amiga_lib.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/animation_dtc.doc.txt animation_dtc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/appdir-handler.doc.txt appdir-handler.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/application.doc.txt application.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/arexx_cl.doc.txt arexx_cl.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/asl.doc.txt asl.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/audio.doc.txt audio.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/aux-handler.doc.txt aux-handler.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/battclock.doc.txt battclock.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/battmem.doc.txt battmem.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/bevel_ic.doc.txt bevel_ic.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/biosversion.doc.txt biosversion.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/bitmap_ic.doc.txt bitmap_ic.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/bootsd.doc.txt bootsd.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/bsdsocket.doc.txt bsdsocket.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/btree.doc.txt btree.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/bullet.doc.txt bullet.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/button_gc.doc.txt button_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/camd.doc.txt camd.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/cardres.doc.txt cardres.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/cd.doc.txt cd.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/checkbox_gc.doc.txt checkbox_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/chooser_gc.doc.txt chooser_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/cia.doc.txt cia.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/clicktab_gc.doc.txt clicktab_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/clipboard.doc.txt clipboard.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/colorwheel_gc.doc.txt colorwheel_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/commodities.doc.txt commodities.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/con-handler.doc.txt con-handler.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/console.doc.txt console.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/datatypes.doc.txt datatypes.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/datebrowser_gc.doc.txt datebrowser_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/ddebug_lib.doc.txt ddebug_lib.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/debug_lib.doc.txt debug_lib.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/diffview_gc.doc.txt diffview_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/disk.doc.txt disk.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/diskfont.doc.txt diskfont.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/diskio.doc.txt diskio.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/docky.doc.txt docky.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/dos.doc.txt dos.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/dos.dospackets.doc.txt dos.dospackets.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/dos.obsolete.doc.txt dos.obsolete.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/drawlist_ic.doc.txt drawlist_ic.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/elf.doc.txt elf.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/exec.doc.txt exec.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/expansion.doc.txt expansion.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/filesysbox.doc.txt filesysbox.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/filesysres.doc.txt filesysres.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/filler_ic.doc.txt filler_ic.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/fillrect_ic.doc.txt fillrect_ic.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/frame_ic.doc.txt frame_ic.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/frbutton_gc.doc.txt frbutton_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/fsldmares.doc.txt fsldmares.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/fuelgauge_gc.doc.txt fuelgauge_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/gadget_gc.doc.txt gadget_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/gadtools.doc.txt gadtools.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/gameport.doc.txt gameport.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/Gameport_pci.doc.txt Gameport_pci.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/gauge_ic.doc.txt gauge_ic.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/getcolor_gc.doc.txt getcolor_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/getfile_gc.doc.txt getfile_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/getfont_gc.doc.txt getfont_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/getscreenmode_gc.doc.txt getscreenmode_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/glyph_ic.doc.txt glyph_ic.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/gradientslider_gc.doc.txt gradientslider_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/graphics.doc.txt graphics.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/group_gc.doc.txt group_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/hunk.doc.txt hunk.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/i2cres.doc.txt i2cres.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/ibutton_gc.doc.txt ibutton_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/ic_cl.doc.txt ic_cl.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/icon.doc.txt icon.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/iconmodule.doc.txt iconmodule.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/iffparse.doc.txt iffparse.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/image_ic.doc.txt image_ic.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/input.doc.txt input.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/integer_gc.doc.txt integer_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/intuition.doc.txt intuition.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/iscroller_gc.doc.txt iscroller_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/istring_gc.doc.txt istring_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/itext_ic.doc.txt itext_ic.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/keyboard.doc.txt keyboard.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/keymap.doc.txt keymap.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/label_ic.doc.txt label_ic.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/launch-handler.doc.txt launch-handler.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/layers.doc.txt layers.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/layout_gc.doc.txt layout_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/libamiga_a.doc.txt libamiga_a.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/listbrowser_gc.doc.txt listbrowser_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/locale.doc.txt locale.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/lowlevel.doc.txt lowlevel.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/mathffp.doc.txt mathffp.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/mathieeedoubbas.doc.txt mathieeedoubbas.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/mathieeedoubtrans.doc.txt mathieeedoubtrans.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/mathieeesingbas.doc.txt mathieeesingbas.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/mathieeesingtrans.doc.txt mathieeesingtrans.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/mathtrans.doc.txt mathtrans.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/menu_cl.doc.txt menu_cl.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/misc.doc.txt misc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/model_cl.doc.txt model_cl.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/mounter.doc.txt mounter.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/narrator.doc.txt narrator.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/nonvolatile.doc.txt nonvolatile.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/nvramres.doc.txt nvramres.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/openfirmware.doc.txt openfirmware.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/page_gc.doc.txt page_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/palette_gc.doc.txt palette_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/parallel.doc.txt parallel.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/partition_gc.doc.txt partition_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/pasemi_dma.doc.txt pasemi_dma.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/penmap_ic.doc.txt penmap_ic.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/performancemonitor.doc.txt performancemonitor.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/Picasso96API.doc.txt Picasso96API.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/picture_dtc.doc.txt picture_dtc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/pointer_cl.doc.txt pointer_cl.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/popupmenu_cl.doc.txt popupmenu_cl.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/port-handler.doc.txt port-handler.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/potgo.doc.txt potgo.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/printer.doc.txt printer.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/prop_gc.doc.txt prop_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/radiobutton_gc.doc.txt radiobutton_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/ram.doc.txt ram.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/ramlib.doc.txt ramlib.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/realtime.doc.txt realtime.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/requester_cl.doc.txt requester_cl.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/resource.doc.txt resource.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/rexxsyslib.doc.txt rexxsyslib.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/root_cl.doc.txt root_cl.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/screenblanker.doc.txt screenblanker.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/scroller_gc.doc.txt scroller_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/serial_dev.doc.txt serial_dev.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/serial.doc.txt serial.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/shell.doc.txt shell.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/sketchboard_gc.doc.txt sketchboard_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/slider_gc.doc.txt slider_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/sound_dtc.doc.txt sound_dtc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/space_gc.doc.txt space_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/speedbar_gc.doc.txt speedbar_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/string_gc.doc.txt string_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/sys_ic.doc.txt sys_ic.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/tapedeck_gc.doc.txt tapedeck_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/textclip.doc.txt textclip.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/textclip-handler.doc.txt textclip-handler.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/text_dtc.doc.txt text_dtc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/texteditor_gc.doc.txt texteditor_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/timer.doc.txt timer.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/timesync.doc.txt timesync.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/timezone.doc.txt timezone.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/trackdisk.doc.txt trackdisk.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/translator.doc.txt translator.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/usbfd.doc.txt usbfd.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/usbhcd.doc.txt usbhcd.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/usbresource.doc.txt usbresource.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/usbsys.doc.txt usbsys.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/utility.doc.txt utility.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/version.doc.txt version.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/virtual_gc.doc.txt virtual_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/warp3d.doc.txt warp3d.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/window_cl.doc.txt window_cl.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/workbench.doc.txt workbench.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/xenares.doc.txt xenares.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/z.doc.txt z.doc]&lt;/div&gt;</summary>
		<author><name>Costel Mincea</name></author>
	</entry>
	<entry>
		<id>https://wiki.amigaos.net/w/index.php?title=Autodocs:Main&amp;diff=12590</id>
		<title>Autodocs:Main</title>
		<link rel="alternate" type="text/html" href="https://wiki.amigaos.net/w/index.php?title=Autodocs:Main&amp;diff=12590"/>
		<updated>2026-06-09T16:28:51Z</updated>

		<summary type="html">&lt;p&gt;Costel Mincea: Added link to Hyperion download pages&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The autodocs are included in the latest [[SDK_FAQ|AmigaOS SDK]] (download from [https://www.hyperion-entertainment.com/index.php/downloads?view=files&amp;amp;parent=30 Hyperion Entertainment]) and are also available as text files below:&lt;br /&gt;
&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/a1floppy.doc.txt a1floppy.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/a1serial_dev.doc.txt a1serial_dev.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/AI_Driver.doc.txt AI_Driver.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/amigaguide.doc.txt amigaguide.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/amigaguide_dtc.doc.txt amigaguide_dtc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/AmigaInput.doc.txt AmigaInput.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/amiga_lib.doc.txt amiga_lib.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/animation_dtc.doc.txt animation_dtc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/application.doc.txt application.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/arexx_cl.doc.txt arexx_cl.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/asl.doc.txt asl.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/audio.doc.txt audio.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/battclock.doc.txt battclock.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/battmem.doc.txt battmem.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/bevel_ic.doc.txt bevel_ic.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/biosversion.doc.txt biosversion.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/bitmap_ic.doc.txt bitmap_ic.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/bsdsocket.doc.txt bsdsocket.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/btree.doc.txt btree.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/bullet.doc.txt bullet.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/button_gc.doc.txt button_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/camd.doc.txt camd.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/cardres.doc.txt cardres.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/cd.doc.txt cd.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/checkbox_gc.doc.txt checkbox_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/chooser_gc.doc.txt chooser_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/cia.doc.txt cia.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/clicktab_gc.doc.txt clicktab_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/clipboard.doc.txt clipboard.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/colorwheel_gc.doc.txt colorwheel_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/commodities.doc.txt commodities.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/console.doc.txt console.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/datatypes.doc.txt datatypes.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/datebrowser_gc.doc.txt datebrowser_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/ddebug_lib.doc.txt ddebug_lib.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/debug_lib.doc.txt debug_lib.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/diffview_gc.doc.txt diffview_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/disk.doc.txt disk.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/diskfont.doc.txt diskfont.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/diskio.doc.txt diskio.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/docky.doc.txt docky.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/dos.doc.txt dos.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/dos.dospackets.doc.txt dos.dospackets.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/dos.obsolete.doc.txt dos.obsolete.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/drawlist_ic.doc.txt drawlist_ic.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/elf.doc.txt elf.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/exec.doc.txt exec.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/expansion.doc.txt expansion.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/filesysbox.doc.txt filesysbox.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/filesysres.doc.txt filesysres.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/filler_ic.doc.txt filler_ic.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/fillrect_ic.doc.txt fillrect_ic.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/frame_ic.doc.txt frame_ic.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/frbutton_gc.doc.txt frbutton_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/fuelgauge_gc.doc.txt fuelgauge_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/gadget_gc.doc.txt gadget_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/gadtools.doc.txt gadtools.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/gameport.doc.txt gameport.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/Gameport_pci.doc.txt Gameport_pci.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/gauge_ic.doc.txt gauge_ic.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/getcolor_gc.doc.txt getcolor_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/getfile_gc.doc.txt getfile_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/getfont_gc.doc.txt getfont_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/getscreenmode_gc.doc.txt getscreenmode_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/glyph_ic.doc.txt glyph_ic.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/gradientslider_gc.doc.txt gradientslider_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/graphics.doc.txt graphics.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/group_gc.doc.txt group_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/hunk.doc.txt hunk.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/ibutton_gc.doc.txt ibutton_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/icon.doc.txt icon.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/iconmodule.doc.txt iconmodule.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/ic_cl.doc.txt ic_cl.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/iffparse.doc.txt iffparse.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/image_ic.doc.txt image_ic.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/input.doc.txt input.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/integer_gc.doc.txt integer_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/intuition.doc.txt intuition.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/iscroller_gc.doc.txt iscroller_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/istring_gc.doc.txt istring_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/itext_ic.doc.txt itext_ic.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/keyboard.doc.txt keyboard.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/keymap.doc.txt keymap.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/label_ic.doc.txt label_ic.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/layers.doc.txt layers.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/layout_gc.doc.txt layout_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/libamiga_a.doc.txt libamiga_a.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/listbrowser_gc.doc.txt listbrowser_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/locale.doc.txt locale.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/lowlevel.doc.txt lowlevel.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/mathffp.doc.txt mathffp.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/mathieeedoubbas.doc.txt mathieeedoubbas.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/mathieeedoubtrans.doc.txt mathieeedoubtrans.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/mathieeesingbas.doc.txt mathieeesingbas.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/mathieeesingtrans.doc.txt mathieeesingtrans.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/mathtrans.doc.txt mathtrans.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/menu_cl.doc.txt menu_cl.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/misc.doc.txt misc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/model_cl.doc.txt model_cl.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/narrator.doc.txt narrator.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/nonvolatile.doc.txt nonvolatile.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/openfirmware.doc.txt openfirmware.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/page_gc.doc.txt page_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/palette_gc.doc.txt palette_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/parallel.doc.txt parallel.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/partition_gc.doc.txt partition_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/penmap_ic.doc.txt penmap_ic.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/performancemonitor.doc.txt performancemonitor.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/Picasso96API.doc.txt Picasso96API.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/picture_dtc.doc.txt picture_dtc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/pointer_cl.doc.txt pointer_cl.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/popupmenu_cl.doc.txt popupmenu_cl.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/potgo.doc.txt potgo.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/printer.doc.txt printer.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/prop_gc.doc.txt prop_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/radiobutton_gc.doc.txt radiobutton_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/realtime.doc.txt realtime.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/requester_cl.doc.txt requester_cl.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/resource.doc.txt resource.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/rexxsyslib.doc.txt rexxsyslib.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/root_cl.doc.txt root_cl.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/scroller_gc.doc.txt scroller_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/serial_dev.doc.txt serial_dev.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/sketchboard_gc.doc.txt sketchboard_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/slider_gc.doc.txt slider_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/sound_dtc.doc.txt sound_dtc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/space_gc.doc.txt space_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/speedbar_gc.doc.txt speedbar_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/string_gc.doc.txt string_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/sys_ic.doc.txt sys_ic.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/tapedeck_gc.doc.txt tapedeck_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/textclip.doc.txt textclip.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/texteditor_gc.doc.txt texteditor_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/text_dtc.doc.txt text_dtc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/timer.doc.txt timer.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/timesync.doc.txt timesync.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/timezone.doc.txt timezone.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/trackdisk.doc.txt trackdisk.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/translator.doc.txt translator.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/usbfd.doc.txt usbfd.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/usbhcd.doc.txt usbhcd.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/usbresource.doc.txt usbresource.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/usbsys.doc.txt usbsys.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/utility.doc.txt utility.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/virtual_gc.doc.txt virtual_gc.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/warp3d.doc.txt warp3d.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/window_cl.doc.txt window_cl.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/workbench.doc.txt workbench.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/xenares.doc.txt xenares.doc]&lt;br /&gt;
* [http://wiki.amigaos.net/amiga/autodocs/z.doc.txt z.doc]&lt;/div&gt;</summary>
		<author><name>Costel Mincea</name></author>
	</entry>
	<entry>
		<id>https://wiki.amigaos.net/w/index.php?title=Amiga_Hardware_Manufacturer_ID_Registry&amp;diff=12581</id>
		<title>Amiga Hardware Manufacturer ID Registry</title>
		<link rel="alternate" type="text/html" href="https://wiki.amigaos.net/w/index.php?title=Amiga_Hardware_Manufacturer_ID_Registry&amp;diff=12581"/>
		<updated>2026-03-06T07:29:18Z</updated>

		<summary type="html">&lt;p&gt;Costel Mincea: /* How to Obtain a Manufacturer Number */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
= How to Obtain a Manufacturer Number =&lt;br /&gt;
&lt;br /&gt;
Manufacturer&#039;s numbers are assigned by the AmigaOS development team. To obtain your unique manufacturer number send a support request to [mailto:support@hyperion-entertainment.com support@hyperion-entertainment.com].&lt;br /&gt;
&lt;br /&gt;
Be sure and include your name and the type of expansion product you are developing.&lt;br /&gt;
&lt;br /&gt;
= Your Manufacturer Number =&lt;br /&gt;
&lt;br /&gt;
Attention hardware manufacturers. If you are developing a hardware expansion product for the Classic Amiga (e.g. 500, 2000, 3000) then you will need to obtain a special manufacturer ID number from the AmigaOS development team to identify your product. This manufacturer number is used by the Amiga to link your hardware with its driver software at boot time.&lt;br /&gt;
&lt;br /&gt;
Your manufacturer number is part of the special protocol that the Amiga uses to automatically configure all expansion devices on the bus without the user having to cut jumpers or adjust dip switches. This is called auto-config.&lt;br /&gt;
&lt;br /&gt;
At start-up time, the system first polls each board in the system and assigns the board its own address space. If it is a memory board, its RAM is linked into the memory free pool. Later in the boot sequence, after DOS is initialized, the binddrivers program is run. Binddrivers will search the directory SYS:Expansion for the drivers that go with the boards.&lt;br /&gt;
&lt;br /&gt;
To do this binddrivers looks in the Tool Type field of all icon files in SYS:Expansion. If the first seven bytes of the Tool Type field are &amp;quot;PRODUCT&amp;quot;, then this is an icon file for a driver.&lt;br /&gt;
&lt;br /&gt;
Binddrivers will then attempt to match the drivers it has found with the boards that were found earlier. This is where your manufacturer number comes in.&lt;br /&gt;
&lt;br /&gt;
Your manufacturer number goes in two places. First, it is burned in hex form into the PAL which is part of ALL auto-config expansion products. Second, it appears in ASCII in the Tool Type field of the icon file for your product&#039;s driver. By matching these two numbers, the Amiga can automatically configure your board and bind it&#039;s software driver into the system as well.&lt;br /&gt;
&lt;br /&gt;
The manufacturer&#039;s number is a 16-bit ID which appears in PAL offsets $10-$17. There is also an 8-bit product number which you assign. The product number is for uniquely identifying different products from the same vendor. The product number will appear in PAL offsets $04-$07. This gives you a total of 24 bits to identify each of your products.&lt;br /&gt;
&lt;br /&gt;
These 24 bits of information in the PAL which identify your product are matched against the information in the Tool Type field of all icon files in the SYS:Expansion drawer. For example, suppose you are manufacturer #1019. You have two products, #1 and #2 which both use the same driver. The icon for your driver for these two products would have a Tool Type set to &amp;quot;PRODUCT=1019/1|1019/2&amp;quot;. This means: I am an icon for a driver that works with product number 1 or 2 from manufacturer 1019, now bind me. Spaces are not legal. Here are two other examples:&lt;br /&gt;
&lt;br /&gt;
; PRODUCT=1208/11&lt;br /&gt;
: is the Tool Type for a driver for product 11 from manufacturer number 1208.&lt;br /&gt;
&lt;br /&gt;
; PRODUCT=1017&lt;br /&gt;
: is the Tool Type for a driver for any product from manufacturer number 1017.&lt;br /&gt;
&lt;br /&gt;
For an informal explanation of the auto-configuration process, see the chapter on Software Expansion Architecture from the 2nd Annual Amiga Developer&#039;s Conference Notes (available on ADCD 2.1). For the details of timing, power, the PAL equations and PAL address specifications and the expansion library documentation, see sections 3.1 to 3.3 of the A500/A2000 Technical Reference Manual. The original auto-config spec appears in the A1000 Schematics and Expansion Specification.&lt;br /&gt;
&lt;br /&gt;
The auto-config process makes the addition of expansion products to the system very easy. All the user has to do is put the board in any slot and copy the driver from the release disk to his own SYS:Expansion drawer. Everything else is automatic. There are no jumpers or dip switches to set. Best of all, you will get a lot less support calls asking how to make your product work with the XYZ-Corp-battery-backed-clock.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
&lt;br /&gt;
Some notes on hardware manufacturer ID assignment.&lt;br /&gt;
&lt;br /&gt;
* Manufacturer ID numbers are assigned free of charge.&lt;br /&gt;
* Please provide the following information when requesting an ID:&lt;br /&gt;
*# Name of the company or person&lt;br /&gt;
*# Postal address/contact address&lt;br /&gt;
*# Name of the contact person, with a corresponding e-mail address&lt;br /&gt;
*# A brief description of the kind of products you want to produce&lt;br /&gt;
* All ID numbers smaller than 5000 must be considered unsafe because no information exists on which numbers exactly were taken during the time Commodore, Inc. disintegrated.&lt;br /&gt;
* ID numbers in the range 8192 to 18841 must be considered unsafe because some hardware developers mistook the numbers assigned to them to be given in hexadecimal format. Hence 0x2000 = 8192 and 0x4999 = 18841.&lt;br /&gt;
&lt;br /&gt;
= Example code =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
/*-----------------------------------------------*/&lt;br /&gt;
/* Here is a short program which will tell you   */&lt;br /&gt;
/* about the expansion boards configured in your */&lt;br /&gt;
/* system without you opening up the machine.    */&lt;br /&gt;
/* Code by Bill Koester of CATS                  */&lt;br /&gt;
/*-----------------------------------------------*/&lt;br /&gt;
#include &amp;lt;libraries/configvars.h&amp;gt;&lt;br /&gt;
#include &amp;lt;libraries/expansion.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
struct ExpansionBase *ExpansionBase;&lt;br /&gt;
&lt;br /&gt;
void cleanup();&lt;br /&gt;
void printdev();&lt;br /&gt;
&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
   struct ConfigDev *MyConfigDev;&lt;br /&gt;
&lt;br /&gt;
   /*----------------------------------*/&lt;br /&gt;
   /* Open the expansion library,      */&lt;br /&gt;
   /* if there is a problem then exit  */&lt;br /&gt;
   /*----------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   ExpansionBase =(struct ExpansionBase *) OpenLibrary(EXPANSIONNAME,0);&lt;br /&gt;
   if(ExpansionBase==NULL)&lt;br /&gt;
   {&lt;br /&gt;
      printf(&amp;quot;Error opening expansion library!!\n&amp;quot;);&lt;br /&gt;
      cleanup();&lt;br /&gt;
      exit(0);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   /*--------------------------------------------*/&lt;br /&gt;
   /* Use FindConfigDev to get info on the first */&lt;br /&gt;
   /* expansion board on the list maintained by  */&lt;br /&gt;
   /* Exec.  If there are no expansion boards in */&lt;br /&gt;
   /* the system then exit.                      */&lt;br /&gt;
   /*--------------------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   MyConfigDev = NULL;&lt;br /&gt;
&lt;br /&gt;
  /*--------------------------------------------------*/&lt;br /&gt;
  /* FindConfigDev(oldConfigDev,manufacturer,product) */&lt;br /&gt;
  /* oldConfigDev = NULL for the top of the list      */&lt;br /&gt;
  /* manufacturer = -1 for any manufacturer           */&lt;br /&gt;
  /* product      = -1 for any product                */&lt;br /&gt;
  /*--------------------------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   MyConfigDev = FindConfigDev(NULL,-1,-1);&lt;br /&gt;
&lt;br /&gt;
   if(MyConfigDev==NULL)&lt;br /&gt;
   {&lt;br /&gt;
      printf(&amp;quot;No Configured Devices found!!\n&amp;quot;);&lt;br /&gt;
      cleanup();&lt;br /&gt;
      exit(0);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   printdev(MyConfigDev);&lt;br /&gt;
&lt;br /&gt;
   /*-----------------------------------*/&lt;br /&gt;
   /* OK, there is at least one board,  */&lt;br /&gt;
   /* so loop and get the entire list   */&lt;br /&gt;
   /* printing as we go with printdev() */&lt;br /&gt;
   /*-----------------------------------*/&lt;br /&gt;
&lt;br /&gt;
   while(MyConfigDev = FindConfigDev(MyConfigDev,-1,-1))&lt;br /&gt;
   {&lt;br /&gt;
      printdev(MyConfigDev);&lt;br /&gt;
   }&lt;br /&gt;
   cleanup();&lt;br /&gt;
   return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*-------------------*/&lt;br /&gt;
/* Close up shop...  */&lt;br /&gt;
/*-------------------*/&lt;br /&gt;
void cleanup()&lt;br /&gt;
{&lt;br /&gt;
   if(ExpansionBase)&lt;br /&gt;
      CloseLibrary(ExpansionBase);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*----------------------------------*/&lt;br /&gt;
/* Print out the contents of the    */&lt;br /&gt;
/* dev structure for this expansion */&lt;br /&gt;
/* product.                         */&lt;br /&gt;
/*----------------------------------*/&lt;br /&gt;
&lt;br /&gt;
void printdev(dev)&lt;br /&gt;
struct ConfigDev *dev;&lt;br /&gt;
{&lt;br /&gt;
   char buff[200];&lt;br /&gt;
&lt;br /&gt;
   printf(&amp;quot;Flags          = &amp;quot;);&lt;br /&gt;
   if(dev-&amp;gt;cd_Flags==NULL)&lt;br /&gt;
      printf(&amp;quot;NULL  &amp;quot;);&lt;br /&gt;
   if(dev-&amp;gt;cd_Flags&amp;amp;CDF_SHUTUP)&lt;br /&gt;
      printf(&amp;quot;CDF_SHUTUP  &amp;quot;);&lt;br /&gt;
   if(dev-&amp;gt;cd_Flags&amp;amp;CDF_CONFIGME)&lt;br /&gt;
      printf(&amp;quot;CDF_CONFIGME  &amp;quot;);&lt;br /&gt;
   printf(&amp;quot;\n&amp;quot;);&lt;br /&gt;
   printf(&amp;quot;Board Address  = %x\n&amp;quot;,dev-&amp;gt;cd_BoardAddr);&lt;br /&gt;
   printf(&amp;quot;Board Size     = %d bytes\n&amp;quot;,dev-&amp;gt;cd_BoardSize);&lt;br /&gt;
   printf(&amp;quot;Slot  Address  = %d\n&amp;quot;,dev-&amp;gt;cd_SlotAddr);&lt;br /&gt;
   printf(&amp;quot;Slot  Size     = %d\n&amp;quot;,dev-&amp;gt;cd_SlotSize);&lt;br /&gt;
   printf(&amp;quot;Driver code at   %x\n&amp;quot;,dev-&amp;gt;cd_Driver);&lt;br /&gt;
&lt;br /&gt;
   printf(&amp;quot;er_Type         = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Type);&lt;br /&gt;
   printf(&amp;quot;er_Product      = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Product);&lt;br /&gt;
   printf(&amp;quot;er_Flags        = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Flags);&lt;br /&gt;
   printf(&amp;quot;er_Reserved03   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved03);&lt;br /&gt;
   printf(&amp;quot;er_Manufacturer = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Manufacturer);&lt;br /&gt;
   printf(&amp;quot;er_SerialNumber = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_SerialNumber);&lt;br /&gt;
   printf(&amp;quot;er_InitDiagVec  = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_InitDiagVec);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0c   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0c);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0d   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0d);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0e   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0e);&lt;br /&gt;
   printf(&amp;quot;er_Reserved0f   = %x\n&amp;quot;,dev-&amp;gt;cd_Rom.er_Reserved0f);&lt;br /&gt;
&lt;br /&gt;
   printf(&amp;quot;Hit Return to continue:\n&amp;quot;);&lt;br /&gt;
   gets(buff);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Registry =&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! ID (decimal)&lt;br /&gt;
! ID (hexadecimal)&lt;br /&gt;
! Manufacturer&lt;br /&gt;
! Notes&lt;br /&gt;
|-&lt;br /&gt;
| 1&lt;br /&gt;
| 0001&lt;br /&gt;
| Micronik&lt;br /&gt;
|-&lt;br /&gt;
| 211&lt;br /&gt;
| 00D3&lt;br /&gt;
| Pacific Peripherals/Profex&lt;br /&gt;
|-&lt;br /&gt;
| 221&lt;br /&gt;
| 00DD&lt;br /&gt;
| Kupke Computertechnik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 256&lt;br /&gt;
| 0100&lt;br /&gt;
| Memphis&lt;br /&gt;
| Originally registered to MacroSystems US&lt;br /&gt;
|-&lt;br /&gt;
| 512&lt;br /&gt;
| 0200&lt;br /&gt;
| 3-State Computertechnik&lt;br /&gt;
|-&lt;br /&gt;
| 513&lt;br /&gt;
| 0201&lt;br /&gt;
| Commodore (Braunschweig)&lt;br /&gt;
|-&lt;br /&gt;
| 514&lt;br /&gt;
| 0202&lt;br /&gt;
| Commodore (West Chester)&lt;br /&gt;
|-&lt;br /&gt;
| 515&lt;br /&gt;
| 0203&lt;br /&gt;
| Commodore (West Chester)&lt;br /&gt;
| Originally registered to Combitech/Macrosystem&lt;br /&gt;
|-&lt;br /&gt;
| 756&lt;br /&gt;
| 02F4&lt;br /&gt;
| Progressive Peripherals &amp;amp; Software&lt;br /&gt;
|-&lt;br /&gt;
| 767&lt;br /&gt;
| 02FF&lt;br /&gt;
| Kolff Computer Supplies&lt;br /&gt;
|-&lt;br /&gt;
| 1001&lt;br /&gt;
| 03E9&lt;br /&gt;
| Tecmar&lt;br /&gt;
|-&lt;br /&gt;
| 1002&lt;br /&gt;
| 03EA&lt;br /&gt;
| Telesys&lt;br /&gt;
|-&lt;br /&gt;
| 1003&lt;br /&gt;
| 03EB&lt;br /&gt;
| The Micro-Forge&lt;br /&gt;
|-&lt;br /&gt;
| 1004&lt;br /&gt;
| 03EC&lt;br /&gt;
| Kronos/C Ltd.&lt;br /&gt;
| Originally registered to Card Co. (Supra)&lt;br /&gt;
|-&lt;br /&gt;
| 1005&lt;br /&gt;
| 03ED&lt;br /&gt;
| A-Squared&lt;br /&gt;
|-&lt;br /&gt;
| 1006&lt;br /&gt;
| 03EE&lt;br /&gt;
| Comspec Communications&lt;br /&gt;
|-&lt;br /&gt;
| 1007&lt;br /&gt;
| 03EF&lt;br /&gt;
| HT Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 1008&lt;br /&gt;
| 03F0&lt;br /&gt;
| RDS Software&lt;br /&gt;
|-&lt;br /&gt;
| 1009&lt;br /&gt;
| 03F1&lt;br /&gt;
| Anakin Research&lt;br /&gt;
|-&lt;br /&gt;
| 1010&lt;br /&gt;
| 03F2&lt;br /&gt;
| MicroBotics&lt;br /&gt;
|-&lt;br /&gt;
| 1011&lt;br /&gt;
| 03F3&lt;br /&gt;
| Bob Krauth&lt;br /&gt;
|-&lt;br /&gt;
| 1012&lt;br /&gt;
| 03F4&lt;br /&gt;
| Access Associates (Alegra)&lt;br /&gt;
|-&lt;br /&gt;
| 1013&lt;br /&gt;
| 03F5&lt;br /&gt;
| Mini Comp Systems Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 1014&lt;br /&gt;
| 03F6&lt;br /&gt;
| Cypress Technology&lt;br /&gt;
|-&lt;br /&gt;
| 1015&lt;br /&gt;
| 03F7&lt;br /&gt;
| Fuller Computers&lt;br /&gt;
|-&lt;br /&gt;
| 1016&lt;br /&gt;
| 03F8&lt;br /&gt;
| Galaxy Computers&lt;br /&gt;
|-&lt;br /&gt;
| 1017&lt;br /&gt;
| 03F9&lt;br /&gt;
| ADA Research&lt;br /&gt;
|-&lt;br /&gt;
| 1018&lt;br /&gt;
| 03FA&lt;br /&gt;
| Computer Service Italia&lt;br /&gt;
|-&lt;br /&gt;
| 1019&lt;br /&gt;
| 03FB&lt;br /&gt;
| Amigo&lt;br /&gt;
|-&lt;br /&gt;
| 1020&lt;br /&gt;
| 03FC&lt;br /&gt;
| Micro-Solutions Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1021&lt;br /&gt;
| 03FD&lt;br /&gt;
| Stacar International&lt;br /&gt;
|-&lt;br /&gt;
| 1022&lt;br /&gt;
| 03FE&lt;br /&gt;
| Video Precisions&lt;br /&gt;
|-&lt;br /&gt;
| 1023&lt;br /&gt;
| 03FF&lt;br /&gt;
| ASDG, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1025&lt;br /&gt;
| 0401&lt;br /&gt;
| Ing. Buero Kalawsky&lt;br /&gt;
|-&lt;br /&gt;
| 1026&lt;br /&gt;
| 0402&lt;br /&gt;
| Computer Tuning&lt;br /&gt;
|-&lt;br /&gt;
| 1027&lt;br /&gt;
| 0403&lt;br /&gt;
| Interplan Unternehmensberatung&lt;br /&gt;
|-&lt;br /&gt;
| 1028&lt;br /&gt;
| 0404&lt;br /&gt;
| Imtronics/Memphis&lt;br /&gt;
| Originally registered to Peter Ohlich&lt;br /&gt;
|-&lt;br /&gt;
| 1030&lt;br /&gt;
| 0406&lt;br /&gt;
| Commodore (Lowell University)&lt;br /&gt;
| Originally registered to Productivity Center&lt;br /&gt;
|-&lt;br /&gt;
| 1041&lt;br /&gt;
| 0411&lt;br /&gt;
| Design Labs&lt;br /&gt;
|-&lt;br /&gt;
| 1042&lt;br /&gt;
| 0412&lt;br /&gt;
| MCS&lt;br /&gt;
|-&lt;br /&gt;
| 1043&lt;br /&gt;
| 0413&lt;br /&gt;
| B. J. Freeman&lt;br /&gt;
|-&lt;br /&gt;
| 1044&lt;br /&gt;
| 0414&lt;br /&gt;
| Side Effects Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1045&lt;br /&gt;
| 0415&lt;br /&gt;
| Oklahoma Personal Comp.&lt;br /&gt;
|-&lt;br /&gt;
| 1046&lt;br /&gt;
| 0416&lt;br /&gt;
| Advanced Micro Innovations&lt;br /&gt;
|-&lt;br /&gt;
| 1047&lt;br /&gt;
| 0417&lt;br /&gt;
| Industrial Support Services&lt;br /&gt;
|-&lt;br /&gt;
| 1048&lt;br /&gt;
| 0418&lt;br /&gt;
| Technisoft&lt;br /&gt;
|-&lt;br /&gt;
| 1049&lt;br /&gt;
| 0419&lt;br /&gt;
| Prolific, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1050&lt;br /&gt;
| 041A&lt;br /&gt;
| Softeam, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1051&lt;br /&gt;
| 041B&lt;br /&gt;
| GRC Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 1052&lt;br /&gt;
| 041C&lt;br /&gt;
| David Lai&lt;br /&gt;
|-&lt;br /&gt;
| 1053&lt;br /&gt;
| 041D&lt;br /&gt;
| Ameristar Technologies&lt;br /&gt;
|-&lt;br /&gt;
| 1054&lt;br /&gt;
| 041E&lt;br /&gt;
| Cline Refrigeration&lt;br /&gt;
|-&lt;br /&gt;
| 1055&lt;br /&gt;
| 041F&lt;br /&gt;
| Cardiac Pacemakers, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1056&lt;br /&gt;
| 0420&lt;br /&gt;
| Supra Corp. (Creative Microsystems)&lt;br /&gt;
|-&lt;br /&gt;
| 1057&lt;br /&gt;
| 0421&lt;br /&gt;
| Wayne Diener&lt;br /&gt;
|-&lt;br /&gt;
| 1058&lt;br /&gt;
| 0422&lt;br /&gt;
| Computer Systems Associates (CSA)&lt;br /&gt;
|-&lt;br /&gt;
| 1059&lt;br /&gt;
| 0423&lt;br /&gt;
| Trionix, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 1060&lt;br /&gt;
| 0424&lt;br /&gt;
| David Lucas&lt;br /&gt;
|-&lt;br /&gt;
| 1061&lt;br /&gt;
| 0425&lt;br /&gt;
| Analog Precision&lt;br /&gt;
| Also assigned to D &amp;amp; L Distributing&lt;br /&gt;
|-&lt;br /&gt;
| 1267&lt;br /&gt;
| 04F3&lt;br /&gt;
| RBM Digitaltechnik&lt;br /&gt;
|-&lt;br /&gt;
| 1282&lt;br /&gt;
| 0502&lt;br /&gt;
| M-TEC Hardware Design&lt;br /&gt;
|-&lt;br /&gt;
| 1337&lt;br /&gt;
| 0539&lt;br /&gt;
| Thomas Stenzel (DaFR34K)&lt;br /&gt;
|-&lt;br /&gt;
| 1576&lt;br /&gt;
| 0628&lt;br /&gt;
| Boris Križma&lt;br /&gt;
|-&lt;br /&gt;
| 1761&lt;br /&gt;
| 06E1&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
|-&lt;br /&gt;
| 1803&lt;br /&gt;
| 070B&lt;br /&gt;
| UAE Amiga Emulator&lt;br /&gt;
|-&lt;br /&gt;
| 2002&lt;br /&gt;
| 07D2&lt;br /&gt;
| Mimetics Corp.&lt;br /&gt;
|-&lt;br /&gt;
| 2003&lt;br /&gt;
| 07D3&lt;br /&gt;
| ACDA&lt;br /&gt;
|-&lt;br /&gt;
| 2004&lt;br /&gt;
| 07D4&lt;br /&gt;
| Finn R. Jacobsen&lt;br /&gt;
|-&lt;br /&gt;
| 2005&lt;br /&gt;
| 07D5&lt;br /&gt;
| Elthen Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2006&lt;br /&gt;
| 07D6&lt;br /&gt;
| Nine Tiles Computer Systems Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2007&lt;br /&gt;
| 07D7&lt;br /&gt;
| Analog Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2008&lt;br /&gt;
| 07D8&lt;br /&gt;
| Bell &amp;amp;amp; Howell&lt;br /&gt;
|-&lt;br /&gt;
| 2009&lt;br /&gt;
| 07D9&lt;br /&gt;
| Roland Kochler&lt;br /&gt;
|-&lt;br /&gt;
| 2010&lt;br /&gt;
| 07DA&lt;br /&gt;
| Byte Corp.&lt;br /&gt;
|-&lt;br /&gt;
| 2011&lt;br /&gt;
| 07DB&lt;br /&gt;
| Reserved&lt;br /&gt;
|-&lt;br /&gt;
| 2012&lt;br /&gt;
| 07DC&lt;br /&gt;
| DKB, Inc.&lt;br /&gt;
| Previously named Michigan Software&lt;br /&gt;
|-&lt;br /&gt;
| 2013&lt;br /&gt;
| 07DD&lt;br /&gt;
| Pacific Peripherals&lt;br /&gt;
|-&lt;br /&gt;
| 2014&lt;br /&gt;
| 07DE&lt;br /&gt;
| Sysaphus Software&lt;br /&gt;
|-&lt;br /&gt;
| 2015&lt;br /&gt;
| 07DF&lt;br /&gt;
| Digitronics&lt;br /&gt;
|-&lt;br /&gt;
| 2016&lt;br /&gt;
| 07E0&lt;br /&gt;
| Akron Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2017&lt;br /&gt;
| 07E1&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
|-&lt;br /&gt;
| 2018&lt;br /&gt;
| 07E2&lt;br /&gt;
| Calmos&lt;br /&gt;
|-&lt;br /&gt;
| 2019&lt;br /&gt;
| 07E3&lt;br /&gt;
| Dover Research&lt;br /&gt;
|-&lt;br /&gt;
| 2020&lt;br /&gt;
| 07E4&lt;br /&gt;
| David Krehbiel&lt;br /&gt;
|-&lt;br /&gt;
| 2021&lt;br /&gt;
| 07E5&lt;br /&gt;
| Synergy Peripheral Systems&lt;br /&gt;
| Also known as California Access&lt;br /&gt;
|-&lt;br /&gt;
| 2022&lt;br /&gt;
| 07E6&lt;br /&gt;
| Xetec&lt;br /&gt;
|-&lt;br /&gt;
| 2023&lt;br /&gt;
| 07E7&lt;br /&gt;
| Micron Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2024&lt;br /&gt;
| 07E8&lt;br /&gt;
| CH Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2025&lt;br /&gt;
| 07E9&lt;br /&gt;
| American Liquid Light&lt;br /&gt;
|-&lt;br /&gt;
| 2026&lt;br /&gt;
| 07EA&lt;br /&gt;
| Progressive Peripherals &amp;amp;amp; Software&lt;br /&gt;
| Also used by Ateo&lt;br /&gt;
|-&lt;br /&gt;
| 2027&lt;br /&gt;
| 07EB&lt;br /&gt;
| Wicat Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2028&lt;br /&gt;
| 07EC&lt;br /&gt;
| Applied Systems &amp;amp;amp; Peripherals&lt;br /&gt;
|-&lt;br /&gt;
| 2029&lt;br /&gt;
| 07ED&lt;br /&gt;
| Delaware Valley Software&lt;br /&gt;
|-&lt;br /&gt;
| 2030&lt;br /&gt;
| 07EE&lt;br /&gt;
| Palomax&lt;br /&gt;
|-&lt;br /&gt;
| 2031&lt;br /&gt;
| 07EF&lt;br /&gt;
| Incognito Software&lt;br /&gt;
|-&lt;br /&gt;
| 2032&lt;br /&gt;
| 07F0&lt;br /&gt;
| Jadesign&lt;br /&gt;
|-&lt;br /&gt;
| 2033&lt;br /&gt;
| 07F1&lt;br /&gt;
| BVR&lt;br /&gt;
|-&lt;br /&gt;
| 2034&lt;br /&gt;
| 07F2&lt;br /&gt;
| Spirit Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2035&lt;br /&gt;
| 07F3&lt;br /&gt;
| Spirit Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2036&lt;br /&gt;
| 07F4&lt;br /&gt;
| Atronic&lt;br /&gt;
|-&lt;br /&gt;
| 2037&lt;br /&gt;
| 07F5&lt;br /&gt;
| Scott Karlin&lt;br /&gt;
|-&lt;br /&gt;
| 2038&lt;br /&gt;
| 07F6&lt;br /&gt;
| Howitch&lt;br /&gt;
|-&lt;br /&gt;
| 2039&lt;br /&gt;
| 07F7&lt;br /&gt;
| Sullivan Brothers Visual Engineers&lt;br /&gt;
|-&lt;br /&gt;
| 2040&lt;br /&gt;
| 07F8&lt;br /&gt;
| G I T&lt;br /&gt;
|-&lt;br /&gt;
| 2041&lt;br /&gt;
| 07F9&lt;br /&gt;
| Amigo Business Computers&lt;br /&gt;
|-&lt;br /&gt;
| 2042&lt;br /&gt;
| 07FA&lt;br /&gt;
| Micro E Ab&lt;br /&gt;
|-&lt;br /&gt;
| 2043&lt;br /&gt;
| 07FB&lt;br /&gt;
| Ralph Kruse&lt;br /&gt;
|-&lt;br /&gt;
| 2044&lt;br /&gt;
| 07FC&lt;br /&gt;
| Clearpoint Research&lt;br /&gt;
|-&lt;br /&gt;
| 2045&lt;br /&gt;
| 07FD&lt;br /&gt;
| Kodiak&lt;br /&gt;
|-&lt;br /&gt;
| 2046&lt;br /&gt;
| 07FE&lt;br /&gt;
| BSC&lt;br /&gt;
| Originally registered to Phoenix Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2047&lt;br /&gt;
| 07FF&lt;br /&gt;
| No Name Shown&lt;br /&gt;
|-&lt;br /&gt;
| 2048&lt;br /&gt;
| 0800&lt;br /&gt;
| Commodore Braunschweig&lt;br /&gt;
|-&lt;br /&gt;
| 2049&lt;br /&gt;
| 0801&lt;br /&gt;
| BSC&lt;br /&gt;
| Originally registered to Elaborate Bytes&lt;br /&gt;
|-&lt;br /&gt;
| 2050&lt;br /&gt;
| 0802&lt;br /&gt;
| Kronos/C Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2051&lt;br /&gt;
| 0803&lt;br /&gt;
| Spartanics&lt;br /&gt;
|-&lt;br /&gt;
| 2052&lt;br /&gt;
| 0804&lt;br /&gt;
| Jochheim Computer Tuning&lt;br /&gt;
|-&lt;br /&gt;
| 2053&lt;br /&gt;
| 0805&lt;br /&gt;
| Trans Data Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2054&lt;br /&gt;
| 0806&lt;br /&gt;
| Applied Systems &amp;amp;amp; Peripherals Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2055&lt;br /&gt;
| 0807&lt;br /&gt;
| Checkpoint Technologies&lt;br /&gt;
| Originally registered to Amiga Solutions&lt;br /&gt;
|-&lt;br /&gt;
| 2056&lt;br /&gt;
| 0808&lt;br /&gt;
| Adept Development&lt;br /&gt;
|-&lt;br /&gt;
| 2057&lt;br /&gt;
| 0809&lt;br /&gt;
| Advanced Computer Design&lt;br /&gt;
|-&lt;br /&gt;
| 2058&lt;br /&gt;
| 080A&lt;br /&gt;
| Sir Netics&lt;br /&gt;
|-&lt;br /&gt;
| 2059&lt;br /&gt;
| 080B&lt;br /&gt;
| Expert Services&lt;br /&gt;
|-&lt;br /&gt;
| 2060&lt;br /&gt;
| 080C&lt;br /&gt;
| Digital Art Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2061&lt;br /&gt;
| 080D&lt;br /&gt;
| Adept Development&lt;br /&gt;
|-&lt;br /&gt;
| 2062&lt;br /&gt;
| 080E&lt;br /&gt;
| Expansion Technologies (Expansion Systems)&lt;br /&gt;
|-&lt;br /&gt;
| 2063&lt;br /&gt;
| 080F&lt;br /&gt;
| Alphatech&lt;br /&gt;
|-&lt;br /&gt;
| 2064&lt;br /&gt;
| 0810&lt;br /&gt;
| Edotronik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2065&lt;br /&gt;
| 0811&lt;br /&gt;
| California Access/Synergy&lt;br /&gt;
| Originally registered to Logical Design Works&lt;br /&gt;
|-&lt;br /&gt;
| 2066&lt;br /&gt;
| 0812&lt;br /&gt;
| Bowden, Williams, Full &amp;amp; Assoc.&lt;br /&gt;
|-&lt;br /&gt;
| 2067&lt;br /&gt;
| 0813&lt;br /&gt;
| NES, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2068&lt;br /&gt;
| 0814&lt;br /&gt;
| Amdev&lt;br /&gt;
|-&lt;br /&gt;
| 2069&lt;br /&gt;
| 0815&lt;br /&gt;
| Big Brother Security Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2070&lt;br /&gt;
| 0816&lt;br /&gt;
| Active Circuits Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2071&lt;br /&gt;
| 0817&lt;br /&gt;
| ICD, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2072&lt;br /&gt;
| 0818&lt;br /&gt;
| Multi-Meg Electronique&lt;br /&gt;
|-&lt;br /&gt;
| 2073&lt;br /&gt;
| 0819&lt;br /&gt;
| Kupke Computertechnik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2074&lt;br /&gt;
| 081A&lt;br /&gt;
| The Checkered Ball&lt;br /&gt;
|-&lt;br /&gt;
| 2075&lt;br /&gt;
| 081B&lt;br /&gt;
| Hi Tension Computer Services Ltd. (UK)&lt;br /&gt;
|-&lt;br /&gt;
| 2076&lt;br /&gt;
| 081C&lt;br /&gt;
| Alfa Data&lt;br /&gt;
| Originally assigned to Elmtech Research, Ltd. (UK)&lt;br /&gt;
|-&lt;br /&gt;
| 2077&lt;br /&gt;
| 081D&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
| Originally registered to Clartscreen, Ltd. (UK)&lt;br /&gt;
|-&lt;br /&gt;
| 2078&lt;br /&gt;
| 081E&lt;br /&gt;
| Interworks&lt;br /&gt;
|-&lt;br /&gt;
| 2079&lt;br /&gt;
| 081F&lt;br /&gt;
| Galysh Enterprises&lt;br /&gt;
|-&lt;br /&gt;
| 2080&lt;br /&gt;
| 0820&lt;br /&gt;
| Hardital Synthesis&lt;br /&gt;
| Originally registered to Realtime Games Software Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2081&lt;br /&gt;
| 0821&lt;br /&gt;
| GBS&lt;br /&gt;
|-&lt;br /&gt;
| 2082&lt;br /&gt;
| 0822&lt;br /&gt;
| Circum Design Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2083&lt;br /&gt;
| 0823&lt;br /&gt;
| Alberta Micro Electronic Center&lt;br /&gt;
|-&lt;br /&gt;
| 2084&lt;br /&gt;
| 0824&lt;br /&gt;
| Bestech&lt;br /&gt;
|-&lt;br /&gt;
| 2085&lt;br /&gt;
| 0825&lt;br /&gt;
| Lasar Fantasy&lt;br /&gt;
|-&lt;br /&gt;
| 2086&lt;br /&gt;
| 0826&lt;br /&gt;
| Pulsar&lt;br /&gt;
|-&lt;br /&gt;
| 2087&lt;br /&gt;
| 0827&lt;br /&gt;
| Ivis&lt;br /&gt;
|-&lt;br /&gt;
| 2088&lt;br /&gt;
| 0828&lt;br /&gt;
| Applied Engineering&lt;br /&gt;
|-&lt;br /&gt;
| 2089&lt;br /&gt;
| 0829&lt;br /&gt;
| Solid-State Design &amp;amp;amp; Development&lt;br /&gt;
|-&lt;br /&gt;
| 2090&lt;br /&gt;
| 082A&lt;br /&gt;
| Vison Quest&lt;br /&gt;
|-&lt;br /&gt;
| 2091&lt;br /&gt;
| 082B&lt;br /&gt;
| Seaview Software&lt;br /&gt;
|-&lt;br /&gt;
| 2092&lt;br /&gt;
| 082C&lt;br /&gt;
| BSC&lt;br /&gt;
| Mistakenly used by ADS (Advanced Development Software)&lt;br /&gt;
|-&lt;br /&gt;
| 2093&lt;br /&gt;
| 082D&lt;br /&gt;
| Bernd Culenfeld&lt;br /&gt;
|-&lt;br /&gt;
| 2094&lt;br /&gt;
| 082E&lt;br /&gt;
| American Liquid Light&lt;br /&gt;
|-&lt;br /&gt;
| 2095&lt;br /&gt;
| 082F&lt;br /&gt;
| CEGITES&lt;br /&gt;
|-&lt;br /&gt;
| 2096&lt;br /&gt;
| 0830&lt;br /&gt;
| Quadlite Computers Ltd.&lt;br /&gt;
| Originally registered to EV Industries&lt;br /&gt;
|-&lt;br /&gt;
| 2097&lt;br /&gt;
| 0831&lt;br /&gt;
| Silicon Peace&lt;br /&gt;
|-&lt;br /&gt;
| 2098&lt;br /&gt;
| 0832&lt;br /&gt;
| Black Belt Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2099&lt;br /&gt;
| 0833&lt;br /&gt;
| Village Tronic&lt;br /&gt;
| Originally registerd to Steve Yaeger&lt;br /&gt;
|-&lt;br /&gt;
| 2100&lt;br /&gt;
| 0834&lt;br /&gt;
| ReadySoft&lt;br /&gt;
|-&lt;br /&gt;
| 2101&lt;br /&gt;
| 0835&lt;br /&gt;
| Phoenix Micro Technologies&lt;br /&gt;
|-&lt;br /&gt;
| 2102&lt;br /&gt;
| 0836&lt;br /&gt;
| Advanced Systems &amp;amp; Software&lt;br /&gt;
| Orignally assigned to Preferred Technology&lt;br /&gt;
|-&lt;br /&gt;
| 2103&lt;br /&gt;
| 0837&lt;br /&gt;
| Rombo Productions&lt;br /&gt;
|-&lt;br /&gt;
| 2104&lt;br /&gt;
| 0838&lt;br /&gt;
| Impulse Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2105&lt;br /&gt;
| 0839&lt;br /&gt;
| Beta Unlimited&lt;br /&gt;
|-&lt;br /&gt;
| 2106&lt;br /&gt;
| 083A&lt;br /&gt;
| Memory Expansion System, Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2107&lt;br /&gt;
| 083B&lt;br /&gt;
| Vortex Computer Systems GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2108&lt;br /&gt;
| 083C&lt;br /&gt;
| Platypus Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2109&lt;br /&gt;
| 083D&lt;br /&gt;
| Gigatron OHG&lt;br /&gt;
|-&lt;br /&gt;
| 2110&lt;br /&gt;
| 083E&lt;br /&gt;
| PG Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2111&lt;br /&gt;
| 083F&lt;br /&gt;
| New Technologies Group&lt;br /&gt;
|-&lt;br /&gt;
| 2112&lt;br /&gt;
| 0840&lt;br /&gt;
| Interactive Video Systems (IVS)&lt;br /&gt;
| Pacific Peripherals&lt;br /&gt;
|-&lt;br /&gt;
| 2113&lt;br /&gt;
| 0841&lt;br /&gt;
| Vector&lt;br /&gt;
| Originally registered to H. K. Computer&lt;br /&gt;
|-&lt;br /&gt;
| 2114&lt;br /&gt;
| 0842&lt;br /&gt;
| Pacific Digital&lt;br /&gt;
| Originally registered to C. H. Helfrich Elektronik&lt;br /&gt;
|-&lt;br /&gt;
| 2115&lt;br /&gt;
| 0843&lt;br /&gt;
| Xanadu&lt;br /&gt;
|-&lt;br /&gt;
| 2116&lt;br /&gt;
| 0844&lt;br /&gt;
| Pacific Digital&lt;br /&gt;
| Originally registered to AMS&lt;br /&gt;
|-&lt;br /&gt;
| 2117&lt;br /&gt;
| 0845&lt;br /&gt;
| X-Pert&lt;br /&gt;
|-&lt;br /&gt;
| 2118&lt;br /&gt;
| 0846&lt;br /&gt;
| The Amiga Centre&lt;br /&gt;
|-&lt;br /&gt;
| 2119&lt;br /&gt;
| 0847&lt;br /&gt;
| Digital Pacific&lt;br /&gt;
|-&lt;br /&gt;
| 2120&lt;br /&gt;
| 0848&lt;br /&gt;
| Solid State Leisure&lt;br /&gt;
|-&lt;br /&gt;
| 2121&lt;br /&gt;
| 0849&lt;br /&gt;
| Hydra Systems&lt;br /&gt;
| Originally registered to Analog Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2122&lt;br /&gt;
| 084A&lt;br /&gt;
| Cumana&lt;br /&gt;
|-&lt;br /&gt;
| 2123&lt;br /&gt;
| 084B&lt;br /&gt;
| KAPS 2C Conception&lt;br /&gt;
|-&lt;br /&gt;
| 2124&lt;br /&gt;
| 084C&lt;br /&gt;
| Mike Mason&lt;br /&gt;
|-&lt;br /&gt;
| 2125&lt;br /&gt;
| 084D&lt;br /&gt;
| For Your Eyes&lt;br /&gt;
|-&lt;br /&gt;
| 2126&lt;br /&gt;
| 084E&lt;br /&gt;
| Volkmar Breitfeld Computersysteme&lt;br /&gt;
|-&lt;br /&gt;
| 2127&lt;br /&gt;
| 084F&lt;br /&gt;
| Sunrize Industries&lt;br /&gt;
|-&lt;br /&gt;
| 2128&lt;br /&gt;
| 0850&lt;br /&gt;
| Scott Advanced Micro Designs&lt;br /&gt;
|-&lt;br /&gt;
| 2129&lt;br /&gt;
| 0851&lt;br /&gt;
| Digital Micronics&lt;br /&gt;
|-&lt;br /&gt;
| 2130&lt;br /&gt;
| 0852&lt;br /&gt;
| Alfa-Laval&lt;br /&gt;
|-&lt;br /&gt;
| 2131&lt;br /&gt;
| 0853&lt;br /&gt;
| Multigros A/S&lt;br /&gt;
|-&lt;br /&gt;
| 2132&lt;br /&gt;
| 0854&lt;br /&gt;
| Archos&lt;br /&gt;
|-&lt;br /&gt;
| 2133&lt;br /&gt;
| 0855&lt;br /&gt;
| Icom Simulations&lt;br /&gt;
|-&lt;br /&gt;
| 2134&lt;br /&gt;
| 0856&lt;br /&gt;
| Commodore Test Engineering Group&lt;br /&gt;
|-&lt;br /&gt;
| 2135&lt;br /&gt;
| 0857&lt;br /&gt;
| Microcreations&lt;br /&gt;
|-&lt;br /&gt;
| 2136&lt;br /&gt;
| 0858&lt;br /&gt;
| Shoestring Productions&lt;br /&gt;
|-&lt;br /&gt;
| 2137&lt;br /&gt;
| 0859&lt;br /&gt;
| Faberushi&lt;br /&gt;
|-&lt;br /&gt;
| 2138&lt;br /&gt;
| 085A&lt;br /&gt;
| Evesham Micro Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2139&lt;br /&gt;
| 085B&lt;br /&gt;
| Panagolin Laser Software&lt;br /&gt;
|-&lt;br /&gt;
| 2140&lt;br /&gt;
| 085C&lt;br /&gt;
| Thomas Rudloff&lt;br /&gt;
|-&lt;br /&gt;
| 2141&lt;br /&gt;
| 085D&lt;br /&gt;
| Daniel Hohabir&lt;br /&gt;
|-&lt;br /&gt;
| 2142&lt;br /&gt;
| 085E&lt;br /&gt;
| GfxBase, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2143&lt;br /&gt;
| 085F&lt;br /&gt;
| Axellabs&lt;br /&gt;
|-&lt;br /&gt;
| 2144&lt;br /&gt;
| 0860&lt;br /&gt;
| Roctec Electronics Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2145&lt;br /&gt;
| 0861&lt;br /&gt;
| Omega Datentechnik&lt;br /&gt;
|-&lt;br /&gt;
| 2146&lt;br /&gt;
| 0862&lt;br /&gt;
| Atlantis&lt;br /&gt;
|-&lt;br /&gt;
| 2147&lt;br /&gt;
| 0863&lt;br /&gt;
| Skytec Computers&lt;br /&gt;
|-&lt;br /&gt;
| 2148&lt;br /&gt;
| 0864&lt;br /&gt;
| Protar Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2149&lt;br /&gt;
| 0865&lt;br /&gt;
| ACS&lt;br /&gt;
|-&lt;br /&gt;
| 2150&lt;br /&gt;
| 0866&lt;br /&gt;
| Software Results Enterprises&lt;br /&gt;
| Originally registered to University of Illinois&lt;br /&gt;
|-&lt;br /&gt;
| 2151&lt;br /&gt;
| 0867&lt;br /&gt;
| Infinity Systems Design Group&lt;br /&gt;
|-&lt;br /&gt;
| 2152&lt;br /&gt;
| 0868&lt;br /&gt;
| Trade It&lt;br /&gt;
|-&lt;br /&gt;
| 2153&lt;br /&gt;
| 0869&lt;br /&gt;
| Suntec, Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2154&lt;br /&gt;
| 086A&lt;br /&gt;
| DJW Micro Systems&lt;br /&gt;
| Originally registered to Tritec Marketing&lt;br /&gt;
|-&lt;br /&gt;
| 2155&lt;br /&gt;
| 086B&lt;br /&gt;
| Power Computing Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2156&lt;br /&gt;
| 086C&lt;br /&gt;
| MacroSystems&lt;br /&gt;
|-&lt;br /&gt;
| 2157&lt;br /&gt;
| 086D&lt;br /&gt;
| Masoboshi GmbH (DCE)&lt;br /&gt;
|-&lt;br /&gt;
| 2158&lt;br /&gt;
| 086E&lt;br /&gt;
| HAL Software Hardware Handel&lt;br /&gt;
|-&lt;br /&gt;
| 2159&lt;br /&gt;
| 086F&lt;br /&gt;
| Mainhattan Data&lt;br /&gt;
| Originally registered to Michael Lamm Computersysteme&lt;br /&gt;
|-&lt;br /&gt;
| 2160&lt;br /&gt;
| 0870&lt;br /&gt;
| Digital Processing System&lt;br /&gt;
| Originally registered to bbdp Electronics&lt;br /&gt;
|-&lt;br /&gt;
| 2161&lt;br /&gt;
| 0871&lt;br /&gt;
| Blue Ribbon Soundworks&lt;br /&gt;
| Originally registered to Design Computer Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2162&lt;br /&gt;
| 0872&lt;br /&gt;
| XPert&lt;br /&gt;
| Originally registered to The Station&lt;br /&gt;
|-&lt;br /&gt;
| 2163&lt;br /&gt;
| 0873&lt;br /&gt;
| DelaComp&lt;br /&gt;
| Originally registered to Bryan Williams&lt;br /&gt;
|-&lt;br /&gt;
| 2164&lt;br /&gt;
| 0874&lt;br /&gt;
| Superformance Computer Engineering GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 2165&lt;br /&gt;
| 0875&lt;br /&gt;
| Overland Engineering&lt;br /&gt;
|-&lt;br /&gt;
| 2166&lt;br /&gt;
| 0876&lt;br /&gt;
| Thomas Hamren&lt;br /&gt;
|-&lt;br /&gt;
| 2167&lt;br /&gt;
| 0877&lt;br /&gt;
| Village Tronic&lt;br /&gt;
|-&lt;br /&gt;
| 2168&lt;br /&gt;
| 0878&lt;br /&gt;
| Toolbox Design&lt;br /&gt;
|-&lt;br /&gt;
| 2169&lt;br /&gt;
| 0879&lt;br /&gt;
| Digital Processing System&lt;br /&gt;
|-&lt;br /&gt;
| 2170&lt;br /&gt;
| 087A&lt;br /&gt;
| Superformance&lt;br /&gt;
|-&lt;br /&gt;
| 2171&lt;br /&gt;
| 087B&lt;br /&gt;
| Utilities Unlimited&lt;br /&gt;
|-&lt;br /&gt;
| 2172&lt;br /&gt;
| 087C&lt;br /&gt;
| phase 5&lt;br /&gt;
|-&lt;br /&gt;
| 2173&lt;br /&gt;
| 087D&lt;br /&gt;
| Juergen Kommos&lt;br /&gt;
|-&lt;br /&gt;
| 2174&lt;br /&gt;
| 087E&lt;br /&gt;
| Electronic Design&lt;br /&gt;
|-&lt;br /&gt;
| 2175&lt;br /&gt;
| 087F&lt;br /&gt;
| James Cook University of North Queensland&lt;br /&gt;
|-&lt;br /&gt;
| 2176&lt;br /&gt;
| 0880&lt;br /&gt;
| AmiTrix Development&lt;br /&gt;
|-&lt;br /&gt;
| 2177&lt;br /&gt;
| 0881&lt;br /&gt;
| Ferranti&lt;br /&gt;
|-&lt;br /&gt;
| 2178&lt;br /&gt;
| 0882&lt;br /&gt;
| Leviathan Development&lt;br /&gt;
|-&lt;br /&gt;
| 2179&lt;br /&gt;
| 0883&lt;br /&gt;
| United Video Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2180&lt;br /&gt;
| 0884&lt;br /&gt;
| GPSoft Pty. Ltd.&lt;br /&gt;
| Originally registered to Juergen Kommos&lt;br /&gt;
|-&lt;br /&gt;
| 2181&lt;br /&gt;
| 0885&lt;br /&gt;
| ArMAX&lt;br /&gt;
| Oliver Bausch&lt;br /&gt;
|-&lt;br /&gt;
| 2182&lt;br /&gt;
| 0886&lt;br /&gt;
| CP Computer&lt;br /&gt;
|-&lt;br /&gt;
| 2183&lt;br /&gt;
| 0887&lt;br /&gt;
| AMOK - Amiga Module &amp;amp;amp; Oberon Klub&lt;br /&gt;
|-&lt;br /&gt;
| 2184&lt;br /&gt;
| 0888&lt;br /&gt;
| ITEK Neser &amp;amp;amp; Sieber GbR&lt;br /&gt;
|-&lt;br /&gt;
| 2185&lt;br /&gt;
| 0889&lt;br /&gt;
| Phillip C. Lello&lt;br /&gt;
|-&lt;br /&gt;
| 2186&lt;br /&gt;
| 088A&lt;br /&gt;
| Cyborg Design Services&lt;br /&gt;
|-&lt;br /&gt;
| 2187&lt;br /&gt;
| 088B&lt;br /&gt;
| G2 Systems&lt;br /&gt;
|-&lt;br /&gt;
| 2188&lt;br /&gt;
| 088C&lt;br /&gt;
| Pro System Computersysteme&lt;br /&gt;
|-&lt;br /&gt;
| 2189&lt;br /&gt;
| 088D&lt;br /&gt;
| ZEUS Electronic&lt;br /&gt;
| Originally registered to MSPI (Markt &amp;amp;amp; Technik)&lt;br /&gt;
|-&lt;br /&gt;
| 2190&lt;br /&gt;
| 088E&lt;br /&gt;
| Altatech&lt;br /&gt;
|-&lt;br /&gt;
| 2191&lt;br /&gt;
| 088F&lt;br /&gt;
| NewTek&lt;br /&gt;
|-&lt;br /&gt;
| 2192&lt;br /&gt;
| 0890&lt;br /&gt;
| M-TEC Hardware Design&lt;br /&gt;
| Originally registered to Hardware Design Udo Neuroth&lt;br /&gt;
|-&lt;br /&gt;
| 2193&lt;br /&gt;
| 0891&lt;br /&gt;
| Great Valley Products&lt;br /&gt;
| Originally registered to Viona Development&lt;br /&gt;
|-&lt;br /&gt;
| 2194&lt;br /&gt;
| 0892&lt;br /&gt;
| Amitek&lt;br /&gt;
| Originally assigned to Marpet Developments&lt;br /&gt;
|-&lt;br /&gt;
| 2195&lt;br /&gt;
| 0893&lt;br /&gt;
| Ingenieurbuero Helfrich&lt;br /&gt;
|-&lt;br /&gt;
| 2196&lt;br /&gt;
| 0894&lt;br /&gt;
| The Neo Group&lt;br /&gt;
|-&lt;br /&gt;
| 2197&lt;br /&gt;
| 0895&lt;br /&gt;
| Cyon&lt;br /&gt;
|-&lt;br /&gt;
| 2198&lt;br /&gt;
| 0896&lt;br /&gt;
| Bob Research Group&lt;br /&gt;
|-&lt;br /&gt;
| 2199&lt;br /&gt;
| 0897&lt;br /&gt;
| Richmond Sound Design Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2200&lt;br /&gt;
| 0898&lt;br /&gt;
| US Cybernetics&lt;br /&gt;
|-&lt;br /&gt;
| 2201&lt;br /&gt;
| 0899&lt;br /&gt;
| Fulvio Ieva&lt;br /&gt;
|-&lt;br /&gt;
| 2202&lt;br /&gt;
| 089A&lt;br /&gt;
| Silicon Studio&lt;br /&gt;
|-&lt;br /&gt;
| 2203&lt;br /&gt;
| 089B&lt;br /&gt;
| MacroSystems (USA)&lt;br /&gt;
| Was named Micro System Devices&lt;br /&gt;
|-&lt;br /&gt;
| 2204&lt;br /&gt;
| 089C&lt;br /&gt;
| Conspector Entertainment&lt;br /&gt;
|-&lt;br /&gt;
| 2205&lt;br /&gt;
| 089D&lt;br /&gt;
| Laserforum&lt;br /&gt;
|-&lt;br /&gt;
| 2206&lt;br /&gt;
| 089E&lt;br /&gt;
| Elbox Computer&lt;br /&gt;
| Mistakenly used by Index Information Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2207&lt;br /&gt;
| 089F&lt;br /&gt;
| Applied Magic Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 2208&lt;br /&gt;
| 08A0&lt;br /&gt;
| SDL Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 2560&lt;br /&gt;
| 0A00&lt;br /&gt;
| Harms&lt;br /&gt;
|-&lt;br /&gt;
| 2588&lt;br /&gt;
| 0A1C&lt;br /&gt;
| A1K.org Community&lt;br /&gt;
|-&lt;br /&gt;
| 2640&lt;br /&gt;
| 0A50&lt;br /&gt;
| Micronik&lt;br /&gt;
|-&lt;br /&gt;
| 3084&lt;br /&gt;
| 0C0C&lt;br /&gt;
| Team 4&lt;br /&gt;
|-&lt;br /&gt;
| 3643&lt;br /&gt;
| 0E3B&lt;br /&gt;
| E3B&lt;br /&gt;
| Michael Boehmer&lt;br /&gt;
|-&lt;br /&gt;
| 3855&lt;br /&gt;
| 0F0F&lt;br /&gt;
| Micronik&lt;br /&gt;
|-&lt;br /&gt;
| 4096&lt;br /&gt;
| 1000&lt;br /&gt;
| MegaMicro&lt;br /&gt;
|-&lt;br /&gt;
| 4110&lt;br /&gt;
| 100E&lt;br /&gt;
| DigiFeX&lt;br /&gt;
|-&lt;br /&gt;
| 4136&lt;br /&gt;
| 1028&lt;br /&gt;
| Imtronics/Memphis&lt;br /&gt;
|-&lt;br /&gt;
| 4149&lt;br /&gt;
| 1035&lt;br /&gt;
| PROTAR&lt;br /&gt;
|-&lt;br /&gt;
| 4369&lt;br /&gt;
| 1111&lt;br /&gt;
| Frank Strauß Elektronik&lt;br /&gt;
| Also used by Kupke&lt;br /&gt;
|-&lt;br /&gt;
| 4626&lt;br /&gt;
| 1212&lt;br /&gt;
| Individual Computers&lt;br /&gt;
|-&lt;br /&gt;
| 4648&lt;br /&gt;
| 1228&lt;br /&gt;
| Flesch Hornemann Computer Elec.&lt;br /&gt;
|-&lt;br /&gt;
| 4680&lt;br /&gt;
| 1248&lt;br /&gt;
| Kupke Computertechnik GmbH&lt;br /&gt;
|-&lt;br /&gt;
| 4711&lt;br /&gt;
| 1267&lt;br /&gt;
| RBM digitaltechnik&lt;br /&gt;
|-&lt;br /&gt;
| 4754&lt;br /&gt;
| 1292&lt;br /&gt;
| MacroSystems&lt;br /&gt;
|-&lt;br /&gt;
| 5000&lt;br /&gt;
| 1388&lt;br /&gt;
| ITH&lt;br /&gt;
|-&lt;br /&gt;
| 5001&lt;br /&gt;
| 1389&lt;br /&gt;
| VMC&lt;br /&gt;
|-&lt;br /&gt;
| 5010&lt;br /&gt;
| 1392&lt;br /&gt;
| Ambience Creation Technology&lt;br /&gt;
|-&lt;br /&gt;
| 5011&lt;br /&gt;
| 1393&lt;br /&gt;
| Creative Development&lt;br /&gt;
|-&lt;br /&gt;
| 5012&lt;br /&gt;
| 1394&lt;br /&gt;
| Georg Braun&lt;br /&gt;
|-&lt;br /&gt;
| 5013&lt;br /&gt;
| 1395&lt;br /&gt;
| Swedish User Group of Amiga&lt;br /&gt;
|-&lt;br /&gt;
| 5014&lt;br /&gt;
| 1396&lt;br /&gt;
| Jakub Bednarski&lt;br /&gt;
|-&lt;br /&gt;
| 5015&lt;br /&gt;
| 1397&lt;br /&gt;
| KryoFlux, Ltd.&lt;br /&gt;
|-&lt;br /&gt;
| 5016&lt;br /&gt;
| 1398&lt;br /&gt;
| Igor Majstorovic&lt;br /&gt;
|-&lt;br /&gt;
| 5017&lt;br /&gt;
| 1399&lt;br /&gt;
| Alastair M. Robinson&lt;br /&gt;
|-&lt;br /&gt;
| 5018&lt;br /&gt;
| 139A&lt;br /&gt;
| Austex Software&lt;br /&gt;
|-&lt;br /&gt;
| 5019&lt;br /&gt;
| 139B&lt;br /&gt;
| Sören Gust&lt;br /&gt;
|-&lt;br /&gt;
| 5020&lt;br /&gt;
| 139C&lt;br /&gt;
| Rok Krajnc&lt;br /&gt;
|-&lt;br /&gt;
| 5030&lt;br /&gt;
| 13A6&lt;br /&gt;
| Tim Tashpulatov&lt;br /&gt;
|-&lt;br /&gt;
| 5040&lt;br /&gt;
| 13B0&lt;br /&gt;
| 7-bit&lt;br /&gt;
|-&lt;br /&gt;
| 5050&lt;br /&gt;
| 13BA&lt;br /&gt;
| Sakura IT&lt;br /&gt;
|-&lt;br /&gt;
| 5060&lt;br /&gt;
| 13C4&lt;br /&gt;
| FPGAArcade&lt;br /&gt;
|-&lt;br /&gt;
| 5070&lt;br /&gt;
| 13CE&lt;br /&gt;
| CancerSoft Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 5080&lt;br /&gt;
| 13D8&lt;br /&gt;
| Stephen Leary&lt;br /&gt;
|-&lt;br /&gt;
| 5090&lt;br /&gt;
| 13E2&lt;br /&gt;
| DMA Softlab LLC&lt;br /&gt;
|-&lt;br /&gt;
| 5100&lt;br /&gt;
| 13EC&lt;br /&gt;
| Brookhouse Engineering&lt;br /&gt;
|-&lt;br /&gt;
| 5110&lt;br /&gt;
| 13F6&lt;br /&gt;
| Eduardo Arana&lt;br /&gt;
|-&lt;br /&gt;
| 5120&lt;br /&gt;
| 1400&lt;br /&gt;
| CS-LAB&lt;br /&gt;
|-&lt;br /&gt;
| 5130&lt;br /&gt;
| 140A&lt;br /&gt;
| Robert Miranda&lt;br /&gt;
|-&lt;br /&gt;
| 5140&lt;br /&gt;
| 1414&lt;br /&gt;
| RastPort&lt;br /&gt;
|-&lt;br /&gt;
| 5132&lt;br /&gt;
| 140C&lt;br /&gt;
| UAS Interface Ltd6&lt;br /&gt;
|-&lt;br /&gt;
| 5150&lt;br /&gt;
| 141E&lt;br /&gt;
| Amiga Kit&lt;br /&gt;
|-&lt;br /&gt;
| 5160&lt;br /&gt;
| 1428&lt;br /&gt;
| Central Texas Commodore User Group&lt;br /&gt;
|-&lt;br /&gt;
| 5170&lt;br /&gt;
| 1432&lt;br /&gt;
| Confusion Research Center&lt;br /&gt;
|-&lt;br /&gt;
| 5180&lt;br /&gt;
| 143C&lt;br /&gt;
| Solar Soyuz Zaibatsu&lt;br /&gt;
|-&lt;br /&gt;
| 5500&lt;br /&gt;
| 157C&lt;br /&gt;
| Inhouse Information&lt;br /&gt;
|-&lt;br /&gt;
| 5768&lt;br /&gt;
| 1688&lt;br /&gt;
| Bio Con&lt;br /&gt;
|-&lt;br /&gt;
| 6148&lt;br /&gt;
| 1804&lt;br /&gt;
| HK-Computer&lt;br /&gt;
|-&lt;br /&gt;
| 6502&lt;br /&gt;
| 1966&lt;br /&gt;
| Cloanto&lt;br /&gt;
|-&lt;br /&gt;
| 6520&lt;br /&gt;
| 1978&lt;br /&gt;
| Oliver Gantert&lt;br /&gt;
|-&lt;br /&gt;
| 7777&lt;br /&gt;
| 1E61&lt;br /&gt;
| Rafal Gabriel Chyla&lt;br /&gt;
|-&lt;br /&gt;
| 8215&lt;br /&gt;
| 2017&lt;br /&gt;
| Vortex&lt;br /&gt;
|-&lt;br /&gt;
| 8244&lt;br /&gt;
| 2034&lt;br /&gt;
| Spirit Technology&lt;br /&gt;
|-&lt;br /&gt;
| 8290&lt;br /&gt;
| 2062&lt;br /&gt;
| Expansion Systems&lt;br /&gt;
|-&lt;br /&gt;
| 8448&lt;br /&gt;
| 2100&lt;br /&gt;
| ReadySoft&lt;br /&gt;
|-&lt;br /&gt;
| 8512&lt;br /&gt;
| 2140&lt;br /&gt;
| Phase 5 Digital Products&lt;br /&gt;
|-&lt;br /&gt;
| 8553&lt;br /&gt;
| 2169&lt;br /&gt;
| Digital Processing Systems Inc.&lt;br /&gt;
|-&lt;br /&gt;
| 8704&lt;br /&gt;
| 2200&lt;br /&gt;
| ACT Elektronik&lt;br /&gt;
|-&lt;br /&gt;
| 8738&lt;br /&gt;
| 2222&lt;br /&gt;
| ACT Elektronik&lt;br /&gt;
|-&lt;br /&gt;
| 9512&lt;br /&gt;
| 2528&lt;br /&gt;
| Tower Technologies&lt;br /&gt;
|-&lt;br /&gt;
| 10676&lt;br /&gt;
| 29B4&lt;br /&gt;
| Electronic Design&lt;br /&gt;
|-&lt;br /&gt;
| 14195&lt;br /&gt;
| 3773&lt;br /&gt;
| Media-net-Point&lt;br /&gt;
|-&lt;br /&gt;
| 14501&lt;br /&gt;
| 38A5&lt;br /&gt;
| Petsoff, Finland&lt;br /&gt;
|-&lt;br /&gt;
| 16375&lt;br /&gt;
| 3FF7&lt;br /&gt;
| Uwe Gerlach&lt;br /&gt;
|-&lt;br /&gt;
| 16707&lt;br /&gt;
| 4143&lt;br /&gt;
| Ateo Concepts&lt;br /&gt;
|-&lt;br /&gt;
| 16708&lt;br /&gt;
| 4144&lt;br /&gt;
| ALiENDESiGN&lt;br /&gt;
|-&lt;br /&gt;
| 16945&lt;br /&gt;
| 4231&lt;br /&gt;
| A.C.T.&lt;br /&gt;
|-&lt;br /&gt;
| 17740&lt;br /&gt;
| 454C&lt;br /&gt;
| HK-Computer (ELSAT)&lt;br /&gt;
|-&lt;br /&gt;
| 18260&lt;br /&gt;
| 4754&lt;br /&gt;
| MacroSystems (Germany)&lt;br /&gt;
|-&lt;br /&gt;
| 19796&lt;br /&gt;
| 4D54&lt;br /&gt;
| Markt &amp;amp; Technik&lt;br /&gt;
|-&lt;br /&gt;
| 22359&lt;br /&gt;
| 5757&lt;br /&gt;
| Markt &amp;amp; Technik&lt;br /&gt;
|-&lt;br /&gt;
| 26464&lt;br /&gt;
| 6760&lt;br /&gt;
| Combitec&lt;br /&gt;
|-&lt;br /&gt;
| 26470&lt;br /&gt;
| 6766&lt;br /&gt;
| Combitec&lt;br /&gt;
|-&lt;br /&gt;
| 28014&lt;br /&gt;
| 6D6E&lt;br /&gt;
| MNT Media and Technology UG&lt;br /&gt;
|-&lt;br /&gt;
| 32768&lt;br /&gt;
| 8000&lt;br /&gt;
| M.A.S.T.&lt;br /&gt;
|-&lt;br /&gt;
| 42240&lt;br /&gt;
| A500&lt;br /&gt;
| Aethreum Digital&lt;br /&gt;
|-&lt;br /&gt;
| 43437&lt;br /&gt;
| A9AD&lt;br /&gt;
| Reis-Ware&lt;br /&gt;
|-&lt;br /&gt;
| 43521&lt;br /&gt;
| AA01&lt;br /&gt;
| Cameron&lt;br /&gt;
|-&lt;br /&gt;
| 43537&lt;br /&gt;
| AA11&lt;br /&gt;
| Reis-Ware&lt;br /&gt;
|-&lt;br /&gt;
| 44359&lt;br /&gt;
| AD47&lt;br /&gt;
| Matay&lt;br /&gt;
|-&lt;br /&gt;
| 46504&lt;br /&gt;
| B5A8&lt;br /&gt;
| Phoenix&lt;br /&gt;
|-&lt;br /&gt;
| 49160&lt;br /&gt;
| C008&lt;br /&gt;
| Combitec&lt;br /&gt;
|-&lt;br /&gt;
| 61453&lt;br /&gt;
| F00D&lt;br /&gt;
| Forefront Technologies Inc.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
For any changes/additions to this registry please use the [http://www.amigaos.net/contact AmigaOS web site contact form].&lt;/div&gt;</summary>
		<author><name>Costel Mincea</name></author>
	</entry>
	<entry>
		<id>https://wiki.amigaos.net/w/index.php?title=AmigaOS_Manual:_AmigaDOS_Using_the_Editors&amp;diff=12580</id>
		<title>AmigaOS Manual: AmigaDOS Using the Editors</title>
		<link rel="alternate" type="text/html" href="https://wiki.amigaos.net/w/index.php?title=AmigaOS_Manual:_AmigaDOS_Using_the_Editors&amp;diff=12580"/>
		<updated>2026-02-12T07:21:56Z</updated>

		<summary type="html">&lt;p&gt;Costel Mincea: /* EDIT */ Set the defaults of PREVIOUS and WIDTH to new 4.1 Final Edition Update 3 values&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;A text editor or word processing program is necessary for creating or editing text files and script files. Amiga Workbench software comes with three text editors. This chapter describes them in the following order:&lt;br /&gt;
&lt;br /&gt;
* ED&lt;br /&gt;
* MEmacs&lt;br /&gt;
* EDIT&lt;br /&gt;
&lt;br /&gt;
Each of the Amiga editors can be used separately for editing AmigaDOS scripts and programs; ED and MEmacs can be used for creating these files. If you are comfortable with the UNIX Emacs editor, you may prefer using the MEmacs editor. If you need to edit files containing binary code or you need to edit files too large to fit into memory, use EDIT. If you are not familiar with any of the editors, we recommend that you use the ED editor.&lt;br /&gt;
&lt;br /&gt;
Each editor has the basic functionality of a word processor, however, none of these editors support style formatting options, such as italics, page numbering, or different fonts. If you need these features, you can purchase third party word processing software containing such features for your Amiga.&lt;br /&gt;
&lt;br /&gt;
= ED =&lt;br /&gt;
&lt;br /&gt;
ED is a full screen ASCII text editor that uses menus and function keys to access its features. It is easy to use and is suitable for editing scripts, startup files, MountLists, and other simple files. Use either a mouse or the keyboard to perform operations with ED. Although ED&#039;s menus are preprogrammed, when you are familiar with the program, you can reconfigure them as needed.&lt;br /&gt;
&lt;br /&gt;
{{Note|ED does not accept files containing binary code. To edit this type of file, use EDIT or MEmacs.}}&lt;br /&gt;
&lt;br /&gt;
The bottom line of the ED window is the status line used for displaying messages, prompts, and commands. Error messages displayed on the status line remain until you enter another ED command. Figure 4-1 illustrates the ED window showing the status line.&lt;br /&gt;
&lt;br /&gt;
[[File:DosFig4-1.png|none|frame|ED Window with Status Line]]&lt;br /&gt;
&lt;br /&gt;
== Starting ED ==&lt;br /&gt;
&lt;br /&gt;
Start ED from a Shell or with the Workbench Execute Command menu item. Open ED at the prompt by entering ED and a new or existing file name, as follows:&lt;br /&gt;
&lt;br /&gt;
 1&amp;gt; ED &amp;lt;filename&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &amp;lt;filename&amp;gt; is the name of an existing file or a new file to be used for saving your work. If the file name specified cannot be found in the current directory, ED opens a blank window and displays the message Creating new file.&lt;br /&gt;
&lt;br /&gt;
The format for ED is the following:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;ED [FROM] &amp;lt;filename&amp;gt; [SIZE &amp;lt;n&amp;gt;] [WITH &amp;lt;filename&amp;gt;]&lt;br /&gt;
 [WINDOW &amp;lt;window specification&amp;gt;] [TABS &amp;lt;n&amp;gt;] [WIDTH | COLS &amp;lt;n&amp;gt;]&lt;br /&gt;
 [HEIGHT | ROWS &amp;lt;n&amp;gt;]&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The FROM argument specifies the source file to be edited. This argument is required, but the FROM keyword is optional.&lt;br /&gt;
&lt;br /&gt;
The SIZE argument changes the ED buffer size. ED has a default text buffer size of 40,000 bytes. For example:&lt;br /&gt;
&lt;br /&gt;
 1&amp;gt; ED Script SIZE 55000&lt;br /&gt;
&lt;br /&gt;
increase the size of the buffer to 55,000 bytes.&lt;br /&gt;
&lt;br /&gt;
The WITH argument specifies an ED command file that can contain any sequence of ED extended mode commands. When WITH is specified, ED executes the commands contained in the command file. The WITH argument&#039;s keywords is required if you use WITH.&lt;br /&gt;
&lt;br /&gt;
The WINDOW argument specifies the console type, such as RAX:0/0/640/256/EdWindow or CONSOLE:. The WINDOW argument&#039;s keyword is required if you use WINDOW.&lt;br /&gt;
&lt;br /&gt;
TABS sets the tab stop interval, which is the number of spaces to the right that the cursor moves when you press the Tab key. The default value for TABS is 3.&lt;br /&gt;
&lt;br /&gt;
The WIDTH and HEIGHT arguments adjust the size of the ED window by specifying the number of characters to display horizontally and vertically. By default the ED window is 640 x 200 picels or approximately 88 characters wide by 21 lines high.&lt;br /&gt;
&lt;br /&gt;
== Using ED ==&lt;br /&gt;
&lt;br /&gt;
All ED commands have key sequences and many are available through menus. You can enter ED commands in either of the following ways:&lt;br /&gt;
&lt;br /&gt;
* By choosing the command&#039;s menu item.&lt;br /&gt;
* By typing in the command&#039;s key sequence and pressing Return.&lt;br /&gt;
&lt;br /&gt;
In addition, you can use the mouse to perform some commands, such as those that control cursor movement.&lt;br /&gt;
&lt;br /&gt;
You can work on files in ED with the following two command modes:&lt;br /&gt;
&lt;br /&gt;
; Immediate&lt;br /&gt;
: Commands are executed as soon as typed. EP opens in immediate mode.&lt;br /&gt;
&lt;br /&gt;
; Extended&lt;br /&gt;
: Commands are not executed until you press Return or Esc.&lt;br /&gt;
&lt;br /&gt;
=== Immediate Commands ===&lt;br /&gt;
&lt;br /&gt;
In immediate mode, ED executes commands right away. Specify an immediate command by pressing a single key or Ctrl+key combination or by using the mouse. All immediate commands have corresponding extended versions.&lt;br /&gt;
&lt;br /&gt;
Immediate commands control the following:&lt;br /&gt;
&lt;br /&gt;
* Cursor movement&lt;br /&gt;
* Text scrolling&lt;br /&gt;
* Text insertion&lt;br /&gt;
* Text deletion&lt;br /&gt;
* Repetition of commands&lt;br /&gt;
&lt;br /&gt;
=== Moving the Cursor in Immediate Mode ===&lt;br /&gt;
&lt;br /&gt;
The cursor can be positioned anywhere in text by moving the pointer to the desired spot and clicking the selection button. To move the cursor with the keyboard, use the arrow keys, Tab, and Ctrl+key combinations.&lt;br /&gt;
&lt;br /&gt;
{{Note|In ED, the Tab key only moves the cursor. It does not insert Tab characters or spaces in a line.}}&lt;br /&gt;
&lt;br /&gt;
Move the cursor one position in any direction by pressing the appropriate arrow key. If the cursor is on the right edge of the screen, ED scrolls the text to the left do display the rest of the line. ED scrolls the text vertically one line at a time and horizontally ten characters at a time. You cannot move the cursor beyond the left edge of the line. If you try to move the cursor beyond the top or bottom of the file, ED displays a Top of File or Bottom of File message.&lt;br /&gt;
&lt;br /&gt;
Additional key combinations that control cursor movement are:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| Shift+up arrow || Top of the file.&lt;br /&gt;
|-&lt;br /&gt;
| Shift+down arrow || Bottom of the file.&lt;br /&gt;
|-&lt;br /&gt;
| Shift+left arrow || Left edge of the ED window (regardless of the margin setting).&lt;br /&gt;
|-&lt;br /&gt;
| Sift+right arrow || End of the current line.&lt;br /&gt;
|-&lt;br /&gt;
| Ctrl+] || Right edge of current line (if cursor is already there, it is moved to the left edge).&lt;br /&gt;
|-&lt;br /&gt;
| Ctrl+E || Start of the first line on the screen (if cursor is already there, it is moved to the end of the last line on the screen).&lt;br /&gt;
|-&lt;br /&gt;
| Ctrl+T || Start of the next word.&lt;br /&gt;
|-&lt;br /&gt;
| Ctrl+R || Space following the previous word.&lt;br /&gt;
|-&lt;br /&gt;
| Tab || The next tab position (multiple of the TABS value; 3 by default).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If your file has more lines than can fit in the ED window, you can scroll through the file vertically. Scroll one line at a time by pressing the up or down cursor key to move in the corresponding direction. Move the text in jumps by pressing:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| Ctrl+D || Moves 12 lines down through the file.&lt;br /&gt;
|-&lt;br /&gt;
| Ctrl+U || Moves 12 lines up through the file.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
These commands do not move the cursor position in the window; they redraw the text in the window with the new line at the cursor position.&lt;br /&gt;
&lt;br /&gt;
If something disturbs your screen, such as an alert from another program appearing in the ED window or message remarks in the status line, press:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| Ctrl+V || Refreshes the window display.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Inserting Text in Immediate Mode ===&lt;br /&gt;
&lt;br /&gt;
Any characters typed in immediate mode are inserted at the current cursor position and the cursor is shifted to the right. Any characters to the right of the cursor are shifted to make room for new text. If the line is wider than the width of the window, the window scrolls to the right to show what you are typing. If you move the cursor beyond the end of the line, ED inserts spaces between the end of the line and any new characters inserted.&lt;br /&gt;
&lt;br /&gt;
There is maximum limit of 255 characters in a line. If you add more characters, ED displays a Line Too Long message.&lt;br /&gt;
&lt;br /&gt;
To split the current line at the cursor, press Return. Any text to the left of the cursor remains on the original line. All text under and to the right of the cursor moves down onto a new line. Pressing Return at the end of the line creates a new blank line.&lt;br /&gt;
&lt;br /&gt;
=== Deleting Text in Immediate Mode ===&lt;br /&gt;
&lt;br /&gt;
ED has no type over mode. To replace a word or line, you must delete the existing words and insert new information with the following keys and key combinations:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| Backspace || Deletes the character to the left of the cursor.&lt;br /&gt;
|-&lt;br /&gt;
| Del || Deletes the character highlighted by the cursor.&lt;br /&gt;
|-&lt;br /&gt;
| Ctrl+O || If the cursor is over a space, all spaces up to the next character are deleted. If the cursor is over a character, all characters up to the next space are deleted.&lt;br /&gt;
|-&lt;br /&gt;
| Ctrl+Y || Deletes all characters from the cursor to the end of the line.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
When text is deleted, any characters remaining on the line shift to the left and any text beyond the right edge of the screen becomes visible.&lt;br /&gt;
&lt;br /&gt;
=== Changing Case in Immediate Mode ===&lt;br /&gt;
&lt;br /&gt;
You can change the case of text by positioning the cursor and pressing Ctrl+F. If the letter is lower case, it becomes upper case and vice versa. Ctrl+F does not change non-alphabetic characters or symbols.&lt;br /&gt;
&lt;br /&gt;
After you press Ctrl+F, the cursor moves to the right. You can hold down Ctrl+F to repeat the command until you change all the letters on the line.&lt;br /&gt;
&lt;br /&gt;
=== Extended Commands ===&lt;br /&gt;
&lt;br /&gt;
In extended mode, commands are displayed on the command line - or status line - at the bottom of the window. ED does not execute these commands until you press Return or Esc. If you use Esc to execute extended commands, ED remains in extended mode. If you use Return to execute extended commands, ED returns to immediate mode.&lt;br /&gt;
&lt;br /&gt;
Extended commands manage the following:&lt;br /&gt;
&lt;br /&gt;
* Program control&lt;br /&gt;
* Cursor movement&lt;br /&gt;
* Text modification&lt;br /&gt;
* Block control&lt;br /&gt;
* Searching and exchanging text&lt;br /&gt;
&lt;br /&gt;
To enter extended mode, press Esc. An asterisk appears as a prompt in the status line. Extended commands consist of one or two characters. Multiple extended commands can be typed on a single command line by separating them with a semicolon. Commands can be grouped together for ED to repeat automatically. Use Backspace to correct mistakes.&lt;br /&gt;
&lt;br /&gt;
You can also execute commands through the programmable menu and function keys. Reconfigure the menus and functions keys by assigning a command to the key or menu item of your choice as described on page 4-21.&lt;br /&gt;
&lt;br /&gt;
=== Using String Delimiters ===&lt;br /&gt;
&lt;br /&gt;
In some cases, commands require arguments, such as a number or a text strig. A string argument for an ED command must be enclosed in a pair of identical delimiter characters. In unambiguous situations you may omit the trailing delimiter. Valid delimiters include &amp;quot;, /, \, !, :, +, -, and %. You cannot use the same delimiter character inside your string. Invalid delimiter characters include letters, numbers, spaces, semicolons, question marks, brackets, and control characters.&lt;br /&gt;
&lt;br /&gt;
=== Using a File Requester ===&lt;br /&gt;
&lt;br /&gt;
You can also ask ED to use a file requester, allowing you to view the contents of the drives and directories in your system.&lt;br /&gt;
&lt;br /&gt;
To invoke a file requester for a load or save command, you must place a question mark (?) before the required string argument. Be sure to include a space before the question mark (for example, sa ?/Text/). Normally, when a command is followed by a string. ED treats the string as the file to be loaded or saved and attempts the operation immediately. However, the question mark indicates that you want to specify the file through a file requester. You must still specify a string after the question mark, but the string becomes the text that appears in the file requester title bar.&lt;br /&gt;
&lt;br /&gt;
== ED Menus ==&lt;br /&gt;
&lt;br /&gt;
ED has two sets of command menu assignments: default and expanded. The default menu assignments, as illustrated in Figure 4-2, are set up by the S:Ed-startup file, which is automatically executed each time you run ED. The S:Ed-startup file is a command file of ED extended mode commands, without the Escape characters. You can edit this file to set up custom menus, as described on page 4-21, or define preprogrammed function key assignments with the Set FN Key menu item.&lt;br /&gt;
&lt;br /&gt;
[[File:DosFig4-2.png|none|frame|Default Menu Assignments]]&lt;br /&gt;
&lt;br /&gt;
=== Enabling Expanded Menus ===&lt;br /&gt;
&lt;br /&gt;
The expanded command menu assignments, as illustrated in Figure 4-3, can be enabled by renaming or deleting the default S:Ed-startup file. If ED cannot find a file named S:Ed-startup, it opens with the expanded set of menus, providing more options.&lt;br /&gt;
&lt;br /&gt;
[[File:DosFig4-3.png|none|frame|Expanded Menu Assignments]]&lt;br /&gt;
&lt;br /&gt;
Rather then deleting your S-Ed-startup file, we recommend that you rename it as follows:&lt;br /&gt;
&lt;br /&gt;
# In the Workbench window, go to the Window menu and select Show All Files.&lt;br /&gt;
# Double-click on the S drawer icon.&lt;br /&gt;
# Click on the Ed-startup icon.&lt;br /&gt;
# Go to the Icons menu and choose Rename.&lt;br /&gt;
# Delete the name in the Rename requester&#039;s New Name text gadget and enter a new name for Ed-startup.&lt;br /&gt;
# Select OK.&lt;br /&gt;
&lt;br /&gt;
You can also create your own customized file of startup options. Avoid including Quit commands in the S:Ed-startup file since they can cause ED to quit immediately after opening.&lt;br /&gt;
&lt;br /&gt;
The menu items in both the default and expanded menus have the same function regardless of which set you use. All of the ED commands are available through the keyboard using extended mode commands even if they do not appear in any menu.&lt;br /&gt;
&lt;br /&gt;
The following sections describe the menu items found in the expanded menus and their corresponding extended and immediate mode commands. An ellipsis (...) indicates that an argument is required or that a menu item opens a requester or prompt.&lt;br /&gt;
&lt;br /&gt;
=== Project Menu ===&lt;br /&gt;
&lt;br /&gt;
The following are the expanded Project menu items:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| New || Esc,N,W || Creates a new file, replacing the existing file. The message Edits will be lost-type Y to confirm: is displayed. Press any key (except Y) to abort the command.&lt;br /&gt;
|-&lt;br /&gt;
| Open... || Esc,O,P... || Opens a file. Specify the file by entering the path to the file as a properly delimited string. (If slashes appear in the path to a file, do not use the slash as a delimiter.) The message Edits will be lost-type Y to confirm: reminds you that you are replacing the current file.&lt;br /&gt;
|-&lt;br /&gt;
| Insert File... || Esc,I,F... || Inserts a file into the current file. ED reads into memory the specified file at the point immediately following the current line.&lt;br /&gt;
|-&lt;br /&gt;
| Write Block... || Esc,W,B... || Writes the currently marked block to a specified file. ED overwrites any other files with that name and copies the block to the file.&lt;br /&gt;
|-&lt;br /&gt;
| Save || Esc,S,A || Saves the text to the current file, overwriting the existing text in the file. Use Save As to save to different file. SA followed by Q is equivalent to the X command.&lt;br /&gt;
|-&lt;br /&gt;
| Save As... || Esc,S,A... || Saves the text to the specified file name.&lt;br /&gt;
|-&lt;br /&gt;
| Save &amp;amp; Exit || Esc,X || Exits ED, saving the current file to the designated file name. ED writes the text it is holding in memory to the file that was specified when ED was opened and then terminates.&lt;br /&gt;
|-&lt;br /&gt;
| About || Esc,S,H || Shows the current state of the editor. The screen display information, such as the value of tab stops, current margins, block marks, and the name of the file being edited.&lt;br /&gt;
|-&lt;br /&gt;
| Quit || Esc,Q || Exits ED without saving changes. If you made any changes to the file, ED asks if you want to quit. If you press Y, ED terminates immediately without saving the changes to the file.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Edit Menu ===&lt;br /&gt;
&lt;br /&gt;
The following are commands used for editing:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| Undo Line || Esc,U || Reverses changes made to the current line. However, ED cannot undo a line deletion. Once you have moved from the current line, the U command cannot undo a change.&lt;br /&gt;
|-&lt;br /&gt;
| Star Block || Esc,B,S || Identify the beginning and end of a block of text. To specify a block of text to be moved, inserted, or deleted, place the cursor on the first line that you want in the block and enter the BS command. Move the cursor to the last line that you want in the block and enter the BE command.&amp;lt;br/&amp;gt;You cannot start or finish a block in the middle of a line.&lt;br /&gt;
|-&lt;br /&gt;
| Show Block || Esc,S,B || Redraws the display so the block is at the top of the screen.&lt;br /&gt;
|-&lt;br /&gt;
| Insert Block || Esc,I,B || Inserts a copy of the block after the current line. The block remains defined until you change the text. Use IB to insert copies of the block throughout the document.&lt;br /&gt;
|-&lt;br /&gt;
| Delete Block || Esc,D,B || Deletes a block.&lt;br /&gt;
|-&lt;br /&gt;
| Delete Line || Esc,D&amp;lt;br/&amp;gt;Ctrl+B || Deletes the entire line.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Movement Menu ===&lt;br /&gt;
&lt;br /&gt;
The following commands move the cursor around the screen:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| Top || Esc,T || Top of the file; first line of the file is brought to the top of the window.&lt;br /&gt;
|-&lt;br /&gt;
| Bottom || Esc,B || Bottom of the file; last line of the file is brought to the bottom of the window.&lt;br /&gt;
|-&lt;br /&gt;
| Go To Line... || Esc,M... || Move the cursor to the specified line. Enter the line number on the status line and press Return. The line specified is brought to the top of the window. If no number is given, the cursor goes to the top of the window.&lt;br /&gt;
|-&lt;br /&gt;
| Next Page || Esc,P,D&amp;lt;br/&amp;gt;Ctrl+D || Go to next page.&lt;br /&gt;
|-&lt;br /&gt;
| Previous Page || Esc,P,U&amp;lt;br/&amp;gt;Ctrl+U || Go to previous page.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Search Menu ===&lt;br /&gt;
&lt;br /&gt;
The following commands let you search through the file for specific instances of text. You can substitute one pattern of text with another (search and replace) and have ED request confirmation of (query) each replace. If the specified text is not found or there are no more instances of the text, the message Search failed is displayed. When using the Find and Replace menu commands, ED prompts for the text strings. Enter the text without delimiters. When using extended mode, include delimited strings with the command.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| Find...&amp;lt;br/&amp;gt;Find Next || Esc,s... || Finds the next occurrence of the specified string of text. The search starts one character beyond the current cursor position and continues forward through the file. If the string is found, the cursor moves to the start of the located string. The search is case-sensitive, unless the Ignore Case command is used. Find Next repeats the command.&lt;br /&gt;
|-&lt;br /&gt;
| Reverse Find...&amp;lt;br/&amp;gt;Reverse Find&amp;lt;br/&amp;gt;Next || Esc,B,F... || Searches backwards through the file for the specified string. This command finds the last occurrence of the string before the current cursor position. The search continues through to the beginning of the file. Reverse Find Next repeats the command.&lt;br /&gt;
|-&lt;br /&gt;
| Replace... || Esc,E... || Exchanges one occurrence of text with another.&amp;lt;br/&amp;gt;In extended mode, enter the strings enclosed by three delimiters. For example, to replace the word to with too, enter &amp;quot;to&amp;quot;too&amp;quot;. Specify empty strings by typing two delimiters with nothing between them. If the first string is empty, ED inserts the second string at the current cursor position. If the second string is empty, ED searches for the next occurrence of the first string and then deletes it. Note that ED ignores margin settings when exchanging text.&lt;br /&gt;
|-&lt;br /&gt;
| Global Replace || Esc,R,P,E... || Exchanges all occurrences of text.&lt;br /&gt;
|-&lt;br /&gt;
| Query-Replace... || Esc,E,Q... || Searches for the text to be exchanged and requests verification by displaying Exchange?. Enter Y to exchange or another other key to abort.&lt;br /&gt;
|-&lt;br /&gt;
| Global Query-Replace... || Esc,R,P,E,Q... || Searches for all occurrences of the text to be exchanged and requests verification for each. Enter Y to exchange or any other key to abort.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Settings Menu ===&lt;br /&gt;
&lt;br /&gt;
The following commands are used for setting up your ED environment:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| Set FN Key... || Esc,S,F... || Defines the function keys and other programmable keys. Defining function key and Ctrl+key commands is similar to defining menu items. See page 4-15 for instructions for defining function keys and an example of the Set FN Key command.&lt;br /&gt;
|-&lt;br /&gt;
| Show FN Key... || Esc,D,F&amp;lt;br/&amp;gt;&amp;lt;nowiki&amp;gt;&amp;lt;key&amp;gt;&amp;lt;/nowiki&amp;gt; || Displays the setting for the function key specified by &amp;lt;nowiki&amp;gt;&amp;lt;key&amp;gt;&amp;lt;/nowiki&amp;gt;. Enter a space and a key slot number for &amp;lt;nowiki&amp;gt;&amp;lt;key&amp;gt;&amp;lt;/nowiki&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| Reset Keys || Esc,R,K || Resets the key definitions to the default. See page 4-16 for a table of special key mappings.&lt;br /&gt;
|-&lt;br /&gt;
| Right Margin... || Esc,S,R... || Sets the right margin. Use the SR command followed by a number indicating the column position.&lt;br /&gt;
|-&lt;br /&gt;
| Left Margin... || Esc,S,L... || Sets the left margin. Use the SL command followed by a number indicating the column position. The left margin should not be set beyond the right edge of the screen.&lt;br /&gt;
|-&lt;br /&gt;
| Ignore Case || Esc,U,C || Specifies a case-insensitive search. UC instructs all subsequent searches not to make any distinction between upper and lower case next. To make searches case-sensitive again, use the LC command.&lt;br /&gt;
|-&lt;br /&gt;
| Case Sensitive || Esc,L,C || Specifies a case-sensitive search.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Set FN Key ===&lt;br /&gt;
&lt;br /&gt;
Set FN Key is used to define function keys and other programmable keys. There are 57 immediate command key slots ranging from 1 to 57. Any slot number can be redefined and any numbers within the range that do not appear in the special key mappings on page 4-16 are not defined.&lt;br /&gt;
&lt;br /&gt;
The following is the syntax for the Set FN Key command:&lt;br /&gt;
&lt;br /&gt;
 SF &amp;lt;slot number&amp;gt; /command string/&lt;br /&gt;
&lt;br /&gt;
Define Ctrl+key combinations by substituting a caret (^) and the other character for the slot number.&lt;br /&gt;
&lt;br /&gt;
==== Example Script ====&lt;br /&gt;
&lt;br /&gt;
This example script assigns function keys to cursor control commands. You can also enter these as a series of extended mode commands. The Top of File, Bottom of File, End of Page, Next Page, Next Line, and Previous Line commands are assigned to the F1 through F6 keys, respectively. Quotation marks are used as delimiters.&lt;br /&gt;
&lt;br /&gt;
 SF 1 &amp;quot;t&amp;quot;&lt;br /&gt;
 SF 2 &amp;quot;b&amp;quot;&lt;br /&gt;
 SF 3 &amp;quot;ep&amp;quot;&lt;br /&gt;
 SF 4 &amp;quot;pd&amp;quot;&lt;br /&gt;
 SF 5 &amp;quot;n&amp;quot;&lt;br /&gt;
 SF 6 &amp;quot;p&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== Special Key Mappings ===&lt;br /&gt;
&lt;br /&gt;
The following table shows the default key definitions used in the Reset Keys command:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Slot# !! Key/Key Sequence !! Function&lt;br /&gt;
|-&lt;br /&gt;
| 1-10 || F1 through F10 || Not defined&lt;br /&gt;
|-&lt;br /&gt;
| 11-20 || Shift+F1 to Shift+F10 || Not defined&lt;br /&gt;
|-&lt;br /&gt;
| 21 || Shift+left arrow || Move to beginning of line&lt;br /&gt;
|-&lt;br /&gt;
| 22 || Shift+right arrow || Move to end of line&lt;br /&gt;
|-&lt;br /&gt;
| 23 || Shift+up arrow || Move to top of document&lt;br /&gt;
|-&lt;br /&gt;
| 24 || Shift+down arrow || Move to bottom of document&lt;br /&gt;
|-&lt;br /&gt;
| 25 || Del || Delete character at cursor&lt;br /&gt;
|-&lt;br /&gt;
| 26 || Not defined || Not defined&lt;br /&gt;
|-&lt;br /&gt;
| 27 || Ctrl+A || Insert line&lt;br /&gt;
|-&lt;br /&gt;
| 28 || Ctrl+B || Delete line&lt;br /&gt;
|-&lt;br /&gt;
| 29 || Ctrl+C || Not defined&lt;br /&gt;
|-&lt;br /&gt;
| 30 || Ctrl+D || Move down 12 lines&lt;br /&gt;
|-&lt;br /&gt;
| 31 || Ctrl+E || Move to top or bottom of screen&lt;br /&gt;
|-&lt;br /&gt;
| 32 || Ctrl+F || Change case&lt;br /&gt;
|-&lt;br /&gt;
| 33 || Ctrl+G || Repeat last extended command line&lt;br /&gt;
|-&lt;br /&gt;
| 34 || Ctrl+H || Delete character left of cursor&lt;br /&gt;
|-&lt;br /&gt;
| 35 || Ctrl+I || Move cursor to next tab position&lt;br /&gt;
|-&lt;br /&gt;
| 36 || Ctrl+J || Not defined&lt;br /&gt;
|-&lt;br /&gt;
| 37 || Ctrl+K || Not defined&lt;br /&gt;
|-&lt;br /&gt;
| 38 || Ctrl+L || Not defined&lt;br /&gt;
|-&lt;br /&gt;
| 39 || Ctrl+M || Return&lt;br /&gt;
|-&lt;br /&gt;
| 40 || Ctrl+N || Not defined&lt;br /&gt;
|-&lt;br /&gt;
| 41 || Ctrl+O || Delete word or spaces&lt;br /&gt;
|-&lt;br /&gt;
| 42 || Ctrl+P || Not defined&lt;br /&gt;
|-&lt;br /&gt;
| 43 || Ctrl+Q || Not defined&lt;br /&gt;
|-&lt;br /&gt;
| 44 || Ctrl+R || Move to end of previous word&lt;br /&gt;
|-&lt;br /&gt;
| 45 || Ctrl+S || Not defined&lt;br /&gt;
|-&lt;br /&gt;
| 46 || Ctrl+T || Move start of next word&lt;br /&gt;
|-&lt;br /&gt;
| 47 || Ctrl+U || Move up 12 lines&lt;br /&gt;
|-&lt;br /&gt;
| 48 || Ctrl+V || Redisplay window&lt;br /&gt;
|-&lt;br /&gt;
| 49 || Ctrl+W || Not defined&lt;br /&gt;
|-&lt;br /&gt;
| 50 || Ctrl+X || Not defined&lt;br /&gt;
|-&lt;br /&gt;
| 51 || Ctrl+Y || Delete to end of line&lt;br /&gt;
|-&lt;br /&gt;
| 52 || Ctrl+Z || Not defined&lt;br /&gt;
|-&lt;br /&gt;
| 53 || Ctrl+[ || Esc (enter extended command mode)&lt;br /&gt;
|-&lt;br /&gt;
| 54 || Not defined || Not defined&lt;br /&gt;
|-&lt;br /&gt;
| 55 || Ctrl+] || Move to end or start of line, depending on cursor position&lt;br /&gt;
|-&lt;br /&gt;
| 56 || Not defined || Not defined&lt;br /&gt;
|-&lt;br /&gt;
| 57 || Not defined || Not defined&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Command Menu ===&lt;br /&gt;
&lt;br /&gt;
The following commands are for manipulating files:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| Extended Command... || Esc,C,M... || Enters extended command mode; equivalent to pressing Ctrl+[ or Esc.&lt;br /&gt;
|-&lt;br /&gt;
| Repeat Last || Esc,R,E || Attempts to repeat the last command.&lt;br /&gt;
|-&lt;br /&gt;
| Run File... || Esc,R,F... || Loads and executes a command file of extended mode commands.&lt;br /&gt;
|-&lt;br /&gt;
| ARexx Command... || Esc,R,X... || Runs the specified ARexx program.&lt;br /&gt;
|-&lt;br /&gt;
| Redisplay || Esc,V,W || Redraws the ED window and clears the status line; equivalent to pressing Ctrl+V.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Other ED Commands ===&lt;br /&gt;
&lt;br /&gt;
There are also ED commands that do not appear in menus. These commands are listed here in functional groups. Use them in extended mode by entering the following key sequences.&lt;br /&gt;
&lt;br /&gt;
==== Program Control ====&lt;br /&gt;
&lt;br /&gt;
The following are program control commands:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| Extend Margins || Esc,E,X || Extends the margins for the current line. Once you enter the EX command, ED ignores the right margin on the current line.&lt;br /&gt;
|-&lt;br /&gt;
| Status Line Message || Esc,S,M... || Prints a given string on the status line.&lt;br /&gt;
|-&lt;br /&gt;
| Exit with Query || Esc,X,Q || Exits ED unless changes were made to the file. If changes have been made, the message File has been changed-type Y to save and exit: is displayed. Press any key (except Y) to abort the exit. XQ is equivalent to clicking the close gadget on the ED window.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Cursor Control ====&lt;br /&gt;
&lt;br /&gt;
The following commands are used for controlling the cursor:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| End Page || Esc,E,P || End of a page.&lt;br /&gt;
|-&lt;br /&gt;
| Previous || Esc,P || Start of the previous line.&lt;br /&gt;
|-&lt;br /&gt;
| Character Left || Esc,C,L || One place to the left.&lt;br /&gt;
|-&lt;br /&gt;
| Character Right || Esc,C,R || One place to the right.&lt;br /&gt;
|-&lt;br /&gt;
| Current End || Esc,C,E || End of the current line.&lt;br /&gt;
|-&lt;br /&gt;
| Current Start || Esc,C,S || Start of the current line.&lt;br /&gt;
|-&lt;br /&gt;
| Tab || Esc,T,B || Next tab position.&lt;br /&gt;
|-&lt;br /&gt;
| Word Next || Esc,W,N || Start of the next word.&lt;br /&gt;
|-&lt;br /&gt;
| Word Previous || Esc,W,P || Space after previous word.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Modifying Text ====&lt;br /&gt;
&lt;br /&gt;
The following commands edit text on the screen:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| Insert Before || Esc,I || Inserts the specified string on the line before the cursor. Specify a new line&#039;s string after the I command to insert text before the current line containing the cursor.&lt;br /&gt;
|-&lt;br /&gt;
| Insert After || Esc,A || Inserts the specified string on the line after the cursor. This command works in the same way as I, except that the string is inserted on a new line beneath the current cursor position.&lt;br /&gt;
|-&lt;br /&gt;
| Split || Esc,S || Splits the current line at the cursor position.&lt;br /&gt;
|-&lt;br /&gt;
| Join || Esc,J || Joins the next line to the end of the current line.&lt;br /&gt;
|-&lt;br /&gt;
| Delete || Esc,D || Deletes the current line.&lt;br /&gt;
|-&lt;br /&gt;
| Delete Character || Esc,D,C || Deletes the character under the cursor.&lt;br /&gt;
|-&lt;br /&gt;
| Delete Left || Esc,D,L || Deletes the character to the left of the cursor.&lt;br /&gt;
|-&lt;br /&gt;
| Delete Word || Esc,D,W || Deletes to the end of the current word.&lt;br /&gt;
|-&lt;br /&gt;
| End Line || Esc,E,L || Deletes to the end of the current line.&lt;br /&gt;
|-&lt;br /&gt;
| Flip Case || Esc,F,C || Switches the case of the selected letters, one at a time.&lt;br /&gt;
|-&lt;br /&gt;
| Set Tab || Esc,S,T || Sets the tab stop. To change the current setting of tabs, use the ST command followed by a number.&lt;br /&gt;
|-&lt;br /&gt;
| Next || Esc,N || Start of the next line.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Repeating Commands in Extended Mode ==&lt;br /&gt;
&lt;br /&gt;
Pressing Ctrl+G repeats a command line. You can set up execute complex sets of editing commands many times.&lt;br /&gt;
&lt;br /&gt;
You can repeat a command a specified number of times by entering the number before the command. For example:&lt;br /&gt;
&lt;br /&gt;
 4 E/rename/copy/&lt;br /&gt;
&lt;br /&gt;
exchanges the next four occurrences of &amp;quot;rename&amp;quot; to &amp;quot;copy&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Use the RP (Repeat) extended command to repeat a command until ED returns an error, such as reaching the end of the file. For example:&lt;br /&gt;
&lt;br /&gt;
 T;RP E/rename/copy/&lt;br /&gt;
&lt;br /&gt;
moves the cursor to the top of the file, then exchanges all occurrences of &amp;quot;rename&amp;quot; with &amp;quot;copy&amp;quot;. The T command (Top of File) changes all occurrences of Rename in the whole file. Otherwise, only the occurrences after the current cursor position are changed.&lt;br /&gt;
&lt;br /&gt;
To execute command groups repeatedly, you can group the commands together in parentheses. You can also nest command groups. For example:&lt;br /&gt;
&lt;br /&gt;
 RP (F/Workbench/;3A//)&lt;br /&gt;
&lt;br /&gt;
inserts three blank lines (the null string//) after every line containing Workbench.&lt;br /&gt;
&lt;br /&gt;
To interrupt any sequence of extended commands, press any key during execution. If an error occurs, ED abandons the command sequence.&lt;br /&gt;
&lt;br /&gt;
== Customizing ED ==&lt;br /&gt;
&lt;br /&gt;
You can customize ED with commands that change the menus and function key setup. These commands can be entered individually within ED. They can also be saved as a script, such as S:Ed-startup, or as a file specified using the WITH argument. To execute the file from within ED, use the Run File (Esc,R,F) extended command. For information about changing the function keys, see page 4-15.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
\ Set Menu Item || Esc,S,I || Defines the menu headings and items. There are 120 menu item slots ranging from 0 to 119. The slot type identifies the contents of the slot and is a number from 0 to 4. The 0 slot type must be the last defined slot. Do not create a menu without items; if you specify a menu heading, include menu items after it. See below for the syntax of the Set Menu Item command and a table of the slot types.&lt;br /&gt;
|-&lt;br /&gt;
| Enable Menu || Esc,E,M || Enables menus. You must follow the Set Menu Item commands with EM to enable the menu commands. See page 4-22 for an example script using the Enable Menu command.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Set Menu Item ===&lt;br /&gt;
&lt;br /&gt;
The following is the syntax for the Set Menu Item command:&lt;br /&gt;
&lt;br /&gt;
 SI &amp;lt;slot number&amp;gt; &amp;lt;slot type&amp;gt; /string1/string2/&lt;br /&gt;
&lt;br /&gt;
The following table shows the slot types and functions used with the Set Menu Item command:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Type !! Function !! String Input&lt;br /&gt;
|-&lt;br /&gt;
| 0 || End of Menus || No arguments&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Menu Heading || String1 = heading name&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Menu Item || String1 = item name&amp;lt;br/&amp;gt;String2 = command string&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Submenu Heading || String1 = heading name&amp;lt;br/&amp;gt;String2 = command string&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Separator bar || No arguments&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Example Script ===&lt;br /&gt;
&lt;br /&gt;
The following is an example script using the Set Menu Item and Enable Menu commands. Quotation marks are used as the delimiters.&lt;br /&gt;
&lt;br /&gt;
 SI 0 1 &amp;quot;Project&amp;quot;&lt;br /&gt;
 SI 1 2 &amp;quot;Open . . . &amp;quot; &amp;quot;op ? /Open file:/&amp;quot;&lt;br /&gt;
 SI 2 2 &amp;quot;Save ... &amp;quot; &amp;quot;sa&amp;quot;&lt;br /&gt;
 SI 3 4&lt;br /&gt;
 SI 4 2 &amp;quot;Quit!&amp;quot; &amp;quot;q&amp;quot;&lt;br /&gt;
 SI 5 1 &amp;quot;Move&amp;quot;&lt;br /&gt;
 SI 6 2 &amp;quot;Top&amp;quot; &amp;quot;t&amp;quot;&lt;br /&gt;
 SI 7 2 &amp;quot;Bottom&amp;quot; &amp;quot;b&amp;quot;&lt;br /&gt;
 SI 8 0&lt;br /&gt;
 EM&lt;br /&gt;
&lt;br /&gt;
This script produces the menus illustrated in Figure 4-4:&lt;br /&gt;
&lt;br /&gt;
[[File:DosFig4-4.png|none|frame|ED Custom Menu Example]]&lt;br /&gt;
&lt;br /&gt;
== Printing From ED ==&lt;br /&gt;
&lt;br /&gt;
Use the following steps to print a file that is open in the current ED window:&lt;br /&gt;
&lt;br /&gt;
# Choose the Save As menu item to display a file requester.&lt;br /&gt;
# Enter prt: in the Drawer field.&lt;br /&gt;
# Select OK.&lt;br /&gt;
&lt;br /&gt;
This prints the file, but does not save it to disk. If you wish to save the file you must select the Save menu item or Save As and a file name.&lt;br /&gt;
&lt;br /&gt;
== Quitting ED ==&lt;br /&gt;
&lt;br /&gt;
You can exit ED in one of the following three ways:&lt;br /&gt;
&lt;br /&gt;
* Esc,X. This method exits ED and saves the current file to a designated file name that was specified when ED was opened.&lt;br /&gt;
* Esc,X,Q or click on the ED window&#039;s close gadget. This method exits ED if no changes were made to the file. If changes were made to the file, ED lets you save the changes or exit without saving.&lt;br /&gt;
* Esc,Q or select the Quit item in the Project menu. This method exits ED without saving any changes if you confirm the status line warning that changes will be lost.&lt;br /&gt;
&lt;br /&gt;
== ARexx Support ==&lt;br /&gt;
&lt;br /&gt;
You can also control ED from ARexx by sending and receiving commands through ED&#039;s ARexx port. Each copy of ED running concurrently has an individual ARexx port name that must be specified to handle information for the correct session. The ARexx port names are assigned as follows:&lt;br /&gt;
&lt;br /&gt;
* The first session&#039;s port name is ED&lt;br /&gt;
* The second session&#039;s is ED_1&lt;br /&gt;
* The third session&#039;s is Ed_2 and so on&lt;br /&gt;
&lt;br /&gt;
Many of ED&#039;s extended commands can be used from ARexx. By using ED&#039;s RV command in ARexx programs, you can send information from ED to ARexx. This gives information about the status of ED, such as the current line number of the name of the file being edited.&lt;br /&gt;
&lt;br /&gt;
The RV command accepts the name of the ARexx stem variable to store its argument information. For example, in ARexx:&lt;br /&gt;
&lt;br /&gt;
 address &#039;Ed&#039; &#039;RV /stem/&#039;&lt;br /&gt;
&lt;br /&gt;
assigns values to the following variables:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| stem.LEFT || Current left margin&lt;br /&gt;
|-&lt;br /&gt;
| stem.RIGHT || Current right margin&lt;br /&gt;
|-&lt;br /&gt;
| stem.TABSTOP || Current tab stop setting&lt;br /&gt;
|-&lt;br /&gt;
| stem.LMAX || Maximum number of lines visible on screen&lt;br /&gt;
|-&lt;br /&gt;
| stem.WIDTH || Width of the screen in characters&lt;br /&gt;
|-&lt;br /&gt;
| stem.X || Cursor X position in the ED window (1 is the left edge)&lt;br /&gt;
|-&lt;br /&gt;
| stem.Y || Cursor Y position in the ED window (1 is the top line)&lt;br /&gt;
|-&lt;br /&gt;
| stem.BASE || Window base (normally 0, but non-zero when the screen is shifted to the right)&lt;br /&gt;
|-&lt;br /&gt;
| stem.EXTEND || Extended margin value (Extend Margins command)&lt;br /&gt;
|-&lt;br /&gt;
| stem.FORCECASE || Case sensitivity flag (Ignore Case = 1, Case Sensitive = 0)&lt;br /&gt;
|-&lt;br /&gt;
| stem.LINE || Current line number in the file (1 is the first line)&lt;br /&gt;
|-&lt;br /&gt;
| stem.FILENAME || Name of the file being edited&lt;br /&gt;
|-&lt;br /&gt;
| stem.CURRENT || Text of the current line&lt;br /&gt;
|-&lt;br /&gt;
| stem.LASTCMD || Last extended command issued&lt;br /&gt;
|-&lt;br /&gt;
| stem.SEARCH || Lst string searched for&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Any valid ARexx symbol can be substituted for &amp;quot;stem&amp;quot;. Enclose the name in proper delimiters. These variables can be treated as ordinary ARexx stem variables.&lt;br /&gt;
&lt;br /&gt;
== ED/ARexx Example Program ==&lt;br /&gt;
&lt;br /&gt;
The example program, Transpose.ed, illustrates the use of several extended commands from ARexx. This program transposes two characters when launched from ED. For example, if a line contains the string 123 and the cursor is highlighted the 3, Transpose.ed changes the string to 213.&lt;br /&gt;
&lt;br /&gt;
Enter this program and save it as REXX:Transpose.ed. Then, open ED and edit an existing file or create a new one. Place the cursor one character to the right of the ones to be transposed, press Esc, and enter:&lt;br /&gt;
&lt;br /&gt;
 RX /transpose.ed/&lt;br /&gt;
&lt;br /&gt;
The program executes and the characters are transposed if ARexx is running and everything is entered correctly. The entire file name, including the extension, must be specified to run the program.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
/*Transpose.ed: An example program to transpose two characters. */&lt;br /&gt;
/*Given string &#039;123&#039;, if cursor is on 3, this macro converts */&lt;br /&gt;
/*string into &#039;213&#039;. */&lt;br /&gt;
HOST = address () /*find out which ED session invoked this program*/&lt;br /&gt;
address VALUE HOST /*...and talk to that session */&lt;br /&gt;
&#039;rv&#039;&#039;/CURR/&#039; /*Ask ED to store info in stem variable CURR */&lt;br /&gt;
             /*Obtain two pieces of information: */&lt;br /&gt;
currpos = CURR.X /*1.position of cursor on line */&lt;br /&gt;
currling = CURR.CURRENT /*2. Contents of current line */&lt;br /&gt;
if /currpos &amp;gt;2) then /*Work only on the current line */&lt;br /&gt;
  currpos = currpos - 1&lt;br /&gt;
else do /*Otheriwse, report error and exit */&lt;br /&gt;
&#039;sm/Cusor must be at position 2 or further to the right/&#039;&lt;br /&gt;
exit 10&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
/*Next the code needs to reverse the CURRPOSth and CURRPOSth-1 */&lt;br /&gt;
/*characters and then replace the current line with the new one. */&lt;br /&gt;
/*drop CURR. CURR is no longer needed; dropping it saves some */&lt;br /&gt;
/*memory. */&lt;br /&gt;
&#039;d&#039; /*Tell ED to delete current line */&lt;br /&gt;
currlin = swapch (currpos,currlin) /*Swap the two characters */&lt;br /&gt;
&#039;i/&#039;||currlin||&#039;/&#039; /*Insert modified line */&lt;br /&gt;
do i = 1 to currpos /*Place cursor back where it started */&lt;br /&gt;
  &#039;cr&#039; /*ED&#039;s `cursor right&#039; command */&lt;br /&gt;
  end&lt;br /&gt;
exit /*Program has finished */&lt;br /&gt;
&lt;br /&gt;
/*Function to swap two characters */&lt;br /&gt;
Swapch: procedure */&lt;br /&gt;
parse arg cpos,clin&lt;br /&gt;
  ch1 = substr(clin,cpos1) /*Get character */&lt;br /&gt;
  clin = delstr(clin,cpos1) /*Delete it from string */&lt;br /&gt;
  clin = insert(ch1,clin,cpos-2,1) /*Insert to create transposition */&lt;br /&gt;
return clin /*Return modified string */ &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= MEmacs =&lt;br /&gt;
&lt;br /&gt;
MEmacs (MicroEmacs), which is similar to the UNIX-based Emacs editor, is a screen-oriented editor in which you can edit multiple files at the same time. MEmacs performs all operations on memory-resident text, requiring that entire text files be able to fit into memory at once.&lt;br /&gt;
&lt;br /&gt;
Line length, generally 80 characters long, is limited to the right edge of the screen. You can enter characters beyond the limit, however, they are not displayed. To see these characters, break the line or delete some of the displayed characters. A dollar sign ($) at the right edge of the screen indicates that there are characters beyond what is displayed.&lt;br /&gt;
&lt;br /&gt;
The format for the MEmacs command is the following:&lt;br /&gt;
&lt;br /&gt;
 MEMACS [&amp;lt;filename&amp;gt;] [GOTO &amp;lt;n&amp;gt;] [OPT W]&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;filename&amp;gt; argument is optional.&lt;br /&gt;
&lt;br /&gt;
The GOTO &amp;lt;n&amp;gt; option specifies the line on which the cursor is to appear when the file is opened.&lt;br /&gt;
&lt;br /&gt;
Specifying OPT W opens MEmacs in a Workbench window rather than on its own screen, which saves memory.&lt;br /&gt;
&lt;br /&gt;
== Starting MEmacs ==&lt;br /&gt;
&lt;br /&gt;
MEmacs can be run from either the Workbench or the Shell. From the Workbench, double-click on the MEmacs icon in the Tools window of the Extras disk. If you have a hard disk, the Tools drawer is in your Workbench window.&lt;br /&gt;
&lt;br /&gt;
From the Shell, enter:&lt;br /&gt;
&lt;br /&gt;
 MEmacs &amp;lt;filename&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &amp;lt;filename&amp;gt; specifies the file to read into MEmacs. If a file with that name does not previously exist, a new file is created when you save your work.&lt;br /&gt;
&lt;br /&gt;
== MEmacs Commands ==&lt;br /&gt;
&lt;br /&gt;
The line at the bottom of the MEmacs screen identifies either the current file name or the name of the current buffer if no file name is specified. Figure 4-5 illustrates the MEmacs opening screen .&lt;br /&gt;
&lt;br /&gt;
[[File:DosFig4-5.png|none|frame|MEmacs Opening Screen]]&lt;br /&gt;
&lt;br /&gt;
Several buffers can be in use at the same time and one or more can be displayed on the screen simultaneously. Menu options switch between them. At all times, the screen displays what is actually in the buffer.&lt;br /&gt;
&lt;br /&gt;
MEMacs has two conditions of operation:&lt;br /&gt;
&lt;br /&gt;
; Normal&lt;br /&gt;
: When you enter and manipulate text directly in the file without special functions.&lt;br /&gt;
&lt;br /&gt;
; Command&lt;br /&gt;
: When you enter a command through a menu selection or the keyboard shortcut for it. In the command condition, the cursor jumps to the bottom line of the display and waits for you to supply additional information following the prompt. You cannot return to the normal condition until you satisfy or cancel the command by pressing Return.&lt;br /&gt;
&lt;br /&gt;
In the MEmacs normal condition, you can:&lt;br /&gt;
&lt;br /&gt;
* Move the cursor using the arrow keys.&lt;br /&gt;
* Move the cursor to the edge of the window by holding down Shift and pressing the appropriate arrow key.&lt;br /&gt;
* Move the cursor by clicking the left mouse button at the desired place on the screen.&lt;br /&gt;
* Insert characters at the current cursor position by typing them.&lt;br /&gt;
* Delete the character at the current cursor position by pressing Del.&lt;br /&gt;
* Delete the character to the left of the cursor by pressing Backspace.&lt;br /&gt;
* Perform other special menu and command functions.&lt;br /&gt;
&lt;br /&gt;
When using MEmacs, you should be familiar with the following special terms:&lt;br /&gt;
&lt;br /&gt;
; Buffer&lt;br /&gt;
: A memory area that MEmacs controls. There is always at least one buffer used by MEmacs containing zero or more text characters.&lt;br /&gt;
&lt;br /&gt;
; Dot&lt;br /&gt;
: The current cursor position.&lt;br /&gt;
&lt;br /&gt;
; Mark&lt;br /&gt;
: A specified cursor position. (Each buffer has its own dot and mark.) The Set-mark menu item marks the current cursor position (described on page 4-33). You can move forward or backward in the file, adding or deleting text. To return to the marked place, select the Swap-dot&amp;amp;mark menu item (described on page 4-36).&lt;br /&gt;
&lt;br /&gt;
: You can also set a mark to indicate the beginning of a block of text that you want to duplicate, move, or delete. The block encompasses all the characters starting with the mark and continuing to the current cursor position.&lt;br /&gt;
&lt;br /&gt;
; Kill&lt;br /&gt;
: Kill commands remove text from the screen to save in a kill buffer. This text can be retrieved and inserted into your document by using the Yank command. Issuing successive Kill commands (without selecting Yank in between) adds each block of the text to the existing text in the kill buffer. If you select Yank, the next block of killed text otherwise the current block.&lt;br /&gt;
&lt;br /&gt;
; Window&lt;br /&gt;
: MEmacs screens can be split into multiple layers for editing and displaying more than one buffer or two or more portions of the same buffer. Each layer is a MEmacs window.&lt;br /&gt;
&lt;br /&gt;
; Modified Buffers&lt;br /&gt;
: Buffers are marked as modified when any changes are made. The modified status is removed when the buffer is saved.&lt;br /&gt;
&lt;br /&gt;
: To see modified buffers, use the List-buffers command (described on page 4-33); modified buffers are identified with an asterisk (*). If you exit MEmacs without saving any changes, a prompt tells you that modified buffers exist and asks if you really want to quit.&lt;br /&gt;
&lt;br /&gt;
== Menu Commands ==&lt;br /&gt;
&lt;br /&gt;
MEmacs has the following menus:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| Project || Contains system and file-oriented items.&lt;br /&gt;
|-&lt;br /&gt;
| Edit || Contains buffer editing commands.&lt;br /&gt;
|-&lt;br /&gt;
| Window || Controls the characteristics of the MEmacs windows.&lt;br /&gt;
|-&lt;br /&gt;
| Move || Controls the placement of the cursor.&lt;br /&gt;
|-&lt;br /&gt;
| Line || Controls line-oriented operations.&lt;br /&gt;
|-&lt;br /&gt;
| Word || Controls word-oriented operations.&lt;br /&gt;
|-&lt;br /&gt;
| Search || Controls search and search/replace options.&lt;br /&gt;
|-&lt;br /&gt;
| Extras || Controls the numerical value of arguments and lets you execute a series of operations as though it were a single special command.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Figure 4-6 illustrates the MEmacs expanded menu bar.&lt;br /&gt;
&lt;br /&gt;
[[File:DosFig4-6.png|none|frame|Expanded Menus]]&lt;br /&gt;
&lt;br /&gt;
=== Project Menu ===&lt;br /&gt;
&lt;br /&gt;
The commands in the Project menu, except for Visit-file, affect the buffer associated with the current cursor position.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| Rename || Ctrl+X,F || Changes the name of the file associated with the current buffer. Pressing Return without specifying a file name disassociates the buffer from any file name.&lt;br /&gt;
|-&lt;br /&gt;
| Read-file || Ctrl+X,&amp;lt;br/&amp;gt;Ctrl+R || Replaces the contents of the current buffer with the contents of a file. Enter a complete file path. Press Return without specifying a file name to ignore the request and return to normal mode.&lt;br /&gt;
|-&lt;br /&gt;
| Visit-file || Ctrl+X,&amp;lt;br/&amp;gt;Ctrl+V || Allows you to work with additional files other than the one you are currently editing. Enter the complete file path.&lt;br /&gt;
|-&lt;br /&gt;
| Insert-file || Ctrl+X,&amp;lt;br/&amp;gt;Ctrl+I || Insert the contents of a file into the current buffer at a point one line above the current cursor position. Enter the complete file path.&lt;br /&gt;
|-&lt;br /&gt;
| Save-file || Ctrl+X,&amp;lt;br/&amp;gt;Ctrl+S || Writes the contents of the current buffer to the file name associated with that buffer. Issues the file&#039;s line count following a successful save. MEmacs does not save the file if no name is provided; it displays this error message: No file name.&lt;br /&gt;
|-&lt;br /&gt;
| Save-as-file || Ctrl+X,&amp;lt;br/&amp;gt;Ctrl+W || Allows you to specify the name and path of a file associated with a buffer.&lt;br /&gt;
|-&lt;br /&gt;
| Save-mod || Ctrl+X,&amp;lt;br/&amp;gt;Ctrl+M || Writes the contents of all modified buffers to the disk. Do not accidentally modify a buffer that you did not intend to change.&lt;br /&gt;
|-&lt;br /&gt;
| Save-exit || Ctrl+X,&amp;lt;br/&amp;gt;Ctrl+F || Saves all modified buffers and exits MEmacs.&lt;br /&gt;
|-&lt;br /&gt;
| New-Cli || Ctrl+- || Opens a new Shell window known as a Spawn Window. Enter AmigaDOS commands in the Spawn Window without interfering with MEmacs. Close the window with ENDSHELL.&lt;br /&gt;
|-&lt;br /&gt;
| Cli-Command || Ctrl+X,! || Lets you execute an AmigaDOS command while in MEmacs. Enter a command following the ! prompt at the bottom of the screen. Command output is placed in the spawn.output buffer.&lt;br /&gt;
|-&lt;br /&gt;
| Quit || Ctrl+C || Exits MEmacs. You are given an opportunity to save modified buffers or quit without saving. Alternative keyboard shortcuts: Ctrl+X,Ctrl+C Esc,Ctrl+C.&lt;br /&gt;
|-&lt;br /&gt;
| About... || || Gives program copyright information&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Edit Menu ===&lt;br /&gt;
&lt;br /&gt;
The commands in the Edit menu affect the editing of your buffers and their associated files.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| Kill-region || Ctrl+W || Deletes block of text from the current buffer and saves them in a kill buffer. Text can be retrieved with the Yank command. Make copies of a block by immediately selecting Yank without changing the cursor position after killing the block. This restores the block to its position and leaves a copy in the kill buffer.&lt;br /&gt;
|-&lt;br /&gt;
| Yank || Ctrl+Y || Copies the contents of the kill buffer to the current cursor location on the current line. Reverses the action of Kill-region without changing the contents of the kill buffer. Used with Kill-region for moving text or for repeatedly copying a single block of text.&lt;br /&gt;
|-&lt;br /&gt;
| Set-mark || Ctrl+@ || Marks the cursor position in a buffer. The subsequent cursor position is referred to as a dot. Move between the mark and the dot using the Swap-dot&amp;amp;mark command in the Move menu. Used for marking blocks of text. Alternative keyboard shortcut: Esc,-.&lt;br /&gt;
|-&lt;br /&gt;
| Copy-region || Esc,W || Copies the contents of the marked region to the kill buffer without deleting it, replacing any previous contents.&lt;br /&gt;
|-&lt;br /&gt;
| Upper-region || Ctrl+X,&amp;lt;br/&amp;gt;Ctrl+U || Changes the text of the entire marked region to upper case.&lt;br /&gt;
|-&lt;br /&gt;
| Lower-region || Ctrl+X,&amp;lt;br/&amp;gt;Ctrl+L || Changes the text of the entire marked region to lower case.&lt;br /&gt;
|-&lt;br /&gt;
| List-buffers || Ctrl+X,&amp;lt;br/&amp;gt;Ctrl+B || Splits the current buffer&#039;s window and displays a list of the buffers MEmacs is maintaining. To redisplay the current buffer, select the One-window command or press Ctrl+X,1. The List-Buffer fields are:&amp;lt;br/&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| C || Displays an asterisk if the buffer has been modified since it was last saved to a file. (Stands for changed.)&lt;br /&gt;
|-&lt;br /&gt;
| Size || Shows how many characters are in the buffer.&lt;br /&gt;
|-&lt;br /&gt;
| Buffer || Shows the name given to the buffer. If you read in a file, this is the name of the file without the full path.&lt;br /&gt;
|-&lt;br /&gt;
| File || Shows the full path to the file. This is the file to which MEmacs writes the buffer if you Save-file or Save-exit while the cursor is in that buffer.&lt;br /&gt;
|}&lt;br /&gt;
|-&lt;br /&gt;
| Select-buffer || Ctrl+X,B || Allows you to select the buffer to edit in the current window. Replaces the contents of the window with the selected buffer or new buffer.&lt;br /&gt;
|-&lt;br /&gt;
| Insert-buffer || Esc,&amp;lt;br/&amp;gt;Ctrl+Y || Insert the contents of a named buffer into the current buffer at the line above the current cursor position.&lt;br /&gt;
|-&lt;br /&gt;
| Kill-buffer || Ctrl+X,K || Deletes the contents of one or more chosen buffers, returning the memory to the memory manager to reuse. You must specify the buffer to be deleted; a buffer cannot be killed if its contents are currently displayed.&lt;br /&gt;
|-&lt;br /&gt;
| Justify-buffer || Ctrl+X,J || Removes all blank spaces and tabs from the left edge of all the lines in the current buffer. The text realigns with the current margins.&lt;br /&gt;
|-&lt;br /&gt;
| Redisplay || Ctrl+L || Redraws the screen.&lt;br /&gt;
|-&lt;br /&gt;
| Quote-char || Ctrl+Q || Allows insertion of any literal character in the text file, except the Tab key. Alternative keyboard shortcut: Ctrl+X,Q.&lt;br /&gt;
|-&lt;br /&gt;
| Indent || Ctrl+J || Moves the cursor to the next line, automatically indenting the same amount of spaces as the previous line. Alternative keyboard shortcuts: Help or Enter on the numeric keypad.&lt;br /&gt;
|-&lt;br /&gt;
| Transpose || Ctrl+T || Swaps the positions of two adjacent characters. Place the cursor on the right-most of the two characters and execute the command.&lt;br /&gt;
|-&lt;br /&gt;
| Cancel || Ctrl+G || Ends an ongoing menu command, such as query search and replace.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Window Menu ===&lt;br /&gt;
&lt;br /&gt;
The Window menu controls how to view your buffers on the screen.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| One-window || Ctrl+X,1 || Makes the current buffer a single, full-sized window on the MEmacs screen.&lt;br /&gt;
|-&lt;br /&gt;
| Split-window || Ctrl+X,2 || Splits the current window in half, positioning the current buffer identically in both windows. Any changes you make in either window affect the whole buffer.&lt;br /&gt;
|-&lt;br /&gt;
| Next-window || Ctrl+X,N || Moves the cursor to the next window and makes that window available for editing.&lt;br /&gt;
|-&lt;br /&gt;
| Prev-window || Ctrl+X,P || Moves the cursor to the previous window and makes that window available for editing.&lt;br /&gt;
|-&lt;br /&gt;
| Expand-window || Ctrl+X,Z || Adds a line to the height of the current window and simultaneously subtracts a line from the height of the adjacent window.&lt;br /&gt;
|-&lt;br /&gt;
| Shrink-window || Ctrl+X,&amp;lt;br/&amp;gt;Ctrl+Z || Substracts a line from the height of the current window and adds a line to the height of the adjacent window.&lt;br /&gt;
|-&lt;br /&gt;
| Next-w-page || Esc,&amp;lt;br/&amp;gt;Ctrl+V || Displays the next page of the adjacent window. This does not make the window available for editing.&lt;br /&gt;
|-&lt;br /&gt;
| Prev-w-page || Ctrl+X,V || Displays the previous page of the adjacent window. If only one window is displayed, it displays the previous page of that window.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Move Menu ===&lt;br /&gt;
&lt;br /&gt;
These commands move the cursor rapidly through the current buffer.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| Top-of-buffer || Esc,&amp;lt; || Moves the cursor to the top line of the current buffer.&lt;br /&gt;
|-&lt;br /&gt;
| End-of-buffer || Esc,&amp;gt; || Moves the cursor to the bottom line of the current buffer.&lt;br /&gt;
|-&lt;br /&gt;
| Top-of-window || Esc,, || Moves the cursor to the top of the current window.&lt;br /&gt;
|-&lt;br /&gt;
| End-of-window || Esc,. || Moves the cursor to the bottom of the current window.&lt;br /&gt;
|-&lt;br /&gt;
| Goto-line || Ctrl+X,&amp;lt;br/&amp;gt;Ctrl+G || Moves the cursor to a specified line number. Specifying a line number larger than the total number of lines in a buffer moves the cursor to the last line of the buffer.&lt;br /&gt;
|-&lt;br /&gt;
| Swap-dot&amp;amp;mark || Ctrl+X,&amp;lt;br/&amp;gt;Ctrl+X || Marks the current cursor position (dot) and moves the cursor to the previously marked setting.&lt;br /&gt;
|-&lt;br /&gt;
| Next-page || Ctrl+V || Moves the cursor toward the end of the buffer by one full window, less one line.&lt;br /&gt;
|-&lt;br /&gt;
| Prev-page || Esc,V || Moves the cursor towards the beginning of the buffer by one full window, less one line.&lt;br /&gt;
|-&lt;br /&gt;
| Next-word || Esc,F || Moves the cursor forward to the next non-alphabetic character, such as a space or punctuation mark, following the current word.&lt;br /&gt;
|-&lt;br /&gt;
| Previous-word || Esc,B || Moves the cursor back to the first letter of the previous word.&lt;br /&gt;
|-&lt;br /&gt;
| Scroll-up || Ctrl+Z || Moves the text up one line.&lt;br /&gt;
|-&lt;br /&gt;
| Scroll-down || Esc,Z || Moves the text down one line.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Line Menu ===&lt;br /&gt;
&lt;br /&gt;
These commands move the cursor within or between lines and perform operations involving entire lines.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| Open-line || Ctrl+O || Splits the line containing the cursor, forcing the character at the current cursor position to become the first character of the following line. The cursor remains on the original line. Pressing the Del key cancels an accidental Open-line.&lt;br /&gt;
|-&lt;br /&gt;
| Kill-line || Ctrl+X,&amp;lt;br/&amp;gt;Ctrl+D || Deletes the line containing the cursor and places the text in the kill buffer.&lt;br /&gt;
|-&lt;br /&gt;
| Kill-to-eol || Ctrl+K || Deletes the text between the current cursor position and the end of the line and places the text in the kill buffer.&lt;br /&gt;
|-&lt;br /&gt;
| Start-of-line || Ctrl+A || Moves the cursor to the first position on a line.&lt;br /&gt;
|-&lt;br /&gt;
| End-of-line || Ctrl+E || Moves the cursor to the last position on a line.&lt;br /&gt;
|-&lt;br /&gt;
| Next-line || Ctrl+N || Moves the cursor down one line.&lt;br /&gt;
|-&lt;br /&gt;
| Previous-line || Ctrl+P || Moves the cursor up one line.&lt;br /&gt;
|-&lt;br /&gt;
| Line-to-top || Esc,! || Moves the line containing the cursor to the top of the window.&lt;br /&gt;
|-&lt;br /&gt;
| Delete-blanks || Ctrl+X,&amp;lt;br/&amp;gt;Ctrl+O || Deletes blank lines, proceeding forward from the current cursor position until MEmacs reaches the next line on which there is text. Does not delete single blank lines.&lt;br /&gt;
|-&lt;br /&gt;
| Show-Line# || Ctrl+X,= || Displays information on the present cursor position.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Word Menu ===&lt;br /&gt;
&lt;br /&gt;
The Word menu contains word-associated operations.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| Delete-forw ||  Esc,D || Deletes the character on which the cursor is positioned and all remaining characters to the right until the next non-alphanumeric character is found, such as a blank space, tab, or punctuation.&lt;br /&gt;
|-&lt;br /&gt;
| Delete-back || Esc,H || Delets all characters to the left of the cursor until it finds the first character of a word. The character at the cursor position is not deleted. Alternative keyboard shortcut: Esc,Del.&lt;br /&gt;
|-&lt;br /&gt;
| Upper-word || Esc,U || Changes a word to upper case, starting at the cursor position and proceeding to the last character of the word.&lt;br /&gt;
|-&lt;br /&gt;
| Lower-word || Esc,L || Changes a word to lower case, starting at the cursor position and proceeding to the last character of the word.&lt;br /&gt;
|-&lt;br /&gt;
| Cap-word || Esc,C || Changes the character at the cursor position to upper case. Also changes the characters to the right of the cursor, up to the end of the word, to lower case.&lt;br /&gt;
|-&lt;br /&gt;
| Switch-case || Esc,^ || Changes the case of a word, starting at the current cursor position and proceeding to the right until it reaches the end of the word. If a word is upper case or has mixed text, it changes upper to lowr case and vice versa.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Search Menu ===&lt;br /&gt;
&lt;br /&gt;
These commands search through the current buffer for specific text strings. The case (upper or lower) of the string is not significant in the search. However, if you are using text substitution (search and replace), the text is replaced in the case of the replacement string.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| Search-forward || Ctrl+S || Searches through the text starting at the current cursor position and moving forward to the end of the buffer. At the prompt, enter the character string for the search. Alternative keyboard shortcut: Ctrl+X,S.&lt;br /&gt;
|-&lt;br /&gt;
| Search-backward || Ctrl+R || Searches through the text from the current cursor position backwards to the beginning to the buffer. Alternative keyboard shortcut: Ctrl+X,R.&lt;br /&gt;
|-&lt;br /&gt;
| Search-replace || Esc,R || Searches the same as Search-forward, allowing you to replace the string with different text. At the prompt, enter the replacement string of characters.&lt;br /&gt;
|-&lt;br /&gt;
| Query-s-r || Esc,Q || Operates the same as Search-replace, except it asks for confirmation to replace each time it finds the specified string. The options are Y (yes), N (no), C (change all occurrences), and Ctrl+G (abort).&lt;br /&gt;
|-&lt;br /&gt;
| Fence-match || Esc,&amp;lt;br/&amp;gt;Ctrl+F || Finds the closest occurrence of the fence character to match the one at the current cursor position. Fence characters are parenthesis, brackets, braces, and angle brackets.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Extras Menu ===&lt;br /&gt;
&lt;br /&gt;
These commands are MEmacs operational commands and macro commands. Specific numeric arguments may be required before selecting a command; an * indicate that an argument is required. Macro commands are executed by selecting the Execute-macro menu item.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| Set-arg || Ctrl+U || Lets you specify a numeric argument for a command.&lt;br /&gt;
|-&lt;br /&gt;
| Set || Esc,S || Lets you set the following MEmacs parameters:&lt;br /&gt;
 {| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
 | Screen || Places the MEmacs display in a Workbench window or back onto a custom screen.&lt;br /&gt;
 |-&lt;br /&gt;
 | Interlace || Turns the interlace mode on or off.&lt;br /&gt;
 |-&lt;br /&gt;
 | Mode || Results in a second prompt &amp;quot;Mode:&amp;quot;; you can enter Cmode (for editing C programs) or Wrap (to enable automatic word-wrap when the text reaches a set cursor position). Cmode provides automatic fence matching. Use +mode or -mode to add or subtract a mode.&lt;br /&gt;
 |-&lt;br /&gt;
 | Left || Determines the left margin. Prompts for a numerical argument if not provided with the entry.&lt;br /&gt;
 |-&lt;br /&gt;
 | Right || Determines the right margin. Prompts for a numerical argument if not provided with the entry.&lt;br /&gt;
 |-&lt;br /&gt;
 | Tab || Sets the increment for tab spacing. Prompts for a numerical argument if not provided with the entry.&lt;br /&gt;
 |-&lt;br /&gt;
 | Indent || Determines how far to indent each level of nesting (used in Cmode). Prompts for a numerical argument if not provided with the entry.&lt;br /&gt;
 |-&lt;br /&gt;
 | Case || Turns case-sensitive searches on of off; default is off.&lt;br /&gt;
 |-&lt;br /&gt;
 | Backup || Turns the MEmacs backup function on or off. Your options are: ON (renames the current file &amp;lt;filename&amp;gt;.bak and saves that bakkup file to the T: directory); SAFE (this option checks to see if a file already exists for the buffer - if so, it displays an error and does not overwrite the existing file, Ctrl+X clears the display); and OFF (this is the default option - MEmacs does not perform any backup).&lt;br /&gt;
 |}&lt;br /&gt;
|-&lt;br /&gt;
| Start-macro || Ctrl+X,( || Tells MEmacs to start recording any subsequent keystrokes. Used with the Stop-macro and Execute-macro commands.&lt;br /&gt;
|-&lt;br /&gt;
| Stop-macro || Ctrl+X,) || Tells MEmacs to stop recording keystrokes.&lt;br /&gt;
|-&lt;br /&gt;
| Execute-macro || Ctrl+X,E || Repeats keystrokes that were entered between Start-macro and Stop-macro.&lt;br /&gt;
|-&lt;br /&gt;
| Set-key || Ctrl+X,&amp;lt;br/&amp;gt;Ctrl+K || Allows you to redefine all of the function keys, the Shifted function keys, the Help key, or any key on the numeric keypad as keyboard macros. You cannot use the menu shortcut of Ctrl+@ to insert the Set-mark command into any keyboard macro definitions.&lt;br /&gt;
|-&lt;br /&gt;
| Reset-keys || Esc,K || Returns any keys defined by Set-keys to their original default state.&lt;br /&gt;
|-&lt;br /&gt;
| Execute-file || Esc,E || Allows you to execute a program file within MEmacs.&lt;br /&gt;
|-&lt;br /&gt;
| Execute-line || Ctrl+[,&amp;lt;br/&amp;gt;Ctrl+[ || Sets MEmacs to command mode. At the prompt enter any menu command and its parameters. Alternate keyboard shortcut: Esc,Esc.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The following table contains the default values of the Set-key/function keys when used in macro commands.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Key !! Assignment !! Key Sequence&lt;br /&gt;
|-&lt;br /&gt;
| F1 || Clone line || Ctrl+A,Ctrl+K,Ctrl+Y,Ctrl+M,Ctrl+Y&lt;br /&gt;
|-&lt;br /&gt;
| F2 || Delete line || Ctrl+X,Ctrl+D&lt;br /&gt;
|-&lt;br /&gt;
| F3 || Execute keyboard macro || Ctrl+X,E&lt;br /&gt;
|-&lt;br /&gt;
| F4 || Next screen || Ctrl+V&lt;br /&gt;
|-&lt;br /&gt;
| F5 || Previous screen || Esc,V&lt;br /&gt;
|-&lt;br /&gt;
| F6 || Split window || Ctrl+X,2&lt;br /&gt;
|-&lt;br /&gt;
| F7 || One window || Ctrl+X,1&lt;br /&gt;
|-&lt;br /&gt;
| F8 || Scroll window up || Ctrl+Z&lt;br /&gt;
|-&lt;br /&gt;
| F9 || Scroll window down || Esc,Z&lt;br /&gt;
|-&lt;br /&gt;
| F10 || Save file and exit || Ctrl+X,Ctrl+F&lt;br /&gt;
|-&lt;br /&gt;
| Help || Insert line || Ctrl+J&lt;br /&gt;
|-&lt;br /&gt;
| Enter (keypad) || Insert line || Ctrl+J&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Commands Not in Menus ==&lt;br /&gt;
&lt;br /&gt;
The following commands are only accessible through the keyboard.&lt;br /&gt;
&lt;br /&gt;
Keys are bound when they can be used to perform a function. For example, any key or key sequence that can be used as a shortcut for a menu item is bound to that menu item.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| Describe Key || Esc,&amp;lt;br/&amp;gt;Ctrl+D || Tells you if any functions are bound to a key or key sequence. At the prompt enter the specific key or key sequence.&lt;br /&gt;
|-&lt;br /&gt;
| Bind Key || Esc,&amp;lt;br/&amp;gt;Ctrl+B || Allows you to bind a key to a function. At the prompt, enter the key or key sequence.&lt;br /&gt;
|-&lt;br /&gt;
| Unbind Key || Esc,&amp;lt;br/&amp;gt;Ctrl+U || Allows you to return a bound key to an unbound state. At the prompt, enter the key or key sequence. Standard bound keys cannot be unbound.&lt;br /&gt;
|-&lt;br /&gt;
| Echo || Esc,&amp;lt;br/&amp;gt;Ctrl+E || Displays the string entered in the command line.&lt;br /&gt;
|-&lt;br /&gt;
| Move to Edge of Window || Shift+Arrow || Moves the cursor to the top, bottom, left, or right edge of the screen.&lt;br /&gt;
|-&lt;br /&gt;
| Delete the Next Character || Ctrl+D || Deletes the character at the current position. Same as pressing Del.&lt;br /&gt;
|-&lt;br /&gt;
| Delete the Previous Character || Ctrl+H || Deletes the character to the left of the current cursor position. Same as pressing Backspace.&lt;br /&gt;
|-&lt;br /&gt;
| Move to Next Line || Ctrl+M || Inserts a newline character after the current cursor position and moves the cursor to the start of the new line.&lt;br /&gt;
|-&lt;br /&gt;
| Move x number of Characters || Ctrl+F,&amp;lt;br/&amp;gt;Ctrl+B || Allows you to move the cursor forward or backward a specified number of spaces. Providing no value moves the cursor only one character.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Customizing MEmacs ==&lt;br /&gt;
&lt;br /&gt;
MEmacs looks for an Emacs_pro file when it is opened to see if there are any command or local files that it should automatically execute. You can customize the Emacs_pro file by adding commands to it that you use often, command sequences, or text strings. If an Emacs_pro file does not already exist, you can create one.&lt;br /&gt;
&lt;br /&gt;
To create a global file of commands, place the Emacs_pro file in the S: directory. Local files can be out in any directory. If that directory is the current directory when MEmacs is opened, the commands in that particular local file are executed.&lt;br /&gt;
&lt;br /&gt;
When both local and global Emacs_pro files are present, the local file overrides the global file.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
 Set Case On&lt;br /&gt;
 Set-Key F11 &amp;quot;Dear Sirs:&amp;quot;&lt;br /&gt;
 Set-Key F12 &amp;quot;^S Workbench&amp;quot;&lt;br /&gt;
 Set-Key F13 &amp;quot;^X^B&amp;quot;&lt;br /&gt;
&lt;br /&gt;
makes the following assignments:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| Shift+F1 || Enter the text string &amp;quot;Dear Sirs:&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
| Shift+F2 || Search forward for the next occurrence of the word Workbench. (The Set Case On commands make any text searches case-sensitive.)&lt;br /&gt;
|-&lt;br /&gt;
| Shift+F3 || Display the list of buffers.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
You must use Ctrl+Q to enter a Ctrl+key sequence. For example, to enter the ^S character shown in the example, press Ctrl+Q, Ctrl+S.&lt;br /&gt;
&lt;br /&gt;
== Quitting MEmacs ==&lt;br /&gt;
&lt;br /&gt;
You can exit MEmacs by selecting the Quit menu item in the Project menu or by entering Ctrl+C. MEmacs lets you save any modified buffers or quit without saving.&lt;br /&gt;
&lt;br /&gt;
= EDIT =&lt;br /&gt;
&lt;br /&gt;
EDIT is a line editor designed for the automated editing of files, particularly binary files or files that are larger than available memory. You cannot create a new file with EDIT.&lt;br /&gt;
&lt;br /&gt;
EDIT processes files line by line. As EDIT moves through the input, or source file, each line is passed after alteration to a sequential output file, the destination file.&lt;br /&gt;
&lt;br /&gt;
EDIT processes the lines in files in a forward direction; however, you can move backward a limited number of lines. EDIT holds the lines in an output queue before writing them to the destination file. The size of this queue depends on the amount of memory available. You can increase the size of the queue with the OPT P and OPT W options.&lt;br /&gt;
&lt;br /&gt;
The format for EDIT is the following:&lt;br /&gt;
&lt;br /&gt;
 EDIT [FROM] &amp;lt;filename&amp;gt; [[TO] &amp;lt;filename&amp;gt;] [WITH &amp;lt;filename&amp;gt;] [VER &amp;lt;filename&amp;gt;]&lt;br /&gt;
 [OPT P &amp;lt;lines&amp;gt; | W &amp;lt;chars&amp;gt; | P&amp;lt;lines&amp;gt;W&amp;lt;chars&amp;gt;] [WIDTH &amp;lt;chars&amp;gt;] [PREVIOUS &amp;lt;lines&amp;gt;]&lt;br /&gt;
&lt;br /&gt;
The FROM argument specifies the source file to be edited. You must specify a source file with EDIT, although the FROM keyword is optional.&lt;br /&gt;
&lt;br /&gt;
The TO argument specifies the destination file to which EDIT sends its output, including editing changes. If you omit the TO argument, EDIT uses a temporary file. This temporary file is renamed with the name of the FROM file and overwrites the FROM file when editing is complete.&lt;br /&gt;
&lt;br /&gt;
The WITH keyword specifies a file containing editing commands.&lt;br /&gt;
&lt;br /&gt;
The VER keyword specifies the file to which EDIT sends error messages and line verifications. If the VER argument is not given, EDIT uses the screen.&lt;br /&gt;
&lt;br /&gt;
Use OPT P &amp;lt;n&amp;gt; and OPT W &amp;lt;n&amp;gt; to specify the PREVIOUS and WIDTH options. However, do nit use the OPT keyword with PREVIOUS and WIDTH.&lt;br /&gt;
&lt;br /&gt;
You can use the PREVIOUS and WIDTH options to increase or decrease the amount of available memory. The PREVIOUS option sets the number of previous lines available to EDIT to the integer &amp;lt;n&amp;gt;. The WIDTH option sets the maximum number of characters allowed on a line to &amp;lt;n&amp;gt;. EDIT multiples the number of previous lines by the maximum number of characters (PREVIOUS * WIDTH) to determine the available memory. The default values are PREVIOUS 100 WIDTH 1200.&lt;br /&gt;
&lt;br /&gt;
== Starting EDIT ==&lt;br /&gt;
&lt;br /&gt;
Start EDIT through a Shell using the following command:&lt;br /&gt;
&lt;br /&gt;
 1.&amp;lt; EDIT &amp;lt;filename&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where &amp;lt;filename&amp;gt; is the name of an existing file to be edited.&lt;br /&gt;
&lt;br /&gt;
== EDIT Commands ==&lt;br /&gt;
&lt;br /&gt;
The following list provides background information about EDIT commands:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| Current line || Refers to the line that EDIT is working on at any time. Every command entered refers to the current line, all text changes are made to the current line, and new lines are inserted before the current line.&lt;br /&gt;
|-&lt;br /&gt;
| Original lines || The lines of the source file. Lines retain their original number until you renumber them with the REWIND or = commands.&lt;br /&gt;
|-&lt;br /&gt;
| Non-original lines || Any lines that are inserted into the source file or original lines that are split. These are not assigned line numbers.&lt;br /&gt;
|-&lt;br /&gt;
| Line verification || When using commands that change information in a line, EDIT displays the revised line after the command is executed.&lt;br /&gt;
|-&lt;br /&gt;
| Arguments || Strings, qualified strings, numbers, and switch values used with EDIT commands.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Enter commands in one of the following three ways:&lt;br /&gt;
&lt;br /&gt;
* Enter the commands, then press Return&lt;br /&gt;
* Enter the final command argument, then press Return&lt;br /&gt;
* Enter a semicolon or closing parenthesis&lt;br /&gt;
&lt;br /&gt;
The text conventions used in the command description are the following:&lt;br /&gt;
&lt;br /&gt;
* Command names are shown in upper case, although EDIT is not case-sensitive.&lt;br /&gt;
* Angle brackets indicate that information must be substituted. For example, &amp;lt;string&amp;gt; indicates that the command takes a string argument.&lt;br /&gt;
* An &amp;lt;n&amp;gt; represents a numeric argument.&lt;br /&gt;
* Square brackets indicate that the argument is optional. For example, [&amp;lt;n&amp;gt;] indicates that the command can take an optional numeric argument.&lt;br /&gt;
* Slashes are used as delimiters for strings; use one slash between two strings.&lt;br /&gt;
* Periods are used as delimiters for file names (slashes cannot be used since they are used to separate strings).&lt;br /&gt;
&lt;br /&gt;
== Selecting the Current Line ==&lt;br /&gt;
&lt;br /&gt;
The following commands let you move through the file and select the current line.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| Move to a specific line number || M &amp;lt;n&amp;gt; || Specify a new current line by entering its line number, a period, and an asterisk as M&#039;s argument. Only original lines can be accessed by line number.&lt;br /&gt;
|-&lt;br /&gt;
| Move to next line in the source file || N || Move forward one line. Entering a number and N indicates the number of lines to move forard. When used as the last line of the source file, EDIT creates an extra line at the end of the file. If you are already on this extra line, using N causes an error message to be displayed.&lt;br /&gt;
|-&lt;br /&gt;
| Move to the previous line in the source file || P || Moves back one line. Entering P repeatedly moves more than one line. Entering a number + P indicates how many lines to move back. You can only move back to previous lines that have not yet been written to the destination file. The default is 100 lines, which can be changed with the PREVIOUS option.&lt;br /&gt;
|-&lt;br /&gt;
| Find || F&amp;lt;string&amp;gt; || Lets you select a current line by specifying some of its content.&lt;br /&gt;
|-&lt;br /&gt;
| Search Backward || B,F&amp;lt;string&amp;gt; || Looks backward starting from the current line through the source file for a line containing the specified string.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Editing the Current Line ==&lt;br /&gt;
&lt;br /&gt;
The following commands add new material or replace material on the current line.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| Insert &amp;lt;string2&amp;gt; after &amp;lt;string1&amp;gt; || A &amp;lt;string1&amp;gt; &amp;lt;string2&amp;gt; || Insert &amp;lt;string2&amp;gt; after the first occurrence of &amp;lt;string1&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| Insert &amp;lt;string2&amp;gt; before &amp;lt;string1&amp;gt; || B &amp;lt;string2&amp;gt; &amp;lt;string1&amp;gt; || Insert &amp;lt;string2&amp;gt; before the first occurrence of &amp;lt;string1&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| Exchange &amp;lt;string2&amp;gt; for &amp;lt;string1&amp;gt; || E &amp;lt;string2&amp;gt; &amp;lt;string1&amp;gt; || Replaces the first occurrence of &amp;lt;string1&amp;gt; with &amp;lt;string2&amp;gt;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Inserting and Deleting Lines ==&lt;br /&gt;
&lt;br /&gt;
The following commands insert new material (non-original lines) and delete lines from the source file. You can also insert complete files into the source file.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| Insert one or more lines || I [&amp;lt;n&amp;gt;] || If given alone or with a line number, inserts text before the current line.&amp;lt;br/&amp;gt;&lt;br /&gt;
If given with an asterisk, the text is inserted at the end of the file.&amp;lt;br/&amp;gt;&lt;br /&gt;
Indicate the end of the insertion by pressing Return, Z, and Return.&lt;br /&gt;
|-&lt;br /&gt;
| Delete one or more lines || D [&amp;lt;n&amp;gt;] || Deletes the current line if entered with no arguments. Deletes a specific line if entered with a line number. Deletes a set of lines if entered with a range of line numbers; do not use punctuation between the numbers. Deletes everything from the current line through the end of the source file of entered with a period and an asterisk as arguments.&lt;br /&gt;
|-&lt;br /&gt;
| Delete all lines until the specified string is found || D,F&amp;lt;string&amp;gt; || Deletes successive lines from the source file until the line containing the matching string is found. If no argument is specified, it deletes all lines until it finds the last string specified.&lt;br /&gt;
|-&lt;br /&gt;
| Delete existing lines and replace with new text || R [&amp;lt;n&amp;gt;] || Lets you delete line and then insert new ones. Entering a line number following R indicates a specific line to replace.&lt;br /&gt;
|-&lt;br /&gt;
| Change the terminator || Z &amp;lt;string&amp;gt; || Tells EDIT that it has reached the end of any new text that is being inserted. Entering a string after Z changes it from the default.&lt;br /&gt;
|-&lt;br /&gt;
| Show current information about EDIT || S,H,D || Displays saved information values, such as the last string searched for, the last command entered, and the input terminator.&lt;br /&gt;
|-&lt;br /&gt;
| Turn trailing spaces on/off || &amp;lt;nowiki&amp;gt;T,R,+|-&amp;lt;/nowiki&amp;gt; || Preserves any blanks that fall at the end of lines.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Editing Line Windows ==&lt;br /&gt;
&lt;br /&gt;
You can define subsections of the line, called line windows, on which EDIT executes all subsequent commands. In the descriptions of EDIT qualifiers, the beginning of the line always indicates the beginning of the line window.&lt;br /&gt;
&lt;br /&gt;
Whenever EDIT verifies a current line, it indicates the position of the line window by displaying a &amp;gt; character directly beneath the line. EDIT omits the pointer if the line window begins at the start of the line.&lt;br /&gt;
&lt;br /&gt;
The following commands control the position of the character pointer:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| &amp;gt; || Moves the pointer one character to the right.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt; || Moves the pointer one character to the left.&lt;br /&gt;
|-&lt;br /&gt;
| PR || Resets the pointer to the start of the line.&lt;br /&gt;
|-&lt;br /&gt;
| PA &amp;lt;string&amp;gt; || Moves the pointer to the first character after the specified string.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;string&amp;gt; || Moves the pointer to the first character before the specified string.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The following commands change the character at the current pointer, then move the pointer.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| $ || Makes the character at the pointer lower case, then moves the pointer one character to the right.&lt;br /&gt;
|-&lt;br /&gt;
| % || Makes the character at the pointer upper case, then moves the pointer one character to the right.&lt;br /&gt;
|-&lt;br /&gt;
| _ || The _ (underscore) command deletes the character at the pointer, turning it into a space, then moves the pointer one character to the right.&lt;br /&gt;
|-&lt;br /&gt;
| # || Deletes the character at the pointer, then moves the rest of the line one character to the left. To delete several characters, specify a number before the #. For example, 5# deletes the next five characters in the window.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
A combination of these commands can be used to edit a line character by character.&lt;br /&gt;
&lt;br /&gt;
The following commands insert and exchange text on the current line, similar to the A, B, and E commands; however, the character pointer is moved on completion.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| Insert &amp;lt;string2&amp;gt; after &amp;lt;string1&amp;gt; || A,P &amp;lt;string1&amp;gt; &amp;lt;string2&amp;gt; || Inserts &amp;lt;string2&amp;gt; after the first occurrence of &amp;lt;string1&amp;gt;. The pointer is then positioned after &amp;lt;string2&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| Insert &amp;lt;string2&amp;gt; before &amp;lt;string1&amp;gt; || B,P &amp;lt;string1&amp;gt; &amp;lt;string2&amp;gt; || Inserts &amp;lt;string2&amp;gt; before the first occurrence of &amp;lt;string1&amp;gt;. The pointer is then positioned after &amp;lt;string2&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| Exchange &amp;lt;string1&amp;gt; with &amp;lt;string2&amp;gt; || E,P, &amp;lt;string1&amp;gt; &amp;lt;string2&amp;gt; || Replaces the first occurrence of &amp;lt;string1&amp;gt; with &amp;lt;string2&amp;gt;. The pointer is then positioned after &amp;lt;string2&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| Delete Till After || D,T,A &amp;lt;string&amp;gt; || Deletes all text from the beginning of the line or the character pointer to the end of the specified string.&lt;br /&gt;
|-&lt;br /&gt;
| Delete Till Before || D,T,B &amp;lt;string&amp;gt; || Deletes all text from the beginning of the line or the character pointer; stops before the specified string.&lt;br /&gt;
|-&lt;br /&gt;
| Delete From After || D,F,A &amp;lt;string&amp;gt; || Deletes all text starting after a specified string to the end of the line.&lt;br /&gt;
|-&lt;br /&gt;
| Delete From Before || D,F,B &amp;lt;string&amp;gt; || Deletes all text starting with the specified string to the end of the line.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Splitting and Joining Lines ==&lt;br /&gt;
&lt;br /&gt;
These commands split a line into more than one line and join together two or more successive lines.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| Split line before &amp;lt;string&amp;gt; || S,B &amp;lt;string&amp;gt; || Splits the current line before the specified string. The first part of the line is sent to the output queue; the second part is made into a new non-original current line. Qualifiers can be used to restrict the context of the string.&lt;br /&gt;
|-&lt;br /&gt;
| Split line after &amp;lt;string&amp;gt; || S,A &amp;lt;string&amp;gt; || Splits the current line after the specified string. The first part of the line is sent to the output queue; the remainder of the line becomes the new current line. Qualifiers can be used to restrict the context of the string.&lt;br /&gt;
|-&lt;br /&gt;
| Join two lines || C,L [&amp;lt;string&amp;gt;] || Joins the current line with the next line of the source file. The string argument is optional; however, if a string is specified it is added to the end of the current line and that whole line is joined with the next line in the source file.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Renumbering Lines ==&lt;br /&gt;
&lt;br /&gt;
These commands renumber the source file&#039;s lines to include non-original lines and to update a file that has been edited.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| Renumber source lines || = &amp;lt;n&amp;gt; || Sets the current line number to &amp;lt;n&amp;gt;. All subsequent original and non-original lines below &amp;lt;n&amp;gt; are renumbered you move to them.&lt;br /&gt;
|-&lt;br /&gt;
| Return to the beginning source file || REWIND || Moves back through the source file to make line 1 the current line. EDIT scans the rest of the source file and writes the lines to the destination file. This file is closed and reopened as a new source file. Non-original lines are now recognized as original lines. Can be entered as REWI.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Verifying Lines ==&lt;br /&gt;
&lt;br /&gt;
These commands describe different ways of verifying lines.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| Turn Verification on/off || V + &amp;lt;nowiki&amp;gt;|&amp;lt;/nowiki&amp;gt; - || Turns line verification on or off. If off, the lines are not displayed on the screen. To turn off, enter V -. To turn on, enter V +.&lt;br /&gt;
|-&lt;br /&gt;
| Verify the current line || ? || Verifies the current line by displaying the line number and the contents of the line.&lt;br /&gt;
|-&lt;br /&gt;
| Verify the current line with character indicators || ! || Produces two lines of verification. In the first line all non-graphic characters are replaced with the first character of their hexadecimal value In the second line, a minus sign is displayed under all positions corresponding to upper case letters and the second hexadecimal digit corresponds to non-graphic characters. All other positions contain spaces. In binary files, non-graphic characters are represented with question marks (??).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Inspecting the Source File ==&lt;br /&gt;
&lt;br /&gt;
These commands advance through the source file, sending the lines it passes to the verification file, as well as to the normal output. They are known as Type commands because they display lines on the screen.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| Type &amp;lt;n&amp;gt; lines to the screen || T &amp;lt;n&amp;gt; || Types the specified number of lines to the screen. The first line typed is the current line. Omitting the &amp;lt;n&amp;gt; continues typing to the end of the source file. Interrupt the command with Ctrl+C.&lt;br /&gt;
|-&lt;br /&gt;
| Type the lines in the output queue || T,P || Displays the lines currently held in the output queue.&lt;br /&gt;
|-&lt;br /&gt;
| Type until EDIT has replaced all the lines in the output queue || T,N || Types from the current line forward until all the lines in the output queue are replaced. The previous contents are sent to the destination file.&lt;br /&gt;
|-&lt;br /&gt;
| Type with line numbers || T,L &amp;lt;n&amp;gt; || Similar to the T command. Types a specified number of lines, displaying the line numbers. EDIT displays + + + + for inserted or split lines since they do not have line numbers.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Making Global Changes ==&lt;br /&gt;
&lt;br /&gt;
These commands start and stop global changes. Global changes take place automatically as EDIT scans the source file in forward direction. These commands automatically apply an A, B, or E command, as appropriate, to any occurrence of &amp;lt;string1&amp;gt; in a new current line. They also apply to the current line that is in effect when the command is given.&lt;br /&gt;
&lt;br /&gt;
 GA [qualifier] &amp;lt;string1&amp;gt; &amp;lt;string2&amp;gt;&lt;br /&gt;
 GB [qualifier] &amp;lt;string1&amp;gt; &amp;lt;string2&amp;gt;&lt;br /&gt;
 GE [qualifier] &amp;lt;string1&amp;gt; &amp;lt;string2&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For example, if you want to change DF0: to DF2: throughout an entire file, enter:&lt;br /&gt;
&lt;br /&gt;
 GE /DF0:/DF2:/&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| Cancel a global command || CG [&amp;lt;id number&amp;gt;] || Cancels a global command. The identification number set with a GA, GB, or GE command is output to the verification file or the serene if EDIT is interactive. If no argument is specified, all global operations are cancelled. To cancel a specific operation, enter the identification number of the CG command.&lt;br /&gt;
|-&lt;br /&gt;
| Suspend a global command || SG [&amp;lt;id number&amp;gt;] || Suspends a global command. All global operations are suspended if no argument is given. Enter the identification number to suspend a specific operation.&lt;br /&gt;
|-&lt;br /&gt;
| Enable a global command || EG [&amp;lt;id number&amp;gt;] || Resumes global operation that had been suspended with the SG command. Unless a specific identification number is provided, all global commands are resumed.&lt;br /&gt;
|-&lt;br /&gt;
| Show global commands || SHG || Displays the current global commands and their identification numbers. Also provides the number of times each global string was matched.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Changing Command, Input, and Output Files ==&lt;br /&gt;
&lt;br /&gt;
These commands change the files set up when you started EDIT from the Shell. These files are:&lt;br /&gt;
&lt;br /&gt;
* the command file - started with the WITH option.&lt;br /&gt;
* the input file - the source file specified with FROM.&lt;br /&gt;
* the output file - the destination file specified with TO.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| Changing the Command File || C &amp;lt;filename&amp;gt; || Reads EDIT commands from a specified file. Delimit the file using a character other than a slash (/) since AmigaDOS uses these characters to separate file names. When all commands in the specified file are executed, the file is closed. You can then enter the commands through the keyboard.&lt;br /&gt;
|-&lt;br /&gt;
| Changing the Input File || FROM &amp;lt;filename&amp;gt; || Reads lines from another source file. EDIT does not close the original source file. Reselect the source file by entering the FROM command without an argument. For example of the FROM command, see page 4-54.&lt;br /&gt;
|-&lt;br /&gt;
| Closing a File || CF &amp;lt;filename&amp;gt; || Closes the destination file that was originally specified with the TO command. You can then open that file for input. CF can also close a new input file that is open. For examples of the CF command, see page 4-54.&lt;br /&gt;
|-&lt;br /&gt;
| Changing the Output File || TO &amp;lt;filename&amp;gt; || Specifies a different file as the destination file. The TO command writes the existing queue of output lines to the new TO file. The new TO file is used until another file is specified. Reselect the original destination file by using the TO command with no argument. The alternate output file remains open, but unused. For examples of the TO command, see page 4-54.&lt;br /&gt;
|-&lt;br /&gt;
| Stop executing the command file || Q || Stops EDIT from executing the current command file specified with the WITH keyword or with the C command. EDIT reverts to any previous command file. Using Q at the outermost level is equivalent to using the W command.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The FROM, CF, and TO commands are used as follows:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Command !! Action&lt;br /&gt;
|-&lt;br /&gt;
| M10 || Pass lines 1-9 in the original source file to the output queue.&lt;br /&gt;
|-&lt;br /&gt;
| FROM .XYZ. || Select the XYZ file for new input; line 10 of the original source file remains current.&lt;br /&gt;
|-&lt;br /&gt;
| M6 || Pass line 10 from the original file, then pass lines 1-5 from the XYZ file to the output queue. Line 6 of XYZ is the new current line.&lt;br /&gt;
|-&lt;br /&gt;
| FROM || Reselect the original source file.&lt;br /&gt;
|-&lt;br /&gt;
| M14 || Pass line 6 from XYZ, then lines 11-13 from the original source file to the output queue. Line 14 of the source file is the new current line.&lt;br /&gt;
|-&lt;br /&gt;
| FROM .XYZ. || Reselect file XYZ. Line 14 of the source file is still the current line.&lt;br /&gt;
|-&lt;br /&gt;
| M* || Pass line 14 of the source file and all remaining lines of file XYZ to the output queue. An extra line is added to the end of file XYZ. That line is the new current line.&lt;br /&gt;
|-&lt;br /&gt;
| FROM || Reselect the original source file. The extra line added to file XYZ is still the current line.&lt;br /&gt;
|-&lt;br /&gt;
| CF .XYZ. || Close file XYZ.&lt;br /&gt;
|-&lt;br /&gt;
| M* || Pass the remaining lines of the source file (lines 15 to the end of the file) to the output queue.&lt;br /&gt;
|-&lt;br /&gt;
| M11 || Pass lines 1-10 of the source file to the original destination file.&lt;br /&gt;
|-&lt;br /&gt;
| TO .XYZ. || Make XYZ the new output file.&lt;br /&gt;
|-&lt;br /&gt;
| M21 || Pass lines 11-20 to file XYZ.&lt;br /&gt;
|-&lt;br /&gt;
| TO M31 || Make the original destination file current, and pass lines 21 to 30 to it.&lt;br /&gt;
|-&lt;br /&gt;
| TO .XYZ. || Make XYZ the current output file.&lt;br /&gt;
|-&lt;br /&gt;
| M41 || Pass lines 31 to 40 to XYZ.&lt;br /&gt;
|-&lt;br /&gt;
| TO || Make the original destination file current.&lt;br /&gt;
|-&lt;br /&gt;
| TO .XYZ. || Send the output queue to file XYZ.&lt;br /&gt;
|-&lt;br /&gt;
| 1000N || Advance through the next 1000 lines of the source file.&lt;br /&gt;
|-&lt;br /&gt;
| TO || Select the original destination file.&lt;br /&gt;
|-&lt;br /&gt;
| CF .XYZ. || Close the XYZ file.&lt;br /&gt;
|-&lt;br /&gt;
| I2000 .XYZ. || Insert the 1000 lines from the source file that were sent to file XYZ back into the source file above line 2000.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Ending EDIT ==&lt;br /&gt;
&lt;br /&gt;
These commands exit EDIT.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| Exit, saving changes || W || Exits EDIT, saving all changes to the destination file specified by TO. EDIT exits after reaching the end of the source, closing all the files, and relinquishing memory. If you started EDIT without specifying a destination file, it renames the temporary destination with the same name as the original source file, which is renamed. T/Edit-backup. This backup is only available until the next time you run EDIT.&lt;br /&gt;
|-&lt;br /&gt;
| Exit, without saving changes || STOP || Stops EDIT immediately without saving any changes to the source file. Prevents EDIT from overwriting to original source file, ensuring that no changes are made to the original input information.&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Costel Mincea</name></author>
	</entry>
	<entry>
		<id>https://wiki.amigaos.net/w/index.php?title=MediaWiki:Sidebar&amp;diff=12578</id>
		<title>MediaWiki:Sidebar</title>
		<link rel="alternate" type="text/html" href="https://wiki.amigaos.net/w/index.php?title=MediaWiki:Sidebar&amp;diff=12578"/>
		<updated>2025-09-12T05:33:18Z</updated>

		<summary type="html">&lt;p&gt;Costel Mincea: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* Navigation&lt;br /&gt;
** mainpage|mainpage-description&lt;br /&gt;
** recentchanges-url|recentchanges&lt;br /&gt;
* Developers&lt;br /&gt;
** Autodocs:Main|Autodocs&lt;br /&gt;
** Tutorials:Main|Tutorials&lt;br /&gt;
** DeveloperDoc:Registries|Registries&lt;br /&gt;
** DeveloperDoc:Standards|Standards&lt;br /&gt;
** DeveloperDoc:Main|Reference&lt;br /&gt;
** https://www.amigaos.net/viewforum.php?f=25|AmigaOS Support Forums&lt;br /&gt;
** https://os4coding.net/forum|OS4Coding Forum&lt;br /&gt;
** https://www.hyperion-entertainment.com/index.php/downloads?view=files&amp;amp;parent=30|Get the SDK&lt;br /&gt;
* Users&lt;br /&gt;
** AmigaOS_Manual:_Workbench|Workbench&lt;br /&gt;
** AmigaOS_Manual:_AmigaDOS|DOS&lt;br /&gt;
** AmigaOS_Manual:_ARexx|ARexx&lt;br /&gt;
** Bars_%26_Pipes_Professional|Bars &amp;amp; Pipes Professional&lt;br /&gt;
* Links&lt;br /&gt;
** https://www.hyperion-entertainment.com/|Hyperion Entertainment&lt;br /&gt;
** https://www.amigaos.net/|AmigaOS Web Site&lt;br /&gt;
** http://support.amigaos.net/|AmigaOS Support Forums&lt;br /&gt;
* SEARCH&lt;br /&gt;
* TOOLBOX&lt;/div&gt;</summary>
		<author><name>Costel Mincea</name></author>
	</entry>
	<entry>
		<id>https://wiki.amigaos.net/w/index.php?title=MediaWiki:Sidebar&amp;diff=12577</id>
		<title>MediaWiki:Sidebar</title>
		<link rel="alternate" type="text/html" href="https://wiki.amigaos.net/w/index.php?title=MediaWiki:Sidebar&amp;diff=12577"/>
		<updated>2025-09-12T05:32:44Z</updated>

		<summary type="html">&lt;p&gt;Costel Mincea: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* Navigation&lt;br /&gt;
** mainpage|mainpage-description&lt;br /&gt;
** recentchanges-url|recentchanges&lt;br /&gt;
* Developers&lt;br /&gt;
** Autodocs:Main|Autodocs&lt;br /&gt;
** Tutorials:Main|Tutorials&lt;br /&gt;
** DeveloperDoc:Registries|Registries&lt;br /&gt;
** DeveloperDoc:Standards|Standards&lt;br /&gt;
** DeveloperDoc:Main|Reference&lt;br /&gt;
** https://www.amigaos.net/viewforum.php?f=25|AmigaOS Support Forums (*)&lt;br /&gt;
** https://os4coding.net/forum|OS4Coding Forum (*)&lt;br /&gt;
** https://www.hyperion-entertainment.com/index.php/downloads?view=files&amp;amp;parent=30|Get the SDK (*)&lt;br /&gt;
* Users&lt;br /&gt;
** AmigaOS_Manual:_Workbench|Workbench&lt;br /&gt;
** AmigaOS_Manual:_AmigaDOS|DOS&lt;br /&gt;
** AmigaOS_Manual:_ARexx|ARexx&lt;br /&gt;
** Bars_%26_Pipes_Professional|Bars &amp;amp; Pipes Professional&lt;br /&gt;
* Links&lt;br /&gt;
** https://www.hyperion-entertainment.com/|Hyperion Entertainment (*)&lt;br /&gt;
** https://www.amigaos.net/|AmigaOS Web Site (*)&lt;br /&gt;
** http://support.amigaos.net/|AmigaOS Support Forums (*)&lt;br /&gt;
* (*) external&lt;br /&gt;
* SEARCH&lt;br /&gt;
* TOOLBOX&lt;/div&gt;</summary>
		<author><name>Costel Mincea</name></author>
	</entry>
	<entry>
		<id>https://wiki.amigaos.net/w/index.php?title=MediaWiki:Sidebar&amp;diff=12576</id>
		<title>MediaWiki:Sidebar</title>
		<link rel="alternate" type="text/html" href="https://wiki.amigaos.net/w/index.php?title=MediaWiki:Sidebar&amp;diff=12576"/>
		<updated>2025-09-12T05:32:10Z</updated>

		<summary type="html">&lt;p&gt;Costel Mincea: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* Navigation&lt;br /&gt;
** mainpage|mainpage-description&lt;br /&gt;
** recentchanges-url|recentchanges&lt;br /&gt;
* Developers&lt;br /&gt;
** Autodocs:Main|Autodocs&lt;br /&gt;
** Tutorials:Main|Tutorials&lt;br /&gt;
** DeveloperDoc:Registries|Registries&lt;br /&gt;
** DeveloperDoc:Standards|Standards&lt;br /&gt;
** DeveloperDoc:Main|Reference&lt;br /&gt;
** https://www.amigaos.net/viewforum.php?f=25|AmigaOS Support Forums (*)&lt;br /&gt;
** https://os4coding.net/forum|OS4Coding Forum (*)&lt;br /&gt;
** https://www.hyperion-entertainment.com/index.php/downloads?view=files&amp;amp;parent=30|Get the SDK (*)&lt;br /&gt;
* Users&lt;br /&gt;
** AmigaOS_Manual:_Workbench|Workbench&lt;br /&gt;
** AmigaOS_Manual:_AmigaDOS|DOS&lt;br /&gt;
** AmigaOS_Manual:_ARexx|ARexx&lt;br /&gt;
** Bars_%26_Pipes_Professional|Bars &amp;amp; Pipes Professional&lt;br /&gt;
* Links&lt;br /&gt;
** https://www.hyperion-entertainment.com/|Hyperion Entertainment*&lt;br /&gt;
** https://www.amigaos.net/|AmigaOS Web Site*&lt;br /&gt;
** http://support.amigaos.net/|AmigaOS Support Forums*&lt;br /&gt;
* SEARCH&lt;br /&gt;
* TOOLBOX&lt;/div&gt;</summary>
		<author><name>Costel Mincea</name></author>
	</entry>
	<entry>
		<id>https://wiki.amigaos.net/w/index.php?title=MediaWiki:Sidebar&amp;diff=12575</id>
		<title>MediaWiki:Sidebar</title>
		<link rel="alternate" type="text/html" href="https://wiki.amigaos.net/w/index.php?title=MediaWiki:Sidebar&amp;diff=12575"/>
		<updated>2025-09-12T05:31:49Z</updated>

		<summary type="html">&lt;p&gt;Costel Mincea: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* Navigation&lt;br /&gt;
** mainpage|mainpage-description&lt;br /&gt;
** recentchanges-url|recentchanges&lt;br /&gt;
* Developers&lt;br /&gt;
** Autodocs:Main|Autodocs&lt;br /&gt;
** Tutorials:Main|Tutorials&lt;br /&gt;
** DeveloperDoc:Registries|Registries&lt;br /&gt;
** DeveloperDoc:Standards|Standards&lt;br /&gt;
** DeveloperDoc:Main|Reference&lt;br /&gt;
** https://www.amigaos.net/viewforum.php?f=25|AmigaOS Support Forums[*]&lt;br /&gt;
** https://os4coding.net/forum|OS4Coding Forum[*]&lt;br /&gt;
** https://www.hyperion-entertainment.com/index.php/downloads?view=files&amp;amp;parent=30|Get the SDK[*]&lt;br /&gt;
* Users&lt;br /&gt;
** AmigaOS_Manual:_Workbench|Workbench&lt;br /&gt;
** AmigaOS_Manual:_AmigaDOS|DOS&lt;br /&gt;
** AmigaOS_Manual:_ARexx|ARexx&lt;br /&gt;
** Bars_%26_Pipes_Professional|Bars &amp;amp; Pipes Professional&lt;br /&gt;
* Links&lt;br /&gt;
** https://www.hyperion-entertainment.com/|Hyperion Entertainment*&lt;br /&gt;
** https://www.amigaos.net/|AmigaOS Web Site*&lt;br /&gt;
** http://support.amigaos.net/|AmigaOS Support Forums*&lt;br /&gt;
* SEARCH&lt;br /&gt;
* TOOLBOX&lt;/div&gt;</summary>
		<author><name>Costel Mincea</name></author>
	</entry>
	<entry>
		<id>https://wiki.amigaos.net/w/index.php?title=MediaWiki:Sidebar&amp;diff=12574</id>
		<title>MediaWiki:Sidebar</title>
		<link rel="alternate" type="text/html" href="https://wiki.amigaos.net/w/index.php?title=MediaWiki:Sidebar&amp;diff=12574"/>
		<updated>2025-09-12T05:31:09Z</updated>

		<summary type="html">&lt;p&gt;Costel Mincea: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* Navigation&lt;br /&gt;
** mainpage|mainpage-description&lt;br /&gt;
** recentchanges-url|recentchanges&lt;br /&gt;
* Developers&lt;br /&gt;
** Autodocs:Main|Autodocs&lt;br /&gt;
** Tutorials:Main|Tutorials&lt;br /&gt;
** DeveloperDoc:Registries|Registries&lt;br /&gt;
** DeveloperDoc:Standards|Standards&lt;br /&gt;
** DeveloperDoc:Main|Reference&lt;br /&gt;
** https://www.amigaos.net/viewforum.php?f=25|AmigaOS Support Forums*&lt;br /&gt;
** https://os4coding.net/forum|OS4Coding Forum*&lt;br /&gt;
** https://www.hyperion-entertainment.com/index.php/downloads?view=files&amp;amp;parent=30|Get the SDK*&lt;br /&gt;
* Users&lt;br /&gt;
** AmigaOS_Manual:_Workbench|Workbench&lt;br /&gt;
** AmigaOS_Manual:_AmigaDOS|DOS&lt;br /&gt;
** AmigaOS_Manual:_ARexx|ARexx&lt;br /&gt;
** Bars_%26_Pipes_Professional|Bars &amp;amp; Pipes Professional&lt;br /&gt;
* Links&lt;br /&gt;
** https://www.hyperion-entertainment.com/|Hyperion Entertainment*&lt;br /&gt;
** https://www.amigaos.net/|AmigaOS Web Site*&lt;br /&gt;
** http://support.amigaos.net/|AmigaOS Support Forums*&lt;br /&gt;
* SEARCH&lt;br /&gt;
* TOOLBOX&lt;br /&gt;
&lt;br /&gt;
(*) external site&lt;/div&gt;</summary>
		<author><name>Costel Mincea</name></author>
	</entry>
	<entry>
		<id>https://wiki.amigaos.net/w/index.php?title=MediaWiki:Sidebar&amp;diff=12573</id>
		<title>MediaWiki:Sidebar</title>
		<link rel="alternate" type="text/html" href="https://wiki.amigaos.net/w/index.php?title=MediaWiki:Sidebar&amp;diff=12573"/>
		<updated>2025-09-12T05:29:20Z</updated>

		<summary type="html">&lt;p&gt;Costel Mincea: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* Navigation&lt;br /&gt;
** mainpage|mainpage-description&lt;br /&gt;
** recentchanges-url|recentchanges&lt;br /&gt;
* Developers&lt;br /&gt;
** Autodocs:Main|Autodocs&lt;br /&gt;
** Tutorials:Main|Tutorials&lt;br /&gt;
** DeveloperDoc:Registries|Registries&lt;br /&gt;
** DeveloperDoc:Standards|Standards&lt;br /&gt;
** DeveloperDoc:Main|Reference&lt;br /&gt;
** https://www.amigaos.net/viewforum.php?f=25|AmigaOS Support Forums (ext)&lt;br /&gt;
** https://os4coding.net/forum|OS4Coding Forum (ext)&lt;br /&gt;
** https://www.hyperion-entertainment.com/index.php/downloads?view=files&amp;amp;parent=30|Get the SDK (ext)&lt;br /&gt;
* Users&lt;br /&gt;
** AmigaOS_Manual:_Workbench|Workbench&lt;br /&gt;
** AmigaOS_Manual:_AmigaDOS|DOS&lt;br /&gt;
** AmigaOS_Manual:_ARexx|ARexx&lt;br /&gt;
** Bars_%26_Pipes_Professional|Bars &amp;amp; Pipes Professional&lt;br /&gt;
* Links&lt;br /&gt;
** https://www.hyperion-entertainment.com/|Hyperion Entertainment (ext)&lt;br /&gt;
** https://www.amigaos.net/|AmigaOS Web Site (ext)&lt;br /&gt;
** http://support.amigaos.net/|AmigaOS Support Forums (ext)&lt;br /&gt;
* SEARCH&lt;br /&gt;
* TOOLBOX&lt;/div&gt;</summary>
		<author><name>Costel Mincea</name></author>
	</entry>
	<entry>
		<id>https://wiki.amigaos.net/w/index.php?title=MediaWiki:Sidebar&amp;diff=12572</id>
		<title>MediaWiki:Sidebar</title>
		<link rel="alternate" type="text/html" href="https://wiki.amigaos.net/w/index.php?title=MediaWiki:Sidebar&amp;diff=12572"/>
		<updated>2025-09-12T05:26:33Z</updated>

		<summary type="html">&lt;p&gt;Costel Mincea: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* Navigation&lt;br /&gt;
** mainpage|mainpage-description&lt;br /&gt;
** recentchanges-url|recentchanges&lt;br /&gt;
* Developers&lt;br /&gt;
** Autodocs:Main|Autodocs&lt;br /&gt;
** Tutorials:Main|Tutorials&lt;br /&gt;
** DeveloperDoc:Registries|Registries&lt;br /&gt;
** DeveloperDoc:Standards|Standards&lt;br /&gt;
** DeveloperDoc:Main|Reference&lt;br /&gt;
** [https://www.amigaos.net/viewforum.php?f=25 AmigaOS Support Forums]&lt;br /&gt;
** [https://os4coding.net/forum OS4Coding Forum]&lt;br /&gt;
** [https://www.hyperion-entertainment.com/index.php/downloads?view=files&amp;amp;parent=30 SDK]&lt;br /&gt;
* Users&lt;br /&gt;
** AmigaOS_Manual:_Workbench|Workbench&lt;br /&gt;
** AmigaOS_Manual:_AmigaDOS|DOS&lt;br /&gt;
** AmigaOS_Manual:_ARexx|ARexx&lt;br /&gt;
** Bars_%26_Pipes_Professional|Bars &amp;amp; Pipes Professional&lt;br /&gt;
* Links&lt;br /&gt;
** [https://www.hyperion-entertainment.com/ Hyperion Entertainment]&lt;br /&gt;
** [https://www.amigaos.net/ AmigaOS Web Site]&lt;br /&gt;
** [http://support.amigaos.net/ AmigaOS Support Forums]&lt;br /&gt;
* SEARCH&lt;br /&gt;
* TOOLBOX&lt;/div&gt;</summary>
		<author><name>Costel Mincea</name></author>
	</entry>
	<entry>
		<id>https://wiki.amigaos.net/w/index.php?title=Writing_Datatype_Classes&amp;diff=12569</id>
		<title>Writing Datatype Classes</title>
		<link rel="alternate" type="text/html" href="https://wiki.amigaos.net/w/index.php?title=Writing_Datatype_Classes&amp;diff=12569"/>
		<updated>2025-01-26T19:46:12Z</updated>

		<summary type="html">&lt;p&gt;Costel Mincea: Text replacement - &amp;quot;&amp;lt;syntaxhighlight&amp;gt;&amp;quot; to &amp;quot;&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Subclassing =&lt;br /&gt;
&lt;br /&gt;
For each of the DataType categories, there is a class that handles the data. Handlers for explicit data are subclasses under the appropriate class. For example, a class that handles ILBM pictures would be a subclass of the Picture class.&lt;br /&gt;
&lt;br /&gt;
In order to fully understand the class concept used by DataTypes it helps to have a basic understanding of BOOPSI.&lt;br /&gt;
&lt;br /&gt;
A subclass must provide an OM_NEW method that converts the source data into the data format required by the superclass.  The subclass must optionally have a OM_DISPOSE method that discards any of the data constructed in the OM_NEW method. All other methods must be passed to the superclass.&lt;br /&gt;
&lt;br /&gt;
Following is a listing of a example class dispatcher for a subclass of the picture class:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
uint32 Dispatch(Class *cl, Object *o, Msg msg)&lt;br /&gt;
{&lt;br /&gt;
    struct ClassBase *cb = (struct ClassBase *) cl-&amp;gt;cl_UserData;&lt;br /&gt;
    uint32 retval;&lt;br /&gt;
&lt;br /&gt;
    switch (msg-&amp;gt;MethodID)&lt;br /&gt;
    {&lt;br /&gt;
        case OM_NEW:&lt;br /&gt;
            if (retval = IIntuition-&amp;gt;IDoSuperMethodA(cl, o, msg))&lt;br /&gt;
            {&lt;br /&gt;
                /* Convert the source data to required data format */&lt;br /&gt;
                if (!GetObjectData (cb, cl, (Object *)retval,&lt;br /&gt;
                             ((struct opSet *) msg)-&amp;gt;ops_AttrList))&lt;br /&gt;
                {&lt;br /&gt;
                    /* Force disposal of the object */&lt;br /&gt;
                    IIntuition-&amp;gt;ICoerceMethod (cl, (Object *) retval, OM_DISPOSE);&lt;br /&gt;
                    retval = NULL;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            break;&lt;br /&gt;
&lt;br /&gt;
        /* Let the superclass handle everything else */&lt;br /&gt;
        default:&lt;br /&gt;
            retval = (uint32) IIntuition-&amp;gt;IDoSuperMethodA (cl, o, msg);&lt;br /&gt;
            break;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return (retval);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Obtaining a Handle to the Source Data ==&lt;br /&gt;
&lt;br /&gt;
The first step that a class has to perform in order to convert the source data, is to get a handle on the data. This is obtained by passing the DTA_Handle tag to the superclass using the OM_GET method. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
Object *o;&lt;br /&gt;
BPTR fh;&lt;br /&gt;
&lt;br /&gt;
IDataTypes-&amp;gt;GetDTAttrs(o, DTA_Handle, &amp;amp;fh, TAG_END);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the source Type is DTF_IFF, then DTA_Handle points to a struct IFFHandle that is already initialized and opened for reading, otherwise the handle points to a BPTR file handle.&lt;br /&gt;
&lt;br /&gt;
== Handling Errors ==&lt;br /&gt;
&lt;br /&gt;
Whenever an error occurs and the class is unable to continue converting the data, then it must set an appropriate error using the DOS SetIoErr() function and the &amp;lt;dos/dos.h&amp;gt; error codes or the error codes defined in &amp;lt;datatypes/datatypes.h&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
For example, if the class is unable to allocate memory:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
if (buf = IExec-&amp;gt;AllocVecTags(size, AVT_ClearWithValue, 0, TAG_END))&lt;br /&gt;
    {&lt;br /&gt;
	... continue with conversion ...&lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
	IDOS-&amp;gt;SetIoErr (ERROR_NO_FREE_STORE);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Data Format ==&lt;br /&gt;
&lt;br /&gt;
The following sections outline the required data format for each of the main object types.&lt;br /&gt;
&lt;br /&gt;
=== Picture Class ===&lt;br /&gt;
&lt;br /&gt;
The picture class is the superclass for any static graphic classes. The structures and tags used by this class are defined in &amp;lt;datatypes/pictureclass.h&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
A picture subclass must fill out a BitMapHeader structure as well as provide a Mode ID, a BitMap and a ColorMap during the OM_NEW method of the class.  There is no need to provide any other methods, as the remainder is handled by the picture class itself.&lt;br /&gt;
&lt;br /&gt;
The picture subclass needs to fill in any fields of the BitMapHeader structure that the class has data for. This will ensure that the picture data can then be saved to a file or copied to the clipboard.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct BitMapHeader *bmh;&lt;br /&gt;
&lt;br /&gt;
/* Obtain a pointer to the BitMapHeader structure from the picture class */&lt;br /&gt;
if (IDataTypes-&amp;gt;GetDTAttrs (dto, PDTA_BitMapHeader, &amp;amp;bmh, TAG_END) &amp;amp;&amp;amp; bmh)&lt;br /&gt;
{&lt;br /&gt;
  /* Fill in some fields */&lt;br /&gt;
  bmh-&amp;gt;bmh_Width  = 640;&lt;br /&gt;
  bmh-&amp;gt;bmh_Height = 200;&lt;br /&gt;
  bmh-&amp;gt;bmh_Depth  = 2;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Before manipulating any color information, the picture subclass must first tell the picture class how many colors it has, so that the information required for color remapping can be established.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
IDataTypes-&amp;gt;SetDTAttrs (dto, PDTA_NumColors, ncolors, TAG_END);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After the number of colors have been established, the palette information can be filled in for the picture. The following fragment illustrates filling in the palette information.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct ColorRegister *cmap;&lt;br /&gt;
int16 n, ncolors;&lt;br /&gt;
int32 *cregs;&lt;br /&gt;
&lt;br /&gt;
/* Get a pointer to the color registers that need to be&lt;br /&gt;
 * filled in */&lt;br /&gt;
IDataTypes-&amp;gt;GetDTAttrs (dto,&lt;br /&gt;
  PDTA_ColorRegisters, &amp;amp;cmap,&lt;br /&gt;
  PDTA_CRegs, &amp;amp;cregs,&lt;br /&gt;
  TAG_END);&lt;br /&gt;
&lt;br /&gt;
/* Set the color information */&lt;br /&gt;
for (n = 0; n &amp;lt; ncolors; n++)&lt;br /&gt;
{&lt;br /&gt;
  if (IDOS-&amp;gt;Read (fh, &amp;amp;rgb, QSIZE) == QSIZE)&lt;br /&gt;
  {&lt;br /&gt;
    /* Set the master color table */&lt;br /&gt;
    cmap-&amp;gt;red   = rgb.rgbRed;&lt;br /&gt;
    cmap-&amp;gt;green = rgb.rgbGreen;&lt;br /&gt;
    cmap-&amp;gt;blue  = rgb.rgbBlue;&lt;br /&gt;
    cmap++;&lt;br /&gt;
&lt;br /&gt;
    /* Set the color table used for remapping */&lt;br /&gt;
    cregs[n * 3 + 0] = rgb.rgbRed   &amp;lt;&amp;lt; 24;&lt;br /&gt;
    cregs[n * 3 + 1] = rgb.rgbGreen &amp;lt;&amp;lt; 24;&lt;br /&gt;
    cregs[n * 3 + 2] = rgb.rgbBlue  &amp;lt;&amp;lt; 24;&lt;br /&gt;
  }&lt;br /&gt;
  else&lt;br /&gt;
  {&lt;br /&gt;
    /* Indicate that we encountered an error. DOS Read&lt;br /&gt;
     * will have already filled in the IoErr() value */&lt;br /&gt;
    return FALSE;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The picture class must get the actual picture information in standard Amiga bitmap format. If the bitmap is allocated using the graphics AllocBitMap() function, then the picture class can dispose of the bitmap at OM_DISPOSE time.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct BitMap *bm;&lt;br /&gt;
&lt;br /&gt;
if (bm = IGraphics-&amp;gt;AllocBitMap (bmh-&amp;gt;bmh_Width, bmh-&amp;gt;bmh_Height, bmh-&amp;gt;bmh_Depth, BMF_CLEAR, NULL))&lt;br /&gt;
{&lt;br /&gt;
  /* Tell the picture class about the picture data */&lt;br /&gt;
  IDataTypes-&amp;gt;SetDTAttrsA (dto, PDTA_BitMap, bm, TAG_END);&lt;br /&gt;
}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
  /* Indicate the error and that we encountered an error */&lt;br /&gt;
  IDOS-&amp;gt;SetIoErr (ERROR_NO_FREE_STORE);&lt;br /&gt;
  return FALSE;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A picture subclass needs to provide the following fields to the superclass, during the OM_NEW method:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| DTA_NominalHoriz || (int32) Set to the width of the picture.&lt;br /&gt;
|-&lt;br /&gt;
| DTA_NominalVert || (int32) Set to the height of the picture.&lt;br /&gt;
|-&lt;br /&gt;
| PDTA_ModeID || (uint32) A valid mode ID for the BitMap.&lt;br /&gt;
|-&lt;br /&gt;
| DTA_ObjName || (STRPTR) The name, or title, of the picture&lt;br /&gt;
|-&lt;br /&gt;
| DTA_ObjAuthor || (STRPTR) The author of the picture.&lt;br /&gt;
|-&lt;br /&gt;
| DTA_ObjAnnotation || (STRPTR) Notes on the picture.&lt;br /&gt;
|-&lt;br /&gt;
| DTA_ObjCopyright || (STRPTR) Copyright notice for the picture.&lt;br /&gt;
|-&lt;br /&gt;
| DTA_ObjVersion || (STRPTR) Version of the picture.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If a picture subclass uses something other than AllocBitMap() to allocate the bitmap, then it must free the bitmap itself. This is done by implementing an OM_DISPOSE method for the subclass.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
uint32 Dispatch (Class *cl, Object *o, Msg msg)&lt;br /&gt;
{&lt;br /&gt;
  struct ClassBase *cb = (struct ClassBase *) cl-&amp;gt;cl_UserData;&lt;br /&gt;
  struct localData *lod;&lt;br /&gt;
  uint32 retval;&lt;br /&gt;
&lt;br /&gt;
  switch (msg-&amp;gt;MethodID)&lt;br /&gt;
  {&lt;br /&gt;
      case OM_NEW:&lt;br /&gt;
        /* ... */&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
      case OM_DISPOSE:&lt;br /&gt;
        /* Get a pointer to our object data */&lt;br /&gt;
        lod = INST_DATA (cl, o);&lt;br /&gt;
&lt;br /&gt;
        /* Tell the picture class that it doesn&#039;t have a&lt;br /&gt;
         * bitmap to free any more */&lt;br /&gt;
        IDataTypes-&amp;gt;SetDTAttrs (o, PDTA_BitMap, NULL, TAG_END);&lt;br /&gt;
&lt;br /&gt;
        /* Free the bitmap ourself */&lt;br /&gt;
        myfreebitmap (lod-&amp;gt;lod_BitMap);&lt;br /&gt;
&lt;br /&gt;
      /* Let the superclass handle everything else */&lt;br /&gt;
      default:&lt;br /&gt;
        retval = (uint32) IIntuition-&amp;gt;DoSuperMethodA (cl, o, msg);&lt;br /&gt;
        break;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return retval;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Sound Class ===&lt;br /&gt;
&lt;br /&gt;
The sound class is the superclass for any sampled audio classes. The structures and tags used by this class are defined in&lt;br /&gt;
&amp;lt;datatypes/soundclass.h&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
A sound subclass needs to provide the following fields to the superclass, during the OM_NEW method:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| SDTA_Sample || (uint8 *) 8-bit sound data. The sound class will FreeVec() the sample data.&lt;br /&gt;
|-&lt;br /&gt;
| SDTA_SampleLength || (uint32) Number of 8-bit bytes in the sound data.&lt;br /&gt;
|-&lt;br /&gt;
| SDTA_Volume || (uint16) Number ranging from 0 being the quietest to 64 being the loudest.&lt;br /&gt;
|-&lt;br /&gt;
| SDTA_Period || (uint16) Amount of time to play the sound.&lt;br /&gt;
|-&lt;br /&gt;
| SDTA_Cycles || (uint16) Number of times to play the sound. 0 being an infinite loop.&lt;br /&gt;
|-&lt;br /&gt;
| DTA_ObjName || (STRPTR) The name, or title, of the sound&lt;br /&gt;
|-&lt;br /&gt;
| DTA_ObjAuthor || (STRPTR) The author of the sound.&lt;br /&gt;
|-&lt;br /&gt;
| DTA_ObjAnnotation || (STRPTR) Notes on the sound.&lt;br /&gt;
|-&lt;br /&gt;
| DTA_ObjCopyright || (STRPTR) Copyright notice for the sound.&lt;br /&gt;
|-&lt;br /&gt;
| DTA_ObjVersion || (STRPTR) Version of the sound.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
No methods other OM_NEW are need, as the remainder is handled by the sound class itself.&lt;br /&gt;
&lt;br /&gt;
The sound subclass also needs to fill in any fields of the VoiceHeader structure that the class has data for. This will ensure that the sound data can then be saved to a file or copied to the clipboard.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct VoiceHeader *vh;&lt;br /&gt;
&lt;br /&gt;
/* Obtain a pointer to the VoiceHeader structure from the sound class */&lt;br /&gt;
if (IDataTypes-&amp;gt;GetDTAttrs (dto, SDTA_VoiceHeader, &amp;amp;vh, TAG_END) &amp;amp;&amp;amp; vh)&lt;br /&gt;
{&lt;br /&gt;
  /* Fill in some fields */&lt;br /&gt;
  vh-&amp;gt;vh_Octaves     = 1;&lt;br /&gt;
  vh-&amp;gt;vh_Compression = 0;&lt;br /&gt;
  vh-&amp;gt;vh_Volume      = 63;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If a sound subclass uses something other than AllocVec() to allocate the sound data, then it must free the sample itself. This is done by implementing an OM_DISPOSE method for the subclass.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
uint32 Dispatch (Class *cl, Object *o, Msg msg)&lt;br /&gt;
{&lt;br /&gt;
  struct ClassBase *cb = (struct ClassBase *) cl-&amp;gt;cl_UserData;&lt;br /&gt;
  struct localData *lod;&lt;br /&gt;
  uint32 retval;&lt;br /&gt;
&lt;br /&gt;
  switch (msg-&amp;gt;MethodID)&lt;br /&gt;
  {&lt;br /&gt;
    case OM_NEW:&lt;br /&gt;
      /* ... */&lt;br /&gt;
      break;&lt;br /&gt;
&lt;br /&gt;
    case OM_DISPOSE:&lt;br /&gt;
      /* Get a pointer to our object data */&lt;br /&gt;
      lod = INST_DATA (cl, o);&lt;br /&gt;
&lt;br /&gt;
      /* Tell the sound class that it doesn&#039;t have a&lt;br /&gt;
       * sample to free any more */&lt;br /&gt;
      IDataTypes-&amp;gt;SetDTAttrs (o, SDTA_Sample, NULL, TAG_END);&lt;br /&gt;
&lt;br /&gt;
      /* Free the sample ourself */&lt;br /&gt;
      IExec-&amp;gt;FreeVec(lod-&amp;gt;lod_Sample);&lt;br /&gt;
&lt;br /&gt;
      /* Let the superclass handle everything else */&lt;br /&gt;
    default:&lt;br /&gt;
      retval = (uint32) IIntuition-&amp;gt;IDoSuperMethodA (cl, o, msg);&lt;br /&gt;
      break;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return retval;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Text Class ===&lt;br /&gt;
&lt;br /&gt;
The text class is the superclass for any formatted or non-formatted text classes. The structures and tags used by this class are defined in &amp;lt;datatypes/textclass.h&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The text class provides the subclass with a buffer that contains the text data. The subclass must then provide the text class with a list of Line segments during the layout method. This Line list should only be created at gpl_Initial time, unless the TDTA_WordWrap attribute is TRUE.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct Line&lt;br /&gt;
{&lt;br /&gt;
  struct MinNode ln_Link;&lt;br /&gt;
  STRPTR         ln_Text;&lt;br /&gt;
  ULONG		 ln_TextLen;&lt;br /&gt;
  UWORD		 ln_XOffset;&lt;br /&gt;
  UWORD		 ln_YOffset;&lt;br /&gt;
  UWORD		 ln_Width;&lt;br /&gt;
  UWORD		 ln_Height;&lt;br /&gt;
  UWORD		 ln_Flags;&lt;br /&gt;
  BYTE		 ln_FgPen;&lt;br /&gt;
  BYTE		 ln_BgPen;&lt;br /&gt;
  ULONG		 ln_Style;&lt;br /&gt;
  APTR		 ln_Data;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The Line structure fields are as follows:&lt;br /&gt;
&lt;br /&gt;
;ln_Link&lt;br /&gt;
: MinNode used to link to the line list.&lt;br /&gt;
&lt;br /&gt;
; ln_Text&lt;br /&gt;
: Pointer to the text for this line segment.&lt;br /&gt;
&lt;br /&gt;
; ln_TextLen&lt;br /&gt;
: Number of bytes of text in this line segment.&lt;br /&gt;
&lt;br /&gt;
; ln_XOffset&lt;br /&gt;
: Left pixel offset from the left edge of the object for this line segment.&lt;br /&gt;
&lt;br /&gt;
; ln_YOffset&lt;br /&gt;
: Top pixel offset from the top edge of the object for this line segment.&lt;br /&gt;
&lt;br /&gt;
; ln_Width&lt;br /&gt;
: Width of the line segment in pixels.&lt;br /&gt;
&lt;br /&gt;
; ln_Height&lt;br /&gt;
: Height of the line segment in pixels.&lt;br /&gt;
&lt;br /&gt;
; ln_Flags&lt;br /&gt;
: Control flags for this line segment.&lt;br /&gt;
:: LNF_LF -- Used to indicate that this segment is the end of a line.&lt;br /&gt;
&lt;br /&gt;
; ln_FgPen&lt;br /&gt;
: Pen to use for the foreground (the text color) for this line segment.&lt;br /&gt;
&lt;br /&gt;
; ln_BgPen&lt;br /&gt;
: Pen to use for the background color for this line segment.&lt;br /&gt;
&lt;br /&gt;
; ln_Style&lt;br /&gt;
: Text attribute soft style to use for this line segment.&lt;br /&gt;
&lt;br /&gt;
As each Line segment is allocated it must be added to the Line list.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct List *linelist;&lt;br /&gt;
struct Line *line;&lt;br /&gt;
&lt;br /&gt;
/* Get a pointer to the line list */&lt;br /&gt;
if (IDataTypes-&amp;gt;GetDTAttrs (o, TDTA_LineList, (uint32) &amp;amp;linelist, TAG_END) &amp;amp;&amp;amp; linelist)&lt;br /&gt;
{&lt;br /&gt;
  /* Create a Line segment */&lt;br /&gt;
  if (line = AllocVecTags(sizeof (struct Line), AVT_ClearWithValue, 0, TAG_END))&lt;br /&gt;
  {&lt;br /&gt;
    /* Add it to the list */&lt;br /&gt;
    IExec-&amp;gt;AddTail (linelist, (struct Node *)&amp;amp;line-&amp;gt;ln_Link);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Currently, this is the hardest class to subclass, due to the number of methods that must be implemented. Following is the shell for a dispatcher and the layout method for a text subclass.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct localData&lt;br /&gt;
{&lt;br /&gt;
  VOID  *lod_Pool;&lt;br /&gt;
  uint32 lod_Flags;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
uint32 Dispatch (Class * cl, Object * o, Msg msg)&lt;br /&gt;
{&lt;br /&gt;
    struct ClassBase *cb = (struct ClassBase *) cl-&amp;gt;cl_UserData;&lt;br /&gt;
    struct localData *lod;&lt;br /&gt;
    struct List *linelist;&lt;br /&gt;
    uint32G retval = 0;&lt;br /&gt;
&lt;br /&gt;
    switch (msg-&amp;gt;MethodID)&lt;br /&gt;
    {&lt;br /&gt;
        case OM_NEW:&lt;br /&gt;
            if (retval = IIntuition-&amp;gt;IDoSuperMethodA (cl, o, msg))&lt;br /&gt;
            {&lt;br /&gt;
                uint32 len, estlines, poolsize;&lt;br /&gt;
                BOOL success = FALSE;&lt;br /&gt;
                STRPTR buffer;&lt;br /&gt;
&lt;br /&gt;
                /* Get a pointer to the object data */&lt;br /&gt;
                lod = INST_DATA (cl, (Object *) retval);&lt;br /&gt;
&lt;br /&gt;
                /* Get the attributes that we need to determine memory pool size */&lt;br /&gt;
                IDataTypes-&amp;gt;GetDTAttrs ((Object *) retval,&lt;br /&gt;
                             TDTA_Buffer,    &amp;amp;buffer,&lt;br /&gt;
                             TDTA_BufferLen, &amp;amp;len,&lt;br /&gt;
                             TAG_END);&lt;br /&gt;
&lt;br /&gt;
                 /* Make sure we have a text buffer */&lt;br /&gt;
                 if (buffer &amp;amp;&amp;amp; len)&lt;br /&gt;
                 {&lt;br /&gt;
                     /* Estimate the pool size that we will need */&lt;br /&gt;
                     estlines = (len / 80) + 1;&lt;br /&gt;
                     estlines = (estlines &amp;gt; 200) ? 200 : estlines;&lt;br /&gt;
                     poolsize = sizeof (struct Line) * estlines;&lt;br /&gt;
&lt;br /&gt;
                     /* Create a memory pool for the line list */&lt;br /&gt;
                     lod-&amp;gt;lod_Pool = IExec-&amp;gt;AllocSysObjectTags(ASOT_MEMPOOL,&lt;br /&gt;
                         ASOPOOL_MFlags, MEMF_SHARED | MEMF_CLEAR,&lt;br /&gt;
                         ASOPOOL_Puddle, poolsize,&lt;br /&gt;
                         ASOPOOL_Threshold, poolsize,&lt;br /&gt;
                         TAG_END);&lt;br /&gt;
                     if (lod-&amp;gt;lod_Pool != NULL)&lt;br /&gt;
                         success = TRUE;&lt;br /&gt;
                     else&lt;br /&gt;
                         IDOS-&amp;gt;SetIoErr (ERROR_NO_FREE_STORE);&lt;br /&gt;
                 }&lt;br /&gt;
                 else&lt;br /&gt;
                 {&lt;br /&gt;
                     /* Indicate that something was missing that we needed */&lt;br /&gt;
                     IDOS-&amp;gt;SetIoErr (ERROR_REQUIRED_ARG_MISSING);&lt;br /&gt;
                 }&lt;br /&gt;
&lt;br /&gt;
                 if (!success)&lt;br /&gt;
                 {&lt;br /&gt;
                     IIntuition-&amp;gt;ICoerceMethod (cl, (Object *) retval, OM_DISPOSE);&lt;br /&gt;
                     retval = NULL;&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
             break;&lt;br /&gt;
&lt;br /&gt;
         case OM_UPDATE:&lt;br /&gt;
         case OM_SET:&lt;br /&gt;
             /* Pass the attributes to the text class and force a refresh if we need it */&lt;br /&gt;
             if ((retval = IIntuition-&amp;gt;IDoSuperMethodA (cl, o, msg)) &amp;amp;&amp;amp; (OCLASS (o) == cl))&lt;br /&gt;
             {&lt;br /&gt;
                 struct RastPort *rp;&lt;br /&gt;
&lt;br /&gt;
                 /* Get a pointer to the rastport */&lt;br /&gt;
                 if (rp = IGraphics-&amp;gt;ObtainGIRPort (((struct opSet *) msg)-&amp;gt;ops_GInfo))&lt;br /&gt;
                 {&lt;br /&gt;
                     IIntuition-&amp;gt;DoRender(o, ((struct opSet *) msg)-&amp;gt;ops_GInfo, GREDRAW_UPDATE);&lt;br /&gt;
&lt;br /&gt;
                     /* Release the temporary rastport */&lt;br /&gt;
                     IGraphics-&amp;gt;ReleaseGIRPort (rp);&lt;br /&gt;
                 }&lt;br /&gt;
                 retval = 0;&lt;br /&gt;
             }&lt;br /&gt;
             break;&lt;br /&gt;
&lt;br /&gt;
         case GM_LAYOUT:&lt;br /&gt;
             /* Tell everyone that we are busy doing things */&lt;br /&gt;
             notifyAttrChanges (o, ((struct gpLayout *) msg)-&amp;gt;gpl_GInfo, NULL,&lt;br /&gt;
                                GA_ID, G(o)-&amp;gt;GadgetID,&lt;br /&gt;
                                DTA_Busy,  TRUE,&lt;br /&gt;
                                TAG_END);&lt;br /&gt;
&lt;br /&gt;
             /* Let the superclass partake */&lt;br /&gt;
             retval = (uint32) IIntuition-&amp;gt;IDoSuperMethodA (cl, o, msg);&lt;br /&gt;
&lt;br /&gt;
             /* We need to do this one asynchronously */&lt;br /&gt;
             retval += IDataTypes-&amp;gt;DoAsyncLayout (o, (struct gpLayout *) msg);&lt;br /&gt;
             break;&lt;br /&gt;
&lt;br /&gt;
         case DTM_PROCLAYOUT:&lt;br /&gt;
             /* Tell everyone that we are busy doing things */&lt;br /&gt;
             notifyAttrChanges (o, ((struct gpLayout *) msg)-&amp;gt;gpl_GInfo, NULL,&lt;br /&gt;
                                GA_ID, G(o)-&amp;gt;GadgetID,&lt;br /&gt;
                                DTA_Busy,  TRUE,&lt;br /&gt;
                                TAG_END);&lt;br /&gt;
&lt;br /&gt;
             /* Let the superclass partake and then fall through to our layout method */&lt;br /&gt;
             retval = (uint32) IDataTypes-&amp;gt;DoSuperMethodA (cl, o, msg);&lt;br /&gt;
&lt;br /&gt;
         case DTM_ASYNCLAYOUT:&lt;br /&gt;
             /* Layout the text */&lt;br /&gt;
             retval = layoutMethod (cb, cl, o, (struct gpLayout *) msg);&lt;br /&gt;
             break;&lt;br /&gt;
&lt;br /&gt;
         case OM_DISPOSE:&lt;br /&gt;
             /* Get a pointer to our object data */&lt;br /&gt;
             lod = INST_DATA (cl, o);&lt;br /&gt;
&lt;br /&gt;
             /* Don&#039;t let the super class free the line list */&lt;br /&gt;
             if (IIntuition-&amp;gt;GetDTAttrs (o, TDTA_LineList, &amp;amp;linelist, TAG_END) &amp;amp;&amp;amp; linelist)&lt;br /&gt;
                 IExec-&amp;gt;NewList (linelist);&lt;br /&gt;
&lt;br /&gt;
             /* Delete the line pool */&lt;br /&gt;
             IExec-&amp;gt;FreeSysObject(ASOT_MEMPOOL, lod-&amp;gt;lod_Pool);&lt;br /&gt;
&lt;br /&gt;
         /* Let the superclass handle everything else */&lt;br /&gt;
         default:&lt;br /&gt;
             retval = (uint32) IIntuition-&amp;gt;DoSuperMethodA (cl, o, msg);&lt;br /&gt;
             break;&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     return (retval);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 uint32 layoutMethod (struct ClassBase *cb, Class * cl, Object * o, struct gpLayout * gpl)&lt;br /&gt;
 {&lt;br /&gt;
     struct DTSpecialInfo *si = (struct DTSpecialInfo *) G (o)-&amp;gt;SpecialInfo;&lt;br /&gt;
     struct localData *lod = INST_DATA (cl, o);&lt;br /&gt;
     uint32 visible = 0, total = 0;&lt;br /&gt;
     struct RastPort trp;&lt;br /&gt;
     uint32 hunit = 1;&lt;br /&gt;
     uint32 bsig = 0;&lt;br /&gt;
&lt;br /&gt;
     /* Switches */&lt;br /&gt;
     BOOL linefeed = FALSE;&lt;br /&gt;
     BOOL newseg = FALSE;&lt;br /&gt;
     BOOL abort = FALSE;&lt;br /&gt;
&lt;br /&gt;
     /* Attributes obtained from superclass */&lt;br /&gt;
     struct TextAttr *tattr;&lt;br /&gt;
     struct TextFont *font;&lt;br /&gt;
     struct List *linelist;&lt;br /&gt;
     struct IBox *domain;&lt;br /&gt;
     uint32 wrap = FALSE;&lt;br /&gt;
     uint32 bufferlen;&lt;br /&gt;
     STRPTR buffer;&lt;br /&gt;
     STRPTR title;&lt;br /&gt;
&lt;br /&gt;
     /* Line information */&lt;br /&gt;
     uint32 num, offset, swidth;&lt;br /&gt;
     uint32 anchor, newanchor;&lt;br /&gt;
     uint32 style = FS_NORMAL;&lt;br /&gt;
     struct Line *line;&lt;br /&gt;
     uint32 yoffset = 0;&lt;br /&gt;
     uint8 fgpen = 1;&lt;br /&gt;
     uint8 bgpen = 0;&lt;br /&gt;
     uint32 tabspace;&lt;br /&gt;
     uint32 numtabs;&lt;br /&gt;
     uint32 i, j;&lt;br /&gt;
&lt;br /&gt;
     uint32 nomwidth, nomheight;&lt;br /&gt;
&lt;br /&gt;
     /* Get all the attributes that we are going to need for a successful layout */&lt;br /&gt;
     if (IDataTypes-&amp;gt;GetDTAttrs (o,&lt;br /&gt;
                          DTA_TextAttr,  &amp;amp;tattr,&lt;br /&gt;
                          DTA_TextFont,  &amp;amp;font,&lt;br /&gt;
                          DTA_Domain,    &amp;amp;domain,&lt;br /&gt;
                          DTA_ObjName,   &amp;amp;title,&lt;br /&gt;
                          TDTA_Buffer,   &amp;amp;buffer,&lt;br /&gt;
                          TDTA_BufferLen,&amp;amp;bufferlen,&lt;br /&gt;
                          TDTA_LineList, &amp;amp;linelist,&lt;br /&gt;
                          TDTA_WordWrap, &amp;amp;wrap,&lt;br /&gt;
                          TAG_END) == 8)&lt;br /&gt;
     {&lt;br /&gt;
         /* Lock the global object data so that nobody else can manipulate it */&lt;br /&gt;
         IExec-&amp;gt;ObtainSemaphore (&amp;amp;(si-&amp;gt;si_Lock));&lt;br /&gt;
&lt;br /&gt;
         /* Make sure we have a buffer */&lt;br /&gt;
         if (buffer)&lt;br /&gt;
         {&lt;br /&gt;
             /* Initialize the temporary RastPort */&lt;br /&gt;
             IGraphics-&amp;gt;InitRastPort (&amp;amp;trp);&lt;br /&gt;
             IGraphics-&amp;gt;SetFont (&amp;amp;trp, font);&lt;br /&gt;
&lt;br /&gt;
             /* Calculate the nominal size */&lt;br /&gt;
             nomheight = (ULONG) (24 * font-&amp;gt;tf_YSize);&lt;br /&gt;
             nomwidth  = (ULONG) (80 * font-&amp;gt;tf_XSize);&lt;br /&gt;
&lt;br /&gt;
             /* Calculate the tab space */&lt;br /&gt;
             tabspace = font-&amp;gt;tf_XSize * 8;&lt;br /&gt;
&lt;br /&gt;
             /* We only need to perform layout if we are doing word wrap, or this&lt;br /&gt;
              * is the initial layout call */&lt;br /&gt;
             if (wrap || gpl-&amp;gt;gpl_Initial)&lt;br /&gt;
             {&lt;br /&gt;
                 /* Delete the old line list */&lt;br /&gt;
                 while (line = (struct Line *) IExec-&amp;gt;RemHead (linelist))&lt;br /&gt;
                     IExec-&amp;gt;FreePooled (lod-&amp;gt;lod_Pool, line, sizeof (struct Line));&lt;br /&gt;
&lt;br /&gt;
                 /* Step through the text buffer */&lt;br /&gt;
                 for (i = offset = num = numtabs = 0;&lt;br /&gt;
                      (i &amp;lt;= bufferlen) &amp;amp;&amp;amp; (bsig == 0) &amp;amp;&amp;amp; !abort;&lt;br /&gt;
                      i++)&lt;br /&gt;
                 {&lt;br /&gt;
                     /* Check for end of line */&lt;br /&gt;
                     if (buffer[i]==13 &amp;amp;&amp;amp; buffer[i+1]==10)&lt;br /&gt;
                     {&lt;br /&gt;
                         newseg = linefeed = TRUE;&lt;br /&gt;
                         newanchor = i + 2;&lt;br /&gt;
                         i++;&lt;br /&gt;
                     }&lt;br /&gt;
                     /* Check for end of page */&lt;br /&gt;
                     else if (buffer[i] == 12)&lt;br /&gt;
                     {&lt;br /&gt;
                         newseg = linefeed = TRUE;&lt;br /&gt;
                         newanchor = i + 1;&lt;br /&gt;
                     }&lt;br /&gt;
                     /* Check for tab */&lt;br /&gt;
                     else if (buffer[i] == 9)&lt;br /&gt;
                     {&lt;br /&gt;
                         /* See if we need to terminate a line segment */&lt;br /&gt;
                         if ((numtabs == 0) &amp;amp;&amp;amp; num)&lt;br /&gt;
                             newseg = TRUE;&lt;br /&gt;
                         numtabs++;&lt;br /&gt;
                     }&lt;br /&gt;
                     else&lt;br /&gt;
                     {&lt;br /&gt;
                         /* See if we have any TABs that we need to finish out */&lt;br /&gt;
                         if (numtabs)&lt;br /&gt;
                         {&lt;br /&gt;
                             offset += (((offset / tabspace) + 1) * tabspace) - offset;&lt;br /&gt;
                             num = numtabs = 0;&lt;br /&gt;
                             anchor = i;&lt;br /&gt;
                         }&lt;br /&gt;
&lt;br /&gt;
                         /* Compute the width of the line. */&lt;br /&gt;
                         swidth = IGraphics-&amp;gt;TextLength (&amp;amp;trp, &amp;amp;buffer[anchor], num+1);&lt;br /&gt;
                         if (offset + swidth &amp;gt; domain-&amp;gt;Width)&lt;br /&gt;
                         {&lt;br /&gt;
                             /* Search for a whitespace character */&lt;br /&gt;
                             for (j = i; (j &amp;gt;= anchor) &amp;amp;&amp;amp; !newseg; j--)&lt;br /&gt;
                             {&lt;br /&gt;
                                 if (buffer[j] == &#039; &#039;)&lt;br /&gt;
                                 {&lt;br /&gt;
                                     num -= (i - j);&lt;br /&gt;
                                     newseg = TRUE;&lt;br /&gt;
                                     i = j + 1;&lt;br /&gt;
                                 }&lt;br /&gt;
                             }&lt;br /&gt;
&lt;br /&gt;
                             newseg = linefeed = TRUE;&lt;br /&gt;
                             newanchor = i;&lt;br /&gt;
                             i--;&lt;br /&gt;
                         }&lt;br /&gt;
                         else&lt;br /&gt;
                         {&lt;br /&gt;
                             num++;&lt;br /&gt;
                         }&lt;br /&gt;
                     }&lt;br /&gt;
&lt;br /&gt;
                     /* Time for a new text segment yet? */&lt;br /&gt;
                     if (newseg)&lt;br /&gt;
                     {&lt;br /&gt;
                         /* Allocate a new line segment from our memory pool */&lt;br /&gt;
                         if (line = IExec-&amp;gt;AllocPooled (lod-&amp;gt;lod_Pool, sizeof (struct Line)))&lt;br /&gt;
                         {&lt;br /&gt;
                             swidth = IGraphics-&amp;gt;TextLength (&amp;amp;trp, &amp;amp;buffer[anchor], num);&lt;br /&gt;
                             line-&amp;gt;ln_Text    = &amp;amp;buffer[anchor];&lt;br /&gt;
                             line-&amp;gt;ln_TextLen = num;&lt;br /&gt;
                             line-&amp;gt;ln_XOffset = offset;&lt;br /&gt;
                             line-&amp;gt;ln_YOffset = yoffset + font-&amp;gt;tf_Baseline;&lt;br /&gt;
                             line-&amp;gt;ln_Width   = swidth;&lt;br /&gt;
                             line-&amp;gt;ln_Height  = font-&amp;gt;tf_YSize;&lt;br /&gt;
                             line-&amp;gt;ln_Flags   = (linefeed) ? LNF_LF : NULL;&lt;br /&gt;
                             line-&amp;gt;ln_FgPen   = fgpen;&lt;br /&gt;
                             line-&amp;gt;ln_BgPen   = bgpen;&lt;br /&gt;
                             line-&amp;gt;ln_Style   = style;&lt;br /&gt;
                             line-&amp;gt;ln_Data    = NULL;&lt;br /&gt;
&lt;br /&gt;
                             /* Add the line to the list */&lt;br /&gt;
                             IExec-&amp;gt;AddTail (linelist, (struct Node *) line);&lt;br /&gt;
&lt;br /&gt;
                             /* Increment the line count */&lt;br /&gt;
                             if (linefeed)&lt;br /&gt;
                             {&lt;br /&gt;
                                 yoffset += font-&amp;gt;tf_YSize;&lt;br /&gt;
                                 offset = 0;&lt;br /&gt;
                                 total++;&lt;br /&gt;
                             }&lt;br /&gt;
                             else&lt;br /&gt;
                             {&lt;br /&gt;
                                 /* Increment the offset */&lt;br /&gt;
                                 offset += swidth;&lt;br /&gt;
                             }&lt;br /&gt;
                         }&lt;br /&gt;
                         else&lt;br /&gt;
                         {&lt;br /&gt;
                             abort = TRUE;&lt;br /&gt;
                         }&lt;br /&gt;
&lt;br /&gt;
                         /* Clear the variables */&lt;br /&gt;
                         newseg = linefeed = FALSE;&lt;br /&gt;
                         anchor = newanchor;&lt;br /&gt;
                         num = 0;&lt;br /&gt;
&lt;br /&gt;
                         /* Check to see if layout has been aborted */&lt;br /&gt;
                         bsig = IDOS-&amp;gt;CheckSignal (SIGBREAKF_CTRL_C);&lt;br /&gt;
                     }&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
             else&lt;br /&gt;
             {&lt;br /&gt;
                 /* No layout to perform */&lt;br /&gt;
                 total = si-&amp;gt;si_TotVert;&lt;br /&gt;
             }&lt;br /&gt;
         }&lt;br /&gt;
&lt;br /&gt;
         /* Compute the lines and columns type information */&lt;br /&gt;
         si-&amp;gt;si_VertUnit  = font-&amp;gt;tf_YSize;&lt;br /&gt;
         si-&amp;gt;si_VisVert   = visible = domain-&amp;gt;Height / si-&amp;gt;si_VertUnit;&lt;br /&gt;
         si-&amp;gt;si_TotVert   = total;&lt;br /&gt;
&lt;br /&gt;
         si-&amp;gt;si_HorizUnit = hunit = 1;&lt;br /&gt;
         si-&amp;gt;si_VisHoriz  = (int32) domain-&amp;gt;Width / hunit;&lt;br /&gt;
         si-&amp;gt;si_TotHoriz  = domain-&amp;gt;Width;&lt;br /&gt;
&lt;br /&gt;
         /* Release the global data lock */&lt;br /&gt;
         IExec-&amp;gt;ReleaseSemaphore (&amp;amp;si-&amp;gt;si_Lock);&lt;br /&gt;
&lt;br /&gt;
         /* Were we aborted? */&lt;br /&gt;
         if (bsig == 0)&lt;br /&gt;
         {&lt;br /&gt;
             /* Not aborted, so tell the world of our newest attributes */&lt;br /&gt;
             notifyAttrChanges (o, gpl-&amp;gt;gpl_GInfo, NULL,&lt;br /&gt;
                                GA_ID,                   G(o)-&amp;gt;GadgetID,&lt;br /&gt;
&lt;br /&gt;
                                DTA_VisibleVert,         visible,&lt;br /&gt;
                                DTA_TotalVert,           total,&lt;br /&gt;
                                DTA_NominalVert,         nomheight,&lt;br /&gt;
                                DTA_VertUnit,            font-&amp;gt;tf_YSize,&lt;br /&gt;
&lt;br /&gt;
                                DTA_VisibleHoriz,        (uint32) (domain-&amp;gt;Width / hunit),&lt;br /&gt;
                                DTA_TotalHoriz,          domain-&amp;gt;Width,&lt;br /&gt;
                                DTA_NominalHoriz,        nomwidth,&lt;br /&gt;
                                DTA_HorizUnit,           hunit,&lt;br /&gt;
&lt;br /&gt;
                                DTA_Title,               title,&lt;br /&gt;
                                DTA_Busy,                FALSE,&lt;br /&gt;
                                DTA_Sync,                TRUE,&lt;br /&gt;
                                TAG_END);&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
     &lt;br /&gt;
     return total;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Writing a Superclass =&lt;br /&gt;
&lt;br /&gt;
(relevant text to be provided)&lt;br /&gt;
&lt;br /&gt;
= Defining a DataType Descriptor =&lt;br /&gt;
&lt;br /&gt;
DataTypes uses a simple descriptor to determine what type of data a file contains and what class, if any, is used to handle that data.&lt;br /&gt;
&lt;br /&gt;
The DTDesc utility is used to define a DataType descriptor. The following steps describe how to use this utility to define a descriptor.&lt;br /&gt;
&lt;br /&gt;
1. Load several sample files of the type being defined. This can be done by dropping their icons into the DTDesc window or by using the &amp;quot;Extras/Load Samples...&amp;quot; menu item.&lt;br /&gt;
&lt;br /&gt;
2. The view area in the bottom right side of the DTDesc window will show the first 64 characters of the files. This area is used to define the Mask. The characters that don&#039;t match will be blotted out and only the similar characters will be shown. If more characters are shown as similar than really are, then they can easily be blotted out by rubbing over them.&lt;br /&gt;
&lt;br /&gt;
3. DataTypes can be broken out into several different categories. Use the Group menu to select the category that the DataType descriptor belongs in.&lt;br /&gt;
&lt;br /&gt;
4. The remaining fields must be filled out. Following is a table describing the fields and the information they require.&lt;br /&gt;
&lt;br /&gt;
:{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Name !! Description&lt;br /&gt;
|-&lt;br /&gt;
| File Type || User description of the DataType.&lt;br /&gt;
|-&lt;br /&gt;
| Base Name || The base name of the DataType. The class library name is derived from this.&lt;br /&gt;
|-&lt;br /&gt;
| Name Pattern || The name of the file can be used to indicate the DataType. AmigaDOS wildcards can be used to specify the file name.&lt;br /&gt;
|-&lt;br /&gt;
| Function || A function can be used to further define a data type. This function must be a stand-alone executable that uses the DataType Descriptor Function Interface.&lt;br /&gt;
|-&lt;br /&gt;
| Case Sensitive? || The Mask can be either case sensitive or not.&lt;br /&gt;
|-&lt;br /&gt;
| Priority || Descriptors are sorted by Type, Function, Name Pattern and Mask. The priority field allows a DataType descriptor to be assigned a different priority than a similar DataType descriptor.&lt;br /&gt;
|-&lt;br /&gt;
| Type || This is a read-only field and is used to indicate what basic type a DataType is. Types include IFF, Binary and ASCII.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
5. Once a DataType descriptor has been defined, it must be saved. Select the &amp;quot;Project/Save As...&amp;quot; menu item for the file requester used to save a DataType descriptor. The default name for a DataType descriptor is the text entered into File Type field.&lt;br /&gt;
&lt;br /&gt;
6. In order for a new DataType descriptor to be loaded, the datatypes.library must be flushed from the system. This can either be done with the [[SDK_Developer_Tools#Expunge|Expunge]] command included in the SDK. Another way that the new DataType descriptor can be loaded is by using the AddDataTypes command with the REFRESH option.&lt;br /&gt;
&lt;br /&gt;
== DataType Descriptor Function Interface ==&lt;br /&gt;
&lt;br /&gt;
Sometimes the fields within the DTDesc utility are not enough to define a DataType descriptor. In this case it is necessary to use a Function to&lt;br /&gt;
further narrow down a DataType.&lt;br /&gt;
&lt;br /&gt;
A Function is a stand-alone executable that expects the following arguments.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
BOOL retval = Function(struct DTHookContext *dthc);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The function must return TRUE if the data matches, FALSE if it doesn&#039;t.&lt;br /&gt;
&lt;br /&gt;
The DTHookContext structure contains the fields that are necessary for narrowing down the DataType. Following is a listing of the DTHookContext&lt;br /&gt;
structure.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct DTHookContext&lt;br /&gt;
{&lt;br /&gt;
    struct Library        *dthc_SysBase;&lt;br /&gt;
    struct Library        *dthc_DOSBase;&lt;br /&gt;
    struct Library        *dthc_IFFParseBase;&lt;br /&gt;
    struct Library        *dthc_UtilityBase;&lt;br /&gt;
&lt;br /&gt;
    /* File context */&lt;br /&gt;
    BPTR                   dthc_Lock;          /* Lock on the file */&lt;br /&gt;
    struct FileInfoBlock  *dthc_FIB;           /* Pointer to a FileInfoBlock */&lt;br /&gt;
    BPTR                   dthc_FileHandle;    /* Pointer to the file handle (may be NULL) */&lt;br /&gt;
    struct IFFHandle      *dthc_IFF;           /* Pointer to an IFFHandle (may be NULL) */&lt;br /&gt;
    STRPTR                 dthc_Buffer;        /* Buffer */&lt;br /&gt;
    ULONG                  dthc_BufferLength;  /* Length of the buffer */&lt;br /&gt;
&lt;br /&gt;
    ULONG                  dthc_Length;       /* size of this structure */&lt;br /&gt;
    struct ExecIFace *     dthc_IExec;&lt;br /&gt;
    struct DOSIFace  *     dthc_IDOS;&lt;br /&gt;
    struct IFFParseIFace * dthc_IIFFParse;&lt;br /&gt;
    struct UtilityIFace *  dthc_IUtility;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The DTHookContext structure fields are as follows:&lt;br /&gt;
&lt;br /&gt;
; dthc_SysBase&lt;br /&gt;
; dthc_DOSBase&lt;br /&gt;
; dthc_IFFParseBase&lt;br /&gt;
; dthc_UtilityBase&lt;br /&gt;
: These are library bases that your function can utilize. It will need to open any other libraries that it needs.&lt;br /&gt;
&lt;br /&gt;
; dthc_Lock&lt;br /&gt;
: If the source data is a DOS file, then this is a lock on the file.&lt;br /&gt;
&lt;br /&gt;
; dthc_FIB&lt;br /&gt;
: If the source data is a DOS file, then this is a filled in FileInfoBlock for the file.&lt;br /&gt;
&lt;br /&gt;
; dthc_FileHandle&lt;br /&gt;
: If the source data is a DOS file, then this is the file handle for the file otherwise the handle will be NULL. The file is guaranteed to be at the beginning.&lt;br /&gt;
&lt;br /&gt;
; dthc_IFF&lt;br /&gt;
: If the source data is IFF, then this is the IFFHandle for accessing the data, otherwise the handle will be NULL. The position is guaranteed to be at the beginning of the data. The DOS file fields must not be accessed if the data is IFF.&lt;br /&gt;
&lt;br /&gt;
; dthc_Buffer&lt;br /&gt;
: This buffer contains the first dthc_BufferLength bytes of data.&lt;br /&gt;
&lt;br /&gt;
; dthc_BufferLength&lt;br /&gt;
: Indicates the number of bytes in dthc_Buffer, up to 64.&lt;br /&gt;
&lt;br /&gt;
; dthc_Length&lt;br /&gt;
: Size in bytes of struct DTHookContext&lt;br /&gt;
&lt;br /&gt;
; dthc_IExec&lt;br /&gt;
; dthc_IDOS&lt;br /&gt;
; dthc_IIFFParse&lt;br /&gt;
; dthc_IUtility&lt;br /&gt;
: These are interface pointers that your function can utilize.&lt;br /&gt;
&lt;br /&gt;
The following example shows how to write a simple DataTypes Descriptor Function.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
/* This example must not be linked with any startup code so that&lt;br /&gt;
 * DTHook is the entry point for the executable.&lt;br /&gt;
 *&lt;br /&gt;
 */&lt;br /&gt;
#include &amp;lt;exec/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;dos/dos.h&amp;gt;&lt;br /&gt;
#include &amp;lt;dos/dosextens.h&amp;gt;&lt;br /&gt;
#include &amp;lt;datatypes/datatypes.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;proto/exec.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/dos.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/utility.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
BOOL DTHook (struct DTHookContext * dthc)&lt;br /&gt;
{&lt;br /&gt;
    BOOL retval = FALSE;&lt;br /&gt;
    uint32 i;&lt;br /&gt;
    uint8 ch;&lt;br /&gt;
&lt;br /&gt;
    /* Make sure we have a buffer */&lt;br /&gt;
    if (dthc-&amp;gt;dthc_Buffer)&lt;br /&gt;
    {&lt;br /&gt;
        for (i = 0; (i &amp;lt; dthc-&amp;gt;dthc_BufferLength) &amp;amp;&amp;amp; !retval; i++)&lt;br /&gt;
        {&lt;br /&gt;
            ch = dthc-&amp;gt;dthc_Buffer[i];&lt;br /&gt;
&lt;br /&gt;
            /* Look at the data... */&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return retval;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The next example shows how to write a DataTypes Descriptor that looks into an IFF file for needed chunk information.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
/* This example must not be linked with any startup code&lt;br /&gt;
 * so that DTHook is the entry point for the executable.&lt;br /&gt;
 */&lt;br /&gt;
#include &amp;lt;exec/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;dos/dos.h&amp;gt;&lt;br /&gt;
#include &amp;lt;dos/dosextens.h&amp;gt;&lt;br /&gt;
#include &amp;lt;datatypes/datatypes.h&amp;gt;&lt;br /&gt;
#include &amp;lt;datatypes/pictureclass.h&amp;gt;&lt;br /&gt;
#include &amp;lt;libraries/iffparse.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;proto/exec.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/dos.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/iffparse.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/utility.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define BMH_SIZE (sizeof (struct BitMapHeader))&lt;br /&gt;
&lt;br /&gt;
BOOL DTHook(struct DTHookContext * dthc)&lt;br /&gt;
{&lt;br /&gt;
  struct BitMapHeader bmh;&lt;br /&gt;
  struct ContextNode *cn;&lt;br /&gt;
  struct IFFHandle *iff;&lt;br /&gt;
  BOOL retval = FALSE;&lt;br /&gt;
&lt;br /&gt;
  /* Make sure that this is an IFF data type */&lt;br /&gt;
  if (iff = dthc-&amp;gt;dthc_IFF)&lt;br /&gt;
&lt;br /&gt;
    /* Stop on the BitMapHeader (type, id) */&lt;br /&gt;
    if (dthc-&amp;gt;dthc_IIFFParse-&amp;gt;StopChunk (iff, ID_ILBM, ID_BMHD) == 0)&lt;br /&gt;
&lt;br /&gt;
      /* Scan through the IFF handle */&lt;br /&gt;
      if (dthc-&amp;gt;dthc_IIFFParse-&amp;gt;ParseIFF (iff, IFFPARSE_SCAN) == 0L)&lt;br /&gt;
&lt;br /&gt;
        /* Make sure we have a current chunk */&lt;br /&gt;
        if (cn = dthc-&amp;gt;dthc_IIFFParse-&amp;gt;CurrentChunk (iff))&lt;br /&gt;
&lt;br /&gt;
          /* Make sure the current chunk is ILBM BMHD */&lt;br /&gt;
          if ((cn-&amp;gt;cn_Type == ID_ILBM) &amp;amp;&amp;amp; (cn-&amp;gt;cn_ID == ID_BMHD))&lt;br /&gt;
&lt;br /&gt;
            /* Read the chunk data */&lt;br /&gt;
            if (dthc-&amp;gt;dthc_IIFFParse-&amp;gt;ReadChunkBytes (iff, &amp;amp;bmh, BMH_SIZE) == BMH_SIZE)&lt;br /&gt;
&lt;br /&gt;
              /* See if the depth is set to 24 */&lt;br /&gt;
              if (bmh.bmh_Depth == 24)&lt;br /&gt;
                retval = TRUE;&lt;br /&gt;
&lt;br /&gt;
  return (retval);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Costel Mincea</name></author>
	</entry>
	<entry>
		<id>https://wiki.amigaos.net/w/index.php?title=Exec_Messages_and_Ports&amp;diff=12568</id>
		<title>Exec Messages and Ports</title>
		<link rel="alternate" type="text/html" href="https://wiki.amigaos.net/w/index.php?title=Exec_Messages_and_Ports&amp;diff=12568"/>
		<updated>2025-01-26T19:40:03Z</updated>

		<summary type="html">&lt;p&gt;Costel Mincea: Text replacement - &amp;quot;&amp;lt;syntaxhighlight&amp;gt;&amp;quot; to &amp;quot;&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Exec Messages and Ports ==&lt;br /&gt;
&lt;br /&gt;
For inter-process communication, Exec provides a consistent, high-performance mechanism of messages and ports. This mechanism is used to pass message structures of arbitrary sizes from task to task, interrupt to task, or task to software interrupt. In addition, messages are often used to coordinate operations between cooperating tasks. This section describes many of the details of using messages and ports that the casual Amiga programmer won&#039;t need. See [[Introduction_to_Exec|Introduction to Exec]] for a general introduction to using messages and ports.&lt;br /&gt;
&lt;br /&gt;
A &#039;&#039;message&#039;&#039; data structure has two parts: system linkage and message body. The system linkage is used by Exec to attach a given message to its destination. The message body contains the actual data of interest. The message body is any arbitrary data up to 64K bytes in size. The message body data can include pointers to other data blocks of any size.&lt;br /&gt;
&lt;br /&gt;
Messages are always sent to a predetermined destination &#039;&#039;port&#039;&#039;. At a port, incoming messages are queued in a first-in-first-out (FIFO) order. There are no system restrictions on the number of ports or the number of messages that may be queued to a port (other than the amount of available system memory).&lt;br /&gt;
&lt;br /&gt;
Messages are always queued by &#039;&#039;reference&#039;&#039;, i.e., by a pointer to the message. For performance reasons message copying is not performed. In essence, a message between two tasks is a temporary license for the receiving task to use a portion of the memory space of the sending task; that portion being the message itself. This means that if task A sends a message to task B, the message is still part of the task A context. Task A, however, should not access the message until it has been &#039;&#039;replied&#039;&#039;; that is, until task B has sent the message back, using the ReplyMsg() function. This technique of message exchange imposes important restrictions on message access.&lt;br /&gt;
&lt;br /&gt;
== Message Ports ==&lt;br /&gt;
&lt;br /&gt;
Message ports are rendezvous points at which messages are collected. A port may contain any number of outstanding messages from many different originators. When a message arrives at a port, the message is appended to the end of the list of messages for that port, and a pre-specified arrival action is invoked. This action may do nothing, or it may cause a predefined task signal or software interrupt (see [[Exec_Interrupts|Exec Interrupts]]).&lt;br /&gt;
&lt;br /&gt;
Like many Exec structures, ports may be given a symbolic name. Such names are particularly useful for tasks that must rendezvous with dynamically created ports. They are also useful for debugging purposes.&lt;br /&gt;
&lt;br /&gt;
A message port consists of a MsgPort structure as defined in the &amp;amp;lt;exec/ports.h&amp;amp;gt; and &amp;amp;lt;exec/ports.i&amp;amp;gt; include files. The C structure for a port is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct MsgPort {&lt;br /&gt;
    struct Node  mp_Node;&lt;br /&gt;
    UBYTE        mp_Flags;&lt;br /&gt;
    UBYTE        mp_SigBit;&lt;br /&gt;
    struct Task *mp_SigTask;&lt;br /&gt;
    struct List  mp_MsgList;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; mp_Node&lt;br /&gt;
: is a standard Node structure. This is useful for tasks that might want to rendezvous with a particular message port by name.&lt;br /&gt;
&lt;br /&gt;
; mp_FLags&lt;br /&gt;
: are used to indicate message arrival actions. See the explanation below.&lt;br /&gt;
&lt;br /&gt;
; mp_SigBit&lt;br /&gt;
: is the signal bit &#039;&#039;number&#039;&#039; when a port is used with the task signal arrival action.&lt;br /&gt;
&lt;br /&gt;
; mp_SigTask&lt;br /&gt;
: is a pointer to the task to be signaled. If a software interrupt arrival action is specified, this is a pointer to the interrupt structure.&lt;br /&gt;
&lt;br /&gt;
; mp_MsgList&lt;br /&gt;
: is the list header for all messages queued to this port. (See [[Exec_Lists_and_Queues|Exec Lists and Queues]]).&lt;br /&gt;
&lt;br /&gt;
The mp_Flags field contains a subfield indicated by the PF_ACTION mask. This sub-field specifies the message arrival action that occurs when a port receives a new message.&lt;br /&gt;
&lt;br /&gt;
The possibilities are as follows:&lt;br /&gt;
&lt;br /&gt;
; PA_SIGNAL&lt;br /&gt;
: This flag tells Exec to signal the mp_SigTask using signal number mp_SigBit on the arrival of a new message. Every time a message is put to the port another signal will occur regardless of how many messages have been queued to the port.&lt;br /&gt;
&lt;br /&gt;
; PA_SOFTINT&lt;br /&gt;
: This flag tells Exec to Cause() a software interrupt when a message arrives at the port. In this case, the mp_SigTask field must contain a pointer to a struct Interrupt rather than a Task pointer. The software interrupt will be Caused every time a message is received.&lt;br /&gt;
&lt;br /&gt;
; PA_IGNORE&lt;br /&gt;
: This flag tells Exec to perform no operation other than queuing the message. This action is often used to stop signaling or software interrupts without disturbing the contents of the mp_SigTask field.&lt;br /&gt;
&lt;br /&gt;
It is important to realize that a port&#039;s arrival action will occur for each new message queued, and that there is not a one-to-one correspondence between messages and signals. Task signals are only single-bit flags so there is no record of how many times a particular signal occurred. There may be many messages queued and only a single task signal; sometimes however there may be a signal, but no messages. All of this has certain implications when designing code that deals with these actions. Your code should not depend on receiving a signal for every message at your port. All of this is also true for software interrupts.&lt;br /&gt;
&lt;br /&gt;
=== Creating a Message Port ===&lt;br /&gt;
&lt;br /&gt;
To create a new message port use AllocSysObject() with an object type of ASOT_PORT. If you want to make the port &#039;&#039;public&#039;&#039;, you will need to use the ASOPORT_Name tag. Don&#039;t make a port public when it is not necessary for it to be so.&lt;br /&gt;
&lt;br /&gt;
Prior to V50 of the operating system, functions such as CreatePort() and CreateMsgPort() were often used. Some older applications may even have created their own static message ports by hand. Although all of the older methods still function for backwards compatibility, they should no longer be used.&lt;br /&gt;
&lt;br /&gt;
Using dynamic message ports with ASOT_PORT is the only way to ensure your applications will remain compatible and its message ports automatically freed by the system when required.&lt;br /&gt;
&lt;br /&gt;
=== Deleting a Message Port ===&lt;br /&gt;
&lt;br /&gt;
Before a message port is deleted, all outstanding messages from other tasks must be returned. This is done by getting and replying to all messages at the port until message queue is empty. Of course, there is no need to reply to messages owned by the current task (the task performing the port deletion). Public ports must be removed from the system properly before deallocation. If a signal was allocated for the message port, it must also be freed. FreeSysObject() handles all of this automatically.&lt;br /&gt;
&lt;br /&gt;
Prior to V50 of the operating system, message ports must be freed using the correct corresponding function such as DeletePort() or DeleteMsgPort(). The FreeSysObject() function must only be used on ports which were allocated with AllocSysObject().&lt;br /&gt;
&lt;br /&gt;
=== How to Rendezvous at a Message Port ===&lt;br /&gt;
&lt;br /&gt;
The FindPort() function provides a means of finding the address of a public port given its symbolic name. For example, FindPort(&amp;amp;quot;Griffin&amp;amp;quot;) will return either the address of the message port named &amp;quot;Griffin&amp;quot; or NULL indicating that no such public port exists. Since FindPort() does not do any arbitration over access to public ports, the usage of FindPort() must be protected with Forbid()/Permit(). Names should be unique to prevent collisions among multiple applications. It is a good idea to use your application name as a prefix for your port name. FindPort() does not arbitrate for access to the port list. The owner of a port might remove it at any time. For these reasons a Forbid()/Permit() pair is required for the use of FindPort(). The port address can no longer be regarded as being valid after Permit() unless your application knows that the port cannot go away (for example, if your application created the port).&lt;br /&gt;
&lt;br /&gt;
The following is an example of how to safely put a message to a specific port:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
#include &amp;lt;exec/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;exec/ports.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
BOOL SafePutToPort(struct Message *message, CONST_STRPTR portname)&lt;br /&gt;
{&lt;br /&gt;
    IExec-&amp;gt;Forbid();&lt;br /&gt;
&lt;br /&gt;
    struct MsgPort *port = IExec-&amp;gt;FindPort(portname);&lt;br /&gt;
    if (port != NULL)&lt;br /&gt;
        IExec-&amp;gt;PutMsg(port,message);&lt;br /&gt;
&lt;br /&gt;
    IExec-&amp;gt;Permit();&lt;br /&gt;
&lt;br /&gt;
    return(port ? TRUE : FALSE);      /* If FALSE, the port was not found */&lt;br /&gt;
&lt;br /&gt;
    /* Once we&#039;ve done a Permit(), the port might go away and leave us with&lt;br /&gt;
       an invalid port address. So we return just a BOOL to indicate whether&lt;br /&gt;
       the message has been sent or not. */&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Messages ==&lt;br /&gt;
&lt;br /&gt;
As mentioned earlier, a message contains both system header information and the actual message content. The system header is of the Message form defined in &amp;lt;exec/ports.h&amp;gt;. This structure is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct Message {&lt;br /&gt;
    struct Node     mn_Node;&lt;br /&gt;
    struct MsgPort *mn_ReplyPort;&lt;br /&gt;
    UWORD           mn_Length;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; mn_Node&lt;br /&gt;
: is a standard Node structure used for port linkage.&lt;br /&gt;
&lt;br /&gt;
; mn_ReplyPort&lt;br /&gt;
: is used to indicate a port to which this message will be returned when a reply is necessary.&lt;br /&gt;
&lt;br /&gt;
; mn_Length&lt;br /&gt;
: indicates the total length of the message, including the Message structure itself.&lt;br /&gt;
&lt;br /&gt;
This structure is always attached to the head of all messages. For example, if you want a message structure that contains the &#039;&#039;x&#039;&#039; and &#039;&#039;y&#039;&#039; coordinates of a point on the screen, you could define it as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct XYMessage {&lt;br /&gt;
    struct Message xy_Msg;&lt;br /&gt;
    UWORD          xy_X;&lt;br /&gt;
    UWORD          xy_Y;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For this structure, the mn_Length field should be set to sizeof(struct XYMessage).&lt;br /&gt;
&lt;br /&gt;
=== Creating a Message ===&lt;br /&gt;
&lt;br /&gt;
Messages are allocated using AllocSysObject() with an object type of ASOT_MESSAGE. The ASOMSG_ReplyPort tag is set to the reply port if desired. Some messages may be sent in one direction in which case the ASOMSG_ReplyPort tag is not used. The size of the message is indicated with ASOMSG_Length and includes the size of the payload.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct XYMessage xymsg = IExec-&amp;gt;AllocSysObjectTags(ASOT_MESSAGE,&lt;br /&gt;
  ASOMSG_Size, sizeof(struct XYMessage),&lt;br /&gt;
  ASOMSG_ReplyPort, replyPort,&lt;br /&gt;
  TAG_END);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Deleting a Message ===&lt;br /&gt;
&lt;br /&gt;
Messages are freed using FreeSysObject(). Programmers should be careful not to free a message which is still in use or queues in a message port.&lt;br /&gt;
&lt;br /&gt;
=== Putting a Message ===&lt;br /&gt;
&lt;br /&gt;
A message is delivered to a given destination port with the PutMsg() function. The message is queued to the port, and that port&#039;s arrival action is invoked. If the action specifies a task signal or a software interrupt, the originating task may temporarily lose the processor while the destination processes the message. If a reply to the message is required, the mn_ReplyPort field must be set up prior to the call to PutMsg().&lt;br /&gt;
&lt;br /&gt;
Here is a code fragment for putting a message to a public port. A complete example is at the end of the article.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
#include &amp;lt;exec/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;exec/memory.h&amp;gt;&lt;br /&gt;
#include &amp;lt;exec/ports.h&amp;gt;&lt;br /&gt;
#include &amp;lt;libraries/dos.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
BOOL SafePutToPort(struct Message *, CONST_STRPTR);&lt;br /&gt;
&lt;br /&gt;
struct XYMessage {&lt;br /&gt;
    struct Message xy_Msg;&lt;br /&gt;
    uint16         xy_X;&lt;br /&gt;
    uint16         xy_Y;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
    struct MsgPort *xyport, *xyreplyport;&lt;br /&gt;
    struct XYMessage *msg;&lt;br /&gt;
    BOOL   foundport;&lt;br /&gt;
&lt;br /&gt;
    /* Allocate the message we&#039;re going to send. */&lt;br /&gt;
    struct XYMessage *xymsg = IExec-&amp;gt;AllocSysObjectTags(ASOT_MESSAGE,&lt;br /&gt;
      ASOMSG_Size, sizeof(struct XYMessage),&lt;br /&gt;
      TAG_END);&lt;br /&gt;
&lt;br /&gt;
    if (xymsg != NULL)&lt;br /&gt;
    {&lt;br /&gt;
        /* The replyport we&#039;ll use to get response */&lt;br /&gt;
        if (xyreplyport = IExec-&amp;gt;AllocSysObject(ASOT_PORT, NULL)) {&lt;br /&gt;
&lt;br /&gt;
            xymsg-&amp;gt;xy_Msg.mn_ReplyPort = xyreplyport;&lt;br /&gt;
            xymsg-&amp;gt;xy_X = 10;&lt;br /&gt;
            xymsg-&amp;gt;xy_Y = 20;&lt;br /&gt;
&lt;br /&gt;
            /* Now try to send that message to a public port named &amp;quot;xyport&amp;quot;.&lt;br /&gt;
             * If foundport eq 0, the port isn&#039;t out there.&lt;br /&gt;
             */&lt;br /&gt;
            if (foundport = SafePutToPort((struct Message *)xymsg, &amp;quot;xyport&amp;quot;))&lt;br /&gt;
            {&lt;br /&gt;
&lt;br /&gt;
            . . .                /* Now let&#039;s wait till the someone responds... */&lt;br /&gt;
&lt;br /&gt;
            }&lt;br /&gt;
            else IDOS-&amp;gt;Printf(&amp;quot;Couldn&#039;t find &#039;xyport&#039;\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
            IExec-&amp;gt;FreeSysObject(ASOT_PORT, xyreplyport);&lt;br /&gt;
        else IDOS-&amp;gt;Printf(&amp;quot;Couldn&#039;t create message port\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        IExec-&amp;gt;FreeSysObject(ASOT_MESSAGE, xymsg);&lt;br /&gt;
    }&lt;br /&gt;
    else IDOS-&amp;gt;Printf(&amp;quot;Couldn&#039;t get memory for xymessage\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Waiting for a Message ===&lt;br /&gt;
&lt;br /&gt;
A task may go to sleep waiting for a message to arrive at one or more ports. This technique is widely used on the Amiga as a general form of event notification. For example, it is used extensively by tasks for I/O request completion.&lt;br /&gt;
&lt;br /&gt;
The MsgPort.mp_SigTask field contains the address of the task to be signaled and mp_SigBit contains a preallocated signal number (as described in [[Exec_Tasks|Exec Tasks]]).&lt;br /&gt;
&lt;br /&gt;
You can call the WaitPort() function to wait for a message to arrive at a port. This function will return the first message (it may not be the only) queued to a port. Note that your application must still call GetMsg() to remove the message from the port. If the port is empty, your task will go to sleep waiting for the first message. If the port is not empty, your task will not go to sleep. It is possible to receive a signal for a port without a message being present yet. The code processing the messages should be able to handle this. The following code illustrates WaitPort().&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct MsgPort *xyport = IExec-&amp;gt;AllocSysObjectTags(ASOT_PORT,&lt;br /&gt;
  ASOPORT_Name, &amp;quot;xyport&amp;quot;,&lt;br /&gt;
  TAG_END);&lt;br /&gt;
&lt;br /&gt;
if (xyport == NULL)&lt;br /&gt;
{&lt;br /&gt;
    IDOS-&amp;gt;Printf(&amp;quot;Couldn&#039;t create xyport\n&amp;quot;);&lt;br /&gt;
    return RETURN_FAIL;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
struct XYMessage *xy_msg = IExec-&amp;gt;WaitPort(xyport);  /* go to sleep until message arrives */&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A more general form of waiting for a message involves the use of the Wait() function (see [[Exec_Signals|Exec Signals]]). This function waits for task event signals directly. If the signal assigned to the message port occurs, the task will awaken. Using the Wait() function is more general because you can wait for more than one signal. By combining the signal bits from each port into one mask for the Wait() function, a loop can be set up to process all messages at all ports.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s an example using Wait():&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct XYMessage *xy_msg;&lt;br /&gt;
BOOL ABORT = FALSE;&lt;br /&gt;
&lt;br /&gt;
struct MsgPort *xyport = IExec-&amp;gt;AllocSysObjectTags(ASOT_PORT,&lt;br /&gt;
  ASOPORT_Name, &amp;quot;xyport&amp;quot;,&lt;br /&gt;
  TAG_END);&lt;br /&gt;
&lt;br /&gt;
if (xyport != NULL)&lt;br /&gt;
{&lt;br /&gt;
    uint32 portsig = 1 &amp;lt;&amp;lt; xyport-&amp;gt;mp_SigBit;&lt;br /&gt;
    uint32 usersig = SIGBREAKF_CTRL_C;            /* User can break with CTRL-C.  */&lt;br /&gt;
    for (;;)&lt;br /&gt;
    {&lt;br /&gt;
        uint32 signal = IExec-&amp;gt;Wait(portsig | usersig);  /* Sleep till someone signals.  */&lt;br /&gt;
&lt;br /&gt;
        if (signal &amp;amp; portsig)              /* Got a signal at the msgport. */&lt;br /&gt;
        {   .  .  .&lt;br /&gt;
        }&lt;br /&gt;
        if (signal &amp;amp; usersig)              /* Got a signal from the user.  */&lt;br /&gt;
        {&lt;br /&gt;
            ABORT = TRUE;                  /* Time to clean up.            */&lt;br /&gt;
             . . .&lt;br /&gt;
        }&lt;br /&gt;
        if (ABORT) break;&lt;br /&gt;
    }&lt;br /&gt;
    IExec-&amp;gt;FreeSysObject(ASOT_PORT, xyport);&lt;br /&gt;
}&lt;br /&gt;
else IDOS-&amp;gt;Printf(&amp;quot;Couldn&#039;t create xyport\n&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Note|text=WaitPort() only returns a pointer to the first message in a port. It does not actually remove the message from the port queue.|title=WaitPort() Does Not Remove A Message}}&lt;br /&gt;
&lt;br /&gt;
=== Getting a Message ===&lt;br /&gt;
&lt;br /&gt;
Messages are usually removed from ports with the GetMsg() function. This function removes the next message at the head of the port queue and returns a pointer to it. If there are no messages in a port, this function returns a zero.&lt;br /&gt;
&lt;br /&gt;
The example below illustrates the use of GetMsg() to print the contents of all messages in a port:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
while (xymsg = IExec-&amp;gt;GetMsg(xyport))&lt;br /&gt;
    IDOS-&amp;gt;Printf(&amp;quot;x=%ld y=%ld\n&amp;quot;, xymsg-&amp;gt;xy_X, xymsg-&amp;gt;xy_Y);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Certain messages may be more important than others. Because ports impose FIFO ordering, these important messages may get queued behind other messages regardless of their priority. If it is necessary to recognize more important messages, it is easiest to create another port for these special messages.&lt;br /&gt;
&lt;br /&gt;
=== Replying ===&lt;br /&gt;
&lt;br /&gt;
When the operations associated with receiving a new message are finished, it is usually necessary to send the message back to the originator. The receiver replies the message by returning it to the originator using the ReplyMsg() function. This is important because it notifies the originator that the message can be reused or deallocated.&lt;br /&gt;
&lt;br /&gt;
The ReplyMsg() function serves this purpose. It returns the message to the port specified in the mn_ReplyPort field of the message. If this field is zero, no reply is returned.&lt;br /&gt;
&lt;br /&gt;
The previous example can be enhanced to reply to each of its messages:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
while (xymsg = IExec-&amp;gt;GetMsg(xyport)) {&lt;br /&gt;
    IDOS-&amp;gt;Printf(&amp;quot;x=%ld y=%ld\n&amp;quot;, xymsg-&amp;gt;xy_X, xymsg-&amp;gt;xy_Y);&lt;br /&gt;
    IExec-&amp;gt;ReplyMsg(xymsg);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Notice that the reply does not occur until &#039;&#039;after&#039;&#039; the message values have been used.&lt;br /&gt;
&lt;br /&gt;
Often the operations associated with receiving a message involve returning &#039;&#039;results&#039;&#039; to the originator. Typically this is done within the message itself. The receiver places the results in fields defined (or perhaps reused) within the message body before replying the message back to the originator. Receipt of the replied message at the originator reply port indicates it is once again safe for the originator to use or change the values found within the message.&lt;br /&gt;
&lt;br /&gt;
The following are two short example tasks that communicate by sending, waiting for and replying to messages. Run these two programs together.&lt;br /&gt;
&lt;br /&gt;
==== Port1.c ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
// port1.c - port and message example, run at the same time as port2.c&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;exec/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;exec/ports.h&amp;gt;&lt;br /&gt;
#include &amp;lt;dos/dos.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/exec.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/dos.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
struct XYMessage {&lt;br /&gt;
    struct Message xym_Msg;&lt;br /&gt;
    int16          xy_X;&lt;br /&gt;
    int16          xy_Y;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
    BOOL ABORT = FALSE;&lt;br /&gt;
&lt;br /&gt;
    struct MsgPort *xyport = IExec-&amp;gt;AllocSysObjectTags(ASOT_PORT,&lt;br /&gt;
      ASOPORT_Name, &amp;quot;xyport&amp;quot;,&lt;br /&gt;
      TAG_END);&lt;br /&gt;
&lt;br /&gt;
    if (xyport != NULL)&lt;br /&gt;
    {&lt;br /&gt;
        uint32 portsig = 1U &amp;lt;&amp;lt; xyport-&amp;gt;mp_SigBit;       /* Give user a `break&#039; signal. */&lt;br /&gt;
        uint32 usersig = SIGBREAKF_CTRL_C;&lt;br /&gt;
&lt;br /&gt;
        IDOS-&amp;gt;Printf(&amp;quot;Start port2 in another shell.  CTRL-C here when done.\n&amp;quot;);&lt;br /&gt;
        do&lt;br /&gt;
        {                                                   /* port1 will wait forever and reply   */&lt;br /&gt;
            uint32 signal = IExec-&amp;gt;Wait(portsig | usersig); /* to messages, until the user breaks. */&lt;br /&gt;
            struct XYMessage *xymsg = 0;&lt;br /&gt;
&lt;br /&gt;
                                   /* Since we only have one port that might get messages we     */&lt;br /&gt;
            if (signal &amp;amp; portsig)  /* have to reply to, it is not really necessary to test for   */&lt;br /&gt;
            {                      /* the portsignal. If there is not message at the port, xymsg */&lt;br /&gt;
&lt;br /&gt;
                while(xymsg = (struct XYMessage *)IExec-&amp;gt;GetMsg(xyport))  /* simply will be NULL. */&lt;br /&gt;
                {&lt;br /&gt;
                    IDOS-&amp;gt;Printf(&amp;quot;port1 received: x = %d y = %d\n&amp;quot;, xymsg-&amp;gt;xy_X, xymsg-&amp;gt;xy_Y);&lt;br /&gt;
&lt;br /&gt;
                    xymsg-&amp;gt;xy_X += 50;       /* Since we have not replied yet to the owner of    */&lt;br /&gt;
                    xymsg-&amp;gt;xy_Y += 50;       /* xymsg, we can change the data contents of xymsg. */&lt;br /&gt;
&lt;br /&gt;
                    IDOS-&amp;gt;Printf(&amp;quot;port1 replying with: x = %d y = %d\n&amp;quot;, xymsg-&amp;gt;xy_X, xymsg-&amp;gt;xy_Y);&lt;br /&gt;
                    IExec-&amp;gt;ReplyMsg((struct Message *)xymsg);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            if (signal &amp;amp; usersig)  /* The user wants to abort. */&lt;br /&gt;
            {&lt;br /&gt;
                while(xymsg = (struct XYMessage *)IExec-&amp;gt;GetMsg(xyport))  /* Make sure port is empty. */&lt;br /&gt;
                    IExec-&amp;gt;ReplyMsg((struct Message *)xymsg);&lt;br /&gt;
                ABORT = TRUE;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        while (ABORT == FALSE);&lt;br /&gt;
            IExec-&amp;gt;FreeSysObject(ASOT_PORT, xyport);&lt;br /&gt;
        }&lt;br /&gt;
    else IDOS-&amp;gt;Printf(&amp;quot;Couldn&#039;t create &#039;xyport&#039;\n&amp;quot;);&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Port2.c ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
// port2.c - port and message example, run at the same time as port1.c&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;exec/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;exec/ports.h&amp;gt;&lt;br /&gt;
#include &amp;lt;exec/memory.h&amp;gt;&lt;br /&gt;
#include &amp;lt;dos/dos.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/exec.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/dos.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
BOOL SafePutToPort(struct Message *, CONST_STRPTR);&lt;br /&gt;
&lt;br /&gt;
struct XYMessage {&lt;br /&gt;
    struct Message xy_Msg;&lt;br /&gt;
    int16          xy_X;&lt;br /&gt;
    int16          xy_Y;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
    struct MsgPort *xyreplyport = IExec-&amp;gt;AllocSysObjectTags(ASOT_PORT, TAG_END);&lt;br /&gt;
&lt;br /&gt;
    if (xyreplyport != NULL)&lt;br /&gt;
    {&lt;br /&gt;
        struct XYMessage *reply = NULL;&lt;br /&gt;
&lt;br /&gt;
        struct XYMessage *xymsg = IExec-&amp;gt;AllocSysObjectTags(ASOT_MESSAGE,&lt;br /&gt;
          ASOMSG_Size, sizeof(struct XYMessage),&lt;br /&gt;
          ASOMSG_ReplyPort, xyreplyport,&lt;br /&gt;
          TAG_END);&lt;br /&gt;
&lt;br /&gt;
        if (xymsg != NULL)&lt;br /&gt;
        {&lt;br /&gt;
            xymsg-&amp;gt;xy_X = 10;   /* our special message information. */&lt;br /&gt;
            xymsg-&amp;gt;xy_Y = 20;&lt;br /&gt;
&lt;br /&gt;
            IDOS-&amp;gt;Printf(&amp;quot;Sending to port1: x = %d y = %d\n&amp;quot;, xymsg-&amp;gt;xy_X, xymsg-&amp;gt;xy_Y);&lt;br /&gt;
            &lt;br /&gt;
                                                                   /* port2 will simply try to put  */&lt;br /&gt;
            if (SafePutToPort((struct Message *)xymsg, &amp;quot;xyport&amp;quot;))  /* one message to port1 wait for */&lt;br /&gt;
            {                                                      /*  the reply, and then exit     */&lt;br /&gt;
                IExec-&amp;gt;WaitPort(xyreplyport);&lt;br /&gt;
                if (reply = (struct XYMessage *)IExec-&amp;gt;GetMsg(xyreplyport))&lt;br /&gt;
                    IDOS-&amp;gt;Printf(&amp;quot;Reply contains: x = %d y = %d\n&amp;quot;,   /* We don&#039;t ReplyMsg since   */&lt;br /&gt;
                            xymsg-&amp;gt;xy_X, xymsg-&amp;gt;xy_Y);                /* WE initiated the message. */&lt;br /&gt;
&lt;br /&gt;
                      /* Since we only use this private port for receiving replies, and we sent     */&lt;br /&gt;
                      /* only one and got one reply there is no need to cleanup. For a public port, */&lt;br /&gt;
                      /* or if you pass a pointer to the port to another process, it is a very good */&lt;br /&gt;
                      /* habit to always handle all messages at the port before you delete it.      */&lt;br /&gt;
            }&lt;br /&gt;
            else IDOS-&amp;gt;Printf(&amp;quot;Can&#039;t find &#039;xyport&#039;; start port1 in a separate shell\n&amp;quot;);&lt;br /&gt;
            IExec-&amp;gt;FreeSysObject(ASOT_MESSAGE, xymsg);&lt;br /&gt;
        }&lt;br /&gt;
        else IDOS-&amp;gt;Printf(&amp;quot;Couldn&#039;t get memory\n&amp;quot;);&lt;br /&gt;
        IExec-&amp;gt;FreeSysObject(ASOT_PORT, xyreplyport);&lt;br /&gt;
    }&lt;br /&gt;
    else IDOS-&amp;gt;Printf(&amp;quot;Couldn&#039;t create xyreplyport\n&amp;quot;);&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
BOOL SafePutToPort(struct Message *message, CONST_STRPTR portname)&lt;br /&gt;
{&lt;br /&gt;
    IExec-&amp;gt;Forbid();&lt;br /&gt;
    struct MsgPort *port = IExec-&amp;gt;FindPort(portname);&lt;br /&gt;
    if (port != NULL) IExec-&amp;gt;PutMsg(port, message);&lt;br /&gt;
    IExec-&amp;gt;Permit();&lt;br /&gt;
    return(port ? TRUE : FALSE); /* FALSE if the port was not found */&lt;br /&gt;
&lt;br /&gt;
         /* Once we&#039;ve done a Permit(), the port might go away and leave us with an invalid port    */&lt;br /&gt;
}        /* address. So we return just a BOOL to indicate whether the message has been sent or not. */&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Function Reference ==&lt;br /&gt;
&lt;br /&gt;
The following chart gives a brief description of the Exec functions that control inter-task communication with messages and ports. See the SDK for details about each call.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Function&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| AddPort()&lt;br /&gt;
| Add a public message port to the system list.&lt;br /&gt;
|-&lt;br /&gt;
| AllocSysObject(ASOT_PORT)&lt;br /&gt;
| Allocate and initialize a new message port.&lt;br /&gt;
|-&lt;br /&gt;
| FindPort()&lt;br /&gt;
| Find a public message port in the system list.&lt;br /&gt;
|-&lt;br /&gt;
| FreeSysObject(ASOT_PORT)&lt;br /&gt;
| Free a message port.&lt;br /&gt;
|-&lt;br /&gt;
| GetMsg()&lt;br /&gt;
| Get next message from the message port.&lt;br /&gt;
|-&lt;br /&gt;
| PutMsg()&lt;br /&gt;
| Put a message to a message port.&lt;br /&gt;
|-&lt;br /&gt;
| RemPort()&lt;br /&gt;
| Remove a message port from the system list.&lt;br /&gt;
|-&lt;br /&gt;
| ReplyMsg()&lt;br /&gt;
| Reply to a message on its reply port.&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Costel Mincea</name></author>
	</entry>
	<entry>
		<id>https://wiki.amigaos.net/w/index.php?title=Audio_Device&amp;diff=12567</id>
		<title>Audio Device</title>
		<link rel="alternate" type="text/html" href="https://wiki.amigaos.net/w/index.php?title=Audio_Device&amp;diff=12567"/>
		<updated>2025-01-26T19:37:57Z</updated>

		<summary type="html">&lt;p&gt;Costel Mincea: Text replacement - &amp;quot;&amp;lt;syntaxhighlight&amp;gt;&amp;quot; to &amp;quot;&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Devices|Audio]]{{CodeReview}}&lt;br /&gt;
== Audio Device ==&lt;br /&gt;
&lt;br /&gt;
The Amiga has four hardware audio channels—two of the channels produce audio output from the left audio connector, and two from the right. These channels can be used in many ways. You can combine a right and a left channel for stereo sound, use a single channel, or play a different sound through each of the channels to create four-part harmony.&lt;br /&gt;
&lt;br /&gt;
== About Amiga Audio ==&lt;br /&gt;
&lt;br /&gt;
Most personal computers that produce sound have hardware designed for one &#039;&#039;specific&#039;&#039; synthesis technique. The Amiga computer uses a very general method of digital sound synthesis that is quite similar to the method used in digital hi-fi components and state-of-the-art keyboard and drum synthesizers.&lt;br /&gt;
&lt;br /&gt;
For programs that can afford the memory, playing sampled sounds gives you a simple and very CPU-efficient method of sound synthesis. A sampled sound is a table of numbers which represents a sound digitally. When the sound is played back by the Amiga, the table is fed by a DMA channel into one of the four digital-to-analog converters in the custom chips. The digital-to-analog converter converts the samples into voltages that can be played through amplifiers and loudspeakers, reproducing the sound.&lt;br /&gt;
&lt;br /&gt;
On the Amiga you can create sound data in many other ways. For instance, you can use trigonometric functions in your programs to create the more traditional sounds—sine waves, square waves, or triangle waves—by using tables that describe their shapes. Then you can combine these waves for richer sound effects by adding the tables together. Once the data are entered, you can modify them with techniques described below. For information about the limitations of the audio hardware and suggestions for improving system efficiency and sound quality, refer to the &#039;&#039;Amiga Hardware Reference Manual&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Some commands enable your program to co-reside with other programs using the audio device at the same time. Programs can co-reside because the audio device handles allocation of audio channels and arbitrates among programs competing for the same resources. When properly used, this allows many programs to use the audio device simultaneously.&lt;br /&gt;
&lt;br /&gt;
The audio device commands help isolate the programmer from the idiosyncrasies of the custom chip hardware and make it easier to use. But you can also produce sound on the Amiga by directly accessing the hardware registers if you temporarily lock out other users first. For certain types of sound synthesis, this is more CPU-efficient.&lt;br /&gt;
&lt;br /&gt;
=== Definitions ===&lt;br /&gt;
&lt;br /&gt;
Terms used in the following discussions may be unfamiliar. Some of the more important ones are defined below.&lt;br /&gt;
;Amplitude&lt;br /&gt;
:The height of a waveform, which corresponds to the amount of voltage or current in the electronic circuit.&lt;br /&gt;
;Amplitude modulation&lt;br /&gt;
:A means of producing special audio effects by using one channel to alter the amplitude of another.&lt;br /&gt;
;Channel&lt;br /&gt;
:One “unit” of the audio device.&lt;br /&gt;
;Cycle&lt;br /&gt;
:One repetition of a waveform.&lt;br /&gt;
;Frequency&lt;br /&gt;
:The number of times per second a cycle repeats.&lt;br /&gt;
;Frequency modulation&lt;br /&gt;
:A means of producing special audio effects by using one channel to affect the period of the waveform produced by another channel.&lt;br /&gt;
;Period&lt;br /&gt;
:The time elapsed between the output of successive sound samples, in units of system clock ticks.&lt;br /&gt;
;Precedence&lt;br /&gt;
:Priority of the user of a sound channel.&lt;br /&gt;
;Sample&lt;br /&gt;
:Unit of audio data, one of the fixed-interval points on the waveform.&lt;br /&gt;
;Waveform&lt;br /&gt;
:Graph that shows a model of how the amplitude of a sound varies over time—usually over one cycle.&lt;br /&gt;
&lt;br /&gt;
== Audio Device Commands and Functions ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!Command!!Command Operation&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;ADCMD_ALLOCATE&#039;&#039;&#039;||Allocate one or more of the four audio channels.&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;ADCMD_FINISH&#039;&#039;&#039;||Abort the current write request on one or more of the channels. Can be done immediately or at the end of the current cycle.&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;ADCMD_FREE&#039;&#039;&#039;||Free one or more audio channels.&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;ADCMD_LOCK&#039;&#039;&#039;||Lock one or more audio channels.&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;ADCMD_PERVOL&#039;&#039;&#039;||Change the period and volume for writes in progress. Can be done immediately or at the end of the cycle.&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;ADCMD_SETPREC&#039;&#039;&#039;||Set the allocation precedence of one or more channels.&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;ADCMD_WAITCYCLE&#039;&#039;&#039;||Wait for the current write cycle to complete on a single channel. Returns at the end of the cycle or immediately if no cycle is active on the channel.&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;CMD_FLUSH&#039;&#039;&#039;||Purge all write cycles and waitcycles (in-progress and queued) for one or more channels.&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;CMD_READ&#039;&#039;&#039;||Return a pointer to the I/O block currently writing on a single channel.&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;CMD_RESET&#039;&#039;&#039;||Reset one or more channels their initialized state. All active and queued requests will be aborted.&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;CMD_START&#039;&#039;&#039;||Resume writes to one or more channels that were stopped.&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;CMD_STOP&#039;&#039;&#039;||Stop any write cycle in progress on one or more channels.&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;CMD_WRITE&#039;&#039;&#039;||Start a write cycle on a single channel.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Device Interface ==&lt;br /&gt;
&lt;br /&gt;
The audio device operates like the other Amiga I/O devices. To make sound, you first open the audio device, then send I/O requests to it, and then close it when finished. See [[Exec_Device_I/O|Exec Device I/O]] for general information on device usage.&lt;br /&gt;
&lt;br /&gt;
Audio device commands use an extended I/O request block named IOAudio to send commands to the audio device. This is the standard IORequest block with some extra fields added at the end.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct IOAudio&lt;br /&gt;
{&lt;br /&gt;
    struct IORequest ioa_Request;   /* I/O request block.  See exec/io.h.     */&lt;br /&gt;
    WORD   ioa_AllocKey;            /* Alloc. key filled in by audio device   */&lt;br /&gt;
    UBYTE  *ioa_Data;               /* Pointer to a sample or allocation mask */&lt;br /&gt;
    ULONG  ioa_Length;              /* Length of sample or allocation mask.   */&lt;br /&gt;
    UWORD  ioa_Period;              /* Sample playback speed                  */&lt;br /&gt;
    UWORD  ioa_Volume;              /* Volume of sound                        */&lt;br /&gt;
    UWORD  ioa_Cycles;              /* # of times to play sample. 0=forever.  */&lt;br /&gt;
    struct Message ioa_WriteMsg;    /* Filled in by device - usually not used */&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See the include file devices/audio.h for the complete structure definition.&lt;br /&gt;
&lt;br /&gt;
=== Opening the Audio Device ===&lt;br /&gt;
&lt;br /&gt;
Before you can use the audio device, you must first open it with a call to OpenDevice(). Four primary steps are required to open the audio device:&lt;br /&gt;
&lt;br /&gt;
* Create a message port using CreatePort. Reply messages from the device must be directed to a message port.&lt;br /&gt;
* Allocate memory for an extended I/O request structure of type IOAudio using AllocMem().&lt;br /&gt;
* Fill in io_Message.mn_ReplyPort with the message port created by CreatePort().&lt;br /&gt;
* Open the audio device. Call OpenDevice(), passing IOAudio.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
struct MsgPort  *AudioMP;          /* Define storage for port pointer */&lt;br /&gt;
struct IOAudio  *AudioIO;          /* Define storage for IORequest pointer */&lt;br /&gt;
&lt;br /&gt;
if (AudioMP = CreatePort(0,0) )&lt;br /&gt;
    {&lt;br /&gt;
    AudioIO = (struct IOAudio *)&lt;br /&gt;
               AllocMem(sizeof(struct IOAudio), MEMF_PUBLIC | MEMF_CLEAR);&lt;br /&gt;
    if (AudioIO)&lt;br /&gt;
        {&lt;br /&gt;
        AudioIO-&amp;amp;gt;ioa_Request.io_Message.mn_ReplyPort  = AudioMP;&lt;br /&gt;
        AudioIO-&amp;amp;gt;ioa_AllocKey                         = 0;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
    if (OpenDevice(AUDIONAME,0L,(struct IORequest *)AudioIO,0L) )&lt;br /&gt;
        printf(&amp;amp;quot;%s did not open\n&amp;amp;quot;,AUDIONAME);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A special feature of the OpenDevice() function with the audio device allows you to automatically allocate channels for your program to use when the device is opened. This is convenient since you &#039;&#039;must&#039;&#039; allocate one or more channels before you can produce sound.&lt;br /&gt;
&lt;br /&gt;
This is done by setting the value of ioa_AllocKey to zero, setting the value of ioa_Request.io_Message.mn_Node.ln_Pri to the appropriate precedence, setting io_Data to the address of a channel combination array, and setting ioa_Request.ioa_Length to a non-zero value (the length of the channel combination array). The audio device will attempt to allocate channels just as if you had sent the ADCMD_ALLOCATE command (see below). If the allocation fails, the OpenDevice() call will return immediately.&lt;br /&gt;
&lt;br /&gt;
If you want to allocate channels at some later time, set the value of the ioa_Request.ioa_Length field of the IOAudio block to zero when you call OpenDevice(). For more on channel allocation and the ADCMD_ALLOCATE command, see the section on “Allocation and Arbitration” below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
UBYTE chans[] = {1,2,4,8};  /* get any of the four channels */&lt;br /&gt;
&lt;br /&gt;
if (AudioIO)&lt;br /&gt;
    {&lt;br /&gt;
    AudioIO-&amp;amp;gt;ioa_Request.io_Message.mn_ReplyPort  = AudioMP;&lt;br /&gt;
    AudioIO-&amp;amp;gt;ioa_AllocKey                         = 0;&lt;br /&gt;
    AudioIO-&amp;amp;gt;ioa_Request.io_Message.mn_Node.ln_Pri= 120;&lt;br /&gt;
    AudioIO-&amp;amp;gt;ioa_Data                             = chans;&lt;br /&gt;
    AudioIO-&amp;amp;gt;ioa_Length                           = sizeof(chans);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
if (OpenDevice(AUDIONAME,0L,(struct IORequest *)AudioIO,0L) )&lt;br /&gt;
    printf(&amp;quot;%s did not open\n&amp;quot;, AUDIONAME);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Audio Device Command Types ===&lt;br /&gt;
&lt;br /&gt;
Commands for audio use can be divided into two categories: allocation/arbitration commands and hardware control commands.&lt;br /&gt;
&lt;br /&gt;
There are four allocation/arbitration commands. These do not actually produce any sound. Instead they manage and arbitrate the audio resources for the many tasks that may be using audio in the Amiga’s multitasking environment.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
|ADCMD_ALLOCATE||Reserves an audio channel for your program to use.&lt;br /&gt;
|-&lt;br /&gt;
|ADCMD_FREE||Frees an audio channel.&lt;br /&gt;
|-&lt;br /&gt;
|ADCMD_SETPREC||Changes the precedence of a sound in progress.&lt;br /&gt;
|-&lt;br /&gt;
|ADCMD_LOCK||Tells if a channel has been stolen from you.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The hardware control commands are used to set up, start, and stop sounds on the audio device:&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|-&lt;br /&gt;
|CMD_WRITE||The main command. Starts a sound playing.&lt;br /&gt;
|-&lt;br /&gt;
|ADCMD_FINISH||Aborts a sound in progress.&lt;br /&gt;
|-&lt;br /&gt;
|ADCMD_PERVOL||Changes the period (speed) and volume of a sound in progress.&lt;br /&gt;
|-&lt;br /&gt;
|CMD_FLUSH||Clears the audio channels.&lt;br /&gt;
|-&lt;br /&gt;
|CMD_RESET||Resets and initializes the audio device.&lt;br /&gt;
|-&lt;br /&gt;
|ADCMD_WAITCYCLE||Signals you when a cycle finishes.&lt;br /&gt;
|-&lt;br /&gt;
|CMD_STOP||Temporarily stops a channel from playing.&lt;br /&gt;
|-&lt;br /&gt;
|CMD_START||Restarts an audio channel that was stopped.&lt;br /&gt;
|-&lt;br /&gt;
|CMD_READ||Returns a pointer to the current IOAudio request.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Scope of Audio Commands ===&lt;br /&gt;
&lt;br /&gt;
Most audio commands can operate on multiple channels. The exceptions are ADCMD_WAITCYCLE, CMD_WRITE and CMD_READ, which can only operate on one channel at a time. You specify the channel(s) that you want to use by setting the appropriate bits in the ioa_Request.io_Unit field of the IOAudio block. If you send a command for a channel that you do not own, your command will be ignored. For more details, see the section on “Allocation and Arbitration” below.&lt;br /&gt;
&lt;br /&gt;
=== Audio and System I/O Functions ===&lt;br /&gt;
&lt;br /&gt;
==== BeginIO() ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
All the commands that you can give to the audio device should be sent by calling the BeginIO() function. This differs from other Amiga devices which generally use SendIO() or DoIO(). You should not use SendIO() or DoIO() with the audio device because these functions clear some special flags used by the audio device; this might cause audio to work incorrectly under certain circumstances. To be safe, you should always use BeginIO() with the audio device.&lt;br /&gt;
&lt;br /&gt;
==== Wait() and WaitPort() ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
These functions can be used to put your task to sleep while a sound plays. Wait() takes a wake-up mask as its argument. The wake-up mask is usually the mp_SigBit of a MsgPort that you have set up to get replies back from the audio device.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;WaitPort()&#039;&#039;&#039; will put your task to sleep while a sound plays. The argument to WaitPort() is a pointer to a MsgPort that you have set up to get replies back from the audio device.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Wait()&#039;&#039;&#039; and WaitPort() will not remove the message from the reply port. You must use GetMsg() to remove it.&lt;br /&gt;
&lt;br /&gt;
You must always use Wait() or WaitPort() to wait for I/O to finish with the audio device.&lt;br /&gt;
&lt;br /&gt;
==== AbortIO() ====&lt;br /&gt;
&lt;br /&gt;
This function can be used to cancel requests for ADCMD_ALLOCATE, ADCMD_LOCK, CMD_WRITE, or ADCMD_WAITCYCLE. When used with the audio device, AbortIO() always succeeds.&lt;br /&gt;
&lt;br /&gt;
=== Closing the Audio Device ===&lt;br /&gt;
&lt;br /&gt;
An OpenDevice() must eventually be matched by a call to CloseDevice().&lt;br /&gt;
&lt;br /&gt;
All I/O requests must be complete before CloseDevice(). If any requests are still pending, abort them with AbortIO():&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;AbortIO((struct IORequest *)AudioIO);  /* Abort any pending requests */&lt;br /&gt;
WaitPort(AudioMP);                     /* Wait for abort message */&lt;br /&gt;
GetMsg(AudioMP);                       /* Get abort message */&lt;br /&gt;
CloseDevice((struct IORequest *)AudioIO);&amp;lt;/pre&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;CloseDevice()&#039;&#039;&#039; performs an ADCMD_FREE command on any channels selected by the ioa_Request.io_Unit field of the IOAudio request. This means that if you close the device with the same IOAudio block that you used to allocate your channels (or a copy of it), the channels will be automatically freed.&lt;br /&gt;
&lt;br /&gt;
If you allocated channels with multiple allocation commands, you cannot use this function to close all of them at once. Instead, you will have to issue one ADCMD_FREE command for each allocation that you made. After issuing the ADCMD_FREE commands for each of the allocations, you can call CloseDevice().&lt;br /&gt;
&lt;br /&gt;
== A Simple Audio Example ==&lt;br /&gt;
&lt;br /&gt;
The Amiga’s audio software has a complex allocation and arbitration system which is described in detail in the sections below. At this point, though, it may be helpful to look at a simple audio example:&lt;br /&gt;
&lt;br /&gt;
== Audio Allocation and Arbitration ==&lt;br /&gt;
&lt;br /&gt;
The first command you send to the audio device should always be ADCMD_ALLOCATE. You can do this when you open the device, or at a later time. You specify the channels you want in the &#039;&#039;&#039;ioa_Data&#039;&#039;&#039; field of the &#039;&#039;&#039;IOAudio&#039;&#039;&#039; block. If the allocation succeeds, the audio device will return the channels that you now own in the lower four bits of the &#039;&#039;&#039;ioa_Request.io_Unit&#039;&#039;&#039; field of your &#039;&#039;&#039;IOAudio&#039;&#039;&#039; block. For instance, if the &#039;&#039;&#039;io_Unit&#039;&#039;&#039; field equals 5 (binary 0101) then you own channels 2 and 0. If the &#039;&#039;&#039;io_Unit&#039;&#039;&#039; field equals 15 (binary 1111) then you own all the channels.&lt;br /&gt;
&lt;br /&gt;
When you send the ADCMD_ALLOCATE command, the audio device will also return a unique allocation key in the &#039;&#039;&#039;ioa_AllocKey&#039;&#039;&#039; of the &#039;&#039;&#039;IOAudio&#039;&#039;&#039; block. You must use this allocation key for all subsequent commands that you send to the audio device. The audio device uses this unique key to identify which task issued the command. If you do not use the correct allocation key assigned to you by the audio device when you send a command, your command will be ignored.&lt;br /&gt;
&lt;br /&gt;
When you request a channel with ADCMD_ALLOCATE, you specify a precedence number from -128 to 127 in the &#039;&#039;&#039;ioa_Request.io_Message.mn_Node.ln_Pri&#039;&#039;&#039; field of the &#039;&#039;&#039;IOAudio&#039;&#039;&#039; block. If a channel you want is being used and you have specified a higher precedence than the current user, ADCMD_ALLOCATE will “steal” the channel from the other user. Later on, if your precedence is lower than that of another user who is performing an allocation, the channel may be stolen from you.&lt;br /&gt;
&lt;br /&gt;
If you set the precedence to 127 when you open the device or raise the precedence to 127 with the ADCMD_SETPREC command, no other tasks can steal a channel from you. When you have finished with a channel, you must relinquish it with the ADCMD_FREE command to make it available for other users.&lt;br /&gt;
&lt;br /&gt;
The following table shows suggested precedence values.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Suggested Precedences for Channel Allocation&lt;br /&gt;
!Predecence!!Type of Sound&lt;br /&gt;
|-&lt;br /&gt;
|127||&#039;&#039;Unstoppable&#039;&#039;. Sounds first allocated at lower precedence, then set to this highest level.&lt;br /&gt;
|-&lt;br /&gt;
|90 – 100||&#039;&#039;Emergencies&#039;&#039;. Alert, urgent situation that requires immediate action.&lt;br /&gt;
|-&lt;br /&gt;
|80 – 90||&#039;&#039;Annunciators&#039;&#039;. Attention, bell (Ctrl-G).&lt;br /&gt;
|-&lt;br /&gt;
|75||&#039;&#039;Speech&#039;&#039;. Synthesized or recorded speech (narrator.device).&lt;br /&gt;
|-&lt;br /&gt;
|50 – 70||&#039;&#039;Sonic cues&#039;&#039;. Sounds that provide information that is not provided by graphics. Only the beginning of each sound (enough to recognize it) should be at this level; the rest should be set to sound effects level.&lt;br /&gt;
|-&lt;br /&gt;
| -50 – 50||&#039;&#039;Music program&#039;&#039;. Musical notes in music-oriented program. The higher levels should be used for the attack portions of each note.&lt;br /&gt;
|-&lt;br /&gt;
| -70 – -50||&#039;&#039;Sound effects&#039;&#039;. Sounds used in conjunction with graphics. More important sounds should use higher levels.&lt;br /&gt;
|-&lt;br /&gt;
| -100 – -80||&#039;&#039;Background&#039;&#039;. Theme music and restartable background sounds.&lt;br /&gt;
|-&lt;br /&gt;
| -128||&#039;&#039;Silence&#039;&#039;. Lowest level (freeing the channel completely is preferred)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If you attempt to perform a command on a channel that has been stolen from you by a higher priority task, an AUDIO_NOALLOCATION error is returned and the bit in the ioa_Request.io_Unit field corresponding to the stolen channel is cleared so you know which channel was stolen.&lt;br /&gt;
&lt;br /&gt;
If you want to be warned before a channel is stolen so that you have a chance to stop your sound gracefully, then you should use the ADCMD_LOCK command after you open the device. This command is also useful for programs which write directly to the audio hardware. For more on ADCMD_LOCK, see the section below.&lt;br /&gt;
&lt;br /&gt;
== Allocation and Arbitration Commands ==&lt;br /&gt;
&lt;br /&gt;
These commands allow the audio channels to be shared among different tasks and programs. None of these commands can be called from interrupt code.&lt;br /&gt;
&lt;br /&gt;
=== ADCMD_ALLOCATE ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This command gives your program a channel to use and should be the first command you send to the audio device. You specify the channels you want by setting a pointer to an array in the &#039;&#039;&#039;ioa_Data&#039;&#039;&#039; field of the &#039;&#039;&#039;IOAudio&#039;&#039;&#039; structure. This array uses a value of 1 to allocate channel 0, 2 for channel 1, 4 for channel 2, and 8 for channel 3. For multiple channels, add the values together. For example, if you want to allocate all channels, use a value of 15.&lt;br /&gt;
&lt;br /&gt;
If you want a pair of stereo channels and you have no preference about which of the left and right channels the system will choose for the allocation, you can pass a pointer to an array containing 3, 5, 10, and 12. Channels 1 and 2 produce sound on the left side and channels 0 and 3 on the right side. The table below shows how this array corresponds to all the possible combinations of a right and a left channel.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Possible Channel Combinations&lt;br /&gt;
!Channel 3&lt;br /&gt;
right&lt;br /&gt;
!Channel 2&lt;br /&gt;
left&lt;br /&gt;
!Channel 1&lt;br /&gt;
left&lt;br /&gt;
!Channel 0&lt;br /&gt;
right&lt;br /&gt;
!Decimal Value &lt;br /&gt;
of&lt;br /&gt;
Allocation Mask&lt;br /&gt;
|-&lt;br /&gt;
|0||0||1||1||3&lt;br /&gt;
|-&lt;br /&gt;
|0||1||0||1||5&lt;br /&gt;
|-&lt;br /&gt;
|1||0||1||0||10&lt;br /&gt;
|-&lt;br /&gt;
|1||1||0||0||12&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== How ADCMD_ALLOCATE Operates ====&lt;br /&gt;
&lt;br /&gt;
The ADCMD_ALLOCATE command tries the first combination, 3, to see if channels 0 and 1 are not being used. If they are available, the 3 is copied into the &#039;&#039;&#039;io_Unit&#039;&#039;&#039; field and you get an allocation key for these channels in the &#039;&#039;&#039;ioa_AllocKey&#039;&#039;&#039; field. You copy the key into other I/O blocks for any other commands you may want to perform on these channels.&lt;br /&gt;
&lt;br /&gt;
If channels 0 and 1 are being used, ADCMD_ALLOCATE tries the other combinations in turn. If all the combinations are in use, ADCMD_ALLOCATE checks the precedence number of the users of the channels and finds the combination that requires it to steal the channel or channels of the lowest precedence. If all the combinations require stealing a channel or channels of equal or higher precedence, the ADCMD_ALLOCATE request fails. Precedence is in the &#039;&#039;&#039;ln_Pri&#039;&#039;&#039; field of the &#039;&#039;&#039;io_Message&#039;&#039;&#039; in the &#039;&#039;&#039;IOAudio&#039;&#039;&#039; block you pass to ADCMD_ALLOCATE; it has a value from -128 to 127.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== The ADIOF_NOWAIT Flag ====&lt;br /&gt;
&lt;br /&gt;
If you need to produce a sound right now and otherwise don’t want to allocate, set the ADIOF_NOWAIT flag to 1. This will cause the command to return an IOERR_ALLOCFAILED error if it cannot allocate any of the channels. If you are producing a non-urgent sound and you can wait, set the ADIOF_NOWAIT flag to 0. Then, the &#039;&#039;&#039;IOAudio&#039;&#039;&#039; block returns only when you get the allocation. If ADIOF_NOWAIT is set to 0, the audio device will continue to retry the allocation request whenever channels are freed until it is successful. If the program decides to cancel the request, &#039;&#039;&#039;AbortIO&#039;&#039;&#039;() can be used.&lt;br /&gt;
&lt;br /&gt;
==== ADCMD_ALLOCATE Examples ====&lt;br /&gt;
&lt;br /&gt;
The following are more examples of how to tell ADCMD_ALLOCATE your channel preferences. If you want any channel, but want a right channel first, use an array containing 1, 8, 2, and 4:&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|0001&lt;br /&gt;
|-&lt;br /&gt;
|1000&lt;br /&gt;
|-&lt;br /&gt;
|0010&lt;br /&gt;
|-&lt;br /&gt;
|0100&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If you only want a right channel, use 1 and 8 (channels 0 and 3):&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|0001&lt;br /&gt;
|-&lt;br /&gt;
|1000&lt;br /&gt;
|}&lt;br /&gt;
If you want only a left channel, use 2 and 4 (channels 1 and 2):&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
|0010&lt;br /&gt;
|-&lt;br /&gt;
|0100&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If you want to allocate a channel and keep it for a sound that can be interrupted and restarted, allocate it at a certain precedence. If it is stolen, allocate it again with the ADIOF_NOWAIT flag set to 0. When the channel is relinquished, you will get it again.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== The Allocation Key ====&lt;br /&gt;
&lt;br /&gt;
If you want to perform multi-channel commands, all the channels must have the same key since the &#039;&#039;&#039;IOAudio&#039;&#039;&#039; block has only one allocation key field. The channels must all have that same key even when they were not allocated simultaneously. If you want to use a key you already have, you can pass that key in the &#039;&#039;&#039;ioa_AllocKey&#039;&#039;&#039; field and ADCMD_ALLOCATE can allocate other channels with that existing key. The ADCMD_ALLOCATE command returns a new and unique key only if you pass it a zero in the allocation key field.&lt;br /&gt;
&lt;br /&gt;
=== ADCMD_FREE ===&lt;br /&gt;
&lt;br /&gt;
ADCMD_FREE is the opposite of ADCMD_ALLOCATE. When you perform ADCMD_FREE on a channel, it does a CMD_RESET command on the hardware and “unlocks” the channel. It also checks to see if there are other pending allocation requests. You do not need to perform ADCMD_FREE on channels stolen from you. If you want channels back after they have been stolen, you must reallocate them with the same allocation key.&lt;br /&gt;
&lt;br /&gt;
=== ADCMD_SETPREC ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This command changes the precedence of an allocated channel. As an example of the use of ADCMD_SETPREC, assume that you are making the sound of a chime that takes a long time to decay. It is important that user hears the chime but not so important that he hears it decay all the way. You could lower precedence after the initial attack portion of the sound to let another program steal the channel. You can also set the precedence to maximum (127) if you do not want the channel(s) stolen from you.&lt;br /&gt;
&lt;br /&gt;
=== ADCMD_LOCK ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The ADCMD_LOCK command performs the “steal verify” function. When another application is attempting to steal a channel or channels, ADCMD_LOCK gives you a chance to clean up before the channel is stolen. You perform a ADCMD_LOCK command right after the ADCMD_ALLOCATE command. ADCMD_LOCK does not return until a higher-priority user attempts to steal the channel(s) or you perform an ADCMD_FREE command. If someone is attempting to steal, you must finish up and ADCMD_FREE the channel as quickly as possible.&lt;br /&gt;
&lt;br /&gt;
You must use ADCMD_LOCK if you want to write directly to the hardware registers instead of using the device commands. If your channel is stolen, you are not notified unless the ADCMD_LOCK command is present. This could cause problems for the task that has stolen the channel and is now using it at the same time as your task. ADCMD_LOCK sets a switch that is not cleared until you perform an ADCMD_FREE command on the channel. Canceling an ADCMD_LOCK request with &#039;&#039;&#039;AbortIO()&#039;&#039;&#039; will not free the channel.&lt;br /&gt;
&lt;br /&gt;
The following outline describes how ADCMD_LOCK works when a channel is stolen and when it is not stolen.&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;User A&#039;&#039; allocates a channel.&lt;br /&gt;
# &#039;&#039;User A&#039;&#039; locks the channel.&lt;br /&gt;
#:If &#039;&#039;User B&#039;&#039; allocates the channel with a higher precedence:&lt;br /&gt;
## &#039;&#039;User B&#039;&#039;’s ADCMD_ALLOCATE command is suspended (regardless of the setting of the ADIOF_NOWAIT flag).&lt;br /&gt;
## &#039;&#039;User A&#039;&#039;’s lock command is replied to with an error (this will be ADIOERR_CHANNELSTOLEN).&lt;br /&gt;
## &#039;&#039;User A&#039;&#039; does whatever is needed to finish up when a channel is stolen.&lt;br /&gt;
## &#039;&#039;User A&#039;&#039; frees the channel with ADCMD_FREE.&lt;br /&gt;
## &#039;&#039;User B&#039;&#039;’s ADCMD_ALLOCATE command is replied to. Now user B has the channel.&lt;br /&gt;
#:If the channel is not allocated by another user:&lt;br /&gt;
## &#039;&#039;User A&#039;&#039; finishes the sound.&lt;br /&gt;
## &#039;&#039;User A&#039;&#039; performs the ADCMD_FREE command.&lt;br /&gt;
## &#039;&#039;User A&#039;&#039;’s ADCMD_LOCK command is replied to.&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Never make the freeing of a channel (if the channel is stolen) dependent on allocating another channel. This may cause a deadlock. If you want channels back after they have been stolen, you must reallocate them with the same allocation key. To keep a channel and never let it be stolen, set precedence to maximum (127). Do not use a lock for this purpose.&lt;br /&gt;
&lt;br /&gt;
== Hardware Control Commands ==&lt;br /&gt;
&lt;br /&gt;
The following commands change hardware registers and affect the actual sound output.&lt;br /&gt;
&lt;br /&gt;
=== CMD_WRITE ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This is a single-channel command and is the main command for making sounds. You pass the following to CMD_WRITE:&lt;br /&gt;
&lt;br /&gt;
* A pointer to the waveform to be played (must start on a word boundary and must be in memory accessible by the custom chips, MEMF_CHIP)&lt;br /&gt;
* The length of the waveform in bytes (must be an even number)&lt;br /&gt;
* A count of how many times you want to play the waveform&lt;br /&gt;
&lt;br /&gt;
If the count is 0, CMD_WRITE will play the waveform from beginning to end, then repeat the waveform continuously until something aborts it.&lt;br /&gt;
&lt;br /&gt;
If you want period and volume to be set at the start of the sound, set the WRITE command’s ADIOF_PERVOL flag. If you do not do this, the previous volume and period for that channel will be used. This is one of the flags that is cleared by &#039;&#039;&#039;DoIO()&#039;&#039;&#039; and &#039;&#039;&#039;SendIO()&#039;&#039;&#039;. The &#039;&#039;&#039;ioa_WriteMsg&#039;&#039;&#039; field in the &#039;&#039;&#039;IOAudio&#039;&#039;&#039; block is an extra message field that can be replied to at the start of the CMD_WRITE. This second message is used only to tell you when the CMD_WRITE command &#039;&#039;starts&#039;&#039; processing, and it is used only when the ADIOF_WRITEMESSAGE flag is set to 1.&lt;br /&gt;
&lt;br /&gt;
If a CMD_STOP has been performed, the CMD_WRITE requests are queued up. The CMD_WRITE command does not make its own copy of the waveform, so any modification of the waveform before the CMD_WRITE command is finished may affect the sound. This is sometimes desirable for special effects. To splice together two waveforms without clicks or pops, you must send a separate, second CMD_WRITE command while the first is still in progress. This technique is used in double-buffering, which is described below.&lt;br /&gt;
&lt;br /&gt;
By using two waveform buffers and two CMD_WRITE requests you can compute a waveform continuously. This is called double-buffering. The following describes how you use double-buffering.&lt;br /&gt;
&lt;br /&gt;
# Compute a waveform in memory buffer A.&lt;br /&gt;
# Issue CMD_WRITE A with &#039;&#039;&#039;io_Data&#039;&#039;&#039; pointing to buffer A.&lt;br /&gt;
# Continue the waveform in memory buffer B.&lt;br /&gt;
# Issue CMD_WRITE B with &#039;&#039;&#039;io_Data&#039;&#039;&#039; pointing to Buffer B.&lt;br /&gt;
# Wait for CMD_WRITE A to finish.&lt;br /&gt;
# Continue the waveform in memory buffer A.&lt;br /&gt;
# Issue CMD_WRITE A with &#039;&#039;&#039;io_Data&#039;&#039;&#039; pointing to Buffer A.&lt;br /&gt;
# Wait for CMD_WRITE B to finish.&lt;br /&gt;
# Loop back to step 3 until the waveform is finished.&lt;br /&gt;
# At the end, remember to wait until both CMD_WRITE A and B are finished.&lt;br /&gt;
&lt;br /&gt;
=== ADCMD_FINISH ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The ADCMD_FINISH command aborts (calls &#039;&#039;&#039;AbortIO()&#039;&#039;&#039;) the current write request on a channel or channels. This is useful if you have something playing, such as a long buffer or some repetitions of a buffer, and you want to stop it.&lt;br /&gt;
&lt;br /&gt;
ADCMD_FINISH has a flag you can set (ADIOF_SYNCCYCLE) that allows the waveform to finish the current cycle before aborting it. This is useful for splicing together sounds at zero crossings or some other place in the waveform where the amplitude at the end of one waveform matches the amplitude at the beginning of the next. Zero crossings are positions within the waveform at which the amplitude is zero. Splicing at zero crossings gives you fewer clicks and pops when the audio channel is turned off or the volume is changed.&lt;br /&gt;
&lt;br /&gt;
=== ADCMD_PERVOL ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ADCMD_PERVOL lets you change the volume and period of a CMD_WRITE that is in progress. The change can take place immediately or you can set the ADIOF_SYNCCYCLE flag to have the change occur at the end of the cycle. This is useful to produce vibratos, glissandos, tremolos, and volume envelopes in music or to change the volume of a sound.&lt;br /&gt;
&lt;br /&gt;
=== CMD_FLUSH ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
CMD_FLUSH aborts (calls AbortIO()) all CMD_WRITEs and all ADCMD_WAITCYCLEs that are queued up for the channel or channels. It does not abort ADCMD_LOCKs (only ADCMD_FREE clears locks).&lt;br /&gt;
&lt;br /&gt;
=== CMD_RESET ===&lt;br /&gt;
&lt;br /&gt;
CMD_RESET restores all the audio hardware registers. It clears the attach bits, restores the audio interrupt vectors if the programmer has changed them, and performs the CMD_FLUSH command to cancel all requests to the channels. CMD_RESET also unstops channels that have had a CMD_STOP performed on them. CMD_RESET does not unlock channels that have been locked by ADCMD_LOCK.&lt;br /&gt;
&lt;br /&gt;
=== ADCMD_WAITCYCLE ===&lt;br /&gt;
&lt;br /&gt;
This is a single-channel command. ADCMD_WAITCYCLE is replied to when the current cycle has completed, If there is no CMD_WRITE in progress, it returns immediately.&lt;br /&gt;
&lt;br /&gt;
=== CMD_STOP ===&lt;br /&gt;
&lt;br /&gt;
This command stops the current write cycle immediately. If there are no CMD_WRITEs in progress, it sets a flag so any future CMD_WRITEs are queued up and do not begin processing (playing).&lt;br /&gt;
&lt;br /&gt;
=== CMD_START ===&lt;br /&gt;
&lt;br /&gt;
CMD_START undoes the CMD_STOP command. Any cycles that were stopped by the CMD_STOP command are actually lost because of the impossibility of determining exactly where the DMA ceased. If the CMD_WRITE command was playing two cycles and the first one was playing when CMD_STOP was issued, the first one is lost and the second one will be played.&lt;br /&gt;
&lt;br /&gt;
This command is also useful when you are playing the same wave form with the same period out of multiple channels. If the channels are stopped when the CMD_WRITE commands are issued, CMD_START exactly synchronizes them, avoiding cancellation and distortion. When channels are allocated, they are effectively started by the CMD_START command.&lt;br /&gt;
&lt;br /&gt;
=== CMD_READ ===&lt;br /&gt;
&lt;br /&gt;
CMD_READ is a single-channel command. Its only function is to return a pointer to the current CMD_WRITE command. It enables you to determine which request is being processed.&lt;br /&gt;
&lt;br /&gt;
== Double Buffered Sound Example ==&lt;br /&gt;
&lt;br /&gt;
The program listed below demonstrates double buffering with the audio device. Run the program from the CLI. It takes one parameter—the name of an IFF 8SVX sample file to play on the Amiga’s audio device. The maximum size for a sample on the Amiga is 128K. However, by using double-buffering and queueing up requests to the audio device, you can play longer samples smoothly and without breaks.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;/*&lt;br /&gt;
 * Audio_8SVX.c&lt;br /&gt;
 *&lt;br /&gt;
 * 8SVX example - double buffers &amp;amp;gt;128K samples&lt;br /&gt;
 *&lt;br /&gt;
 * Compile with SAS C 5.10  lc -b1 -cfistq -v -y -L&lt;br /&gt;
 *&lt;br /&gt;
 * Run from CLI only&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
#include &amp;amp;lt;exec/types.h&amp;amp;gt;&lt;br /&gt;
#include &amp;amp;lt;exec/memory.h&amp;amp;gt;&lt;br /&gt;
#include &amp;amp;lt;devices/audio.h&amp;amp;gt;&lt;br /&gt;
#include &amp;amp;lt;dos/dos.h&amp;amp;gt;&lt;br /&gt;
#include &amp;amp;lt;dos/dosextens.h&amp;amp;gt;&lt;br /&gt;
#include &amp;amp;lt;graphics/gfxbase.h&amp;amp;gt;&lt;br /&gt;
#include &amp;amp;lt;iff/iff.h&amp;amp;gt;&lt;br /&gt;
#include &amp;amp;lt;iff/8svx.h&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;amp;lt;clib/exec_protos.h&amp;amp;gt;&lt;br /&gt;
#include &amp;amp;lt;clib/alib_protos.h&amp;amp;gt;&lt;br /&gt;
#include &amp;amp;lt;clib/dos_protos.h&amp;amp;gt;&lt;br /&gt;
#include &amp;amp;lt;clib/graphics_protos.h&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;amp;lt;stdlib.h&amp;amp;gt;&lt;br /&gt;
#include &amp;amp;lt;stdio.h&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
#ifdef LATTICE&lt;br /&gt;
int CXBRK(void) { return(0); }     /* Disable SAS CTRL/C handling */&lt;br /&gt;
int chkabort(void) { return(0); }  /* really */&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#define VHDR MakeID(&#039;V&#039;,&#039;H&#039;,&#039;D&#039;,&#039;R&#039;)&lt;br /&gt;
#define BODY MakeID(&#039;B&#039;,&#039;O&#039;,&#039;D&#039;,&#039;Y&#039;)&lt;br /&gt;
#define MY8S MakeID(&#039;8&#039;,&#039;S&#039;,&#039;V&#039;,&#039;X&#039;)&lt;br /&gt;
&lt;br /&gt;
void              kill8svx(char *);&lt;br /&gt;
void              kill8(void);&lt;br /&gt;
&lt;br /&gt;
/*--------------------*/               /* These globals are needed */&lt;br /&gt;
/*   G L O B A L S    */               /* by the clean up routines */&lt;br /&gt;
/*--------------------*/&lt;br /&gt;
struct IOAudio     *AIOptr1,           /* Pointers to Audio IOBs      */&lt;br /&gt;
                   *AIOptr2,&lt;br /&gt;
                   *Aptr;&lt;br /&gt;
struct Message     *msg;               /* Msg, port and device for    */&lt;br /&gt;
struct MsgPort     *port,              /* driving audio               */&lt;br /&gt;
                   *port1,*port2;&lt;br /&gt;
       ULONG        device;&lt;br /&gt;
       UBYTE       *sbase,*fbase;      /* For sample memory allocation */&lt;br /&gt;
       ULONG        fsize,ssize;       /* and freeing                  */&lt;br /&gt;
&lt;br /&gt;
struct FileHandle  *v8handle;&lt;br /&gt;
       UBYTE        chan1[]  = {  1 }; /* Audio channel allocation arrays */&lt;br /&gt;
       UBYTE        chan2[]  = {  2 };&lt;br /&gt;
       UBYTE        chan3[]  = {  4 };&lt;br /&gt;
       UBYTE        chan4[]  = {  8 };&lt;br /&gt;
       UBYTE       *chans[] = {chan1,chan2,chan3,chan4};&lt;br /&gt;
&lt;br /&gt;
       BYTE         oldpri,c;          /* Stuff for bumping priority */&lt;br /&gt;
&lt;br /&gt;
struct Task        *mt=0L;&lt;br /&gt;
struct GfxBase     *GfxBase = NULL;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*-----------*/&lt;br /&gt;
/*  M A I N  */&lt;br /&gt;
/*-----------*/&lt;br /&gt;
&lt;br /&gt;
void main(int argc,char **argv)&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
/*-------------*/&lt;br /&gt;
/* L O C A L S */&lt;br /&gt;
/*-------------*/&lt;br /&gt;
&lt;br /&gt;
       char         *fname;               /* File name and data pointer*/&lt;br /&gt;
       UBYTE        *p8data;              /* for file read.            */&lt;br /&gt;
       ULONG         clock;               /* Clock constant            */&lt;br /&gt;
       ULONG         length[2];           /* Sample lengths            */&lt;br /&gt;
       BYTE          iobuffer[8],         /* Buffer for 8SVX header    */&lt;br /&gt;
                    *psample[2];          /* Sample pointers           */&lt;br /&gt;
       Chunk        *p8Chunk;             /* Pointers for 8SVX parsing */&lt;br /&gt;
       Voice8Header *pVoice8Header;&lt;br /&gt;
       ULONG         y,rd8count,speed;    /* Counters, sampling speed   */&lt;br /&gt;
       ULONG         wakebit;             /* A wakeup mask              */&lt;br /&gt;
&lt;br /&gt;
/*-------------*/&lt;br /&gt;
/*   C O D E   */&lt;br /&gt;
/*-------------*/&lt;br /&gt;
&lt;br /&gt;
/*------------------------------*/&lt;br /&gt;
/* Check Arguments, Initialize  */&lt;br /&gt;
/*------------------------------*/&lt;br /&gt;
&lt;br /&gt;
fbase=0L;&lt;br /&gt;
sbase=0L;&lt;br /&gt;
AIOptr1=0L;&lt;br /&gt;
AIOptr2=0L;&lt;br /&gt;
port=0L;&lt;br /&gt;
port1=0L;&lt;br /&gt;
port2=0L;&lt;br /&gt;
v8handle=0L;&lt;br /&gt;
device=1L;&lt;br /&gt;
&lt;br /&gt;
if (argc &amp;amp;lt; 2)&lt;br /&gt;
    {&lt;br /&gt;
    kill8svx(&amp;amp;quot;No file name given.\n&amp;amp;quot;);&lt;br /&gt;
    exit(1L);&lt;br /&gt;
    }&lt;br /&gt;
fname=argv[1];&lt;br /&gt;
&lt;br /&gt;
/*---------------------------*/&lt;br /&gt;
/* Initialize Clock Constant */&lt;br /&gt;
/*---------------------------*/&lt;br /&gt;
&lt;br /&gt;
GfxBase=(struct GfxBase *)OpenLibrary(&amp;amp;quot;graphics.library&amp;amp;quot;,0L);&lt;br /&gt;
if (GfxBase==0L)&lt;br /&gt;
    {&lt;br /&gt;
    puts(&amp;amp;quot;Can&#039;t open graphics library\n&amp;amp;quot;);&lt;br /&gt;
    exit(1L);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
if (GfxBase-&amp;amp;gt;DisplayFlags &amp;amp;amp; PAL)&lt;br /&gt;
    clock=3546895L;        /* PAL clock */&lt;br /&gt;
else&lt;br /&gt;
    clock=3579545L;        /* NTSC clock */&lt;br /&gt;
&lt;br /&gt;
if (GfxBase)&lt;br /&gt;
    CloseLibrary( (struct Library *) GfxBase);&lt;br /&gt;
&lt;br /&gt;
/*---------------*/&lt;br /&gt;
/* Open the File */&lt;br /&gt;
/*---------------*/&lt;br /&gt;
&lt;br /&gt;
v8handle= (struct FileHandle *) Open(fname,MODE_OLDFILE);&lt;br /&gt;
if (v8handle==0)&lt;br /&gt;
    {&lt;br /&gt;
    kill8svx(&amp;amp;quot;Can&#039;t open 8SVX file.\n&amp;amp;quot;);&lt;br /&gt;
    exit(1L);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
/*-------------------------------------------*/&lt;br /&gt;
/* Read the 1st 8 Bytes of the File for Size */&lt;br /&gt;
/*-------------------------------------------*/&lt;br /&gt;
rd8count=Read((BPTR)v8handle,iobuffer,8L);&lt;br /&gt;
if (rd8count==-1)&lt;br /&gt;
    {&lt;br /&gt;
    kill8svx (&amp;amp;quot;Read error.\n&amp;amp;quot;);&lt;br /&gt;
    exit(1L);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
if (rd8count&amp;amp;lt;8)&lt;br /&gt;
    {&lt;br /&gt;
    kill8svx (&amp;amp;quot;Not an IFF 8SVX file, too short\n&amp;amp;quot;);&lt;br /&gt;
    exit(1L);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
/*-----------------*/&lt;br /&gt;
/* Evaluate Header */&lt;br /&gt;
/*-----------------*/&lt;br /&gt;
p8Chunk=(Chunk *)iobuffer;&lt;br /&gt;
if (p8Chunk-&amp;amp;gt;ckID != FORM )&lt;br /&gt;
    {&lt;br /&gt;
    kill8svx(&amp;amp;quot;Not an IFF FORM.\n&amp;amp;quot;);&lt;br /&gt;
    exit(1L);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
/*--------------------------------------------*/&lt;br /&gt;
/* Allocate Memory for File and Read it in.   */&lt;br /&gt;
/*--------------------------------------------*/&lt;br /&gt;
fbase= (UBYTE *)AllocMem(fsize=p8Chunk-&amp;amp;gt;ckSize , MEMF_PUBLIC|MEMF_CLEAR);&lt;br /&gt;
if (fbase==0)&lt;br /&gt;
    {&lt;br /&gt;
    kill8svx(&amp;amp;quot;No memory for read.\n&amp;amp;quot;);&lt;br /&gt;
    exit(1L);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
p8data=fbase;&lt;br /&gt;
&lt;br /&gt;
rd8count=Read((BPTR)v8handle,p8data,p8Chunk-&amp;amp;gt;ckSize);&lt;br /&gt;
if (rd8count==-1)&lt;br /&gt;
    {&lt;br /&gt;
    kill8svx (&amp;amp;quot;Read error.\n&amp;amp;quot;);&lt;br /&gt;
    exit(1L);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
if (rd8count&amp;amp;lt;p8Chunk-&amp;amp;gt;ckSize)&lt;br /&gt;
    {&lt;br /&gt;
    kill8svx (&amp;amp;quot;Malformed IFF, too short.\n&amp;amp;quot;);&lt;br /&gt;
    exit(1L);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
/*-------------------*/&lt;br /&gt;
/* Evaluate IFF Type */&lt;br /&gt;
/*-------------------*/&lt;br /&gt;
if (MakeID( *p8data, *(p8data+1) , *(p8data+2) , *(p8data+3) ) != MY8S )&lt;br /&gt;
    {&lt;br /&gt;
    kill8svx(&amp;amp;quot;Not an IFF 8SVX file.\n&amp;amp;quot;);&lt;br /&gt;
    exit(1L);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
/*----------------------*/&lt;br /&gt;
/* Evaluate 8SVX Chunks */&lt;br /&gt;
/*----------------------*/&lt;br /&gt;
p8data=p8data+4;&lt;br /&gt;
&lt;br /&gt;
while( p8data &amp;amp;lt; fbase+fsize )&lt;br /&gt;
  {&lt;br /&gt;
  p8Chunk=(Chunk *)p8data;&lt;br /&gt;
&lt;br /&gt;
  switch(p8Chunk-&amp;amp;gt;ckID)&lt;br /&gt;
    {&lt;br /&gt;
    case VHDR:&lt;br /&gt;
      /*------------------------------------------------*/&lt;br /&gt;
      /* Get a pointer to the 8SVX header for later use */&lt;br /&gt;
      /*------------------------------------------------*/&lt;br /&gt;
      pVoice8Header=(Voice8Header *)(p8data+8L);&lt;br /&gt;
      break;&lt;br /&gt;
&lt;br /&gt;
    case BODY:&lt;br /&gt;
      /*-------------------------------------------------*/&lt;br /&gt;
      /* Create pointers to 1-shot and continuous parts  */&lt;br /&gt;
      /* for the top octave and get length. Store them.  */&lt;br /&gt;
      /*-------------------------------------------------*/&lt;br /&gt;
        psample[0] = (BYTE *)(p8data + 8L);&lt;br /&gt;
        psample[1] = psample[0] + pVoice8Header-&amp;amp;gt;oneShotHiSamples;&lt;br /&gt;
        length[0] = (ULONG)pVoice8Header-&amp;amp;gt;oneShotHiSamples;&lt;br /&gt;
        length[1] = (ULONG)pVoice8Header-&amp;amp;gt;repeatHiSamples;&lt;br /&gt;
        break;&lt;br /&gt;
&lt;br /&gt;
    default:&lt;br /&gt;
      break;&lt;br /&gt;
    }&lt;br /&gt;
    /* end switch */&lt;br /&gt;
&lt;br /&gt;
  p8data = p8data + 8L + p8Chunk-&amp;amp;gt;ckSize;&lt;br /&gt;
&lt;br /&gt;
  if (p8Chunk-&amp;amp;gt;ckSize&amp;amp;amp;1L == 1)&lt;br /&gt;
      p8data++;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
/* Play either the one-shot or continuous, not both */&lt;br /&gt;
if (length[0]==0)&lt;br /&gt;
    y=1;&lt;br /&gt;
else&lt;br /&gt;
    y=0;&lt;br /&gt;
&lt;br /&gt;
/*---------------------------------------*/&lt;br /&gt;
/* Allocate chip memory for samples and  */&lt;br /&gt;
/* copy from read buffer to chip memory. */&lt;br /&gt;
/*---------------------------------------*/&lt;br /&gt;
if (length[y]&amp;amp;lt;=102400)&lt;br /&gt;
    ssize=length[y];&lt;br /&gt;
else&lt;br /&gt;
    ssize=102400;&lt;br /&gt;
&lt;br /&gt;
sbase=(UBYTE *)AllocMem( ssize , MEMF_CHIP | MEMF_CLEAR);&lt;br /&gt;
if (sbase==0)&lt;br /&gt;
    {&lt;br /&gt;
    kill8svx(&amp;amp;quot;No chip memory.\n&amp;amp;quot;);&lt;br /&gt;
    exit(1L);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
CopyMem(psample[y],sbase,ssize);&lt;br /&gt;
psample[y]+=ssize;&lt;br /&gt;
&lt;br /&gt;
/*----------------------------------*/&lt;br /&gt;
/* Calculate playback sampling rate */&lt;br /&gt;
/*----------------------------------*/&lt;br /&gt;
speed =  clock / pVoice8Header-&amp;amp;gt;samplesPerSec;&lt;br /&gt;
&lt;br /&gt;
/*-------------------*/&lt;br /&gt;
/* Bump our priority */&lt;br /&gt;
/*-------------------*/&lt;br /&gt;
mt=FindTask(NULL);&lt;br /&gt;
oldpri=SetTaskPri(mt,21);&lt;br /&gt;
&lt;br /&gt;
/*--------------------------------*/&lt;br /&gt;
/* Allocate two audio I/O blocks  */&lt;br /&gt;
/*--------------------------------*/&lt;br /&gt;
AIOptr1=(struct IOAudio *)&lt;br /&gt;
      AllocMem( sizeof(struct IOAudio),MEMF_PUBLIC|MEMF_CLEAR);&lt;br /&gt;
if (AIOptr1==0)&lt;br /&gt;
    {&lt;br /&gt;
    kill8svx(&amp;amp;quot;No IO memory\n&amp;amp;quot;);&lt;br /&gt;
    exit(1L);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
AIOptr2=(struct IOAudio *)&lt;br /&gt;
      AllocMem( sizeof(struct IOAudio),MEMF_PUBLIC|MEMF_CLEAR);&lt;br /&gt;
if (AIOptr2==0)&lt;br /&gt;
    {&lt;br /&gt;
    kill8svx(&amp;amp;quot;No IO memory\n&amp;amp;quot;);&lt;br /&gt;
    exit(1L);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
/*----------------------*/&lt;br /&gt;
/* Make two reply ports */&lt;br /&gt;
/*----------------------*/&lt;br /&gt;
&lt;br /&gt;
port1=CreatePort(0,0);&lt;br /&gt;
if (port1==0)&lt;br /&gt;
    {&lt;br /&gt;
    kill8svx(&amp;amp;quot;No port\n&amp;amp;quot;);&lt;br /&gt;
    exit(1L);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
port2=CreatePort(0,0);&lt;br /&gt;
if (port2==0)&lt;br /&gt;
    {&lt;br /&gt;
    kill8svx(&amp;amp;quot;No port\n&amp;amp;quot;);&lt;br /&gt;
    exit(1L);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
c=0;&lt;br /&gt;
while(device!=0 &amp;amp;amp;&amp;amp;amp; c&amp;amp;lt;4)&lt;br /&gt;
  {&lt;br /&gt;
  /*---------------------------------------*/&lt;br /&gt;
  /* Set up audio I/O block for channel    */&lt;br /&gt;
  /* allocation and Open the audio device  */&lt;br /&gt;
  /*---------------------------------------*/&lt;br /&gt;
  AIOptr1-&amp;amp;gt;ioa_Request.io_Message.mn_ReplyPort   = port1;&lt;br /&gt;
  AIOptr1-&amp;amp;gt;ioa_Request.io_Message.mn_Node.ln_Pri = 127;  /* No stealing! */&lt;br /&gt;
  AIOptr1-&amp;amp;gt;ioa_AllocKey                          = 0;&lt;br /&gt;
  AIOptr1-&amp;amp;gt;ioa_Data                              = chans[c];&lt;br /&gt;
  AIOptr1-&amp;amp;gt;ioa_Length                            = 1;&lt;br /&gt;
&lt;br /&gt;
  device=OpenDevice(AUDIONAME,0L,(struct IORequest *)AIOptr1,0L);&lt;br /&gt;
  c++;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
if (device!=0)&lt;br /&gt;
    {&lt;br /&gt;
    kill8svx(&amp;amp;quot;No channel\n&amp;amp;quot;);&lt;br /&gt;
    exit(1L);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
/*-------------------------------------------*/&lt;br /&gt;
/* Set Up Audio IO Blocks for Sample Playing */&lt;br /&gt;
/*-------------------------------------------*/&lt;br /&gt;
&lt;br /&gt;
AIOptr1-&amp;amp;gt;ioa_Request.io_Command   =CMD_WRITE;&lt;br /&gt;
AIOptr1-&amp;amp;gt;ioa_Request.io_Flags     =ADIOF_PERVOL;&lt;br /&gt;
&lt;br /&gt;
/*--------*/&lt;br /&gt;
/* Volume */&lt;br /&gt;
/*--------*/&lt;br /&gt;
&lt;br /&gt;
AIOptr1-&amp;amp;gt;ioa_Volume=60;&lt;br /&gt;
&lt;br /&gt;
/*---------------*/&lt;br /&gt;
/* Period/Cycles */&lt;br /&gt;
/*---------------*/&lt;br /&gt;
&lt;br /&gt;
AIOptr1-&amp;amp;gt;ioa_Period =(UWORD)speed;&lt;br /&gt;
AIOptr1-&amp;amp;gt;ioa_Cycles =1;&lt;br /&gt;
&lt;br /&gt;
*AIOptr2 = *AIOptr1;   /* Make sure we have the same allocation keys, */&lt;br /&gt;
                       /* same channels selected and same flags       */&lt;br /&gt;
                       /* (but different ports...)                    */&lt;br /&gt;
&lt;br /&gt;
AIOptr1-&amp;amp;gt;ioa_Request.io_Message.mn_ReplyPort   = port1;&lt;br /&gt;
AIOptr2-&amp;amp;gt;ioa_Request.io_Message.mn_ReplyPort   = port2;&lt;br /&gt;
&lt;br /&gt;
/*--------*/&lt;br /&gt;
/*  Data  */&lt;br /&gt;
/*--------*/&lt;br /&gt;
&lt;br /&gt;
AIOptr1-&amp;amp;gt;ioa_Data            =(UBYTE *)sbase;&lt;br /&gt;
AIOptr2-&amp;amp;gt;ioa_Data            =(UBYTE *)sbase + 51200;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*-----------------*/&lt;br /&gt;
/*  Run the sample */&lt;br /&gt;
/*-----------------*/&lt;br /&gt;
&lt;br /&gt;
if (length[y]&amp;amp;lt;=102400)&lt;br /&gt;
    {&lt;br /&gt;
    AIOptr1-&amp;amp;gt;ioa_Length=length[y];         /* No double buffering needed */&lt;br /&gt;
    BeginIO((struct IORequest *)AIOptr1);  /* Begin the sample, wait for */&lt;br /&gt;
    wakebit=0L;                            /* it to finish, then quit.   */&lt;br /&gt;
    wakebit=Wait(1 &amp;amp;lt;&amp;amp;lt; port1-&amp;amp;gt;mp_SigBit);&lt;br /&gt;
    while((msg=GetMsg(port1))==0){};&lt;br /&gt;
    }&lt;br /&gt;
else&lt;br /&gt;
    {&lt;br /&gt;
    length[y]-=102400;                    /* It&#039;s a real long sample so  */&lt;br /&gt;
    AIOptr1-&amp;amp;gt;ioa_Length=51200L;           /* double buffering is needed  */&lt;br /&gt;
    AIOptr2-&amp;amp;gt;ioa_Length=51200L;&lt;br /&gt;
    BeginIO((struct IORequest *)AIOptr1); /* Start up the first 2 blocks... */&lt;br /&gt;
    BeginIO((struct IORequest *)AIOptr2);&lt;br /&gt;
    Aptr=AIOptr1;&lt;br /&gt;
    port=port1;                           /* Set the switch... */&lt;br /&gt;
&lt;br /&gt;
    while(length[y]&amp;amp;gt;0)&lt;br /&gt;
      {                                   /* We Wait() for one IO to finish, */&lt;br /&gt;
      wakebit=Wait(1 &amp;amp;lt;&amp;amp;lt; port-&amp;amp;gt;mp_SigBit); /* then reuse the IO block &amp;amp;amp; queue */&lt;br /&gt;
      while((msg=GetMsg(port))==0){};     /* it up again while the 2nd IO    */&lt;br /&gt;
                                          /* block plays. Switch and repeat. */&lt;br /&gt;
      /* Set length of next IO block */&lt;br /&gt;
      if (length[y]&amp;amp;lt;=51200)&lt;br /&gt;
          Aptr-&amp;amp;gt;ioa_Length=length[y];&lt;br /&gt;
      else&lt;br /&gt;
          Aptr-&amp;amp;gt;ioa_Length=51200L;&lt;br /&gt;
&lt;br /&gt;
      /* Copy sample fragment from read buffer to chip memory */&lt;br /&gt;
      CopyMem(psample[y],Aptr-&amp;amp;gt;ioa_Data,Aptr-&amp;amp;gt;ioa_Length);&lt;br /&gt;
&lt;br /&gt;
      /* Adjust size and pointer of read buffer*/&lt;br /&gt;
      length[y]-=Aptr-&amp;amp;gt;ioa_Length;&lt;br /&gt;
      psample[y]+=51200;&lt;br /&gt;
&lt;br /&gt;
      BeginIO((struct IORequest *)Aptr);&lt;br /&gt;
&lt;br /&gt;
      if (Aptr==AIOptr1)&lt;br /&gt;
          {&lt;br /&gt;
          Aptr=AIOptr2;                  /* This logic handles switching  */&lt;br /&gt;
          port=port2;                    /* between the 2 IO blocks and   */&lt;br /&gt;
          }                               /* the 2 ports we are using.     */&lt;br /&gt;
      else&lt;br /&gt;
          {&lt;br /&gt;
          Aptr=AIOptr1;&lt;br /&gt;
          port=port1;&lt;br /&gt;
          }&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
    /*-------------------------------------------------*/&lt;br /&gt;
    /* OK we are at the end of the sample so just wait */&lt;br /&gt;
    /* for the last two parts of the sample to finish  */&lt;br /&gt;
    /*-------------------------------------------------*/&lt;br /&gt;
    wakebit=Wait(1 &amp;amp;lt;&amp;amp;lt; port-&amp;amp;gt;mp_SigBit);&lt;br /&gt;
    while((msg=GetMsg(port))==0){};&lt;br /&gt;
    if (Aptr==AIOptr1)&lt;br /&gt;
        {&lt;br /&gt;
        Aptr=AIOptr2;                  /* This logic handles switching  */&lt;br /&gt;
        port=port2;                    /* between the 2 IO blocks and   */&lt;br /&gt;
        }                              /* the 2 ports we are using.     */&lt;br /&gt;
    else&lt;br /&gt;
        {&lt;br /&gt;
        Aptr=AIOptr1;&lt;br /&gt;
        port=port1;&lt;br /&gt;
        }&lt;br /&gt;
    wakebit=Wait(1 &amp;amp;lt;&amp;amp;lt; port-&amp;amp;gt;mp_SigBit);&lt;br /&gt;
    while((msg=GetMsg(port))==0){};&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
kill8();&lt;br /&gt;
exit(0L);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*----------------*/&lt;br /&gt;
/* Abort the Read */&lt;br /&gt;
/*----------------*/&lt;br /&gt;
void&lt;br /&gt;
kill8svx(kill8svxstring)&lt;br /&gt;
char *kill8svxstring;&lt;br /&gt;
{&lt;br /&gt;
puts(kill8svxstring);&lt;br /&gt;
kill8();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*-------------------------*/&lt;br /&gt;
/* Return system resources */&lt;br /&gt;
/*-------------------------*/&lt;br /&gt;
void&lt;br /&gt;
kill8()&lt;br /&gt;
{&lt;br /&gt;
if (device ==0)&lt;br /&gt;
    CloseDevice((struct IORequest *)AIOptr1);&lt;br /&gt;
if (port1  !=0)&lt;br /&gt;
    DeletePort(port1);&lt;br /&gt;
if (port2  !=0)&lt;br /&gt;
    DeletePort(port2);&lt;br /&gt;
if (AIOptr1!=0)&lt;br /&gt;
    FreeMem( AIOptr1,sizeof(struct IOAudio) );&lt;br /&gt;
if (AIOptr2!=0)&lt;br /&gt;
    FreeMem( AIOptr2,sizeof(struct IOAudio) );&lt;br /&gt;
&lt;br /&gt;
if (mt!=0)&lt;br /&gt;
    SetTaskPri(mt,oldpri);&lt;br /&gt;
&lt;br /&gt;
if (sbase !=0)&lt;br /&gt;
    FreeMem (sbase, ssize);&lt;br /&gt;
if (fbase !=0)&lt;br /&gt;
    FreeMem(fbase,fsize);&lt;br /&gt;
if (v8handle!=0)&lt;br /&gt;
    Close((BPTR)v8handle);&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Additional Information on the Audio Device ==&lt;br /&gt;
&lt;br /&gt;
Additional programming information on the audio device can be found in the include files and the Autodocs for the audio device. Both are contained in the [[Autodocs:Main|Autodocs]]. Information can also be found in the &#039;&#039;Amiga Hardware Reference Manual&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!colspan=&amp;quot;2&amp;quot;|Audio Device Information&lt;br /&gt;
|-&lt;br /&gt;
|Includes||devices/audio.h&amp;lt;br /&amp;gt;devices/audio.i&lt;br /&gt;
|-&lt;br /&gt;
|[[Autodocs:Main|Autodocs]]||[[audio.doc]]&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Costel Mincea</name></author>
	</entry>
	<entry>
		<id>https://wiki.amigaos.net/w/index.php?title=Intuition_Menu_Class&amp;diff=12566</id>
		<title>Intuition Menu Class</title>
		<link rel="alternate" type="text/html" href="https://wiki.amigaos.net/w/index.php?title=Intuition_Menu_Class&amp;diff=12566"/>
		<updated>2025-01-26T19:36:51Z</updated>

		<summary type="html">&lt;p&gt;Costel Mincea: Text replacement - &amp;quot;&amp;lt;syntaxhighlight&amp;gt;&amp;quot; to &amp;quot;&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= An overview =&lt;br /&gt;
&lt;br /&gt;
Starting with version 54.6, Intuition features a built-in BOOPSI menu class (&amp;quot;menuclass&amp;quot;) which aims to fully replace the traditional way of setting up and handling menus in applications.&lt;br /&gt;
&lt;br /&gt;
Its object-oriented API allows to easily build complex menu trees, freeing a program from the need to use gadtools.library for that job. It also provides extensive control over menus, making it possible to define, read and change their properties thanks to simple yet flexible methods and attributes.&lt;br /&gt;
&lt;br /&gt;
Moreover, menuclass extends the capabilities of the original Intuition menu system. For instance, it can handle any number of sub-menu levels, as well as any amount of items in menus and sub-menus. For nearly all operations, it transparently synchronizes itself with Intuition and performs menu relayout if needed. Automatic placement of custom images in front of menu item labels is also supported.&lt;br /&gt;
&lt;br /&gt;
== BOOPSI menus vs. traditional menus ==&lt;br /&gt;
&lt;br /&gt;
BOOPSI menus may look and feel identical to traditional ones from the point of view of the user, but are handled quite differently in application code.&lt;br /&gt;
&lt;br /&gt;
The old-style, white-box Menu and MenuItem structures are replaced by abstract objects (instances of menuclass) accessed through an object-oriented interface, removing the need for manual poking or dedicated menu functions.&lt;br /&gt;
&lt;br /&gt;
Such BOOPSI menu objects are able to perform automatically most operations for which their traditional counterparts would require special assistance from the application.&lt;br /&gt;
&lt;br /&gt;
== Types of menuclass objects ==&lt;br /&gt;
&lt;br /&gt;
There exist three distinct types of menuclass objects -- menu root, menu and menu item. Any instance of the class belongs to one of these types, specified at OM_NEW time through the MA_Type attribute.&lt;br /&gt;
&lt;br /&gt;
The possible values for MA_Type are:&lt;br /&gt;
&lt;br /&gt;
; T_ROOT&lt;br /&gt;
: A menu root object, also known as a menu strip as it is the parent of all menu objects. This differs from the old-style menu system, where a &amp;quot;menu strip&amp;quot; was just a linked list of Menu structures. Besides being the actual root of a menu tree, a menu root object also holds essential state information on the tree as a whole. It may be used in any place an old-style menu strip can, except for the ItemAddress() function (replaced by the MM_FINDID method). A menu root object can have any number of menu objects as children.&lt;br /&gt;
&lt;br /&gt;
; T_MENU&lt;br /&gt;
: A menu object, equivalent to the old-style Menu structure. A menu object can have any number of menu item objects as children (and should always have at least one).&lt;br /&gt;
&lt;br /&gt;
; T_ITEM&lt;br /&gt;
: A menu item object, equivalent to the old-style MenuItem structure. A menu item object can have any number of menu item objects as children (sub-items), even in the case it is itself a sub-item of some other menu item. Only a menu (sub-)item having no children (i.e. a leaf item) can be actually selected by the user.&lt;br /&gt;
&lt;br /&gt;
== Compatibility ==&lt;br /&gt;
&lt;br /&gt;
Save where explicitly allowed, menu and menu item objects instantiated from menuclass cannot be transparently used in place of the equivalent old-style Intuition elements, as not all of the traditional menu-related functions and rules apply to them.&lt;br /&gt;
&lt;br /&gt;
A limited form of compatibility exists due to menuclass objects having Menu or MenuItem structures embedded in them, just like gadgetclass ones do with the (Ext)Gadget structure. However, such structures should never be directly accessed by user code unless otherwise documented.&lt;br /&gt;
&lt;br /&gt;
Under most circumstances, applications should treat menuclass instances as &amp;quot;black boxes&amp;quot;, the only exception to this rule currently being that it is permitted to read certain bits from the Flags field of their embedded legacy structure (see also next subsection).&lt;br /&gt;
&lt;br /&gt;
== Recognizing a BOOPSI menu object ==&lt;br /&gt;
&lt;br /&gt;
Although an application normally should know if it is using BOOPSI menus, it may happen that a library or a class needs to check the type of menus passed to it by a client. This is easily done with the following test:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
  if ((((struct Menu *)menu_object_ptr)-&amp;gt;Flags &amp;amp; BOOPSIMENU) != 0)&lt;br /&gt;
    ...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the flag BOOPSIMENU is set, the object is a menuclass instance, otherwise it is a traditional Menu or MenuItem structure.&lt;br /&gt;
&lt;br /&gt;
{{Note|text=In the above test it would have been exactly the same if we had chosen to cast the object to a struct MenuItem * rather than to a struct Menu * because the Flags field is located at the same offset (and has the same size) in both structures.}}&lt;br /&gt;
&lt;br /&gt;
= Adding BOOPSI menus to an application =&lt;br /&gt;
&lt;br /&gt;
In this section we&#039;ll cover the basics of using the new menuclass in a typical application, and the main differences between BOOPSI and traditional menus.&lt;br /&gt;
&lt;br /&gt;
The first step in adding BOOPSI menus to your application is to build a tree of menuclass objects, each with its appearance and behavior defined by attributes that can be set at NewObject() time.&lt;br /&gt;
&lt;br /&gt;
== Label and ID of menus and menu items ==&lt;br /&gt;
&lt;br /&gt;
For menu and menu item objects, the application should specify at least a label string and an ID number as a minimal set of attributes.&lt;br /&gt;
&lt;br /&gt;
The label is assigned via MA_Label and is the text Intuition will display to represent a menu or menu item on the screen. A special value for this attribute is the constant ML_SEPARATOR, which turns a menu item into a separator line.&lt;br /&gt;
&lt;br /&gt;
The ID, passed with the MA_ID tag, is a 32-bit unsigned integer that uniquely identifies a particular menu or menu item object. This number is passed back to the application through the IDCMP mechanism whenever the user picks a menu item or asks for help on a menu or menu item.&lt;br /&gt;
&lt;br /&gt;
Any number may be chosen as an ID for a menuclass object, except for 0 (zero): this constant has the alias NO_MENU_ID in &amp;lt;intuition/menuclass.h&amp;gt; and is always an invalid value for an object&#039;s MA_ID attribute. Also, when an IDCMP_MENUPICK or IDCMP_MENUHELP ExtIntuiMessage reports NO_MENU_ID in its eim_LongCode field, this is to be interpreted as &amp;quot;no menu selection&amp;quot; (i.e. it has the same meaning MENUNULL has for old-style menus).&lt;br /&gt;
&lt;br /&gt;
Menu root objects, as well as menu items acting as separator lines, don&#039;t need to have an ID number. Menu root objects don&#039;t need a label string either.&lt;br /&gt;
&lt;br /&gt;
== Building a menu tree with menuclass ==&lt;br /&gt;
&lt;br /&gt;
A menu tree is organized as a hierarchy of nested menuclass objects.&lt;br /&gt;
&lt;br /&gt;
At the very top of the tree there is the menu root, having one or more menus as children. These make up the menu strip that appears on the screen when the user presses the right mouse button.&lt;br /&gt;
&lt;br /&gt;
Each menu is the parent of one or more menu items. A menu item can have other menu items as children as well, thus forming a sub-menu. A menu item which is part of a sub-menu (also called a sub-item, i.e. the child of another menu item) can in turn have children (sub-items) of its own.&lt;br /&gt;
&lt;br /&gt;
The leaf nodes of the tree are menu items or sub-items with no children. These are the actually selectable menu options.&lt;br /&gt;
&lt;br /&gt;
There is no limit to the depth of the menu tree other than the available system memory.&lt;br /&gt;
&lt;br /&gt;
You can append children to a menuclass object at OM_NEW or OM_SET time with the MA_AddChild tag, or by using the OM_ADDMEMBER method (more on this later).&lt;br /&gt;
&lt;br /&gt;
An example of a very simple menu tree generation could be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
  Object *menustripobj;&lt;br /&gt;
&lt;br /&gt;
  menustripobj = IIntuition-&amp;gt;NewObject(NULL,&amp;quot;menuclass&amp;quot;,MA_Type,T_ROOT,&lt;br /&gt;
                   MA_AddChild, IIntuition-&amp;gt;NewObject(NULL,&amp;quot;menuclass&amp;quot;,MA_Type,T_MENU,&lt;br /&gt;
                     MA_Label, &amp;quot;Project&amp;quot;,&lt;br /&gt;
                     MA_AddChild, IIntuition-&amp;gt;NewObject(NULL,&amp;quot;menuclass&amp;quot;,MA_Type,T_ITEM,&lt;br /&gt;
                       MA_Label, &amp;quot;Open...&amp;quot;,&lt;br /&gt;
                       MA_ID, MID_PROJECT_OPEN,&lt;br /&gt;
                       TAG_END),&lt;br /&gt;
                     MA_AddChild, IIntuition-&amp;gt;NewObject(NULL,&amp;quot;menuclass&amp;quot;,MA_Type,T_ITEM,&lt;br /&gt;
                       MA_Label, &amp;quot;Save&amp;quot;,&lt;br /&gt;
                       MA_ID, MID_PROJECT_SAVE,&lt;br /&gt;
                       TAG_END),&lt;br /&gt;
                     MA_AddChild, IIntuition-&amp;gt;NewObject(NULL,&amp;quot;menuclass&amp;quot;,MA_Type,T_ITEM,&lt;br /&gt;
                       MA_Label, &amp;quot;Save as...&amp;quot;,&lt;br /&gt;
                       MA_ID, MID_PROJECT_SAVEAS,&lt;br /&gt;
                       TAG_END),&lt;br /&gt;
                     MA_AddChild, IIntuition-&amp;gt;NewObject(NULL,&amp;quot;menuclass&amp;quot;,MA_Type,T_ITEM,&lt;br /&gt;
                       MA_Label, ML_SEPARATOR,&lt;br /&gt;
                       TAG_END),&lt;br /&gt;
                     MA_AddChild, IIntuition-&amp;gt;NewObject(NULL,&amp;quot;menuclass&amp;quot;,MA_Type,T_ITEM,&lt;br /&gt;
                       MA_Label, &amp;quot;About...&amp;quot;,&lt;br /&gt;
                       MA_ID, MID_PROJECT_ABOUT,&lt;br /&gt;
                       TAG_END),&lt;br /&gt;
                     MA_AddChild, IIntuition-&amp;gt;NewObject(NULL,&amp;quot;menuclass&amp;quot;,MA_Type,T_ITEM,&lt;br /&gt;
                       MA_Label, ML_SEPARATOR,&lt;br /&gt;
                       TAG_END),&lt;br /&gt;
                     MA_AddChild, IIntuition-&amp;gt;NewObject(NULL,&amp;quot;menuclass&amp;quot;,MA_Type,T_ITEM,&lt;br /&gt;
                       MA_Label, &amp;quot;Quit&amp;quot;,&lt;br /&gt;
                       MA_ID, MID_PROJECT_QUIT,&lt;br /&gt;
                       TAG_END),&lt;br /&gt;
                     TAG_END),&lt;br /&gt;
                   TAG_END);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you prefer a more compact style of coding, &amp;lt;intuition/menuclass.h&amp;gt; offers a number of macros allowing to simplify the tree description a little. Using said macros, the above code could be rewritten as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
  Object *menustripobj;&lt;br /&gt;
&lt;br /&gt;
  menustripobj = MStrip,&lt;br /&gt;
                   MA_AddChild, MTitle(&amp;quot;Project&amp;quot;),&lt;br /&gt;
                     MA_AddChild, MItem(&amp;quot;Open...&amp;quot;),&lt;br /&gt;
                       MA_ID, MID_PROJECT_OPEN,&lt;br /&gt;
                     MEnd,&lt;br /&gt;
                     MA_AddChild, MItem(&amp;quot;Save&amp;quot;),&lt;br /&gt;
                       MA_ID, MID_PROJECT_SAVE,&lt;br /&gt;
                     MEnd,&lt;br /&gt;
                     MA_AddChild, MItem(&amp;quot;Save as...&amp;quot;),&lt;br /&gt;
                       MA_ID, MID_PROJECT_SAVEAS,&lt;br /&gt;
                     MEnd,&lt;br /&gt;
                     MA_AddChild, MSeparator,&lt;br /&gt;
                     MEnd,&lt;br /&gt;
                     MA_AddChild, MItem(&amp;quot;About...&amp;quot;),&lt;br /&gt;
                       MA_ID, MID_PROJECT_ABOUT,&lt;br /&gt;
                     MEnd,&lt;br /&gt;
                     MA_AddChild, MSeparator,&lt;br /&gt;
                     MEnd,&lt;br /&gt;
                     MA_AddChild, MItem(&amp;quot;Quit&amp;quot;),&lt;br /&gt;
                       MA_ID, MID_PROJECT_QUIT,&lt;br /&gt;
                     MEnd,&lt;br /&gt;
                   MEnd,&lt;br /&gt;
                 MEnd;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Note|text=When using the MTitle() and MItem() macros, the label is passed as an argument to the macro itself rather than via an explicit MA_Label tag.}}&lt;br /&gt;
&lt;br /&gt;
We&#039;ll use the compact style in the rest of this document, except in cases where the more verbose one provides greater clarity.&lt;br /&gt;
&lt;br /&gt;
== Menu item keyboard shortcuts ==&lt;br /&gt;
&lt;br /&gt;
As with traditional Intuition menus, menuclass item objects can have a keyboard shortcut which is displayed next to the item&#039;s label. Shortcuts can have one or more characters; a shortcut of more than one character is also called &amp;quot;command string&amp;quot; (for instance, &amp;quot;ctrl z&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
A single-character shortcut is processed directly by Intuition, and appears at the right side of the menu item with an &amp;quot;Amiga key&amp;quot; symbol prepended to it. When using a command string of more than one character, however, Intuition will display it at the right side of the item (without the &amp;quot;Amiga key&amp;quot; symbol) but won&#039;t process the corresponding key combination; the application has to handle that on its own.&lt;br /&gt;
&lt;br /&gt;
There are two ways to specify a keyboard shortcut for a menuclass item object.&lt;br /&gt;
&lt;br /&gt;
You can pass it with the MA_Key attribute, as in the following example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
  item = MItem(&amp;quot;Save&amp;quot;),&lt;br /&gt;
           MA_ID, MID_SAVE,&lt;br /&gt;
           MA_Key, &amp;quot;S&amp;quot;,&lt;br /&gt;
         MEnd;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternatively, you can prepend it to the item&#039;s label string, separed by a &#039;|&#039; character, this way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
  item = MItem(&amp;quot;S|Save&amp;quot;),&lt;br /&gt;
           MA_ID, MID_SAVE,&lt;br /&gt;
         MEnd;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you opt for the latter approach, you may also use a NUL (&#039;\0&#039;) character in place of the &#039;|&#039;. This can prove useful when converting to BOOPSI menu usage an existing application employing such a method to embed shortcuts in its catalog strings.&lt;br /&gt;
&lt;br /&gt;
{{Note|text=The NUL byte solution only works for single-letter shortcuts and requires that no item in the menu tree has a label of just one letter, as any such label would be mistaken for a shortcut followed by random bytes. When you have single-letter labels, therefore, you cannot use this feature and must disable it for the whole tree. That&#039;s done by passing { MA_EmbeddedKey, FALSE } to the menu root object; this attribute will be inherited by all objects.}}&lt;br /&gt;
&lt;br /&gt;
== Inheritance of menu attributes ==&lt;br /&gt;
&lt;br /&gt;
There are some attributes of menuclass objects that are automatically inherited by all their descendants, except those for which they&#039;re explicitly set to some different value. For instance, if you want your menus to use a particular font, you only need to set the MA_TextAttr attribute for the menu root, and all items (and sub-items) of all menus will be displayed with that font.&lt;br /&gt;
&lt;br /&gt;
Any menuclass attribute which is automatically inherited from the parent object when not specified explicitly is clearly described as such, both in the autodoc and in the &amp;lt;intuition/menuclass.h&amp;gt; header file.&lt;br /&gt;
&lt;br /&gt;
== Attaching the menu tree to a window ==&lt;br /&gt;
&lt;br /&gt;
You can attach a menu tree built with menuclass to a window just like you would do with traditional non-BOOPSI menus, i.e. by calling SetMenuStrip(). Starting with Intuition V54, this function accepts a BOOPSI menu root object as the menu strip pointer.&lt;br /&gt;
Therefore, once you&#039;ve opened your window, you can simply do the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
  IIntuition-&amp;gt;SetMenuStrip(window,menustripobj);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and the menu tree will be ready to use, after undergoing an automatic layout to adapt itself to the window&#039;s screen.&lt;br /&gt;
&lt;br /&gt;
An alternative to the above is passing the menus to the window at opening time, via the new V54 tag WA_MenuStrip. This way your window will open with the menus already attached and laid out.&lt;br /&gt;
&lt;br /&gt;
When using window.class, you can achieve the same by passing the class-specific tag WINDOW_MenuStrip. (Starting with V54, window.class supports WA_MenuStrip as well, as an alias for WINDOW_MenuStrip.)&lt;br /&gt;
&lt;br /&gt;
== Detaching the menu tree from a window ==&lt;br /&gt;
&lt;br /&gt;
BOOPSI menus, like traditional ones, can be detached from a window at any time with ClearMenuStrip(). After having been detached, they can also be reattached by way of ResetMenuStrip(), as usual.&lt;br /&gt;
&lt;br /&gt;
In many cases, however, you don&#039;t need to remove BOOPSI menus as you would with old-style menus. Changing the selection state of &amp;quot;checkmarkable&amp;quot; items, as well as disabling or enabling single items or whole menus, may be performed by just setting the appropriate attribute of the menu object in question, regardless of whether or not the menus are in use. Any needed synchronization with Intuition is handled internally by menuclass.&lt;br /&gt;
&lt;br /&gt;
The above is generally true for all operations you can do on menuclass objects, such as changing their label, image, font or charset, or even their position in the menu tree. In fact, a BOOPSI menu tree even supports addition or removal of menus and items on-the-fly without any clearing and resetting of the menus.&lt;br /&gt;
&lt;br /&gt;
Whenever a change requires a relayout of some part of the menu tree, menuclass will automatically take care of that.&lt;br /&gt;
&lt;br /&gt;
Additionally, as of Intuition V54 it is no longer mandatory to remove the menus with ClearMenuStrip() before closing the window. CloseWindow() itself will take care of clearing the menus if needed (no matter if BOOPSI or old-style).&lt;br /&gt;
&lt;br /&gt;
{{Note|text=It is still required, however, to use ClearMenuStrip() to remove the menu strip of a window before setting a different one with SetMenuStrip().}}&lt;br /&gt;
&lt;br /&gt;
== Handling menu item selections by the user ==&lt;br /&gt;
&lt;br /&gt;
Upon receiving a menu pick event such as IDCMP_MENUPICK (or WMHI_MENUPICK if using window.class), your application can find out which menu items the user selected by invoking repeatedly the MM_NEXTSELECT method on the root object of the menu tree (i.e. the menu strip object). This will return all selected item IDs in sequence; in many cases there will be only one, but there may be more if the user performed multiple selection.&lt;br /&gt;
&lt;br /&gt;
Once all IDs have been retrieved, MM_NEXTSELECT will return NO_MENU_ID which means there are no more selections in the list.&lt;br /&gt;
&lt;br /&gt;
{{Note|text=MM_NEXTSELECT might even return NO_MENU_ID immediately on the first invocation; this would mean the user initiated and terminated a menu session without picking any item. Be prepared to handle this case.}}&lt;br /&gt;
&lt;br /&gt;
The MM_NEXTSELECT method uses the following mpNextSelect message structure:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
  struct mpNextSelect&lt;br /&gt;
  {&lt;br /&gt;
     uint32 MethodID;&lt;br /&gt;
     uint32 mpns_Reserved;&lt;br /&gt;
     uint32 mpns_CurrentID;&lt;br /&gt;
  };&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where MethodID is MM_NEXTSELECT, mpns_Reserved should be always set to zero, and mpns_CurrentID is the menu item ID the method returned on the previous invocation. To obtain the first ID in the selection list, pass NO_MENU_ID in the mpns_CurrentID field.&lt;br /&gt;
&lt;br /&gt;
An example of this method&#039;s usage would be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
  uint32 id = NO_MENU_ID;&lt;br /&gt;
&lt;br /&gt;
  while ((id = IIntuition-&amp;gt;IDoMethod(menustripobj,MM_NEXTSELECT,0,id)) != NO_MENU_ID)&lt;br /&gt;
  {&lt;br /&gt;
    switch (id)&lt;br /&gt;
    {&lt;br /&gt;
      /* Process menu selections */&lt;br /&gt;
&lt;br /&gt;
      case MID_PROJECT_OPEN:&lt;br /&gt;
        ...&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An alternative way to get the ID of the first (or only) selected menu item is to read it from the eim_LongCode field of the ExtIntuiMessage reporting the IDCMP_MENUPICK event (IntuiMessages generated by Intuition are always really ExtIntuiMessages, and can be cast as such). Since a menuclass object&#039;s ID is a 32-bit value, it can&#039;t fit in the 16-bit IntuiMessage.Code field, the value of which is currently undefined for IDCMP events coming from BOOPSI menus.&lt;br /&gt;
&lt;br /&gt;
The above example could thus be modified as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
  uint32 id = ((struct ExtIntuiMessage *)intuimsg)-&amp;gt;eim_LongCode;&lt;br /&gt;
&lt;br /&gt;
  while (id != NO_MENU_ID)&lt;br /&gt;
  {&lt;br /&gt;
    switch (id)&lt;br /&gt;
    {&lt;br /&gt;
      /* Process menu selections */&lt;br /&gt;
&lt;br /&gt;
      case MID_PROJECT_OPEN:&lt;br /&gt;
        ...&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    id = IIntuition-&amp;gt;IDoMethod(menustripobj,MM_NEXTSELECT,0,id);&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first approach is probably more convenient when using window.class since in that case you would need an additional IDCMP hook to access the ExtIntuiMessage in order to read its eim_LongCode field.&lt;br /&gt;
&lt;br /&gt;
== Handling menu help requests by the user ==&lt;br /&gt;
&lt;br /&gt;
If your window has the WA_MenuHelp attribute set to TRUE, and it&#039;s listening to IDCMP_MENUHELP events, the user can request help on a menu item or a menu title by pressing the [Help] key when that item or title is being highlighted by the mouse pointer. Upon reception of a menu help event, your application can easily find out the ID of the item or title the help request was about by querying the MA_MenuHelpID attribute of the menu root object.&lt;br /&gt;
&lt;br /&gt;
An example of this might be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
  uint32 help_id;&lt;br /&gt;
&lt;br /&gt;
  IIntuition-&amp;gt;GetAttr(MA_MenuHelpID,menustripobj,&amp;amp;help_id);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Note|text=The menu help ID value may be NO_MENU_ID, which means the [Help] key was pressed by the user while no menu item or title was highlighted.}}&lt;br /&gt;
&lt;br /&gt;
Menu help doesn&#039;t support multiple selection, so you have to deal with just one ID per event. As with menu pick, you can also retrieve the ID value by reading the ExtIntuiMessage.eim_LongCode field.&lt;br /&gt;
&lt;br /&gt;
== Menu pick hooks and menu help hooks ==&lt;br /&gt;
&lt;br /&gt;
Any menuclass object can have custom hooks associated to it with dedicated code to handle menu selections or help requests for that specific object. Such hooks can be invoked automatically by the main event handling loop every time a menu pick or menu help event occurs.&lt;br /&gt;
&lt;br /&gt;
The hook that handles menu item selections is specified through the MA_PickHook attribute; similarly, you can use the MA_HelpHook attribute to specify the hook handling menu help requests.&lt;br /&gt;
&lt;br /&gt;
These two attributes are inherited by all children of a menuclass object. This allows, if desired, to reuse the same hook for all the items of a menu (or all the sub-items of an item) simply by setting it for that menu (or item), rather than having to pass it to each child explicitly. Such a &amp;quot;common&amp;quot; hook could act as a dispatcher, calling the appropriate individual handling function according to the ID of the object it is invoked on.&lt;br /&gt;
&lt;br /&gt;
A menuclass object&#039;s pick or help hook will be invoked as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
  HookFunction(struct Hook *hook, Object *obj, struct MenuEventMessage *msg)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &#039;obj&#039; is the object itself and &#039;msg&#039; is a pointer to a MenuEventMessage structure.&lt;br /&gt;
&lt;br /&gt;
The MenuEventMessage structure is defined as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
  struct MenuEventMessage&lt;br /&gt;
  {&lt;br /&gt;
      uint32 StructSize;      /* For future expansion */&lt;br /&gt;
      uint32 EventType;       /* ET_MENUPICK or ET_MENUHELP */&lt;br /&gt;
      struct Window *Window;  /* Event window pointer */&lt;br /&gt;
      APTR UserData;          /* Custom data pointer */&lt;br /&gt;
  };&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The EventType field is useful to distinguish between the two types of event the hook could be invoked for, in case the same hook function is used for both. The Window field holds the address of the event&#039;s window (i.e. the window your menu tree is associated to) and the UserData field is used to pass to the hook any kind of context information it might require, as explained a little below.&lt;br /&gt;
&lt;br /&gt;
The pick or help hook can use the supplied information (menu object, window and custom data pointer) to process the event. The return value of the hook is not currently defined; it&#039;s recommended to set it to zero for future compatibility.&lt;br /&gt;
&lt;br /&gt;
To have menuclass invoke the pick hook of a menuclass object, your application needs to use the MM_HANDLEPICK method in its event loop.&lt;br /&gt;
&lt;br /&gt;
Like MM_NEXTSELECT, MM_HANDLEPICK can be invoked repeatedly to browse through all items in the menu selection chain. The difference is that this method only returns the ID of selected items that don&#039;t have a pick hook; whenever it finds a selected item whose pick hook is non-NULL, it invokes that hook and proceeds to the next item without returning anything. When there are no more items left in the menu selection chain, MM_HANDLEPICK returns NO_MENU_ID.&lt;br /&gt;
&lt;br /&gt;
The mechanism is exactly the same for help hooks, except in that case you have to use the MM_HANDLEHELP method, which only needs to invoked once as menu help events don&#039;t support multiple selection: if the menu object the user asked help about doesn&#039;t have a help hook, MM_HANDLEHELP will return its ID, otherwise it will invoke the hook and return NO_MENU_ID.&lt;br /&gt;
&lt;br /&gt;
Both the MM_HANDLEPICK and MM_HANDLEHELP methods should be invoked on the menu root object, and use the same message structure:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
  struct mpHandleEvent&lt;br /&gt;
  {&lt;br /&gt;
      uint32 MethodID;&lt;br /&gt;
      uint32 mphe_Reserved;&lt;br /&gt;
      uint32 mphe_CurrentID;&lt;br /&gt;
      struct Window *mphe_Window;&lt;br /&gt;
      APTR mphe_UserData;&lt;br /&gt;
  };&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where MethodID is MM_HANDLEPICK or MM_HANDLEHELP, mphe_Reserved should always be set to zero, and mphe_CurrentID is the ID returned by the method&#039;s previous invocation (ignored by MM_HANDLEHELP; pass NO_MENU_ID on the first invocation of MM_HANDLEPICK). Additionally, you should store the event&#039;s window address in mphe_Window (e.g. IntuiMessage-&amp;gt;IDCMPWindow) and any custom data to be passed to the pick or help hook in mphe_UserData; your hook will be able to read back this information from the MenuEventMessage.&lt;br /&gt;
&lt;br /&gt;
A simple example of how to take advantage of the custom pick hook feature might be the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
  uint32 id = NO_MENU_ID;&lt;br /&gt;
&lt;br /&gt;
  while ((id = IIntuition-&amp;gt;IDoMethod(menustripobj,MM_HANDLEPICK,&lt;br /&gt;
                                                  0,&lt;br /&gt;
                                                  id,&lt;br /&gt;
                                                  imsg-&amp;gt;IDCMPWindow,&lt;br /&gt;
                                                  mycustomdata)) != NO_MENU_ID)&lt;br /&gt;
  {&lt;br /&gt;
    /* This selected menu object doesn&#039;t have&lt;br /&gt;
     * a pick hook, so let&#039;s handle it here.&lt;br /&gt;
     */&lt;br /&gt;
    switch (id)&lt;br /&gt;
    {&lt;br /&gt;
      /* Process menu selections */&lt;br /&gt;
&lt;br /&gt;
      case MID_PROJECT_OPEN:&lt;br /&gt;
        ...&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
It goes without saying that if none of your application&#039;s menuclass object has a pick hook or help hook, you never need to invoke MM_HANDLEPICK/MM_HANDLEHELP in your event handling code; you can just use the simpler MM_NEXTSELECT method and MA_MenuHelpID attribute instead, as covered in previous subsections.&lt;br /&gt;
&lt;br /&gt;
== Retrieving a menuclass object&#039;s address from its ID number ==&lt;br /&gt;
&lt;br /&gt;
Once you have found out which menu item was picked by the user by examining its ID, you may want to do some operations on the item object itself, and thus need its actual address. One way to achieve this could be to keep a look-up table in your application, initialized as the menu tree gets built, and using the IDs as indices. For instance, something like the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
  ...&lt;br /&gt;
  MA_AddChild, mtable[MID_PROJECT_OPEN] = MItem(&amp;quot;Open...&amp;quot;),&lt;br /&gt;
    MA_ID, MID_PROJECT_OPEN,&lt;br /&gt;
  MEnd,&lt;br /&gt;
  MA_AddChild, mtable[MID_PROJECT_SAVE] = MItem(&amp;quot;Save&amp;quot;),&lt;br /&gt;
    MA_ID, MID_PROJECT_SAVE,&lt;br /&gt;
  MEnd,&lt;br /&gt;
  ...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The drawbacks of such an approach are increased memory consumption and reduced code readability. A simpler solution is offered by menuclass in the form of the MM_FINDID method. This uses the mpFindID structure, defined as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
  struct mpFindID&lt;br /&gt;
  {&lt;br /&gt;
      uint32 MethodID;&lt;br /&gt;
      uint32 mpfi_Reserved;&lt;br /&gt;
      uint32 mpfi_ID;&lt;br /&gt;
  };&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where MethodID is MM_FINDID, mpfi_Reserved should always be set to zero, while mpfi_ID is the ID of the menu object whose address you&#039;re looking for. Here&#039;s a simple example of this method&#039;s invocation on the menu root object:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
  m_obj = (Object *)IIntuition-&amp;gt;IDoMethod(menustripobj,MM_FINDID,0,id);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If a menu object with the specified ID is found within the menu tree, MM_FINDID will return its address, otherwise it will return NULL.&lt;br /&gt;
&lt;br /&gt;
The MM_FINDID method doesn&#039;t actually need to be invoked on the menu root as in the above example. It just searches for an object having a given ID within the menu (sub-)tree hanging from the object it&#039;s invoked on. So if you already know the address of an object whose local sub-tree contains the one you want, it is possible to invoke MM_FINDID directly on that object and restrict the search to only a part of the menu tree.&lt;br /&gt;
&lt;br /&gt;
Invoking the MM_FINDID method is the BOOPSI equivalent of calling ItemAddress() with traditional menus.&lt;br /&gt;
&lt;br /&gt;
== Enabling and disabling menus and menu items ==&lt;br /&gt;
&lt;br /&gt;
By default, a BOOPSI menu or item is enabled, meaning it looks clearly readable and can be selected by the user. When disabled, it is instead rendered with low contrast or a recessed appearance and is not selectable.&lt;br /&gt;
&lt;br /&gt;
The MA_Disabled attribute is used to control the enable state of BOOPSI menu or item objects. It is possible to disable a menuclass object right from the start by passing { MA_Disabled, TRUE } to NewObject(), or change the object&#039;s enable state later at any time via SetAttrs(). Setting MA_Disabled to TRUE or FALSE is the BOOPSI equivalent of calling OnMenu() or OffMenu() on old-style menus.&lt;br /&gt;
&lt;br /&gt;
Disabling a menu or a menu item will make all of its children show up disabled as well, down to the deepest sub-menu levels. Additionally, you can disable all your menus at once (i.e. make the entire menu tree disabled and not selectable) simply by disabling the menu strip object.&lt;br /&gt;
&lt;br /&gt;
Another way to examine and modify the enable state of a menu or menu item is to invoke the MM_GETSTATE and MM_SETSTATE methods (see below for more on this).&lt;br /&gt;
&lt;br /&gt;
== Selection state of toggle select and mutual exclude items ==&lt;br /&gt;
&lt;br /&gt;
Whenever a toggle select or mutual exclude menu item is picked by the user, you can examine its selection state by reading the item&#039;s MA_Selected attribute. If its value is TRUE, the item is currently selected (checked) and is displayed with some small checkmark or radio button symbol drawn in front of it.&lt;br /&gt;
&lt;br /&gt;
You can also programmatically change the selection state of this kind of items at any time by setting the value of MA_Selected with SetAttrs(), without having to clear and then reset the menu strip as you would with non-BOOPSI menus.&lt;br /&gt;
&lt;br /&gt;
This attribute has no meaning for action items, i.e. items that don&#039;t represent the &amp;quot;on&amp;quot; or &amp;quot;off&amp;quot; state of some option.&lt;br /&gt;
&lt;br /&gt;
Another way to examine and modify the selection state of a menu or menu item is to invoke the MM_GETSTATE and MM_SETSTATE methods (see below for more on this).&lt;br /&gt;
&lt;br /&gt;
== Methods for controlling the enable and selection state of menu items ==&lt;br /&gt;
&lt;br /&gt;
It is possible to examine and modify the enable state of a menu or menu item by invoking the MM_GETSTATE and MM_SETSTATE methods. These may prove more handy in many cases since they take an ID number to specify the target object instead of the object&#039;s actual address. This means they can be directly fed the result of MM_NEXTSELECT without having to go through MM_FINDID first.&lt;br /&gt;
&lt;br /&gt;
Both these methods use the bitmask constants MS_CHECKED and MS_DISABLED to read or modify the corresponding MA_Selected and MA_Disabled attributes.&lt;br /&gt;
&lt;br /&gt;
The MM_GETSTATE method uses the following message structure:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
  struct mpGetState&lt;br /&gt;
  {&lt;br /&gt;
      uint32 MethodID;&lt;br /&gt;
      uint32 mpgs_Reserved;&lt;br /&gt;
      uint32 mpgs_ID;&lt;br /&gt;
  };&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where MethodID is MM_GETSTATE, mpgs_Reserved should always be set to zero, and mpgs_ID is the ID number of the menuclass object whose state you want to read. The method should be invoked on the menu root object (or on the parent of the target object, if you have its address) and will return a bit mask whose value can be MS_CHECKED, MS_DISABLED, both constants ORed together, or zero. For instance, if MS_CHECKED is set in the method&#039;s return value it means that the object&#039;s MA_Selected attribute is currently TRUE.&lt;br /&gt;
&lt;br /&gt;
The MM_SETSTATE method uses the following message structure:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
  struct mpSetState&lt;br /&gt;
  {&lt;br /&gt;
      uint32 MethodID;&lt;br /&gt;
      uint32 mpss_Reserved;&lt;br /&gt;
      uint32 mpss_ID;&lt;br /&gt;
      uint32 mpss_ApplyMask;&lt;br /&gt;
      uint32 mpss_StateMask;&lt;br /&gt;
  };&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where the first three fields are analogous to those of the mpGetState structure while mpss_ApplyMask is used to specify which attribute(s) should be modified, and mpss_StateMask contains the new values. For instance, if MS_DISABLED is set in mpss_ApplyMask, but not in mpss_StateMask, the object will become enabled as its MA_Disabled attribute will be set to FALSE. If MS_CHECKED is cleared in the mpss_ApplyMask field, on the other hand, the object&#039;s selection state will stay unchanged no matter what the value of mpss_StateMask is.&lt;br /&gt;
&lt;br /&gt;
== Disposing of the menu tree ==&lt;br /&gt;
&lt;br /&gt;
Due to its dynamic nature, usually a BOOPSI menu tree doesn&#039;t need to be freed and rebuilt by your application on environment changes or each time it has to undergo some significant modification. You may for instance reuse the same menu tree on different screens (as long as it&#039;s used on one screen at a time).&lt;br /&gt;
&lt;br /&gt;
This means that all important state information stored in the menu tree such as which items are checked, disabled, etc. is never lost while the application is running, and that the menu tree can be disposed of just once on program&#039;s exit.&lt;br /&gt;
&lt;br /&gt;
To free an entire menu tree, you just have to call DisposeObject() on its root object. Whatever disposable object you attached to some menu item, such as e.g. a BOOPSI image, will be freed as well unless you asked not to do so.&lt;br /&gt;
&lt;br /&gt;
= Further menuclass features =&lt;br /&gt;
&lt;br /&gt;
This section will outline a number of attributes and methods giving access to some more specialized functionality of menuclass.&lt;br /&gt;
&lt;br /&gt;
== Specifying the menu font ==&lt;br /&gt;
&lt;br /&gt;
Each menu item object can be displayed in its own font and size, although this is strongly discouraged as such an arrangement would look quite unprofessional. Still, if you for any reason need to set the font used by a menu item, you can do so with the MA_TextAttr attribute.&lt;br /&gt;
&lt;br /&gt;
The font specified this way will be opened and closed by menuclass as needed.&lt;br /&gt;
&lt;br /&gt;
If you set MA_TextAttr for a menuclass object, it will be inherited by all of its children. To specify a font for the entire menu tree, therefore, just set MA_TextAttr for the menu root object.&lt;br /&gt;
&lt;br /&gt;
Whenever there isn&#039;t any specific reason to do otherwise, it&#039;s recommended not to use MA_TextAttr at all and just let the menus be displayed in the font that was chosen in the user&#039;s preferences for the screen they appear on.&lt;br /&gt;
&lt;br /&gt;
== Adding images to menu items ==&lt;br /&gt;
&lt;br /&gt;
A BOOPSI menu item can have an image displayed at the left side of (or in place of) the item&#039;s label. The image is specified through the MA_Image attribute; it may be either traditional or BOOPSI.&lt;br /&gt;
&lt;br /&gt;
The item&#039;s height is adjusted if needed to make enough room for the image.&lt;br /&gt;
&lt;br /&gt;
If the image is BOOPSI, it will be automatically disposed of when the menu item object is; to avoid that, you should set the item&#039;s MA_FreeImage attribute to FALSE. However, if you want to prevent automatic disposal for ALL images in the menu tree, it is more practical to set MA_FreeImage to FALSE for the menu root object since this way it will be inherited by all objects.&lt;br /&gt;
&lt;br /&gt;
If the menu item has no label (i.e. it&#039;s an image-only item), you can still use MA_TextAttr to specify the font used for its keyboard shortcut character.&lt;br /&gt;
&lt;br /&gt;
== Hiding menus and menu items ==&lt;br /&gt;
&lt;br /&gt;
Any member of a BOOPSI menu tree can be hidden or revealed again at any time by your application. A hidden menuclass object is still physically present in the menu tree, but does not appear on the screen when menus are displayed, as if it had been actually removed.&lt;br /&gt;
&lt;br /&gt;
The MA_Hidden attribute is used to control the hiding of a BOOPSI menu or item objects. It is possible to make a menu or item hidden right from the start by passing { MA_Hidden, TRUE } to NewObject(), or change the object&#039;s hiding state later via SetAttrs().&lt;br /&gt;
&lt;br /&gt;
Hiding a menu or a menu item will (obviously) hide all of its children as well. Unlike disabling, however, you cannot hide the menu strip object -- if you want to make the entire menu tree disappear, just call ClearMenuStrip().&lt;br /&gt;
&lt;br /&gt;
== Dynamic menu localization ==&lt;br /&gt;
&lt;br /&gt;
So far, we&#039;ve only examined the simple case where you pass an actual string as the value of a menuclass object&#039;s MA_Label attribute. There is however another possibility, and that is to specify a numeric index as MA_Label&#039;s value, which is later used to look up the appropriate string in the currently open catalog.&lt;br /&gt;
&lt;br /&gt;
To be able to pass an integer value for MA_Label instead of a string, you need to tell menuclass what is the numeric range of string IDs. Any value outside of that range will be considered a string, and used directly as such. Values lying in the range, on the other hand, will be treated as catalog indices. The string ID range is specified with the MA_MinStringID and MA_MaxStringID attributes. (By default, the string ID range is empty and MA_Label is always interpreted as a string.)&lt;br /&gt;
&lt;br /&gt;
Whenever an object&#039;s MA_Label attribute is actually a numeric index, its value is passed on each menu layout to a &amp;quot;localization hook&amp;quot; which will convert it to the correct string for the current language and charset.&lt;br /&gt;
&lt;br /&gt;
The localization hook (aka string hook) is supplied by your application via the MA_StringHook attribute. You can simply set it for the root object, and it will be inherited by all objects in the menu tree.&lt;br /&gt;
&lt;br /&gt;
Your hook will be invoked as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
  HookFunction(struct Hook *hook, Object *obj, struct MenuStringMessage *msg)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &#039;obj&#039; is the menu or item the string ID to be converted belongs to, and &#039;msg&#039; is a pointer to a MenuStringMessage structure (see below for definition) which carries the string ID.&lt;br /&gt;
&lt;br /&gt;
You can also specify the address of an open catalog and/or a charset by setting the MA_Catalog and MA_CharSet attributes for the menu root object; if supplied, this information is also passed back to the hook in the MenuStringMessage.&lt;br /&gt;
&lt;br /&gt;
The MenuStringMessage structure is defined as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct MenuStringMessage&lt;br /&gt;
{&lt;br /&gt;
    uint32 StructSize;        /* For future expansion */&lt;br /&gt;
    uint32 StringID;          /* The string ID number */&lt;br /&gt;
    struct Catalog *Catalog;  /* Catalog pointer, may be NULL */&lt;br /&gt;
    uint32 CharSet;           /* Charset number, may be zero */&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Your string hook should return the correct catalog string for the passed string ID, or a default string if no catalog is available.&lt;br /&gt;
&lt;br /&gt;
{{Note|text=All of the above is equally valid for the MA_Key attribute, which can be a string ID instead of an actual string just like MA_Label. Its string ID range is the same one of MA_Label (as defined by MA_MinStringID and MA_MaxStringID).}}&lt;br /&gt;
&lt;br /&gt;
{{Note|title=Also Note|text=If you don&#039;t use a string hook, MA_Label and MA_Key should always be real strings and not numeric IDs, otherwise they&#039;ll get converted by menuclass to &amp;quot;????&amp;quot;, which isn&#039;t very meaningful. The same will happen if the string hook returns a NULL string pointer.}}&lt;br /&gt;
&lt;br /&gt;
== Adding and removing menus and menu items ==&lt;br /&gt;
&lt;br /&gt;
A BOOPSI menu tree built with menuclass allows for dynamic addition and removal of menus and items at any time. As with other modifications, there&#039;s no need to detach the menu tree from the window in order to perform these operations; it&#039;s menuclass that takes care of synchronizing each change with Intuition and doing any necessary relayout afterwards.&lt;br /&gt;
&lt;br /&gt;
To add a child to a menuclass object, you can simply call SetAttrs() to pass it the MA_AddChild tag with the address of the new child as data, the same way you would at OM_NEW time.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s an example of adding a sub-item to an item:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
  /* Append a new entry to our &amp;quot;recent files&amp;quot; sub-menu */&lt;br /&gt;
&lt;br /&gt;
  new_item = MItem(filename), MA_ID, new_id++, MEnd;&lt;br /&gt;
&lt;br /&gt;
  IIntuition-&amp;gt;SetAttrs(recentfiles_itemobj,MA_AddChild,new_item,TAG_END);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A NULL pointer can safely be passed with MA_AddChild, and is simply ignored.&lt;br /&gt;
&lt;br /&gt;
{{Note|text=In this example we&#039;re using a simple counter variable to generate an unique ID for each new sub-item -- we don&#039;t care about the ID value itself, we simply want to take notice if the item gets selected, and be able to retrieve its address with MM_FINDID whenever needed. This requires the new item to have a valid and unique ID number.}}&lt;br /&gt;
&lt;br /&gt;
Just like they can be added, menus and menu items can also be removed from the menu tree as needed. This is achieved by passing the MA_RemoveChild tag to the parent menu object via SetAttrs(), with the address of the child as data.&lt;br /&gt;
&lt;br /&gt;
For instance, we could remove an item from a menu this way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
  /* Close a window and remove its entry from our &amp;quot;open windows&amp;quot; menu */&lt;br /&gt;
&lt;br /&gt;
  id = (uint32)window-&amp;gt;UserData;  /* We stored the menu item&#039;s ID there */&lt;br /&gt;
&lt;br /&gt;
  IIntuition-&amp;gt;CloseWindow(window);&lt;br /&gt;
&lt;br /&gt;
  item = (Object *)IIntuition-&amp;gt;IDoMethod(openwindows_menuobj,MM_FINDID,0,id);&lt;br /&gt;
&lt;br /&gt;
  IIntuition-&amp;gt;SetAttrs(openwindows_menuobj,MA_RemoveChild,item,TAG_END);&lt;br /&gt;
&lt;br /&gt;
  IIntuition-&amp;gt;DisposeObject(item);  /* Accepts a NULL argument */&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As with MA_AddChild, you can safely pass a NULL pointer with MA_RemoveChild.&lt;br /&gt;
&lt;br /&gt;
Another way to perform addition and removal of children with menuclass objects is to use rootclass&#039; OM_ADDMEMBER and OM_REMMEMBER methods. The above examples could thus be rewritten by replacing the SetAttrs() calls with:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
  IIntuition-&amp;gt;IDoMethod(recentfiles_itemobj,OM_ADDMEMBER,new_item);&lt;br /&gt;
&lt;br /&gt;
  IIntuition-&amp;gt;IDoMethod(openwindows_menuobj,OM_REMMEMBER,item);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you would when dealing with Exec lists, you must be careful to avoid adding or removing the same child twice, or removing a child which was never added in the first place, since doing so will cause memory corruption.&lt;br /&gt;
&lt;br /&gt;
== Browsing through all children of a menu object ==&lt;br /&gt;
&lt;br /&gt;
You can obtain the addresses of all children of a menuclass object in sequence by invoking the MM_NEXTCHILD method in a loop. Once all the object&#039;s children have been been retrieved, MM_NEXTCHILD will return NULL to signal there are no more children.&lt;br /&gt;
&lt;br /&gt;
The MM_NEXTCHILD method uses the following message structure:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
  struct mpNextChild&lt;br /&gt;
  {&lt;br /&gt;
    uint32 MethodID;&lt;br /&gt;
    uint32 mpnc_Reserved;&lt;br /&gt;
    Object *mpnc_Current;&lt;br /&gt;
  };&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where MethodID is MM_NEXTCHILD, mpnc_Reserved should always be set to zero, and mpnc_Current is the child object address the method did return on the previous invocation. Pass NULL in mpnc_Current to get the address of the first child.&lt;br /&gt;
&lt;br /&gt;
An example of a loop retrieving all items of a menu:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
  Object *obj = NULL;&lt;br /&gt;
&lt;br /&gt;
  while ((obj = (Object *)IIntuition-&amp;gt;IDoMethod(menuobj,MM_NEXTCHILD,0,obj)) != NULL)&lt;br /&gt;
  {&lt;br /&gt;
    /* Do something with the item object */&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you use MM_NEXTCHILD in a loop to remove an object&#039;s children one by one, be careful not to pass the method the address of an already removed object.&lt;br /&gt;
&lt;br /&gt;
The correct way to do a sequential child removal is the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
  while ((obj = (Object *)IIntuition-&amp;gt;IDoMethod(menuobj,MM_NEXTCHILD,0,NULL)) != NULL)&lt;br /&gt;
  {&lt;br /&gt;
     IIntuition-&amp;gt;IDoMethod(menuobj,OM_REMMEMBER,obj);&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is analogous to performing a RemHead() loop on an Exec list.&lt;br /&gt;
&lt;br /&gt;
== Scanning the menu tree ==&lt;br /&gt;
&lt;br /&gt;
You can perform a scan of the whole menu tree, or even just a subsection of it, and have a custom function called on each object that is part of it. This makes it possible to implement any kind of operation that is not already provided by the existing menuclass methods.&lt;br /&gt;
&lt;br /&gt;
To scan a menu (sub-)tree, you invoke the MM_SCAN method on its root object and specify a callback function and some parameters that will be passed back to it on each call. The MM_SCAN method uses the following message structure:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
  struct mpScan&lt;br /&gt;
  {&lt;br /&gt;
    uint32 MethodID;&lt;br /&gt;
    uint32 mps_Reserved;&lt;br /&gt;
    struct Hook *mps_Hook;&lt;br /&gt;
    uint32 mps_Args[4];&lt;br /&gt;
  };&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where MethodID is MM_SCAN, mps_Reserved should always be set to zero, mps_Hook is a pointer to your custom hook, and mps_Args[0] to mps_Args[3] are (optional) arguments for the hook&#039;s function. Your hook will be invoked as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
  HookFunction(struct Hook *hook, Object *obj, struct MenuScanMessage *msg)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &#039;obj&#039; is a menuclass object (whose exact type you can inspect by reading its MA_Type attribute) and &#039;msg&#039; is a pointer to a MenuScanMessage structure.&lt;br /&gt;
&lt;br /&gt;
The MenuScanMessage structure is defined as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
  struct MenuScanMessage&lt;br /&gt;
  {&lt;br /&gt;
    uint32 StructSize;  /* For future expansion */&lt;br /&gt;
    int32 Level;        /* How deep we are in the menu tree */&lt;br /&gt;
    uint32 Args[4];     /* Custom arguments */&lt;br /&gt;
  };&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The Level field indicates the depth in the tree of the current object, starting from -1 for the root object. The four Args variables hold the same values which were passed upon invocation of the MM_SCAN method and can be used to feed your custom arguments back to the hook.&lt;br /&gt;
&lt;br /&gt;
If your hook returns a non-zero value, the scan stops with the method returning the address of the object on which it stopped. If the hook always returns zero, all objects are scanned and the MM_SCAN method returns NULL.&lt;br /&gt;
&lt;br /&gt;
An example of this method&#039;s usage could be the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
  /* A simple function to count how many items a menu has, using MM_SCAN */&lt;br /&gt;
&lt;br /&gt;
  uint32 HookFunction(struct Hook *h, Object *o, struct MenuScanMessage *msg)&lt;br /&gt;
  {&lt;br /&gt;
     if (msg-&amp;gt;Level == 1)&lt;br /&gt;
        *((uint32 *)msg-&amp;gt;Args[0]) += 1;&lt;br /&gt;
     return (0);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  uint32 CountMenuItems(Object *menuobj)&lt;br /&gt;
  {&lt;br /&gt;
     struct Hook hook;&lt;br /&gt;
     uint32 count = 0;&lt;br /&gt;
&lt;br /&gt;
     memset(&amp;amp;hook,0,sizeof(struct Hook));&lt;br /&gt;
&lt;br /&gt;
     hook.h_Entry = (HOOKFUNC)HookFunction;&lt;br /&gt;
&lt;br /&gt;
     IIntuition-&amp;gt;IDoMethod(menuobj,MM_SCAN,0,&amp;amp;hook,&amp;amp;count,0,0,0);&lt;br /&gt;
&lt;br /&gt;
     return (count);&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this example we pass as the only custom argument the address of an variable which, once the MM_SCAN method returns, will hold the amount of children of the specified menu object. In the hook function we check that the object&#039;s level is 1, to make sure we only take it into account if it is a direct child of a menu (menus have a level of zero), rather than being a sub-item of an item, or even the menu object itself on which the method is invoked.&lt;br /&gt;
&lt;br /&gt;
== Generating a whole menu (sub-)tree from a single tag list ==&lt;br /&gt;
&lt;br /&gt;
So far we have only seen menu trees built by way of a series of nested calls to NewObject(). This is certainly a working approach to putting together a tree of BOOPSI objects organized in a hierarchy. Still, it presents a few drawbacks:&lt;br /&gt;
&lt;br /&gt;
* It can consume a significant amount of stack with very deep trees;&lt;br /&gt;
* It may produce code which is hard to read unless special macros are used;&lt;br /&gt;
* It makes error checking not very easy.&lt;br /&gt;
&lt;br /&gt;
All in all, nesting NewObject() calls is quite acceptable with relatively small menu trees, while it can become less manageable as the tree&#039;s size grows.&lt;br /&gt;
&lt;br /&gt;
A different technique for building menu trees, which attempts to overcome these issues, is provided by menuclass&#039; MM_NEWMENU method. This allows to generate an entire tree, or a sub-tree, out of a flat description of its structure given in the form of a single tag list.&lt;br /&gt;
&lt;br /&gt;
The MM_NEWMENU method uses the following message structure:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
  struct mpNewMenu&lt;br /&gt;
  {&lt;br /&gt;
    uint32 MethodID;&lt;br /&gt;
    uint32 mpnm_Reserved;&lt;br /&gt;
    struct TagItem *mpnm_AttrList;&lt;br /&gt;
  };&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where MethodID is MM_NEWMENU, mpnm_Reserved should always be set to zero, and mpnm_AttrList is the tag list describing the menu tree to be generated.&lt;br /&gt;
&lt;br /&gt;
Said tag list is made up for the most part of the usual menuclass tags that are used to specify attributes of the individual objects; however, the menu objects themselves are introduced by special tags prepended with NM_ which are actually directives for the method.&lt;br /&gt;
&lt;br /&gt;
MM_NEWMENU understands three directives: NM_Menu / NM_Item, indicating to add a new menu or item object at the current level (the tag data is the object&#039;s text label), and NM_SubItems, indicating to move down or up by one level before the next item object is added. If the tag data of NM_SubItems is SI_BEGIN, the next item will become a child of the most recent one added (i.e. we move down by one level); if it is SI_END, the next item will become a sibling of the most recent one&#039;s parent (i.e. we move up by one level).&lt;br /&gt;
&lt;br /&gt;
{{Note|text=NM_SubItems is not needed to add menus to a menu strip object, nor to add items to a menu object -- its only purpose is to act as a &amp;quot;delimiter&amp;quot; for a list of sub-items of an item object.}}&lt;br /&gt;
&lt;br /&gt;
Any menuclass tag that is encountered in the tag list is passed as an attribute to the most recently added object.&lt;br /&gt;
&lt;br /&gt;
The method should be invoked on an existing menuclass object, which in case of success will become the new tree&#039;s root. MM_NEWMENU returns FALSE to indicate failure, the exact reasons for which can be inspected through the MA_ErrorCode and MA_ErrorTagItem tags. See &amp;lt;intuition/menuclass.h&amp;gt; for a list of menuclass error codes and their explanation.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s a simple example to illustrate the method&#039;s usage:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
  /* Service function allowing to pass varargs tag list to MM_NEWMENU&lt;br /&gt;
   */&lt;br /&gt;
  static BOOL VARARGS68K DoNewMenu(Object *root, ...)&lt;br /&gt;
  {&lt;br /&gt;
    va_list ap;&lt;br /&gt;
    struct TagItem *tags;&lt;br /&gt;
    BOOL result;&lt;br /&gt;
&lt;br /&gt;
    va_startlinear(ap,root);&lt;br /&gt;
    tags = (struct TagItem *)va_getlinearva(ap,struct TagItem *);&lt;br /&gt;
    result = IIntuition-&amp;gt;IDoMethod(root,MM_NEWMENU,0,tags);&lt;br /&gt;
    va_end(ap);&lt;br /&gt;
&lt;br /&gt;
    return (result);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  /* Build a menu tree with the MM_NEWMENU method&lt;br /&gt;
   */&lt;br /&gt;
  Object *BuildMenuTree(void)&lt;br /&gt;
  {&lt;br /&gt;
    Object *menustripobj;&lt;br /&gt;
    uint32 success, error;&lt;br /&gt;
    struct TagItem *error_ti;&lt;br /&gt;
&lt;br /&gt;
    menustripobj = IIntuition-&amp;gt;NewObject(NULL,&amp;quot;menuclass&amp;quot;,MA_Type,T_ROOT,TAG_END);&lt;br /&gt;
&lt;br /&gt;
    if (menustripobj)&lt;br /&gt;
    {&lt;br /&gt;
      success = DoNewMenu(menustripobj,&lt;br /&gt;
        MA_ErrorCode, &amp;amp;error,&lt;br /&gt;
        MA_ErrorTagItem, &amp;amp;error_ti,&lt;br /&gt;
        NM_Menu, &amp;quot;Project&amp;quot;,         MA_ID, MID_PROJECT,&lt;br /&gt;
          NM_Item, &amp;quot;O|Open&amp;quot;,        MA_ID, MID_OPEN,&lt;br /&gt;
          NM_Item, &amp;quot;S|Save&amp;quot;,        MA_ID, MID_SAVE,&lt;br /&gt;
          NM_Item, &amp;quot;A|Save as...&amp;quot;,  MA_ID, MID_SAVEAS,&lt;br /&gt;
          NM_Item, ML_SEPARATOR,&lt;br /&gt;
          NM_Item, &amp;quot;Q|Quit&amp;quot;,        MA_ID, MID_QUIT,&lt;br /&gt;
        NM_Menu, &amp;quot;Options&amp;quot;,         MA_ID, MID_OPTIONS,&lt;br /&gt;
          NM_Item, &amp;quot;F|Font...&amp;quot;,     MA_ID, MID_FONT,&lt;br /&gt;
          NM_Item, &amp;quot;Style&amp;quot;,         MA_ID, MID_STYLE,&lt;br /&gt;
            NM_SubItems, SI_BEGIN,&lt;br /&gt;
            NM_Item, &amp;quot;B|Bold&amp;quot;,      MA_ID, MID_BOLD,      MA_Toggle, TRUE,&lt;br /&gt;
            NM_Item, &amp;quot;I|Italic&amp;quot;,    MA_ID, MID_ITALIC,    MA_Toggle, TRUE,&lt;br /&gt;
            NM_Item, &amp;quot;U|Underline&amp;quot;, MA_ID, MID_UNDERLINE, MA_Toggle, TRUE,&lt;br /&gt;
            NM_SubItems, SI_END,&lt;br /&gt;
          NM_Item, &amp;quot;W|Word wrap&amp;quot;,   MA_ID, MID_WORDWRAP,  MA_Toggle, TRUE,&lt;br /&gt;
        TAG_END);&lt;br /&gt;
&lt;br /&gt;
      if (!success)&lt;br /&gt;
      {&lt;br /&gt;
        IDOS-&amp;gt;Printf(&amp;quot;Failed with error %ld, at tag %08lX\n&amp;quot;,error,error_ti-&amp;gt;ti_Tag);&lt;br /&gt;
        IIntuition-&amp;gt;IDoMethod(menustripobj,MM_DELETEMENU,0);&lt;br /&gt;
        IIntuition-&amp;gt;DisposeObject(menustripobj);&lt;br /&gt;
        menustripobj = NULL;&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return (menustripobj);&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this example we make use of a small service function to pass the tag list on the stack as varargs; of course the tag list can also be allocated statically. Also, the above tree is rather small for the sake of keeping the example short, so it does not benefit much from using MM_NEWMENU instead of nested NewObject() calls, but obviously the same technique can be used to build trees of any size.&lt;br /&gt;
&lt;br /&gt;
As you can see, with MM_NEWMENU you can write compact and quite readable code to describe your menu trees, without having to resort to using macros on top of nested calls. The tree&#039;s description can even be made somewhat reminiscent of traditional NewMenu arrays as used with GadTools, which may look more familiar to long-time developers.&lt;br /&gt;
&lt;br /&gt;
To free a menu (sub-)tree generated with MM_NEWMENU, you invoke MM_DELETEMENU on the root object. This method uses the following message structure:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
  struct mpDeleteMenu&lt;br /&gt;
  {&lt;br /&gt;
    uint32 MethodID;&lt;br /&gt;
    uint32 mpdm_Reserved;&lt;br /&gt;
  };&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where MethodID is MM_DELETEMENU, and mpdm_Reserved should (as usual) be set to zero. Therefore, the correct way to invoke the method is the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
  IIntuition-&amp;gt;IDoMethod(menustripobj,MM_DELETEMENU,0);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Note|text=This call only disposes of all of the object&#039;s children, not of the root object itself. This way you can reuse the object in case you need to build another menu tree with MM_NEWMENU. To free the root object (and its children if you didn&#039;t already do that), simply use DisposeObject().}}&lt;/div&gt;</summary>
		<author><name>Costel Mincea</name></author>
	</entry>
	<entry>
		<id>https://wiki.amigaos.net/w/index.php?title=Preferences&amp;diff=12565</id>
		<title>Preferences</title>
		<link rel="alternate" type="text/html" href="https://wiki.amigaos.net/w/index.php?title=Preferences&amp;diff=12565"/>
		<updated>2025-01-26T19:36:36Z</updated>

		<summary type="html">&lt;p&gt;Costel Mincea: Text replacement - &amp;quot;&amp;lt;syntaxhighlight&amp;gt;&amp;quot; to &amp;quot;&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{WIP}}&lt;br /&gt;
== Preferences ==&lt;br /&gt;
&lt;br /&gt;
To make the Amiga operating system easily configurable by the user, the OS comes with a family of editors and associated data files known collectively as Preferences. Preferences allows the user to set system-wide configuration options such as the printer driver to use, serial port baud rate and other items. To make an application appealing to the user, the system-wide Preferences settings should be respected as much as possible by applications. This article describes how to use the Preferences system in your programs.&lt;br /&gt;
&lt;br /&gt;
== Preferences Editors and Storage ==&lt;br /&gt;
&lt;br /&gt;
In AmigaOS there can be any number of Preferences editors each with its own separate configuration file covering a specific area. All these Preferences editors have the same look and feel. Using separate Preferences editors and configuration files allows for adding new Preferences items (and editors) in future versions of the OS.&lt;br /&gt;
&lt;br /&gt;
Preferences are store in various &amp;quot;.prefs&amp;quot; files located in the &amp;quot;ENV:sys&amp;quot; and &amp;quot;ENVARC:sys&amp;quot; directories. Preferences options currently in use are located in &amp;quot;ENV:sys&amp;quot;. Permanent, saved copies of Preferences files are stored in &amp;quot;ENVARC:sys&amp;quot;. These are copied to &amp;quot;ENV:&amp;quot; on an as-needed basis. Applications may also store their own preference files in &amp;quot;ENV:&amp;quot; but should use a sub-directory for that purpose.&lt;br /&gt;
&lt;br /&gt;
Currently the following Preferences editors and files are available:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Preferences Editors&lt;br /&gt;
! Preferences Editor&lt;br /&gt;
! Preferences Configuration File&lt;br /&gt;
|-&lt;br /&gt;
| IControl&lt;br /&gt;
| icontrol.prefs&lt;br /&gt;
|-&lt;br /&gt;
| Input&lt;br /&gt;
| input.prefs&lt;br /&gt;
|-&lt;br /&gt;
| Palette&lt;br /&gt;
| palette.ilbm&lt;br /&gt;
|-&lt;br /&gt;
| Pointer&lt;br /&gt;
| pointer.ilbm&lt;br /&gt;
|-&lt;br /&gt;
| Printer&lt;br /&gt;
| printer.prefs&lt;br /&gt;
|-&lt;br /&gt;
| PrinterGfx&lt;br /&gt;
| printergfx.prefs&lt;br /&gt;
|-&lt;br /&gt;
| Overscan&lt;br /&gt;
| overscan.prefs&lt;br /&gt;
|-&lt;br /&gt;
| ScreenMode&lt;br /&gt;
| screenmode.prefs&lt;br /&gt;
|-&lt;br /&gt;
| Serial&lt;br /&gt;
| serial.prefs&lt;br /&gt;
|-&lt;br /&gt;
| -&lt;br /&gt;
| wbconfig.prefs&lt;br /&gt;
|-&lt;br /&gt;
| Font&lt;br /&gt;
| wbfont.prefs, sysfont.prefs and screenfont.prefs&lt;br /&gt;
|-&lt;br /&gt;
| Time&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
| WBPattern&lt;br /&gt;
| wb.pat and win.pat&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Each .prefs file is managed by editor with the same name, except for wbconfig.prefs, which is written directly by Workbench and has no editor. One Preferences editor has no .prefs file, Time. That Preferences editor writes directly to the battery backed clock.&lt;br /&gt;
&lt;br /&gt;
When the user makes a change to a Preferences item with one of the editors, the changes will be saved in either &amp;quot;ENV:sys&amp;quot; or &#039;&#039;both&#039;&#039; &amp;quot;ENV:sys&amp;quot; and &amp;quot;ENVARC:sys&amp;quot; depending on whether the user saves the changes with the &amp;quot;Use&amp;quot; gadget or &amp;quot;Save&amp;quot; gadget of the Preferences editor.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;Use&amp;quot; gadget is for making temporary changes and the new preferences will be stored only in &amp;quot;ENV:sys&amp;quot;. If the user reboots, the old preferences will be restored from the permanent copy in &amp;quot;ENVARC:sys&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;Save&amp;quot; gadget is for making permanent changes and the new preferences will be stored in both &amp;quot;ENV:sys&amp;quot; and &amp;quot;ENVARC:sys&amp;quot;. That way, if the user reboots, the new preferences will still be in effect since the system looks in &amp;quot;ENVARC:sys&amp;quot; to find out what preferences should be set to at boot time.&lt;br /&gt;
&lt;br /&gt;
=== The ENV: Directory and Notification ===&lt;br /&gt;
&lt;br /&gt;
One advantage of the new Preferences system is file notification. File notification is a form of inter-process communication that allows an application to be automatically notified if a change is made to a specific file or directory. This makes it easy for the application to react to changes the user makes to Preferences files. See [[Notification]] for more complete information about the notification feature.&lt;br /&gt;
&lt;br /&gt;
File notification is also used by the system itself. The Preferences control program, IPrefs, sets up notification on most of the Preferences files in &amp;quot;ENV:sys&amp;quot;. If the user alters a Preferences item (normally this is done with a Preferences editor), the system will notify IPrefs about the change and IPrefs will attempt to alter the user&#039;s environment to reflect the change.&lt;br /&gt;
&lt;br /&gt;
For example, if the user opens the ScreenMode Preferences editor and changes the Workbench screen mode to high-resolution, the new settings are saved in &amp;quot;screenmode.prefs&amp;quot; in the &amp;quot;ENV:sys&amp;quot; directory. IPrefs sets up notification on this file at boot time, so the file system will notify IPrefs of the change. IPrefs will read in the Screenmode.prefs file and reset the Workbench screen to high resolution mode.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s a short example showing how to set up notification on the &amp;quot;serial.prefs&amp;quot; file in &amp;quot;ENV:sys&amp;quot;. The program displays a message in a window whenever this file is changed (e.g., when the user selects the &amp;quot;Use&amp;quot; or &amp;quot;Save&amp;quot; gadget in the Serial Preferences editor).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
** prefnotify.c - notified if serial prefs change&lt;br /&gt;
*/&lt;br /&gt;
#include &amp;lt;exec/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;exec/memory.h&amp;gt;&lt;br /&gt;
#include &amp;lt;dos/dos.h&amp;gt;&lt;br /&gt;
#include &amp;lt;dos/notify.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;proto/exec.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/dos.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define PREFSFILENAME &amp;quot;ENV:sys/serial.prefs&amp;quot;&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char **argv)&lt;br /&gt;
{&lt;br /&gt;
  /* Allocate a NotifyRequest structure */&lt;br /&gt;
  struct NotifyRequest *notifyrequest = IExec-&amp;gt;AllocMem(sizeof(struct NotifyRequest), MEMF_CLEAR);&lt;br /&gt;
&lt;br /&gt;
  if (notifyrequest != NULL)&lt;br /&gt;
  {&lt;br /&gt;
    /* And allocate a signalsbit */&lt;br /&gt;
    int8 signum;&lt;br /&gt;
    if ((signum = IExec-&amp;gt;AllocSignal(-1L)) != -1)&lt;br /&gt;
    {&lt;br /&gt;
      /* Initialize notifcation request */&lt;br /&gt;
      CONST_STRPTR filename = PREFSFILENAME;&lt;br /&gt;
      notifyrequest-&amp;gt;nr_Name = filename;&lt;br /&gt;
      notifyrequest-&amp;gt;nr_Flags = NRF_SEND_SIGNAL;&lt;br /&gt;
      /* Signal this task */&lt;br /&gt;
      notifyrequest-&amp;gt;nr_stuff.nr_Signal.nr_Task = (struct Task *) IExec-&amp;gt;FindTask(NULL);&lt;br /&gt;
      /* with this signals bit */&lt;br /&gt;
      notifyrequest-&amp;gt;nr_stuff.nr_Signal.nr_SignalNum = signum;&lt;br /&gt;
&lt;br /&gt;
      if ((IDOS-&amp;gt;StartNotify(notifyrequest)) == DOSTRUE)&lt;br /&gt;
      {&lt;br /&gt;
        IDOS-&amp;gt;Printf(&amp;quot;Select Serial Prefs SAVE or USE to notify this program\n&amp;quot;);&lt;br /&gt;
        IDOS-&amp;gt;Printf(&amp;quot;CTRL-C to exit\n\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        BOOL done = FALSE;&lt;br /&gt;
&lt;br /&gt;
        /* Loop until Ctrl-C to exit */&lt;br /&gt;
        while(!done)&lt;br /&gt;
        {&lt;br /&gt;
          uint32 signals = IExec-&amp;gt;Wait(  (1L &amp;lt;&amp;lt; signum) | SIGBREAKF_CTRL_C  );&lt;br /&gt;
          if (signals &amp;amp; (1L &amp;lt;&amp;lt; signum))&lt;br /&gt;
            IDOS-&amp;gt;Printf(&amp;quot;Notification signal received.\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
          if (signals &amp;amp; SIGBREAKF_CTRL_C)&lt;br /&gt;
          {&lt;br /&gt;
            IDOS-&amp;gt;EndNotify(notifyrequest);&lt;br /&gt;
            done = TRUE;&lt;br /&gt;
          }&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
      else IDOS-&amp;gt;Printf(&amp;quot;Can&#039;t start notification\n&amp;quot;);&lt;br /&gt;
      IExec-&amp;gt;FreeSignal(signum);&lt;br /&gt;
    }&lt;br /&gt;
    else IDOS-&amp;gt;Printf(&amp;quot;No signals available\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    IExec-&amp;gt;FreeMem(notifyrequest, sizeof(struct NotifyRequest));&lt;br /&gt;
  }&lt;br /&gt;
  else IDOS-&amp;gt;Printf(&amp;quot;Not enough memory for NotifyRequest.\n&amp;quot;);&lt;br /&gt;
    &lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Preference File Format ===&lt;br /&gt;
&lt;br /&gt;
To understand the format of Preferences files, you must be familiar with IFF file standard (see [[IFF_Standard|IFF Standard]] for the complete specification).&lt;br /&gt;
&lt;br /&gt;
In general all Preferences files are stored in the IFF format with a type of PREF (see the exceptions noted below). Each file contains at least two Chunks, a header Chunk and a data Chunk.&lt;br /&gt;
&lt;br /&gt;
==== The Header Chunk ====&lt;br /&gt;
&lt;br /&gt;
The PRHD header chunk, contains a PrefHeader structure:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct PrefHeader&lt;br /&gt;
{&lt;br /&gt;
    UBYTE ph_Version;&lt;br /&gt;
    UBYTE ph_Type;&lt;br /&gt;
    ULONG ph_Flags;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Currently all the fields are set to NULL. In future revisions these fields may be used to indicate a particular version and contents of a PREF chunk.&lt;br /&gt;
&lt;br /&gt;
==== The Data Chunk ====&lt;br /&gt;
&lt;br /&gt;
The data Chunk that follows the header Chunk depends on the kind of Preferences data the file contains. The types of Preferences data Chunks that are currently part of the system are:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ IFF Chunk Types in Preferences Data Files&lt;br /&gt;
! Chunk Name&lt;br /&gt;
! Used With&lt;br /&gt;
|-&lt;br /&gt;
| FONT&lt;br /&gt;
| Fonts, used for all font Preferences files. In future the PrefHeader may indicate what the font is used for.&lt;br /&gt;
|-&lt;br /&gt;
| ICTL&lt;br /&gt;
| IControl&lt;br /&gt;
|-&lt;br /&gt;
| INPT&lt;br /&gt;
| Input&lt;br /&gt;
|-&lt;br /&gt;
| OSCN&lt;br /&gt;
| Overscan&lt;br /&gt;
|-&lt;br /&gt;
| PGFX&lt;br /&gt;
| PrinterGfx&lt;br /&gt;
|-&lt;br /&gt;
| PTXT&lt;br /&gt;
| PrinterText&lt;br /&gt;
|-&lt;br /&gt;
| SCRM&lt;br /&gt;
| ScreenMode&lt;br /&gt;
|-&lt;br /&gt;
| SERL&lt;br /&gt;
| Serial&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Each chunk contains a structure applicable to the type.&lt;br /&gt;
&lt;br /&gt;
=== FONT ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct FontPrefs&lt;br /&gt;
{&lt;br /&gt;
    LONG            fp_Reserved[4];&lt;br /&gt;
    UBYTE           fp_FrontPen;                /* Textcolor */&lt;br /&gt;
    UBYTE           fp_BackPen;                 /* Character background color */&lt;br /&gt;
    UBYTE           fp_DrawMode;&lt;br /&gt;
    struct TextAttr fp_TextAttr;&lt;br /&gt;
    BYTE            fp_Name[FONTNAMESIZE];      /* Font name */&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ICTL ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct IControlPrefs&lt;br /&gt;
{&lt;br /&gt;
    LONG  ic_Reserved[4];        /* System reserved              */&lt;br /&gt;
    UWORD ic_TimeOut;            /* Verify timeout               */&lt;br /&gt;
    WORD  ic_MetaDrag;           /* Meta drag mouse event        */&lt;br /&gt;
    ULONG ic_Flags;              /* IControl flags (see below)   */&lt;br /&gt;
    UBYTE ic_WBtoFront;          /* CKey: WB to front            */&lt;br /&gt;
    UBYTE ic_FrontToBack;        /* CKey: front screen to back   */&lt;br /&gt;
    UBYTE ic_ReqTrue;            /* CKey: Requester TRUE         */&lt;br /&gt;
    UBYTE ic_ReqFalse;           /* CKey: Requester FALSE        */&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The ic_Flags field can have the following values:&lt;br /&gt;
&lt;br /&gt;
; ICF_COERCE_COLORS&lt;br /&gt;
: This indicates that a displaymode with a matching number of colors has preference over a correct aspect ration when screen coercing takes place.&lt;br /&gt;
&lt;br /&gt;
; ICF_COERCE_LACE&lt;br /&gt;
: This indicates that choosing an interlaced display mode is allowed when coercing screens. Otherwise a non-interlaced display mode will be selected.&lt;br /&gt;
&lt;br /&gt;
; ICF_STRGAD_FILTER&lt;br /&gt;
: This indicates that control characters should be filtered out of string gadget user input.&lt;br /&gt;
&lt;br /&gt;
; ICF_MENUSNAP&lt;br /&gt;
: This indicates that an auto-scroll screen should be snapped back to origin when the mouse menu-button is selected.&lt;br /&gt;
&lt;br /&gt;
Note that the command key values in the last four fields of the IControlPrefs structure are ANSI codes, not RAWKEY codes.&lt;br /&gt;
&lt;br /&gt;
=== INPT ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct InputPrefs&lt;br /&gt;
{&lt;br /&gt;
    LONG           ip_Reserved[4];&lt;br /&gt;
    UWORD          ip_PointerTicks; /* Sensitivity of the pointer */&lt;br /&gt;
    struct timeval ip_DoubleClick;  /* Interval between clicks */&lt;br /&gt;
    struct timeval ip_KeyRptDelay;  /* keyboard repeat delay   */&lt;br /&gt;
    struct timeval ip_KeyRptSpeed;  /* Keyboard repeat speed   */&lt;br /&gt;
    WORD           ip_MouseAccel;   /* Mouse acceleration      */&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== OSCN ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct OverscanPrefs&lt;br /&gt;
{&lt;br /&gt;
    ULONG            os_Reserved[4];&lt;br /&gt;
    ULONG            os_DisplayID;       /* Displaymode ID */&lt;br /&gt;
    Point            os_ViewPos;         /* View X/Y Offset */&lt;br /&gt;
    Point            os_Text;            /* TEXT overscan dimension */&lt;br /&gt;
    struct Rectangle os_Standard;        /* STANDARD overscan dimension */&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== PGFX ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct PrinterGfxPrefs&lt;br /&gt;
{&lt;br /&gt;
    LONG  pg_Reserved[4];&lt;br /&gt;
    UWORD pg_Aspect;                      /* Horizontal or vertical */&lt;br /&gt;
    UWORD pg_Shade;                       /* B&amp;amp;amp;W, Greyscale, Color */&lt;br /&gt;
    UWORD pg_Image;                       /* Positive or negative image */&lt;br /&gt;
    WORD  pg_Threshold;                   /* Black threshold */&lt;br /&gt;
    UBYTE pg_ColorCorrect;                /* RGB color correction */&lt;br /&gt;
    UBYTE pg_Dimensions;                  /* Dimension type */&lt;br /&gt;
    UBYTE pg_Dithering;                   /* Type of dithering */&lt;br /&gt;
    UWORD pg_GraphicFlags;                /* Rastport dump flags */&lt;br /&gt;
    UBYTE pg_PrintDensity;                /* Print density 1 - 7 */&lt;br /&gt;
    UWORD pg_PrintMaxWidth;               /* Maximum width */&lt;br /&gt;
    UWORD pg_PrintMaxHeight;              /* Maximum height */&lt;br /&gt;
    UBYTE pg_PrintXOffset;                /* X Offset */&lt;br /&gt;
    UBYTE pg_PrintYOffset;                /* Y Offset */&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The possible values of each field are defined in &amp;amp;lt;prefs/printergfx.h&amp;amp;gt;. Note that your application is responsible for checking if the supplied values are valid.&lt;br /&gt;
&lt;br /&gt;
=== PTXT ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct PrinterTxtPrefs&lt;br /&gt;
{&lt;br /&gt;
    LONG  pt_Reserved[4];                /* System reserved            */&lt;br /&gt;
    UBYTE pt_Driver[DRIVERNAMESIZE];     /* printer driver filename    */&lt;br /&gt;
    UBYTE pt_Port;                       /* printer port connection    */&lt;br /&gt;
&lt;br /&gt;
    UWORD pt_PaperType;                  /* Fanfold or single */&lt;br /&gt;
    UWORD pt_PaperSize;                  /* Standard, Legal, A4, A3 etc. */&lt;br /&gt;
    UWORD pt_PaperLength;                /* Paper length in # of lines */&lt;br /&gt;
&lt;br /&gt;
    UWORD pt_Pitch;                      /* Pica or Elite */&lt;br /&gt;
    UWORD pt_Spacing;                    /* 6 or 8 LPI */&lt;br /&gt;
    UWORD pt_LeftMargin;                 /* Left margin */&lt;br /&gt;
    UWORD pt_RightMargin;                /* Right margin */&lt;br /&gt;
    UWORD pt_Quality;                    /* Draft or Letter */&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== SCRM ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct ScreenModePrefs&lt;br /&gt;
{&lt;br /&gt;
    ULONG sm_Reserved[4];&lt;br /&gt;
    ULONG sm_DisplayID;                    /* Displaymode ID */&lt;br /&gt;
    UWORD sm_Width;                        /* Screen width */&lt;br /&gt;
    UWORD sm_Height;                       /* Screen height */&lt;br /&gt;
    UWORD sm_Depth;                        /* Screen depth */&lt;br /&gt;
    UWORD sm_Control;                      /* BIT 0, Autoscroll yes/no */&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== SERL ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct SerialPrefs&lt;br /&gt;
{&lt;br /&gt;
    LONG  sp_Reserved[4];                /* System reserved                  */&lt;br /&gt;
    ULONG sp_BaudRate;                   /* Baud rate                        */&lt;br /&gt;
&lt;br /&gt;
    ULONG sp_InputBuffer;                /* Input buffer: 0 - 64K          */&lt;br /&gt;
    ULONG sp_OutputBuffer;               /* Future: Output: 0 - 64K, def 0 */&lt;br /&gt;
&lt;br /&gt;
    UBYTE sp_InputHandshake;             /* Input handshaking                */&lt;br /&gt;
    UBYTE sp_OutputHandshake;            /* Future: Output handshaking       */&lt;br /&gt;
&lt;br /&gt;
    UBYTE sp_Parity;                     /* Parity                           */&lt;br /&gt;
    UBYTE sp_BitsPerChar;                /* I/O bits per character           */&lt;br /&gt;
    UBYTE sp_StopBits;                   /* Stop bits                        */&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Other Preferences File Formats ===&lt;br /&gt;
&lt;br /&gt;
Not every Preferences file is stored as an IFF file of type PREF. The palette.ilbm and pointer.ilbm files contain a regular ILBM FORM to store their imagery. The win.pat and wb.pat files use a raw format with 16 bytes reserved, followed by a WORD giving the total size of the pattern, a WORD giving the bitplane count, and byte arrays (currently 32 bytes) for each bitplane. The format of the wbconfig.prefs file is private.&lt;br /&gt;
&lt;br /&gt;
=== Reading a Preferences File ===&lt;br /&gt;
&lt;br /&gt;
The following example shows a way to read a Preferences file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
** showprefs.c - parse and show some info from an IFF Preferences file&lt;br /&gt;
**&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;exec/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;dos/dos.h&amp;gt;&lt;br /&gt;
#include &amp;lt;libraries/dos.h&amp;gt;&lt;br /&gt;
#include &amp;lt;libraries/iffparse.h&amp;gt;&lt;br /&gt;
#include &amp;lt;prefs/prefhdr.h&amp;gt;&lt;br /&gt;
#include &amp;lt;prefs/font.h&amp;gt;&lt;br /&gt;
#include &amp;lt;prefs/icontrol.h&amp;gt;&lt;br /&gt;
#include &amp;lt;prefs/input.h&amp;gt;&lt;br /&gt;
#include &amp;lt;prefs/overscan.h&amp;gt;&lt;br /&gt;
#include &amp;lt;prefs/printergfx.h&amp;gt;&lt;br /&gt;
#include &amp;lt;prefs/printertxt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;prefs/screenmode.h&amp;gt;&lt;br /&gt;
#include &amp;lt;prefs/serial.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;proto/exec.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/dos.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/iffparse.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
struct IFFParseIFace *IIFF;&lt;br /&gt;
&lt;br /&gt;
static uint8 *IFFErrTxt[] = {&lt;br /&gt;
  &amp;quot;EOF&amp;quot;,    /* (end of file, not an error) */&lt;br /&gt;
  &amp;quot;EOC&amp;quot;,     /* (end of context, not an error) */&lt;br /&gt;
  &amp;quot;no lexical scope&amp;quot;,&lt;br /&gt;
  &amp;quot;insufficient memory&amp;quot;,&lt;br /&gt;
  &amp;quot;stream read error&amp;quot;,&lt;br /&gt;
  &amp;quot;stream write error&amp;quot;,&lt;br /&gt;
  &amp;quot;stream seek error&amp;quot;,&lt;br /&gt;
  &amp;quot;file corrupt&amp;quot;,&lt;br /&gt;
  &amp;quot;IFF syntax error&amp;quot;,&lt;br /&gt;
  &amp;quot;not an IFF file&amp;quot;,&lt;br /&gt;
  &amp;quot;required call-back hook missing&amp;quot;,&lt;br /&gt;
  NULL,     /* (return to client, never shown) */&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
  struct RDArgs *readargs;&lt;br /&gt;
  int32 rargs[2];&lt;br /&gt;
  struct IFFHandle *iffhandle;&lt;br /&gt;
  struct ContextNode *cnode;&lt;br /&gt;
  struct StoredProperty *hdrsp;&lt;br /&gt;
  struct StoredProperty *sp;&lt;br /&gt;
  uint8 *filename;&lt;br /&gt;
  int32 ifferror, error = 0, rc = RETURN_OK;&lt;br /&gt;
&lt;br /&gt;
  struct Library *IFFParseBase = IExec-&amp;gt;OpenLibrary (&amp;quot;iffparse.library&amp;quot;, 50);&lt;br /&gt;
  IIFF = (struct IFFParseIFace*)IExec-&amp;gt;GetInterface(IFFParseBase, &amp;quot;main&amp;quot;, 1, NULL);&lt;br /&gt;
  &lt;br /&gt;
  if (IIFF != NULL) {&lt;br /&gt;
      if (readargs = IDOS-&amp;gt;ReadArgs(&amp;quot;FILE/A&amp;quot;, rargs, NULL)) {&lt;br /&gt;
&lt;br /&gt;
        /* Test later if valid */&lt;br /&gt;
        filename = (uint8 *)rargs[0];&lt;br /&gt;
&lt;br /&gt;
        /* allocate an IFF handle */&lt;br /&gt;
        if (iffhandle = IIFF-&amp;gt;AllocIFF()) {&lt;br /&gt;
          /* Open the file for reading */&lt;br /&gt;
          if (iffhandle-&amp;gt;iff_Stream = (int32)IDOS-&amp;gt;Open(filename, MODE_OLDFILE)) {&lt;br /&gt;
            /* initialize the iff handle */&lt;br /&gt;
            IIFF-&amp;gt;InitIFFasDOS (iffhandle);&lt;br /&gt;
            if ((ifferror = IIFF-&amp;gt;OpenIFF (iffhandle, IFFF_READ)) == 0) {&lt;br /&gt;
              IIFF-&amp;gt;PropChunk(iffhandle, ID_PREF, ID_PRHD);&lt;br /&gt;
&lt;br /&gt;
              IIFF-&amp;gt;PropChunk(iffhandle, ID_PREF, ID_FONT);&lt;br /&gt;
              IIFF-&amp;gt;PropChunk(iffhandle, ID_PREF, ID_ICTL);&lt;br /&gt;
              IIFF-&amp;gt;PropChunk(iffhandle, ID_PREF, ID_INPT);&lt;br /&gt;
              IIFF-&amp;gt;PropChunk(iffhandle, ID_PREF, ID_OSCN);&lt;br /&gt;
              IIFF-&amp;gt;PropChunk(iffhandle, ID_PREF, ID_PGFX);&lt;br /&gt;
              IIFF-&amp;gt;PropChunk(iffhandle, ID_PREF, ID_PTXT);&lt;br /&gt;
              IIFF-&amp;gt;PropChunk(iffhandle, ID_PREF, ID_SCRM);&lt;br /&gt;
              IIFF-&amp;gt;PropChunk(iffhandle, ID_PREF, ID_SERL);&lt;br /&gt;
&lt;br /&gt;
              for (;;) {&lt;br /&gt;
                ifferror = IIFF-&amp;gt;ParseIFF(iffhandle, IFFPARSE_STEP);&lt;br /&gt;
&lt;br /&gt;
                 if (ifferror == IFFERR_EOC)&lt;br /&gt;
                   continue;&lt;br /&gt;
                else if (ifferror)&lt;br /&gt;
                  break;&lt;br /&gt;
&lt;br /&gt;
                /* Do nothing is this is a PrefHeader chunk,&lt;br /&gt;
                 * we&#039;ll pop it later when there is a pref&lt;br /&gt;
                 * chunk.&lt;br /&gt;
                 */&lt;br /&gt;
                if (cnode = IIFF-&amp;gt;CurrentChunk(iffhandle))&lt;br /&gt;
                  if (cnode-&amp;gt;cn_ID == ID_PRHD || cnode-&amp;gt;cn_ID == ID_FORM)&lt;br /&gt;
                    continue;&lt;br /&gt;
&lt;br /&gt;
                /* Get the preferences header, stored previously */&lt;br /&gt;
                hdrsp = IIFF-&amp;gt;FindProp(iffhandle, ID_PREF, ID_PRHD);&lt;br /&gt;
&lt;br /&gt;
                if (sp = IIFF-&amp;gt;FindProp(iffhandle, ID_PREF, ID_FONT)) {&lt;br /&gt;
                  IDOS-&amp;gt;Printf(&amp;quot;FrontPen:  %ld\n&amp;quot;,&lt;br /&gt;
                        ((struct FontPrefs *)sp-&amp;gt;sp_Data)-&amp;gt;fp_FrontPen);&lt;br /&gt;
                  IDOS-&amp;gt;Printf(&amp;quot;BackPen:   %ld\n&amp;quot;,&lt;br /&gt;
                        ((struct FontPrefs *)sp-&amp;gt;sp_Data)-&amp;gt;fp_BackPen);&lt;br /&gt;
                  IDOS-&amp;gt;Printf(&amp;quot;DrawMode:  %ld\n&amp;quot;,&lt;br /&gt;
                        ((struct FontPrefs *)sp-&amp;gt;sp_Data)-&amp;gt;fp_DrawMode);&lt;br /&gt;
                  IDOS-&amp;gt;Printf(&amp;quot;Font:      %s\n&amp;quot;,&lt;br /&gt;
                        (LONG)((struct FontPrefs *)sp-&amp;gt;sp_Data)-&amp;gt;fp_Name);&lt;br /&gt;
                  IDOS-&amp;gt;Printf(&amp;quot;ta_YSize:  %ld\n&amp;quot;,&lt;br /&gt;
                        ((struct FontPrefs *)sp-&amp;gt;sp_Data)-&amp;gt;fp_TextAttr.ta_YSize);&lt;br /&gt;
                  IDOS-&amp;gt;Printf(&amp;quot;ta_Style:  %ld\n&amp;quot;,&lt;br /&gt;
                        ((struct FontPrefs *)sp-&amp;gt;sp_Data)-&amp;gt;fp_TextAttr.ta_Style);&lt;br /&gt;
                  IDOS-&amp;gt;Printf(&amp;quot;ta_Flags:  %ld\n&amp;quot;,&lt;br /&gt;
                        ((struct FontPrefs *)sp-&amp;gt;sp_Data)-&amp;gt;fp_TextAttr.ta_Flags);&lt;br /&gt;
                } else   if (sp = FindProp(iffhandle, ID_PREF, ID_ICTL)) {&lt;br /&gt;
                  IDOS-&amp;gt;Printf(&amp;quot;TimeOut:   %ld\n&amp;quot;,&lt;br /&gt;
                        ((struct IControlPrefs *)sp-&amp;gt;sp_Data)-&amp;gt;ic_TimeOut);&lt;br /&gt;
                  IDOS-&amp;gt;Printf(&amp;quot;MetaDrag:  %ld\n&amp;quot;,&lt;br /&gt;
                        ((struct IControlPrefs *)sp-&amp;gt;sp_Data)-&amp;gt;ic_MetaDrag);&lt;br /&gt;
                  IDOS-&amp;gt;Printf(&amp;quot;WBtoFront: %ld\n&amp;quot;,&lt;br /&gt;
                        ((struct IControlPrefs *)sp-&amp;gt;sp_Data)-&amp;gt;ic_WBtoFront);&lt;br /&gt;
                  IDOS-&amp;gt;Printf(&amp;quot;FrontToBack: %ld\n&amp;quot;,&lt;br /&gt;
                        ((struct IControlPrefs *)sp-&amp;gt;sp_Data)-&amp;gt;ic_FrontToBack);&lt;br /&gt;
                  IDOS-&amp;gt;Printf(&amp;quot;ReqTrue:    %ld\n&amp;quot;,&lt;br /&gt;
                        ((struct IControlPrefs *)sp-&amp;gt;sp_Data)-&amp;gt;ic_ReqTrue);&lt;br /&gt;
                  IDOS-&amp;gt;Printf(&amp;quot;ReqFalse:    %ld\n&amp;quot;,&lt;br /&gt;
                        ((struct IControlPrefs *)sp-&amp;gt;sp_Data)-&amp;gt;ic_ReqFalse);&lt;br /&gt;
                  /* etc */&lt;br /&gt;
                } else if (sp = IIFF-&amp;gt;FindProp(iffhandle, ID_PREF, ID_INPT)) {&lt;br /&gt;
                  IDOS-&amp;gt;Printf(&amp;quot;PointerTicks:      %ld\n&amp;quot;,&lt;br /&gt;
                        ((struct InputPrefs *)sp-&amp;gt;sp_Data)-&amp;gt;ip_PointerTicks);&lt;br /&gt;
                  IDOS-&amp;gt;Printf(&amp;quot;DoubleClick/Secs:  %ld\n&amp;quot;,&lt;br /&gt;
                        ((struct InputPrefs *)sp-&amp;gt;sp_Data)-&amp;gt;ip_DoubleClick.tv_secs);&lt;br /&gt;
                  IDOS-&amp;gt;Printf(&amp;quot;DoubleClick/Micro: %ld\n&amp;quot;,&lt;br /&gt;
                        ((struct InputPrefs *)sp-&amp;gt;sp_Data)-&amp;gt;ip_DoubleClick.tv_micro);&lt;br /&gt;
                  /* etc */&lt;br /&gt;
                } else if (sp = IIFF-&amp;gt;FindProp(iffhandle, ID_PREF, ID_OSCN)) {&lt;br /&gt;
                  IDOS-&amp;gt;Printf(&amp;quot;DisplayID:  0x%lx\n&amp;quot;,&lt;br /&gt;
                        ((struct OverscanPrefs *)sp-&amp;gt;sp_Data)-&amp;gt;os_DisplayID);&lt;br /&gt;
                  /* etc */&lt;br /&gt;
                } else if (sp = IIFF-&amp;gt;FindProp(iffhandle, ID_PREF, ID_PGFX)) {&lt;br /&gt;
                  IDOS-&amp;gt;Printf(&amp;quot;Aspect:     %ld\n&amp;quot;,&lt;br /&gt;
                        ((struct PrinterGfxPrefs *)sp-&amp;gt;sp_Data)-&amp;gt;pg_Aspect);&lt;br /&gt;
                  /* etc */&lt;br /&gt;
                } else if (sp = IIFF-&amp;gt;FindProp(iffhandle, ID_PREF, ID_PTXT)) {&lt;br /&gt;
                  IDOS-&amp;gt;Printf(&amp;quot;Driver:     %s\n&amp;quot;,&lt;br /&gt;
                        (LONG)((struct PrinterTxtPrefs *)sp-&amp;gt;sp_Data)-&amp;gt;pt_Driver);&lt;br /&gt;
                  /* etc */&lt;br /&gt;
                } else if (sp = IIFF-&amp;gt;FindProp(iffhandle, ID_PREF, ID_SCRM)) {&lt;br /&gt;
                  IDOS-&amp;gt;Printf(&amp;quot;DisplayID:  0x%lx\n&amp;quot;,&lt;br /&gt;
                        ((struct ScreenModePrefs *)sp-&amp;gt;sp_Data)-&amp;gt;sm_DisplayID);&lt;br /&gt;
                  /* etc */&lt;br /&gt;
                } else if (sp = IIFF-&amp;gt;FindProp(iffhandle, ID_PREF, ID_SERL)) {&lt;br /&gt;
                  IDOS-&amp;gt;Printf(&amp;quot;BaudRate:   %ld\n&amp;quot;,&lt;br /&gt;
                        ((struct SerialPrefs *)sp-&amp;gt;sp_Data)-&amp;gt;sp_BaudRate);&lt;br /&gt;
                  /* etc */&lt;br /&gt;
                }&lt;br /&gt;
              }&lt;br /&gt;
&lt;br /&gt;
              IIFF-&amp;gt;CloseIFF(iffhandle);&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            if (ifferror != IFFERR_EOF) {&lt;br /&gt;
              rargs[1] = (LONG)IFFErrTxt[-ifferror - 1];&lt;br /&gt;
              IDOS-&amp;gt;VFPrintf(IDOS-&amp;gt;Output(), &amp;quot;%s: %s\n&amp;quot;, rargs);&lt;br /&gt;
              rc = RETURN_FAIL;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
            IDOS-&amp;gt;Close(iffhandle-&amp;gt;iff_Stream);&lt;br /&gt;
          } else&lt;br /&gt;
            error = IoErr();&lt;br /&gt;
&lt;br /&gt;
          IIFF-&amp;gt;FreeIFF(iffhandle);&lt;br /&gt;
        } else {&lt;br /&gt;
          IDOS-&amp;gt;VFPrintf(Output(), &amp;quot;Can&#039;t allocate IFF handle\n&amp;quot;, NULL);&lt;br /&gt;
          rc = RETURN_FAIL;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        IDOS-&amp;gt;FreeArgs(readargs);&lt;br /&gt;
      } else&lt;br /&gt;
        error = IoErr();&lt;br /&gt;
&lt;br /&gt;
      IDOS-&amp;gt;SetIoErr(error);&lt;br /&gt;
      if (error) {&lt;br /&gt;
        rc = RETURN_FAIL;&lt;br /&gt;
        IDOS-&amp;gt;PrintFault(error, filename);&lt;br /&gt;
      }&lt;br /&gt;
  } else {&lt;br /&gt;
    rc = RETURN_FAIL;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  IExec-&amp;gt;DropInterface((struct Interface*)IIFF);&lt;br /&gt;
  IExec-&amp;gt;CloseLibrary(IFFParseBase);&lt;br /&gt;
&lt;br /&gt;
  return(rc);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Preferences in 1.3 and Older Versions of the OS ==&lt;br /&gt;
&lt;br /&gt;
In 1.3, the Preferences program allows the user to see and change many system wide parameters, like the Workbench colors, pointer image, printer settings etc. When a Preferences item is changed, the new setting can be used temporarily (until a reset occurs) or stored permanently in the &amp;quot;DEVS:system-configuration&amp;quot; file. Under 1.3, all Preferences items are stored in this file which the system reads at boot time to find out how to set various system-wide options.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct Preferences *GetPrefs(struct Preferences *preferences, LONG size);&lt;br /&gt;
struct Preferences *GetDefPrefs(struct Preferences *preferences, LONG size);&lt;br /&gt;
struct Preferences *SetPrefs( struct Preferences *preferences, LONG size, BOOL inform );&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
None of these functions should be used in any new programs. They are only present for backwards compatibility.&lt;br /&gt;
&lt;br /&gt;
== Function Reference ==&lt;br /&gt;
&lt;br /&gt;
The following are brief descriptions of the system functions that relate to the use of Preferences. See the SDK for details on each function call.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Function&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| GetPrefs()&lt;br /&gt;
| Old 1.3 (V34) function for making a copy of the Preferences structure&lt;br /&gt;
|-&lt;br /&gt;
| SetPrefs()&lt;br /&gt;
| Old 1.3 (V34) function for overwriting Preferences with new data&lt;br /&gt;
|-&lt;br /&gt;
| GetDefPrefs()&lt;br /&gt;
| Old 1.3 (V34) function for copying default Preferences from ROM&lt;br /&gt;
|-&lt;br /&gt;
| StartNotify()&lt;br /&gt;
| DOS library function for monitoring a .prefs file for changes&lt;br /&gt;
|-&lt;br /&gt;
| EndNotify()&lt;br /&gt;
| Ends notification started with StartNotify()&lt;br /&gt;
|-&lt;br /&gt;
| AllocIFF()&lt;br /&gt;
| IFFParse library function that creates an IFFHandle for parsing&lt;br /&gt;
|-&lt;br /&gt;
| InitIFFasDOS()&lt;br /&gt;
| Initialize the IFFHandle as a DOS stream&lt;br /&gt;
|-&lt;br /&gt;
| OpenIFF()&lt;br /&gt;
| Initialize an IFFHandle for reading or writing a new stream&lt;br /&gt;
|-&lt;br /&gt;
| PropChunk()&lt;br /&gt;
| Specify a property chunk to store&lt;br /&gt;
|-&lt;br /&gt;
| ParseIFF()&lt;br /&gt;
| Parse an IFF file from the IFFHandle stream&lt;br /&gt;
|-&lt;br /&gt;
| CurrentChunk()&lt;br /&gt;
| Returns the top level context of an IFF stream&lt;br /&gt;
|-&lt;br /&gt;
| FindProp()&lt;br /&gt;
| Search for a property chunk previously declared with PropChunk()&lt;br /&gt;
|-&lt;br /&gt;
| CloseIFF()&lt;br /&gt;
| Closes an IFF context opened with OpenIFF()&lt;br /&gt;
|-&lt;br /&gt;
| FreeIFF()&lt;br /&gt;
| Frees the IFFHandle created with AllocIFF()&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Costel Mincea</name></author>
	</entry>
	<entry>
		<id>https://wiki.amigaos.net/w/index.php?title=Console_Device&amp;diff=12564</id>
		<title>Console Device</title>
		<link rel="alternate" type="text/html" href="https://wiki.amigaos.net/w/index.php?title=Console_Device&amp;diff=12564"/>
		<updated>2025-01-26T19:36:02Z</updated>

		<summary type="html">&lt;p&gt;Costel Mincea: Text replacement - &amp;quot;&amp;lt;syntaxhighlight&amp;gt;&amp;quot; to &amp;quot;&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Devices|Console]]&lt;br /&gt;
== Console Device ==&lt;br /&gt;
&lt;br /&gt;
The console device provides the text-oriented interface for Intuition windows. It acts like an enhanced ASCII terminal obeying many of the standard ANSI sequences as well as special sequences unique to the Amiga. The console device also provides a copy-and-paste facility and an internal character map to redraw a window when it is resized.&lt;br /&gt;
&lt;br /&gt;
== Console Device Commands and Functions ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Command&lt;br /&gt;
! Command Operation&lt;br /&gt;
|-&lt;br /&gt;
| CD_ASKDEFAULTKEYMAP || Get the current default keymap.&lt;br /&gt;
|-&lt;br /&gt;
| CD_ASKKEYMAP || Get the current key map structure for this console.&lt;br /&gt;
|-&lt;br /&gt;
| CD_ASKKEYMAP_POINTERS || Get pointers to the current key map structures for this console. (V51.19)&lt;br /&gt;
|-&lt;br /&gt;
| CD_GETATTRS || Get attributes for this console. (V53)&lt;br /&gt;
|-&lt;br /&gt;
| CD_SETATTRS || Set attributes for this console. (V53)&lt;br /&gt;
|-&lt;br /&gt;
| CD_SETDEFAULTKEYMAP || Set the current default keymap.&lt;br /&gt;
|-&lt;br /&gt;
| CD_SETKEYMAP || Set the current key map structure for this console.&lt;br /&gt;
|-&lt;br /&gt;
| CD_SETKEYMAP_POINTERS || Set the current key map structures for the console. (V51.19)&lt;br /&gt;
|-&lt;br /&gt;
| CMD_CLEAR || Remove any reports waiting to satisfy read requests from the console input buffer.&lt;br /&gt;
|-&lt;br /&gt;
| CMD_READ || Read the next input, generally from the keyboard. The form of this input is as an ANSI byte stream.&lt;br /&gt;
|-&lt;br /&gt;
| CMD_WRITE || Write a text record to the display interpreting any ANSI control characters in the record.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Console Device Functions:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| CDInputHandler() || Handle an input event for the console device.&lt;br /&gt;
|-&lt;br /&gt;
| RawKeyConvert() || Decode raw input classes and convert input events of type IECLASS_RAWKEY to ANSI bytes based on the keymap in use.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Device Interface ==&lt;br /&gt;
&lt;br /&gt;
The console device operates like the other Amiga devices. To use it, you must first open the console device, then send I/O requests to it, and then close it when finished. See [[Exec_Device_I/O|Exec Device I/O]] for general information on device usage.&lt;br /&gt;
&lt;br /&gt;
The I/O request used by the console device is called IOStdReq.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct IOStdReq&lt;br /&gt;
{&lt;br /&gt;
    struct  Message io_Message;&lt;br /&gt;
    struct  Device  *io_Device;     /* device node pointer  */&lt;br /&gt;
    struct  Unit    *io_Unit;       /* unit (driver private)*/&lt;br /&gt;
    UWORD   io_Command;             /* device command */&lt;br /&gt;
    UBYTE   io_Flags;&lt;br /&gt;
    BYTE    io_Error;               /* error or warning num */&lt;br /&gt;
    ULONG   io_Actual;              /* actual number of bytes transferred */&lt;br /&gt;
    ULONG   io_Length;              /* requested number bytes transferred*/&lt;br /&gt;
    APTR    io_Data;                /* points to data area */&lt;br /&gt;
    ULONG   io_Offset;              /* offset for block structured devices */&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See the include file exec/io.h for the complete structure definition.&lt;br /&gt;
&lt;br /&gt;
=== Console Device Units ===&lt;br /&gt;
&lt;br /&gt;
The console device provides four units, three that require a console window and one that does not. The unit type is specified when you open the device. See the [[#Opening the Console Device|Opening the Console Device]] section below for more details.&lt;br /&gt;
&lt;br /&gt;
The CONU_STANDARD unit (0) is generally used with a SMART_REFRESH window. This unit has the least amount of overhead (e.g., memory usage and rendering time), and is highly compatible with all versions of the operating system.&lt;br /&gt;
&lt;br /&gt;
There are two variations of character mapped console units. Both must be used with SIMPLE_REFRESH windows and both have the ability to automatically redraw a console window when resized or revealed.&lt;br /&gt;
&lt;br /&gt;
A character mapped console can be opened which allows the user to drag-select text with the mouse and &#039;&#039;&#039;Copy&#039;&#039;&#039; the highlighted area. The copied text can then be &#039;&#039;&#039;Paste&#039;&#039;&#039;d into other console windows or other windows which support reading data from the [[Clipboard_Device|clipboard device]].&lt;br /&gt;
&lt;br /&gt;
Character mapped console units have more overhead than standard consoles (e.g., rendering times and memory usage).&lt;br /&gt;
&lt;br /&gt;
The CONU_LIBRARY unit (-1) does not require a console window. It is designed to be primarily used with the console device functions and also with the console device commands that do not require a console window.&lt;br /&gt;
&lt;br /&gt;
The Amiga uses the [http://www.ecma-international.org/publications/standards/Ecma-094.htm ECMA-94 Latin 1 International 8-bit] character set.&lt;br /&gt;
&lt;br /&gt;
=== Opening the Console Device ===&lt;br /&gt;
&lt;br /&gt;
Four primary steps are required to open the console device:&lt;br /&gt;
&lt;br /&gt;
# Create a message port using AllocSysObject(ASOT_PORT). Reply messages from the device must be directed to a message port.&lt;br /&gt;
# Create an I/O request structure of type IOStdReq. The IOStdReq structure is created by the AllocSysObject(ASOT_IOREQUEST) function. AllocSysObject() will initialize your I/O request to point to your reply port.&lt;br /&gt;
# Open an Intuition window and set a pointer to it in the io_Data field of the IOStdReq and the size of the window in the io_Length field. This is the window to which the console will be attached. The window must be SIMPLE_REFRESH for use with the CONU_CHARMAP and CONU_SNIPMAP units.&lt;br /&gt;
# Open the console device. Call OpenDevice() passing it the I/O request and the type of console unit set in the unit and flags fields. Console unit types and flag values are listed below.&lt;br /&gt;
&lt;br /&gt;
Console device units:&lt;br /&gt;
&lt;br /&gt;
; CONU_LIBRARY&lt;br /&gt;
: Return the device library vector pointer used for calling console device functions. No console is opened.&lt;br /&gt;
&lt;br /&gt;
; CONU_STANDARD&lt;br /&gt;
: Open a standard console.&lt;br /&gt;
&lt;br /&gt;
; CONU_CHARMAP&lt;br /&gt;
: Open a console with a character map.&lt;br /&gt;
&lt;br /&gt;
; CONU_SNIPMAP&lt;br /&gt;
: Open a console with a character map and copy-and-paste support.&lt;br /&gt;
&lt;br /&gt;
; CONU_HISTORY (V53)&lt;br /&gt;
: Similar to CONU_SNIPMAP with content history and tabbed windows.&lt;br /&gt;
&lt;br /&gt;
See the include file devices/conunit.h for the unit definitions and the SDK for an explanation of each unit.&lt;br /&gt;
&lt;br /&gt;
{{Note|title=No Changes Required|text=CONU_STANDARD has a numeric value of zero to insure compatibility with pre-V36 applications. CONU_LIBRARY has a numeric value of negative one and is also compatible with pre-V36 applications.}}&lt;br /&gt;
&lt;br /&gt;
Console device flags:&lt;br /&gt;
&lt;br /&gt;
; CONFLAG_DEFAULT&lt;br /&gt;
: The console device will redraw the window when it is resized.&lt;br /&gt;
&lt;br /&gt;
; CONFLAG_NODRAW_ON_NEWSIZE&lt;br /&gt;
: The console device will not redraw the window when it is resized&lt;br /&gt;
&lt;br /&gt;
; CONFLAG_CREATE_WINDOW and CONFLAG_TABBED_WINDOW (V53)&lt;br /&gt;
: These bits define the combinations of window source, tabs and sharing. These are only applicable when using CONUNIT_HISTORY or greater.&lt;br /&gt;
&lt;br /&gt;
; CONFLAG_SYNC_WRITES (V53)&lt;br /&gt;
: Forces a task issuing a Write request to wait until the request is complete before returning to the caller.&lt;br /&gt;
&lt;br /&gt;
The character map units are the only units which use the flags parameter to set how the character map is used. CONU_STANDARD units ignore the flags parameter. See the console.doc autodoc for the most up to date information.&lt;br /&gt;
&lt;br /&gt;
See the include file devices/conunit.h for the flag definitions and the SDK for an explanation of the flags.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct NewWindow nw =&lt;br /&gt;
{&lt;br /&gt;
    10, 10,                    /* starting position (left,top) */&lt;br /&gt;
    620,180,                   /* width, height */&lt;br /&gt;
    -1,-1,                     /* detailpen, blockpen */&lt;br /&gt;
    CLOSEWINDOW,               /* flags for idcmp */&lt;br /&gt;
    WINDOWDEPTH|WINDOWSIZING|&lt;br /&gt;
    WINDOWDRAG|WINDOWCLOSE|&lt;br /&gt;
    SIMPLE_REFRESH|ACTIVATE,    /* window flags */&lt;br /&gt;
    NULL,                      /* no user gadgets */&lt;br /&gt;
    NULL,                      /* no user checkmark */&lt;br /&gt;
    &amp;quot;Console Test&amp;quot;,            /* title */&lt;br /&gt;
    NULL,                      /* pointer to window screen */&lt;br /&gt;
    NULL,                      /* pointer to super bitmap */&lt;br /&gt;
    100,45,                    /* min width, height */&lt;br /&gt;
    640,200,                   /* max width, height */&lt;br /&gt;
    WBENCHSCREEN               /* open on workbench screen */&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
    /* Create reply port console */&lt;br /&gt;
struct MsgPort *ConsoleMP = IExec-&amp;gt;AllocSysObjectTags(ASOT_PORT,&lt;br /&gt;
     ASOPORT_Name, &amp;quot;RKM.Console&amp;quot;,&lt;br /&gt;
     TAG_END);&lt;br /&gt;
if (ConsoleMP == NULL)&lt;br /&gt;
    cleanexit(&amp;quot;Can&#039;t create write port\n&amp;quot;, RETURN_FAIL);&lt;br /&gt;
&lt;br /&gt;
    /* Create message block for device I/O */&lt;br /&gt;
struct IOStdReq *ConsIO = IExec-&amp;gt;AllocSysObjectTags(ASOT_IOREQUEST,&lt;br /&gt;
    ASOIOR_Size, sizeof(struct IOStdReq),&lt;br /&gt;
    ASOIOR_ReplyPort, ConsoleMP,&lt;br /&gt;
    TAG_END);&lt;br /&gt;
if (ConsIO == NULL)&lt;br /&gt;
    cleanexit(&amp;quot;Can&#039;t create IORequest\n&amp;quot;, RETURN_FAIL);&lt;br /&gt;
&lt;br /&gt;
    /* Open a window --- we assume intuition.library is already open */&lt;br /&gt;
struct Window *win = IIntuition-&amp;gt;OpenWindow(&amp;amp;nw);&lt;br /&gt;
if (win == NULL)&lt;br /&gt;
    cleanexit(&amp;quot;Can&#039;t open window\n&amp;quot;,RETURN_FAIL);&lt;br /&gt;
&lt;br /&gt;
    /* Set window pointer and size in I/O request */&lt;br /&gt;
ConsIO-&amp;gt;io_Data = (APTR) win;&lt;br /&gt;
ConsIO-&amp;gt;io_Length = sizeof(struct Window);&lt;br /&gt;
&lt;br /&gt;
    /* Open the console device */&lt;br /&gt;
if (error = IExec-&amp;gt;OpenDevice(&amp;quot;console.device&amp;quot;, CONU_CHARMAP, ConsIO, CONFLAG_DEFAULT))&lt;br /&gt;
    cleanexit(&amp;quot;Can&#039;t open console.device\n&amp;quot;,RETURN_FAIL);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Closing the Console Device ===&lt;br /&gt;
&lt;br /&gt;
Each OpenDevice() must eventually be matched by a call to CloseDevice().&lt;br /&gt;
&lt;br /&gt;
All I/O requests must be complete before CloseDevice(). If any requests are still pending, abort them with AbortIO().&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
if (!(IExec-&amp;gt;CheckIO(ConsIO)))&lt;br /&gt;
    IExec-&amp;gt;AbortIO(ConsIO);      /* Ask device to abort any pending requests */&lt;br /&gt;
&lt;br /&gt;
IExec-&amp;gt;WaitIO(ConsIO);           /* Wait for abort, then clean up */&lt;br /&gt;
IExec-&amp;gt;CloseDevice(ConsIO);      /* Close console device */&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== About Console I/O ==&lt;br /&gt;
&lt;br /&gt;
The console device may be thought of as a kind of terminal. You send character streams to the console device; you also receive them from the console device. These streams may be characters, control sequences or a combination of the two.&lt;br /&gt;
&lt;br /&gt;
Console I/O is closely associated with the Amiga Intuition interface; a console must be tied to a window that is already opened. From the Window data structure, the console device determines how many characters it can display on a line and how many lines of text it can display in a window without clipping at any edge.&lt;br /&gt;
&lt;br /&gt;
You can open the console device many times, if you wish. The result of each open call is a new console unit. AmigaDOS and Intuition see to it that only one window is currently active and its console, if any, is the only one (with a few exceptions) that receives notification of input events, such as keystrokes. Later in this article you will see that other Intuition events can be sensed by the console device as well.&lt;br /&gt;
&lt;br /&gt;
{{Note|title=Introducing...|text=For this entire article the characters &amp;lt;CSI&amp;gt; represent the &#039;&#039;control sequence introducer&#039;&#039;. For output you may use either the two-character sequence &amp;lt;Esc&amp;gt;[ (0x1B 0x5B) or the one-byte value 0x9B. For input you will receive 0x9B unless the sequence has been typed by the user.}}&lt;br /&gt;
&lt;br /&gt;
=== Exec Functions and the Console Device ===&lt;br /&gt;
&lt;br /&gt;
The various Exec functions such as DoIO(), SendIO(), AbortIO() and CheckIO() operate normally. The only caveats are that CMD_WRITE may cause your application to wait internally, even with SendIO(), and a task using CMD_READ to wait on a response from a console is at the user’s mercy. If the user never reselects that window, and the console response provides the only wake-up call, that task will sleep forever.&lt;br /&gt;
&lt;br /&gt;
=== General Console Screen Output ===&lt;br /&gt;
&lt;br /&gt;
Console character screen output (as compared to console command sequence transmission) outputs all standard printable characters (character values hex 20 through 7E and A0 through FF) normally.&lt;br /&gt;
&lt;br /&gt;
Many control characters such as &#039;&#039;&#039;Backspace&#039;&#039;&#039; (0x08) and &#039;&#039;&#039;Return&#039;&#039;&#039; (0x0D) are translated into their exact ANSI equivalent actions. The &#039;&#039;&#039;Line feed&#039;&#039;&#039; character (0x0A) is a bit different in that it can be translated into a &#039;&#039;&#039;Return/Line feed&#039;&#039;&#039; action. The net effect is that the cursor moves to the first column of the next line whenever an &amp;amp;lt;LF&amp;amp;gt; is displayed. This option is set via the mode control sequences discussed under “Control Sequences for Window Output.”&lt;br /&gt;
&lt;br /&gt;
=== Console Keyboard Input ===&lt;br /&gt;
&lt;br /&gt;
If you read from the console device, the keyboard inputs are preprocessed for you and you will get ASCII characters, such as “B.” Most normal text-gathering programs will read from the console device in this manner. Some programs may also ask to receive raw events in their console stream. Keypresses are converted to ASCII characters or CSI sequences via the keymap associated with the unit.&lt;br /&gt;
&lt;br /&gt;
== Writing to the Console Device ==&lt;br /&gt;
&lt;br /&gt;
You write to the console device by passing an I/O request to the device with a pointer to the write buffer set in io_Data, the number of bytes in the buffer set in io_Length and CMD_WRITE set in io_Command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
CONST_STRPTR outstring= &amp;quot;Make it so&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
ConsIO-&amp;gt;io_Data    = outstring;&lt;br /&gt;
ConsIO-&amp;gt;io_Length  = IUtility-&amp;gt;Strlen(outstring);&lt;br /&gt;
ConsIO-&amp;gt;io_Command = CMD_WRITE;&lt;br /&gt;
IExec-&amp;gt;DoIO(ConsIO);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You may also send NULL-terminated strings to the console device in the same manner except that io_Length must be set to -1.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
ConsIO-&amp;gt;io_Data    = &amp;quot;\033[3mOh boy.&amp;quot;;&lt;br /&gt;
ConsIO-&amp;gt;io_Length  = -1;&lt;br /&gt;
ConsIO-&amp;gt;io_Command = CMD_WRITE;&lt;br /&gt;
IExec-&amp;gt;DoIO(ConsIO);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The fragment above will output the string “Oh boy.” in italics. Keep in mind that setting the text rendition to italics will remain in effect until you specifically instruct the console device to change it to another text style.&lt;br /&gt;
&lt;br /&gt;
=== Synchronized Writes ===&lt;br /&gt;
&lt;br /&gt;
Synchronized writes were the only option for Console Device before version 53.38. Returning from the Write call means that the data has been transferred from the caller&#039;s buffer and the IORequest structure contents are no longer required. The data may not yet have been written to the display and any effects caused by the data (e.g. change of cursor position) may not yet have started or been completed.&lt;br /&gt;
&lt;br /&gt;
If the Console was opened in legacy mode (no TABBED or HISTORY options), then the SYNCWRITES option is forced for greater compatibility with older applications. Otherwise, the Console is opened with synchronized writes disabled. This enables the application to continue to do work while the Console works in parallel.&lt;br /&gt;
&lt;br /&gt;
You can still force the Write operation to block until completed by opening the Console with the CONFLAG_SYNC_WRITES set or (for a Shell) including the option SYNCWRITES in the command line.&lt;br /&gt;
&lt;br /&gt;
If you do not want to wait for all Write requests, you can set the IOF_WAIT_WRITE bit in the io_Flags byte before calling CMD_WRITE. This flag bit has the same effect as opening the console with the CONFLAG_SYNC_WRITES set, but its scope is limited to the current IORequest.&lt;br /&gt;
&lt;br /&gt;
=== Control Sequences for Window Output ===&lt;br /&gt;
&lt;br /&gt;
The following table lists functions that the console device supports, along with the character stream that you must send to the console to produce the effect. For more information on the control sequences, consult the console.doc in the SDK. The table uses the second form of &amp;amp;lt;CSI&amp;amp;gt;, that is, the hex value 0x9B, to minimize the number of characters to be transmitted to produce a function.&lt;br /&gt;
&lt;br /&gt;
A couple of notes about the table. If an item is enclosed in square brackets, it is optional and may be omitted. For example, for &#039;&#039;&#039;Insert [N] Characters&#039;&#039;&#039; the value for &#039;&#039;N&#039;&#039; is shown as optional. The console device responds to such optional items by treating the value of &#039;&#039;N&#039;&#039; as 1 if it is not specified. The value of &#039;&#039;N&#039;&#039; or &#039;&#039;M&#039;&#039; is always a decimal number, having one or more ASCII digits to express its value.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ ANSI Console Control Sequences&lt;br /&gt;
! Console Command&lt;br /&gt;
! Comment&lt;br /&gt;
! Sequence of Characters (in Hexadecimal Form)&lt;br /&gt;
|-&lt;br /&gt;
| Bell || Flash the display—do an Intuition DisplayBeep() || 07&lt;br /&gt;
|-&lt;br /&gt;
| Backspace || Move left one column || 08&lt;br /&gt;
|-&lt;br /&gt;
| Horizontal Tab || Move right one tab stop || 09&lt;br /&gt;
|-&lt;br /&gt;
| Line Feed || Move down one text line as specified by the mode function || 0A&lt;br /&gt;
|-&lt;br /&gt;
| Vertical Tab || Move up one text line || 0B&lt;br /&gt;
|-&lt;br /&gt;
| Form Feed || Clear the console’s window || 0C&lt;br /&gt;
|-&lt;br /&gt;
| Carriage Return || Move to first column || 0D&lt;br /&gt;
|-&lt;br /&gt;
| Shift In || Undo Shift Out || OE&lt;br /&gt;
|-&lt;br /&gt;
| Shift Out || Set MSB of each character before displaying || 0F&lt;br /&gt;
|-&lt;br /&gt;
| Esc || Escape can be part of the control sequence introducer || 1B&lt;br /&gt;
|-&lt;br /&gt;
| Index || Move the active position down one line || 84&lt;br /&gt;
|-&lt;br /&gt;
| Next Line || Go to the beginning of the next line || 85&lt;br /&gt;
|-&lt;br /&gt;
| Horizontal Tabulation || Set a tab at the active cursor position || 88&lt;br /&gt;
|-&lt;br /&gt;
| Reverse Index || Move the active position up one line || 8D&lt;br /&gt;
|-&lt;br /&gt;
| CSI || Control sequence introducer || 9B&lt;br /&gt;
|-&lt;br /&gt;
| Reset to Initial State || || 1B 63&lt;br /&gt;
|-&lt;br /&gt;
| Insert [N] Characters || Insert one or more spaces, shifting the remainder of the line to the right || 9B [N] 40&lt;br /&gt;
|-&lt;br /&gt;
| Cursor Up [N] Character Positions || (default = 1) || 9B [N] 41&lt;br /&gt;
|-&lt;br /&gt;
| Cursor Down [N] Character Positions || (default = 1) || 9B [N] 42&lt;br /&gt;
|-&lt;br /&gt;
| Cursor Forward [N] Character Positions || (default = 1) || 9B [N] 43&lt;br /&gt;
|-&lt;br /&gt;
| Cursor Backward [N] Character Positions || (default = 1) || 9B [N] 44&lt;br /&gt;
|-&lt;br /&gt;
| Cursor Position || Where &#039;&#039;N&#039;&#039; is row, &#039;&#039;M&#039;&#039; is column, and semicolon (hex 3B) must be present as a separator, or if row is left out, so the console device can tell that the number after the semicolon actually represents the column number || 9B [N] [3B M] 48&lt;br /&gt;
|-&lt;br /&gt;
| Cursor Horizontal Tabulation || move cursor forward to &#039;&#039;N&#039;&#039;th tab position || 9B [N] 49&lt;br /&gt;
|-&lt;br /&gt;
| Cursor Next Line [N] || (to column 1) || 9B [N] 45&lt;br /&gt;
|-&lt;br /&gt;
| Cursor Preceding Line [N] || (to column 1) || 9B [N] 46&lt;br /&gt;
|-&lt;br /&gt;
| Erase in Display || (only to end of display) || 9B 4A&lt;br /&gt;
|-&lt;br /&gt;
| Erase in Line || (only to end of line) || 9B 4B&lt;br /&gt;
|-&lt;br /&gt;
| Insert Line || Above the line containing the cursor || 9B 4C&lt;br /&gt;
|-&lt;br /&gt;
| Delete Line || Remove current line, move all lines up one position to fill gap, blank bottom line || 9B 4D&lt;br /&gt;
|-&lt;br /&gt;
| Delete Character [N] || That cursor is sitting on and to the right if [N] is specified || 9B [N] 50&lt;br /&gt;
|-&lt;br /&gt;
| Scroll up [N] Lines || Remove line(s) from top of window, move all other lines up, blanks [N] bottom lines || 9B [N] 53&lt;br /&gt;
|-&lt;br /&gt;
| Scroll down [N] Lines || Remove line(s) from bottom of window, move all other lines down, blanks [N] top lines || 9B [N] 54&lt;br /&gt;
|-&lt;br /&gt;
| Cursor Tabulation Control || where &#039;&#039;N&#039;&#039;=0 set tab, &#039;&#039;N&#039;&#039;=2 clear tab, &#039;&#039;N&#039;&#039;=5 clear all tabs || 9B [N] 57&lt;br /&gt;
|-&lt;br /&gt;
| Cursor Backward Tabulation || move cursor backward to &#039;&#039;N&#039;&#039;th tab position || 9B [N] 5A&lt;br /&gt;
|-&lt;br /&gt;
| Set Line Feed Mode || Cause &#039;&#039;&#039;Line Feed&#039;&#039;&#039; to respond as Return-Line Feed || 9B 32 30 68&lt;br /&gt;
|-&lt;br /&gt;
| Reset Newline Mode || Cause &#039;&#039;&#039;Line Feed&#039;&#039;&#039; to respond only as Line Feed || 9B 32 30 6C&lt;br /&gt;
|-&lt;br /&gt;
| Device Status Report || Cause console device to insert a &#039;&#039;&#039;Cursor&#039;&#039;&#039; Position Report into your read stream; see “Reading from the Console Device” for more information || 9B 36 6E&lt;br /&gt;
|-&lt;br /&gt;
| Select Graphic Rendition || Select text style (K), character color (L), character cell color (M), background color (N). See note below. || 9B K 3B 3L 3B 4M 3B &amp;amp;gt;N 6D&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
For &#039;&#039;&#039;Select Graphic Rendition&#039;&#039;&#039;, any number of parameters, in any order, are valid. They are separated by semicolons. The parameters follow:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| 0 || Plain text&lt;br /&gt;
|-&lt;br /&gt;
| 1 || Boldface&lt;br /&gt;
|-&lt;br /&gt;
| 2 || faint (secondary color)&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Italic&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Underscore&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Set slow character blink (V53.5)&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Set fast character blink (V53.5)&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Reversed character/cell colors&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Concealed mode&lt;br /&gt;
|-&lt;br /&gt;
| 22 || Normal color, not bold (V36)&lt;br /&gt;
|-&lt;br /&gt;
| 23 || Italic off (V36)&lt;br /&gt;
|-&lt;br /&gt;
| 24 || Underscore off (V36)&lt;br /&gt;
|-&lt;br /&gt;
| 25 || Slow blink off (V53.5)&lt;br /&gt;
|-&lt;br /&gt;
| 26 || Fast blink off (V53.5)&lt;br /&gt;
|-&lt;br /&gt;
| 27 || Reversed off (V36)&lt;br /&gt;
|-&lt;br /&gt;
| 28 || Concealed off (V36)&lt;br /&gt;
|-&lt;br /&gt;
| 29 || Strike-through off (V53.5)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| 30–37 || System colors 0–7 for character color.&lt;br /&gt;
|-&lt;br /&gt;
| 39 || Reset to default character color&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Transmitted as two ASCII characters.&lt;br /&gt;
| 40–47 || System colors 0–7 for character cell color.&lt;br /&gt;
|-&lt;br /&gt;
| 39 || Reset to default character color&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Transmitted as two ASCII characters&lt;br /&gt;
| &amp;gt;0–7 || System colors 0–7 for background color. (V36)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
You must specify the “&amp;gt;” in order for this to be recognized and it must be the last parameter.&lt;br /&gt;
&lt;br /&gt;
For example, to select bold face, with color 3 as the character color, and color 0 as the character cell color and the background color, send the hex sequence:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;9B 31 3B 33 33 3B 34 30 3B 3E 30 6D&amp;lt;/pre&amp;gt;&lt;br /&gt;
representing the ASCII sequence:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;amp;lt;CSI&amp;amp;gt;1;33;40;&amp;amp;gt;0m&amp;lt;/pre&amp;gt;&lt;br /&gt;
where &amp;amp;lt;CSI&amp;amp;gt; is the control sequence introducer, here used as the single character value 0x9B.&lt;br /&gt;
&lt;br /&gt;
{{Note|title=Go Easy On The Eyes|text=In most cases, the character cell color and the background color should be the same.}}&lt;br /&gt;
&lt;br /&gt;
==== Set Graphic Rendition Implementation Notes ====&lt;br /&gt;
&lt;br /&gt;
The sequences in the next table are not ANSI standard sequences, they are private Amiga sequences. In these command descriptions, length, width, and offset are comprised of one or more ASCII digits, defining a decimal value.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Amiga Console Control Sequences&lt;br /&gt;
! Console Command&lt;br /&gt;
! Comment&lt;br /&gt;
! Sequence of Characters (in Hexadecimal Form)&lt;br /&gt;
|-&lt;br /&gt;
| Enable Scroll || (this is the default) || 9B 3E 31 68&lt;br /&gt;
|-&lt;br /&gt;
| Disable Scroll || || 9B 3E 31 6C&lt;br /&gt;
|-&lt;br /&gt;
| Autowrap On || (the default) || 9B 3F 37 68&lt;br /&gt;
|-&lt;br /&gt;
| Autowrap Off || || 9B 3F 37 6C&lt;br /&gt;
|-&lt;br /&gt;
| Set Page Length || In character raster lines, causes console to recalculate, using current font, how many text lines will fit on the page || 9B &amp;amp;lt;length&amp;amp;gt; 74&lt;br /&gt;
|-&lt;br /&gt;
| Set Line Length || In character positions, using current font, how many characters should be placed on each line&lt;br /&gt;
 || 9B &amp;amp;lt;width&amp;amp;gt; 75&lt;br /&gt;
|-&lt;br /&gt;
| Set Left Offset || In raster columns, how far from the left of the window should the text begin || 9B &amp;amp;lt;offset&amp;amp;gt; 78&lt;br /&gt;
|-&lt;br /&gt;
| Set Top Offset || In raster lines, how far from the top of the window’s RastPort should the topmost line of the character begin || 9B &amp;amp;lt;offset&amp;amp;gt; 79&lt;br /&gt;
|-&lt;br /&gt;
| Set Raw Events || Set the raw input events that will trigger an &#039;&#039;&#039;Input Event Report&#039;&#039;&#039;. see the “Selecting Raw Input Events” section below for more details. || 9B &amp;amp;lt;events&amp;amp;gt; 7B&lt;br /&gt;
|-&lt;br /&gt;
| Input Event Report || Returned by the console device in response to a raw event set by the &#039;&#039;&#039;Set Raw Event&#039;&#039;&#039; sequence. See the “Input Event Reports” section below for more details. || 9B &amp;amp;lt;parameters&amp;amp;gt; 7C&lt;br /&gt;
|-&lt;br /&gt;
| Reset Raw Events || Reset the raw events set by the &#039;&#039;&#039;Set Raw Event&#039;&#039;&#039; sequence. see the “Selecting Raw Input Events” section below. || 9B &amp;amp;lt;events&amp;amp;gt; 7D&lt;br /&gt;
|-&lt;br /&gt;
| Special Key Report || Returned by the console device whenever &#039;&#039;&#039;Help&#039;&#039;&#039;, or one of the function keys or arrow keys is pressed. Some sequences do not end with 7E || 9B &amp;amp;lt;keyvalue&amp;amp;gt; 7E&lt;br /&gt;
|-&lt;br /&gt;
| Set Cursor Rendition || Make the cursor visible or invisible; turning off the cursor increases text output speed || 9B N 20 70 &amp;lt;br/&amp;gt; Invisible = 9B 30 20 70 &amp;lt;br/&amp;gt; Visible = 9B 20 70&lt;br /&gt;
|-&lt;br /&gt;
| Window Status Request || Ask the console device to tell you the current bounds of the window, in upper and lower row and column character positions. User may have resized or repositioned it. See “Window Bounds Report” below. || 9B 30 20 71&lt;br /&gt;
|-&lt;br /&gt;
| Window Bounds Report || Returned by the console device in response to a &#039;&#039;&#039;Window Status Request&#039;&#039;&#039; sequence || 9B 31 3B 31 3B &amp;amp;lt;bottom margin&amp;amp;gt; 3B &amp;amp;lt;right margin&amp;amp;gt; 72&lt;br /&gt;
|-&lt;br /&gt;
| Right ‘Amiga V’ Press || Returned by the console device when the user presses &#039;&#039;&#039;Right-Amiga-V&#039;&#039;&#039;. See the “Copy and Paste Support” section below for more details. || 9B 30 20 76&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{{Note|title=Give Back What You Take|text=The console device normally handles the &#039;&#039;&#039;Set Page Length&#039;&#039;&#039;, &#039;&#039;&#039;Set Line Length&#039;&#039;&#039;, &#039;&#039;&#039;Set Left Offset&#039;&#039;&#039;, and &#039;&#039;&#039;Set Top Offset&#039;&#039;&#039; functions automatically. To allow it to do so again after setting your own values, send the functions without a parameter.}}&lt;br /&gt;
&lt;br /&gt;
=== Example Console Control Sequences ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| Move cursor right by 1 || &amp;amp;lt;CSI&amp;amp;gt;C or &amp;lt;br/&amp;gt; &amp;amp;lt;CSI&amp;amp;gt;1C || 9B 43 &amp;lt;br/&amp;gt; 9B 31 43&lt;br /&gt;
|-&lt;br /&gt;
| Move cursor right by 20 || &amp;amp;lt;CSI&amp;amp;gt;20C || 9B 32 30 43&lt;br /&gt;
|-&lt;br /&gt;
| Move cursor to upper-left corner (Home Position) || &amp;amp;lt;CSI&amp;amp;gt;H or &amp;lt;br/&amp;gt; &amp;amp;lt;CSI&amp;amp;gt;1;1H or &amp;lt;br/&amp;gt; &amp;amp;lt;CSI&amp;amp;gt;;1H or &amp;lt;br/&amp;gt; &amp;amp;lt;CSI&amp;amp;gt;1;H || 9B 48 &amp;lt;br/&amp;gt; 9B 31 3B 31 48 &amp;lt;br/&amp;gt; 9B 3B 31 48 &amp;lt;br/&amp;gt; 9B 31 3B 48&lt;br /&gt;
|-&lt;br /&gt;
| Move cursor to the fourth column of the first line of the window || &amp;amp;lt;CSI&amp;amp;gt;1;4H or &amp;lt;br/&amp;gt; &amp;amp;lt;CSI&amp;amp;gt;;4H || 9B 31 3B 34 48 &amp;lt;br/&amp;gt; 9B 3B 34 48&lt;br /&gt;
|-&lt;br /&gt;
| Clear the window || &amp;amp;lt;FF&amp;amp;gt; or Ctrl-L (clear window) or &amp;lt;br/&amp;gt; &amp;amp;lt;CSI&amp;amp;gt;H&amp;amp;lt;CSI&amp;amp;gt;J (home and clear to end of window) || 0C &amp;lt;br/&amp;gt; 9B 48 9B 4A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Reading from the Console Device ==&lt;br /&gt;
&lt;br /&gt;
Reading input from the console device returns an ANSI 3.64 standard byte stream. This stream may contain normal characters and/or raw input event information. You may also request other raw input events using the &#039;&#039;&#039;Set Raw Events&#039;&#039;&#039; and &#039;&#039;&#039;Reset Raw Events&#039;&#039;&#039; control sequences discussed below. See “Selection of Raw Input Events.”&lt;br /&gt;
&lt;br /&gt;
Generally, console reads are performed asynchronously so that your program can respond to other events and other user input (such as menu selections) when the user is not typing on the keyboard. To perform asynchronous I/O, an I/O request is sent to the console using the SendIO() function (rather than a synchronous DoIO() which would wait until the read request returned with a character).&lt;br /&gt;
&lt;br /&gt;
You read from the console device by passing an I/O request to the device with a pointer to the read buffer set in io_Data, the number of bytes in the buffer set in io_Length and CMD_READ set in io_Command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
#define READ_BUFFER_SIZE 25&lt;br /&gt;
char ConsoleReadBuffer[READ_BUFFER_SIZE];&lt;br /&gt;
&lt;br /&gt;
ConsIO-&amp;gt;io_Data    = (APTR)ConsoleReadBuffer;&lt;br /&gt;
ConsIO-&amp;gt;io_Length  = READ_BUFFER_SIZE;&lt;br /&gt;
ConsIO-&amp;gt;io_Command = CMD_READ;&lt;br /&gt;
IExec-&amp;gt;SendIO(ConsIO);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Note|title=You May Get Less Than You Bargained For|text=A request for more than one character may be satisfied by the receipt of only one character. If you request more than one character, you will have to examine the io_Actual field of the request when it returns to determine how many characters you have actually received.}}&lt;br /&gt;
&lt;br /&gt;
After sending the read request, your program can wait on a combination of signal bits including that of the reply port you created. The following fragment demonstrates waiting on both a queued console read request, and Window IDCMP messages:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
uint32 conreadsig = 1 &amp;lt;&amp;lt; ConsoleMP-&amp;gt;mp_SigBit;&lt;br /&gt;
uint32 windowsig = 1 &amp;lt;&amp;lt; win-&amp;gt;UserPort-&amp;gt;mp_SigBit;&lt;br /&gt;
&lt;br /&gt;
/* A character, or an IDCMP msg, or both will wake us up */&lt;br /&gt;
ULONG signals = IExec-&amp;gt;Wait(conreadsig | windowsig);&lt;br /&gt;
&lt;br /&gt;
if (signals &amp;amp; conreadsig)&lt;br /&gt;
    {&lt;br /&gt;
    /* Then check for a character */&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
if (signals &amp;amp; windowsig)&lt;br /&gt;
    {&lt;br /&gt;
    /* Then check window messages */&lt;br /&gt;
    };&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Information About the Input Stream ===&lt;br /&gt;
&lt;br /&gt;
For the most part, keys whose keycaps are labeled with ANSI-standard characters will ordinarily be translated into their ASCII-equivalent character by the console device through the use of its keymap. Keymap information can be found in [[Keymap_Library|Keymap Library]].&lt;br /&gt;
&lt;br /&gt;
For keys other than those with normal ASCII equivalents, an escape sequence is generated and inserted into your input stream. For example, in the default state (no raw input events selected) the function, arrow and special keys (reserved for 101 key keyboards) will cause the sequences shown in the next table to be inserted in the input stream.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Special Key Report Sequences&lt;br /&gt;
! Key&lt;br /&gt;
! Unshifted Sends &lt;br /&gt;
! Shifted Sends&lt;br /&gt;
! Comment&lt;br /&gt;
|-&lt;br /&gt;
| F1 || &amp;amp;lt;CSI&amp;amp;gt;0 || &amp;amp;lt;CSI&amp;amp;gt;10 ||&lt;br /&gt;
|-&lt;br /&gt;
| F2 || &amp;amp;lt;CSI&amp;amp;gt;1 || &amp;amp;lt;CSI&amp;amp;gt;11 ||&lt;br /&gt;
|-&lt;br /&gt;
| F3 || &amp;amp;lt;CSI&amp;amp;gt;2 || &amp;amp;lt;CSI&amp;amp;gt;12 ||&lt;br /&gt;
|-&lt;br /&gt;
| F4 || &amp;amp;lt;CSI&amp;amp;gt;3 || &amp;amp;lt;CSI&amp;amp;gt;13 ||&lt;br /&gt;
|-&lt;br /&gt;
| F5 || &amp;amp;lt;CSI&amp;amp;gt;4 || &amp;amp;lt;CSI&amp;amp;gt;14 ||&lt;br /&gt;
|-&lt;br /&gt;
| F6 || &amp;amp;lt;CSI&amp;amp;gt;5 || &amp;amp;lt;CSI&amp;amp;gt;15 ||&lt;br /&gt;
|-&lt;br /&gt;
| F7 || &amp;amp;lt;CSI&amp;amp;gt;6 || &amp;amp;lt;CSI&amp;amp;gt;16 ||&lt;br /&gt;
|-&lt;br /&gt;
| F8 || &amp;amp;lt;CSI&amp;amp;gt;7 || &amp;amp;lt;CSI&amp;amp;gt;17 ||&lt;br /&gt;
|-&lt;br /&gt;
| F9 || &amp;amp;lt;CSI&amp;amp;gt;8 || &amp;amp;lt;CSI&amp;amp;gt;18 ||&lt;br /&gt;
|-&lt;br /&gt;
| F10 || &amp;amp;lt;CSI&amp;amp;gt;9 || &amp;amp;lt;CSI&amp;amp;gt;19 ||&lt;br /&gt;
|-&lt;br /&gt;
| F11 || &amp;amp;lt;CSI&amp;amp;gt;20 || &amp;amp;lt;CSI&amp;amp;gt;30 || (101 key keyboard)&lt;br /&gt;
|-&lt;br /&gt;
| F12 || &amp;amp;lt;CSI&amp;amp;gt;21 || &amp;amp;lt;CSI&amp;amp;gt;31 || (101 key keyboard)&lt;br /&gt;
|-&lt;br /&gt;
| Help || &amp;amp;lt;CSI&amp;amp;gt;? || &amp;amp;lt;CSI&amp;amp;gt;? || (same sequence for both)&lt;br /&gt;
|-&lt;br /&gt;
| Insert || &amp;amp;lt;CSI&amp;amp;gt;40 || &amp;amp;lt;CSI&amp;amp;gt;50 || (101 key keyboard)&lt;br /&gt;
|-&lt;br /&gt;
| Page Up || &amp;amp;lt;CSI&amp;amp;gt;41 || &amp;amp;lt;CSI&amp;amp;gt;51 || (101 key keyboard)&lt;br /&gt;
|-&lt;br /&gt;
| Page Down || &amp;amp;lt;CSI&amp;amp;gt;42 || &amp;amp;lt;CSI&amp;amp;gt;52 || (101 key keyboard)&lt;br /&gt;
|-&lt;br /&gt;
| Pause/Break || &amp;amp;lt;CSI&amp;amp;gt;43 || &amp;amp;lt;CSI&amp;amp;gt;53 || (101 key keyboard)&lt;br /&gt;
|-&lt;br /&gt;
| Home || &amp;amp;lt;CSI&amp;amp;gt;44 || &amp;amp;lt;CSI&amp;amp;gt;54 || (101 key keyboard)&lt;br /&gt;
|-&lt;br /&gt;
| End || &amp;amp;lt;CSI&amp;amp;gt;45 || &amp;amp;lt;CSI&amp;amp;gt;55 || (101 key keyboard)&lt;br /&gt;
|-&lt;br /&gt;
| Cursor Up || &amp;amp;lt;CSI&amp;amp;gt;A || &amp;amp;lt;CSI&amp;amp;gt;T ||&lt;br /&gt;
|-&lt;br /&gt;
| Cursor Down || &amp;amp;lt;CSI&amp;amp;gt;B || &amp;amp;lt;CSI&amp;amp;gt;S ||&lt;br /&gt;
|-&lt;br /&gt;
| Cursor Left || &amp;amp;lt;CSI&amp;amp;gt;D || &amp;amp;lt;CSI&amp;amp;gt; A || (notice the space after &amp;amp;lt;CSI&amp;amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| Cursor Right || &amp;amp;lt;CSI&amp;amp;gt;C || &amp;amp;lt;CSI&amp;amp;gt; @ || (notice the space after &amp;amp;lt;CSI&amp;amp;gt;)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Cursor Position Report ===&lt;br /&gt;
&lt;br /&gt;
If you have sent the &#039;&#039;&#039;Device Status Report&#039;&#039;&#039; command sequence, the console device returns a cursor position report into your input stream. It takes the form:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;amp;lt;CSI&amp;amp;gt;&amp;amp;lt;row&amp;amp;gt;;&amp;amp;lt;column&amp;amp;gt;R&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For example, if the cursor is at column 40 and row 12, here are the ASCII values (in hex) you receive in a stream:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
9B 34 30 3B 31 32 52&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Window Bounds Report ===&lt;br /&gt;
&lt;br /&gt;
A user may have either moved or resized the window to which your console is bound. By issuing a &#039;&#039;&#039;Window Status Report&#039;&#039;&#039; to the console, you can read the current position and size in the input stream. This window bounds report takes the following form:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;amp;lt;CSI&amp;amp;gt;1;1;&amp;amp;lt;bottom margin&amp;amp;gt;;&amp;amp;lt;right margin&amp;amp;gt; r&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The bottom and right margins give you the window row and column dimensions as well. For a window that holds 20 lines with 60 characters per line, you will receive the following in the input stream:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
9B 31 3B 31 3B 32 30 3B 36 30 20 72&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Copy and Paste Support ==&lt;br /&gt;
&lt;br /&gt;
As noted above, opening the console device with a unit of CONU_SNIPMAP allows the user to drag-select text with the mouse and copy the selection with &#039;&#039;&#039;Right-Amiga-C&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Internally, the snip is copied to a private buffer managed by the console device where it can be copied to other console device windows by pressing &#039;&#039;&#039;Right-Amiga-V&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
However, your application should assume that the user is running the “Conclip” utility which is part of the standard Workbench 2.0 environment. Conclip copies snips from the console device to the clipboard device where they can be used by other applications which support reading from the clipboard.&lt;br /&gt;
&lt;br /&gt;
When Conclip is running and the user presses &#039;&#039;&#039;Right-Amiga-V&#039;&#039;&#039;, the console device puts an escape sequence in your read stream—&amp;amp;lt;CSI&amp;amp;gt;0 v (Hex 9B 30 20 76)—which tells you that the user wants to paste text from the clipboard.&lt;br /&gt;
&lt;br /&gt;
Upon receipt of this sequence, your application should read the contents of the clipboard device, make a copy of any text found there and then release the clipboard so that it can be used by other applications. See [[Clipboard_Device|Clipboard Device]] for more information on reading data from it.&lt;br /&gt;
&lt;br /&gt;
You paste what you read from the clipboard by using successive writes to the console. In order to avoid problems with excessively long data in the clipboard, you should limit the size of writes to something reasonable. (We define reasonable as no more than 1K per write with the ideal amount being 256 bytes.) You should also continue to monitor the console read stream for additional use input, paster requests and, possibly, &#039;&#039;&#039;Raw Input Events&#039;&#039;&#039; while you are doing this.&lt;br /&gt;
&lt;br /&gt;
You should &#039;&#039;not&#039;&#039; open a character mapped console unit with COPY capability if you are unable to support &#039;&#039;&#039;Paste&#039;&#039;&#039; from the clipboard device. The user will reasonably expect to be able to &#039;&#039;&#039;Paste&#039;&#039;&#039; into windows from which a &#039;&#039;&#039;Copy&#039;&#039;&#039; can be done.&lt;br /&gt;
&lt;br /&gt;
Keep in mind that users do make mistakes, so an &#039;&#039;&#039;Undo&#039;&#039;&#039; mechanism for aborting a &#039;&#039;&#039;Paste&#039;&#039;&#039; is highly desirable—particularly if the user has just accidentally pasted text into an application like a terminal program which is sending data at a slow rate.&lt;br /&gt;
&lt;br /&gt;
{{Note|title=Use “CON:”, You’ll Be Glad You Did|text=It is highly recommended that you consider using the console-handler (CON:) if you want a console window with &#039;&#039;&#039;Copy&#039;&#039;&#039; and &#039;&#039;&#039;Paste&#039;&#039;&#039; capabilities. CON: provides you with free &#039;&#039;&#039;Paste&#039;&#039;&#039; support and is considerably easier to open and use than using the console device directly.}}&lt;br /&gt;
&lt;br /&gt;
== Selecting Raw Input Events ==&lt;br /&gt;
&lt;br /&gt;
If the keyboard information–including “cooked” keystrokes–does not give you enough information about input events, you can request additional information from the console driver.&lt;br /&gt;
&lt;br /&gt;
The command to &#039;&#039;&#039;Set Raw Events&#039;&#039;&#039; is formatted as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;amp;lt;CSI&amp;amp;gt;[event-types-separated-by-semicolons]{&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If, for example, you need to know when each key is pressed and released, you would request “Raw keyboard input.” This is done by writing &amp;amp;lt;CSI&amp;amp;gt;1&amp;lt;math&amp;gt;\{&amp;lt;/math&amp;gt; to the console. In a single &#039;&#039;&#039;Set Raw Events&#039;&#039;&#039; request, you can ask the console to set up for multiple event types at one time. You must send multiple numeric parameters, separating them by semicolons (;). For example, to ask for gadget pressed, gadget released, and close gadget events, write:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;amp;lt;CSI&amp;amp;gt;7;8;11{&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can reset, that is, delete from reporting, one or more of the raw input event types by using the &#039;&#039;&#039;Reset Raw Events&#039;&#039;&#039; command, in the same manner as the &#039;&#039;&#039;Set Raw Events&#039;&#039;&#039; was used to establish them in the first place. This command stream is formatted as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;amp;lt;CSI&amp;amp;gt;[event-types-separated-by-semicolons]}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
So, for example, you could reset all of the events set in the above example by transmitting the command sequence:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;amp;lt;CSI&amp;amp;gt;7;8;11}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Note|title=The Read Stream May Not Be Dry|text=There could still be pending &#039;&#039;&#039;Raw Input Events&#039;&#039;&#039; in your read stream after turning off one or more &#039;&#039;&#039;Raw Input Events&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
The following table lists the valid raw input event types.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Raw Input Event Types&lt;br /&gt;
! Request Number&lt;br /&gt;
! Request Description&lt;br /&gt;
|-&lt;br /&gt;
| 0 || No-op (used internally)&lt;br /&gt;
|-&lt;br /&gt;
| 1 || RAW keyboard input (Intuition swallows all except the select button)&lt;br /&gt;
|-&lt;br /&gt;
| 2 || RAW mouse input&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Private Console Event&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Pointer position&lt;br /&gt;
|-&lt;br /&gt;
| 5 || (unused)&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Timer&lt;br /&gt;
|-&lt;br /&gt;
| 7 || Gadget pressed&lt;br /&gt;
|-&lt;br /&gt;
| 8 || Gadget released&lt;br /&gt;
|-&lt;br /&gt;
| 9 || Requester activity&lt;br /&gt;
|-&lt;br /&gt;
| 10 || Menu numbers&lt;br /&gt;
|-&lt;br /&gt;
| 11 || Close Gadget&lt;br /&gt;
|-&lt;br /&gt;
| 12 || Window resized&lt;br /&gt;
|-&lt;br /&gt;
| 13 || Window refreshed&lt;br /&gt;
|-&lt;br /&gt;
| 14 || Preferences changed&lt;br /&gt;
|-&lt;br /&gt;
| 15 || Disk removed&lt;br /&gt;
|-&lt;br /&gt;
| 16 || Disk inserted&lt;br /&gt;
|-&lt;br /&gt;
| 17 || Active window&lt;br /&gt;
|-&lt;br /&gt;
| 18 || Inactive window&lt;br /&gt;
|-&lt;br /&gt;
| 19 || New pointer position&lt;br /&gt;
|-&lt;br /&gt;
| 20 || Menu help&lt;br /&gt;
|-&lt;br /&gt;
| 21 || Window changed (zoom, move)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The event types—requester, window refreshed, active window, inactive window, window resized and window changed—are dispatched to the console unit which owns the window from which the events are generated, even if it is not the active (selected ) window at the time the event is generated. This ensures that the proper console unit is notified of those events. All other events are dispatched to the active console unit (if it has requested those events).&lt;br /&gt;
&lt;br /&gt;
== Input Event Reports ==&lt;br /&gt;
&lt;br /&gt;
If you select any of these events you will start to get information about the events in the following form:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;amp;lt;CSI&amp;amp;gt;&amp;amp;lt;class&amp;amp;gt;;&amp;amp;lt;subclass&amp;amp;gt;;&amp;amp;lt;keycode&amp;amp;gt;;&amp;amp;lt;qualifiers&amp;amp;gt;;&amp;amp;lt;x&amp;amp;gt;;&amp;amp;lt;y&amp;amp;gt;;&amp;amp;lt;seconds&amp;amp;gt;;&amp;amp;lt;microseconds&amp;amp;gt;|&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;CSI&amp;gt;&lt;br /&gt;
: is a one-byte field. It is the “control sequence introducer,” 0x9B in hex.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;class&amp;gt;&lt;br /&gt;
: is the raw input event type, from the above table.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;subclass&amp;gt;&lt;br /&gt;
: is usually 0. If the mouse is moved to the right controller, this would be 1.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;keycode&amp;gt;&lt;br /&gt;
: indicates which raw key number was pressed. This field can also be used for mouse information.&lt;br /&gt;
&lt;br /&gt;
: {{Note|title=The Raw Key Might Be The Wrong Key|text=National keyboards often have different keyboard arrangements. This means that a particular raw key number may represent different characters on different national keyboards. The normal console read stream (as opposed to raw events) will contain the proper ASCII character for the keypress as translated according to the user’s keymap.}}&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;qualifiers&amp;gt;&lt;br /&gt;
: indicates the state of the keyboard and system. The qualifiers are defined as follows:&lt;br /&gt;
&lt;br /&gt;
:{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Input Event Qualifiers&lt;br /&gt;
! Bit&lt;br /&gt;
! Mask&lt;br /&gt;
! Key&lt;br /&gt;
! Comment&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 0001 || Left shift&lt;br /&gt;
|-&lt;br /&gt;
| 1 || 0002 || Right shift&lt;br /&gt;
|-&lt;br /&gt;
| 2 || 0004 || Caps Lock || Associated keycode is special; see below&lt;br /&gt;
|-&lt;br /&gt;
| 3 || 0008 || Ctrl&lt;br /&gt;
|-&lt;br /&gt;
| 4 || 0010 || Left Alt&lt;br /&gt;
|-&lt;br /&gt;
| 5 || 0020 || Right Alt&lt;br /&gt;
|-&lt;br /&gt;
| 6 || 0040 || Left Amiga key pressed&lt;br /&gt;
|-&lt;br /&gt;
| 7 || 0080 || Right Amiga key pressed&lt;br /&gt;
|-&lt;br /&gt;
| 8 || 0100 || Numeric pad&lt;br /&gt;
|-&lt;br /&gt;
| 9 || 0200 || Repeat&lt;br /&gt;
|-&lt;br /&gt;
| 10 || 0400 || Interrupt || Not currently used.&lt;br /&gt;
|-&lt;br /&gt;
| 11 || 0800 || Multibroadcast || This window (active one) or all windows.&lt;br /&gt;
|-&lt;br /&gt;
| 12 || 1000 || Middle mouse button || (Not available on standard mouse)&lt;br /&gt;
|-&lt;br /&gt;
| 13 || 2000 || Right mouse button&lt;br /&gt;
|-&lt;br /&gt;
| 14 || 4000 || Left mouse button&lt;br /&gt;
|-&lt;br /&gt;
| 15 || 8000 || Relative mouse || Mouse coordinates are relative, not absolute.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
: The &#039;&#039;&#039;Caps Lock&#039;&#039;&#039; key is handled in a special manner. It generates a keycode only when it is pressed, not when it is released. However, the up/down bit (80 hex) is still used and reported. If pressing the &#039;&#039;&#039;Caps Lock&#039;&#039;&#039; key causes the LED to light, keycode 62 (&#039;&#039;&#039;Caps Lock&#039;&#039;&#039; pressed) is sent. If pressing the &#039;&#039;&#039;Caps Lock&#039;&#039;&#039; key extinguishes the LED, keycode 190 (&#039;&#039;&#039;Caps Lock&#039;&#039;&#039; released) is sent. In effect, the keyboard reports this key as held down until it is struck again.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;x&amp;gt; and &amp;lt;y&amp;gt;&lt;br /&gt;
: filled by some classes with an Intuition address: x&amp;amp;lt;&amp;amp;lt;16+y.&lt;br /&gt;
&lt;br /&gt;
; &amp;lt;seconds&amp;gt; and &amp;lt;microseconds&amp;gt;&lt;br /&gt;
: contain the system time stamp taken at the time the event occurred. These values are stored as longwords by the system.&lt;br /&gt;
&lt;br /&gt;
With RAW keyboard input selected, keys will no longer return a simple one-character “A” to “Z” but will instead return raw keycode reports of the form:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;amp;lt;CSI&amp;amp;gt;1;0;&amp;amp;lt;keycode&amp;amp;gt;;&amp;amp;lt;qualifiers&amp;amp;gt;;&amp;amp;lt;prev1&amp;amp;gt;;&amp;amp;lt;prev2&amp;amp;gt;;&amp;amp;lt;seconds&amp;amp;gt;;&amp;amp;lt;microseconds&amp;amp;gt;|&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For example, if the user pressed and released the &#039;&#039;&#039;A&#039;&#039;&#039; key with the &#039;&#039;&#039;Left Shift&#039;&#039;&#039; and &#039;&#039;&#039;Right Amiga&#039;&#039;&#039; keys also pressed, you might receive the following data:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;amp;lt;CSI&amp;amp;gt;1;0;32;32769;14593;5889;421939940;316673|&lt;br /&gt;
&amp;amp;lt;CSI&amp;amp;gt;1;0;160;32769;0;0;421939991;816683|&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;amp;lt;keycode&amp;amp;gt; field is an ASCII decimal value representing the key pressed or released. Adding 128 to the pressed key code will result in the released keycode.&lt;br /&gt;
&lt;br /&gt;
The &amp;amp;lt;prev1&amp;amp;gt; and &amp;amp;lt;prev2&amp;amp;gt; fields are relevant for the interpretation of keys which are modifiable by dead-keys (see “Dead-Class Keys” section). The &amp;amp;lt;prev1&amp;amp;gt; field shows the previous key pressed. The lower byte shows the qualifier, the upper byte shows the key code. The &amp;amp;lt;prev2&amp;amp;gt; field shows the key pressed before the previous key. The lower byte shows the qualifier, the upper byte shows the key code.&lt;br /&gt;
&lt;br /&gt;
== Using the Console Device Without a Window ==&lt;br /&gt;
&lt;br /&gt;
Most console device processing involves a window, but there are functions and special commands that may be used without a window. To use the console device without a window, you call OpenDevice() with the console unit CONU_LIBRARY.&lt;br /&gt;
&lt;br /&gt;
The console device functions are CDInputHandler() and RawKeyConvert(); they may only be used with the CONU_LIBRARY console unit. The console device commands which do not require a window are CD_ASKDEFAULTKEYMAP and CD_SETDEFAULTKEYMAP; they be used with any console unit. The advantage of using the commands with the CONU_LIBRARY unit is the lack of overhead required for CONU_LIBRARY because it doesn’t require a window.&lt;br /&gt;
&lt;br /&gt;
To use the functions requires the following steps:&lt;br /&gt;
&lt;br /&gt;
* Declare the console device base address variable ConsoleDevice in the global data area.&lt;br /&gt;
* Declare storage for an I/O request of type IOStdReq.&lt;br /&gt;
* Open the console device with CONU_LIBRARY set as the console unit.&lt;br /&gt;
* Set the console device base address variable to point to the device library vector which is returned in io_Device.&lt;br /&gt;
* Call the console device function(s).&lt;br /&gt;
* Close the console device when you are finished.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
#include &amp;lt;devices/conunit.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
  struct IOStdReq ConsIO = {0};&lt;br /&gt;
&lt;br /&gt;
  /* Open the device with CONU_LIBRARY for function use */&lt;br /&gt;
  if (0 == IExec-&amp;gt;OpenDevice(&amp;quot;console.device&amp;quot;, CONU_LIBRARY, (struct IORequest *)&amp;amp;ConsIO, 0))&lt;br /&gt;
  {&lt;br /&gt;
    /* Set the base address variable to the device library vector */&lt;br /&gt;
    struct ConsoleDevice *ConsoleDevice = (struct ConsoleDevice *)ConsIO.io_Device;&lt;br /&gt;
    struct ConsoleIFace *IConsole = (struct ConsoleIFace*)&lt;br /&gt;
      IExec-&amp;gt;GetInterface((struct Library*)ConsoleDevice, &amp;quot;main&amp;quot;, 1, NULL);&lt;br /&gt;
&lt;br /&gt;
                  .&lt;br /&gt;
                  .    (console device functions would be called here)&lt;br /&gt;
                  .&lt;br /&gt;
&lt;br /&gt;
    IExec-&amp;gt;DropInterface((struct Interface *)IConsole);&lt;br /&gt;
    IExec-&amp;gt;CloseDevice(ConsIO);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The code fragment shows only the steps outlined above, it is not complete in any sense of the word. For a complete example of using a console device function, see the &#039;&#039;rawkey.c&#039;&#039; code example in the [[Intuition_Keyboard|Intuition Keyboard]]. The example uses the RawKeyConvert() function.&lt;br /&gt;
&lt;br /&gt;
To use the commands with the CONU_LIBRARY console unit, you follow the same steps that were outlined in [[#Opening the Console Device|Opening the Console Device]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct KeyMap  *keymap;          /* pointer to keymap */&lt;br /&gt;
&lt;br /&gt;
    /* Create the message port */&lt;br /&gt;
struct MsgPort *ConsoleMP = IExec-&amp;gt;AllocSysObjectTags(ASOT_PORT, TAG_END);&lt;br /&gt;
if (ConsoleMP != NULL)&lt;br /&gt;
    {&lt;br /&gt;
        /* Create the I/O request */&lt;br /&gt;
    struct IOStdReq *ConsoleIO = IExec-&amp;gt;AllocSysObjectTags(ASOT_IOREQUEST,&lt;br /&gt;
        ASOIOR_Size, sizeof(struct IOStdReq),&lt;br /&gt;
        ASOIOR_ReplyPort, ConsoleMP,&lt;br /&gt;
        TAG_END);&lt;br /&gt;
        &lt;br /&gt;
    if (ConsoleIO != NULL)&lt;br /&gt;
        {&lt;br /&gt;
            /* Open the Console device */&lt;br /&gt;
        if (IExec-&amp;gt;OpenDevice(&amp;quot;console.device&amp;quot;, CONU_LIBRARY, (struct IORequest *)ConsoleIO, 0))&lt;br /&gt;
&lt;br /&gt;
            /* Inform user that it could not be opened */&lt;br /&gt;
            IDOS-&amp;gt;Printf(&amp;quot;Error: console.device did not open\n&amp;quot;);&lt;br /&gt;
        else&lt;br /&gt;
            {&lt;br /&gt;
               /* Allocate memory for the keymap */&lt;br /&gt;
            if (keymap = (struct KeyMap *)&lt;br /&gt;
                    AllocVecTags(sizeof(struct KeyMap), AVT_ClearWithValue, 0, TAG_END))&lt;br /&gt;
                {&lt;br /&gt;
                /* device opened, send CD_ASKKEYMAP command to it */&lt;br /&gt;
                ConsoleIO-&amp;gt;io_Length  = sizeof(struct KeyMap);&lt;br /&gt;
                ConsoleIO-&amp;gt;io_Data    = (APTR)keymap;      /* where to put it */&lt;br /&gt;
                ConsoleIO-&amp;gt;io_Command = CD_ASKKEYMAP;&lt;br /&gt;
                IExec-&amp;gt;DoIO((struct IORequest *)ConsoleIO))&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
            IExec-&amp;gt;CloseDevice(ConsIO);&lt;br /&gt;
            }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Again, as in the previous code fragment, this is not complete and you should only use it as a guide.&lt;br /&gt;
&lt;br /&gt;
== Console Device Caveats ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;Only one console unit can be attached per window. Sharing a console window must be done at a level higher than the device.&amp;lt;/p&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;Do not mix graphics.library calls with console rendering in the same areas of a window. It is permissible to send console sequences to adjust the area in which console renders, and use graphics.library calls to render outside of the area console is using.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;For example, do not render text with console sequences and scroll using the graphics.library ScrollRaster() function.&amp;lt;/p&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;The character map feature is private and cannot be accessed by the programmer. Implementation details and behaviors of the character map my change in the future.&amp;lt;/p&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;Do not use an IDCMP with character mapped consoles. All Intuition messages should be obtained via &#039;&#039;&#039;Raw Input Events&#039;&#039;&#039; from the console device.&amp;lt;/p&amp;gt;&amp;lt;/li&amp;gt;&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Console Device Example Code ==&lt;br /&gt;
&lt;br /&gt;
The following is a console device demonstration program with supporting routines:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
 * Console.c&lt;br /&gt;
 *&lt;br /&gt;
 * Example of opening a window and using the console device&lt;br /&gt;
 * to send text and control sequences to it.  The example can be&lt;br /&gt;
 * easily modified to do additional control sequences.&lt;br /&gt;
 *&lt;br /&gt;
 * Run from CLI only.&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;exec/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;exec/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;exec/memory.h&amp;gt;&lt;br /&gt;
#include &amp;lt;intuition/intuition.h&amp;gt;&lt;br /&gt;
#include &amp;lt;libraries/dos.h&amp;gt;&lt;br /&gt;
#include &amp;lt;devices/console.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;proto/exec.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/dos.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/intuition.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/utility.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/* Note - using two character &amp;lt;CSI&amp;gt; ESC[.  Hex 9B could be used instead */&lt;br /&gt;
#define RESETCON  &amp;quot;\033c&amp;quot;&lt;br /&gt;
#define CURSOFF   &amp;quot;\033[0 p&amp;quot;&lt;br /&gt;
#define CURSON    &amp;quot;\033[ p&amp;quot;&lt;br /&gt;
#define DELCHAR   &amp;quot;\033[P&amp;quot;&lt;br /&gt;
&lt;br /&gt;
/* SGR (set graphic rendition) */&lt;br /&gt;
#define COLOR02   &amp;quot;\033[32m&amp;quot;&lt;br /&gt;
#define COLOR03   &amp;quot;\033[33m&amp;quot;&lt;br /&gt;
#define ITALICS   &amp;quot;\033[3m&amp;quot;&lt;br /&gt;
#define BOLD      &amp;quot;\033[1m&amp;quot;&lt;br /&gt;
#define UNDERLINE &amp;quot;\033[4m&amp;quot;&lt;br /&gt;
#define NORMAL    &amp;quot;\033[0m&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/* our functions */&lt;br /&gt;
void cleanexit(uint8 *,LONG);&lt;br /&gt;
void cleanup(void);&lt;br /&gt;
int8 OpenConsole(struct IOStdReq *,struct IOStdReq *, struct Window *);&lt;br /&gt;
void CloseConsole(struct IOStdReq *);&lt;br /&gt;
void QueueRead(struct IOStdReq *, uint8 *);&lt;br /&gt;
uint8 ConGetChar(struct MsgPort *, uint8 *);&lt;br /&gt;
LONG ConMayGetChar(struct MsgPort *, uint8 *);&lt;br /&gt;
void ConPuts(struct IOStdReq *, uint8 *);&lt;br /&gt;
void ConWrite(struct IOStdReq *, uint8 *, LONG);&lt;br /&gt;
void ConPutChar(struct IOStdReq *, uint8);&lt;br /&gt;
&lt;br /&gt;
struct NewWindow nw =&lt;br /&gt;
    {&lt;br /&gt;
    10, 10,                           /* starting position (left,top) */&lt;br /&gt;
    620,180,                          /* width, height */&lt;br /&gt;
    -1,-1,                            /* detailpen, blockpen */&lt;br /&gt;
    CLOSEWINDOW,                      /* flags for idcmp */&lt;br /&gt;
    WINDOWDEPTH|WINDOWSIZING|&lt;br /&gt;
    WINDOWDRAG|WINDOWCLOSE|&lt;br /&gt;
    SMART_REFRESH|ACTIVATE,           /* window flags */&lt;br /&gt;
    NULL,                             /* no user gadgets */&lt;br /&gt;
    NULL,                             /* no user checkmark */&lt;br /&gt;
    &amp;quot;Console Test&amp;quot;,                   /* title */&lt;br /&gt;
    NULL,                             /* pointer to window screen */&lt;br /&gt;
    NULL,                             /* pointer to super bitmap */&lt;br /&gt;
    100,45,                           /* min width, height */&lt;br /&gt;
    640,200,                          /* max width, height */&lt;br /&gt;
    WBENCHSCREEN                      /* open on workbench screen */&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/* Opens/allocations we&#039;ll need to clean up */&lt;br /&gt;
struct Library *IntuitionBase = NULL;&lt;br /&gt;
struct IntuitionIFace *IIntuition = NULL;&lt;br /&gt;
struct Window   *win = NULL;&lt;br /&gt;
struct IOStdReq *writeReq = NULL;    /* IORequest block pointer */&lt;br /&gt;
struct MsgPort  *writePort = NULL;   /* replyport for writes      */&lt;br /&gt;
struct IOStdReq *readReq = NULL;     /* IORequest block pointer */&lt;br /&gt;
struct MsgPort  *readPort = NULL;    /* replyport for reads       */&lt;br /&gt;
BOOL OpenedConsole = FALSE;&lt;br /&gt;
&lt;br /&gt;
BOOL FromWb;&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char **argv)&lt;br /&gt;
    {&lt;br /&gt;
    struct IntuiMessage *winmsg;&lt;br /&gt;
    ULONG signals, conreadsig, windowsig;&lt;br /&gt;
    LONG lch;&lt;br /&gt;
    SHORT InControl = 0;&lt;br /&gt;
    BOOL Done = FALSE;&lt;br /&gt;
    uint8 ch, ibuf;&lt;br /&gt;
    uint8 obuf[200];&lt;br /&gt;
    int8 error;&lt;br /&gt;
&lt;br /&gt;
    FromWb = (argc==0) ? TRUE : FALSE;&lt;br /&gt;
&lt;br /&gt;
    IntuitionBase = IExec-&amp;gt;OpenLibrary(&amp;quot;intuition.library&amp;quot;, 50);&lt;br /&gt;
    IIntuition = (struct IntuitionIFace*)IExec-&amp;gt;GetInterface(IntuitionBase, &amp;quot;main&amp;quot;, 1, NULL);&lt;br /&gt;
    if(IIntuition == NULL)&lt;br /&gt;
         cleanexit(&amp;quot;Can&#039;t open intuition\n&amp;quot;,RETURN_FAIL);&lt;br /&gt;
&lt;br /&gt;
    /* Create reply port and io block for writing to console */&lt;br /&gt;
    writePort = IExec-&amp;gt;AllocSysObjectTags(ASOT_PORT,&lt;br /&gt;
        ASOPORT_Name, &amp;quot;RKM.console.write&amp;quot;,&lt;br /&gt;
        TAG_END);&lt;br /&gt;
    if(writePort == NULL)&lt;br /&gt;
         cleanexit(&amp;quot;Can&#039;t create write port\n&amp;quot;,RETURN_FAIL);&lt;br /&gt;
&lt;br /&gt;
    writeReq = IExec-&amp;gt;AllocSysObjectTags(ASOT_IOREQUEST,&lt;br /&gt;
        ASOIOR_Size, sizeof(struct IOStdReq),&lt;br /&gt;
        ASOIOR_ReplyPort, writePort,&lt;br /&gt;
        TAG_END);&lt;br /&gt;
    if(writeReq == NULL)&lt;br /&gt;
         cleanexit(&amp;quot;Can&#039;t create write request\n&amp;quot;,RETURN_FAIL);&lt;br /&gt;
&lt;br /&gt;
    /* Create reply port and io block for reading from console */&lt;br /&gt;
    readPort = IExec-&amp;gt;AllocSysObjectTags(ASOT_PORT,&lt;br /&gt;
        ASOPORT_Name, &amp;quot;RKM.console.read&amp;quot;,&lt;br /&gt;
        TAG_END);&lt;br /&gt;
    if(readPort == NULL)&lt;br /&gt;
         cleanexit(&amp;quot;Can&#039;t create read port\n&amp;quot;,RETURN_FAIL);&lt;br /&gt;
&lt;br /&gt;
    readReq = IExec-&amp;gt;AllocSysObjectTags(ASOT_IOREQUEST,&lt;br /&gt;
        ASOIOR_Size, sizeof(struct IOStdReq),&lt;br /&gt;
        ASOIOR_ReplyPort, readPort,&lt;br /&gt;
        TAG_END);&lt;br /&gt;
    if(readReq == NULL)&lt;br /&gt;
         cleanexit(&amp;quot;Can&#039;t create read request\n&amp;quot;,RETURN_FAIL);&lt;br /&gt;
&lt;br /&gt;
    /* Open a window */&lt;br /&gt;
    if(!(win = IIntuition-&amp;gt;OpenWindow(&amp;amp;nw)))&lt;br /&gt;
         cleanexit(&amp;quot;Can&#039;t open window\n&amp;quot;,RETURN_FAIL);&lt;br /&gt;
&lt;br /&gt;
    /* Now, attach a console to the window */&lt;br /&gt;
    if(error = OpenConsole(writeReq, readReq, win))&lt;br /&gt;
         cleanexit(&amp;quot;Can&#039;t open console.device\n&amp;quot;,RETURN_FAIL);&lt;br /&gt;
    else OpenedConsole = TRUE;&lt;br /&gt;
&lt;br /&gt;
    /* Demonstrate some console escape sequences */&lt;br /&gt;
    ConPuts(writeReq,&amp;quot;Here&#039;s some normal text\n&amp;quot;);&lt;br /&gt;
    IUtility-&amp;gt;SNPrintf(obuf, sizeof(obuf), &amp;quot;%s%sHere&#039;s text in color 3 and italics\n&amp;quot;, COLOR03, ITALICS);&lt;br /&gt;
    ConPuts(writeReq,obuf);&lt;br /&gt;
    ConPuts(writeReq,NORMAL);&lt;br /&gt;
    IDOS-&amp;gt;Delay(50);      /* Delay for dramatic demo effect */&lt;br /&gt;
    ConPuts(writeReq,&amp;quot;We will now delete this asterisk =*=&amp;quot;);&lt;br /&gt;
    IDOS-&amp;gt;Delay(50);&lt;br /&gt;
    ConPuts(writeReq,&amp;quot;\b\b&amp;quot;);  /* backspace twice */&lt;br /&gt;
    IDOS-&amp;gt;Delay(50);&lt;br /&gt;
    ConPuts(writeReq,DELCHAR); /* delete the character */&lt;br /&gt;
    IDOS-&amp;gt;Delay(50);&lt;br /&gt;
&lt;br /&gt;
    QueueRead(readReq,&amp;amp;ibuf); /* send the first console read request */&lt;br /&gt;
&lt;br /&gt;
    ConPuts(writeReq,&amp;quot;\n\nNow reading console\n&amp;quot;);&lt;br /&gt;
    ConPuts(writeReq,&amp;quot;Type some keys.  Close window when done.\n\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    conreadsig = 1 &amp;lt;&amp;lt; readPort-&amp;gt;mp_SigBit;&lt;br /&gt;
    windowsig = 1 &amp;lt;&amp;lt; win-&amp;gt;UserPort-&amp;gt;mp_SigBit;&lt;br /&gt;
&lt;br /&gt;
    while(!Done)&lt;br /&gt;
        {&lt;br /&gt;
        /* A character, or an IDCMP msg, or both could wake us up */&lt;br /&gt;
        signals = IExec-&amp;gt;Wait(conreadsig|windowsig);&lt;br /&gt;
&lt;br /&gt;
        /* If a console signal was received, get the character */&lt;br /&gt;
        if (signals &amp;amp; conreadsig)&lt;br /&gt;
            {&lt;br /&gt;
            if((lch = ConMayGetChar(readPort,&amp;amp;ibuf)) != -1)&lt;br /&gt;
                {&lt;br /&gt;
                ch = lch;&lt;br /&gt;
                /* Show hex and ascii (if printable) for char we got.&lt;br /&gt;
                 * If you want to parse received control sequences, such as&lt;br /&gt;
                 * function or Help keys, you would buffer control sequences&lt;br /&gt;
                 * as you receive them, starting to buffer whenever you&lt;br /&gt;
                 * receive 0x9B (or 0x1B[ for user-typed sequences) and&lt;br /&gt;
                 * ending when you receive a valid terminating character&lt;br /&gt;
                 * for the type of control sequence you are receiving.&lt;br /&gt;
                 * For CSI sequences, valid terminating characters&lt;br /&gt;
                 * are generally 0x40 through 0x7E.&lt;br /&gt;
                 * In our example, InControl has the following values:&lt;br /&gt;
                 * 0 = no, 1 = have 0x1B, 2 = have 0x9B OR 0x1B and [,&lt;br /&gt;
                 * 3 = now inside control sequence, -1 = normal end esc,&lt;br /&gt;
                 * -2 = non-CSI(no [) 0x1B end esc&lt;br /&gt;
                 * NOTE - a more complex parser is required to recognize&lt;br /&gt;
                 *  other types of control sequences.&lt;br /&gt;
                 */&lt;br /&gt;
&lt;br /&gt;
                /* 0x1B ESC not followed by &#039;[&#039;, is not CSI seq */&lt;br /&gt;
                if (InControl==1)&lt;br /&gt;
                    {&lt;br /&gt;
                    if(ch==&#039;[&#039;) InControl = 2;&lt;br /&gt;
                    else InControl = -2;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                if ((ch==0x9B)||(ch==0x1B))  /* Control seq starting */&lt;br /&gt;
                    {&lt;br /&gt;
                    InControl = (ch==0x1B) ? 1 : 2;&lt;br /&gt;
                    ConPuts(writeReq,&amp;quot;=== Control Seq ===\n&amp;quot;);&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                /* We&#039;ll show value of this char we received */&lt;br /&gt;
                if (((ch &amp;gt;= 0x1F)&amp;amp;&amp;amp;(ch &amp;lt;= 0x7E))||(ch &amp;gt;= 0xA0))&lt;br /&gt;
                   IUtility-&amp;gt;SNPrintf(obuf, sizeof(obuf), &amp;quot;Received: hex %02x = %c\n&amp;quot;,ch,ch);&lt;br /&gt;
                else IUtility-&amp;gt;SNPrintf(obuf, sizeof(obuf), &amp;quot;Received: hex %02x\n&amp;quot;,ch);&lt;br /&gt;
                ConPuts(writeReq,obuf);&lt;br /&gt;
&lt;br /&gt;
                /* Valid ESC sequence terminator ends an ESC seq */&lt;br /&gt;
                if ((InControl==3)&amp;amp;&amp;amp;((ch &amp;gt;= 0x40) &amp;amp;&amp;amp; (ch &amp;lt;= 0x7E)))&lt;br /&gt;
                    {&lt;br /&gt;
                    InControl = -1;&lt;br /&gt;
                    }&lt;br /&gt;
                if (InControl==2) InControl = 3;&lt;br /&gt;
                /* ESC sequence finished (-1 if OK, -2 if bogus) */&lt;br /&gt;
                if (InControl &amp;lt; 0)&lt;br /&gt;
                    {&lt;br /&gt;
                    InControl = 0;&lt;br /&gt;
                    ConPuts(writeReq,&amp;quot;=== End Control ===\n&amp;quot;);&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
        /* If IDCMP messages received, handle them */&lt;br /&gt;
        if (signals &amp;amp; windowsig)&lt;br /&gt;
            {&lt;br /&gt;
            /* We have to ReplyMsg these when done with them */&lt;br /&gt;
            while (winmsg = (struct IntuiMessage *)IExec-&amp;gt;GetMsg(win-&amp;gt;UserPort))&lt;br /&gt;
                {&lt;br /&gt;
                switch(winmsg-&amp;gt;Class)&lt;br /&gt;
                    {&lt;br /&gt;
                    case CLOSEWINDOW:&lt;br /&gt;
                      Done = TRUE;&lt;br /&gt;
                      break;&lt;br /&gt;
                    default:&lt;br /&gt;
                      break;&lt;br /&gt;
                     }&lt;br /&gt;
                IExec-&amp;gt;ReplyMsg((struct Message *)winmsg);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
    /* We always have an outstanding queued read request&lt;br /&gt;
     * so we must abort it if it hasn&#039;t completed,&lt;br /&gt;
     * and we must remove it.&lt;br /&gt;
     */&lt;br /&gt;
    if(!(IExec-&amp;gt;CheckIO(readReq)))  IExec-&amp;gt;AbortIO(readReq);&lt;br /&gt;
    IExec-&amp;gt;WaitIO(readReq);     /* clear it from our replyport */&lt;br /&gt;
&lt;br /&gt;
    cleanup();&lt;br /&gt;
    return RETURN_OK;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
void cleanexit(uint8 *s,LONG n)&lt;br /&gt;
    {&lt;br /&gt;
    if(*s &amp;amp; (!FromWb)) IDOS-&amp;gt;Printf(s);&lt;br /&gt;
    cleanup();&lt;br /&gt;
    exit(n);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
void cleanup()&lt;br /&gt;
    {&lt;br /&gt;
    if(OpenedConsole) CloseConsole(writeReq);&lt;br /&gt;
    IExec-&amp;gt;FreeSysObject(ASOT_IOREQUEST, readReq);&lt;br /&gt;
    IExec-&amp;gt;FreeSysObject(ASOT_PORT, readPort);&lt;br /&gt;
    IExec-&amp;gt;FreeSysObject(ASOT_IOREQUEST, writeReq);&lt;br /&gt;
    IExec-&amp;gt;FreeSysObject(ASOT_PORT, writePort);&lt;br /&gt;
    if(IIntuition != NULL &amp;amp;&amp;amp; win != NULL) IIntuition-&amp;gt;CloseWindow(win);&lt;br /&gt;
    IExec-&amp;gt;DropInterface((struct Interface *)IIntuition);&lt;br /&gt;
    IExec-&amp;gt;CloseLibrary(IntuitionBase);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/* Attach console device to an open Intuition window.&lt;br /&gt;
 * This function returns a value of 0 if the console&lt;br /&gt;
 * device opened correctly and a nonzero value (the error&lt;br /&gt;
 * returned from OpenDevice) if there was an error.&lt;br /&gt;
 */&lt;br /&gt;
int8 OpenConsole(struct IOStdReq *writereq, struct IOStdReq *readreq, struct Window *window)&lt;br /&gt;
    {&lt;br /&gt;
    int8 error;&lt;br /&gt;
&lt;br /&gt;
    writereq-&amp;gt;io_Data = (APTR) window;&lt;br /&gt;
    writereq-&amp;gt;io_Length = sizeof(struct Window);&lt;br /&gt;
    error = IExec-&amp;gt;OpenDevice(&amp;quot;console.device&amp;quot;, 0, writereq, 0);&lt;br /&gt;
    readreq-&amp;gt;io_Device = writereq-&amp;gt;io_Device; /* clone required parts */&lt;br /&gt;
    readreq-&amp;gt;io_Unit   = writereq-&amp;gt;io_Unit;&lt;br /&gt;
    return(error);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
void CloseConsole(struct IOStdReq *writereq)&lt;br /&gt;
    {&lt;br /&gt;
    IExec-&amp;gt;CloseDevice(writereq);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
/* Output a single character to a specified console&lt;br /&gt;
 */&lt;br /&gt;
void ConPutChar(struct IOStdReq *writereq, uint8 character)&lt;br /&gt;
    {&lt;br /&gt;
    writereq-&amp;gt;io_Command = CMD_WRITE;&lt;br /&gt;
    writereq-&amp;gt;io_Data = (APTR)&amp;amp;character;&lt;br /&gt;
    writereq-&amp;gt;io_Length = 1;&lt;br /&gt;
    IExec-&amp;gt;DoIO(writereq);&lt;br /&gt;
    /* command works because DoIO blocks until command is done&lt;br /&gt;
     * (otherwise ptr to the character could become invalid)&lt;br /&gt;
     */&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/* Output a stream of known length to a console&lt;br /&gt;
 */&lt;br /&gt;
void ConWrite(struct IOStdReq *writereq, uint8 *string, LONG length)&lt;br /&gt;
    {&lt;br /&gt;
    writereq-&amp;gt;io_Command = CMD_WRITE;&lt;br /&gt;
    writereq-&amp;gt;io_Data = (APTR)string;&lt;br /&gt;
    writereq-&amp;gt;io_Length = length;&lt;br /&gt;
    IExec-&amp;gt;DoIO(writereq);&lt;br /&gt;
    /* command works because DoIO blocks until command is done&lt;br /&gt;
     * (otherwise ptr to string could become invalid in the meantime)&lt;br /&gt;
     */&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/* Output a NULL-terminated string of characters to a console&lt;br /&gt;
 */&lt;br /&gt;
void ConPuts(struct IOStdReq *writereq,uint8 *string)&lt;br /&gt;
    {&lt;br /&gt;
    writereq-&amp;gt;io_Command = CMD_WRITE;&lt;br /&gt;
    writereq-&amp;gt;io_Data = (APTR)string;&lt;br /&gt;
    writereq-&amp;gt;io_Length = -1;  /* means print till terminating null */&lt;br /&gt;
    IExec-&amp;gt;DoIO(writereq);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
/* Queue up a read request to console, passing it pointer&lt;br /&gt;
 * to a buffer into which it can read the character&lt;br /&gt;
 */&lt;br /&gt;
void QueueRead(struct IOStdReq *readreq, uint8 *whereto)&lt;br /&gt;
   {&lt;br /&gt;
   readreq-&amp;gt;io_Command = CMD_READ;&lt;br /&gt;
   readreq-&amp;gt;io_Data = (APTR)whereto;&lt;br /&gt;
   readreq-&amp;gt;io_Length = 1;&lt;br /&gt;
   IExec-&amp;gt;SendIO(readreq);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/* Check if a character has been received.&lt;br /&gt;
 * If none, return -1&lt;br /&gt;
 */&lt;br /&gt;
LONG ConMayGetChar(struct MsgPort *msgport, uint8 *whereto)&lt;br /&gt;
    {&lt;br /&gt;
    struct IOStdReq *readreq;&lt;br /&gt;
&lt;br /&gt;
    if (!(readreq = (struct IOStdReq *)IExec-&amp;gt;GetMsg(msgport))) return(-1);&lt;br /&gt;
    int temp = *whereto;            /* get the character */&lt;br /&gt;
    QueueRead(readreq,whereto);     /* then re-use the request block */&lt;br /&gt;
    return(temp);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
/* Wait for a character&lt;br /&gt;
 */&lt;br /&gt;
uint8 ConGetChar(struct MsgPort *msgport, uint8 *whereto)&lt;br /&gt;
    {&lt;br /&gt;
    struct IOStdReq *readreq;&lt;br /&gt;
&lt;br /&gt;
    WaitPort(msgport);&lt;br /&gt;
    readreq = (struct IOStdReq *)GetMsg(msgport);&lt;br /&gt;
    int temp = *whereto;           /* get the character */&lt;br /&gt;
    QueueRead(readreq,whereto);    /* then re-use the request block*/&lt;br /&gt;
    return((uint8)temp);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Additional Information on the Console Device ==&lt;br /&gt;
&lt;br /&gt;
Additional programming information on the console device can be found in the include files and the Autodocs for the console device. Both are contained in the SDK.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Includes&lt;br /&gt;
|-&lt;br /&gt;
| devices/console.h&lt;br /&gt;
|-&lt;br /&gt;
| devices/conunit.h&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! AutoDocs&lt;br /&gt;
|-&lt;br /&gt;
| console.doc&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Costel Mincea</name></author>
	</entry>
	<entry>
		<id>https://wiki.amigaos.net/w/index.php?title=Programming_AmigaOS_4:_Utility_-_Little_Helpers&amp;diff=12563</id>
		<title>Programming AmigaOS 4: Utility - Little Helpers</title>
		<link rel="alternate" type="text/html" href="https://wiki.amigaos.net/w/index.php?title=Programming_AmigaOS_4:_Utility_-_Little_Helpers&amp;diff=12563"/>
		<updated>2025-01-26T19:35:24Z</updated>

		<summary type="html">&lt;p&gt;Costel Mincea: Text replacement - &amp;quot;&amp;lt;syntaxhighlight&amp;gt;&amp;quot; to &amp;quot;&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;This article was adapted from Amiga Future magazine&#039;s series on developing for AmigaOS....&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
The inconspicuous AmigaOS 4 utility.library has been extended with some useful functions. So it&#039;s about time we took a closer look at it.&lt;br /&gt;
&lt;br /&gt;
We have sub-divided the overall description into different sections. So, let&#039;s get started with part one, the very flexible taglists. &lt;br /&gt;
&lt;br /&gt;
= Tag list improvements =&lt;br /&gt;
&lt;br /&gt;
Extending function-calls and their parameters can be a complicated issue, without updating all the old sources. By using a tag list, you can include new tags very flexibly, so unknown tags will be ignored. So if you are running the program on an older system, these new options are not available. That means, tag lists will become more and more important. Many of these new functions are about creating, searching and filtering the tagslists. A complete overview about all the new functions can be found in the final section of this article. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
  struct TagItem *taglist;&lt;br /&gt;
&lt;br /&gt;
  /* allocates memory for four pairs of tag-entries */&lt;br /&gt;
  /* the fifth entry only includes the identification for the list-ending */&lt;br /&gt;
  if((taglist = IUtility-&amp;gt;AllocateTagItems(5)))&lt;br /&gt;
  {&lt;br /&gt;
    /* Fill the taglist */&lt;br /&gt;
    taglist[0].ti_Tag  = TAG_IGNORE;&lt;br /&gt;
    taglist[0].ti_Data = 1;&lt;br /&gt;
    ...&lt;br /&gt;
    taglist[4].ti_Tag  = TAG_END;&lt;br /&gt;
    taglist[4].ti_Data = 0;&lt;br /&gt;
&lt;br /&gt;
    /* do something wiht the taglist */&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
    /*at the end the taglist memory can be deallocated*/&lt;br /&gt;
    IUtility-&amp;gt;FreeTagItems(taglist);&lt;br /&gt;
  }  &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Check-digits =&lt;br /&gt;
 &lt;br /&gt;
The utility.library provides a list of interesting features for check-digits. There are a great number of different check-digits and algorithms (i.e. CR32, MD5). The Amiga allows you to calculate a 160 bit (= 20 byte) check-digit via the SHA-1 algorithm. This comes in handy, if you want to check over huge data sections, without having an identical number. In comparison to check-digits with only 2 respectively 4 bytes, this can become a real problem. In detail, there are 3 steps to be made.&lt;br /&gt;
&lt;br /&gt;
First of all, you have to initialise the data structure by using the IUtility-&amp;gt;MessageDigest_SHA_Unit() command. Second comes the actual calculation via the IUtility-&amp;gt;MessageDigest_SHA_Update() command, whereas the data and the length must be given to create the check-digit.&lt;br /&gt;
&lt;br /&gt;
Lastly we type in the IUtility-&amp;gt;MessageDigest_SHA_Final() command. After completing all three steps, it&#039;s possible to get the calculated check-digit through mdsha_Code. The example below shows you how:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
  struct MessageDigest_SHA mdsha = { 0 };&lt;br /&gt;
  STRPTR testdata = &amp;quot;This is just a test&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
  IUtility-&amp;gt;MessageDigest_SHA_Init(&amp;amp;mdsha);&lt;br /&gt;
  IUtility-&amp;gt;MessageDigest_SHA_Update(&amp;amp;mdsha, testdata, IUtility-&amp;gt;Strlen(somedata));&lt;br /&gt;
  IUtility-&amp;gt;MessageDigest_SHA_Final(&amp;amp;mdsha);&lt;br /&gt;
&lt;br /&gt;
  IDOS-&amp;gt;Printf(&amp;quot; Checksum is: %.20s\n&amp;quot;,mdsha.mdsha_Code);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The test value will be output bit by bit, so it&#039;s not very clever to use the IDOS-&amp;gt;Printf() command, because control-characters can be included there as well. The value can be compared with the reference value thru the IUtility-&amp;gt;StriCmp() command.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
 * CalcChecksum.c&lt;br /&gt;
 *&lt;br /&gt;
 * gcc CalcChecksum.c -o CalcChecksum -l auto&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
/******************************* INCLUDES *************************************/&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;proto/exec.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/dos.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/utility.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/******************************* DEFINES **************************************/&lt;br /&gt;
&lt;br /&gt;
#define BUFFER_SIZE 65536  /* 64 kByte Block */&lt;br /&gt;
&lt;br /&gt;
/************************ VARIABLEN DEKLARATIONEN *****************************/&lt;br /&gt;
&lt;br /&gt;
const UBYTE *gb_ArgTemplate = &amp;quot;FILENAME/A&amp;quot;;&lt;br /&gt;
enum { ARG_filename, ARG_MAX };&lt;br /&gt;
ULONG gb_Args[ARG_MAX] = { 0 };&lt;br /&gt;
&lt;br /&gt;
/******************************************************************************/&lt;br /&gt;
&lt;br /&gt;
BOOL CalculateChecksum(CONST_STRPTR filename, UBYTE *checksum)&lt;br /&gt;
{&lt;br /&gt;
  BPTR fh;&lt;br /&gt;
  struct MessageDigest_SHA mdsha = { 0 };&lt;br /&gt;
&lt;br /&gt;
  /* Preparing checksum calculation */&lt;br /&gt;
  IUtility-&amp;gt;MessageDigest_SHA_Init(&amp;amp;mdsha);&lt;br /&gt;
&lt;br /&gt;
  if((fh = IDOS-&amp;gt;Open((STRPTR)filename, MODE_OLDFILE)))&lt;br /&gt;
  {&lt;br /&gt;
    LONG character;&lt;br /&gt;
    UBYTE *buffer;&lt;br /&gt;
&lt;br /&gt;
    if((buffer = (UBYTE *) IExec-&amp;gt;AllocVecTags(BUFFER_SIZE, TAG_END)))&lt;br /&gt;
    {&lt;br /&gt;
      while((character = IDOS-&amp;gt;Read(fh, buffer, BUFFER_SIZE)) &amp;gt; 0)&lt;br /&gt;
      {&lt;br /&gt;
        IUtility-&amp;gt;MessageDigest_SHA_Update(&amp;amp;mdsha, buffer, character);&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      IExec-&amp;gt;FreeVec(buffer);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    IDOS-&amp;gt;Close(fh);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  IUtility-&amp;gt;MessageDigest_SHA_Final(&amp;amp;mdsha);&lt;br /&gt;
  IUtility-&amp;gt;Strlcpy(checksum, mdsha.mdsha_Code, 20);&lt;br /&gt;
  checksum[20] = &#039;\0&#039;;&lt;br /&gt;
&lt;br /&gt;
  return fh ? TRUE : FALSE;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/******************************************************************************/&lt;br /&gt;
&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
  struct RDArgs *rda;&lt;br /&gt;
&lt;br /&gt;
  if((rda = IDOS-&amp;gt;ReadArgs((STRPTR)gb_ArgTemplate,(LONG*)gb_Args,NULL)))&lt;br /&gt;
  {&lt;br /&gt;
    UBYTE keybuffer[21]; /* 20 Bytes Checksum + \0 */&lt;br /&gt;
&lt;br /&gt;
    if(BerechneChecksumme((STRPTR)gb_Args[ARG_filename], keybuffer))&lt;br /&gt;
    {&lt;br /&gt;
      /*&lt;br /&gt;
      ** The checksum is a 160-bit data stream which should&lt;br /&gt;
      ** not strictly be output like a string. We do so here&lt;br /&gt;
      ** for convenience only.&lt;br /&gt;
      */&lt;br /&gt;
      IDOS-&amp;gt;Printf(&amp;quot;Checksum for file &#039;%s&#039; is %s\n&amp;quot;,&lt;br /&gt;
        gb_Args[ARG_filename], keybuffer);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    IDOS-&amp;gt;FreeArgs(rda);&lt;br /&gt;
  }&lt;br /&gt;
  else IDOS-&amp;gt;PrintFault(IDOS-&amp;gt;IoErr(),&amp;quot;CalcChecksum&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:AF111_CalcChecksum.png|frame|center]]&lt;br /&gt;
&lt;br /&gt;
= Standard-C-Functions =&lt;br /&gt;
&lt;br /&gt;
If you don&#039;t like to include the additonal C-libraries (newlib or clib2), it&#039;s possible to get similar functions from the utility.libary. In the case of string-functions, there are IUtility-&amp;gt;Strlcpy() and IUtility-&amp;gt;Strlcat() functions, which seem to have a slightly strange name, but work in a similar way as strncpy and strncat from the C-libaries. Since version 53.4 there is also a function called IUtility-&amp;gt;Strlen() which determines the length of a string. With AmigaOS 4.1 Final Edition new functions were added for handling UTF-8 coded strings.&lt;br /&gt;
&lt;br /&gt;
Like the memset function, there is a function called IUtility-&amp;gt;SetMem(), which is able to set the memory-area. The required arguments are the starting-address in the memory, the value to be set (usually 0 deletes the memory-area) and the number of bytes that have to be amended. In general the order of the arguments are the same as in the memset function. A shortcut can be taken, if you just use the IUtility-&amp;gt;ClearMem() function. This one only needs the starting-address and the number of bytes that should be cleared to zero. One other function, that works with memory-areas, is called IUtility-&amp;gt;MoveMem(). As the name implies, the memory-area will be moved. Well the source material stays unchanged, so it&#039;s more like copying the areas. You can compare this function to the IExec-&amp;gt;CopyMem() function from the exec.libary, but with the difference of allowing overlapping memory-areas. Make sure that your destination has enough free space for the data and, of course, it has to be reserved in your own program as well, because without reserving it, the OS will shutdown your program, if &amp;quot;aggravated&amp;quot; memory protection is enabled.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
 * MemoryFunctions.c&lt;br /&gt;
 *&lt;br /&gt;
 * gcc MemoryFunctions.c -o MemoryFunctions -l auto&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
/******************************* INCLUDES *************************************/&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;proto/exec.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/dos.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/utility.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/******************************************************************************/&lt;br /&gt;
&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
  UBYTE *mem;&lt;br /&gt;
&lt;br /&gt;
  /* Request memory */&lt;br /&gt;
  if((mem = (UBYTE *) IExec-&amp;gt;AllocVecTags(512, TAG_END)))&lt;br /&gt;
  {&lt;br /&gt;
    IDOS-&amp;gt;Printf(&amp;quot;memory allocated\n&amp;quot;);&lt;br /&gt;
    &lt;br /&gt;
    /* Clear memory area */&lt;br /&gt;
    IUtility-&amp;gt;ClearMem(mem,512);&lt;br /&gt;
&lt;br /&gt;
    /* Set memory area */    &lt;br /&gt;
    IUtility-&amp;gt;SetMem(mem,&#039;@&#039;,128);&lt;br /&gt;
&lt;br /&gt;
    /* Move memory area */&lt;br /&gt;
    IUtility-&amp;gt;MoveMem(mem,mem + 128,256);&lt;br /&gt;
&lt;br /&gt;
    /* Free memory area */&lt;br /&gt;
    IExec-&amp;gt;FreeVec(mem);&lt;br /&gt;
  }&lt;br /&gt;
  else IDOS-&amp;gt;Printf(&amp;quot;Not enough memory\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  return( 0 );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Randomizing =&lt;br /&gt;
&lt;br /&gt;
If you ever liked to create your own lottery numbers, the new IUtility-&amp;gt;Random() function will allow you to do just that. All you need is a number, so you can just pick the actual time or a random value from the stack. The function will return a number ranging from 1 up to 2147483647, which can be cut down via the modulo operation. Next up we see an example of how to create your own lottery numbers. &lt;br /&gt;
The same number can be chosen again, so there is room for improvement.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
  struct RandomState state;&lt;br /&gt;
  ULONG i, number;&lt;br /&gt;
  IDOS-&amp;gt;Printf(&amp;quot;6 out of 49:\n&amp;quot;);&lt;br /&gt;
  for(i=1; i&amp;lt;7; i++)&lt;br /&gt;
  {&lt;br /&gt;
    /* determines a number between 1 and 49 */&lt;br /&gt;
    number = (IUtility-&amp;gt;Random(&amp;amp;state) % 48) + 1;&lt;br /&gt;
    IDOS-&amp;gt;Printf(&amp;quot;%ld. Number %2ld\n&amp;quot;,i,number);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  number = (IUtility-&amp;gt;Random(&amp;amp;state) % 48) + 1;&lt;br /&gt;
  IDOS-&amp;gt;Printf(&amp;quot;Additional number %2ld\n&amp;quot;,number); &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
/* LottoGenerator.c&lt;br /&gt;
 *&lt;br /&gt;
 * gcc LottoGenerator.c -o LottoGenerator -l auto&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
/******************************* INCLUDES *************************************/&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;proto/exec.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/dos.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/utility.h&amp;gt;&lt;br /&gt;
#include &amp;lt;time.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/******************************************************************************/&lt;br /&gt;
&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
  struct RandomState state;&lt;br /&gt;
  uint32 i, number;&lt;br /&gt;
&lt;br /&gt;
  /*&lt;br /&gt;
  ** Initialize the start values so that a different&lt;br /&gt;
  ** series of random numbers are generated each time.&lt;br /&gt;
  */&lt;br /&gt;
  state.rs_High = time(NULL);&lt;br /&gt;
  state.rs_Low  = time(NULL);&lt;br /&gt;
&lt;br /&gt;
  IDOS-&amp;gt;Printf(&amp;quot;Lotto 6 out of 49:\n&amp;quot;);&lt;br /&gt;
  for(i=1; i&amp;lt;7; i++)&lt;br /&gt;
  {&lt;br /&gt;
    /*&lt;br /&gt;
    ** Determine a number from 1 to 49.&lt;br /&gt;
    */&lt;br /&gt;
    number = (IUtility-&amp;gt;Random(&amp;amp;state) % 48) + 1;&lt;br /&gt;
    IDOS-&amp;gt;Printf(&amp;quot;%ld. Number is %2ld\n&amp;quot;,i,number);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  number = (IUtility-&amp;gt;Random(&amp;amp;state) % 48) + 1;&lt;br /&gt;
  IDOS-&amp;gt;Printf(&amp;quot;The bonus number is %2ld\n&amp;quot;,number);&lt;br /&gt;
&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:AF111_LottoGenerator.png|frame|center]]&lt;br /&gt;
&lt;br /&gt;
= Miscellaneous functions =&lt;br /&gt;
&lt;br /&gt;
Another helpful function is called IUtility-&amp;gt;GetUniqueID(), which determines a unique number. This comes in handy by creating temporary files using multiple processes. As long as the system isn&#039;t shutdown, this unique number will be available. By restarting the system, the numbers will be created from scratch. Here is an easy example of how to create files with unique numbers:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
  ULONG id = IUtility-&amp;gt;GetUniqueID();&lt;br /&gt;
  BPTR fh;&lt;br /&gt;
  TEXT filename[30];&lt;br /&gt;
  IUtility-&amp;gt;SNPrintf(filename,sizeof(filename),&amp;quot;t:tmp.%ld&amp;quot;,id);&lt;br /&gt;
  if(IDOS-&amp;gt;Open(filename,MODE_NEWFILE))&lt;br /&gt;
  {&lt;br /&gt;
    ...&lt;br /&gt;
    IDOS-&amp;gt;CLose(fh);&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= New utility.library functions =&lt;br /&gt;
&lt;br /&gt;
== Taglist functions ==&lt;br /&gt;
&lt;br /&gt;
Allocates the memory for the number of given tags.&lt;br /&gt;
 struct TagItem *AllocateTagItems(ULONG numtags);&lt;br /&gt;
&lt;br /&gt;
Changes the tag-data-values in the changelist based on the values from the list. Unknown tags in the list will be ignored.&lt;br /&gt;
 VOID ApplyTagChanges(struct TagItem *list, struct TagItem *changelist);&lt;br /&gt;
&lt;br /&gt;
Creating a taglist copy; has to be deallocated via FreeTagItems().&lt;br /&gt;
 struct TagItem *CloneTagItems(struct TagItem *orglist);&lt;br /&gt;
&lt;br /&gt;
Deallocates the memory for the taglist.&lt;br /&gt;
 VOID FreeTagItems(struct TagItem *taglist);&lt;br /&gt;
&lt;br /&gt;
Creates a skip-tag-list; has to be deallocated via DeleteSkipList().&lt;br /&gt;
 struct SkipList * CreateSkipList(struct Hook *hook, LONG max_levels);&lt;br /&gt;
 VOID DeleteSkipList(struct SkipList *list);&lt;br /&gt;
&lt;br /&gt;
Searches the changelist and deletes all entries, which are identical to the entries in the orglist. In the case of different values, the keyword &amp;quot;apply&amp;quot; defines if the value should be assumed from the orglist.&lt;br /&gt;
 VOID FilterTagChanges(struct TagItem *changelist, struct TagItem *orglist, ULONG apply);&lt;br /&gt;
&lt;br /&gt;
Deletes the tags from the changelist, if they occur in the filter array.&lt;br /&gt;
 ULONG FilterTagItems(struct TagItem *changelist, Tag *filterarray ,ULONG logic);&lt;br /&gt;
&lt;br /&gt;
Searches the taglist for the right entry and returns the matching items.&lt;br /&gt;
 struct TagItem *FindTagItem(Tag tag,struct TagItem *taglist);&lt;br /&gt;
&lt;br /&gt;
Determines the data value of the declared tag from the list.&lt;br /&gt;
 ULONG GetTagData(Tag tag, ULONG default, struct TagItem *taglist);&lt;br /&gt;
&lt;br /&gt;
Transfers the maplist values into the corresponding fields of the taglist. Type pin-points what happens to all entries, which only occur in the taglist.&lt;br /&gt;
 VOID MapTags(struct TagItem *taglist, struct TagItem *maplist, ULONG type);&lt;br /&gt;
&lt;br /&gt;
== Splay-Tree-Functions ==&lt;br /&gt;
&lt;br /&gt;
Creating a Splay-Tree-Datastructure; has to be deallocated via DeleteSplayTree()&lt;br /&gt;
 struct SplayTree * CreateSplayTree(struct Hook *hook);&lt;br /&gt;
 VOID DeleteSplayTree(struct SplayTree *tree);&lt;br /&gt;
&lt;br /&gt;
Searches the tree for a specific key and returns the matching node&lt;br /&gt;
 struct SplayNode * FindSplayNode(struct SplayTree *tree, APTR key);&lt;br /&gt;
&lt;br /&gt;
Creates a new SplayNode and adds it to the tree&lt;br /&gt;
 struct SplayNode * InsertSplayNode(struct SplayTree *tree, APTR key, ULONG data_size);&lt;br /&gt;
&lt;br /&gt;
Removes the SplayNode from the tree, if a matching entry for the key was found.&lt;br /&gt;
 BOOL RemoveSplayNode(struct SplayTree *tree, APTR key);&lt;br /&gt;
&lt;br /&gt;
== Skip-List-Functions ==&lt;br /&gt;
&lt;br /&gt;
Searches the list for a specific key and returns the matching node.&lt;br /&gt;
 struct SkipNode * FindSkipNode(struct SkipList *list, APTR key);&lt;br /&gt;
&lt;br /&gt;
Determines the first node in the list&lt;br /&gt;
 struct SkipNode * GetFirstSkipNode(struct SkipList *list);&lt;br /&gt;
&lt;br /&gt;
Determines the next node after the previous node in the list.&lt;br /&gt;
 struct SkipNode * GetNextSkipNode(struct SkipList *list, struct SkipNode *previousnode);&lt;br /&gt;
&lt;br /&gt;
Creates a new skipnode and adds it to the list.&lt;br /&gt;
 struct SkipNode * InsertSkipNode(struct SkipList *list, APTR key, ULONG total_size);&lt;br /&gt;
&lt;br /&gt;
Removes the SkipNode from the list, if a matching entry for the key was found.&lt;br /&gt;
 BOOL RemoveSkipNode(struct SkipList *list, APTR key);&lt;br /&gt;
&lt;br /&gt;
== Miscellaneous functions ==&lt;br /&gt;
&lt;br /&gt;
Calculates a 160 bit checksum&lt;br /&gt;
 VOID MessageDigest_SHA_Init(struct MessageDigest_SHA *mdsha);&lt;br /&gt;
 VOID MessageDigest_SHA_Update(struct MessageDigest_SHA *mdsha, APTR data, LONG num_bytes);&lt;br /&gt;
 VOID MessageDigest_SHA_Final(struct MessageDigest_SHA *mdsha);&lt;br /&gt;
&lt;br /&gt;
A hook-function for an object to send a message&lt;br /&gt;
 ULONG CallHookPkt(struct Hook *hook, APTR object, APTR message);&lt;br /&gt;
&lt;br /&gt;
Provides a unique number (as long as the computer is running)&lt;br /&gt;
 ULONG GetUniqueID(void);&lt;br /&gt;
&lt;br /&gt;
A random number between 1 ... 2147483647 will be returned&lt;br /&gt;
 LONG Random(struct RandomState *state);&lt;br /&gt;
&lt;br /&gt;
Adds a value to the memory-area&lt;br /&gt;
 APTR SetMem(APTR destination, UBYTE value, LONG length);&lt;br /&gt;
&lt;br /&gt;
Deletes a memory-area (it will be filled with 0 bytes):&lt;br /&gt;
 VOID ClearMem(APTR destination, uint32 size);&lt;br /&gt;
&lt;br /&gt;
Moves parts of the memory-area (even if they are overlapping):&lt;br /&gt;
 VOID MoveMem(APTR source, APTR destination, uint32 size);&lt;br /&gt;
&lt;br /&gt;
Adds the source string to the destination, where the max length will be considered.&lt;br /&gt;
 LONG Strlcat(STRPTR destination, CONST_STRPTR source, LONG destination_size);&lt;br /&gt;
&lt;br /&gt;
Copies the string from its source to its destination, where the max length will be considered.&lt;br /&gt;
 LONG Strlcpy(STRPTR destination, CONST_STRPTR source, LONG destination_size);&lt;br /&gt;
&lt;br /&gt;
Determines the length of a string&lt;br /&gt;
uint32 Strlen(CONST_STRPTR string);&lt;br /&gt;
&lt;br /&gt;
Searches a node based on its name. Lower and Upper case will be ignored.&lt;br /&gt;
 struct Node *node = FindNameNC(struct Node *start, STRPTR name);&lt;br /&gt;
&lt;br /&gt;
Creates a string based on a specific format and the required args, (the returned string has to be deallocated via FreeVec)&lt;br /&gt;
 STRPTR VASPrintf(CONST_STRPTR format, APTR args);&lt;br /&gt;
 STRPTR ASPrintf(CONST_STRPTR format, ...);&lt;br /&gt;
&lt;br /&gt;
Creates a Format-String, where the result is stored in the buffer.&lt;br /&gt;
 LONG VSNPrintf(STRPTR buffer, LONG buffer_size, CONST_STRPTR format, APTR args);&lt;br /&gt;
 LONG SNPrintf(STRPTR buffer, LONG buffer_size, CONST_STRPTR format, ...);&lt;br /&gt;
&lt;br /&gt;
= Authors =&lt;br /&gt;
&lt;br /&gt;
Written by Michael Christoph&amp;lt;br/&amp;gt;&lt;br /&gt;
Translation by Florian Hanel&amp;lt;br/&amp;gt;&lt;br /&gt;
Copyright (c) 2013 Michael Christoph&lt;/div&gt;</summary>
		<author><name>Costel Mincea</name></author>
	</entry>
	<entry>
		<id>https://wiki.amigaos.net/w/index.php?title=SANA-II_Revision_7&amp;diff=12562</id>
		<title>SANA-II Revision 7</title>
		<link rel="alternate" type="text/html" href="https://wiki.amigaos.net/w/index.php?title=SANA-II_Revision_7&amp;diff=12562"/>
		<updated>2025-01-26T19:34:56Z</updated>

		<summary type="html">&lt;p&gt;Costel Mincea: Text replacement - &amp;quot;&amp;lt;syntaxhighlight&amp;gt;&amp;quot; to &amp;quot;&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{WIP}}&lt;br /&gt;
= SANA-II Network Device Driver Specification =&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;SANA-II Network Device Driver Specification&amp;quot; is a standard for an Amiga software interface between networking hardware and network protocol stacks (or for software tools such as network monitors). A network protocol stack is a layer of software that network applications use to address particular processes on remote machines and to send data reliably in spite of hardware errors. There are several common network protocol stacks including &#039;&#039;TCP/IP&#039;&#039;, &#039;&#039;OSI&#039;&#039;, &#039;&#039;AppleTalk&#039;&#039;, &#039;&#039;DECNet&#039;&#039; and &#039;&#039;Novell&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
SANA-II device drivers are intended to allow multiple network protocol stacks running on the same machine to share one network device. For example, the TCP/IP and AppleTalk protocol stacks could both run on the same machine over one ethernet board. The device drivers are also intended to allow network protocol stacks to be written in a hardware-independent fashion so that a different version of each protocol stack doesn&#039;t have to be written for each networking hardware device.&lt;br /&gt;
&lt;br /&gt;
The standard does not address the writing of network applications. Application writers must not use SANA-II Device Drivers directly. Network applications must use the API provided by the network protocol software the application supports. The Amiga standard network API for TCP/IP is provided via the bsdsocket.library which is a part of Roadshow.&lt;br /&gt;
&lt;br /&gt;
To write a SANA-II device driver, you will need to be familiar with the specification documents for the hardware you are writing to and with the &amp;quot;SANA-II Network Device Driver Specification&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
To write a network protocol stack which will use SANA-II device drivers, you should have general familiarity with common network hardware and must be very familiar with the &amp;quot;SANA-II Network Device Driver Specification&amp;quot; as well as the specification for the protocol you are developing. If you are creating a new protocol, you must obtain a protocol type number for any hardware on which your protocol will be used.&lt;br /&gt;
&lt;br /&gt;
This version of the specification is final. Any new version of the standard (i.e., to add new features) is planned to be backward compatible. No SANA-II device driver or software utilizing those drivers should be written to any earlier version of the specification.&lt;br /&gt;
&lt;br /&gt;
Distribution of this version of the standard is unlimited. Anyone may write Amiga software which implements a SANA-II network device driver or which calls a SANA-II network device driver without restriction and may freely distribute such software that they have written.&lt;br /&gt;
&lt;br /&gt;
It is important to try to test each SANA-II device driver against all software which uses SANA-II devices. Available example programs are valuable in initial testing. The Amiga Networking Group is interested in receiving evaluation and/or beta test copies of all Amiga networking hardware, SANA-II device drivers and software which uses SANA-II devices. However, we make no assurances regarding any testing which we may or may not perform with such evaluation copies.&lt;br /&gt;
&lt;br /&gt;
The SANA-II standard caters to both Motorola 68000 platforms and PowerPC platforms.&lt;br /&gt;
&lt;br /&gt;
Please feel free to comment. You can contact the AmigaOS development team through the [http://www.amigaos.net/contact AmigaOS contact form].&lt;br /&gt;
&lt;br /&gt;
= Driver Form =&lt;br /&gt;
&lt;br /&gt;
SANA-II device drivers are Amiga Exec device drivers. They use an extended IORequest structure and a number of extended commands for tallying network statistics, sending broadcasts and multicasts, network addressing and the handling of unexpected packets. The SDK includes information on how to construct an Exec device.&lt;br /&gt;
&lt;br /&gt;
= Opening a SANA-II Device =&lt;br /&gt;
&lt;br /&gt;
As when opening any other Exec device, on the call to OpenDevice() a SANA-II device receives an IORequest structure which the device initializes for the opener&#039;s use. The opener must copy this structure if it desires to use multiple asynchronous requests. The SANA-II IORequest is defined as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct IOSana2Req&lt;br /&gt;
{&lt;br /&gt;
  struct IORequest ios2_Req;&lt;br /&gt;
  ULONG ios2_WireError;&lt;br /&gt;
  ULONG ios2_PacketType;&lt;br /&gt;
  UBYTE ios2_SrcAddr[SANA2_MAX_ADDR_BYTES];&lt;br /&gt;
  UBYTE ios2_DstAddr[SANA2_MAX_ADDR_BYTES];&lt;br /&gt;
  ULONG ios2_DataLength;&lt;br /&gt;
  APTR ios2_Data;&lt;br /&gt;
  APTR ios2_StatData;&lt;br /&gt;
  APTR ios2_BufferManagement;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; ios2_Req&lt;br /&gt;
: A standard Exec device IORequest.&lt;br /&gt;
; ios2_WireError&lt;br /&gt;
: A more specific device code which may be set when there is an io_Error. See &amp;amp;lt;devices/sana2.h&amp;amp;gt; for the defined WireErrors.&lt;br /&gt;
; ios2_PacketType&lt;br /&gt;
: The type of packet requested. See the section on &amp;quot;Packet Types&amp;quot;.&lt;br /&gt;
; ios2_SrcAddr&lt;br /&gt;
: The device fills in this field with the interface (network hardware) address of the source of the packet that satisfied a read command. The bytes used to hold the address will be left justified but the bit layout is dependent on the particular type of network.&lt;br /&gt;
; ios2_DstAddr&lt;br /&gt;
: Before the device user sends a packet, it fills this with the interface destination address of the packet. On receives, the device fills this with the interface destination address. Other commands may use this field differently (see the &amp;quot;SANA-II network device driver Autodocs&amp;quot; in the SDK). The bytes used to hold the address will be left justified but the bit layout is dependent on the particular type of network.&lt;br /&gt;
; ios2_DataLength&lt;br /&gt;
: The device user initializes this field with the amount of data available in the Data buffer before passing the IOSana2Req to the device. The device fills in this field with the size of the packet data as it was sent on the wire. This does not include the header and trailer information. Depending on the network type and protocol type, the driver may have to calculate this value. This is generally used only for reads and writes (including broadcast and multicast).&lt;br /&gt;
; ios2_Data&lt;br /&gt;
: A pointer to some abstract data structure containing packet data. &#039;&#039;Drivers may not directly manipulate or examine anything pointed to by Data!&#039;&#039; This is generally used only for reads and writes (including broadcast and multicast).&lt;br /&gt;
&lt;br /&gt;
; ios2_StatData&lt;br /&gt;
: Pointer to a structure in which to place a snapshot of device statistics. The data area must be long word aligned. This is only used on calls to the statistics commands.&lt;br /&gt;
&lt;br /&gt;
; ios2_BufferManagement&lt;br /&gt;
: The opener places a pointer to a tag list in this field before calling OpenDevice(). Functions pointed to in the tag list are called by the device when processing IORequests from the opener. When returned from OpenDevice(), this field contains a pointer to driver-private information used to access these functions. See &amp;quot;Buffer Management&amp;quot; below for more details.&lt;br /&gt;
&lt;br /&gt;
: Note that the &amp;lt;tt&amp;gt;ios2_BufferManagement&amp;lt;/tt&amp;gt; field provided by the driver on &amp;lt;tt&amp;gt;OpenDevice()&amp;lt;/tt&amp;gt; time in conjunction with &amp;lt;tt&amp;gt;io_Device&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;io_Unit&amp;lt;/tt&amp;gt; is the unique identifier for all requests coming from this protocol stack until &amp;lt;tt&amp;gt;CloseDevice()&amp;lt;/tt&amp;gt;. The driver must not ever change the &amp;lt;tt&amp;gt;ios2_BufferManagement&amp;lt;/tt&amp;gt; field for a protocol stack at run time, even if &amp;lt;tt&amp;gt;S2_SANAHOOK&amp;lt;/tt&amp;gt; is called to request extended features.&lt;br /&gt;
&lt;br /&gt;
The flags used with the device on OpenDevice() are (SANA2OPB_xxx):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Name&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| SANA2OPB_MINE&lt;br /&gt;
| Exclusive access to the unit requested.&lt;br /&gt;
|-&lt;br /&gt;
| SANA2OPB_PROM&lt;br /&gt;
| Promiscuous mode requested. Hardware which supports promiscuous mode allows all packets sent over the wire to be captured whether or not they are addressed to this node.&amp;lt;/br&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;Note:&#039;&#039;&#039; Promiscuous mode requires exclusive opening of the device.&#039;&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The flags used during I/O requests are (SANA2IOB_xxx):&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Name&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| SANA2IOB_RAW&lt;br /&gt;
| Raw packet read/write requested. Raw packets should include the entire data-link layer packet. Devices with the same hardware device number should have the same raw packet format.&lt;br /&gt;
|-&lt;br /&gt;
| SANA2IOB_BCAST&lt;br /&gt;
| Broadcast packet (received).&lt;br /&gt;
|-&lt;br /&gt;
| SANA2IOB_MCAST&lt;br /&gt;
| Multicast packet (received).&lt;br /&gt;
|-&lt;br /&gt;
| SANA2IOB_QUICK&lt;br /&gt;
| Quick IO requested.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Buffer Management =&lt;br /&gt;
&lt;br /&gt;
Unlike most other Exec Device drivers, SANA-II drivers have no internal buffers. Instead, they read/write to/from an abstract data structure allocated by the driver user. The driver accesses these buffers only via functions that the driver user provides to the driver. The driver user must provide two functions: one copies data to the abstract data structure and one copies data from the abstract data structure. The driver user can therefore choose the data structure used for buffer management by both the driver and driver user in order to have efficient memory and CPU usage overall.&lt;br /&gt;
&lt;br /&gt;
The IOSana2Req contains a pointer to data and the length of said data. A driver is not allowed to make assumptions about how the data is stored. The driver cannot directly manipulate or examine the buffer in any manner. The driver can only access the buffer by calling the functions provided by the driver user.&lt;br /&gt;
&lt;br /&gt;
Before calling OpenDevice(), the driver user points ios2_BufferManagement to a list of tags (defined in &amp;amp;lt;devices/sana2.h&amp;amp;gt;) which include pointers to the buffer management functions required by the driver (defined below). The driver will fail to open if the driver user does not supply all of the required functions. If the device opens successfully, the driver sets ios2_BufferManagement to a value which this opener must use in all future calls to the driver. This &amp;quot;magic cookie&amp;quot; is used from then on to access these functions (a &amp;quot;magic cookie&amp;quot; is a value which one software entity passes to another but which is only meaningful to one of the software entities). The driver user may not use the &amp;quot;magic cookie&amp;quot; in any way--it is for the driver to do with as it wishes. The driver could in theory choose to just copy the tag list to driver-owned memory and then parse the list for every IORequest, but it is much more efficient for the driver to create some sort of table of functions and to point ios2_BufferManagement to that table.&lt;br /&gt;
&lt;br /&gt;
Another recommendation for the ``magic cookie`` is to use it to maintain a separate packet read queue for each device opener. This would allow multiple protocol stacks that all wish to receive the same packet type to work together without having to &amp;quot;know&amp;quot; about each other as &#039;&#039;Envoy&#039;&#039; and &#039;&#039;AS225&#039;&#039; do right now. What does multiple protocol stack support mean? Basically this means that each opener gets all the packets necessary. If a packet comes in that fills a request for more than one opener of the device, all of them will get a copy of the packet. This feature should never be left out of a device design. If it is missing, the usefulness of the device is severely limited.&lt;br /&gt;
&lt;br /&gt;
In order to help system load, a packet filter callback allows protocol stacks to reject packets that are known to not be useful. &#039;&#039;Envoy&#039;&#039;&#039;s nipc.library (for example) could be modified to reject TCP packets (as it never uses them).&lt;br /&gt;
&lt;br /&gt;
The specification currently defines the following tags for the OpenDevice() ios2_BufferManagement tag list:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Copy data from network interface to protocol stack buffer&lt;br /&gt;
! Tag&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| S2_CopyToBuff (mandatory)&lt;br /&gt;
| This is a pointer to a function which conforms to the CopyToBuff Autodoc.&lt;br /&gt;
|-&lt;br /&gt;
| S2_CopyToBuff16 (optional)&lt;br /&gt;
| Copy to a 16 bit aligned buffer using 16 bit data words.&lt;br /&gt;
|-&lt;br /&gt;
| S2_CopyToBuff32 (optional)&lt;br /&gt;
| Copy to a 32 bit aligned buffer using 32 bit data words.&lt;br /&gt;
|-&lt;br /&gt;
| S2_DMACopyToBuff32 (optional)&lt;br /&gt;
| Perform a DMA copy to a 32 bit aligned contiguous buffer using 32 bit data words.&lt;br /&gt;
|-&lt;br /&gt;
| S2_DMACopyToBuff64 (optional)&lt;br /&gt;
| Perform a DMA copy to a 64 bit aligned contiguous buffer using 64 bit data words.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Copy data from protocol stack buffer to network interface&lt;br /&gt;
! Tag&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| S2_CopyFromBuff (mandatory)&lt;br /&gt;
| This is a pointer to a function which conforms to the CopyFromBuff Autodoc.&lt;br /&gt;
|-&lt;br /&gt;
| S2_CopyFromBuff16 (optional)&lt;br /&gt;
| Copy from a 16 bit aligned buffer using 16 bit data words.&lt;br /&gt;
|-&lt;br /&gt;
| S2_CopyFromBuff32 (optional)&lt;br /&gt;
| Copy from a 32 bit aligned buffer using 32 bit data words.&lt;br /&gt;
|-&lt;br /&gt;
| S2_DMACopyFromBuff32 (optional)&lt;br /&gt;
| Perform a DMA copy from a 32 bit aligned contiguous buffer using 32 bit data words.&lt;br /&gt;
|-&lt;br /&gt;
| S2_DMACopyFromBuff64 (optional)&lt;br /&gt;
| Perform a DMA copy from a 64 bit aligned contiguous buffer using 64 bit data words.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Filter data before protocol stack buffer&lt;br /&gt;
! Tag&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| S2_PacketFilter (optional)&lt;br /&gt;
| This is a pointer to a standard Hook to be called before S2_CopyToBuff is done. See the PacketFilter Autodoc for more information.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Logging messages from the driver&lt;br /&gt;
! Tag&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| S2_Log (optional)&lt;br /&gt;
| This is a pointer to a standard Hook to be called when the driver logs events.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Better buffer management ==&lt;br /&gt;
&lt;br /&gt;
The mandatory buffer management callbacks may not be very efficient for certain types of hardware. They also do not allow driver DMA access.&lt;br /&gt;
&lt;br /&gt;
All the new features are completely optional and do not collide with existing features. They may be used only when the protocol stack asks for them on opening a driver.&lt;br /&gt;
&lt;br /&gt;
The enhancements consist of several new tags that may be specified by a protocol stack on OpenDevice() to offer certain data transfer options. It is up to the device driver to chose which callbacks to use at what time. These tags are advisory only and may be ignored by the driver for any data buffer at any time:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| S2_CopyToBuff16&lt;br /&gt;
|-&lt;br /&gt;
| S2_CopyFromBuff16&lt;br /&gt;
|-&lt;br /&gt;
| S2_CopyToBuff32&lt;br /&gt;
|-&lt;br /&gt;
| S2_CopyFromBuff32&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
These are optional callbacks presented to the device with the same calling interface as for S2_CopyToBuff or S2_CopyFromBuff, respectively. The difference to the original callbacks is the required and guaranteed transfer size and alignment for accessing the device&#039;s buffer for a single piece of a data of either 16 or 32 bits, a data word. The copy function called may only use 16/32 bit aligned read/write commands of 16/32 bits at once to transfer the data words, respectively. If the buffer data length is not a multiple of the required data word transfer size, the last data word transfer may contain garbage padding in either transfer direction.&lt;br /&gt;
&lt;br /&gt;
The following tags have been added to support direct writes into hardware buffers that do not allow arbitrarily sized or aligned accesses:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| S2_DMACopyToBuff32&lt;br /&gt;
|-&lt;br /&gt;
| S2_DMACopyFromBuff32&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
If the protocol stack wants to optionally enhance data transfer efficiency with DMA supporting devices, it may pass any of these optional tags to the device on OpenDevice().&lt;br /&gt;
&lt;br /&gt;
If the device driver supports DMA, it may call the respective callback with the abstract magic cookie ios2_Data in register A0. The callback may return NULL in D0. In this case, the driver may not use DMA for this buffer. Alternatively, the callback may return the address of the actual data buffer in D0, if it has these characteristics:&lt;br /&gt;
&lt;br /&gt;
* The buffer is in contiguous memory. Depending on the intended data direction, it shall be readable or writable.&lt;br /&gt;
* The buffer is aligned on a 32 bit boundary.&lt;br /&gt;
* The buffer size shall be a multiple of 32 bit and it is at least = ios2_DataLength.&lt;br /&gt;
* It is up to the driver to decide if it can use DMA for this buffer and it shall fall back to the standard CPU callbacks if necessary. The data transfer method actually used by the driver will not be known in advance by the protocol stack.&lt;br /&gt;
&lt;br /&gt;
The following tags have been added to allow for 64 bit aligned PCI DMA accesses to take place:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| S2_DMACopyToBuff64&lt;br /&gt;
|-&lt;br /&gt;
| S2_DMACopyFromBuff64&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
These two callbacks are identical in operation to the &amp;lt;tt&amp;gt;S2_DMACopyToBuff32&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2_DMACopyFromBuff32&amp;lt;/tt&amp;gt; callbacks. The difference is in that the memory region DMA is to take place in must be aligned to a 64 bit boundary and must be large enough to hold data that is a multiple of 64 bits in size.&lt;br /&gt;
&lt;br /&gt;
== Best buffer management ==&lt;br /&gt;
&lt;br /&gt;
The SANA-II driver interface is intended to transform data between the hardware layer and the link layer, to be used by networking software such as TCP/IP stacks. This transformation is performed by callback functions which are supplied by the networking software at the time the device driver is opened. The device driver then invokes these functions later in order to transfer data received and data to be sent.&lt;br /&gt;
&lt;br /&gt;
The function parameters used by these callbacks are passed in 68000 registers for the lowest overhead. The problem with 68000 register parameters is that on the PowerPC platform, this form of parameter passing may require the use of emulation code. This is costly and may incur a severe performance penalty. It is an even greater problem if PowerPC native networking software is calling PowerPC native networking driver software and the other way round. In both cases the runtime environment will have to enter emulation mode, return to to PowerPC native execution, dip into emulation mode and return to native PowerPC execution. It would be much better if the chain of execution would stay in PowerPC mode all the time.&lt;br /&gt;
&lt;br /&gt;
Alternatively, if a hook function is used, the operating system may be able to decide whether the function to be invoked needs emulating or called directly. The &amp;lt;tt&amp;gt;Hook&amp;lt;/tt&amp;gt; effectively works as an abstraction which makes the function invocation platform independent.&lt;br /&gt;
&lt;br /&gt;
The following standard wraps the copying and logging functions into the standardized &amp;lt;tt&amp;gt;Hook&amp;lt;/tt&amp;gt; interface.&lt;br /&gt;
&lt;br /&gt;
==== The hook function ====&lt;br /&gt;
&lt;br /&gt;
The hook function itself is invoked with the following parameters:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
   result = hook_function(hook, sana2req, sana2hookmsg)&lt;br /&gt;
&lt;br /&gt;
   ULONG hook_function(struct Hook *hook,&lt;br /&gt;
                       struct IOSana2Req *sana2req,&lt;br /&gt;
                       struct SANA2HookMsg *sana2hookmsg);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the result is not necessarily of type &amp;lt;tt&amp;gt;ULONG&amp;lt;/tt&amp;gt;. It is a 32 bit value, which can be a boolean result code (for &amp;lt;tt&amp;gt;CopyFromBuff&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;CopyToBuff&amp;lt;/tt&amp;gt; and their like) or a pointer to a memory address (for &amp;lt;tt&amp;gt;DMACopyToBuff&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;DMACopyFromBuff&amp;lt;/tt&amp;gt; and their like).&lt;br /&gt;
&lt;br /&gt;
=== Data structures ===&lt;br /&gt;
&lt;br /&gt;
The following hook messages are to be used:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct SANA2HookMsg&lt;br /&gt;
{&lt;br /&gt;
  ULONG shm_Method;&lt;br /&gt;
  ULONG shm_MsgSize;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this data structure the &amp;lt;tt&amp;gt;shm_Method&amp;lt;/tt&amp;gt; field would indicate the task to be performed. This can be a request to copy data or to store a log message. The &amp;lt;tt&amp;gt;shm_MsgSize&amp;lt;/tt&amp;gt; field tells you how large the data structure is for future enhancements which may cause the data structure to grow.&lt;br /&gt;
&lt;br /&gt;
==== Copying operations ====&lt;br /&gt;
&lt;br /&gt;
For copying operations the message is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct SANA2CopyHookMsg&lt;br /&gt;
{&lt;br /&gt;
  ULONG schm_Method;&lt;br /&gt;
  ULONG schm_MsgSize;&lt;br /&gt;
&lt;br /&gt;
  APTR  schm_To;&lt;br /&gt;
  APTR  schm_From;&lt;br /&gt;
  ULONG schm_Size;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The structure members are as follows:&lt;br /&gt;
&lt;br /&gt;
; schm_Method&lt;br /&gt;
: This must be one &amp;lt;tt&amp;gt;S2_CopyToBuff&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;S2_CopyFromBuff&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;S2_CopyToBuff16&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;S2_CopyFromBuff16&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;S2_CopyToBuff32&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;S2_CopyFromBuff32&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;S2_DMACopyToBuff32&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;S2_DMACopyFromBuff32&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;S2_DMACopyToBuff64&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;S2_DMACopyFromBuff64&amp;lt;/tt&amp;gt; to identify the function to be performed.&lt;br /&gt;
&lt;br /&gt;
; schm_MsgSize&lt;br /&gt;
: Size of this message data structure in bytes. This must be &amp;amp;gt;= 20 for this message type.&lt;br /&gt;
: The driver shall set &amp;lt;tt&amp;gt;schm_MsgSize&amp;lt;/tt&amp;gt; always correctly to be compliant. The protocol stack shall use this field to validate the message and to reject/ignore bad messages via a &amp;lt;tt&amp;gt;FALSE&amp;lt;/tt&amp;gt; hook function return value. For DMA related hooks, a &amp;lt;tt&amp;gt;FALSE&amp;lt;/tt&amp;gt; return value is equivalent to a &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; pointer.&lt;br /&gt;
&lt;br /&gt;
; schm_To&lt;br /&gt;
: Equivalent to the &amp;lt;tt&amp;gt;to&amp;lt;/tt&amp;gt; parameter of the &amp;lt;tt&amp;gt;CopyFromBuff&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;CopyToBuff&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;DMACopyToBuff&amp;lt;/tt&amp;gt; functions.&lt;br /&gt;
&lt;br /&gt;
; schm_From&lt;br /&gt;
: Equivalent to the &amp;lt;tt&amp;gt;from&amp;lt;/tt&amp;gt; parameter of the &amp;lt;tt&amp;gt;CopyFromBuff&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;CopyToBuff&amp;lt;/tt&amp;gt; functions.&lt;br /&gt;
&lt;br /&gt;
; schm_Size&lt;br /&gt;
: Equivalent to the &amp;lt;tt&amp;gt;n&amp;lt;/tt&amp;gt; parameter of the &amp;lt;tt&amp;gt;CopyFromBuff&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;CopyToBuff&amp;lt;/tt&amp;gt;, functions.&lt;br /&gt;
&lt;br /&gt;
==== Logging operations ====&lt;br /&gt;
&lt;br /&gt;
For logging operations the message is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct SANA2LogHookMsg&lt;br /&gt;
{&lt;br /&gt;
  ULONG  slhm_Method;&lt;br /&gt;
  ULONG  slhm_MsgSize;&lt;br /&gt;
&lt;br /&gt;
  ULONG  slhm_Priority;&lt;br /&gt;
  STRPTR slhm_Name;&lt;br /&gt;
  STRPTR slhm_Message;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The structure members would be used as follows:&lt;br /&gt;
&lt;br /&gt;
; slhm_Method&lt;br /&gt;
: This must be &amp;lt;tt&amp;gt;S2_Log&amp;lt;/tt&amp;gt;, as defined in the SANA-IIR4 specification.&lt;br /&gt;
&lt;br /&gt;
; slhm_MsgSize&lt;br /&gt;
: Size of this message data structure in bytes. This must be &amp;amp;gt;= 20 for this message type.&lt;br /&gt;
: The driver shall set &amp;lt;tt&amp;gt;slhm_MsgSize&amp;lt;/tt&amp;gt; always correctly to be compliant. The protocol stack shall use this field to validate the message and to reject/ignore bad messages via a &amp;lt;tt&amp;gt;FALSE&amp;lt;/tt&amp;gt; hook function return value. For DMA related hooks, a &amp;lt;tt&amp;gt;FALSE&amp;lt;/tt&amp;gt; return value is equivalent to a &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; pointer.&lt;br /&gt;
&lt;br /&gt;
; slhm_Priority&lt;br /&gt;
: The smaller this value, the more important the message to be logged or displayed. The following priority levels are defined (similar to the Unix syslog() mechanism):&lt;br /&gt;
:{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| S2LOG_Emergency || A panic condition.&lt;br /&gt;
|-&lt;br /&gt;
| S2LOG_Alert || A condition that should be corrected immediately.&lt;br /&gt;
|-&lt;br /&gt;
| S2LOG_Critical || Critical conditions.&lt;br /&gt;
|-&lt;br /&gt;
| S2LOG_Error || A plain error.&lt;br /&gt;
|-&lt;br /&gt;
| S2LOG_Warning || A warning message.&lt;br /&gt;
|-&lt;br /&gt;
| S2LOG_Notice || Conditions that are not error conditions, but should possibly be handled specially.&lt;br /&gt;
|-&lt;br /&gt;
| S2LOG_Information || An informational message.&lt;br /&gt;
|-&lt;br /&gt;
| S2LOG_Debug || Messages that contain information normally of use only when debugging.&lt;br /&gt;
|}&lt;br /&gt;
: Only these priority values may be used by a driver. It is suggested that a driver is configurable to generate different types of messages or not, e.g., a driver may be configured to only emit &amp;lt;tt&amp;gt;S2LOG_Emergency&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2LOG_Debug&amp;lt;/tt&amp;gt; messages&lt;br /&gt;
&lt;br /&gt;
; slhm_Name&lt;br /&gt;
: Pointer to a &amp;lt;tt&amp;gt;NUL&amp;lt;/tt&amp;gt;-terminated string which identifies the source of this message. This can be &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; in which case the OS device name of the driver shall be used by the protocol stack.&lt;br /&gt;
&lt;br /&gt;
; slhm_Message&lt;br /&gt;
: Pointer to a &amp;lt;tt&amp;gt;NUL&amp;lt;/tt&amp;gt;-terminated string which contains the log message. The text should not contain any formatting characters such as line feeds or carriage returns. The &amp;lt;tt&amp;gt;slhm_Message&amp;lt;/tt&amp;gt; member must never be &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt;.&lt;br /&gt;
: All message texts shall preferably be formatted in the current user&#039;s locale. If that is not possible, the english language shall be used. &amp;lt;tt&amp;gt;slhm_Name&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;slhm_Message&amp;lt;/tt&amp;gt; shall only contain printable characters.&lt;br /&gt;
&lt;br /&gt;
=== Application and driver software use of the new functions ===&lt;br /&gt;
&lt;br /&gt;
Since plenty of software exists which uses the &#039;traditional&#039; &amp;lt;tt&amp;gt;TagItem&amp;lt;/tt&amp;gt; list provided at &amp;lt;tt&amp;gt;OpenDevice()&amp;lt;/tt&amp;gt; time, drivers must always examine these parameters and not expect a &amp;lt;tt&amp;gt;S2_SANA2HOOK&amp;lt;/tt&amp;gt; command to be sent later.&lt;br /&gt;
&lt;br /&gt;
If the new &amp;lt;tt&amp;gt;Hook&amp;lt;/tt&amp;gt;-based callback functions are used then the driver must invoke the Hooks via &amp;lt;tt&amp;gt;utility.library/CallHookPkt&amp;lt;/tt&amp;gt;. It must never invoke the hook functions through local assembly language stubs or the &amp;lt;tt&amp;gt;amiga.lib/CallHook&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;amiga.lib/CallHookA&amp;lt;/tt&amp;gt; functions.&lt;br /&gt;
&lt;br /&gt;
=== Caveats ===&lt;br /&gt;
&lt;br /&gt;
The functionality above suggests that one could do entirely without the &amp;lt;tt&amp;gt;TagItem&amp;lt;/tt&amp;gt; list passed in at &amp;lt;tt&amp;gt;OpenDevice()&amp;lt;/tt&amp;gt; time. However, at this time it is hard to tell how existing driver software will react to empty &amp;lt;tt&amp;gt;TagItem&amp;lt;/tt&amp;gt; lists or even a NULL pointer in the &amp;lt;tt&amp;gt;IOSana2Req-&amp;amp;gt;ios2_BufferManagement&amp;lt;/tt&amp;gt; field. It is therefore important to always provide for a &amp;lt;tt&amp;gt;TagItem&amp;lt;/tt&amp;gt; list which includes proper (i.e. they must point to working functions and may not be &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt;) function pointers for the &amp;lt;tt&amp;gt;S2_CopyToBuff&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2_CopyFromBuff&amp;lt;/tt&amp;gt; tags. Once the device has been opened successfully, the next step is to try and install the copy &amp;lt;tt&amp;gt;Hook&amp;lt;/tt&amp;gt; through the proposed &amp;lt;tt&amp;gt;S2_SANA2HOOK&amp;lt;/tt&amp;gt; command. If the command fails, the application can still expect that the &amp;lt;tt&amp;gt;S2_CopyToBuff&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2_CopyFromBuff&amp;lt;/tt&amp;gt; tags supplied at &amp;lt;tt&amp;gt;OpenDevice()&amp;lt;/tt&amp;gt; time will work.&lt;br /&gt;
&lt;br /&gt;
== Packet filtering ==&lt;br /&gt;
&lt;br /&gt;
With the original &amp;quot;SANA-II Network Device Driver Specification&amp;quot;, a protocol stack could open a device and ask for certain packet types. It got all the packets that matched this type. As it turned out, this could be mighty inefficient if there were packets that the protocol stack did not use at all. These would go into read processing of the protocol stack and waste CPU time even though they could have been easily identified on arrival.&lt;br /&gt;
&lt;br /&gt;
== Driver event logging ==&lt;br /&gt;
&lt;br /&gt;
A driver may want to report an important event for the user to see. Adding a log message to a file or opening a window to display a message in may not be the optimum approach as the user may be unaware of the context into which the message belongs. It may be advisable for the driver to use the message reporting and logging facilities used by the client software that uses its services, such as a TCP/IP stack. The &amp;lt;tt&amp;gt;S2_Log&amp;lt;/tt&amp;gt; callback hook is intended to provide for such a link.&lt;br /&gt;
&lt;br /&gt;
If present, the driver must use this callback hook rather than whatever logging methods it implements itself. Note that unlike the other SANA-II callbacks, this is a regular hook, as to be invoked using &amp;lt;tt&amp;gt;utility.library&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;CallHookPkt()&amp;lt;/tt&amp;gt;. The hook function is invoked using the following parameters:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
log_hook_function(hook, reserved, message)&lt;br /&gt;
&lt;br /&gt;
void log_hook_function(struct hook * hook,APTR reserved,&lt;br /&gt;
                       struct S2LogMessage * message);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;reserved&amp;lt;/tt&amp;gt; parameter &#039;&#039;&#039;must&#039;&#039;&#039; be set to &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt;. The &amp;lt;tt&amp;gt;S2LogMessage&amp;lt;/tt&amp;gt; structure passed as the third parameter looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct S2LogMessage&lt;br /&gt;
{&lt;br /&gt;
   LONG   s2lm_Size;&lt;br /&gt;
   ULONG  s2lm_Priority;&lt;br /&gt;
   STRPTR s2lm_Name;&lt;br /&gt;
   STRPTR s2lm_Message;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The individual structure members serve the following functions:&lt;br /&gt;
&lt;br /&gt;
; s2lm_Size&lt;br /&gt;
: Size of the &amp;lt;tt&amp;gt;S2LogMessage&amp;lt;/tt&amp;gt; structure, in bytes. The idea is to extend this data structure in the future, and the size stored in here tells you how long the structure is. The size &#039;&#039;&#039;must&#039;&#039;&#039; always be &amp;amp;gt;= 16.&lt;br /&gt;
&lt;br /&gt;
;s2lm_Priority&lt;br /&gt;
: The smaller this value, the more important the message to be logged or displayed. The following priority levels are defined (similar to the Unix &amp;lt;tt&amp;gt;syslog()&amp;lt;/tt&amp;gt; mechanism):&lt;br /&gt;
:{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| S2LOG_Emergency || A panic condition.&lt;br /&gt;
|-&lt;br /&gt;
| S2LOG_Alert || A condition that should be corrected immediately.&lt;br /&gt;
|-&lt;br /&gt;
| S2LOG_Critical || Critical conditions.&lt;br /&gt;
|-&lt;br /&gt;
| S2LOG_Error || A plain error.&lt;br /&gt;
|-&lt;br /&gt;
| S2LOG_Warning || A warning message.&lt;br /&gt;
|-&lt;br /&gt;
| S2LOG_Notice || Conditions that are not error conditions, but should possibly be handled specially.&lt;br /&gt;
|-&lt;br /&gt;
| S2LOG_Information || An informational message.&lt;br /&gt;
|-&lt;br /&gt;
| S2LOG_Debug || Messages that contain information normally of use only when debugging.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
; s2lm_Name&amp;lt;/tt&amp;gt;&lt;br /&gt;
: Pointer to a &amp;lt;tt&amp;gt;NUL&amp;lt;/tt&amp;gt;-terminated string which identifies the source of this message. This can be &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; in which case the name is treated as being unknown.&lt;br /&gt;
&lt;br /&gt;
; s2lm_Message&lt;br /&gt;
: Pointer to a &amp;lt;tt&amp;gt;NUL&amp;lt;/tt&amp;gt;-terminated string which contains the log message. The text should not contain any formatting characters such as line feeds or carriage returns. The &amp;lt;tt&amp;gt;s2lm_Message&amp;lt;/tt&amp;gt; member &#039;&#039;&#039;must never&#039;&#039;&#039; be &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
All error messages issued by the device driver should use the current system locale wherever this is possible. The purpose of an error message is, after all, to assist the user in recovering from the error. Which may be difficult if the user does not even know the language in which the message is written.&lt;br /&gt;
&lt;br /&gt;
The log message string is valid until the log hook function returns. If the driver needs to retain the message any longer, it must make a copy of it.&lt;br /&gt;
&lt;br /&gt;
Since the client software into which the log hook calls may have to allocate memory to hold and display the log message, the log hook &#039;&#039;&#039;must not&#039;&#039;&#039; be called from interrupt code. The log hook shall not &amp;lt;tt&amp;gt;Wait()&amp;lt;/tt&amp;gt; and it shall assume only a &amp;lt;tt&amp;gt;Task&amp;lt;/tt&amp;gt; calling context of unknown priority. &amp;lt;tt&amp;gt;dos.library&amp;lt;/tt&amp;gt; functions may not be called. Also, stack space is provided only to call &amp;lt;tt&amp;gt;exec.library&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;utility.library&amp;lt;/tt&amp;gt; functions. The callback shall not place excessive data on the stack. Stack space should be considered limited and the callback should be designed to be fast and short.&lt;br /&gt;
&lt;br /&gt;
This hook is installed at &amp;lt;tt&amp;gt;OpenDevice()&amp;lt;/tt&amp;gt; time, which means that the hook is used for the unit that was opened, and not just for the I/O request it was opened with. The hook must remain installed until the I/O request that installed it is eventually used to close the device. When this happens, the device should fall back to use no log hook at all. No nesting is permitted or required.&lt;br /&gt;
&lt;br /&gt;
= Packet Type =&lt;br /&gt;
&lt;br /&gt;
Network frames always have a type field associated with them. These type fields vary in length, position and meaning by frame type (frame types generally correspond one-to-one with hardware types, but see &amp;quot;Ethernet Packet Types&amp;quot; below). The meanings of the type numbers are always carefully defined and every type number is registered with some official body. Do not use a type number which is not registered for any standard hardware you use or in a manner inconsistent with that registration.&lt;br /&gt;
&lt;br /&gt;
The type field allows the SANA-II device driver to fulfill CMD_READs based on the type of packet the driver user wants. Multiple protocols can therefore run over the same wire using the same driver without stepping on each other&#039;s toes.&lt;br /&gt;
&lt;br /&gt;
Packet types are specified as a long word. Unfortunately, the type field means different things on different wires. Driver users must allow their software to be configured with a SANA-II device name, unit number and the type number(s) used by the protocol stack with each device. This way, if new hardware becomes available, a hardware manufacturer can supply a listing of type assignments to configure pre-existing software.&lt;br /&gt;
&lt;br /&gt;
== Ethernet Packet Types ==&lt;br /&gt;
&lt;br /&gt;
Ethernet has a special problem with packet types. Two types of ethernet frames can be sent over the same wire: ethernet and 802.3. These frames differ in that the Type field of an ethernet frame is the Length field of an 802.3 frame. This creates a problem in that demultiplexing incoming packets can be cumbersome and inefficient, as well as requiring driver users to be aware of the frame type used.&lt;br /&gt;
&lt;br /&gt;
All 802.3 frames have numbers less than 1500 in the Type field. The only frames with numbers less than 1500 in the type field are 802.3 frames. SANA-II ethernet drivers abnormally return packets contained in ethernet frames when the requested Type falls within the 802.3 range-if the Type requested is within the 802.3 range, the driver returns the next packet contained within an 802.3 frame, regardless of the type specified for the packet within the 802.3 frame. This requires that there be no more than one driver user requesting 802.3 packets and that it do its own interpretation of the frames.&lt;br /&gt;
&lt;br /&gt;
== ARCNET Frames ==&lt;br /&gt;
&lt;br /&gt;
ARCNET also has a special problem with framing. ARCNET frames consist of a hardware header and a software header. The software header is in the data area of the hardware packet, and includes at least the protocol ID.&lt;br /&gt;
&lt;br /&gt;
There are two types of software header. Old-style ARCNET software headers consist entirely of a one or two byte protocol ID. New ARCNET software headers (defined in RFC 1201 and in the paper &amp;quot;ARCNET Packet Header Definition Standard&amp;quot;, Novell, Inc., 1989) include more information. They allow more efficient use of ARCNET through data link layer fragmentation and reassembly (ARCNET has a small Maximum Transmission Unit) and allow sending any size packet up to the MTU (rather than requiring that packets of size 253, 254 and 255 be padded to at least 256 bytes).&lt;br /&gt;
&lt;br /&gt;
SANA-II device drivers for ARCNET should implement the old ARCNET packet headers. Driver users which wish to interoperate with platforms using the new software headers must add the new fields to the data to be sent and must process it for incoming data. A SANA-II driver which implemented the data link layer fragmentation internally (and advertised a large MTU) could be more efficient than requiring the driver user to do it. This would make driver writing more difficult and reduce interoperability, but if there is ever a demand for that extra performance, a new hardware type may be assigned by Amiga for SANA-II ARCNET device drivers which implement the new framing.&lt;br /&gt;
&lt;br /&gt;
= Addressing =&lt;br /&gt;
&lt;br /&gt;
In the SANA-II standard, network hardware addresses are stored in an array of &#039;&#039;n&#039;&#039; bytes. No meaning is ascribed by the standard to the contents of the array.&lt;br /&gt;
&lt;br /&gt;
In case there exists a network which does not have an address field consisting of a number of bits not divisible by eight, add pad bits at the end of the bit stream. For example, if an address is ten bits long it will be stored like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
98765432 10PPPPPP&lt;br /&gt;
BYTE 0   BYTE 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where the numerals are bit numbers and &amp;quot;P&amp;quot; is a pad (ignored) bit.&lt;br /&gt;
&lt;br /&gt;
Driver users which do not implement the bit shifting necessary to use a network with such addressing (if one exists) should at least check the number of significant bits in the address field (returned from the device&#039;s S2_DEVICEQUERY function) to make sure that it is evenly divisible by eight.&lt;br /&gt;
&lt;br /&gt;
Driver users will map hardware addresses to protocol addresses in a protocol and hardware dependent manner, as described by the relevant standards (i.e., RFC 826 for TCP/IP over Ethernet, RFC 1201 or RFC 1051 for TCP/IP over ARCNET). Some protocols will always use the same mapping on all hardware, but other protocols will have particular address mapping schemes for some particular hardware and a reasonable default for other (unknown) hardware.&lt;br /&gt;
&lt;br /&gt;
Some SANA-II devices will have &amp;quot;hardware addresses&amp;quot; which aren&#039;t really hardware addresses. As an example, consider &#039;&#039;PPP&#039;&#039; (Point-to-Point Protocol). PPP is a standard for transmitting IP packets over a serial line. It uses IP addresses negotiated during the establishment of a connection. In a SANA-II driver implementation of PPP, the driver would negotiate the address at S2_CONFIGINTERFACE. Thus, the address in SrcAddr returned by the device on an S2_CONFIGINTERFACE (or in a subsequent S2_GETSTATIONADDRESS) will be a protocol address, not a true hardware address.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; Some hardware always uses a ROM hardware address. Other hardware which has a ROM address or is configurable with DIP switches may be overridden by software. Some hardware always dynamically allocates a new hardware address at initialization. See &amp;quot;Configuration&amp;quot; for details on how this is handled by driver writers and by driver users.&lt;br /&gt;
&lt;br /&gt;
= Hardware Type =&lt;br /&gt;
&lt;br /&gt;
The HardwareType returned by the device&#039;s S2_DEVICEQUERY function is necessary for those protocols whose standards require different behavior on different hardware. It is also useful for determining appropriate packet type numbers to use with the device. The HardwareType values already issued for standard network hardware are the same as those in RFC 1060 (assigned numbers). Hardware developers implementing networks without a SANA-II hardware number must contact the AmigaOS development team to have a new hardware type number assigned. Driver users should all have reasonable defaults which can be used for hardware with which they are not familiar.&lt;br /&gt;
&lt;br /&gt;
= Errors =&lt;br /&gt;
&lt;br /&gt;
The SANA-II extended IORequest structure (struct IOSana2Req) includes both the ios2_Error and ios2_WireError fields. Driver users must always check IOSana2Reqs on return for an error in ios2_Error. ios2_Error will be zero if no error occurred, otherwise it will contain a value from &amp;amp;lt;exec/errors.h&amp;amp;gt; or &amp;amp;lt;devices/sana2.h&amp;amp;gt;. If there was an error, there may be more specific information in ios2_WireError. Drivers are required to fill in the WireError if there is an applicable error code.&lt;br /&gt;
&lt;br /&gt;
Error codes are #define&#039;d in the &amp;quot;defined errors&amp;quot; sections of the file &amp;amp;lt;devices/sana2.h&amp;amp;gt;:&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! IOSana2Req S2io_Error field&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| S2ERR_NO_RESOURCES&lt;br /&gt;
| Insufficient resources available.&lt;br /&gt;
|-&lt;br /&gt;
| S2ERR_BAD_ARGUMENT&lt;br /&gt;
| Noticeably bad argument.&lt;br /&gt;
|-&lt;br /&gt;
| S2ERR_BAD_STATE&lt;br /&gt;
| Command inappropriate for current state.&lt;br /&gt;
|-&lt;br /&gt;
| S2ERR_BAD_ADDRESS&lt;br /&gt;
| Noticeably bad address.&lt;br /&gt;
|-&lt;br /&gt;
| S2ERR_MTU_EXCEEDED&lt;br /&gt;
| Write data too large.&lt;br /&gt;
|-&lt;br /&gt;
| S2ERR_NOT_SUPPORTED&lt;br /&gt;
| Command is not supported by this driver. This is similar to IOERR_NOCMD as defined in &amp;amp;lt;exec/errors.h&amp;amp;gt; but S2ERR_NOT_SUPPORTED indicates that the requested command is a valid SANA-II command and that the driver does not support it because the hardware is incapable of supporting it (e.g., S2_MULTICAST). Note that IOERR_NOCMD is still valid for reasons other than a lack of hardware support (i.e., commands which are no-ops in a SANA-II driver).&lt;br /&gt;
|-&lt;br /&gt;
| S2ERR_SOFTWARE&lt;br /&gt;
| Software error of some kind.&lt;br /&gt;
|-&lt;br /&gt;
| S2ERR_OUTOFSERVICE&lt;br /&gt;
| When a hardware device is taken off-line, any pending requests are returned with this error.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
See also the standard errors in &amp;amp;lt;exec/errors.h&amp;amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! IOSana2Req S2io_WireError field&lt;br /&gt;
! Description&lt;br /&gt;
! Value&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_NOT_CONFIGURED&lt;br /&gt;
| Command requires unit to be configured.&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_UNIT_ONLINE&lt;br /&gt;
| Command requires that the unit be off-line.&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_UNIT_OFFLINE&lt;br /&gt;
| Command requires that the unit be on-line.&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_ALREADY_TRACKED&lt;br /&gt;
| Protocol is already being tracked.&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_NOT_TRACKED&lt;br /&gt;
| Protocol is not being tracked.&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_BUFF_ERROR&lt;br /&gt;
| Buffer management function returned an error.&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_SRC_ADDRESS&lt;br /&gt;
| Problem with the source address field.&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_DST_ADDRESS&lt;br /&gt;
| Problem with destination address field.&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_BAD_BROADCAST&lt;br /&gt;
| Problem with an attempt to broadcast.&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_BAD_MULTICAST&lt;br /&gt;
| Problem with an attempt to multicast.&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_MULTICAST_FULL&lt;br /&gt;
| Multicast address list full.&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_BAD_EVENT&lt;br /&gt;
| Event specified is unknown.&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_BAD_STATDATA&lt;br /&gt;
| The ios2_StatData pointer or the data it points to failed a sanity check.&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_IS_CONFIGURED&lt;br /&gt;
| Attempt to reconfigure the unit.&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_NULL_POINTER&lt;br /&gt;
| A NULL pointer was detected in one of the arguments. S2ERR_BAD_ARGUMENT should always be the S2ERR.&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_UNIT_DISCONNECTED&lt;br /&gt;
| This error code is a counterpart to &amp;lt;tt&amp;gt;S2WERR_UNIT_OFFLINE&amp;lt;/tt&amp;gt;. It indicates that the associated command could not be executed because the link layer is not connected.&lt;br /&gt;
| 19&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_UNIT_CONNECTED&lt;br /&gt;
| This error code is a counterpart to &amp;lt;tt&amp;gt;S2WERR_UNIT_ONLINE&amp;lt;/tt&amp;gt;. It indicates that the associated command could not be executed because the link layer is already connected.&lt;br /&gt;
| 20&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_INVALID_OPTION&lt;br /&gt;
| This error code indicates that an option, such as passed by the &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt; command, is not acceptable. The option&#039;s value may be out of range or may not match the syntax specifications. To indicate which option that may be, a different mechanism &#039;&#039;&#039;must&#039;&#039;&#039; be used; a simple indication that something was wrong is &#039;&#039;&#039;not sufficient&#039;&#039;&#039;.&lt;br /&gt;
| 21&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_MISSING_OPTION&lt;br /&gt;
| This error code indicates that a mandatory option, such as passed by the &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt; command, is not present. To indicate which option that may be, a different mechanism &#039;&#039;&#039;must&#039;&#039;&#039; be used; a simple indication that something was wrong is &#039;&#039;&#039;not sufficient&#039;&#039;&#039;.&lt;br /&gt;
| 22&lt;br /&gt;
|-&lt;br /&gt;
| S2WERR_AUTHENTICATION_FAILED&lt;br /&gt;
| Some drivers run protocols that require them to authenticate to a server. That process may fail. This wire error code is to indicate this fact.&lt;br /&gt;
| 23&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Standard Commands =&lt;br /&gt;
&lt;br /&gt;
See the &amp;quot;SANA-II network device driver Autodocs&amp;quot; for full details on each of the SANA-II device commands. Extended commands are explained in the sections below.&lt;br /&gt;
&lt;br /&gt;
Many of the Exec device standard commands are no-ops in SANA-II devices, but this may not always be the case. For example, CMD_RESET might someday be used for dynamically reconfiguring hardware. This should present no compatibility problems for properly written drivers.&lt;br /&gt;
&lt;br /&gt;
== Broadcast and Multicast ==&lt;br /&gt;
&lt;br /&gt;
Some hardware supports broadcast and/or multicast. A broadcast is a packet sent to all other machines. A multicast is a packet sent to a set of machines. Drivers for hardware which does not allow broadcast or multicast will return ios2_Error S2ERR_NOT_SUPPORTED as appropriate.&lt;br /&gt;
&lt;br /&gt;
To send a broadcast, use S2_BROADCAST instead of CMD_WRITE. Broadcasts are received just like any other packets (using a CMD_READ for the appropriate packet type).&lt;br /&gt;
&lt;br /&gt;
To send a multicast, use S2_MULTICAST instead of CMD_WRITE. The device keeps a list of addresses that want to receive multicasts. You add a receiver&#039;s address to this list by using S2_ADDMULTICASTADDRESS. The receiver then posts a CMD_READ for the type of packet to be received. Some SANA-II devices which support multicast may have a limit on the number of addresses that can simultaneously wait for packets. Always check for an S2WERR_MULTICAST_FULL error return when adding a multicast address.&lt;br /&gt;
&lt;br /&gt;
Note that when the device adds a multicast address, it is usually added for all users of the device, not just the driver user which called S2_ADDMULTICASTADDRESS. In other words, received multicast packets will fill a read request of the appropriate type regardless of whether the requesting driver user is the same one which added the multicast address.&lt;br /&gt;
&lt;br /&gt;
In general, driver users should not care how received packets were sent (normally or broadcast/multicast), only that it was received. If a driver user really must know, however, it can check for SANA2IOB_BCAST and/or SANA2IOB_MCAST in the ios2_Flags field.&lt;br /&gt;
&lt;br /&gt;
Drivers should keep a count for the number of opens on a multicast address so that they don&#039;t actually remove it until it has been S2_DELMULTICASTADDRESS&#039;d as many times as it has been S2_ADDMULTICASTADDRESS&#039;d.&lt;br /&gt;
&lt;br /&gt;
== Stats ==&lt;br /&gt;
&lt;br /&gt;
There are many statistics which may be very important to someone trying to debug, tune or optimize a protocol stack, as well as to the end user who may need to tune parameters or investigate a problem. Some of these statistics can only be kept by the SANA-II driver, thus there are several required and optional statistics and commands for this purpose.&lt;br /&gt;
&lt;br /&gt;
S2_TRACKTYPE tells the device driver to gather statistics for a particular packet type. S2_UNTRACKTYPE tells it to stop (keeping statistics by type causes the driver to use additional resources). S2_GETTYPESTATS returns any statistics accumulated by the driver for a type being tracked (stats are lost when a type is S2_UNTRACKTYPE&#039;d). Drivers are required to implement the functionality of type tracking. The stats are returned in a struct Sana2PacketTypeStats:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct Sana2PacketTypeStats&lt;br /&gt;
{&lt;br /&gt;
  ULONG PacketsSent;&lt;br /&gt;
  ULONG PacketsReceived;&lt;br /&gt;
  ULONG BytesSent;&lt;br /&gt;
  ULONG BytesReceived;&lt;br /&gt;
  ULONG PacketsDropped;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; PacketsSent&lt;br /&gt;
: Number of packets of a particular type sent.&lt;br /&gt;
; PacketsReceived&lt;br /&gt;
: Number of packets of a particular type that satisfied a read command.&lt;br /&gt;
; BytesSent&lt;br /&gt;
: Number of bytes of data sent in packets of a particular type.&lt;br /&gt;
; BytesReceived&lt;br /&gt;
: Number of bytes of data of a particular packet type that satisfied a read command.&lt;br /&gt;
; PacketsDropped&lt;br /&gt;
: Number of packets of a particular type that were received while there were no pending reads of that packet type.&lt;br /&gt;
&lt;br /&gt;
returns global statistics kept by the driver. Drivers are required to keep all applicable statistics. Since all are applicable to most hardware, most drivers will maintain all statistics. The stats are returned in a struct Sana2DeviceStats:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct Sana2DeviceStats&lt;br /&gt;
{&lt;br /&gt;
  ULONG PacketsReceived;&lt;br /&gt;
  ULONG PacketsSent;&lt;br /&gt;
  ULONG BadData;&lt;br /&gt;
  ULONG Overruns;&lt;br /&gt;
  ULONG UnknownTypesReceived;&lt;br /&gt;
  ULONG Reconfigurations;&lt;br /&gt;
  struct timeval LastStart;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; PacketsReceived&lt;br /&gt;
: Number of packets that this unit has received.&lt;br /&gt;
; PacketsSent&lt;br /&gt;
: Number of packets that this unit has sent.&lt;br /&gt;
; BadData&lt;br /&gt;
: Number of bad packets received (i.e., hardware CRC failed).&lt;br /&gt;
; Overruns&lt;br /&gt;
: Number of packets dropped due to insufficient resources available in the network interface.&lt;br /&gt;
; UnknownTypeReceived&lt;br /&gt;
: Number of packets received that had no pending read command with the appropriate packet type.&lt;br /&gt;
; Reconfigurations&lt;br /&gt;
: Number of network reconfigurations since this unit was last configured.&lt;br /&gt;
; LastStart&lt;br /&gt;
: The time when this unit last went on-line.&lt;br /&gt;
&lt;br /&gt;
returns any special statistics kept by a particular driver. Each new wire type will have a set of documented, required statistics for that wire type and a standard set of optional statistics for that wire type (optional because they might not be available from all hardware). The data returned by S2_GETSPECIALSTATS will require wire-specific interpretation. See &amp;amp;lt;devices/sana2specialstats.h&amp;amp;gt; on page devices&amp;lt;sub&amp;gt;s&amp;lt;/sub&amp;gt;ana2specialstats&amp;lt;sub&amp;gt;p&amp;lt;/sub&amp;gt;age for currently defined special statistics. The statistics are returned in the following structures:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct Sana2SpecialStatRecord&lt;br /&gt;
{&lt;br /&gt;
  ULONG Type;&lt;br /&gt;
  ULONG Count;&lt;br /&gt;
  char * String;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; Type&lt;br /&gt;
: Statistic identifier.&lt;br /&gt;
; Count&lt;br /&gt;
: Statistic itself.&lt;br /&gt;
; String&lt;br /&gt;
: An identifying, null-terminated string for the statistic. Should be plain ASCII with no formatting characters.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct Sana2SpecialStatHeader&lt;br /&gt;
{&lt;br /&gt;
  ULONG RecordCountMax;&lt;br /&gt;
  ULONG RecordCountSupplied;&lt;br /&gt;
  struct Sana2SpecialStatRecord[RecordCountMax];&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; RecordCountMax&lt;br /&gt;
: There is space for this many records into which statistics may be placed.&lt;br /&gt;
; RecordCountSupplied&lt;br /&gt;
: Number of statistic records supplied.&lt;br /&gt;
&lt;br /&gt;
is not, strictly speaking, a statistical function. It is a request to read any packet of a type for which there is no outstanding CMD_READ. S2_READORPHAN might be used in the same manner as many statistics, though, such as to determine what packet types are causing overruns, etc.&lt;br /&gt;
&lt;br /&gt;
== Configuration ==&lt;br /&gt;
&lt;br /&gt;
The device driver needs to configure the hardware before using it. The driver user must know some network hardware parameters (hardware address and MTU, for example) when using it. These commands address those needs.&lt;br /&gt;
&lt;br /&gt;
When a driver user is initialized, it should try to S2_CONFIGINTERFACE even though an interface can only be configured once and someone else may have done it. Before you call S2_CONFIGINTERFACE, first call S2_GETSTATIONADDRESS to determine the factory address (if any). Also provide for user-override of the factory address (that address may be optional and the user may need to override it). When S2_CONFIGINTERFACE returns, check the ios2_SrcAddr for the actual address the hardware has been configured with. This is because some hardware (or serial line standards such as PPP) always dynamically allocates an address at initialization.&lt;br /&gt;
&lt;br /&gt;
Driver users will want to use S2_DEVICEQUERY to determine the MTU and other characteristics of the network. The structure returned from S2_DEVICEQUERY is defined as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct Sana2DeviceQuery&lt;br /&gt;
{&lt;br /&gt;
    /*&lt;br /&gt;
    ** Standard information&lt;br /&gt;
    */&lt;br /&gt;
    ULONG SizeAvailable;    /* bytes available */&lt;br /&gt;
    ULONG SizeSupplied;     /* bytes supplied */&lt;br /&gt;
    LONG  DevQueryFormat;   /* this is type 0 */&lt;br /&gt;
    LONG  DeviceLevel;      /* this document is level 0 */&lt;br /&gt;
&lt;br /&gt;
    /*&lt;br /&gt;
    ** Common information&lt;br /&gt;
    */&lt;br /&gt;
    UWORD AddrFieldSize;    /* address size in bits */&lt;br /&gt;
    ULONG MTU;              /* maximum packet data size */&lt;br /&gt;
    LONG  BPS;              /* line rate (bits/sec) */&lt;br /&gt;
    LONG  HardwareType;     /* what the wire is */&lt;br /&gt;
    ULONG RawMTU;           /* maximum raw packet data size */&lt;br /&gt;
&lt;br /&gt;
    /*&lt;br /&gt;
    ** Format specific information&lt;br /&gt;
    */&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; SizeAvailable&lt;br /&gt;
: Size, in bytes, of the space available in which to place device information. This includes both size fields.&lt;br /&gt;
; SizeSupplied&lt;br /&gt;
: Size, in bytes, of the data supplied.&lt;br /&gt;
; DevQueryFormat&lt;br /&gt;
: The format defined here is format 0.&lt;br /&gt;
; DeviceLevel&lt;br /&gt;
: This spec defines level 0.&lt;br /&gt;
; AddrFieldSize&lt;br /&gt;
: The number of bits in an interface address.&lt;br /&gt;
; MTU&lt;br /&gt;
: Maximum Transmission Unit, the size, in bytes, of the maximum packet size, not including header and trailer information.&lt;br /&gt;
; BPS&lt;br /&gt;
: Best guess at the raw line rate for this network in bits per second.&lt;br /&gt;
&lt;br /&gt;
; HardwareType&lt;br /&gt;
: Specifies the type of network hardware the driver controls.&lt;br /&gt;
&lt;br /&gt;
; RawMTU&lt;br /&gt;
: The &amp;lt;tt&amp;gt;RawMTU&amp;lt;/tt&amp;gt; member is new as of SANA-II Revision 4. Devices which do not know and support this structure member may fill in the &amp;lt;tt&amp;gt;Sana2DeviceQuery&amp;lt;/tt&amp;gt; structure only up to and including the &amp;lt;tt&amp;gt;HardwareType&amp;lt;/tt&amp;gt; member.&lt;br /&gt;
&lt;br /&gt;
: In this context &#039;raw&#039; means the number of bytes that are available for reading and writing when using the &amp;lt;tt&amp;gt;SANA2IOB_RAW&amp;lt;/tt&amp;gt; flag with a &amp;lt;tt&amp;gt;CMD_READ&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;CMD_WRITE&amp;lt;/tt&amp;gt; request on a device that supports these access methods. Currently, software developers can only make assumptions on how many bytes might comprise the &#039;raw&#039; MTU by checking the &amp;lt;tt&amp;gt;Sana2DeviceQuery.HardwareType&amp;lt;/tt&amp;gt; member and hoping that the driver supports raw &amp;lt;tt&amp;gt;CMD_READ&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;CMD_WRITE&amp;lt;/tt&amp;gt; access.&lt;br /&gt;
&lt;br /&gt;
: Devices which know and support the &amp;lt;tt&amp;gt;RawMTU&amp;lt;/tt&amp;gt; member must fill it with a well-defined value. For Amiga Ethernet drivers, that value would be 1514, which is the standard MTU value of 1500 bytes plus the size of the Ethernet frame header, as per RFC894 (six bytes for the destination address, six bytes for the source address and two bytes for the frame type; the eight byte preamble and the terminating four byte CRC value are typically not under the control of the driver). Drivers which do not support raw read or write access must set the &amp;lt;tt&amp;gt;RawMTU&amp;lt;/tt&amp;gt; member to zero.&lt;br /&gt;
&lt;br /&gt;
: If the &amp;lt;tt&amp;gt;RawMTU&amp;lt;/tt&amp;gt; member is not provided, all bets are off and the application software must fall back to making estimates based upon the hardware type and the raw frame types it wishes to read and write. Ultimatively, the driver itself must decide whether it can accept raw read and write commands (or has to reject them with &amp;lt;tt&amp;gt;S2ERR_NOT_SUPPORTED&amp;lt;/tt&amp;gt;) and whether the raw packet size is still covered by the underlying hardware MTU (or must be rejected with &amp;lt;tt&amp;gt;S2ERR_MTU_EXCEEDED&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
: A word of warning: a little testing with various Ethernet hardware drivers has revealed that the A2065 driver &amp;lt;tt&amp;gt;a2065.device&amp;lt;/tt&amp;gt; does not handle the &amp;lt;tt&amp;gt;S2_DEVICEQUERY&amp;lt;/tt&amp;gt; command properly if the &amp;lt;tt&amp;gt;Sana2DeviceQuery&amp;lt;/tt&amp;gt; structure provided is larger than 30 bytes. In other words, the command will fail if the proposed &amp;lt;tt&amp;gt;RawMTU&amp;lt;/tt&amp;gt; member is present in the query data structure to be filled in.&lt;br /&gt;
&lt;br /&gt;
== On-line ==&lt;br /&gt;
&lt;br /&gt;
In order to run hardware tests on an otherwise live system, the S2_OFFLINE command allows the SANA-II device driver to be &amp;quot;turned off&amp;quot; until the tests are complete and an S2_ONLINE is sent to the driver. S2_ONLINE causes the interface to re-configure and re-initialize. Any packets destined for the hardware while the device is off-line will be lost. All pending and new requests to the driver shall be returned with S2ERR_OUTOFSERVICE when a device is off-line.&lt;br /&gt;
&lt;br /&gt;
All driver users must understand that any IO request may return with S2ERR_OUTOFSERVICE because the driver is off-line (any other program may call S2_OFFLINE to make it so). In such an event, the driver will usually want to wait until the unit comes back on-line (for the program which called S2_OFFLINE to call S2_ONLINE). It may do this by calling S2_ONEVENT to wait for S2EVENT_ONLINE. S2_ONEVENT allows the driver user to wait on various events.&lt;br /&gt;
&lt;br /&gt;
A driver must track events, but may not distinguish between some types of events. Drivers return S2_ONEVENT with S2ERR_NOT_SUPPORTED and S2WERR_BAD_EVENT for unsupported events. One error may cause more than one event (see below). Errors which seem to have been caused by a malformed or unusual request should not generally trigger an event.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Event type&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| S2EVENT_ERROR&lt;br /&gt;
| Return when any error occurs.&lt;br /&gt;
|-&lt;br /&gt;
| S2EVENT_TX&lt;br /&gt;
| Return on any transmit error (always an error).&lt;br /&gt;
|-&lt;br /&gt;
| S2EVENT_RX&lt;br /&gt;
| Return on any receive error (always an error).&lt;br /&gt;
|-&lt;br /&gt;
| S2EVENT_ONLINE&lt;br /&gt;
| Return when unit goes on-line or return immediately if unit is already on-line (not an error).&lt;br /&gt;
|-&lt;br /&gt;
| S2EVENT_OFFLINE&lt;br /&gt;
| Return when unit goes off-line or return immediately if unit is already off-line (not an error.)&lt;br /&gt;
|-&lt;br /&gt;
| S2EVENT_BUFF&lt;br /&gt;
| Return on any buffer management function error (always an error).&lt;br /&gt;
|-&lt;br /&gt;
| S2EVENT_HARDWARE&lt;br /&gt;
| Return when any hardware error occurs (always an error, may be a S2EVENT_TX or S2EVENT_RX, too).&lt;br /&gt;
|-&lt;br /&gt;
| S2EVENT_SOFTWARE&lt;br /&gt;
| Return when any software error occurs (always an error, may be a S2EVENT_TX or S2EVENT_RX, too).&lt;br /&gt;
|-&lt;br /&gt;
| S2EVENT_CONFIGCHANGED&lt;br /&gt;
| Return when client-visible configuration information changes (not an error).&lt;br /&gt;
|-&lt;br /&gt;
| S2EVENT_CONNECT&lt;br /&gt;
| Return when the driver has successfully established a link layer connection (not an error).&lt;br /&gt;
|-&lt;br /&gt;
| S2EVENT_DISCONNECT &lt;br /&gt;
| Return when the driver has closed the link layer connection previously established by the S2_CONNECT command (not an error).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== S2EVENT_CONFIGCHANGED ===&lt;br /&gt;
&lt;br /&gt;
For drivers such as those which implement the &amp;lt;tt&amp;gt;S2_GETPEERADDRESS&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2_GETDNSADDRESS&amp;lt;/tt&amp;gt; commands it is vital that such changes can take place and be noticed by the client software. For this purpose a new event type is introduced, to be used with the SANA-II &amp;lt;tt&amp;gt;S2_ONEVENT&amp;lt;/tt&amp;gt; command, using the following definition:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;#define S2EVENT_CONFIGCHANGED (1L&amp;amp;lt;&amp;amp;lt;8)&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This event should be triggered whenever client-visible configuration information changes, as can be queried via the &amp;lt;tt&amp;gt;S2_DEVICEQUERY&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;S2_GETSTATIONADDRESS&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;S2_GETSPECIALSTATS&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;S2_GETGLOBALSTATS&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;S2_GETPEERADDRESS&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2_GETDNSADDRESS&amp;lt;/tt&amp;gt; commands. Here is a short list of what could change:&lt;br /&gt;
&lt;br /&gt;
# S2_DEVICEQUERY: &amp;lt;tt&amp;gt;AddrFieldSize&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;MTU&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;BPS&amp;lt;/tt&amp;gt;&lt;br /&gt;
# S2_GETSTATIONADDRESS: &amp;lt;tt&amp;gt;ios2_SrcAddr&amp;lt;/tt&amp;gt;&lt;br /&gt;
# S2_GETGLOBALSTATS: &amp;lt;tt&amp;gt;Reconfigurations&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;LastStart&amp;lt;/tt&amp;gt;&lt;br /&gt;
# S2_GETPEERADDRESS: &amp;lt;tt&amp;gt;ios2_SrcAddr&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ios2_DstAddr&amp;lt;/tt&amp;gt;&lt;br /&gt;
# S2_GETDNSADDRESS: &amp;lt;tt&amp;gt;ios2_SrcAddr&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ios2_DstAddr&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The purpose of this event &#039;&#039;&#039;is not&#039;&#039;&#039; to post a notification whenever another byte or event counter has changed so that a monitoring program may update its display. The purpose &#039;&#039;&#039;is&#039;&#039;&#039; to convey to the client software that an important device configuration option has changed and that it is supposed to react and adapt to it. For example, a TCP/IP stack may, upon learning that a device&#039;s IP address has changed, rebuild its routing table.&lt;br /&gt;
&lt;br /&gt;
Since the &amp;lt;tt&amp;gt;S2EVENT_CONFIGCHANGED&amp;lt;/tt&amp;gt; event may arrive at any time and does not indicate what exactly has changed, application software should query the information it expects to change during its life time, and keep a copy of it around for later reference. When the &amp;lt;tt&amp;gt;S2EVENT_CONFIGCHANGED&amp;lt;/tt&amp;gt; event arrives, it can compare the contents of the copy against the current state of affairs and act according to the differences it finds.&lt;br /&gt;
&lt;br /&gt;
=== S2EVENT_CONNECT ===&lt;br /&gt;
&lt;br /&gt;
This event is a counterpart to &amp;lt;tt&amp;gt;S2EVENT_ONLINE&amp;lt;/tt&amp;gt;, and is associated with the &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt; command. It has the following semantics:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;#define S2EVENT_CONNECT (1L&amp;amp;lt;&amp;amp;lt;9) /* Driver has opened session */&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The event is to be sent when the driver has successfully established a link layer connection.&lt;br /&gt;
&lt;br /&gt;
=== S2EVENT_DISCONNECT ===&lt;br /&gt;
&lt;br /&gt;
This event is a counterpart to &amp;lt;tt&amp;gt;S2EVENT_OFFLINE&amp;lt;/tt&amp;gt;, and is associated with the &amp;lt;tt&amp;gt;S2_DISCONNECT&amp;lt;/tt&amp;gt; command. It has the following semantics:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;#define S2EVENT_DISCONNECT (1L&amp;amp;lt;&amp;amp;lt;10) /* Driver has closed session */&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The event is to be sent when the driver has closed the link layer connection previously established by the &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt; command.&lt;br /&gt;
&lt;br /&gt;
== S2_ONLINE and S2_OFFLINE ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2_DISCONNECT&amp;lt;/tt&amp;gt; commands are somewhat related to the &amp;lt;tt&amp;gt;S2_ONLINE&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2_OFFLINE&amp;lt;/tt&amp;gt; commands. How this relation works out shall be explained below. Note that the following text assumes that both the &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;S2_DISCONNECT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2_ONLINE&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;S2_OFFLINE&amp;lt;/tt&amp;gt; command pairs are implemented.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt; implies &amp;lt;tt&amp;gt;S2_ONLINE&amp;lt;/tt&amp;gt; and, if successful, may report &amp;lt;tt&amp;gt;S2EVENT_ONLINE&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2EVENT_CONNECT&amp;lt;/tt&amp;gt; events. If the unit is currently disconnected, but still online, only the &amp;lt;tt&amp;gt;S2EVENT_CONNECT&amp;lt;/tt&amp;gt; event shall be sent. Invoking the &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt; command on a driver which is already connected must be rejected with &amp;lt;tt&amp;gt;ios2_Req.io_Error=S2ERR_BAD_STATE&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;ios2_WireError=S2WERR_UNIT_CONNECTED&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;S2_DISCONNECT&amp;lt;/tt&amp;gt; implies &amp;lt;tt&amp;gt;S2_OFFLINE&amp;lt;/tt&amp;gt; and, if successful, may report &amp;lt;tt&amp;gt;S2EVENT_OFFLINE&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2EVENT_DISCONNECT&amp;lt;/tt&amp;gt; events. If the unit is currently connected and offline, then only the &amp;lt;tt&amp;gt;S2EVENT_DISCONNECT&amp;lt;/tt&amp;gt; event shall be sent. Invoking the &amp;lt;tt&amp;gt;S2_DISCONNECT&amp;lt;/tt&amp;gt; command on a driver which is already disconnected must be rejected with &amp;lt;tt&amp;gt;ios2_Req.io_Error=S2ERR_BAD_STATE&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;ios2_WireError=S2WERR_UNIT_DISCONNECTED&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;S2_OFFLINE&amp;lt;/tt&amp;gt; may be used after the &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt; has successfully connected the unit. In this case the driver will release control over the link layer and report the &amp;lt;tt&amp;gt;S2EVENT_OFFLINE&amp;lt;/tt&amp;gt; event. The connection established using the &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt; will, however, persist.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;S2_ONLINE&amp;lt;/tt&amp;gt; may be used after &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt; has successfully connected the unit and the &amp;lt;tt&amp;gt;S2_OFFLINE&amp;lt;/tt&amp;gt; was used. In this case the driver will again try to obtain control over the link layer and report the &amp;lt;tt&amp;gt;S2EVENT_ONLINE&amp;lt;/tt&amp;gt; event if successful.&lt;br /&gt;
&lt;br /&gt;
If the &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt; command was never successfully executed, then the commands &amp;lt;tt&amp;gt;S2_ONLINE&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2_OFFLINE&amp;lt;/tt&amp;gt; must be rejected with &amp;lt;tt&amp;gt;ios2_Req.io_Error=S2ERR_BAD_STATE&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;ios2_WireError=S2WERR_UNIT_DISCONNECTED&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Wireless (IEEE 802.11) ==&lt;br /&gt;
&lt;br /&gt;
Several new commands have been added to the SANA-II API to facilitate use of IEEE 802.11 wireless network devices in client and ad-hoc modes. The new commands are split into two overlapping sets. One set needs to be implemented by drivers for Soft-MAC wireless devices, while the other is implemented for Hard-MAC devices.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Soft-MAC commands&lt;br /&gt;
|-&lt;br /&gt;
| S2_SETOPTIONS&lt;br /&gt;
|-&lt;br /&gt;
| S2_SETKEY&lt;br /&gt;
|-&lt;br /&gt;
| S2_WRITEMGMT&lt;br /&gt;
|-&lt;br /&gt;
| S2_READMGMT&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Hard-MAC commands&lt;br /&gt;
|-&lt;br /&gt;
| S2_SETOPTIONS&lt;br /&gt;
|-&lt;br /&gt;
| S2_SETKEY&lt;br /&gt;
|-&lt;br /&gt;
| S2_GETNETWORKS&lt;br /&gt;
|-&lt;br /&gt;
| S2_GETNETWORKINFO&lt;br /&gt;
|-&lt;br /&gt;
| S2_GETSIGNALQUALITY&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== sana2wireless.h ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
#ifndef DEVICES_SANA2WIRELESS_H&lt;br /&gt;
#define DEVICES_SANA2WIRELESS_H&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;exec/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;utility/tagitem.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/* Constants */&lt;br /&gt;
/* ========= */&lt;br /&gt;
&lt;br /&gt;
/* Tags to get and set information */&lt;br /&gt;
&lt;br /&gt;
#define S2INFO_SSID           (TAG_USER + 0)&lt;br /&gt;
#define S2INFO_BSSID          (TAG_USER + 1)&lt;br /&gt;
#define S2INFO_AuthTypes      (TAG_USER + 2)&lt;br /&gt;
#define S2INFO_AssocID        (TAG_USER + 3)&lt;br /&gt;
#define S2INFO_Encryption     (TAG_USER + 4)&lt;br /&gt;
#define S2INFO_PortType       (TAG_USER + 5)&lt;br /&gt;
#define S2INFO_BeaconInterval (TAG_USER + 6)&lt;br /&gt;
#define S2INFO_Channel        (TAG_USER + 7)&lt;br /&gt;
#define S2INFO_Signal         (TAG_USER + 8)&lt;br /&gt;
#define S2INFO_Noise          (TAG_USER + 9)&lt;br /&gt;
#define S2INFO_Capabilities   (TAG_USER + 10)&lt;br /&gt;
#define S2INFO_InfoElements   (TAG_USER + 11)&lt;br /&gt;
#define S2INFO_WPAInfo        (TAG_USER + 12)&lt;br /&gt;
#define S2INFO_Band           (TAG_USER + 13)&lt;br /&gt;
#define S2INFO_DefaultKeyNo   (TAG_USER + 14)&lt;br /&gt;
&lt;br /&gt;
/* Wireless Commands */&lt;br /&gt;
&lt;br /&gt;
#define S2_GETSIGNALQUALITY 0xc010&lt;br /&gt;
#define S2_GETNETWORKS      0xc011&lt;br /&gt;
#define S2_SETOPTIONS       0xc012&lt;br /&gt;
#define S2_SETKEY           0xc013&lt;br /&gt;
#define S2_GETNETWORKINFO   0xc014&lt;br /&gt;
#define S2_READMGMT         0xc015&lt;br /&gt;
#define S2_WRITEMGMT        0xc016&lt;br /&gt;
#define S2_GETRADIOBANDS    0xc017&lt;br /&gt;
&lt;br /&gt;
/* Encryption types */&lt;br /&gt;
&lt;br /&gt;
#define S2ENC_NONE 0&lt;br /&gt;
#define S2ENC_WEP  1&lt;br /&gt;
#define S2ENC_TKIP 2&lt;br /&gt;
#define S2ENC_CCMP 3&lt;br /&gt;
&lt;br /&gt;
/* Radio modes */&lt;br /&gt;
&lt;br /&gt;
#define S2BAND_A 0&lt;br /&gt;
#define S2BAND_B 1&lt;br /&gt;
#define S2BAND_G 2&lt;br /&gt;
#define S2BAND_N 3&lt;br /&gt;
&lt;br /&gt;
/* Network topologies */&lt;br /&gt;
&lt;br /&gt;
#define S2PORT_MANAGED 7&lt;br /&gt;
#define S2PORT_ADHOC   8&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/* Structures */&lt;br /&gt;
/* ========== */&lt;br /&gt;
&lt;br /&gt;
/* Structure for returning signal quality */&lt;br /&gt;
&lt;br /&gt;
struct Sana2SignalQuality&lt;br /&gt;
{&lt;br /&gt;
   LONG SignalLevel;   /* signal level in dBm */&lt;br /&gt;
   LONG NoiseLevel;   /* noise level in dBm */&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Driver requirements =&lt;br /&gt;
&lt;br /&gt;
This section is an attempt to clarify parts of the specification and to lay down a few rules that every SANA-II driver must follow.&lt;br /&gt;
&lt;br /&gt;
* A driver that does not use a broadcast medium, such as Ethernet, must not implement the &amp;lt;tt&amp;gt;S2_BROADCAST&amp;lt;/tt&amp;gt; command. Likewise, if no multicast mechanism is supported, the &amp;lt;tt&amp;gt;S2_MULTICAST&amp;lt;/tt&amp;gt; must not be implemented either.&lt;br /&gt;
&lt;br /&gt;
* SANA-II standard commands which the driver does not implement must be rejected with the &amp;lt;tt&amp;gt;IOERR_NOCMD&amp;lt;/tt&amp;gt; error code. Commands that are implemented, but which cannot perform the requested services, must be rejected with the &amp;lt;tt&amp;gt;S2ERR_NOT_SUPPORTED&amp;lt;/tt&amp;gt; error code. The difference between the two cases is in when the decision is made whether a command can be handled or not. Which commands should return &amp;lt;tt&amp;gt;IOERR_NOCMD&amp;lt;/tt&amp;gt; is decided upon at the time the driver is designed and implemented. At this stage the implementer knows for sure which capabilities the driver will have and which it will not have. Commands which the driver will never be able to execute will be made to return the &amp;lt;tt&amp;gt;IOERR_NOCMD&amp;lt;/tt&amp;gt; error code. If the decision whether a command can be executed is made only at run time, by evaluating the conditions under which a command can be executed, then the error code &amp;lt;tt&amp;gt;S2ERR_NOT_SUPPORTED&amp;lt;/tt&amp;gt; should be returned in case of failure.&lt;br /&gt;
&lt;br /&gt;
* It must be possible to open the driver with an ordinary &amp;lt;tt&amp;gt;struct IOStdReq&amp;lt;/tt&amp;gt;. This is necessary for the NewStyleDevices query command to work. In the command dispatcher, the driver must verify that all SANA-II commands are invoked with a proper size &amp;lt;tt&amp;gt;struct IOSana2Req&amp;lt;/tt&amp;gt; I/O request. If the I/O request is shorter (as can be verified by looking at the embedded Message&#039;s &amp;lt;tt&amp;gt;mn_Length&amp;lt;/tt&amp;gt; member), the command must be rejected with &amp;lt;tt&amp;gt;ios2_Req.io_Error=IOERR_BADLENGTH&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* A driver must implement the NewStyleDevices &amp;lt;tt&amp;gt;NSCMD_DEVICEQUERY&amp;lt;/tt&amp;gt; command, in conformance with the NSD specification 1.6 or newer. The motivation for this is to have a mechanism available for probing the capabilities of the driver, and the supported command set can provide for vital clues. In this context, the absence of the &amp;lt;tt&amp;gt;S2_BROADCAST&amp;lt;/tt&amp;gt; command would suggest that the driver cannot send or receive broadcast messages.&lt;br /&gt;
&lt;br /&gt;
* A driver that does not allow its station address to be set with the &amp;lt;tt&amp;gt;S2_CONFIGINTERFACE&amp;lt;/tt&amp;gt; command may silently ignore the command (returning it without setting an error condition) and even pretend that it can be configured more than once.&lt;br /&gt;
&lt;br /&gt;
* In response to the &amp;lt;tt&amp;gt;S2_DEVICEQUERY&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;S2_GETSPECIALSTATS&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2_GETGLOBALSTATS&amp;lt;/tt&amp;gt; commands a driver may return information that is not entirely correct if it has to go online before it can provide for the correct data. For example, the maximum transmission unit for PPP is a number in the range of [1..1500] which is negotiated during the protocol configuration process. It is unlikely that numbers greater than 1500 will be used, yet it is still not impossible. Since the actual number will be known only after the driver has configured the protocol, the MTU value returned before the session was opened can differ from the MTU value valid after it has been opened. A driver should therefore attempt to return &#039;safe&#039; defaults in place of information that is unavailable at the time it is queried. The &#039;safe&#039; values shall be set up to allow the driver to work even if the protocol stack is not aware of later changes to those values. Beware of zero-length buffer sizes or time intervals that may cause client software to perform zero-length memory allocations or divisions by zero.&lt;br /&gt;
&lt;br /&gt;
* SANA-II assigns packet type numbers according to the underlying transport media. For example, Ethernet uses packet type 2048 for IP frames. No such packet type definition exists for PPP yet, which is why this standard proposes to assign packet type 31 for IP packets transmitted via PPP. To simplify client software configuration, drivers may treat packet type 2048 as equivalent to the packet number associated with IP frames. This association is permitted only if it does not introduce ambiguity. For example, this association would not be permitted if the driver would receive and transmit IP packets in two different frame types or if the driver already associates packet type 2048 with non-IP packets.&lt;br /&gt;
&lt;br /&gt;
= Driver Installation =&lt;br /&gt;
&lt;br /&gt;
The standard system location for SANA-II network device driver is in a directory called &amp;amp;quot;Networks&amp;amp;quot; which exists in the &amp;amp;quot;DEVS:&amp;amp;quot; directory.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
DEVS:Networks/eth3com.device&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the official location for the drivers. It may be necessary for your install program/script to create this directory if it doesn&#039;t exist in a user&#039;s system.&lt;br /&gt;
&lt;br /&gt;
= Unresolved Issues =&lt;br /&gt;
&lt;br /&gt;
* Unfortunately, it isn&#039;t possible to completely isolate network protocols from the hardware they run on. Hardware types and addressing both remain somewhat hardware-dependent in spite of our efforts. See the &amp;quot;Packet Type&amp;quot; section for an explanation of how packet types are handled and why protocols cannot be isolated from them. See the &amp;quot;Addressing&amp;quot; section for an explanation of how addressing is handled any why protocols cannot be isolated from it.&lt;br /&gt;
&lt;br /&gt;
* Additionally, there are at least two cases where a hardware type has multiple framing methods in use (ethernet/802.3 and arcnet/(Novell) &amp;quot;ARCNET Packet Header Definition Standard&amp;quot;). In both cases, software which must interoperate with other platforms on this hardware may need to be aware of the distinctions and may have to do extra processing in order to use the appropriate frame type. See the sections on &amp;quot;Ethernet Packet Types&amp;quot; and on &amp;quot;ARCNET frames&amp;quot; for more details.&lt;br /&gt;
&lt;br /&gt;
* Protocols like PPP can provide both for IPv4 and IPv6 addresses that should be used by the local client, the peer or any of the domain name servers. While the two addressing families are interoperable, there is a problem in how the driver should report them. Can you assume 128 bit addresses and encapsulate 32 bit addresses in them? If so, how do you make sure that the address format is unambiguous?&lt;br /&gt;
&lt;br /&gt;
* Currently, only the device&#039;s hardware type provides a clue as to what packet type responds to which protocol transported via the link. For Ethernet, IP packets are encapsulated in type 2048 frames, PPP encapsulates IP packets in type 31 frames, Arcnet can use type 240 or 212. Matching a protocol with a frame type is not an easy process which could be handled more elegantly.&lt;br /&gt;
&lt;br /&gt;
* How to extend the &amp;lt;tt&amp;gt;Sana2DeviceQuery&amp;lt;/tt&amp;gt; structure in the future? The current layout separates standard, common and format specific information, but there is no hint as to where which each section starts and where the next begins. Now that there is a proposal to add a new field to the common section, how would you add fields to the format specific section?&lt;br /&gt;
&lt;br /&gt;
= SANA-II network device driver Autodocs =&lt;br /&gt;
&lt;br /&gt;
== AbortIO ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        AbortIO -- Remove an existing device request.&lt;br /&gt;
&lt;br /&gt;
   SYNOPSIS&lt;br /&gt;
        error = AbortIO(Sana2Req)&lt;br /&gt;
        D0              A1&lt;br /&gt;
&lt;br /&gt;
        LONG AbortIO(struct IOSana2Req *);&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This is an exec.library call.&lt;br /&gt;
&lt;br /&gt;
        This function aborts an ioRequest. If the request is active, it may or&lt;br /&gt;
        may not be aborted. If the request is queued it is removed. The&lt;br /&gt;
        request will be returned in the same way as if it had normally&lt;br /&gt;
        completed.  You must WaitIO() after AbortIO() for the request to&lt;br /&gt;
        return.&lt;br /&gt;
&lt;br /&gt;
   INPUTS&lt;br /&gt;
        Sana2Req        - Sana2Req to be aborted.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        error           - Zero if the request was aborted, non-zero otherwise.&lt;br /&gt;
                          io_Error in Sana2Req will be set to IOERR_ABORTED&lt;br /&gt;
                          if it was aborted.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        exec.library/AbortIO(), exec.library/WaitIO()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== CloseDevice ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        CloseDevice -- Close the device.&lt;br /&gt;
&lt;br /&gt;
   SYNOPSIS&lt;br /&gt;
        CloseDevice(Sana2Req)&lt;br /&gt;
                    A1&lt;br /&gt;
&lt;br /&gt;
        void CloseDevice(struct IOSana2Req *);&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This function is called by exec.library CloseDevice().&lt;br /&gt;
&lt;br /&gt;
        This function performs whatever cleanup is required at device closes.&lt;br /&gt;
&lt;br /&gt;
        Note that all IORequests MUST be complete before closing. If any are&lt;br /&gt;
        pending, your program must AbortIO() then WaitIO() each outstanding&lt;br /&gt;
        IORequest to complete them.&lt;br /&gt;
&lt;br /&gt;
   INPUTS&lt;br /&gt;
        Sana2Req        - Pointer to IOSana2Req initialized by OpenDevice().&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        exec.library/CloseDevice(), exec.library/OpenDevice()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== CMD_CLEAR ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        CMD_CLEAR -- Clear internal network interface read buffers.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        There are no device internal buffers, so CMD_CLEAR does not apply to&lt;br /&gt;
        this class of device.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - CMD_CLEAR.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - IOERR_NOCMD.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== CMD_FLUSH ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        CMD_FLUSH -- Clear all queued I/O requests for the SANA-II device.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command aborts all I/O requests in both the read and write&lt;br /&gt;
        request queues of the device.  All pending I/O requests are&lt;br /&gt;
        returned with an error message (IOERR_ABORTED).  CMD_FLUSH does not&lt;br /&gt;
        affect active requests.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - CMD_FLUSH.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - Zero if successful; non-zero otherwise.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== CMD_INVALID ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        CMD_INVALID -- Return with error IOERR_NOCMD.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command causes device driver to reply with an error IOERR_NOCMD&lt;br /&gt;
        as defined in &amp;amp;lt;exec/errors.h&amp;amp;gt; indicating the command is not supported.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - CMD_INVALID.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - IOERR_NOCMD.&lt;br /&gt;
&lt;br /&gt;
   BUGS&lt;br /&gt;
        Not known to be useful.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== CMD_READ ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        CMD_READ -- Get a packet from the network.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        Get the next packet available of the requested packet type. The data&lt;br /&gt;
        copied (via a call to the requestor-provided CopyToBuffer function)&lt;br /&gt;
        into ios2_Data is normally the Data Link Layer packet data only. If&lt;br /&gt;
        bit SANA2IOB_RAW is set in ios2_Flags, then the entire physical frame&lt;br /&gt;
        will be returned.&lt;br /&gt;
&lt;br /&gt;
        Unlike most Exec devices, SANA-II device drivers do not have internal&lt;br /&gt;
        buffers.  If you wish to read data from a SANA-II device you should&lt;br /&gt;
        have multiple CMD_READ requests pending at any given time.  The&lt;br /&gt;
        functions provided by you the requestor will be used for any incoming&lt;br /&gt;
        packets of the type you&#039;ve requested.  If no read requests are&lt;br /&gt;
        outstanding for a type which comes in and no read_orphan requests are&lt;br /&gt;
        outstanding, the packet will be lost.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - CMD_READ&lt;br /&gt;
        ios2_Flags      - Supported flags are:&lt;br /&gt;
                            SANA2IOB_RAW&lt;br /&gt;
                            SANA2IOB_QUICK&lt;br /&gt;
        ios2_PacketType - Packet type desired.&lt;br /&gt;
        ios2_Data       - Abstract data structure to hold packet data.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - Zero if successful; non-zero otherwise.&lt;br /&gt;
        ios2_WireError  - More specific error number.&lt;br /&gt;
        ios2_Flags      - The following flags may be returned:&lt;br /&gt;
                            SANA2IOB_RAW&lt;br /&gt;
                            SANA2IOB_BCAST&lt;br /&gt;
                            SANA2IOB_MCAST&lt;br /&gt;
        ios2_SrcAddr    - Source interface address of packet.&lt;br /&gt;
        ios2_DstAddr    - Destination interface address of packet.&lt;br /&gt;
        ios2_DataLength - Length of packet data.&lt;br /&gt;
        ios2_Data       - Abstract data structure which packet data is&lt;br /&gt;
                          contained in.&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        The driver may not directly examine or modify anything pointed to by&lt;br /&gt;
        ios2_Data.  It *must* use the requester-provided functions to access&lt;br /&gt;
        this data.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        S2_READORPHAN, CMD_WRITE, any_protocol/CopyToBuffer&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== CMD_RESET ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        CMD_RESET -- Reset the network interface to initialized state.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        Currently, SANA-II devices can only be configured once (with&lt;br /&gt;
        CMD_CONFIGINTERFACE) and cannot be re-configured, hence,&lt;br /&gt;
        CMD_RESET does not apply to this class of device.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - CMD_RESET.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - IOERR_NOCMD.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== CMD_START ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        CMD_START -- Restart device operation.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        There is no way for the driver to keep queuing requests without&lt;br /&gt;
        servicing them, so CMD_STOP does not apply to this class of device.&lt;br /&gt;
        S2_OFFLINE and S2_ONLINE do perform a similar function to CMD_STOP&lt;br /&gt;
        and CMD_START&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - CMD_START.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - IOERR_NOCMD.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        S2_ONLINE, S2_OFFLINE&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== CMD_STOP ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        CMD_STOP -- Pause device operation.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        There is no way for the driver to keep queuing requests without&lt;br /&gt;
        servicing them, so CMD_STOP does not apply to this class of device.&lt;br /&gt;
        S2_OFFLINE and S2_ONLINE do perform a similar function to CMD_STOP&lt;br /&gt;
        and CMD_START&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - CMD_STOP.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - IOERR_NOCMD.&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        S2_ONLINE, S2_OFFLINE&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== CMD_UPDATE ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        CMD_UPDATE -- Force packets out to device.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        Since there are no device internal buffers, CMD_UPDATE does not&lt;br /&gt;
        apply to this class of device.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - CMD_UPDATE.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - IOERR_NOCMD.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== CMD_WRITE ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        CMD_WRITE -- Send packet to the network.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command causes the packet to be sent to the specified network&lt;br /&gt;
        interface. Normally, appropriate packet header and trailer information&lt;br /&gt;
        will be added to the packet data when it is sent.  If bit SANA2IOB_RAW&lt;br /&gt;
        is set in io_Flags, then the ios2_Data is assumed to contain an entire&lt;br /&gt;
        physical frame and will be sent (copied to the wire via&lt;br /&gt;
        CopyFromBuffer() unmodified.&lt;br /&gt;
&lt;br /&gt;
        Note that the device should not check to see if the destination&lt;br /&gt;
        address is on the local hardware.  Network protocols should realize&lt;br /&gt;
        that the packet has a local destination long before it gets to a&lt;br /&gt;
        SANA-II driver.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - CMD_WRITE.&lt;br /&gt;
        ios2_Flags      - Supported flags are:&lt;br /&gt;
                            SANA2IOB_RAW&lt;br /&gt;
                            SANA2IOB_QUICK&lt;br /&gt;
        ios2_PacketType - Packet type to send.&lt;br /&gt;
        ios2_DstAddr    - Destination interface address for this packet.&lt;br /&gt;
        ios2_DataLength - Length of the Data to be sent.&lt;br /&gt;
        ios2_Data       - Abstract data structure which packet data is&lt;br /&gt;
                          contained in.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - Zero if successful; non-zero otherwise.&lt;br /&gt;
        ios2_WireError  - More specific error number.&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        The driver may not directly examine or modify anything pointed to by&lt;br /&gt;
        ios2_Data.  It *must* use the requester-provided functions to access&lt;br /&gt;
        this data.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        CMD_READ, S2_BROADCAST, S2_MULTICAST, any_protocol/CopyFromBuffer&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== OpenDevice ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        Open -- Request an opening of the network device.&lt;br /&gt;
&lt;br /&gt;
   SYNOPSIS&lt;br /&gt;
        error = OpenDevice(unit, IOSana2Req, flags)&lt;br /&gt;
        D0                 D0    A1          D1&lt;br /&gt;
&lt;br /&gt;
        BYTE OpenDevice(ULONG, struct IOSana2Req *, ULONG);&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This function is called by exec.library OpenDevice().&lt;br /&gt;
&lt;br /&gt;
        This function performs whatever initialization is required per&lt;br /&gt;
        device open and initializes the Sana2Req for use by the&lt;br /&gt;
        device.&lt;br /&gt;
&lt;br /&gt;
   INPUTS&lt;br /&gt;
        unit            - Device unit to open.&lt;br /&gt;
        Sana2Req        - Pointer to IOSana2Req structure to be initialized by&lt;br /&gt;
                          the sana2.device.&lt;br /&gt;
        flags           - Supported flags are:&lt;br /&gt;
                                SANA2OPB_MINE&lt;br /&gt;
                                SANA2OPB_PROM&lt;br /&gt;
        ios2_BufferManagement   - A pointer to a tag list containing&lt;br /&gt;
                                  pointers to buffer management functions.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        error           - same as io_Error&lt;br /&gt;
        io_Error        - Zero if successful; non-zero otherwise.&lt;br /&gt;
        io_Device       - A pointer to whatever device will handle the calls&lt;br /&gt;
                          for this unit.  This pointer may be different&lt;br /&gt;
                          depending on what unit is requested.&lt;br /&gt;
        ios2_BufferManagement   - A pointer to device internal information&lt;br /&gt;
                                  used to call buffer management functions.&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        A SANA-II device must reject all open requests with a request&lt;br /&gt;
        structure that is too short, e.g. an IOStdReq. A simple check of the&lt;br /&gt;
        mn_Length field in the Message part of the request is needed to make&lt;br /&gt;
        sure that a device does not dereference invalid data due to a wrong&lt;br /&gt;
        device configuration.&lt;br /&gt;
&lt;br /&gt;
        A SANA-II device may open if no buffer management tags are provided to&lt;br /&gt;
        make the configuration process and obtaining statistics easier. Buffer&lt;br /&gt;
        management tags with a NULL value must be treated as not specified.&lt;br /&gt;
        The device shall fail requests gracefully depending on the missing&lt;br /&gt;
        tags in this case. Any malfunction is not acceptable.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        exec.library/OpenDevice(), exec.library/CloseDevice()&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_ADDMULTICASTADDRESS ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_ADDMULTICASTADDRESS -- Enable an interface multicast address.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command causes the device driver to enable multicast packet&lt;br /&gt;
        reception for the requested address.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - S2_ADDMULTICASTADDRESS.&lt;br /&gt;
        ios2_SrcAddr    - Multicast address to enable.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - Zero if successful; non-zero otherwise.&lt;br /&gt;
        ios2_WireError  - More specific error number.&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        Multicast addresses are added globally -- anyone using the device&lt;br /&gt;
        may receive packets as a result of any multicast address which has&lt;br /&gt;
        been added for the device.&lt;br /&gt;
&lt;br /&gt;
        Since multicast addresses are not &amp;amp;quot;bound&amp;amp;quot; to a particular packet type,&lt;br /&gt;
        each enabled multicast address has an &amp;amp;quot;enabled&amp;amp;quot; count associated with&lt;br /&gt;
        it so that if two protocols add the same multicast address and later&lt;br /&gt;
        one removes it, it is still enabled until the second removes it.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        S2_MULTICAST, S2_DELMULTICASTADDRESS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_BROADCAST ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_BROADCAST -- Broadcast a packet on network.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command works the same as CMD_WRITE except that it also performs&lt;br /&gt;
        whatever special processing of the packet is required to do a&lt;br /&gt;
        broadcast send. The actual broadcast mechanism is neccessarily&lt;br /&gt;
        network/interface/device specific.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - S2_BROADCAST.&lt;br /&gt;
        ios2_Flags      - Supported flags are:&lt;br /&gt;
                                SANA2IOB_RAW&lt;br /&gt;
                                SANA2IOB_QUICK&lt;br /&gt;
        ios2_PacketType - Packet type to send.&lt;br /&gt;
        ios2_DataLength - Length of the Data to be sent.&lt;br /&gt;
        ios2_Data       - Abstract data structure which packet data is&lt;br /&gt;
                          contained in.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_DstAddr    - The contents of this field are to be&lt;br /&gt;
                          considered trash upon return of the IOReq.&lt;br /&gt;
        ios2_Error      - Zero if successful; non-zero otherwise.&lt;br /&gt;
                          This command can fail for many reasons and&lt;br /&gt;
                          is not supported by all networks and/or&lt;br /&gt;
                          network interfaces.&lt;br /&gt;
        ios2_WireError  - More specific error number.&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        The DstAddr field may be trashed by the driver because this function&lt;br /&gt;
        may be implemented by filling DstAddr with a broadcast address and&lt;br /&gt;
        internally calling CMD_WRITE.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        CMD_WRITE, S2_MULTICAST&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_CONFIGINTERFACE ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_CONFIGINTERFACE -- Configure the network interface.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command causes the device driver to initialize the interface&lt;br /&gt;
        hardware and to set the network interface address to the address in&lt;br /&gt;
        ios2_SrcAddr. This command can only be executed once and, if&lt;br /&gt;
        successful, will leave the driver and network interface fully&lt;br /&gt;
        operational and the network interface in ios2_SrcAddr.&lt;br /&gt;
&lt;br /&gt;
        To set the interface address to the factory address, the network&lt;br /&gt;
        management software must use GetStationAddress first and then call&lt;br /&gt;
        ConfigInterface with the result. If there is no factory address then&lt;br /&gt;
        the network software must pick an address to use.&lt;br /&gt;
&lt;br /&gt;
        Until this command is executed the device will not listen for any&lt;br /&gt;
        packets on the hardware.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - S2_CONFIGINTERFACE.&lt;br /&gt;
        ios2_Flags      - Supported flags are:&lt;br /&gt;
                                SANA2IOB_QUICK&lt;br /&gt;
        ios2_SrcAddr    - Address for this interface.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - Zero if successful; non-zero otherwise.&lt;br /&gt;
        ios2_WireError  - More specific error number.&lt;br /&gt;
        ios2_SrcAddr    - Address of this interface as configured.&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        Some networks have the interfaces choose a currently unused interface&lt;br /&gt;
        address each time the interface is initialized. The caller must check&lt;br /&gt;
        ios2_SrcAddr for the actual interface address after configuring the&lt;br /&gt;
        interface.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        S2_GETSTATIONADDRESS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_CONNECT ==&lt;br /&gt;
&lt;br /&gt;
The driver model specified by the SANA-II standard really only covers networking hardware well. Software-only drivers, such as for dial-up networking, are, well, somehow mentioned in the standard, but they don&#039;t receive much attention. In particular, this means that a networking driver is assumed to be practically always attached to its link layer and no provisions exist to specify what kind of link layer that might be and how it might be accessed. This small oversight can probably be explained by the fact that at the time the SANA-II standard was adopted, dial-up networking had not yet gained the prominence it has today.&lt;br /&gt;
&lt;br /&gt;
To bridge this gap, I propose a new command which will make a driver connect to its link layer and go online, which uses the following data structure:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct Sana2Connection&lt;br /&gt;
{&lt;br /&gt;
   ULONG          s2c_Size;&lt;br /&gt;
   struct MinList s2c_Options;&lt;br /&gt;
   struct Hook    s2c_ErrorHook;&lt;br /&gt;
   struct Hook    s2c_ConnectHook;&lt;br /&gt;
   struct Hook    s2c_DisconnectHook;&lt;br /&gt;
   STRPTR         s2c_Login;&lt;br /&gt;
   STRPTR         s2c_Password;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The individual structure members have the following purposes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2c_Size&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The size of the entire data structure is stored here. This value &#039;&#039;&#039;must&#039;&#039;&#039; be &amp;amp;gt;= 84. Smaller values &#039;&#039;&#039;must&#039;&#039;&#039; be rejected with &amp;lt;tt&amp;gt;ios2_Req.io_Error&amp;lt;/tt&amp;gt;=&amp;lt;tt&amp;gt;IOERR_BADLENGTH&amp;lt;/tt&amp;gt;. The purpose of &amp;lt;tt&amp;gt;s2c_Size&amp;lt;/tt&amp;gt; is to allow for future expansion during which the structure may grow in size.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2c_Options&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This list contains options, to be used during the connection process. Each node has the following format:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct Sana2ConnectionOption&lt;br /&gt;
{&lt;br /&gt;
   struct MinNode s2co_MinNode;&lt;br /&gt;
   STRPTR         s2co_Name;&lt;br /&gt;
   STRPTR         s2co_Value;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;s2co_Name&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;s2co_Value&amp;lt;/tt&amp;gt; entries point to &amp;lt;tt&amp;gt;NUL&amp;lt;/tt&amp;gt;-terminated strings, which contain the name and the value of a parameter. &#039;&#039;Note that for numeric values, the respective number will be encoded in a text string.&#039;&#039; A number of parameters are reserved, which are [[#s2c_options|listed later]] in this text.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2c_ErrorHook&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This hook is called whenever an error message is to be reported during the connection/disconnection process. The hook function is invoked using the following parameters:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;error_hook_func(hook,reserved,message);&lt;br /&gt;
&lt;br /&gt;
VOID error_hook_func(struct Hook *hook,APTR reserved,&lt;br /&gt;
                     STRPTR message);&amp;lt;/pre&amp;gt;&lt;br /&gt;
The &amp;lt;tt&amp;gt;reserved&amp;lt;/tt&amp;gt; parameter &#039;&#039;&#039;must&#039;&#039;&#039; be &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt;. The &amp;lt;tt&amp;gt;message&amp;lt;/tt&amp;gt; parameter points to a &amp;lt;tt&amp;gt;NUL&amp;lt;/tt&amp;gt;-terminated string. It &#039;&#039;&#039;must not&#039;&#039;&#039; be &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Because the hook function may have to allocate memory, it &#039;&#039;&#039;must not&#039;&#039;&#039; be called from interrupt code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2c_ConnectHook&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This hook is called when the link level device has been set up, but further initializations are necessary, such as telling a modem to dial out. The hook function is invoked with the following parameters:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
success = connect_hook_func(hook,reserved,s2cm);&lt;br /&gt;
&lt;br /&gt;
BOOL connect_hook_func(struct Hook *hook,APTR reserved,&lt;br /&gt;
                       struct Sana2ConnectionMessage *s2cm);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;reserved&amp;lt;/tt&amp;gt; parameter &#039;&#039;&#039;must&#039;&#039;&#039; be &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt;. The &amp;lt;tt&amp;gt;s2cm&amp;lt;/tt&amp;gt; parameter points to a data structure, as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct Sana2ConnectionMessage&lt;br /&gt;
{&lt;br /&gt;
   ULONG                    s2cm_Size;&lt;br /&gt;
   struct Sana2Connection * s2cm_Connection;&lt;br /&gt;
   struct IORequest *       s2cm_Request[2];&lt;br /&gt;
   LONG                     s2cm_RequestType;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this structure, the members have the following purposes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2cm_Size&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The size of this data structure; it &#039;&#039;&#039;must&#039;&#039;&#039; be at least 20 bytes in size. The purpose of &amp;lt;tt&amp;gt;s2cm_Size&amp;lt;/tt&amp;gt; is to allow for future expansion, which may cause the size of this structure to grow.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2cm_Connection&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This points back to the &amp;lt;tt&amp;gt;Sana2Connection&amp;lt;/tt&amp;gt; structure which the hook that was invoked with the &amp;lt;tt&amp;gt;Sana2ConnectionMessage&amp;lt;/tt&amp;gt; is embedded in.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2cm_Request&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here you will find two I/O requests which can be used for reading and writing data to the link layer. These pointers &#039;&#039;&#039;must not&#039;&#039;&#039; be &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; and they &#039;&#039;&#039;must&#039;&#039;&#039; refer to different I/O requests, it is not permitted to pass the same request twice.&lt;br /&gt;
&lt;br /&gt;
The dialer can use these requests for communicating with the modem, but it is also permitted to clone these requests by creating new I/O requests of the same size, copying the original contents and filling in different reply ports.&lt;br /&gt;
&lt;br /&gt;
There is a danger in that the hook code may not receive the right kind of I/O request, which is why the &amp;lt;tt&amp;gt;s2cm_RequestType&amp;lt;/tt&amp;gt; field identifies the kind of device the requests were created for.&lt;br /&gt;
&lt;br /&gt;
When the hook function returns, it &#039;&#039;&#039;must&#039;&#039;&#039; make sure that none of the I/O requests are still pending, i.e. asynchronous I/O &#039;&#039;&#039;must&#039;&#039;&#039; have been stopped.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2cm_RequestType&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This identifies the type of device the I/O requests passed in &amp;lt;tt&amp;gt;s2cm_Request&amp;lt;/tt&amp;gt; were created for. Possible values for this entry come from the New Style Device specification, e.g. &amp;lt;tt&amp;gt;NSDEVTYPE_SERIAL&amp;lt;/tt&amp;gt; for a &amp;lt;tt&amp;gt;serial.device&amp;lt;/tt&amp;gt;-like device or &amp;lt;tt&amp;gt;NSDEVTYPE_SANA2&amp;lt;/tt&amp;gt; for a networking driver.&lt;br /&gt;
&lt;br /&gt;
The hook function &#039;&#039;&#039;must&#039;&#039;&#039; return &amp;lt;tt&amp;gt;TRUE&amp;lt;/tt&amp;gt; if the connection could be established, and &amp;lt;tt&amp;gt;FALSE&amp;lt;/tt&amp;gt; otherwise. Note that it is &#039;&#039;not&#039;&#039; sufficient to just return &amp;lt;tt&amp;gt;FALSE&amp;lt;/tt&amp;gt; in case of failure. Your code &#039;&#039;&#039;must&#039;&#039;&#039; have called the &amp;lt;tt&amp;gt;s2c_ErrorHook&amp;lt;/tt&amp;gt; with an explanation why things went wrong first.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2c_DisconnectHook&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This hook is called by &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt; when the connection could not be established (the &amp;lt;tt&amp;gt;s2c_ConnectHook&amp;lt;/tt&amp;gt; returned &amp;lt;tt&amp;gt;FALSE&amp;lt;/tt&amp;gt;), or by &amp;lt;tt&amp;gt;S2_DISCONNECT&amp;lt;/tt&amp;gt;, shortly before the link level device is to be closed. The hook function is invoked with the following parameters:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
disconnect_hook_func(hook,reserved,s2cm);&lt;br /&gt;
&lt;br /&gt;
VOID disconnect_hook_func(struct Hook *hook,APTR reserved,&lt;br /&gt;
                          struct Sana2ConnectionMessage *s2cm);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;reserved&amp;lt;/tt&amp;gt; parameter &#039;&#039;&#039;must&#039;&#039;&#039; be &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt;. The &amp;lt;tt&amp;gt;s2cm&amp;lt;/tt&amp;gt; parameter points to a data structure, as was described for the &amp;lt;tt&amp;gt;s2c_ConnectHook&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2c_Login&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2c_Password&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The purpose of these entries is to transport the authentication information the protocol may require. These entries are either &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; or contain pointers to &amp;lt;tt&amp;gt;NUL&amp;lt;/tt&amp;gt;-terminated strings. If &amp;lt;tt&amp;gt;s2c_Login&amp;lt;/tt&amp;gt; is &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt;, then both login and password &#039;&#039;&#039;must&#039;&#039;&#039; be assumed to be empty. If &amp;lt;tt&amp;gt;s2c_Login&amp;lt;/tt&amp;gt; is not &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;s2c_Password&amp;lt;/tt&amp;gt; is &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt;, then the password &#039;&#039;&#039;must&#039;&#039;&#039; be assumed to be empty.&lt;br /&gt;
&lt;br /&gt;
The list of options in &amp;lt;tt&amp;gt;s2c_Options&amp;lt;/tt&amp;gt; supplies the necessary information on how the driver is to connect to the link layer. Each node contains an option, which bears a name and contains a value. This pair is what I call a &#039;&#039;parameter&#039;&#039;. A number of parameter names are reserved, as will be listed below:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp&amp;lt;/tt&amp;gt;.async.device&lt;br /&gt;
&lt;br /&gt;
Name of device driver to use for asynchronous PPP.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;serial.device&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp&amp;lt;/tt&amp;gt;.async.unit&lt;br /&gt;
&lt;br /&gt;
Device unit number to use for asynchronous PPP.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp&amp;lt;/tt&amp;gt;.async.speed&lt;br /&gt;
&lt;br /&gt;
Transmission speed to use for asynchronous PPP in bits per second.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;115200&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.async.buffersize&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Receive buffer size for asynchronous PPP.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;50000&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.async.checkcarrier&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whether the carrier signal of the link layer should be tested or not. This can be either 0 (do not test) or 1 (test the carrier signal).&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.async.rtscts&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whether or not hardware handshaking should be used by the link layer. This can be either &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; (off) or &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; (on).&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.async.shared&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whether or not the link layer device should be opened in shared mode. This can be either &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; (off) or &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; (on).&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.async.nullmodem&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whether or not the link layer is a direct connection, such as a nullmodem. This can be either &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; (off) or &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; (on).&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.async.eof&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whether or not the underlying serial device driver&#039;s &#039;EOF mode&#039; should be enabled. This can be either &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; (off) or &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; (on).&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.async.readrequests&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Number of read requests to be used for asynchronous PPP.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;16&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.async.writerequests&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Number of write requests to be used for asynchronous PPP.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;16&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.async.accm&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Asynchronous control character map, expressed as a hexadecimal value.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;$000A0000&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.async.pfc&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whether or not protocol field compression should be used. This can be either &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; (off) or &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; (on).&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.async.aacfc&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whether or not address and control field compression should be used. This can be either &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; (off) or &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; (on).&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.async.vjhc&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whether or not Van Jacobson header compression should be used. This can be either &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; (off) or &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; (on).&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.async.ignorefcs&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whether or not frame check sequences should be ignored upon reception. This can be either &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; (off) or &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; (on).&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.async.initialize&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The modem initialization command, with embedded control sequences, if possible.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;AT\r&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.async.dial&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The modem dial command, with embedded control sequences, if possible.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;ATD12345\r&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.async.dialtimeout&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The dial timeout, i.e. the number of seconds to wait after the dial command has been sent for the modem to establish a connection.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;60&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.async.hangup&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The modem hangup command, with embedded control sequences, if possible.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;ATH0\r&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.idletimeout&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Number of seconds the local host may remain idle, i.e. send no data to the peer, before a watchdog timeout elapses and proceeds to verify that the line is still operational.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;30&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.localaddress&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The IP address to assign to the local host, as part of the PPP negotiation process. This must be given in dotted decimal notation (RFC1700).&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;1.2.3.4&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.remoteaddress&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The IP address to assume for the peer, as part of the PPP negotiation process. This must be given in dotted decimal notation (RFC1700).&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;1.2.3.4&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.dns1address&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The IP address to be used by the primary domain name server, as part of the PPP negotiation process. This must be given in dotted decimal notation (RFC1700).&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;1.2.3.4&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.dns2address&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The IP address to be used by the secondary domain name server, as part of the PPP negotiation process. This must be given in dotted decimal notation (RFC1700).&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;1.2.3.4&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.maxfail&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The maximum number of negative configuration acknowledgements to be sent before the PPP negotiation process switches to reject those options.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;5&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.maxterm&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The maximum number of termination requests to be sent before the respective PPP network or link protocol gives up.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;2&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.maxconfig&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The maximum number of configuration requests to be sent before the respective PPP network or link protocol gives up.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;10&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.timeout&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The number of seconds that have to pass before the respective PPP network or link protocol will retry to do whatever didn&#039;t work during the last attempt.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;3&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.mtu&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The maximum transmission unit to use.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;1500&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.peeridletimeout&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Number of seconds the peer may remain idle, i.e. send no data to the local host, before a watchdog timeout elapses and proceeds to verify that the line is still operational.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;30&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.rejectpap&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whether or not the Password Authentication Protocol should be accepted, if offered by the peer. This can be either &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; (accept) or &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; (reject).&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.sendid&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A flag which controls whether the local host should send LCP identification packets or not. This can be either &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; (off) or &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; (on).&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.pap.timeout&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The Password Authentication Protocol requires that the server answers to the client&#039;s request to log in. The server may be unable to respond immediately, which means that the client will have to repeat its request. A short delay should separate each request sent, such as three seconds.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;3&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.pap.retry&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the client does not manage to authenticate with the server immediately, it may resend the authentication request several times. But the attempts have to stop eventually, such as after having resent the message ten times.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;10&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.dummyremoteaddress&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whether or not the PPP driver should make up an IP address if the peer refuses to state its own IP address.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;logfile&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The name of a log file to create. If the file already exists, then new data should be appended to it.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;t:logfile&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;logoptions&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A list of options which control what exactly should be logged.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.ethernet.device&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Name of device driver to use for PPPoE (PPP over Ethernet).&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;a2065.device&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.ethernet.unit&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Device unit number to use for PPPoE.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.ethernet.raw&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whether or not raw link layer frames should be constructed for transmission or not. This can be either &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; (off) or &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; (on).&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.ethernet.bypass&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Whether or not the IP packet transmission and reception should bypass several copying steps. This can be either &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; (off) or &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; (on).&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.ethernet.readpackets&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The number of read requests to queue for the link layer.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;16&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.ethernet.writepackets&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The number of write requests to queue for the link layer.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;16&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.ethernet.service&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The name of the PPPoE service to request.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;?&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.ethernet.ac&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The name of the PPPoE access concentrator to request.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;?&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;ppp.ethernet.connecttimeout&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The number of seconds to wait for the PPPoE server to allow a session to be opened.&lt;br /&gt;
&lt;br /&gt;
Example: &amp;lt;tt&amp;gt;3&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
While this list of parameters may suggest that the command described above can be used solely with the PPP protocol, do not let that put you off. This list is merely the starting point, but it is not set in stone that it cannot be extended.&lt;br /&gt;
&lt;br /&gt;
The names of the parameters are not case sensitive. As the names suggest, the name space itself is hierarchic in construction, i.e. everything related to the PPP protocol bears a name starting with the letters &#039;ppp&#039; with the dot &#039;.&#039; separating the individual items. By this rule, ppp.async refers to options that concern asynchronous PPP and ppp.ethernet to options that concern PPP over Ethernet wire.&lt;br /&gt;
&lt;br /&gt;
To add your own parameter, register it with the maintainer of the SANA-II standard or prefix its name with the letters &#039;x-&#039;. For example, to use your own kind of &#039;ppp.ethernet.connecttimeout&#039; parameter, change the name of the last component like this: ppp.ethernet.x-connecttimeout. No officially-registered parameter will ever begin with the prefix &#039;x-&#039;.&lt;br /&gt;
&lt;br /&gt;
The command should work as follows:&lt;br /&gt;
&lt;br /&gt;
# The client must set up the &amp;lt;tt&amp;gt;Sana2Connection&amp;lt;/tt&amp;gt; data structure, initialize the &amp;lt;tt&amp;gt;s2c_Size&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;s2c_Options&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;s2c_ErrorHook&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;s2c_ConnectHook&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;s2c_DisconnectHook&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;s2c_Login&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;s2c_Password&amp;lt;/tt&amp;gt; fields.&lt;br /&gt;
# The connection options must be filled in, which means that nodes containing the respective information must be stored in the &amp;lt;tt&amp;gt;s2c_Options&amp;lt;/tt&amp;gt; list. The client must make sure that the syntax of the parameters conforms to the specifications described above.&lt;br /&gt;
# A pointer to the &amp;lt;tt&amp;gt;Sana2Connection&amp;lt;/tt&amp;gt; data structure is placed in the &amp;lt;tt&amp;gt;ios2_Data&amp;lt;/tt&amp;gt; member of an &amp;lt;tt&amp;gt;IOSana2Req&amp;lt;/tt&amp;gt;, the command is set to &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt; and the request is sent via &amp;lt;tt&amp;gt;DoIO()&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;SendIO()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
# The driver receives the request and begins to examine the contents of the &amp;lt;tt&amp;gt;s2c_Options&amp;lt;/tt&amp;gt; list, as provided in the data structure pointed to by the &amp;lt;tt&amp;gt;ios2_Data&amp;lt;/tt&amp;gt; member of the request. Unknown options are ignored, options whose values do not conform to the syntax specification are rejected; this is done by calling the &amp;lt;tt&amp;gt;s2c_ErrorHook&amp;lt;/tt&amp;gt; with an error message referring to the option in question and by returning the &amp;lt;tt&amp;gt;IOSana2Req&amp;lt;/tt&amp;gt; with an error code of &amp;lt;tt&amp;gt;S2ERR_BAD_ARGUMENT&amp;lt;/tt&amp;gt; and wire error code of &amp;lt;tt&amp;gt;S2WERR_INVALID_OPTION&amp;lt;/tt&amp;gt;.&lt;br /&gt;
# If the options are all in good order, the driver proceeds to verify that all mandatory options are provided. If this is not the case, the &amp;lt;tt&amp;gt;s2c_ErrorHook&amp;lt;/tt&amp;gt; is called with an error message referring to the option in question and the &amp;lt;tt&amp;gt;IOSana2Req&amp;lt;/tt&amp;gt; is returned with an error code of &amp;lt;tt&amp;gt;S2ERR_BAD_ARGUMENT&amp;lt;/tt&amp;gt; and wire error code of &amp;lt;tt&amp;gt;S2WERR_MISSING_OPTION&amp;lt;/tt&amp;gt;.&lt;br /&gt;
# The driver proceeds to do its local initialization, which involves opening the link layer device, etc. If this initialization fails, the &amp;lt;tt&amp;gt;s2c_ErrorHook&amp;lt;/tt&amp;gt; is called with an error message referring to the problem and the &amp;lt;tt&amp;gt;IOSana2Req&amp;lt;/tt&amp;gt; is returned with an appropriate error code.&lt;br /&gt;
# When the initialization has finished, the driver may invoke the &amp;lt;tt&amp;gt;s2c_ConnectHook&amp;lt;/tt&amp;gt; callback. Some drivers may require this, such as asynchronous PPP, some may not, such as PPPoE. The purpose of the hook function is to give the client a chance to perform modem initializations and connect to the peer. If the &amp;lt;tt&amp;gt;s2c_ConnectHook&amp;lt;/tt&amp;gt; cannot perform its duties, it has to invoke the &amp;lt;tt&amp;gt;s2c_ErrorHook&amp;lt;/tt&amp;gt; with an error message and eventually return &amp;lt;tt&amp;gt;FALSE&amp;lt;/tt&amp;gt;. If &amp;lt;tt&amp;gt;FALSE&amp;lt;/tt&amp;gt; is returned, the driver must invoke the &amp;lt;tt&amp;gt;s2c_DisconnectHook&amp;lt;/tt&amp;gt;, reverse any initializations it had made and eventually returned the &amp;lt;tt&amp;gt;IOSana2Req&amp;lt;/tt&amp;gt; with an appropriate error code. If the &amp;lt;tt&amp;gt;s2c_ConnectHook&amp;lt;/tt&amp;gt; returned &amp;lt;tt&amp;gt;TRUE&amp;lt;/tt&amp;gt;, then the driver must proceed with the actions that require that the link layer is operational. A protocol negotiation may follow, which, if successful, will make the driver return the &amp;lt;tt&amp;gt;IOSana2Req&amp;lt;/tt&amp;gt; with an error code of zero, indicating success. If successful, the SANA-II events &amp;lt;tt&amp;gt;S2EVENT_CONNECT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2EVENT_ONLINE&amp;lt;/tt&amp;gt; must be sent.&lt;br /&gt;
# The command will eventually return, but the client &#039;&#039;&#039;must not&#039;&#039;&#039; release the memory allocated for the &amp;lt;tt&amp;gt;Sana2Connection&amp;lt;/tt&amp;gt; structure and the option nodes in the &amp;lt;tt&amp;gt;s2c_Options&amp;lt;/tt&amp;gt; list. This is because the driver may have to invoke the &amp;lt;tt&amp;gt;s2c_DisconnectHook&amp;lt;/tt&amp;gt; hook due to the connection shutting down on its own accord.&lt;br /&gt;
&lt;br /&gt;
The connect and disconnect hook functions &#039;&#039;&#039;must not&#039;&#039;&#039; be called from interrupt code. For each hook only a &amp;lt;tt&amp;gt;Task&amp;lt;/tt&amp;gt; calling context of unknown priority must be assumed. Also, stack space is provided only to call &amp;lt;tt&amp;gt;exec.library&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;utility.library&amp;lt;/tt&amp;gt; functions. The callback shall not place excessive data on the stack. Stack space should be considered limited.&lt;br /&gt;
&lt;br /&gt;
I propose a command with the following semantics:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_CONNECT -- Establish a link layer connection and go&lt;br /&gt;
            online.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command is for use by networking devices which require&lt;br /&gt;
        a special link layer device to transmit their data, such as&lt;br /&gt;
        an asynchronous serial line and need to know about the&lt;br /&gt;
        configuration parameters necessary to open the connection.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command          - S2_CONNECT&lt;br /&gt;
        ios2_Data             - Pointer to Sana2Connection structure&lt;br /&gt;
        ios2_BufferManagement - Magic cookie as returned when opening the&lt;br /&gt;
                                driver with a struct IOSana2Req&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Req.io_Error - Zero if successful; non-zero otherwise&lt;br /&gt;
        ios2_WireError    - More specific error number&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        If successful, this command implies S2_ONLINE, i.e. the&lt;br /&gt;
        link layer is allocated and used by the driver.&lt;br /&gt;
&lt;br /&gt;
        The contents of the Sana2Connection structure must be valid&lt;br /&gt;
        until the connection is eventually shut down. The driver will&lt;br /&gt;
        need to cache it, so it must not be deallocated or otherwise&lt;br /&gt;
        modified.&lt;br /&gt;
&lt;br /&gt;
        Note that S2_ONLINE does not necessarily imply S2_CONNECT, if&lt;br /&gt;
        the S2_CONNECT command is listed as supported by the driver via&lt;br /&gt;
        NSCMD_DEVICEQUERY. If S2_CONNECT is not listed as supported,&lt;br /&gt;
        S2_ONLINE obviously implies connect functionality.&lt;br /&gt;
&lt;br /&gt;
        S2_CONNECT/S2_DISCONNECT do not nest.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        S2_DISCONNECT&amp;lt;/pre&amp;gt;&lt;br /&gt;
I propose that the following command number should be assigned:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;#define S2_CONNECT 0xC005&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_DELMULTICASTADDRESS ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_DELMULTICASTADDRESS -- Disable an interface multicast address.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command causes device driver to disable multicast packet&lt;br /&gt;
        reception for the requested address.&lt;br /&gt;
&lt;br /&gt;
        It is an error to disable a multicast address that is not enabled.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - S2_DELMULTICASTADDRESS&lt;br /&gt;
        ios2_SrcAddr    - Multicast address to disable.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - Zero if successful; non-zero otherwise.&lt;br /&gt;
        ios2_WireError  - More specific error number.&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        Multicast addresses are added globally -- anyone using the device&lt;br /&gt;
        may receive packets as a result of any multicast address which has&lt;br /&gt;
        been added for the device.&lt;br /&gt;
&lt;br /&gt;
        Since multicast addresses are not &amp;amp;quot;bound&amp;amp;quot; to a particular packet type,&lt;br /&gt;
        each enabled multicast address has an &amp;amp;quot;enabled&amp;amp;quot; count associated with&lt;br /&gt;
        it so that if two protocols add the same multicast address and later&lt;br /&gt;
        one removes it, it is still enabled until the second removes it.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        S2_ADDMULTICASTADDRESS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_DEVICEQUERY ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_DEVICEQUERY -- Return parameters for this network interface.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command causes the device driver to report information about the&lt;br /&gt;
        device. Up to SizeAvailable bytes of the information is copied&lt;br /&gt;
        into a buffer pointed to by ios2_StatData. The format of the data is&lt;br /&gt;
        as follows:&lt;br /&gt;
&lt;br /&gt;
            struct Sana2DeviceQuery&lt;br /&gt;
            {&lt;br /&gt;
            /*&lt;br /&gt;
            ** Standard information&lt;br /&gt;
            */&lt;br /&gt;
                ULONG SizeAvailble; /* bytes available */&lt;br /&gt;
                ULONG SizeSupplied; /* bytes supplied */&lt;br /&gt;
                LONG  DevQueryFormat;   /* this is type 0 */&lt;br /&gt;
                LONG  DeviceLevel;      /* this document is level 0 */&lt;br /&gt;
&lt;br /&gt;
            /*&lt;br /&gt;
            ** Common information&lt;br /&gt;
            */&lt;br /&gt;
                UWORD AddrFieldSize;    /* address size in bits */&lt;br /&gt;
                ULONG MTU;              /* maximum packet data size */&lt;br /&gt;
                LONG  bps;              /* line rate (bits/sec) */&lt;br /&gt;
                LONG  HardwareType;     /* what the wire is */&lt;br /&gt;
&lt;br /&gt;
            /*&lt;br /&gt;
            ** Format specific information&lt;br /&gt;
            */&lt;br /&gt;
            };&lt;br /&gt;
&lt;br /&gt;
        The SizeAvailable specifies the number of bytes that the caller&lt;br /&gt;
        is prepared to accomodate, including the standard information fields.&lt;br /&gt;
&lt;br /&gt;
        SizeSupplied is the number of bytes actually supplied,&lt;br /&gt;
        including the standard information fields, which will not exceed&lt;br /&gt;
        SizeAvailable.&lt;br /&gt;
&lt;br /&gt;
        &amp;amp;lt;devices/sana2.h&amp;amp;gt; includes constants for these values.  If your&lt;br /&gt;
        hardware does not have a number assigned to it, you must contact&lt;br /&gt;
        the AmigaOS development team to get a hardware number.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - S2_DEVICEQUERY.&lt;br /&gt;
        ios2_StatData   - Pointer to Sana2DeviceQuery structure to fill in.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - Zero if successful; non-zero otherwise.&lt;br /&gt;
        ios2_WireError  - More specific error number.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_DISCONNECT ==&lt;br /&gt;
&lt;br /&gt;
This command complements &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt; in that it tears down a connection. It uses the same &amp;lt;tt&amp;gt;Sana2Connection&amp;lt;/tt&amp;gt; structure and hooks, but most of these members are ignored.&lt;br /&gt;
&lt;br /&gt;
The command should work as follows:&lt;br /&gt;
&lt;br /&gt;
# The client must set up the &amp;lt;tt&amp;gt;Sana2Connection&amp;lt;/tt&amp;gt; data structure, initialize the &amp;lt;tt&amp;gt;s2c_Size&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;s2c_Options&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;s2c_ErrorHook&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;s2c_ConnectHook&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;s2c_DisconnectHook&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;s2c_Login&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;s2c_Password&amp;lt;/tt&amp;gt; fields. The &amp;lt;tt&amp;gt;s2c_Options&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;s2c_ConnectHook&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;s2c_Login&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;s2c_Password&amp;lt;/tt&amp;gt; fields will be ignored, but the client should play things safe.&lt;br /&gt;
# A pointer to the &amp;lt;tt&amp;gt;Sana2Connection&amp;lt;/tt&amp;gt; data structure is placed in the &amp;lt;tt&amp;gt;ios2_Data&amp;lt;/tt&amp;gt; member of an &amp;lt;tt&amp;gt;IOSana2Req&amp;lt;/tt&amp;gt;, the command is set to &amp;lt;tt&amp;gt;S2_DISCONNECT&amp;lt;/tt&amp;gt; and the request is sent via &amp;lt;tt&amp;gt;DoIO()&amp;lt;/tt&amp;gt; or &amp;lt;tt&amp;gt;SendIO()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
# The driver receives the request and proceeds to reverse the steps that previously allowed it to establish a connection. This includes telling the peer to shut down the link, but it does not include cleaning up the link layer device access, i.e. no I/O requests used for accessing a modem may be shut down yet.&lt;br /&gt;
# The &amp;lt;tt&amp;gt;s2c_DisconnectHook&amp;lt;/tt&amp;gt; may be invoked with the proper parameters. Some drivers, such as for asynchronous PPP, will need the hook to tell the modem to hang up the line. Some drivers, such as for PPPoE, may not need this hook and thus ignore it.&lt;br /&gt;
# The initialization is reversed completely, all resources allocated when the connection was previously opened are released. The &amp;lt;tt&amp;gt;IOSana2Req&amp;lt;/tt&amp;gt; is returned with an error code of zero, indicating success. The SANA-II event &amp;lt;tt&amp;gt;S2EVENT_DISCONNECT&amp;lt;/tt&amp;gt; must be sent, and, if necessary, &amp;lt;tt&amp;gt;S2EVENT_OFFLINE&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The connect and disconnect hook functions must not be called from interrupt code. For each hook only a &amp;lt;tt&amp;gt;Task&amp;lt;/tt&amp;gt; calling context of unknown priority must be assumed. Also, stack space is provided only to call &amp;lt;tt&amp;gt;exec.library&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;utility.library&amp;lt;/tt&amp;gt; functions. The callback shall not place excessive data on the stack. Stack space should be considered limited.&lt;br /&gt;
&lt;br /&gt;
I propose a command with the following semantics:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_DISCONNECT -- Go offline and close a link layer connection&lt;br /&gt;
            previously established with S2_CONNECT.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command complements the S2_CONNECT command in that it&lt;br /&gt;
        reverses the steps taken to establish a link layer connection.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command          - S2_DISCONNECT&lt;br /&gt;
        ios2_Data             - Pointer to Sana2Connection structure&lt;br /&gt;
        ios2_BufferManagement - Magic cookie as returned when opening the&lt;br /&gt;
                                driver with a struct IOSana2Req&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Req.io_Error - Zero if successful; non-zero otherwise&lt;br /&gt;
        ios2_WireError    - More specific error number&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        If successful, this command implies S2_OFFLINE, i.e. the&lt;br /&gt;
        link layer is deallocated.&lt;br /&gt;
&lt;br /&gt;
        The driver must ignore the S2_DISCONNECT command and&lt;br /&gt;
        recover gracefully if the S2_CONNECT was never sent or&lt;br /&gt;
        returned with an error.&lt;br /&gt;
&lt;br /&gt;
        The contents of the Sana2Connection structure are valid only&lt;br /&gt;
        until the device driver has processed the command and returned&lt;br /&gt;
        the IOSana2Req. Any data the driver may need to retain beyond&lt;br /&gt;
        that point of time must be copied.&lt;br /&gt;
&lt;br /&gt;
        Once the S2_DISCONNECT command has returned, it is safe to dispose&lt;br /&gt;
        of the Sana2Connection structure provided at S2_CONNECT time.&lt;br /&gt;
&lt;br /&gt;
        Note that S2_OFFLINE does not necessarily imply S2_DISCONNECT, if&lt;br /&gt;
        the S2_DISCONNECT command is listed as supported by the driver via&lt;br /&gt;
        NSCMD_DEVICEQUERY. If S2_DISCONNECT is not listed as supported,&lt;br /&gt;
        S2_OFFLINE obviously implies disconnect functionality.&lt;br /&gt;
&lt;br /&gt;
        S2_CONNECT/S2_DISCONNECT do not nest.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        S2_CONNECT&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
I propose that the following command number should be assigned:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;#define S2_DISCONNECT 0xC006&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_GETDNSADDRESS ==&lt;br /&gt;
&lt;br /&gt;
The PPP negotiation process may produce information on which domain name and NetBIOS name servers are available to the client. I think that it is doubtful that the availability of NetBIOS name servers will be useful for Amiga software (let alone whether NetBIOS name resolution has a future), which is why I suggest that a SANA-II command for returning only the domain name servers is introduced.&lt;br /&gt;
&lt;br /&gt;
I propose a command with the following semantics:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_GETDNSADDRESS -- Obtain the addresses of the primary&lt;br /&gt;
           and secondary domain name servers.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        Obtain the addresses of the domain name servers available to the&lt;br /&gt;
        client using this driver&#039;s address.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command          - S2_GETDNSADDRESS&lt;br /&gt;
        ios2_Flags            - Supported flags are:&lt;br /&gt;
                                SANA2IOB_QUICK&lt;br /&gt;
        ios2_BufferManagement - Magic cookie as returned when opening the&lt;br /&gt;
                                driver with a struct IOSana2Req&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Req.io_Error - Zero if successful; non-zero otherwise&lt;br /&gt;
        ios2_WireError    - More specific error number&lt;br /&gt;
        ios2_SrcAddr      - Address of primary domain name server&lt;br /&gt;
        ios2_DstAddr      - Address of secondary domain name server&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        The size of the address returned by S2_GETPEERADDRESS must not be&lt;br /&gt;
        different from the size as returned by the S2_DEVICEQUERY command. For&lt;br /&gt;
        example, if a 32 bit IPv4 address was advertized, the driver must not&lt;br /&gt;
        return a 128 bit IPv6 address instead.&lt;br /&gt;
&lt;br /&gt;
        If the driver is unable to return the primary domain name server&lt;br /&gt;
        address (ios2_SrcAddr) or the secondary domain name server address&lt;br /&gt;
        (ios2_DstAddr) it must fill the respective address fields with zeroes.&lt;br /&gt;
        It is legal for a driver to respond to the S2_GETDNSADDRESS command&lt;br /&gt;
        with two zero addresses (both ios2_SrcAddr and ios2_DstAddr filled&lt;br /&gt;
        with zeroes).&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
I propose that the following command number should be assigned:&lt;br /&gt;
&amp;lt;tt&amp;gt;#define S2_GETDNSADDRESS 0xC003&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This command may be useful beyond the typical application (PPP) described above.&lt;br /&gt;
&lt;br /&gt;
== S2_GETEXTENDEDGLOBALSTATS ==&lt;br /&gt;
&lt;br /&gt;
There already exists a SANA-II command for querying global device statistics (&amp;lt;tt&amp;gt;S2_GETGLOBALSTATS&amp;lt;/tt&amp;gt;) which should be common to all kinds of networking devices. Statistics that are particular to a certain device type are intended to be returned through the &amp;lt;tt&amp;gt;S2_GETSPECIALSTATS&amp;lt;/tt&amp;gt; command. I feel that these mechanisms both fail to cater well enough for dial-up or session-oriented networking applications such as PPP or PPPoE. Since the data structure used by &amp;lt;tt&amp;gt;S2_GETGLOBALSTATS&amp;lt;/tt&amp;gt; is of a fixed size and not intended to accomodate for new fields, I propose to introduce a new command which uses a different data structure, as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct Sana2ExtDeviceStats&lt;br /&gt;
{&lt;br /&gt;
   ULONG          s2xds_Length;&lt;br /&gt;
   ULONG          s2xds_Actual;&lt;br /&gt;
&lt;br /&gt;
   S2QUAD         s2xds_PacketsReceived;&lt;br /&gt;
   S2QUAD         s2xds_PacketsSent;&lt;br /&gt;
   S2QUAD         s2xds_BadData;&lt;br /&gt;
   S2QUAD         s2xds_Overruns;&lt;br /&gt;
   S2QUAD         s2xds_UnknownTypesReceived;&lt;br /&gt;
   S2QUAD         s2xds_Reconfigurations;&lt;br /&gt;
   struct timeval s2xds_LastStart;&lt;br /&gt;
&lt;br /&gt;
   struct timeval s2xds_LastConnected;&lt;br /&gt;
   struct timeval s2xds_LastDisconnected;&lt;br /&gt;
   struct timeval s2xds_TimeConnected;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Before I proceed to explain what purposes the individual members serve, a few words on the &amp;lt;tt&amp;gt;S2QUAD&amp;lt;/tt&amp;gt; type, which is defined as follows:&lt;br /&gt;
&amp;lt;tt&amp;gt;typedef struct { ULONG s2q_High; ULONG s2q_Low; } S2QUAD;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In other words, the &amp;lt;tt&amp;gt;S2QUAD&amp;lt;/tt&amp;gt; type stands for an unsigned 64 bit big endian integer, as expressed in ISO &#039;C&#039; terms.&lt;br /&gt;
&lt;br /&gt;
The structure members have the following purposes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2xds_Length&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the size of the data structure to be filled in and should be initialized by the caller to &amp;lt;tt&amp;gt;sizeof(struct Sana2ExtDeviceStats)&amp;lt;/tt&amp;gt;. Smaller values are permitted, but these &#039;&#039;&#039;must not&#039;&#039;&#039; be smaller than 8 (which covers the &amp;lt;tt&amp;gt;s2xds_Length&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;s2xds_Actual&amp;lt;/tt&amp;gt; members). A driver which finds an &amp;lt;tt&amp;gt;s2xds_Length&amp;lt;/tt&amp;gt; &amp;amp;lt; 8 &#039;&#039;&#039;must&#039;&#039;&#039; treat this as an error and reject the command with &amp;lt;tt&amp;gt;ios2_Req.io_Error&amp;lt;/tt&amp;gt;=&amp;lt;tt&amp;gt;IOERR_BADLENGTH&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2xds_Actual&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The size of the data structure filled with information. This member is initialized by the driver and &#039;&#039;&#039;must&#039;&#039;&#039; be &amp;amp;lt;= &amp;lt;tt&amp;gt;s2xds_Length&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2xds_PacketsReceived&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Number of packets that this unit has received. This is a 64 bit integer.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2xds_PacketsSent&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Number of packets that this unit has sent. This is a 64 bit integer.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2xds_BadData&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Number of bad packets received (i.e., hardware CRC failed). This is a 64 bit integer.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2xds_Overruns&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Number of packets dropped due to insufficient resources available in the network interface. This is a 64 bit integer.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2xds_UnknownTypesReceived&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Number of packets received that had no pending read command with the appropriate packet type. This is a 64 bit integer.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2xds_Reconfigurations&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Number of network reconfigurations since this unit was last configured. This is a 64 bit integer.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2xds_LastStart&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The time when this unit last went on-line.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2xds_LastConnected&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The time when this unit last established a connection. For dial-up connections, this should be the time when the underlying serial line started to accumulate costs. &amp;lt;tt&amp;gt;s2xds_LastConnected&amp;lt;/tt&amp;gt; &#039;&#039;&#039;must&#039;&#039;&#039; be set to zero if the unit never managed to make a connection.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2xds_LastDisconnected&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The time when this unit last shut down a connection. For dial-up connections, this should be the time when the underlying serial line stopped accumulating costs, e.g. when the modem&#039;s carrier signal was lost. &amp;lt;tt&amp;gt;s2xds_LastDisconnected&amp;lt;/tt&amp;gt; &#039;&#039;&#039;must&#039;&#039;&#039; be set to zero if the unit never disconnected.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2xds_TimeConnected&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The time this unit has been connected. For dial-up connections this should be the time between now and when the underlying serial line started accumulating costs.&lt;br /&gt;
&lt;br /&gt;
If this unit is not currently connected, then &amp;lt;tt&amp;gt;s2xds_TimeConnected&amp;lt;/tt&amp;gt; &#039;&#039;&#039;must&#039;&#039;&#039; be set to zero. This means in particular that when the connection is lost, &amp;lt;tt&amp;gt;s2xds_TimeConnected&amp;lt;/tt&amp;gt; &#039;&#039;&#039;must&#039;&#039;&#039; be immediately set to zero and &amp;lt;tt&amp;gt;s2xds_LastDisconnected&amp;lt;/tt&amp;gt; &#039;&#039;&#039;must&#039;&#039;&#039; be filled in so that client software can query how long the unit was connected by subtracting &amp;lt;tt&amp;gt;s2xds_LastConnected&amp;lt;/tt&amp;gt; from &amp;lt;tt&amp;gt;s2xds_LastDisconnected&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
If this unit is currently connected, &amp;lt;tt&amp;gt;s2xds_TimeConnected&amp;lt;/tt&amp;gt; &#039;&#039;&#039;must never&#039;&#039;&#039; be zero; if necessary, set &amp;lt;tt&amp;gt;s2xds_TimeConnected.tv_secs=0&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;s2xds_TimeConnected.tv_micros=1&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
If &amp;lt;tt&amp;gt;s2xds_TimeConnected&amp;lt;/tt&amp;gt; is zero, check &amp;lt;tt&amp;gt;s2xds_LastConnected&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;s2xds_LastDisconnected&amp;lt;/tt&amp;gt;; if the latter two are not zero, you can calculate the previous connection time by subtracting &amp;lt;tt&amp;gt;s2xds_LastConnected&amp;lt;/tt&amp;gt; from &amp;lt;tt&amp;gt;s2xds_LastDisconnected&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The layout and semantics used by the &amp;lt;tt&amp;gt;Sana2ExtDeviceStats&amp;lt;/tt&amp;gt; data structure suggest that there is a difference between the underlying networking media (the link layer) and the state of the protocol that is running on top of it. With drivers for networking hardware such as Ethernet there was no difference between these two, but for protocols like SLIP, PPP or PPPoE there is a difference. The difference is in that a session or connection may exist for a certain time whereas the protocol running inside that session may be switched &#039;online&#039; later. The primary purpose of the &amp;lt;tt&amp;gt;s2xds_LastConnected&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;s2xds_LastDisconnected&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;s2xds_TimeConnected&amp;lt;/tt&amp;gt; fields is to allow for cost accounting and traffic monitoring (so that, for example, a driver may be disconnected after it has been idle for a while) to be written.&lt;br /&gt;
&lt;br /&gt;
I propose a command with the following semantics:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_GETEXTENDEDGLOBALSTATS -- Get interface accumulated statistics;&lt;br /&gt;
           updated version.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command causes the device driver to retrieve various global&lt;br /&gt;
        runtime statistics for this network interface. The format of the data&lt;br /&gt;
        returned is as follows:&lt;br /&gt;
&lt;br /&gt;
           struct Sana2ExtDeviceStats&lt;br /&gt;
           {&lt;br /&gt;
              ULONG s2xds_Length;&lt;br /&gt;
              ULONG s2xds_Actual;&lt;br /&gt;
&lt;br /&gt;
              S2QUAD s2xds_PacketsReceived;&lt;br /&gt;
              S2QUAD s2xds_PacketsSent;&lt;br /&gt;
              S2QUAD s2xds_BadData;&lt;br /&gt;
              S2QUAD s2xds_Overruns;&lt;br /&gt;
              S2QUAD s2xds_UnknownTypesReceived;&lt;br /&gt;
              S2QUAD s2xds_Reconfigurations;&lt;br /&gt;
              struct timeval s2xds_LastStart;&lt;br /&gt;
&lt;br /&gt;
              struct timeval s2xds_LastConnected;&lt;br /&gt;
              struct timeval s2xds_LastDisconnected;&lt;br /&gt;
              struct timeval s2xds_TimeConnected;&lt;br /&gt;
           };&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command          - S2_GETEXTENDEDGLOBALSTATS&lt;br /&gt;
        ios2_StatData         - Pointer to Sana2ExtDeviceStats structure&lt;br /&gt;
                                to fill in&lt;br /&gt;
        ios2_BufferManagement - Magic cookie as returned when opening the&lt;br /&gt;
                                driver with a struct IOSana2Req&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Req.io_Error - Zero if successful; non-zero otherwise&lt;br /&gt;
        ios2_WireError    - More specific error number&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
I propose that the following command number should be assigned:&lt;br /&gt;
&amp;lt;tt&amp;gt;#define S2_GETEXTENDEDGLOBALSTATS 0xC004&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_GETGLOBALSTATS ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        GetGlobalStats -- Get interface accumulated statistics.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command causes the device driver to retrieve various global&lt;br /&gt;
        runtime statistics for this network interface. The format of the&lt;br /&gt;
        data returned is as follows:&lt;br /&gt;
&lt;br /&gt;
            struct Sana2DeviceStats&lt;br /&gt;
            {&lt;br /&gt;
                ULONG PacketsReceived;&lt;br /&gt;
                ULONG PacketsSent;&lt;br /&gt;
                ULONG BadData;&lt;br /&gt;
                ULONG Overruns;&lt;br /&gt;
                ULONG UnknownTypesReceived;&lt;br /&gt;
                ULONG Reconfigurations;&lt;br /&gt;
                timeval LastStart;&lt;br /&gt;
            };&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - S2_GETGLOBALSTATS.&lt;br /&gt;
        ios2_StatData   - Pointer to Sana2DeviceStats structure to fill.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - Zero if successful; non-zero otherwise.&lt;br /&gt;
        ios2_WireError  - More specific error number.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        S2_GETSPECIALSTATS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_GETNETWORKINFO ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
	S2_GETNETWORKINFO -- Get information on current network.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
	This command provides information on the status of the currently&lt;br /&gt;
	used network. If this command completes successfully, ios2_StatData&lt;br /&gt;
	will contain a pointer to a tag list that contains information on&lt;br /&gt;
	the network. The S2INFO_#? tags used are defined in the&lt;br /&gt;
	devices/sana2wireless.h include file.&lt;br /&gt;
&lt;br /&gt;
	The returned taglist is allocated from the supplied memory pool.&lt;br /&gt;
	To discard the results of this command, the entire memory pool&lt;br /&gt;
	should be destroyed.&lt;br /&gt;
&lt;br /&gt;
   INPUTS&lt;br /&gt;
	ios2_Data - Pointer to an Exec memory pool.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
	ios2_Data - Remains unchanged.&lt;br /&gt;
	ios2_StatData - Pointer to a tag list.&lt;br /&gt;
	io_Error - Zero if successful; non-zero otherwise.&lt;br /&gt;
	ios2_WireError - More specific error code.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_GETNETWORKS ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
	S2_GETNETWORKS -- Scan for available networks.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
	This command supplies details of available networks. If the scan&lt;br /&gt;
	should be limited to one specific network, the S2INFO_SSID tag&lt;br /&gt;
	should specify its name.&lt;br /&gt;
&lt;br /&gt;
	If this command completes successfully, ios2_StatData will contain&lt;br /&gt;
	an array of pointers to tag lists, each of which contains&lt;br /&gt;
	information on a single network. The device will set ios2_DataLength&lt;br /&gt;
	to the number of elements in this array.&lt;br /&gt;
&lt;br /&gt;
	The returned taglists are allocated from the supplied memory pool.&lt;br /&gt;
	To discard the results of this command, the entire memory pool&lt;br /&gt;
	should be destroyed.&lt;br /&gt;
&lt;br /&gt;
	The S2INFO_#? tags used with this command are defined in the&lt;br /&gt;
	devices/sana2wireless.h include file.&lt;br /&gt;
&lt;br /&gt;
   INPUTS&lt;br /&gt;
	ios2_Data - Pointer to an Exec memory pool.&lt;br /&gt;
	ios2_StatData - Pointer to taglist that specifies parameters to use.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
	ios2_DataLength - Number of tag lists returned.&lt;br /&gt;
	ios2_Data - Remains unchanged.&lt;br /&gt;
	ios2_StatData - Pointer to an array of tag lists.&lt;br /&gt;
	io_Error - Zero if successful; non-zero otherwise.&lt;br /&gt;
	ios2_WireError - More specific error code.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_GETPEERADDRESS ==&lt;br /&gt;
&lt;br /&gt;
As part of the negotiation process, the PPP protocol can return the addresses used by the peer (the other side of the point-to-point connection PPP establishes; typically a dial-in server) and assigned to the client establishing the connection. The SANA-II standard does not provide for a mechanism to return such information. Existing drivers therefore had to resort to other means, such as by setting global environment variables containing this information.&lt;br /&gt;
&lt;br /&gt;
I propose a command with the following semantics:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_GETPEERADDRESS -- Obtain the addresses used by the peer&lt;br /&gt;
           (server) and the client of a point-to-point connection.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        Obtain the address used by the peer of a point-to-point connection and&lt;br /&gt;
        the address assigned to the local driver.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command          - S2_GETPEERADDRESS&lt;br /&gt;
        ios2_Flags            - Supported flags are:&lt;br /&gt;
                                SANA2IOB_QUICK&lt;br /&gt;
        ios2_BufferManagement - Magic cookie as returned when opening the&lt;br /&gt;
                                driver with a struct IOSana2Req&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Req.io_Error - Zero if successful; non-zero otherwise&lt;br /&gt;
        ios2_WireError    - More specific error number&lt;br /&gt;
        ios2_SrcAddr      - Address assigned to the local driver&lt;br /&gt;
        ios2_DstAddr      - Address used by the peer&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        The size of the address returned by S2_GETPEERADDRESS must not be&lt;br /&gt;
        different from the size returned by the S2_DEVICEQUERY command. For&lt;br /&gt;
        example, if a 32 bit IPv4 address was advertized, the driver must not&lt;br /&gt;
        return a 128 bit IPv6 address instead.&lt;br /&gt;
&lt;br /&gt;
        If the driver is unable to return the local driver address&lt;br /&gt;
        (ios2_SrcAddr) or the peer&#039;s address (ios2_DstAddr) it must fill the&lt;br /&gt;
        respective address fields with zeroes. It is legal for a driver to&lt;br /&gt;
        respond to the S2_GETPEERADDRESS command with two zero addresses (both&lt;br /&gt;
        ios2_SrcAddr and ios2_DstAddr filled with zeroes).&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
I propose that the following command number should be assigned:&lt;br /&gt;
&amp;lt;tt&amp;gt;#define S2_GETPEERADDRESS 0xC002&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This command may be useful beyond the typical application (PPP) described above.&lt;br /&gt;
&lt;br /&gt;
== S2_GETSIGNALQUALITY ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
	S2_GETSIGNALQUALITY -- Get signal quality statistics.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
	This command fills in the supplied Sana2SignalQuality structure with&lt;br /&gt;
	current signal and noise levels. The unit for these figures is dBm.&lt;br /&gt;
	Typically, they are negative values.&lt;br /&gt;
&lt;br /&gt;
   INPUTS&lt;br /&gt;
	ios2_StatData - Pointer to Sana2SignalQuality structure.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
	io_Error - Zero if successful; non-zero otherwise.&lt;br /&gt;
	ios2_WireError - More specific error code.&lt;br /&gt;
	ios2_StatData - Pointer to filled Sana2SignalQuality structure.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_GETSPECIALSTATS ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_GETSPECIALSTATS -- Get network type specific statistics.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This function returns statistics which are specific to the type of&lt;br /&gt;
        network medium this driver controls. For example, this command could&lt;br /&gt;
        return statistics common to all Ethernets which are not common to all&lt;br /&gt;
        network mediums in general.&lt;br /&gt;
&lt;br /&gt;
        The supplied Sana2SpecialStatData structure is given below:&lt;br /&gt;
&lt;br /&gt;
            struct Sana2SpecialStatData&lt;br /&gt;
            {&lt;br /&gt;
                ULONG RecordCountMax;&lt;br /&gt;
                ULONG RecordCountSupplied;&lt;br /&gt;
                struct Sana2StatRecord[RecordCountMax];&lt;br /&gt;
            };&lt;br /&gt;
&lt;br /&gt;
        The format of the data returned is:&lt;br /&gt;
&lt;br /&gt;
            struct Sana2StatRecord&lt;br /&gt;
            {&lt;br /&gt;
                ULONG Type;     /* Amiga registered */&lt;br /&gt;
                LONG Count;     /* the stat itself */&lt;br /&gt;
                char *String;   /* null terminated */&lt;br /&gt;
            };&lt;br /&gt;
&lt;br /&gt;
        The RecordCountMax field specifies the number of records that the&lt;br /&gt;
        caller is prepared to accomodate.&lt;br /&gt;
&lt;br /&gt;
        RecordCountSupplied is the number of record actually supplied which&lt;br /&gt;
        will not exceed RecordCountMax.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - S2_GETSPECIALSTATS.&lt;br /&gt;
        ios2_StatData   - Pointer to a Sana2SpecialStatData structure to fill.&lt;br /&gt;
                          RecordCountMax must be initialized.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - Zero if successful; non-zero otherwise.&lt;br /&gt;
        ios2_WireError  - More specific error number.&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        Amiga will maintain registered statistic Types.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        S2_GETGLOBALSTATS, &amp;amp;lt;devices/sana2specialstats.h&amp;amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_GETSTATIONADDRESS ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_GETSTATIONADDRESS -- Get default and interface address.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command causes the device driver to copy the current interface&lt;br /&gt;
        address into ios2_SrcAddr, and to copy the factory default station&lt;br /&gt;
        address (if any) into ios2_DstAddr.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - S2_GETSTATIONADDRESS.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - Zero if successful; non-zero otherwise.&lt;br /&gt;
        ios2_WireError  - More specific error number.&lt;br /&gt;
        ios2_SrcAddr    - Current interface address.&lt;br /&gt;
        ios2_DstAddr    - Default interface address (if any).&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        S2_CONFIGINTERFACE&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_GETTYPESTATS ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_GETTYPESTATS -- Get accumulated type specific statistics.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command causes the device driver to retrieve various packet type&lt;br /&gt;
        specific runtime statistics for this network interface. The format of&lt;br /&gt;
        the data returned is as follows:&lt;br /&gt;
&lt;br /&gt;
            struct Sana2TypeStatData&lt;br /&gt;
            {&lt;br /&gt;
                LONG PacketsSent;&lt;br /&gt;
                LONG PacketsReceived;&lt;br /&gt;
                LONG BytesSent;&lt;br /&gt;
                LONG BytesReceived;&lt;br /&gt;
                LONG PacketsDropped;&lt;br /&gt;
            };&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - S2_GETTYPESTATS.&lt;br /&gt;
        ios2_PacketType - Packet type of interest.&lt;br /&gt;
        ios2_StatData   - Pointer to TypeStatData structure to fill in.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - Zero if successful; non-zero otherwise.&lt;br /&gt;
        ios2_WireError  - More specific error number.&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        Statistics for a particular packet type are only available while that&lt;br /&gt;
        packet type is being ``tracked&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        S2_TRACKTYPE, S2_UNTRACKTYPE&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_MULTICAST ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_MULTICAST -- Multicast a packet on network.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command works the same as CMD_WRITE except that it also performs&lt;br /&gt;
        whatever special processing of the packet is required to do a&lt;br /&gt;
        multicast send. The actual multicast mechanism is neccessarily&lt;br /&gt;
        network/interface/device specific.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - S2_MULTICAST.&lt;br /&gt;
        ios2_Flags      - Supported flags are:&lt;br /&gt;
                                SANA2IOB_RAW&lt;br /&gt;
                                SANA2IOB_QUICK&lt;br /&gt;
        ios2_PacketType - Packet type to send.&lt;br /&gt;
        ios2_DstAddr    - Destination interface address for this packet.&lt;br /&gt;
        ios2_DataLength - Length of the Data to be sent.&lt;br /&gt;
        ios2_Data       - Abstract data structure which packet data is&lt;br /&gt;
                          contained in.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - Zero if successful; non-zero otherwise.&lt;br /&gt;
                          This command can fail for many reasons and&lt;br /&gt;
                          is not supported by all networks and/or&lt;br /&gt;
                          network interfaces.&lt;br /&gt;
        ios2_WireError  - More specific error number.&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        The address supplied in ios2_DstAddr will be sanity checked (if&lt;br /&gt;
        possible) by the driver. If the supplied address fails this sanity&lt;br /&gt;
        check, the multicast request will fail immediately with ios2_Error&lt;br /&gt;
        set to S2WERR_BAD_MULTICAST.&lt;br /&gt;
&lt;br /&gt;
        Another Amiga will not receive a multicast packet unless it has had&lt;br /&gt;
        the particular multicast address being used S2_ADDMULTICASTADRESS&#039;d.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        CMD_WRITE, S2_BROADCAST, S2_ADDMULTICASTADDRESS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_OFFLINE ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_OFFLINE -- Remove interface from service.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command removes a network interface from service.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - S2_OFFLINE.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - Zero if successful; non-zero otherwise.&lt;br /&gt;
        ios2_WireError  - More specific error number.&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        Aborts all pending reads and writes with ios2_Error set to&lt;br /&gt;
        S2ERR_OUTOFSERVICE.&lt;br /&gt;
&lt;br /&gt;
        While the interface is offline, all read, writes and any other&lt;br /&gt;
        command that touches interface hardware will be rejected with&lt;br /&gt;
        ios2_Error set to S2ERR_OUTOFSERVICE.&lt;br /&gt;
&lt;br /&gt;
        This command is intended to permit a network interface to be&lt;br /&gt;
        tested on an otherwise live system.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        S2_ONLINE&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_ONEVENT ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_ONEVENT -- Return when specified event occures.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command returns when a particular event condition has occured&lt;br /&gt;
        on the network or this network interface.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - S2_ONEVENT.&lt;br /&gt;
        ios2_Flags      - Supported flags are:&lt;br /&gt;
                                SANA2IOB_QUICK&lt;br /&gt;
        ios2_WireError  - Mask of event(s) to wait for&lt;br /&gt;
                          (from &amp;amp;lt;devices/sana2.h&amp;amp;gt;).&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - Zero if successful; non-zero otherwise.&lt;br /&gt;
        ios2_WireError  - Mask of events that occured.&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        If this device driver does not understand the specified event&lt;br /&gt;
        condition(s) then the command returns immediately with&lt;br /&gt;
        ios2_Req.io_Error set to S2_ERR_NOT_SUPPORTED and ios2_WireError&lt;br /&gt;
        S2WERR_BAD_EVENT.  A successful return will have ios2_Error set to&lt;br /&gt;
        zero ios2_WireError set to the event number.&lt;br /&gt;
&lt;br /&gt;
        All pending requests for a particular event will be returned when&lt;br /&gt;
        that event occurs.&lt;br /&gt;
&lt;br /&gt;
        All event types that cover a particular condition are returned when&lt;br /&gt;
        that condition occures. For instance, if an error is returned by&lt;br /&gt;
        a buffer management function during receive processing, events of&lt;br /&gt;
        types S2EVENT_ERROR, S2EVENT_RX and S2EVENT_BUFF would be returned if&lt;br /&gt;
        pending.&lt;br /&gt;
&lt;br /&gt;
        Types ONLINE and OFFLINE return immediately if the device is&lt;br /&gt;
        already in the state to be waited for.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_ONLINE ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_ONLINE -- Put a network interface back in service.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command places an offline network interface back into service.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - S2_ONLINE.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - Zero if successful; non-zero otherwise.&lt;br /&gt;
        ios2_WireError  - More specific error number.&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        This command is responsible for putting the network interface&lt;br /&gt;
        hardware back into a known state (as close as possible to the&lt;br /&gt;
        state before S2_OFFLINE) and resets the unit global and special&lt;br /&gt;
        statistics.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        S2_OFFLINE&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_READMGMT ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
	S2_READMGMT -- Read a management frame.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
	Reads a raw IEEE 802.11 management frame from the device. The buffer&lt;br /&gt;
	management mechanism used is simpler than that used for data&lt;br /&gt;
	packets (e.g. with CMD_READ): a buffer pointer and a length value&lt;br /&gt;
	are passed to the device.&lt;br /&gt;
&lt;br /&gt;
	As with CMDREAD/S2_READORPHAN, multiple S2_READMGMT requests can&lt;br /&gt;
	(and should) be queued concurrently to ensure no incoming frames are&lt;br /&gt;
	missed.&lt;br /&gt;
&lt;br /&gt;
   INPUTS&lt;br /&gt;
	ios2_DataLength - size of frame buffer.&lt;br /&gt;
	ios2_Data - pointer to a frame buffer.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
	io_Error - Zero if successful; non-zero otherwise.&lt;br /&gt;
	ios2_WireError - More specific error code.&lt;br /&gt;
	ios2_DataLength - actual size of received frame.&lt;br /&gt;
	ios2_Data - pointer to the filled frame buffer.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_READORPHAN ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_READORPHAN -- Get a packet for which there is no reader.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        Get the next packet available that does not satisfy any then-pending&lt;br /&gt;
        CMD_READ requests. The data returned in the ios2_Data structure is&lt;br /&gt;
        normally the Data Link Layer packet type field and the packet data. If&lt;br /&gt;
        bit SANA2IOB_RAW is set in ios2_Flags, then the entire Data Link Layer&lt;br /&gt;
        packet, including both header and trailer information, will be&lt;br /&gt;
        returned.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - CMD_READORPHAN.&lt;br /&gt;
        ios2_Flags      - Supported flags are:&lt;br /&gt;
                                SANA2IOB_RAW&lt;br /&gt;
                                SANA2IOB_QUICK&lt;br /&gt;
        ios2_DataLength - Length of the Data to be sent.&lt;br /&gt;
        ios2_Data       - Abstract data structure which packet data is&lt;br /&gt;
                          contained in.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - Zero if successful; non-zero otherwise.&lt;br /&gt;
        ios2_WireError  - More specific error number.&lt;br /&gt;
        ios2_Flags      - The following flags may be returned:&lt;br /&gt;
                                SANA2IOB_RAW&lt;br /&gt;
                                SANA2IOB_BCAST&lt;br /&gt;
                                SANA2IOB_MCAST&lt;br /&gt;
        ios2_SrcAddr    - Source interface address of packet.&lt;br /&gt;
        ios2_DstAddr    - Destination interface address of packet.&lt;br /&gt;
        ios2_DataLength - Length of the Data to be sent.&lt;br /&gt;
        ios2_Data       - Abstract data structure which packet data is&lt;br /&gt;
                          contained in.&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        This is intended for debugging and management tools.  Protocols should&lt;br /&gt;
        not use this.&lt;br /&gt;
&lt;br /&gt;
        As with 802.3 packets on an ethernet, to determine which protocol&lt;br /&gt;
        family the returned packet belongs to you may have to specify&lt;br /&gt;
        SANA2IOB_RAW to get the entire data link layer wrapper (which is where&lt;br /&gt;
        the protocol type may be kept). Notice this necessarily means that&lt;br /&gt;
        this cannot be done in a network interface independent fashion.  The&lt;br /&gt;
        driver will, however, fill in the PacketType field to the best of its&lt;br /&gt;
        ability.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        CMD_READ, CMD_WRITE&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_SAMPLE_THROUGHPUT ==&lt;br /&gt;
&lt;br /&gt;
The SANA-II standard already allows for statistics to be returned on the amount of data that has passed through a driver. Unfortunately, that information is not very accurate in that no information is provided on the time span in which the data was accumulated. Such information would be helpful in trying to determine as accurately as possible how large the data throughput actually is. I therefore propose a new command which can be used to obtain that information, which uses the following data structure:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct Sana2ThroughputStats&lt;br /&gt;
{&lt;br /&gt;
   ULONG          s2ts_Length;&lt;br /&gt;
   ULONG          s2ts_Actual;&lt;br /&gt;
&lt;br /&gt;
   struct Task *  s2ts_NotifyTask;&lt;br /&gt;
   ULONG          s2ts_NotifyMask;&lt;br /&gt;
&lt;br /&gt;
   struct timeval s2ts_StartTime;&lt;br /&gt;
   struct timeval s2ts_EndTime;&lt;br /&gt;
   S2QUAD         s2ts_BytesSent;&lt;br /&gt;
   S2QUAD         s2ts_BytesReceived;&lt;br /&gt;
   S2QUAD         s2ts_Updates;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Before I proceed to explain what purposes the individual members serve, a few words on the &amp;lt;tt&amp;gt;S2QUAD&amp;lt;/tt&amp;gt; type, which is defined as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;typedef struct { ULONG s2q_High; ULONG s2q_Low; } S2QUAD;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In other words, the &amp;lt;tt&amp;gt;S2QUAD&amp;lt;/tt&amp;gt; type stands for an unsigned 64 bit big endian integer, as expressed in ISO &#039;C&#039; terms.&lt;br /&gt;
&lt;br /&gt;
The structure members have the following purposes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2ts_Length&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the size of the data structure to be filled in and should be initialized by the caller to &amp;lt;tt&amp;gt;sizeof(struct Sana2ThroughputStats)&amp;lt;/tt&amp;gt;. Smaller values are permitted, but these must not be smaller than 8 (which covers the &amp;lt;tt&amp;gt;s2ts_Length&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;s2ts_Actual&amp;lt;/tt&amp;gt; members). A driver which finds an &amp;lt;tt&amp;gt;s2ts_Length&amp;lt;/tt&amp;gt; &amp;amp;lt; 8 must treat this as an error and reject the command with &amp;lt;tt&amp;gt;ios2_Req.io_Error&amp;lt;/tt&amp;gt;=&amp;lt;tt&amp;gt;IOERR_BADLENGTH&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2ts_Actual&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The size of the data structure filled with information. This member is initialized by the driver and must be &amp;amp;lt;= &amp;lt;tt&amp;gt;s2ts_Length&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2ts_NotifyTask&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;Task&amp;lt;/tt&amp;gt; to notify whenever the contents of this data structure change. This must be &amp;lt;tt&amp;gt;NULL&amp;lt;/tt&amp;gt; if no notification is desired.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; This feature should be used carefully, as so much data may arrive that the driver will almost be constantly signalling this &amp;lt;tt&amp;gt;Task&amp;lt;/tt&amp;gt; that a change has taken place.&lt;br /&gt;
&lt;br /&gt;
It is recommend that periodic polling be used, such as to update displays of a link monitoring program.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2ts_NotifyMask&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The signal mask to use for notifying the &amp;lt;tt&amp;gt;Task&amp;lt;/tt&amp;gt; whose address is found in &amp;lt;tt&amp;gt;s2ts_NotifyTask&amp;lt;/tt&amp;gt; (via &amp;lt;tt&amp;gt;Signal(s2ts-&amp;amp;gt;s2ts_NotifyTask,s2ts-&amp;amp;gt;s2ts_NotifyMask);&amp;lt;/tt&amp;gt;). This must be zero if no notification is desired.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2ts_StartTime&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The time when the driver started to fill in this data structure.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2ts_EndTime&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The time when the driver last updated the contents of this data structure.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2ts_BytesSent&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Total number of bytes sent since the driver started to fill in this data structure. This is a 64 bit integer.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2ts_BytesReceived&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Total number of bytes received since the driver started to fill in this data structure. This is a 64 bit integer.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;s2ts_Updates&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Number of times the driver has updated this data structure. This value will increase with every change. This is a 64 bit integer.&lt;br /&gt;
&lt;br /&gt;
A driver implementing this command should take care to update the members &amp;lt;tt&amp;gt;s2ts_EndTime&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;s2ts_BytesSent&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;s2ts_BytesReceived&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;s2ts_Updates&amp;lt;/tt&amp;gt; atomically each time changes are made.&lt;br /&gt;
&lt;br /&gt;
I propose a command with the following semantics:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_SAMPLE_THROUGHPUT -- Obtain accurate information on&lt;br /&gt;
           driver data throughput.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command installs a data structure which is updated every time&lt;br /&gt;
        data is sent or received by the driver.&lt;br /&gt;
&lt;br /&gt;
        This command must be sent via SendIO() or BeginIO(); until&lt;br /&gt;
        the associated I/O request is recalled using AbortIO(), the&lt;br /&gt;
        device unit will continue to update the Sana2ThroughputStats&lt;br /&gt;
        structure in real time.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command          - S2_SAMPLE_THROUGHPUT&lt;br /&gt;
        ios2_StatData         - Pointer to Sana2ThroughputStats structure&lt;br /&gt;
                                to fill in&lt;br /&gt;
        ios2_BufferManagement - Magic cookie as returned when opening the&lt;br /&gt;
                                driver with a struct IOSana2Req&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Req.io_Error - Zero if successful; non-zero otherwise&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        If this device driver does not understand this command,&lt;br /&gt;
        it will immediately return the IOSana2Req with&lt;br /&gt;
        ios2_Req.io_Error set to IOERR_NOCMD. Otherwise, the request will&lt;br /&gt;
        remain queued until it is removed with AbortIO() later.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
I propose that the following command number should be assigned:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;#define S2_SAMPLE_THROUGHPUT 0xC007&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_SANA2HOOK ==&lt;br /&gt;
&lt;br /&gt;
The &#039;traditional&#039; copy call-back functions are installed at &amp;lt;tt&amp;gt;OpenDevice()&amp;lt;/tt&amp;gt; time, and they are found in a &amp;lt;tt&amp;gt;TagItem&amp;lt;/tt&amp;gt; list which is passed along with the &amp;lt;tt&amp;gt;IOSana2Req&amp;lt;/tt&amp;gt;. For the new &amp;lt;tt&amp;gt;Hook&amp;lt;/tt&amp;gt;-based call-back functionality, I propose to introduce a new command. This command would take care of installing one single &amp;lt;tt&amp;gt;Hook&amp;lt;/tt&amp;gt; which will be invoked with the parameters described in section 3.1. The hook function can key off the &amp;lt;tt&amp;gt;SANA2HookMsg-&amp;amp;gt;schm_Method&amp;lt;/tt&amp;gt; field to figure out which function should be performed. Once the &amp;lt;tt&amp;gt;Hook&amp;lt;/tt&amp;gt; is installed via the command as follows, the driver shall ignore any and all tags passed to it during &amp;lt;tt&amp;gt;OpenDevice()&amp;lt;/tt&amp;gt; time.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_SANA2HOOK -- Install a Hook to perform operations such as copying,&lt;br /&gt;
                        overriding the call-back functions installed at&lt;br /&gt;
                        OpenDevice() time.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        The S2_SANA2HOOK command is to replace the &#039;traditional&#039; call-back&lt;br /&gt;
        functions installed through the TagItem list found in the&lt;br /&gt;
        IOSana2Req-&amp;amp;gt;ios2_BufferManagement field. Instead of assigning a&lt;br /&gt;
        function pointer for each copying function, all operations are&lt;br /&gt;
        to be performed through a Hook. This is intended to make the&lt;br /&gt;
        interface more portable and less dependant on a certain hardware&lt;br /&gt;
        architecture.&lt;br /&gt;
&lt;br /&gt;
        The hook message and the hook data structures allow for more than&lt;br /&gt;
        copying to be done.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - S2_SANA2HOOK&lt;br /&gt;
        ios2_Data       - Points to a struct Sana2Hook, which looks&lt;br /&gt;
                          like this:&lt;br /&gt;
&lt;br /&gt;
                             struct Sana2Hook&lt;br /&gt;
                             {&lt;br /&gt;
                                struct Hook s2h_Hook;&lt;br /&gt;
                                Tag *       s2h_Methods;&lt;br /&gt;
                             };&lt;br /&gt;
&lt;br /&gt;
                          The structure fields have the following purposes:&lt;br /&gt;
&lt;br /&gt;
                             s2h_Hook&lt;br /&gt;
                                A standard Hook structure, ready to be&lt;br /&gt;
                                called. Once installed, the complete Hook&lt;br /&gt;
                                structure including its Node structure is&lt;br /&gt;
                                off limits! The s2h_Hook remains installed&lt;br /&gt;
                                until CloseDevice().&lt;br /&gt;
&lt;br /&gt;
                             s2h_Methods&lt;br /&gt;
                                Points to a table of Tag values, each&lt;br /&gt;
                                identifying a copy method supported&lt;br /&gt;
                                (S2_CopyToBuff, S2_CopyFromBuff,&lt;br /&gt;
                                S2_CopyToBuff16, S2_CopyFromBuff16,&lt;br /&gt;
                                S2_CopyToBuff32, S2_CopyFromBuff32,&lt;br /&gt;
                                S2_DMACopyToBuff32, S2_DMACopyFromBuff32,&lt;br /&gt;
                                S2_DMACopyToBuff64 or S2_DMACopyFromBuff64)&lt;br /&gt;
                                or the logging facility (S2_Log).&lt;br /&gt;
                                The table must be terminated by TAG_END.&lt;br /&gt;
&lt;br /&gt;
                                The driver will check the table and&lt;br /&gt;
                                verify that the mandatory S2_CopyToBuff&lt;br /&gt;
                                and S2_CopyFromBuff commands are present.&lt;br /&gt;
                                Additional functionality is used as&lt;br /&gt;
                                available if the driver supports it.&lt;br /&gt;
&lt;br /&gt;
        ios2_DataLength - Must be &amp;amp;gt;= 20, which is the default length of&lt;br /&gt;
                          the Sana2Hook structure. This may grow in&lt;br /&gt;
                          the future, and larger values for ios2_DataLength&lt;br /&gt;
                          may indicate additional functionality associated&lt;br /&gt;
                          with the Sana2Hook.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - IOERR_NOCMD if this command is not supported&lt;br /&gt;
                          by the driver.&lt;br /&gt;
&lt;br /&gt;
                          IOERR_BADLENGTH if IOSana2Req-&amp;amp;gt;ios2_DataLength&lt;br /&gt;
                          is &amp;amp;lt; 20.&lt;br /&gt;
&lt;br /&gt;
                          IOERR_UNITBUSY if the Hook was already&lt;br /&gt;
                          installed or if any of the CMD_READ, CMD_WRITE,&lt;br /&gt;
                          S2_MULTICAST or S2_BROADCAST have already been&lt;br /&gt;
                          invoked.&lt;br /&gt;
&lt;br /&gt;
                          S2WERR_FUNCTIONS_MISSING if the table pointed&lt;br /&gt;
                          to by Sana2Hook-&amp;amp;gt;s2h_Methods does not&lt;br /&gt;
                          include the S2_CopyToBuff and S2_CopyFromBuff&lt;br /&gt;
                          tags.&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        The S2_SANA2HOOK command shall be invoked right after OpenDevice()&lt;br /&gt;
        as very first command.&lt;br /&gt;
&lt;br /&gt;
        When the command has been executed, the driver must use the&lt;br /&gt;
        newly installed Hook for all its copying or logging and cease to&lt;br /&gt;
        use the call-back functions provided at OpenDevice() time.&lt;br /&gt;
&lt;br /&gt;
        The contents of the Sana2Hook structure, as passed to the&lt;br /&gt;
        driver, must not be modified. This includes the MinNode&lt;br /&gt;
        at the beginning of the Hook structure which the driver may&lt;br /&gt;
        need to use for its own purposes.&lt;br /&gt;
&lt;br /&gt;
        The table pointed to by Sana2Hook-&amp;amp;gt;s2h_Methods must&lt;br /&gt;
        include at least the S2_CopyToBuff and S2_CopyFromBuff tags.&lt;br /&gt;
        It must be valid until CloseDevice() is called.&lt;br /&gt;
&lt;br /&gt;
        This field is to be treated as private by a protocol stack.&lt;br /&gt;
        IOSana2Req structures may be duplicated by copying&lt;br /&gt;
        ios2_BufferManagement, io_Device, and io_Unit.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The new command value is defined as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   #define S2_SANA2HOOK 0xC008&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The new error code is defined as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   #define S2WERR_FUNCTIONS_MISSING 24 /* mandatory copy functions are missing */&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_SETKEY ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
	S2_SETKEY -- Set an encryption key.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
	Sets one of the encryption keys for the device. Note that&lt;br /&gt;
	ios2_StatData, if used, points to a byte array representing the RX&lt;br /&gt;
	RX counter value.&lt;br /&gt;
&lt;br /&gt;
   INPUTS&lt;br /&gt;
	ios2_WireError - Key index.&lt;br /&gt;
	ios2_PacketType - Encryption type (e.g. S2ENC_WEP).&lt;br /&gt;
	ios2_DataLength - Key length.&lt;br /&gt;
	ios2_Data - Key.&lt;br /&gt;
	ios2_StatData - RX counter number (NULL if unused).&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
	io_Error - Zero if successful; non-zero otherwise.&lt;br /&gt;
	ios2_WireError - More specific error code.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_SETOPTIONS ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
	S2_SETOPTIONS -- Set network options.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
	Set various parameters for the network interface. This command&lt;br /&gt;
	should be called before going online to set any essential parameters&lt;br /&gt;
	not covered elsewhere. The S2INFO_#? tags used are defined in the&lt;br /&gt;
	devices/sana2wireless.h include file.&lt;br /&gt;
&lt;br /&gt;
   INPUTS&lt;br /&gt;
	ios2_Data - Pointer to a taglist that specifies parameters to use.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
	io_Error - Zero if successful; non-zero otherwise.&lt;br /&gt;
	ios2_WireError - More specific error code.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_TRACKTYPE ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_TRACKTYPE -- Accumulate statistics about a packet type.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command causes the device driver to accumulate statistics about&lt;br /&gt;
        a particular packet type. Packet type statistics, for the particular&lt;br /&gt;
        packet type, are zeroed by this command.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - S2_TRACKTYPE.&lt;br /&gt;
        ios2_PacketType - Packet type of interest.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - Zero if successful; non-zero otherwise.&lt;br /&gt;
        ios2_WireError  - More specific error number.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        S2_UNTRACKTYPE, S2_GETTYPESTATS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_UNTRACKTYPE ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        S2_UNTRACKTYPE -- End statistics about a packet type.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This command causes the device driver to stop accumulating&lt;br /&gt;
        statistics about a particular packet type.&lt;br /&gt;
&lt;br /&gt;
   IO REQUEST&lt;br /&gt;
        ios2_Command    - S2_UNTRACKTYPE.&lt;br /&gt;
        ios2_PacketType - Packet type of interest.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
        ios2_Error      - Zero if successful; non-zero otherwise.&lt;br /&gt;
        ios2_WireError  - More specific error number.&lt;br /&gt;
&lt;br /&gt;
   SEE ALSO&lt;br /&gt;
        S2_TRACKTYPE, S2_GETTYPESTATS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== S2_WRITEMGMT ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
	S2_WRITEMGMT -- Write a management frame.&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
	Writes a raw IEEE 802.11 management frame to the device. The buffer&lt;br /&gt;
	management mechanism used is simpler than that used for data&lt;br /&gt;
	packets (e.g. with CMD_WRITE): a buffer pointer and a length value&lt;br /&gt;
	are passed to the device.&lt;br /&gt;
&lt;br /&gt;
   INPUTS&lt;br /&gt;
	ios2_DataLength - full frame length.&lt;br /&gt;
	ios2_Data - pointer to a complete IEEE 802.11 management frame.&lt;br /&gt;
&lt;br /&gt;
   RESULTS&lt;br /&gt;
	io_Error - Zero if successful; non-zero otherwise.&lt;br /&gt;
	ios2_WireError - More specific error code.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Callback mechanisms =&lt;br /&gt;
&lt;br /&gt;
== CopyFromBuff ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        CopyFromBuff -- Copy n bytes from an abstract data structure.&lt;br /&gt;
&lt;br /&gt;
   SYNOPSIS&lt;br /&gt;
        success = CopyFromBuff(to, from, n)&lt;br /&gt;
        d0                     a0  a1    d0&lt;br /&gt;
&lt;br /&gt;
        BOOL CopyToBuff(VOID *, VOID *, ULONG);&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This function copies &#039;n&#039; bytes of data in the abstract data structure&lt;br /&gt;
        pointed to by &#039;from&#039; into the contigous memory pointed to by &#039;to&#039;.&lt;br /&gt;
        &#039;to&#039; must contain at least &#039;n&#039; bytes of usable memory or innocent&lt;br /&gt;
        memory will be overwritten.&lt;br /&gt;
&lt;br /&gt;
   INPUTS&lt;br /&gt;
        to              - pointer to contiguous memory to copy to.&lt;br /&gt;
        from            - pointer to abstract structure to copy from.&lt;br /&gt;
        n               - number of bytes to copy.&lt;br /&gt;
&lt;br /&gt;
   RESULT&lt;br /&gt;
        success         - TRUE if operation was successful, else FALSE.&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        This function must be callable from interrupts.  In particular, this&lt;br /&gt;
        means that this function may not directly or indirectly call any&lt;br /&gt;
        system memory functions (since those functions rely on Forbid() to&lt;br /&gt;
        protect themselves) and that  you must not compile this function&lt;br /&gt;
        with stack checking enabled.  See the Exec Interrupts&lt;br /&gt;
        chapter for more details on what is legal in a routine called from&lt;br /&gt;
        an interrupt handler.&lt;br /&gt;
&lt;br /&gt;
        &#039;C&#039; programmers should not compile with stack checking (option &#039;-v&#039;&lt;br /&gt;
        in SAS) and should geta4() or __saveds.&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== CopyToBuff ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        CopyToBuff -- Copy n bytes to an abstract data structure.&lt;br /&gt;
&lt;br /&gt;
   SYNOPSIS&lt;br /&gt;
        success = CopyToBuff(to, from, n)&lt;br /&gt;
        d0                   a0  a1    d0&lt;br /&gt;
&lt;br /&gt;
        BOOL CopyToBuff(VOID *, VOID *, ULONG);&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This function first does any initialization and/or allocation&lt;br /&gt;
        required to prepare the abstract data structure pointed at by &#039;to&#039;&lt;br /&gt;
        to be filled with &#039;n&#039; bytes of data from &#039;from&#039;.  It then executes&lt;br /&gt;
        the copy operation.&lt;br /&gt;
&lt;br /&gt;
        If, for example, there is not enough memory available to prepare&lt;br /&gt;
        the abstract data structure, the call is failed and FALSE is returned.&lt;br /&gt;
&lt;br /&gt;
        The buffer management scheme should be such that any memory needed&lt;br /&gt;
        to fulfill CopyToBuff() calls is already allocated from the system&lt;br /&gt;
        before the call to CopyToBuff() is made.&lt;br /&gt;
&lt;br /&gt;
   INPUTS&lt;br /&gt;
        to              - pointer to abstract structure to copy to.&lt;br /&gt;
        from            - pointer to contiguous memory to copy from.&lt;br /&gt;
        n               - number of bytes to copy.&lt;br /&gt;
&lt;br /&gt;
   RESULT&lt;br /&gt;
        success         - TRUE if operation was successful, else FALSE.&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        This function must be callable from interrupts.  In particular, this&lt;br /&gt;
        means that this function may not directly or indirectly call any&lt;br /&gt;
        system memory functions (since those functions rely on Forbid() to&lt;br /&gt;
        protect themselves) and that you must not compile this function&lt;br /&gt;
        with stack checking enabled.  See the Exec Interrupts&lt;br /&gt;
        chapter for more details on what is legal in a routine called from&lt;br /&gt;
        an interrupt handler.&lt;br /&gt;
&lt;br /&gt;
        &#039;C&#039; programmers should not compile with stack checking (option &#039;-v&#039;&lt;br /&gt;
        in SAS) and should geta4() or __saveds.&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== PacketFilter ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   NAME&lt;br /&gt;
        PacketFilter -- Perform filtering operation on CMD_READ&#039;s.&lt;br /&gt;
&lt;br /&gt;
   SYNOPSIS&lt;br /&gt;
        keep = PacketFilter(hook, ios2, data)&lt;br /&gt;
        d0                   a0    a2    a1&lt;br /&gt;
&lt;br /&gt;
        BOOL PacketFilter(struct Hook *, struct IOSana2Req *, APTR);&lt;br /&gt;
&lt;br /&gt;
   FUNCTION&lt;br /&gt;
        This function (if supplied by a protocol stack) may be used to&lt;br /&gt;
        reject packets before they are copied into a protocol stack&#039;s&lt;br /&gt;
        internal buffers.&lt;br /&gt;
&lt;br /&gt;
        The IOSana2Req structure should be set up to look (almost) exactly&lt;br /&gt;
        as it would if it was successfully returned for the current packet.&lt;br /&gt;
        Specifically, the fields that should be set up correctly are:&lt;br /&gt;
&lt;br /&gt;
        ios2-&amp;amp;gt;ios2_DataLength&lt;br /&gt;
        ios2-&amp;amp;gt;ios2_SrcAddr&lt;br /&gt;
        ios2-&amp;amp;gt;ios2_DstAddr&lt;br /&gt;
&lt;br /&gt;
       The &amp;amp;quot;data&amp;amp;quot; pointer must point to the beginning of the packet data&lt;br /&gt;
        that is stored in contiguous memory.  The data should NOT include&lt;br /&gt;
        any hardware specific headers (unless of course the CMD_READ&lt;br /&gt;
        request wanted RAW packets).&lt;br /&gt;
&lt;br /&gt;
   INPUTS&lt;br /&gt;
        hook            - pointer to the Hook originally supplied during&lt;br /&gt;
                          OpenDevice().&lt;br /&gt;
        ios2            - The IOSana2Req CMD_READ request that will be used&lt;br /&gt;
                          (the &amp;amp;quot;object&amp;amp;quot; of the Hook call).&lt;br /&gt;
        data            - The packet data (the &amp;amp;quot;message&amp;amp;quot; of the Hook call).&lt;br /&gt;
&lt;br /&gt;
   RESULT&lt;br /&gt;
        success         - TRUE if the driver should provide the packet to&lt;br /&gt;
                          the protocol stack, FALSE if the packet should be&lt;br /&gt;
                          ignored.&lt;br /&gt;
&lt;br /&gt;
   NOTES&lt;br /&gt;
        This function must be callable from interrupts.  In particular, this  &lt;br /&gt;
        means that this function may not directly or indirectly call any&lt;br /&gt;
        system memory functions (since those functions rely on Forbid() to&lt;br /&gt;
        protect themselves) and that  you must not compile this function&lt;br /&gt;
        with stack checking enabled.  See the Exec Interrupts&lt;br /&gt;
        chapter for more details on what is legal in a routine called from&lt;br /&gt;
        an interrupt handler.&lt;br /&gt;
&lt;br /&gt;
        &#039;C&#039; programmers should not compile with stack checking (option &#039;-v&#039;&lt;br /&gt;
        in SAS) and should geta4() or __saveds.&lt;br /&gt;
&lt;br /&gt;
        What does packet filtering do? With the original ``SANA-II Network&lt;br /&gt;
        Device Driver Specification&#039;&#039;, a protocol stack could open a device&lt;br /&gt;
        and ask for certain packet types. It got all the packets that matched&lt;br /&gt;
        this type. As it turned out, this could be mighty inefficient if there&lt;br /&gt;
        were packets that the protocol stack did not use at all. These would&lt;br /&gt;
        go into read processing of the protocol stack and waste CPU time even&lt;br /&gt;
        though they could have been easily identified on arrival.&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Ethernet description =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;#define S2WireType_Ethernet             1&lt;br /&gt;
&lt;br /&gt;
ios2_DataLength:&lt;br /&gt;
        valid ethernet packets have 64 to 1500 bytes of data.&lt;br /&gt;
&lt;br /&gt;
Address format:&lt;br /&gt;
        Ethernet addresses consist of 47 bits of address information and&lt;br /&gt;
        a 1 bit multicast flag. The standard for expressing ethernet&lt;br /&gt;
        addresses is as 6 bytes (octets) in the order in which the bytes&lt;br /&gt;
        are transmitted with the low-order bits in a byte transmitted&lt;br /&gt;
        first. The multicast flag bit is the least-significant bit of the&lt;br /&gt;
        first byte.&lt;br /&gt;
&lt;br /&gt;
        Ethernet addresses in a Sana2IOReq occupy the first 6 bytes of&lt;br /&gt;
        an address field in transmission order with the low-order bits in&lt;br /&gt;
        a byte transmitted first.&lt;br /&gt;
&lt;br /&gt;
Station Address:&lt;br /&gt;
        Each ethernet board must have a unique ethernet hardware address.&lt;br /&gt;
        Drivers will override any attempt to set the address to anything&lt;br /&gt;
        other than the ROM address.&lt;br /&gt;
&lt;br /&gt;
Raw reads and writes:&lt;br /&gt;
        6 bytes of destination address,&lt;br /&gt;
        6 bytes of source address,&lt;br /&gt;
        2 bytes of type,&lt;br /&gt;
        64 to 1500 bytes of data&lt;br /&gt;
        (followed by 4 byte CRC value covering all of the above&lt;br /&gt;
         which is hardware generated and checked, hence not included&lt;br /&gt;
         in even raw packets)&lt;br /&gt;
&lt;br /&gt;
Multicast:      Supported&lt;br /&gt;
&lt;br /&gt;
Broadcast:      Supported&lt;br /&gt;
&lt;br /&gt;
Promiscuous:    Supported&lt;br /&gt;
&lt;br /&gt;
Packet Type Numbers for Ethernet are assigned by:&lt;br /&gt;
&lt;br /&gt;
        Xerox Corporation&lt;br /&gt;
        Xerox Systems Institute&lt;br /&gt;
        475 Oakmead Parkway, Sunnyvale, CA 94086&lt;br /&gt;
        Attn: Ms. Fonda Pallone&lt;br /&gt;
        (408) 737-4652&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Some Common Packet Type Numbers:&lt;br /&gt;
&lt;br /&gt;
      decimal  Hex        Description&lt;br /&gt;
      -------  ---        -----------&lt;br /&gt;
         000   0000-05DC  IEEE 802.3 Length Field&lt;br /&gt;
        2048   0800       TCP/IP -- IP&lt;br /&gt;
        2054   0806       TCP/IP -- ARP&lt;br /&gt;
       32821   8035       TCP/IP -- RARP&lt;br /&gt;
       32923   809B       Appletalk&lt;br /&gt;
       33011   80F3       AppleTalk AARP (Kinetics)&lt;br /&gt;
       33100   814C       SNMP&lt;br /&gt;
       33079   8137-8138  Novell, Inc.&amp;lt;/pre&amp;gt;&lt;br /&gt;
= ARCNET description =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;S2WireType_Arcnet       7&lt;br /&gt;
&lt;br /&gt;
ios2_DataLength:&lt;br /&gt;
        506 byte MTU (because of the possibility of two byte Types).&lt;br /&gt;
        Packets of size 254, 255, or 256 bytes are padded to 257 bytes before&lt;br /&gt;
        transmition.&lt;br /&gt;
&lt;br /&gt;
Station Address:&lt;br /&gt;
        ARCNET hardware may have addresses set with jumpers, DIP switches&lt;br /&gt;
        or software.  Different drivers may therefore behave differently&lt;br /&gt;
        with S2_CONFIGINTERFACE.&lt;br /&gt;
&lt;br /&gt;
        Hardware addresses should be assigned by users from highest to lowest&lt;br /&gt;
        because there is some efficiency gained in the token passing scheme&lt;br /&gt;
        this way.  For example, on a three node network, hardware numbers 254,&lt;br /&gt;
        253 and 252 should be used rather than 1, 2 and 3.&lt;br /&gt;
&lt;br /&gt;
Raw reads and writes:&lt;br /&gt;
        Short Packets (1-253 bytes)&lt;br /&gt;
                Destination Address             (1 byte)&lt;br /&gt;
                Source Address                  (1 byte)&lt;br /&gt;
                Count (256-N-Type length)       (1 byte)&lt;br /&gt;
                Padding                         (to byte number Count)&lt;br /&gt;
                Type                            (1 or 2 bytes)&lt;br /&gt;
                Data                            (N bytes)&lt;br /&gt;
&lt;br /&gt;
        Long Packets (257-506 bytes)&lt;br /&gt;
                Destination Address             (1 byte)&lt;br /&gt;
                Source Address                  (1 byte)&lt;br /&gt;
                zero                            (1 byte)&lt;br /&gt;
                Count (512-N-Type length)       (1 byte)&lt;br /&gt;
                Padding                         (to byte number Count)&lt;br /&gt;
                Type                            (1 or 2 bytes)&lt;br /&gt;
                Data                            (N bytes)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Multicast:      Not Supported&lt;br /&gt;
&lt;br /&gt;
Broadcast:      Supported&lt;br /&gt;
&lt;br /&gt;
Promiscuous:    Generally Not Supported&lt;br /&gt;
&lt;br /&gt;
Packet Type Numbers for ARCNET are assigned by:&lt;br /&gt;
        Datapoint Corporation&lt;br /&gt;
&lt;br /&gt;
Some Common Packet Type Numbers&lt;br /&gt;
&lt;br /&gt;
        decimal  hex    description&lt;br /&gt;
        -------  ---    -----------&lt;br /&gt;
        221      DD     AppleTalk&lt;br /&gt;
        240      F0     TCP/IP -- IP   (RFC 1051)&lt;br /&gt;
        241      F1     TCP/IP -- ARP  (RFC 1051)&lt;br /&gt;
        212      F0     TCP/IP    IP   (RFC 1201, proposed)&lt;br /&gt;
        213      F1     TCP/IP -- ARP  (RFC 1201, proposed)&lt;br /&gt;
        214      D6     TCP/IP -- RARP (RFC 1201, proposed)&lt;br /&gt;
        247      F7     Banyan Vines&lt;br /&gt;
        250      FA     Novell IPX&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Authors =&lt;br /&gt;
&lt;br /&gt;
== Revision 2 &amp;amp; 3 ==&lt;br /&gt;
&lt;br /&gt;
Copyright © 1992-2000 Amiga, Inc. All Rights Reserved&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Amiga is a registered trademark of Amiga, Inc. Ethernet is a trademark of Xerox Corporation. ARCNET is a trademark of Datapoint Corporation. DECNet is a trademark of Digital Equipment Corporation. AppleTalk is a trademark of Apple Computer, Inc.&lt;br /&gt;
&lt;br /&gt;
== Revision 4 ==&lt;br /&gt;
&lt;br /&gt;
Extending the SANA-II network driver specification&amp;lt;br /&amp;gt;&lt;br /&gt;
by Olaf Barthel&lt;br /&gt;
&lt;br /&gt;
(Last updated 02-Mar-2003)&lt;br /&gt;
&lt;br /&gt;
== Revision 5 ==&lt;br /&gt;
&lt;br /&gt;
Hook-based callback function extensions for SANA-II (SANA-IIR5) &amp;lt;br /&amp;gt;&lt;br /&gt;
by Olaf Barthel and Heinz Wrobel&lt;br /&gt;
&lt;br /&gt;
== Revision 6 ==&lt;br /&gt;
&lt;br /&gt;
SANA-II IEEE 802.11 wireless API &amp;lt;br/&amp;gt;&lt;br /&gt;
by Neil Cafferkey&lt;br /&gt;
&lt;br /&gt;
= Acknowledgments =&lt;br /&gt;
&lt;br /&gt;
== Revision 2 &amp;amp; 3 ==&lt;br /&gt;
&lt;br /&gt;
Many people and companies have contributed to the &amp;quot;SANA-II Network Device Driver Specification&amp;quot;. The original SANA-II Autodocs and includes were put together by Ray Brand, Perry Kivolowitz (ASDG) and Martin Hunt. Those original documents evolved to their current state and grew to include this document at the hands of Dale Larson and Greg Miller. Brian Jackson and John Orr provided valuable editing. Randell Jesup has provided sage advice on several occasions. The buffer management callback mechanism was his idea. Dale Luck (GfxBase) and Rick Spanbauer (Ameristar Technologies) have provided valuable comments throughout the process. Nicolas Benezan (ADONIS) provided many detailed and useful comments on weaknesses in late drafts of the specification. The enhancements for better buffer management, clarifications and notes for device implementers were added to the specification by Heinz Wrobel whilst consulting for Amiga Technologies GmbH, yielding revision 3.0 of the specification.&lt;br /&gt;
&lt;br /&gt;
Thanks to all the above and the numerous others who have contributed with their comments, questions and discussions.&lt;br /&gt;
&lt;br /&gt;
= Changes =&lt;br /&gt;
&lt;br /&gt;
== Revision 4 ==&lt;br /&gt;
&lt;br /&gt;
Changes since 24-Dec-2002:&lt;br /&gt;
&lt;br /&gt;
* The &amp;lt;tt&amp;gt;Sana2Connection&amp;lt;/tt&amp;gt; data structure used by the &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt; command now must remain valid until the &amp;lt;tt&amp;gt;S2_DISCONNECT&amp;lt;/tt&amp;gt; command is sent (see [[#2.4|section 2.4]]).&lt;br /&gt;
&lt;br /&gt;
Changes since 01-May-2002:&lt;br /&gt;
&lt;br /&gt;
* Added the &amp;lt;tt&amp;gt;ppp.async.readrequests&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;ppp.async.eof&amp;lt;/tt&amp;gt; configuration keywords.&lt;br /&gt;
&lt;br /&gt;
Changes since 04-Jan-2002:&lt;br /&gt;
&lt;br /&gt;
* Added the &amp;lt;tt&amp;gt;ppp.dummyremoteaddress&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;ppp.ethernet.ac&amp;lt;/tt&amp;gt; configuration keywords.&lt;br /&gt;
&lt;br /&gt;
Changes since 10-Dec-2001:&lt;br /&gt;
&lt;br /&gt;
* Converted to HTML format.&lt;br /&gt;
* Added the &amp;lt;tt&amp;gt;&amp;amp;lt;devices/sana2.h&amp;amp;gt;&amp;lt;/tt&amp;gt; header file to the appendix.&lt;br /&gt;
* The memory alignment for the &amp;lt;tt&amp;gt;S2_DMACopyToBuff64&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2_DMACopyFromBuff64&amp;lt;/tt&amp;gt; hooks refers to bits and not to bytes.&lt;br /&gt;
&lt;br /&gt;
Changes since 19-Nov-2001:&lt;br /&gt;
&lt;br /&gt;
* Added to the list of reserved configuration keywords (&amp;lt;tt&amp;gt;ppp.idletimeout&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ppp.peeridletimeout&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;ppp.sendid&amp;lt;/tt&amp;gt;).&lt;br /&gt;
* Renamed the fields of the &amp;lt;tt&amp;gt;Sana2ExtDeviceStats&amp;lt;/tt&amp;gt; structure.&lt;br /&gt;
* Clarified that the &amp;lt;tt&amp;gt;S2QUAD&amp;lt;/tt&amp;gt; type is a big endian integer.&lt;br /&gt;
* More clarifications for the &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;S2_DISCONNECT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2_ONLINE&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;S2_OFFLINE&amp;lt;/tt&amp;gt; commands.&lt;br /&gt;
* Updated the discussion of the &amp;lt;tt&amp;gt;Sana2DeviceQuery.RawMTU&amp;lt;/tt&amp;gt; field, clarifying what is included in the the Ethernet &amp;lt;tt&amp;gt;RawMTU&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* Updated the &amp;lt;tt&amp;gt;&amp;amp;lt;devices/sana2.h&amp;amp;gt;&amp;lt;/tt&amp;gt; header file. Note that there is no equivalent &amp;lt;tt&amp;gt;&amp;amp;quot;devices/sana2.i&amp;amp;quot;&amp;lt;/tt&amp;gt; header file yet.&lt;br /&gt;
&lt;br /&gt;
Changes since 12-Nov-2001:&lt;br /&gt;
&lt;br /&gt;
* Changed the command numbers of &amp;lt;tt&amp;gt;S2_GETPEERADDRESS&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;S2_GETDNSADDRESS&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;S2_GETEXTENDEDGLOBALSTATS&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;S2_DISCONNECT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2_SAMPLE_THROUGHPUT&amp;lt;/tt&amp;gt; to be NSD-compliant. Also assigned a new number to the &amp;lt;tt&amp;gt;S2_SAMPLE_THROUGHPUT &amp;lt;/tt&amp;gt; command.&lt;br /&gt;
* Added section 4 (&amp;amp;quot;Extensions for existing commands&amp;amp;quot;).&lt;br /&gt;
* Added the last paragraph to section 9, relating to the future extension of the &amp;lt;tt&amp;gt;Sana2DeviceQuery&amp;lt;/tt&amp;gt; structure.&lt;br /&gt;
&lt;br /&gt;
Changes since 03-Nov-2001:&lt;br /&gt;
&lt;br /&gt;
* Renamed &amp;lt;tt&amp;gt;S2_GETNEWGLOBALSTATS&amp;lt;/tt&amp;gt; to &amp;lt;tt&amp;gt;S2_GETEXTENDEDGLOBALSTATS&amp;lt;/tt&amp;gt; (see [[#2.3|section 2.3]]).&lt;br /&gt;
* The &amp;lt;tt&amp;gt;S2_GETEXTENDEDGLOBALSTATS&amp;lt;/tt&amp;gt; now uses 64 bit quantities for the &amp;lt;tt&amp;gt;s2xds_PacketsReceived&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;s2xds_PacketsSent&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;s2xds_BadData&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;s2xds_Overruns&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;s2xds_UnknownTypesReceived&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;s2xds_Reconfigurations&amp;lt;/tt&amp;gt; counters.&lt;br /&gt;
* In section 2.6 the &amp;lt;tt&amp;gt;S2_SAMPLE_THROUGHPUT&amp;lt;/tt&amp;gt; command was modified to use 64 bit integers for all members of the &amp;lt;tt&amp;gt;Sana2ThroughputStats&amp;lt;/tt&amp;gt; structure.&lt;br /&gt;
* All proposed commands are now listed with their numeric IDs.&lt;br /&gt;
* The command autodocs specifically mention the &amp;lt;tt&amp;gt;ios2_BufferManagement&amp;lt;/tt&amp;gt; field.&lt;br /&gt;
* All references to &amp;lt;tt&amp;gt;ios2_Error&amp;lt;/tt&amp;gt; have been replaced with &amp;lt;tt&amp;gt;ios2_Req.io_Error&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* In section 7 the use of the &amp;lt;tt&amp;gt;IOERR_NOCMD&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;S2ERR_NOT_SUPPORTED&amp;lt;/tt&amp;gt; error codes is clarified.&lt;br /&gt;
* Section 7 takes a more detailed look at safe default values returned by the query commands.&lt;br /&gt;
* Inserted section 3 (&amp;amp;quot;Annotations for existing commands&amp;amp;quot;).&lt;br /&gt;
* The &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2_DISCONNECT&amp;lt;/tt&amp;gt; commands now specifically mention the life time of the data they have to deal with.&lt;br /&gt;
&lt;br /&gt;
Changes since 14-Oct-2001:&lt;br /&gt;
&lt;br /&gt;
* Added &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2_DISCONNECT&amp;lt;/tt&amp;gt; commands.&lt;br /&gt;
* Added &amp;lt;tt&amp;gt;S2EVENT_CONNECT&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;S2EVENT_DISCONNECT&amp;lt;/tt&amp;gt; events.&lt;br /&gt;
* Added section 4 (&amp;amp;quot;New wire error codes&amp;amp;quot;).&lt;br /&gt;
* In section 5.2 the originally proposed log callback function has been wrapped into a standard Hook structure.&lt;br /&gt;
* Removed item on &amp;lt;tt&amp;gt;S2_CONNECT&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;S2_DISCONNECT&amp;lt;/tt&amp;gt; from section 7 (&amp;amp;quot;Unsolved problems&amp;amp;quot;).&lt;br /&gt;
* Added section 8 (&amp;amp;quot;Changes&amp;amp;quot;).&lt;br /&gt;
&lt;br /&gt;
== Revision 5 ==&lt;br /&gt;
&lt;br /&gt;
22-Mar-2004:&lt;br /&gt;
&lt;br /&gt;
* Conversion to HTML&lt;br /&gt;
&lt;br /&gt;
21-Jan-2004:&lt;br /&gt;
&lt;br /&gt;
* Added clarifications for &amp;lt;tt&amp;gt;schm_MsgSize&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;slhm_MsgSize&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;slhm_Priority&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;slhm_Name&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;slhm_Message&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;s2h_Hook&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* Updated the &amp;lt;tt&amp;gt;S2_SANA2HOOK&amp;lt;/tt&amp;gt; documentation.&lt;br /&gt;
* Shortened section 4.&lt;br /&gt;
* Updated section 5.&lt;br /&gt;
&lt;br /&gt;
30-Nov-2003:&lt;br /&gt;
&lt;br /&gt;
* Extended the applicability of the &amp;lt;tt&amp;gt;Hook&amp;lt;/tt&amp;gt; to logging.&lt;br /&gt;
* Renamed &amp;lt;tt&amp;gt;S2_COPYHOOK&amp;lt;/tt&amp;gt; to &amp;lt;tt&amp;gt;S2_SANA2HOOK&amp;lt;/tt&amp;gt;, which matches the extended scope it should cover.&lt;br /&gt;
* The message passed to the &amp;lt;tt&amp;gt;Hook&amp;lt;/tt&amp;gt; now includes a size field which holds the size of the message, expressed in bytes.&lt;br /&gt;
&lt;br /&gt;
06-Oct-2003:&lt;br /&gt;
&lt;br /&gt;
* Replaced the list of new tag items with a single &amp;lt;tt&amp;gt;Hook&amp;lt;/tt&amp;gt;, which is installed through a new command.&lt;br /&gt;
* Added &amp;amp;quot;Caveats&amp;amp;quot; and &amp;amp;quot;Changes&amp;amp;quot; sections&lt;br /&gt;
* Removed the documentation for the originally proposed &amp;lt;tt&amp;gt;TagItem&amp;lt;/tt&amp;gt; (sections 3.2.1 through 3.2.10)&lt;br /&gt;
&lt;br /&gt;
= History =&lt;br /&gt;
&lt;br /&gt;
== Revision 2 and 3 ==&lt;br /&gt;
&lt;br /&gt;
This standard has undergone several drafts with long periods for comment from developers and the Amiga community at large. These drafts include a UseNet release which was also distributed on the Fish Disks in June, 1991 (as well as published in the &#039;91 DevCon notes), and the November 7 Draft for Final Comment and Approval distributed via Bix, ADSP and UseNet. There were also several intermediate drafts with more limited distribution.&lt;br /&gt;
&lt;br /&gt;
== Revision 4 ==&lt;br /&gt;
&lt;br /&gt;
(Olaf Barthel)&lt;br /&gt;
&lt;br /&gt;
I&#039;ve been working on a TCP/IP stack and PPP drivers to go with them for a while and found that there were some things that SANA-II did specifically not address, and which ought to be covered by it. In other areas clarification was needed. Also, discussions I had with Harald Frank suggested that the extensions made by Heinz Wrobel and Stefan Sticht in the SANA-IIR3 specification could need extending.&lt;/div&gt;</summary>
		<author><name>Costel Mincea</name></author>
	</entry>
	<entry>
		<id>https://wiki.amigaos.net/w/index.php?title=Layers_Library&amp;diff=12561</id>
		<title>Layers Library</title>
		<link rel="alternate" type="text/html" href="https://wiki.amigaos.net/w/index.php?title=Layers_Library&amp;diff=12561"/>
		<updated>2025-01-26T19:34:52Z</updated>

		<summary type="html">&lt;p&gt;Costel Mincea: Text replacement - &amp;quot;&amp;lt;syntaxhighlight&amp;gt;&amp;quot; to &amp;quot;&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{WIP}}&lt;br /&gt;
== Layers Library ==&lt;br /&gt;
&lt;br /&gt;
This article describes the layers library which provides routines that are used to manage overlapping rectangular drawing areas that share a common display. Intuition uses the layers library to manage its system of windows.&lt;br /&gt;
&lt;br /&gt;
The Graphics Library describes the use of &#039;&#039;regions&#039;&#039;, special structures used to mask off areas where drawing can take place. Regions are installed through the layers library function InstallClipRegion() but the routines for the creation, disposal and manipulation of regions are part of the graphics library.&lt;br /&gt;
&lt;br /&gt;
== Layers ==&lt;br /&gt;
&lt;br /&gt;
The concept of a &#039;&#039;layer&#039;&#039; is closely tied to Intuition windows. A layer is a rectangular drawing area. A layer can overlap other layers and has a display priority that determines whether it will appear in front or behind other layers. Every Intuition window has an associated Layer structure. Layers allow Intuition and application programs to :&lt;br /&gt;
&lt;br /&gt;
* Share a display&#039;s BitMap among various tasks in an orderly way by creating layers, separate drawing rectangles, within the BitMap.&lt;br /&gt;
* Move, size or depth-arrange a layer while automatically keeping track of which portions of other layers are hidden or revealed by the operation.&lt;br /&gt;
* Manage the remapping of coordinates, so the application need not track the layer&#039;s offset into the BitMap.&lt;br /&gt;
* Maintain each layer as a separate entity, which may optionally have its own BitMap.&lt;br /&gt;
* Automatically update same newly visible portions.&lt;br /&gt;
&lt;br /&gt;
The layers library takes care of housekeeping: the low level, repetitive tasks which are required to keep track of where to place bits. The layers library also provides a locking mechanism which coordinates display updating when multiple tasks are drawing graphics to layers. The windowing environment provided by the Intuition library is largely based on layers.&lt;br /&gt;
&lt;br /&gt;
{{Note|title=WARNING|text=Layers may not be created or used directly with Intuition screens. Intuition windows are the only supported method of adding layers to Intuition screens. &#039;&#039;Only&#039;&#039; the layer locking and unlocking functions are safe to use with Intuition. An application must create and manage its own View if it will be creating layers directly on the display.}}&lt;br /&gt;
&lt;br /&gt;
=== The Layer Structure ===&lt;br /&gt;
&lt;br /&gt;
The internal representation of layers is essentially a set of clipping rectangles. Each layer is represented by an instance of the Layer structure. All the layers in a display are linked together through the Layer_Info structure. Any display shared by multiple layers (such as an Intuition screen) requires one Layer_Info data structure to handle interactions between the various layers.&lt;br /&gt;
&lt;br /&gt;
Here is a partial listing of the Layer structure from &amp;amp;lt;graphics/clip.h&amp;amp;gt;. (For a complete listing refer to the SDK.)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct Layer&lt;br /&gt;
{&lt;br /&gt;
    struct  Layer *front,*back;&lt;br /&gt;
    struct  ClipRect    *ClipRect;  /* read by ROMs to find first cliprect */&lt;br /&gt;
    struct  RastPort    *rp;&lt;br /&gt;
    struct  Rectangle   bounds;&lt;br /&gt;
      ...&lt;br /&gt;
&lt;br /&gt;
    UWORD   Flags;                  /* obscured ?, Virtual BitMap? */&lt;br /&gt;
    struct  BitMap *SuperBitMap;&lt;br /&gt;
      ...&lt;br /&gt;
&lt;br /&gt;
    struct  Region  *DamageList;    /* list of rectangles to refresh through */&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Note|title=The Layer Structure is Read-Only|text=Applications should never directly modify any of the elements of the Layer structure. In addition, applications should only read the front, back, rp, bounds, Flags, SuperBitMap and DamageList elements of the Layer structure. (Some of these elements are subject to dynamic change by the system so proper layer locking procedures must be followed when relying on what the application has read.)}}&lt;br /&gt;
&lt;br /&gt;
=== The Layer&#039;s RastPort ===&lt;br /&gt;
&lt;br /&gt;
When a layer is created, a RastPort is automatically to go along with it. The pointer to the RastPort is contained in the layer data structure. Using this RastPort, the application may draw anywhere into the layer&#039;s bounds rectangle. If the application tries to draw outside of this rectangle, the graphics routines will clip the graphics.&lt;br /&gt;
&lt;br /&gt;
Here is sample code showing how to access the layer&#039;s RastPort:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct RastPort *myRPort;    /* allocate a RastPort pointer for each layer */&lt;br /&gt;
&lt;br /&gt;
myRPort = layer-&amp;gt;rp;&lt;br /&gt;
&lt;br /&gt;
/* The layer&#039;s RastPort may be used with any of the graphics library calls&lt;br /&gt;
** that require this structure.  For instance, to fill layer with color:&lt;br /&gt;
*/&lt;br /&gt;
IGraphics-&amp;gt;SetRast(layer-&amp;gt;rp, color);&lt;br /&gt;
&lt;br /&gt;
/* set up for writing text into layer */&lt;br /&gt;
IGraphics-&amp;gt;SetDrMd(layer-&amp;gt;rp, JAM1);&lt;br /&gt;
IGraphics-&amp;gt;SetAPen(layer-&amp;gt;rp, 0);&lt;br /&gt;
IGraphics-&amp;gt;Move(layer-&amp;gt;rp, 5, 7);&lt;br /&gt;
&lt;br /&gt;
/* write into layer */&lt;br /&gt;
IGraphics-&amp;gt;Text(layer-&amp;gt;rp, string, strlen(string));&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Types of Layers ===&lt;br /&gt;
&lt;br /&gt;
The layers library supports three types of layers: simple refresh, smart refresh and super bitmap. The type of the layer, specified by the Flags field in the Layers structure, determines what facilities the layer provides.&lt;br /&gt;
&lt;br /&gt;
{{Note|title=Use Only One Layer Type Flag|text=The three layer-type Flags are mutually exclusive. That is, only one layer-type flag (LAYERSIMPLE, LAYERSMART and LAYERSUPER) should be specified.}}&lt;br /&gt;
&lt;br /&gt;
==== Simple Refresh Layer ====&lt;br /&gt;
&lt;br /&gt;
When an application draws into the layer, any portion of the layer that is visible (not obscured) will be rendered into the common BitMap of the viewing area. All graphics rendering routines are &amp;quot;clipped&amp;quot; so that only exposed sections of the layer are drawn into. No back-up of obscured areas is provided.&lt;br /&gt;
&lt;br /&gt;
If another layer operation is performed that causes an obscured part of a simple refresh layer to be exposed, the application must determine if the section need be refreshed, re-drawing the newly exposed part of the layer as required.&lt;br /&gt;
&lt;br /&gt;
The basic advantage of simple refresh is that it does not require back-up area to save drawing sections that cannot be seen, saving memory. However, the application needs to monitor the layer to see if it needs refreshing. This is typically performed with statements like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
if (layer-&amp;gt;Flags &amp;amp; LAYERREFRESH)&lt;br /&gt;
    refresh(layer);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When an application restores the layer by performing a full-layer redraw, only the damaged areas are redrawn, making the operation fairly time efficient.&lt;br /&gt;
&lt;br /&gt;
==== Smart Refresh Layer ====&lt;br /&gt;
&lt;br /&gt;
Under smart refresh, the system provides dynamic backup of obscured sections of the layer. The graphics routines will automatically draw into these backup areas when they encounter an obscured part of the layer. The backup memory will be used to automatically update the display when obscured sections later become exposed.&lt;br /&gt;
&lt;br /&gt;
With smart refresh layers, the system handles all of the refresh requirements of the layer, except when the layer is made larger. When parts of the layer are exposed by a sizing operation, the application must refresh the newly exposed areas.&lt;br /&gt;
&lt;br /&gt;
The advantage of smart refresh is the speed of updating exposed regions of the layer and the ability of the system to manage part of the updating process for the application.. Its main disadvantage is the additional memory required to handle this automatic refresh.&lt;br /&gt;
&lt;br /&gt;
==== Super Bitmap Layer ====&lt;br /&gt;
&lt;br /&gt;
A super bitmap layer is similar to a smart refresh layer. It too has a back-up area for rendering graphics for currently obscured parts of the display. Whenever an obscured area is made visible, the corresponding part of the backup area is copied to the display automatically.&lt;br /&gt;
&lt;br /&gt;
However, it differs from smart refresh in that:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;The back-up BitMap is user-supplied, rather than being allocated dynamically by the system.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;The back-up BitMap may be as large or larger than the the current size of the layer. It may also be larger than the maximum size of the layer.&amp;lt;/p&amp;gt;&amp;lt;/li&amp;gt;&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To see a larger portion of a super bitmap on-display, use SizeLayer(). To see a different portion of the super bitmap in the layer, use ScrollLayer().&lt;br /&gt;
&lt;br /&gt;
When the graphics routines perform drawing commands, part of the drawing appears in the common BitMap (the on-display portion). Any drawing outside the displayed portion itself is rendered into the super bitmap. When the layer is scrolled or sized, the layer contents are copied into the super bitmap, the scroll or size positioning is modified, and the appropriate portions are then copied back into the layer. (Refer to the graphics library functions SyncSBitMap() and CopySBitMap().&lt;br /&gt;
&lt;br /&gt;
==== Backdrop Layer ====&lt;br /&gt;
&lt;br /&gt;
A layer of any type may be designated a backdrop layer which will always appear behind all other layers. They may not be moved, sized, or depth-arranged. Non-backdrop layers will always remain in front of backdrop layers regardless of how the non-backdrop layer is moved, sized or depth-arranged.&lt;br /&gt;
&lt;br /&gt;
=== Opening the Layers Library ===&lt;br /&gt;
&lt;br /&gt;
Like all libraries, the layers library must be opened before it may be used. Check the Layers Autodocs to determine what version of the library is required for any particular Layers function.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/layers.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
struct Library *LayersBase = IExec-&amp;gt;OpenLibrary(&amp;quot;layers.library&amp;quot;, 50);&lt;br /&gt;
&lt;br /&gt;
struct LayersIFace *ILayers = (struct LayersIFace*)IExec-&amp;gt;GetInterface(LayersBase, &amp;quot;main&amp;quot;, 1, NULL);&lt;br /&gt;
&lt;br /&gt;
if (ILayers != NULL)&lt;br /&gt;
    {&lt;br /&gt;
    /* use Layers library */&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
IExec-&amp;gt;DropInterface((struct Interface*)ILayers);&lt;br /&gt;
IExec-&amp;gt;CloseLibrary(LayersBase);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Working With Existing Layers ===&lt;br /&gt;
&lt;br /&gt;
A common operation performed by applications is to render text or graphics into an existing layer such as an Intuition window. To prevent Intuition from changing the layer (for instance when the user resizes or moves the window) during a series of graphic operations, the layers library provides locking functions for obtaining exclusive access to a layer.&lt;br /&gt;
&lt;br /&gt;
These locking functions are also useful for applications that create their own layers if the application has more than one task operating on the layers asynchronously. These calls coordinate multiple access to layers.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Functions for Intertask Control of Layers (Layers Library)&lt;br /&gt;
| LockLayer()&lt;br /&gt;
| Lock out rendering in a single layer.&lt;br /&gt;
|-&lt;br /&gt;
| UnlockLayer()&lt;br /&gt;
| Release LockLayer() lock.&lt;br /&gt;
|-&lt;br /&gt;
| LockLayers()&lt;br /&gt;
| Lock out rendering in all layers of a display.&lt;br /&gt;
|-&lt;br /&gt;
| UnlockLayers()&lt;br /&gt;
| Release LockLayers() lock.&lt;br /&gt;
|-&lt;br /&gt;
| LockLayerInfo()&lt;br /&gt;
| Gain exclusive access to the display&#039;s layers.&lt;br /&gt;
|-&lt;br /&gt;
| UnlockLayerInfo()&lt;br /&gt;
| Release LockLayerInfo() lock.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The following routines from the graphics library also allow multitasking access to layer structures:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Functions for Intertask Control of Layers (Graphics Library)&lt;br /&gt;
| LockLayerRom()&lt;br /&gt;
| Same as LockLayer(), from layers library.&lt;br /&gt;
|-&lt;br /&gt;
| UnlockLayerRom()&lt;br /&gt;
| Release LockLayerRom() lock.&lt;br /&gt;
|-&lt;br /&gt;
| AttemptLockLayerRom()&lt;br /&gt;
| Lock layer only if it is immediately available.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
These functions are similar to the layers LockLayer() and UnlockLayer() functions, but do not require the layers library to be open. See the SDK for details.&lt;br /&gt;
&lt;br /&gt;
==== Intertask Operations ====&lt;br /&gt;
&lt;br /&gt;
If multiple tasks are manipulating layers on the same display they will be sharing a Layer_Info structure and their use of it and its related data structures need to be coordinated. To ensure that a structure remains cohesive, it should be operated on by only one task at a time. The Layer_Info encompasses all the layers existing on a single display.&lt;br /&gt;
&lt;br /&gt;
LockLayerInfo() must be called whenever the visible portions of layers may be affected, or when the Layer_Info structure is changed.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
VOID LockLayerInfo( struct Layer_Info *li );&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The lock should be obtained whenever a layer is created, deleted sized or moved, as the list of layers that is being managed by the Layer_Info data structure must be updated.&lt;br /&gt;
&lt;br /&gt;
It is not necessary to lock the Layer_Info data structure while rendering, or when calling routines like ScrollLayer(), because layer sizes and on-display positions are not being affected.&lt;br /&gt;
&lt;br /&gt;
Use UnlockLayerInfo() when you have finished the layer operation:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
VOID UnlockLayerInfo( struct Layer_Info *li );&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you don&#039;t unlock the Layer_Info then any other task calling LockLayerInfo() on the same Layer_Info structure will be blocked creating a potential deadlock situation.&lt;br /&gt;
&lt;br /&gt;
In addition to locking the Layer_Info structure, the layer itself should be locked if it is shared between tasks so that only one task at a time renders graphics to it. LockLayer() is used to get exclusive graphics output to a layer.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
VOID LockLayer( long dummy, struct Layer *layer );&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If a graphics function is in process, the lock will return when the function is completed. Other tasks are blocked only if they attempt to draw graphics into this layer, or try to obtain a lock on this layer. The MoveLayer(), SizeLayer() and ScrollLayer() functions automatically lock and unlock the layer they operate on.&lt;br /&gt;
&lt;br /&gt;
UnlockLayer() should be used after the graphics operation to make the layer available to other tasks again.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
VOID UnlockLayer( struct Layer *layer );&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If more than one layer must be locked, then the LockLayer() calls should be surrounded by LockLayerInfo() and UnlockLayerInfo() calls, to prevent deadlock situations.&lt;br /&gt;
&lt;br /&gt;
The layers library provides two additional functions, LockLayers() and UnlockLayers(), for locking multiple layers.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
VOID LockLayers( struct Layer_Info *li );&lt;br /&gt;
VOID UnlockLayers( struct Layer_Info *li );&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
LockLayers() is used to lock all layers in a single command. UnlockLayers() releases the layers lock. The system calls these routines during the BehindLayer(), UpfrontLayer() and MoveLayerInFrontOf() operations (described below).&lt;br /&gt;
&lt;br /&gt;
==== Determining Layer Position ====&lt;br /&gt;
&lt;br /&gt;
If the viewing area has been separated into several layers, the application may need to find out which layer is topmost at a particular &#039;&#039;x,y&#039;&#039; coordinate. Use the WhichLayer() function for this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct Layer *WhichLayer( struct Layer_Info *li, int32 x, int32 y );&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To be sure that no task adds, deletes, or changes the sequence of layers before this information is used, call LockLayerInfo() before calling WhichLayer(), and call UnlockLayerInfo() when the operation is complete. In this way, the program may ensure that it is acting on valid information. Always check for a NULL return value (coordinate not in a layer) from WhichLayer().&lt;br /&gt;
&lt;br /&gt;
=== Creating and Using New Layers ===&lt;br /&gt;
&lt;br /&gt;
The functions described in this section are generally not safe to use with Intuition. To create new layers for Intuition you use Intuition window calls (see [[Intuition_Windows|Intuition Windows]]).&lt;br /&gt;
&lt;br /&gt;
Only applications that create and mange their own View will be able to call the layer creation and updating functions discussed here.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Functions for Creating and Updating Layers&lt;br /&gt;
| NewLayerInfo() || Allocating a Layer_Info structure.&lt;br /&gt;
|-&lt;br /&gt;
| DisposeLayerInfo() || Deallocating a Layer_Info structure.&lt;br /&gt;
|-&lt;br /&gt;
| CreateUpfrontLayer() || Make a new layer in front of others.&lt;br /&gt;
|-&lt;br /&gt;
| CreateBehindLayer() || Make a new layer behind others.&lt;br /&gt;
|-&lt;br /&gt;
| DeleteLayer() || Remove and delete an existing layer.&lt;br /&gt;
|-&lt;br /&gt;
| MoveLayer() || Change the position (not depth) of a layer.&lt;br /&gt;
|-&lt;br /&gt;
| SizeLayer() || Change the size of a layer.&lt;br /&gt;
|-&lt;br /&gt;
| ScrollLayer() || Change the internal coordinates of a layer.&lt;br /&gt;
|-&lt;br /&gt;
| BehindLayer() || Depth arrange a layer behind others.&lt;br /&gt;
|-&lt;br /&gt;
| UpfrontLayer() || Depth arrange a layer in front of others.&lt;br /&gt;
|-&lt;br /&gt;
| MoveLayerInFrontOf() || Depth arrange a layer to a specific position.&lt;br /&gt;
|-&lt;br /&gt;
| SwapBitsRastPortClipRect() || Fast, non-layered and non-damaging display operation.&lt;br /&gt;
|-&lt;br /&gt;
| BeginUpdate() || Synchronize optimized refreshing for layer.&lt;br /&gt;
|-&lt;br /&gt;
| EndUpdate() || End optimized layer refresh.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Creating a Viewing Workspace ====&lt;br /&gt;
&lt;br /&gt;
A viewing workspace may be created by using the primitives InitVPort(), InitView(), MakeVPort(), MrgCop(), and LoadView(). Please reference [[Graphics_Primitives|Graphics Primitives]] for details on creating a low-level graphics display. Do not create Layers directly on Intuition screens. Windows are the only supported method of creating a layer on a screen.&lt;br /&gt;
&lt;br /&gt;
==== Creating the Layers ====&lt;br /&gt;
&lt;br /&gt;
The application must first allocate and initialize a Layer_Info data structure which the system uses to keep track of layers that are created, use statements like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct Layer_Info *theLayerInfo;&lt;br /&gt;
&lt;br /&gt;
if (NULL != (theLayerInfo = ILayers-&amp;gt;NewLayerInfo()))&lt;br /&gt;
    {&lt;br /&gt;
    /* use Layer_Info */&lt;br /&gt;
&lt;br /&gt;
    ILayers-&amp;gt;DisposeLayerInfo(theLayerInfo);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Layers may be created in the common bit map by calling CreateUpfrontLayer() or CreateBehindLayer(), with a sequence such as the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct Layer      *layer;&lt;br /&gt;
struct Layer_Info *theLayerInfo;&lt;br /&gt;
struct BitMap     *theBitMap;&lt;br /&gt;
&lt;br /&gt;
/* requests construction of a smart refresh layer. */&lt;br /&gt;
if (NULL == (layer = ILayers-&amp;gt;CreateUpfrontLayer(theLayerInfo, theBitMap, 20, 20, 100, 80, LAYERSMART, NULL)))&lt;br /&gt;
    error(&amp;quot;CreateUpfrontLayer() failed.&amp;quot;);&lt;br /&gt;
else&lt;br /&gt;
    {&lt;br /&gt;
    ; /* layer successfully created here. */&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Allocating and Deallocating Layer_Info ====&lt;br /&gt;
&lt;br /&gt;
Use NewLayerInfo() to allocate and initialize a Layer_Info structure and associated sub-structures.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct Layer_Info *NewLayerInfo( VOID );&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You &#039;&#039;must&#039;&#039; call this function before attempting to use any of the other layers functions described below. When you have finished with a Layer_Info structure, use DisposeLayerInfo() to deallocate it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
VOID DisposeLayerInfo( struct Layer_Info *li );&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This function deallocates a Layer_Info and associated structures previously allocated with NewLayerInfo().&lt;br /&gt;
&lt;br /&gt;
==== Allocating and Deallocating Layers ====&lt;br /&gt;
&lt;br /&gt;
Layers are created using the routines CreateUpfrontLayer() and CreateBehindLayer(). CreateUpfrontLayer() creates a layer that will appear in front of any existing layers.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct Layer *CreateUpfrontLayer( struct Layer_Info *li, struct BitMap *bm, int32 x0, int32 y0, int32 x1, int32 y1, int32 flags, struct BitMap *bm2 );&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
CreateBehindLayer() creates a layer that appears behind existing layers, but in front of backdrop layers.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct Layer *CreateBehindLayer( struct Layer_Info *li, struct BitMap *bm, int32 x0, int32 y0, int32 x1, int32 y1, int32 flags, struct BitMap *bm2 );&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Both of these routines return a pointer to a Layer data structure (as defined in the include file &amp;amp;lt;graphics/layers.h&amp;amp;gt;), or NULL if the operation was unsuccessful.&lt;br /&gt;
&lt;br /&gt;
{{Note|title=A New Layer Also Gets a RastPort|text=When a layer is created, the routine automatically creates a RastPort to go along with it. If the layer&#039;s RastPort is passed to the drawing routines, drawing will be restricted to the layer. See &amp;quot;The Layer&#039;s RastPort&amp;quot; section above.}}&lt;br /&gt;
&lt;br /&gt;
Use the DeleteLayer() call to remove a layer:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
int32 DeleteLayer( int32 dummy, struct Layer *layer );&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
DeleteLayer() removes a layer from the layer list and frees the memory allocated by the layer creation calls listed above.&lt;br /&gt;
&lt;br /&gt;
==== Moving and Sizing Layers ====&lt;br /&gt;
&lt;br /&gt;
The layers library includes three functions for moving and sizing layers:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
int32 MoveLayer( int32 dummy, struct Layer *layer, int32 dx, int32 dy );&lt;br /&gt;
int32 SizeLayer( int32 dummy, struct Layer *layer, int32 dx, int32 dy );&lt;br /&gt;
int32 MoveSizeLayer( struct Layer *layer, int32 dx, int32 dy, int32 dw, int32 dh);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MoveLayer() moves a layer to a new position relative to its current position. SizeLayer() changes the size of a layer by modifying the coordinates of the lower right corner of the layer. MoveSizeLayer() changes both the size and position of a layer in a single call.&lt;br /&gt;
&lt;br /&gt;
==== Changing a Viewpoint ====&lt;br /&gt;
&lt;br /&gt;
The ScrollLayer() function changes the portion of a super bitmap that is shown by a layer:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
VOID ScrollLayer( int32 dummy, struct Layer *layer, int32 dx, int32 dy );&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This function is most useful with super bitmap layers but can also simulate the effect on other layer types by adding the scroll offset to all future rendering.&lt;br /&gt;
&lt;br /&gt;
==== Reordering Layers ====&lt;br /&gt;
&lt;br /&gt;
The layers library provides three function calls for reordering layers:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
int32 BehindLayer ( int32 dummy, struct Layer *layer );&lt;br /&gt;
int32 UpfrontLayer( int32 dummy, struct Layer *layer );&lt;br /&gt;
int32 MoveLayerInFrontOf( struct Layer *layer_to_move, struct Layer *other_layer );&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
BehindLayer() moves a layer behind all other layers. This function considers any backdrop layers, moving a current layer behind all others except backdrop layers. UpfrontLayer() moves a layer in front of all other layers. MoveLayerInFrontOf() is used to place a layer at a specific depth, just in front of a given layer.&lt;br /&gt;
&lt;br /&gt;
As areas of simple refresh layers become exposed, due to layer movement or sizing for example, the newly exposed areas have not been drawn into, and need refreshing. The system keeps track of these areas by using a DamageList. To update only those areas that need it, the BeginUpdate() EndUpdate() functions are called.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
int32 BeginUpdate( struct Layer *l );&lt;br /&gt;
VOID EndUpdate  ( struct Layer *layer, uint32 flag );&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
BeginUpdate() saves the pointer to the current clipping rectangles and installs a pointer to a set of ClipRects generated from the DamageList in the layer structure. To repair the layer, use the graphics rendering routines as if to redraw the entire layer, and the routines will automatically use the new clipping rectangle list. So, only the damaged areas are actually rendered into, saving time.&lt;br /&gt;
&lt;br /&gt;
{{Note|title=Never Modify the DamageList|text=The system generates and maintains the DamageList region. All application clipping should be done through the InstallClipRegion() function.}}&lt;br /&gt;
&lt;br /&gt;
To complete the update process call EndUpdate() which will restore the original ClipRect list.&lt;br /&gt;
&lt;br /&gt;
==== Sub-Layer Rectangle Operations ====&lt;br /&gt;
&lt;br /&gt;
The SwapBitsRastPortClipRect() routine is for applications that do not want to worry about clipping rectangles.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
VOID SwapBitsRastPortClipRect( struct RastPort *rp, struct ClipRect *cr );&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For instance, you may use The SwapBitsRastPortClipRect() to produce a menu without using Intuition. There are two ways to produce such a menu:&lt;br /&gt;
&lt;br /&gt;
# Create an up-front layer with CreateUpfrontLayer(), then render the menu in it. This could use lots of memory and require a lot of (very temporary) &amp;quot;slice-and-dice&amp;quot; operations to create all of the clipping rectangles for the existing windows and so on.&lt;br /&gt;
# Use SwapBitsRastPortClipRect(), directly on the display drawing area:&lt;br /&gt;
#* Render the menu in a back-up area off the display, then lock all of the on-display layers so that no task may use graphics routines to draw over the menu area on the display.&lt;br /&gt;
#* Next, swap the on-display bits with the off-display bits, making the menu appear.&lt;br /&gt;
#* When finished with the menu, swap again and unlock the layers.&lt;br /&gt;
&lt;br /&gt;
The second method is faster and leaves the clipping rectangles and most of the rest of the window data structures untouched.&lt;br /&gt;
&lt;br /&gt;
{{Note|title=Warning|text=All of the layers must be locked while the menu is visible if you use the second method above. Any task that is using any of the layers for graphics output will be halted while the menu operations are taking place. If, on the other hand, the menu is rendered as a layer, no task need be halted while the menu is up because the lower layers need not be locked.}}&lt;br /&gt;
&lt;br /&gt;
=== Layers Example ===&lt;br /&gt;
&lt;br /&gt;
For the sake of brevity, the example is a single task. No Layer locking is done. Also note that the routine myLabelLayer() is used to redraw a given layer. It is called only when a layer needs refreshing.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
/* Layers.c */&lt;br /&gt;
&lt;br /&gt;
/* Force use of new variable names to help prevent errors */&lt;br /&gt;
#define INTUI_V36_NAMES_ONLY&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;exec/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;graphics/gfxbase.h&amp;gt;&lt;br /&gt;
#include &amp;lt;graphics/layers.h&amp;gt;&lt;br /&gt;
#include &amp;lt;graphics/displayinfo.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;proto/exec.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/dos.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/graphics.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/layers.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define L_DELAY  (100)&lt;br /&gt;
#define S_DELAY   (50)&lt;br /&gt;
&lt;br /&gt;
#define DUMMY      (0L)&lt;br /&gt;
&lt;br /&gt;
#define RED_PEN    (1)&lt;br /&gt;
#define GREEN_PEN  (2)&lt;br /&gt;
#define BLUE_PEN   (3)&lt;br /&gt;
&lt;br /&gt;
#define SCREEN_D   (2)&lt;br /&gt;
#define SCREEN_W (320)&lt;br /&gt;
#define SCREEN_H (200)&lt;br /&gt;
&lt;br /&gt;
/* the starting size of example layers, offsets are used for placement */&lt;br /&gt;
#define W_H (50)&lt;br /&gt;
#define W_T (5)&lt;br /&gt;
#define W_B ((W_T+W_H)-1)&lt;br /&gt;
#define W_W (80)&lt;br /&gt;
#define W_L ((SCREEN_W/2) - (W_W/2))&lt;br /&gt;
#define W_R ((W_L+W_W)-1)&lt;br /&gt;
&lt;br /&gt;
/* size of the superbitmap */&lt;br /&gt;
#define SUPER_H SCREEN_H&lt;br /&gt;
#define SUPER_W SCREEN_W&lt;br /&gt;
&lt;br /&gt;
/* starting size of the message layer */&lt;br /&gt;
#define M_H (10)&lt;br /&gt;
#define M_T (SCREEN_H-M_H)&lt;br /&gt;
#define M_B ((M_T+M_H)-1)&lt;br /&gt;
#define M_W (SCREEN_W)&lt;br /&gt;
#define M_L (0)&lt;br /&gt;
#define M_R ((M_L+M_W)-1)&lt;br /&gt;
&lt;br /&gt;
struct GraphicsIFace *IGraphics = 0;&lt;br /&gt;
struct LayersIFace *ILayers = 0;&lt;br /&gt;
&lt;br /&gt;
/* global constant data for initializing the layers */&lt;br /&gt;
LONG  theLayerFlags[3] = { LAYERSUPER, LAYERSMART, LAYERSIMPLE };&lt;br /&gt;
UWORD colortable[]     = { 0x000, 0xf44, 0x4f4, 0x44f };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
** Clear the layer then draw in a text string.&lt;br /&gt;
*/&lt;br /&gt;
VOID myLabelLayer(struct Layer *layer, LONG color, UBYTE *string)&lt;br /&gt;
{&lt;br /&gt;
/* fill layer with color */&lt;br /&gt;
IGraphics-&amp;gt;SetRast(layer-&amp;gt;rp, color);&lt;br /&gt;
&lt;br /&gt;
/* set up for writing text into layer */&lt;br /&gt;
IGraphics-&amp;gt;SetDrMd(layer-&amp;gt;rp,JAM1);&lt;br /&gt;
IGraphics-&amp;gt;SetAPen(layer-&amp;gt;rp,0);&lt;br /&gt;
IGraphics-&amp;gt;Move(layer-&amp;gt;rp, 5, 7);&lt;br /&gt;
&lt;br /&gt;
/* write into layer */&lt;br /&gt;
IGraphics-&amp;gt;Text(layer-&amp;gt;rp, string, strlen(string));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
** write a message into a layer with a delay.&lt;br /&gt;
*/&lt;br /&gt;
VOID pMessage(struct Layer *layer, UBYTE *string)&lt;br /&gt;
{&lt;br /&gt;
IDOS-&amp;gt;Delay(S_DELAY);&lt;br /&gt;
myLabelLayer(layer, GREEN_PEN, string);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
** write an error message into a layer with a delay.&lt;br /&gt;
*/&lt;br /&gt;
VOID error(struct Layer *layer, UBYTE *string)&lt;br /&gt;
{&lt;br /&gt;
myLabelLayer(layer, RED_PEN, string);&lt;br /&gt;
IDOS-&amp;gt;Delay(L_DELAY);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
** do some layers manipulations to demonstrate their abilities.&lt;br /&gt;
*/&lt;br /&gt;
VOID doLayers(struct Layer *msgLayer, struct Layer *layer_array[])&lt;br /&gt;
{&lt;br /&gt;
WORD ktr;&lt;br /&gt;
WORD ktr_2;&lt;br /&gt;
&lt;br /&gt;
pMessage(msgLayer, &amp;quot;Label all Layers&amp;quot;);&lt;br /&gt;
myLabelLayer(layer_array[0], RED_PEN,   &amp;quot;Super&amp;quot;);&lt;br /&gt;
myLabelLayer(layer_array[1], GREEN_PEN, &amp;quot;Smart&amp;quot;);&lt;br /&gt;
myLabelLayer(layer_array[2], BLUE_PEN,  &amp;quot;Simple&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
pMessage(msgLayer, &amp;quot;MoveLayer 1 InFrontOf 0&amp;quot;);&lt;br /&gt;
if (!ILayers-&amp;gt;MoveLayerInFrontOf(layer_array[1], layer_array[0]))&lt;br /&gt;
    error(msgLayer, &amp;quot;MoveLayerInFrontOf() failed.&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
pMessage(msgLayer, &amp;quot;MoveLayer 2 InFrontOf 1&amp;quot;);&lt;br /&gt;
if (!ILayers-&amp;gt;MoveLayerInFrontOf(layer_array[2], layer_array[1]))&lt;br /&gt;
    error(msgLayer, &amp;quot;MoveLayerInFrontOf() failed.&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
pMessage(msgLayer, &amp;quot;Refresh Simple Refresh Layer&amp;quot;);&lt;br /&gt;
myLabelLayer(layer_array[2], BLUE_PEN, &amp;quot;Simple&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
pMessage(msgLayer, &amp;quot;Incrementally MoveLayers...&amp;quot;);&lt;br /&gt;
for(ktr = 0; ktr &amp;lt; 30; ktr++)&lt;br /&gt;
    {&lt;br /&gt;
    if (!ILayers-&amp;gt;MoveLayer(DUMMY, layer_array[1], -1, 0))&lt;br /&gt;
        error(msgLayer, &amp;quot;MoveLayer() failed.&amp;quot;);&lt;br /&gt;
    if (!ILayers-&amp;gt;MoveLayer(DUMMY, layer_array[2], -2, 0))&lt;br /&gt;
        error(msgLayer, &amp;quot;MoveLayer() failed.&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
pMessage(msgLayer, &amp;quot;Refresh Simple Refresh Layer&amp;quot;);&lt;br /&gt;
myLabelLayer(layer_array[2], BLUE_PEN, &amp;quot;Simple&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
pMessage(msgLayer, &amp;quot;make Layer 0 the UpfrontLayer&amp;quot;);&lt;br /&gt;
if (!ILayers-&amp;gt;UpfrontLayer(DUMMY, layer_array[0]))&lt;br /&gt;
    error(msgLayer, &amp;quot;UpfrontLayer() failed.&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
pMessage(msgLayer, &amp;quot;make Layer 2 the BehindLayer&amp;quot;);&lt;br /&gt;
if (!ILayers-&amp;gt;BehindLayer(DUMMY, layer_array[2]))&lt;br /&gt;
    error(msgLayer, &amp;quot;BehindLayer() failed.&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
pMessage(msgLayer, &amp;quot;Incrementally MoveLayers again...&amp;quot;);&lt;br /&gt;
for(ktr = 0; ktr &amp;lt; 30; ktr++)&lt;br /&gt;
    {&lt;br /&gt;
    if (!ILayers-&amp;gt;MoveLayer(DUMMY, layer_array[1], 0, 1))&lt;br /&gt;
        error(msgLayer, &amp;quot;MoveLayer() failed.&amp;quot;);&lt;br /&gt;
    if (!ILayers-&amp;gt;MoveLayer(DUMMY, layer_array[2], 0, 2))&lt;br /&gt;
        error(msgLayer, &amp;quot;MoveLayer() failed.&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
pMessage(msgLayer, &amp;quot;Refresh Simple Refresh Layer&amp;quot;);&lt;br /&gt;
myLabelLayer(layer_array[2], BLUE_PEN, &amp;quot;Simple&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
pMessage(msgLayer, &amp;quot;Big MoveLayer&amp;quot;);&lt;br /&gt;
for(ktr = 0; ktr &amp;lt; 3; ktr++)&lt;br /&gt;
    {&lt;br /&gt;
    if (!ILayers-&amp;gt;MoveLayer(DUMMY, layer_array[ktr], -layer_array[ktr]-&amp;gt;bounds.MinX, 0))&lt;br /&gt;
        error(msgLayer, &amp;quot;MoveLayer() failed.&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
pMessage(msgLayer, &amp;quot;Incrementally increase size&amp;quot;);&lt;br /&gt;
for(ktr = 0; ktr &amp;lt; 5; ktr++)&lt;br /&gt;
    {&lt;br /&gt;
    for(ktr_2 = 0; ktr_2 &amp;lt; 3; ktr_2++)&lt;br /&gt;
        {&lt;br /&gt;
        if (!ILayers-&amp;gt;SizeLayer(DUMMY, layer_array[ktr_2], 1, 1))&lt;br /&gt;
            error(msgLayer, &amp;quot;SizeLayer() failed.&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
pMessage(msgLayer, &amp;quot;Refresh Smart Refresh Layer&amp;quot;);&lt;br /&gt;
myLabelLayer(layer_array[1], GREEN_PEN, &amp;quot;Smart&amp;quot;);&lt;br /&gt;
pMessage(msgLayer, &amp;quot;Refresh Simple Refresh Layer&amp;quot;);&lt;br /&gt;
myLabelLayer(layer_array[2], BLUE_PEN,  &amp;quot;Simple&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
pMessage(msgLayer, &amp;quot;Big SizeLayer&amp;quot;);&lt;br /&gt;
for(ktr = 0; ktr &amp;lt; 3; ktr++)&lt;br /&gt;
    {&lt;br /&gt;
    if (!ILayers-&amp;gt;SizeLayer(DUMMY,layer_array[ktr],&lt;br /&gt;
                SCREEN_W-(layer_array[ktr]-&amp;gt;bounds.MaxX)-1,0))&lt;br /&gt;
        error(msgLayer, &amp;quot;SizeLayer() failed.&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
pMessage(msgLayer, &amp;quot;Refresh Smart Refresh Layer&amp;quot;);&lt;br /&gt;
myLabelLayer(layer_array[1], GREEN_PEN, &amp;quot;Smart&amp;quot;);&lt;br /&gt;
pMessage(msgLayer, &amp;quot;Refresh Simple Refresh Layer&amp;quot;);&lt;br /&gt;
myLabelLayer(layer_array[2], BLUE_PEN,  &amp;quot;Simple&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
pMessage(msgLayer, &amp;quot;ScrollLayer down&amp;quot;);&lt;br /&gt;
for(ktr = 0; ktr &amp;lt; 30; ktr++)&lt;br /&gt;
    {&lt;br /&gt;
    for(ktr_2 = 0; ktr_2 &amp;lt; 3; ktr_2++)&lt;br /&gt;
        {&lt;br /&gt;
        ILayers-&amp;gt;ScrollLayer(DUMMY, layer_array[ktr_2], 0, -1);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
pMessage(msgLayer, &amp;quot;Refresh Smart Refresh Layer&amp;quot;);&lt;br /&gt;
myLabelLayer(layer_array[1], GREEN_PEN, &amp;quot;Smart&amp;quot;);&lt;br /&gt;
pMessage(msgLayer, &amp;quot;Refresh Simple Refresh Layer&amp;quot;);&lt;br /&gt;
myLabelLayer(layer_array[2], BLUE_PEN,  &amp;quot;Simple&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
pMessage(msgLayer, &amp;quot;ScrollLayer up&amp;quot;);&lt;br /&gt;
for(ktr = 0; ktr &amp;lt; 30; ktr++)&lt;br /&gt;
    {&lt;br /&gt;
    for(ktr_2 = 0; ktr_2 &amp;lt; 3; ktr_2++)&lt;br /&gt;
        {&lt;br /&gt;
        ILayers-&amp;gt;ScrollLayer(DUMMY, layer_array[ktr_2], 0, 1);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
pMessage(msgLayer, &amp;quot;Refresh Smart Refresh Layer&amp;quot;);&lt;br /&gt;
myLabelLayer(layer_array[1], GREEN_PEN, &amp;quot;Smart&amp;quot;);&lt;br /&gt;
pMessage(msgLayer, &amp;quot;Refresh Simple Refresh Layer&amp;quot;);&lt;br /&gt;
myLabelLayer(layer_array[2], BLUE_PEN,  &amp;quot;Simple&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
IDOS_&amp;gt;Delay(L_DELAY);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
** delete the layer array created by allocLayers().&lt;br /&gt;
*/&lt;br /&gt;
VOID disposeLayers(struct Layer *msgLayer, struct Layer *layer_array[])&lt;br /&gt;
{&lt;br /&gt;
WORD ktr;&lt;br /&gt;
&lt;br /&gt;
for (ktr = 0; ktr &amp;lt; 3; ktr++)&lt;br /&gt;
    {&lt;br /&gt;
    if (layer_array[ktr] != NULL)&lt;br /&gt;
        {&lt;br /&gt;
        if (!ILayers-&amp;gt;DeleteLayer(DUMMY, layer_array[ktr]))&lt;br /&gt;
            error(msgLayer, &amp;quot;Error deleting layer&amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
** Create some hard-coded layers.  The first must be super-bitmap, with&lt;br /&gt;
** the bitmap passed as an argument.  The others must not be super-bitmap.&lt;br /&gt;
** The pointers to the created layers are returned in layer_array.&lt;br /&gt;
**&lt;br /&gt;
** Return FALSE on failure.  On a FALSE return, the layers are&lt;br /&gt;
** properly cleaned up.&lt;br /&gt;
*/&lt;br /&gt;
BOOL allocLayers(struct Layer *msgLayer, struct Layer *layer_array[],&lt;br /&gt;
    struct BitMap *super_bitmap, struct Layer_Info *theLayerInfo,&lt;br /&gt;
    struct BitMap *theBitMap)&lt;br /&gt;
{&lt;br /&gt;
WORD ktr;&lt;br /&gt;
BOOL create_layer_ok = TRUE;&lt;br /&gt;
&lt;br /&gt;
for (ktr = 0;&lt;br /&gt;
     (ktr &amp;lt; 3) &amp;amp;&amp;amp; (create_layer_ok);&lt;br /&gt;
     ktr++)&lt;br /&gt;
    {&lt;br /&gt;
    pMessage(msgLayer, &amp;quot;Create BehindLayer&amp;quot;);&lt;br /&gt;
    if (ktr == 0)&lt;br /&gt;
        {&lt;br /&gt;
        if ((layer_array[ktr] = ILayers-&amp;gt;CreateBehindLayer(theLayerInfo, theBitMap,&lt;br /&gt;
                  W_L+(ktr*30), W_T+(ktr*30), W_R+(ktr*30), W_B+(ktr*30),&lt;br /&gt;
                  theLayerFlags[ktr], super_bitmap)) == NULL)&lt;br /&gt;
            create_layer_ok = FALSE;&lt;br /&gt;
        }&lt;br /&gt;
     else&lt;br /&gt;
        {&lt;br /&gt;
        if ((layer_array[ktr] = ILayers-&amp;gt;CreateBehindLayer(theLayerInfo, theBitMap,&lt;br /&gt;
                  W_L+(ktr*30), W_T+(ktr*30), W_R+(ktr*30), W_B+(ktr*30),&lt;br /&gt;
                  theLayerFlags[ktr], NULL)) == NULL)&lt;br /&gt;
            create_layer_ok = FALSE;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
    if (create_layer_ok)&lt;br /&gt;
        {&lt;br /&gt;
        pMessage(msgLayer, &amp;quot;Fill the RastPort&amp;quot;);&lt;br /&gt;
        IGraphics-&amp;gt;SetRast(layer_array[ktr]-&amp;gt;rp, ktr + 1);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
if (!create_layer_ok)&lt;br /&gt;
    disposeLayers(msgLayer, layer_array);&lt;br /&gt;
&lt;br /&gt;
return(create_layer_ok);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
** Free the bitmap and all bitplanes created by allocBitMap().&lt;br /&gt;
*/&lt;br /&gt;
VOID disposeBitMap(struct BitMap *bitmap, LONG depth, LONG width, LONG height)&lt;br /&gt;
{&lt;br /&gt;
WORD ktr;&lt;br /&gt;
&lt;br /&gt;
if (NULL != bitmap)&lt;br /&gt;
    {&lt;br /&gt;
    for (ktr = 0; ktr &amp;lt; depth; ktr++)&lt;br /&gt;
        {&lt;br /&gt;
        if (NULL != bitmap-&amp;gt;Planes[ktr])&lt;br /&gt;
            IGraphics-&amp;gt;FreeRaster(bitmap-&amp;gt;Planes[ktr], width, height);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
    IExec-&amp;gt;FreeMem(bitmap, sizeof(*bitmap));&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
** Allocate and initialize a bitmap structure.&lt;br /&gt;
*/&lt;br /&gt;
struct BitMap *allocBitMap(LONG depth, LONG width, LONG height)&lt;br /&gt;
{&lt;br /&gt;
WORD ktr;&lt;br /&gt;
BOOL bit_map_failed = FALSE;&lt;br /&gt;
struct BitMap *bitmap = NULL;&lt;br /&gt;
&lt;br /&gt;
if (NULL != (bitmap = IExec-&amp;gt;AllocMem(sizeof(*bitmap),NULL)))&lt;br /&gt;
    {&lt;br /&gt;
    IGraphics-&amp;gt;InitBitMap(bitmap,depth,width,height);&lt;br /&gt;
&lt;br /&gt;
    for (ktr = 0; ktr &amp;lt; depth; ktr++)&lt;br /&gt;
        {&lt;br /&gt;
        if (NULL == (bitmap-&amp;gt;Planes[ktr] = (PLANEPTR)IGraphics-&amp;gt;AllocRaster(width,height)))&lt;br /&gt;
            bit_map_failed = TRUE;&lt;br /&gt;
        else&lt;br /&gt;
            IGraphics-&amp;gt;BltClear(bitmap-&amp;gt;Planes[ktr], RASSIZE(width,height), 1);&lt;br /&gt;
        }&lt;br /&gt;
    if (bit_map_failed)&lt;br /&gt;
        {&lt;br /&gt;
        disposeBitMap(bitmap,depth,width,height);&lt;br /&gt;
        bitmap = NULL;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
return(bitmap);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
** Set up to run the layers example, doLayers(). Clean up when done.&lt;br /&gt;
*/&lt;br /&gt;
VOID startLayers(struct Layer_Info *theLayerInfo, struct BitMap *theBitMap)&lt;br /&gt;
{&lt;br /&gt;
struct Layer  *msgLayer;&lt;br /&gt;
struct BitMap *theSuperBitMap;&lt;br /&gt;
struct Layer  *theLayers[3] = { NULL, NULL, NULL, };&lt;br /&gt;
&lt;br /&gt;
if (NULL != (msgLayer = ILayers-&amp;gt;CreateUpfrontLayer(theLayerInfo, theBitMap,&lt;br /&gt;
                     M_L, M_T, M_R, M_B, LAYERSMART, NULL)))&lt;br /&gt;
    {&lt;br /&gt;
    pMessage(msgLayer, &amp;quot;Setting up Layers&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    if (NULL != (theSuperBitMap = allocBitMap(SCREEN_D, SUPER_W, SUPER_H)))&lt;br /&gt;
        {&lt;br /&gt;
        if (allocLayers(msgLayer, theLayers, theSuperBitMap, theLayerInfo, theBitMap))&lt;br /&gt;
            {&lt;br /&gt;
            doLayers(msgLayer, theLayers);&lt;br /&gt;
&lt;br /&gt;
            disposeLayers(msgLayer, theLayers);&lt;br /&gt;
            }&lt;br /&gt;
        disposeBitMap(theSuperBitMap, SCREEN_D, SUPER_W, SUPER_H);&lt;br /&gt;
        }&lt;br /&gt;
    if (!ILayers-&amp;gt;DeleteLayer(DUMMY, msgLayer))&lt;br /&gt;
        error(msgLayer, &amp;quot;Error deleting layer&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
** Set up a low-level graphics display for layers to work on.  Layers&lt;br /&gt;
** should not be built directly on Intuition screens, use a low-level&lt;br /&gt;
** graphics view.  If you need mouse or other events for the layers&lt;br /&gt;
** display, you have to get them directly from the input device.  The&lt;br /&gt;
** only supported method of using layers library calls with Intuition&lt;br /&gt;
** (other than the InstallClipRegion() call) is through Intuition windows.&lt;br /&gt;
**&lt;br /&gt;
** See graphics primitives articles for details on creating and using the&lt;br /&gt;
** low-level graphics calls.&lt;br /&gt;
*/&lt;br /&gt;
VOID runNewView(VOID)&lt;br /&gt;
{&lt;br /&gt;
struct View        theView;&lt;br /&gt;
struct View       *oldview;&lt;br /&gt;
struct ViewPort    theViewPort;&lt;br /&gt;
struct RasInfo     theRasInfo;&lt;br /&gt;
struct ColorMap   *theColorMap;&lt;br /&gt;
struct Layer_Info *theLayerInfo;&lt;br /&gt;
struct BitMap     *theBitMap;&lt;br /&gt;
UWORD             *colorpalette;&lt;br /&gt;
WORD               ktr;&lt;br /&gt;
&lt;br /&gt;
/* save current view, to be restored when done */&lt;br /&gt;
if (NULL != (oldview = GfxBase-&amp;gt;ActiView))&lt;br /&gt;
    {&lt;br /&gt;
    /* get a LayerInfo structure */&lt;br /&gt;
    if (NULL != (theLayerInfo = ILayers-&amp;gt;NewLayerInfo()))&lt;br /&gt;
        {&lt;br /&gt;
        if (NULL != (theColorMap = IGraphics-&amp;gt;GetColorMap(4)))&lt;br /&gt;
            {&lt;br /&gt;
            colorpalette = (UWORD *)theColorMap-&amp;gt;ColorTable;&lt;br /&gt;
            for(ktr = 0; ktr &amp;lt; 4; ktr++)&lt;br /&gt;
                *colorpalette++ = colortable[ktr];&lt;br /&gt;
&lt;br /&gt;
            if (NULL != (theBitMap = allocBitMap(SCREEN_D, SCREEN_W, SCREEN_H)))&lt;br /&gt;
                {&lt;br /&gt;
                IGraphics-&amp;gt;InitView(&amp;amp;theView);&lt;br /&gt;
                IGraphics-&amp;gt;InitVPort(&amp;amp;theViewPort);&lt;br /&gt;
&lt;br /&gt;
                theView.ViewPort = &amp;amp;theViewPort;&lt;br /&gt;
&lt;br /&gt;
                theViewPort.DWidth   = SCREEN_W;&lt;br /&gt;
                theViewPort.DHeight  = SCREEN_H;&lt;br /&gt;
                theViewPort.RasInfo  = &amp;amp;theRasInfo;&lt;br /&gt;
                theViewPort.ColorMap = theColorMap;&lt;br /&gt;
&lt;br /&gt;
                theRasInfo.BitMap   = theBitMap;&lt;br /&gt;
                theRasInfo.RxOffset = 0;&lt;br /&gt;
                theRasInfo.RyOffset = 0;&lt;br /&gt;
                theRasInfo.Next     = NULL;&lt;br /&gt;
&lt;br /&gt;
                IGraphics-&amp;gt;MakeVPort(&amp;amp;theView, &amp;amp;theViewPort);&lt;br /&gt;
                IGraphics-&amp;gt;MrgCop(&amp;amp;theView);&lt;br /&gt;
                IGraphics-&amp;gt;LoadView(&amp;amp;theView);&lt;br /&gt;
                IGraphics-&amp;gt;WaitTOF();&lt;br /&gt;
&lt;br /&gt;
                startLayers(theLayerInfo, theBitMap);&lt;br /&gt;
&lt;br /&gt;
                /* put back the old view, wait for it to become&lt;br /&gt;
                ** active before freeing any of our display&lt;br /&gt;
                */&lt;br /&gt;
                IGraphics-&amp;gt;LoadView(oldview);&lt;br /&gt;
                IGraphics-&amp;gt;WaitTOF();&lt;br /&gt;
&lt;br /&gt;
                /* free dynamically created structures */&lt;br /&gt;
                IGraphics-&amp;gt;FreeVPortCopLists(&amp;amp;theViewPort);&lt;br /&gt;
                IGraphics-&amp;gt;FreeCprList(theView.LOFCprList);&lt;br /&gt;
&lt;br /&gt;
                disposeBitMap(theBitMap, SCREEN_D, SCREEN_W, SCREEN_H);&lt;br /&gt;
                }&lt;br /&gt;
            IGraphics-&amp;gt;FreeColorMap(theColorMap);       /* free the color map */&lt;br /&gt;
            }&lt;br /&gt;
        ILayers-&amp;gt;DisposeLayerInfo(theLayerInfo);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
** Open the libraries used by the example.  Clean up when done.&lt;br /&gt;
*/&lt;br /&gt;
int main(int argc, char **argv)&lt;br /&gt;
{&lt;br /&gt;
    struct Library *GfxBase = IExec-&amp;gt;OpenLibrary(&amp;quot;graphics.library&amp;quot;, 50);&lt;br /&gt;
    struct Library *LayersBase = IExec-&amp;gt;OpenLibrary(&amp;quot;layers.library&amp;quot;, 50);&lt;br /&gt;
    IGraphics = (struct GraphicsIFace*)IExec-&amp;gt;GetInterface(GfxBase, &amp;quot;main&amp;quot;, 1, NULL);&lt;br /&gt;
    ILayers = (struct LayersIFace*)IExec-&amp;gt;GetInterface(LayersBase, &amp;quot;main&amp;quot;, 1, NULL); &lt;br /&gt;
    &lt;br /&gt;
    if (IGraphics != NULL &amp;amp;&amp;amp; ILayers != NULL)&lt;br /&gt;
    {   &lt;br /&gt;
        runNewView();&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    IExec-&amp;gt;DropInterface((struct Interface*)ILayers);&lt;br /&gt;
    IExec-&amp;gt;DropInterface((struct Interface*)IGraphics);&lt;br /&gt;
    IExec-&amp;gt;CloseLibrary(LayersBase);&lt;br /&gt;
    IExec-&amp;gt;CloseLibrary(GfxBase);&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Function Reference ==&lt;br /&gt;
&lt;br /&gt;
The following are brief descriptions of the layers library functions. See the SDK for details on each function call.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Layers Library Functions&lt;br /&gt;
! Function&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| NewLayerInfo()&lt;br /&gt;
| Allocating a Layer_Info structure.&lt;br /&gt;
|-&lt;br /&gt;
| DisposeLayerInfo()&lt;br /&gt;
| Deallocating a Layer_Info structure.&lt;br /&gt;
|-&lt;br /&gt;
| CreateUpfrontLayer()&lt;br /&gt;
| Make a new layer in front of others.&lt;br /&gt;
|-&lt;br /&gt;
| CreateBehindLayer()&lt;br /&gt;
| Make a new layer behind others.&lt;br /&gt;
|-&lt;br /&gt;
| DeleteLayer()&lt;br /&gt;
| Remove and delete an existing layer.&lt;br /&gt;
|-&lt;br /&gt;
| MoveLayer()&lt;br /&gt;
| Change the position (not depth) of a layer.&lt;br /&gt;
|-&lt;br /&gt;
| SizeLayer()&lt;br /&gt;
| Change the size of a layer.&lt;br /&gt;
|-&lt;br /&gt;
| ScrollLayer()&lt;br /&gt;
| Change the internal coordinates of a layer.&lt;br /&gt;
|-&lt;br /&gt;
| BehindLayer()&lt;br /&gt;
| Depth arrange a layer behind others.&lt;br /&gt;
|-&lt;br /&gt;
| UpfrontLayer()&lt;br /&gt;
| Depth arrange a layer in front of others.&lt;br /&gt;
|-&lt;br /&gt;
| MoveLayerInFrontOf()&lt;br /&gt;
| Depth arrange a layer to a specific position.&lt;br /&gt;
|-&lt;br /&gt;
| WhichLayer()&lt;br /&gt;
| Find the frontmost layer at a position.&lt;br /&gt;
|-&lt;br /&gt;
| SwapBitsRastPortClipRect()&lt;br /&gt;
| Fast, non-layered and non-damaging display operation.&lt;br /&gt;
|-&lt;br /&gt;
| BeginUpdate()&lt;br /&gt;
| Synchronize optimized refreshing for layer.&lt;br /&gt;
|-&lt;br /&gt;
| EndUpdate()&lt;br /&gt;
| End optimized layer refresh.&lt;br /&gt;
|-&lt;br /&gt;
| LockLayer()&lt;br /&gt;
| Lock out rendering in a single layer.&lt;br /&gt;
|-&lt;br /&gt;
| UnlockLayer()&lt;br /&gt;
| Release LockLayer() lock.&lt;br /&gt;
|-&lt;br /&gt;
| LockLayers()&lt;br /&gt;
| Lock out rendering in all layers of a display.&lt;br /&gt;
|-&lt;br /&gt;
| UnlockLayers()&lt;br /&gt;
| Release LockLayers() lock.&lt;br /&gt;
|-&lt;br /&gt;
| LockLayerInfo()&lt;br /&gt;
| Gain exclusive access to the display‚Äôs layers.&lt;br /&gt;
|-&lt;br /&gt;
| UnlockLayerInfo()&lt;br /&gt;
| Release LockLayerInfo() lock.&lt;br /&gt;
|-&lt;br /&gt;
| InstallClipRegion()&lt;br /&gt;
| Add a clipping region to a layer.&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Costel Mincea</name></author>
	</entry>
	<entry>
		<id>https://wiki.amigaos.net/w/index.php?title=Using_Crash-Logs_for_Debugging&amp;diff=12560</id>
		<title>Using Crash-Logs for Debugging</title>
		<link rel="alternate" type="text/html" href="https://wiki.amigaos.net/w/index.php?title=Using_Crash-Logs_for_Debugging&amp;diff=12560"/>
		<updated>2025-01-26T19:33:28Z</updated>

		<summary type="html">&lt;p&gt;Costel Mincea: Text replacement - &amp;quot;&amp;lt;syntaxhighlight&amp;gt;&amp;quot; to &amp;quot;&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Debug]]&lt;br /&gt;
= Introduction =&lt;br /&gt;
&lt;br /&gt;
Bugs in software are a fact of life. It is almost impossible to write software with zero bugs. To date, no-one has come up with a method of even proving that a computer program is bug-free. Given these facts, it would be desirable to obtain as much information as possible about any crash that occurs. This is essential for debugging purposes.&lt;br /&gt;
&lt;br /&gt;
AmigaOS provides substantial information via the Grim-Reaper. The Grim-Reaper pops up whenever a program performs an illegal operation, and provides a whole host of information about the crash. Details that are listed include the name of the program/library in which the crash occurred is listed along with the state of the CPU, a stack trace, and other state information. This information could be used in order to isolate the specific line of code at which the program crashed. However, this requires suitable preparation.&lt;br /&gt;
&lt;br /&gt;
[[File:UsingCrashLogs1.jpg|center|frame|The Grim Reaper displaying a DSI error.]]&lt;br /&gt;
&lt;br /&gt;
It is possible to embed debug information into a binary. However, this is undesirable in software being released to consumers as the binaries are inflated to several times the original size (tens of megabytes in size is easily obtainable in this manner). From the customers perspective, this is completely wasted space. Also, it gives a wealth of information about the internals of your program, which is undesirable. As will be shown below, there is a methodt hat can be used to provide compact binaries to end-users whilst still being able to use their crash-logs in order to locate and fix bugs.&lt;br /&gt;
&lt;br /&gt;
= Enabling Debugging =&lt;br /&gt;
&lt;br /&gt;
It is very easy to enable debugging in GCC. Simply add the compiler flag &amp;quot;-gstabs&amp;quot; when compiling and linking. This tells GCC that you wish to include debugging symbols in the binary, and even works if optimizations are enabled. &amp;quot;Stabs&amp;quot; is a particular format in which the debugging symbol; &amp;quot;-ggdb&amp;quot; is another option that also adds debugging symbols, but in a different format. However, I have been told that there are issues with &amp;quot;-ggdb&amp;quot; and large applications, so it is best to stick to &amp;quot;-gstabs.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
= Debug Binaries =&lt;br /&gt;
&lt;br /&gt;
As was mentioned previously, enabling debug symbols inflates the binray size significantly. What many people do not realize is that it is possible to create a separate file that contains all the debug information; here is an excerpt from the make-file that achieves this:&lt;br /&gt;
&lt;br /&gt;
 $(TARGET): $(OBJS)&lt;br /&gt;
     $(CC) $(CFLAGS) -o $@.debug $(OBJS) $(LIBS) $(LINK)&lt;br /&gt;
     $(STRIP) $@.debug -o $@ &lt;br /&gt;
&lt;br /&gt;
Where CFLAGS = -mcrt=newlib $(OPTIMIZE) -Wall -gstabs&lt;br /&gt;
&lt;br /&gt;
In the [[Media:usingcrashlogs.lha|example template]] this translates to:&lt;br /&gt;
 gcc -mcrt=newlib -O3 -Wall -gstabs -c -o badboy.o badboy.c&lt;br /&gt;
 gcc -mcrt=newlib -O3 -Wall -gstabs -o badboy.debug badboy.o&lt;br /&gt;
 strip badboy.debug badboy&lt;br /&gt;
&lt;br /&gt;
The first line compiles the single source-file, badboy.c. The next one links it, and creates an executable called badboy.debug, which contains all the debugging symbols. Finally, strip removes all the debugging symbols and creates a binary called badboy. This stripped binary can then be distributed to end-users; badboy.debug is kept by the developer for interpreting crash-logs.&lt;br /&gt;
&lt;br /&gt;
= Interpreting Crash-Logs =&lt;br /&gt;
&lt;br /&gt;
This is best understood by example. Download and extract the [[Media:usingcrashlogs.lha|example template]]. Open a shell window and change to the directory containing the template code. Type make, and press enter. This will compile a program called badboy that deliberately performs an illegal operation. It performs a classical NULL-pointer dereferencing for a write operation; a very common bug. Now run badboy; the grim-reaper should pop up and display the error message below.&lt;br /&gt;
&lt;br /&gt;
[[File:UsingCrashLogs1.jpg|center|frame|The Grim Reaper displaying a DSI error.]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Note about the &amp;quot;redzone&amp;quot; message:&#039;&#039;&lt;br /&gt;
The lower part of the stack is made up of unmapped virtual pages that throw an exception when accessed, to prevent the program from wreaking havoc.&lt;br /&gt;
A redzone is a stack barrier that makes the program exhausting it&#039;s stack space crash. With memory, the term &amp;quot;electric fence&amp;quot; has been established for &amp;quot;hot&amp;quot; barriers (due to the name given to a tool under Linux that was used for this purpose).&lt;br /&gt;
&lt;br /&gt;
Now click on &amp;quot;More...&amp;quot; and select the &amp;quot;Stack Trace&amp;quot; tab. Clicking on the &amp;quot;Generate Stack Trace&amp;quot; button will generate a stack trace.&lt;br /&gt;
&lt;br /&gt;
[[File:UsingCrashLogs2.jpg|center|frame|A stack trace for the program &amp;quot;badboy&amp;quot;]]&lt;br /&gt;
&lt;br /&gt;
This shows that the crash occurred within &amp;quot;badboy&amp;quot; in section 5 at 0x608. Open a new shell window and change to the directory containing &amp;quot;badboy&amp;quot; once again. Enter the following line:&lt;br /&gt;
&lt;br /&gt;
 addr2line -e badboy.debug --section=.text 0x608 &lt;br /&gt;
&lt;br /&gt;
This performs a lookup of 0x608 inside &amp;quot;badboy.debug,&amp;quot; which contains the debug symbols. Addr2line will respond by giving the file and line number of this address.&lt;br /&gt;
&lt;br /&gt;
[[File:UsingCrashLogs3.jpg|center|frame|A stack trace for the program &amp;quot;badboy&amp;quot;]]&lt;br /&gt;
&lt;br /&gt;
Line 25 performs a write to address zero:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
int *a = NULL;&lt;br /&gt;
*a = 0;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The procedure above has identified the exact source-line at which the crash occurred. In this case the crash was deliberate in order to present an easy to understand example. However, in a real application, the*.debug version of each release would be kept by the developer so that crash-logs submitted by users can be used in order to identify the source-line at which the crash occurred. If you look at the [http://hdrlab.org.nz/articles/amiga-os-articles/minigl-templates/ MiniGL templates] that I have written, you will notice that all of them use this technique.&lt;br /&gt;
&lt;br /&gt;
= Download =&lt;br /&gt;
&lt;br /&gt;
[[Media:usingcrashlogs.lha|Using crash-logs template and example]]&lt;br /&gt;
&lt;br /&gt;
= Wish-List =&lt;br /&gt;
&lt;br /&gt;
Whilst the technique above works, a more automated bug tracking system would be nice. The first component of such a system would be an automated crash-log submission system. If Grim Reaper provided a singl-click method of submitting a bug report to the developer via the internet, more crash-logs are likely to be submitted. Having a tool that would parse the crash-log and automatically find file names and line numbers for the entry in the crash-log would also be useful.&lt;br /&gt;
&lt;br /&gt;
= Author =&lt;br /&gt;
&lt;br /&gt;
Copyright (c) 2008 Hans de Ruiter.&amp;lt;br/&amp;gt;&lt;br /&gt;
Reproduced with permission.&amp;lt;br/&amp;gt;&lt;br /&gt;
See the original article [http://hdrlab.org.nz/articles/amiga-os-articles/using-crash-logs/ here].&lt;/div&gt;</summary>
		<author><name>Costel Mincea</name></author>
	</entry>
	<entry>
		<id>https://wiki.amigaos.net/w/index.php?title=AmiWest_Setup&amp;diff=12559</id>
		<title>AmiWest Setup</title>
		<link rel="alternate" type="text/html" href="https://wiki.amigaos.net/w/index.php?title=AmiWest_Setup&amp;diff=12559"/>
		<updated>2025-01-26T19:33:15Z</updated>

		<summary type="html">&lt;p&gt;Costel Mincea: Text replacement - &amp;quot;&amp;lt;syntaxhighlight&amp;gt;&amp;quot; to &amp;quot;&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Setup =&lt;br /&gt;
&lt;br /&gt;
Developing software on and for AmigaOS involves three major components:  the &#039;&#039;&#039;AmigaOS SDK&#039;&#039;&#039; or &amp;quot;Software Development Kit&amp;quot;, a source code &#039;&#039;&#039;Editor&#039;&#039;&#039; and your &#039;&#039;&#039;imagination&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The first part of this equation, the AmigaOS Software Development Kit or &#039;&#039;&#039;AmigaOS SDK&#039;&#039;&#039;, is a collection of files and tools that will convert your source code into an Amiga application.  The SDK consists of a collection of the latest documentation, &amp;quot;include&amp;quot; files, example code, utilities and the GCC compiler.  With each major version of AmigaOS a new SDK is issued that allows developers and their applications take advantage of the latest OS features.&lt;br /&gt;
&lt;br /&gt;
The second part of the equation is a means to edit and manage your programming project and its source code. While you can edit source code in the AmigaOS &#039;&#039;&#039;NotePad&#039;&#039;&#039; text editor, there are much better &amp;amp; easier ways. The most powerful programming environment on AmigaOS is called [http://codebench.co.uk/ CodeBench]. In addition to providing a source code editor that provide syntax highlighting, help as you type and context sensitive help, CodeBench takes care of building &amp;quot;makefiles&amp;quot;, runs the compiler, collects &amp;amp; presents errors and can interact to remote source code servers.&lt;br /&gt;
&lt;br /&gt;
Finally there is &#039;&#039;&#039;you&#039;&#039;&#039;!  Obviously, developing AmigaOS applications with the SDK requires a working understanding of the C language.  To take advantage of the specific powers of AmigaOS, there are more methodologies and functions to learn.  The SDK provides a number of example programs to learn from and a bounty of &amp;quot;autodocs&amp;quot; that document AmigaOS functions.  Every day there are new things to learn.&lt;br /&gt;
&lt;br /&gt;
== Installing the SDK ==&lt;br /&gt;
&lt;br /&gt;
The latest version of the SDK can be downloaded from the Hyperion Entertainment [http://www.hyperion-entertainment.biz/index.php?option=com_registration&amp;amp;view=files&amp;amp;parent=30&amp;amp;Itemid=63 SDK webpage].&lt;br /&gt;
&lt;br /&gt;
Once downloaded, you can double-click on the SDK archive file to use the AmigaOS &#039;&#039;&#039;Unarc&#039;&#039;&#039; utility to decompress the SDK to your RAM Disk. This will create a directory that includes all the SDK files to be installed.&lt;br /&gt;
&lt;br /&gt;
In that directory you will find the &#039;&#039;&#039;Install SDK&#039;&#039;&#039; installer program. If you run that, it will ask you what you want to install and for a location to install to.  Unless you have a severe limitation on hard disk space, it&#039;s recommended you make a &amp;quot;Full&amp;quot; install.  As part of the install process, a few commands will be added to your &amp;quot;user-startup&amp;quot; script to assign SDK: to your system.&lt;br /&gt;
&lt;br /&gt;
Once the SDK installation is complete, your SDK: path will include the following directories:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Documentation&#039;&#039;&#039; - This drawer contains various documentation, AutoDocs, and other information related to the SDK. It also contains documentation on the various tools and compilers.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Examples&#039;&#039;&#039; - This drawer contains example source code on how to program for AmigaOS 4.x. Examples are sorted by theme/topic.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Local&#039;&#039;&#039; - The Local drawer is our means of isolating the compilers and third-party additions. See SDK documentation PDF file for more information on the Local drawer.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;gcc&#039;&#039;&#039; - The gcc drawer contains the GNU C/C++ compiler. It is set up in a way that there are no user-serviceable parts inside. This makes it easy to exchange the compiler when later versions become available.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Include&#039;&#039;&#039; - This drawer contains system-level include files. Like the gcc drawer, it should not need to be modified.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Contrib&#039;&#039;&#039; - The Contrib drawer contains various files that where contributed to the SDK. Among other things, it contains the latest source code for the static C runtime library clib2.&lt;br /&gt;
&lt;br /&gt;
You can test the installation of SDK and its GCC compiler by opening a shell and typing the following command:&lt;br /&gt;
&lt;br /&gt;
 gcc --version&lt;br /&gt;
&lt;br /&gt;
This should cause a text to be printed by the compiler, including the version number.&lt;br /&gt;
&lt;br /&gt;
== Testing the SDK ==&lt;br /&gt;
&lt;br /&gt;
Open the &#039;&#039;&#039;NotePad&#039;&#039;&#039; text editor and type the following text:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/dos.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
 IDOS-&amp;gt;Printf(&amp;quot;Hello, World\n&amp;quot;);&lt;br /&gt;
 return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then save the file to &amp;quot;hello_world.c&amp;quot; and go back to the shell, CD to the directory with your file and enter this command:&lt;br /&gt;
&lt;br /&gt;
 gcc -o hello_world hello_world.c&lt;br /&gt;
&lt;br /&gt;
After a few seconds, the gcc compiler should return. As long the source was correctly entered and no errors or warnings were displayed by GCC, then you will have successfully compiled your first Amiga program. Just type &amp;quot;hello_world&amp;quot; into the command line to see it run. Congratulations!&lt;br /&gt;
&lt;br /&gt;
== Installing CodeBench ==&lt;br /&gt;
&lt;br /&gt;
You may have used the &#039;&#039;&#039;NotePad&#039;&#039;&#039; text editor and your Shell console to create the sample C program above, but there are much better ways to edit and compile C programs. Such development systems provide more specialized editors suited for coding and means for managing compilation, handling warnings and errors, etc.&lt;br /&gt;
&lt;br /&gt;
On AmigaOS we have &#039;&#039;&#039;CodeBench&#039;&#039;&#039; to improve and automate our coding sessions. CodeBench provides a text editor with &amp;quot;syntax highlighting&amp;quot; which means that it color-codes text on the basis of what it is: comments, commands, strings, etc.  CodeBench also provides a GUI for GCC - click a button to compile, review the results in a window.  There are even more features for more serious projects.&lt;br /&gt;
&lt;br /&gt;
CodeBench can be downloaded from the  [http://codebench.co.uk/downloads.php website] of the developer, SImon Archer.  Once downloaded, you can double-click on the archive to open it in the AmigaOS &#039;&#039;&#039;Unarc&#039;&#039;&#039; utility and decompress the files to your RAM Disk. Once finished, you will find an &amp;quot;Install CodeBench&amp;quot; installer program icon. When you run the installer, it will confirm whether you are upgrading or making a new install and ask you for a location.&lt;br /&gt;
&lt;br /&gt;
Once this process is done, you&#039;re ready to start a project in CodeBench. CodeBench comes with comprehensive documentation on itself in web format (that can also be accessed [http://codebench.co.uk/docs/codebench.html here]). &lt;br /&gt;
&lt;br /&gt;
== Testing CodeBench: Hello World ==&lt;br /&gt;
&lt;br /&gt;
The first thing you can do with CodeBench is to start a test project to how things work.  At [http://codebench.co.uk/docs/started.html this page] you can find information on on starting a project.  Basically, it&#039;s a matter of clicking the Start Project button, setting a few names and variables and entering a path for your project.  &lt;br /&gt;
&lt;br /&gt;
Once the new project is established, then you can use the &amp;quot;Editor/Create New File...&amp;quot; menu item to start a new source file.  If you copy the above &amp;quot;Hello World&amp;quot; source code and paste it into the editor and save the source as &amp;quot;hello-world.c&amp;quot; then you will be ready for compiling.  &lt;br /&gt;
&lt;br /&gt;
In the CodeBench tool bar window, click the green &amp;quot;Build&amp;quot; button and CodeBench will automatically prepare, compile and link your project into an executable program.  &lt;br /&gt;
A Build window will appear that will show the status of the building of your project.  Assuming your code compiles without errors, you will then see a Run button with a play icon in the CodeBench toolbar.  Clicking that button will bring up a window to let you run your program.&lt;br /&gt;
&lt;br /&gt;
== Testing CodeBench: Hello with a GUI ==&lt;br /&gt;
&lt;br /&gt;
Once you start coding with CodeBench, you will find it provides a number of aids to help with coding: such as highlighting or coloring the source code by type, letting you work with a number of sources at one time, letting you access AmigaOS documents by shift-double-clicking on AmigaOS functions and providing a quick way to track compiling errors into the source code.&lt;br /&gt;
&lt;br /&gt;
With CodeBench you can easily jump into more advanced coding, such as our old &amp;quot;Hello World&amp;quot; program with a modern GUI.  Just copy and paste the following source into a new project and try to compile it:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
#include &amp;lt;dos/dos.h&amp;gt;&lt;br /&gt;
#include &amp;lt;classes/window.h&amp;gt;&lt;br /&gt;
#include &amp;lt;gadgets/button.h&amp;gt;&lt;br /&gt;
#include &amp;lt;gadgets/layout.h&amp;gt;&lt;br /&gt;
#include &amp;lt;images/label.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;proto/intuition.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/exec.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
    // Create a window with a label and button.&lt;br /&gt;
   &lt;br /&gt;
    Object* winobj = IIntuition-&amp;gt;NewObject(NULL, &amp;quot;window.class&amp;quot;,&lt;br /&gt;
        WA_Title, &amp;quot;Hello World Example&amp;quot;,&lt;br /&gt;
        WA_Activate, TRUE,&lt;br /&gt;
        WA_DepthGadget, TRUE,&lt;br /&gt;
        WA_DragBar, TRUE,&lt;br /&gt;
        WA_CloseGadget, TRUE,&lt;br /&gt;
        WA_SizeGadget, TRUE,&lt;br /&gt;
        WINDOW_Position, WPOS_CENTERMOUSE,&lt;br /&gt;
&lt;br /&gt;
        WINDOW_Layout, IIntuition-&amp;gt;NewObject(NULL, &amp;quot;layout.gadget&amp;quot;,&lt;br /&gt;
            LAYOUT_Orientation, LAYOUT_ORIENT_VERT,&lt;br /&gt;
            LAYOUT_SpaceOuter, TRUE,&lt;br /&gt;
            LAYOUT_DeferLayout, TRUE,&lt;br /&gt;
&lt;br /&gt;
            LAYOUT_AddImage, IIntuition-&amp;gt;NewObject(NULL, &amp;quot;label.image&amp;quot;,&lt;br /&gt;
                LABEL_Text, &amp;quot;Hello, World&amp;quot;,&lt;br /&gt;
                TAG_END),&lt;br /&gt;
&lt;br /&gt;
            LAYOUT_AddChild, IIntuition-&amp;gt;NewObject(NULL, &amp;quot;button.gadget&amp;quot;,&lt;br /&gt;
                GA_RelVerify, TRUE,&lt;br /&gt;
                GA_Text, &amp;quot;Quit&amp;quot;,&lt;br /&gt;
                TAG_END),&lt;br /&gt;
           TAG_END),&lt;br /&gt;
        TAG_END);&lt;br /&gt;
&lt;br /&gt;
    if (winobj != NULL)&lt;br /&gt;
    {&lt;br /&gt;
        //  Open the window.&lt;br /&gt;
        struct Window *window = (struct Window *) IIntuition-&amp;gt;IDoMethod(winobj, WM_OPEN);&lt;br /&gt;
&lt;br /&gt;
        if (window != NULL)&lt;br /&gt;
        {&lt;br /&gt;
            // Obtain the window wait signal mask.&lt;br /&gt;
&lt;br /&gt;
            uint32 signal = 0;&lt;br /&gt;
            IIntuition-&amp;gt;GetAttr(WINDOW_SigMask, winobj, &amp;amp;signal);&lt;br /&gt;
&lt;br /&gt;
            // Input Event Loop&lt;br /&gt;
&lt;br /&gt;
            BOOL done = FALSE;&lt;br /&gt;
&lt;br /&gt;
            while (!done)&lt;br /&gt;
            {&lt;br /&gt;
                uint32 wait = IExec-&amp;gt;Wait(signal | SIGBREAKF_CTRL_C);&lt;br /&gt;
&lt;br /&gt;
                if ( wait &amp;amp; SIGBREAKF_CTRL_C )&lt;br /&gt;
                {&lt;br /&gt;
                    done = TRUE;&lt;br /&gt;
                    break;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                if ( wait &amp;amp; signal )&lt;br /&gt;
                {&lt;br /&gt;
                    uint32 result = WMHI_LASTMSG;&lt;br /&gt;
                    int16 code = 0;&lt;br /&gt;
&lt;br /&gt;
                    while ((result = IIntuition-&amp;gt;IDoMethod(winobj, WM_HANDLEINPUT, &amp;amp;code)) != WMHI_LASTMSG)&lt;br /&gt;
                    {&lt;br /&gt;
                        switch (result &amp;amp; WMHI_CLASSMASK)&lt;br /&gt;
                        {&lt;br /&gt;
                            case WMHI_GADGETUP:&lt;br /&gt;
                                done = TRUE;&lt;br /&gt;
                                break;&lt;br /&gt;
&lt;br /&gt;
                            case WMHI_CLOSEWINDOW:&lt;br /&gt;
                                window = NULL;&lt;br /&gt;
                                done = TRUE;&lt;br /&gt;
                                break;&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        /* Disposing of the window object will also close the window if it is&lt;br /&gt;
         * already opened and all attached objects.&lt;br /&gt;
         */&lt;br /&gt;
        IIntuition-&amp;gt;DisposeObject(winobj);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return RETURN_OK;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once you have built and run this example program the following GUI will be produced:&lt;br /&gt;
&lt;br /&gt;
[[File:HelloWorldWindow.png]]&lt;/div&gt;</summary>
		<author><name>Costel Mincea</name></author>
	</entry>
	<entry>
		<id>https://wiki.amigaos.net/w/index.php?title=Intuition_Borders&amp;diff=12558</id>
		<title>Intuition Borders</title>
		<link rel="alternate" type="text/html" href="https://wiki.amigaos.net/w/index.php?title=Intuition_Borders&amp;diff=12558"/>
		<updated>2025-01-26T19:32:23Z</updated>

		<summary type="html">&lt;p&gt;Costel Mincea: Text replacement - &amp;quot;&amp;lt;syntaxhighlight&amp;gt;&amp;quot; to &amp;quot;&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Creating Borders =&lt;br /&gt;
&lt;br /&gt;
This data type is called a Border since it was originally used to create border lines around display objects. It is actually a general purpose structure for drawing connected lines between any series of points.&lt;br /&gt;
&lt;br /&gt;
A Border is easier to use than an Image structure. Only the following need be specified to define a border:&lt;br /&gt;
&lt;br /&gt;
* An internal position component which is used in determining the final position of the border.&lt;br /&gt;
* A set of coordinate pairs for each vertex.&lt;br /&gt;
* A color for the lines.&lt;br /&gt;
* One of several drawing modes.&lt;br /&gt;
&lt;br /&gt;
== Border Structure Definition ==&lt;br /&gt;
&lt;br /&gt;
To use a border, the application must create one or more instances of the Border structure. Here is the specification:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct Border&lt;br /&gt;
    {&lt;br /&gt;
    WORD LeftEdge, TopEdge;&lt;br /&gt;
    UBYTE FrontPen, BackPen;&lt;br /&gt;
    UBYTE DrawMode;&lt;br /&gt;
    BYTE Count;&lt;br /&gt;
    WORD *XY;&lt;br /&gt;
    struct Border *NextBorder;&lt;br /&gt;
    };&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here is a brief description of the fields of the Border structure.&lt;br /&gt;
&lt;br /&gt;
; LeftEdge, TopEdge&lt;br /&gt;
: These fields are used to determine the position of the Border relative to its base position (the base position is the upper left corner for requesters, menus, or gadgets and is specified in the call to DrawBorder() for windows and screens).&lt;br /&gt;
&lt;br /&gt;
; FrontPen, BackPen&lt;br /&gt;
: These fields contain color registers numbers. FrontPen is the color used to draw the lines. BackPen is currently unused.&lt;br /&gt;
&lt;br /&gt;
;DrawMode&lt;br /&gt;
: Set the DrawMode field to one of the following:&lt;br /&gt;
:{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| JAM1&lt;br /&gt;
| Use FrontPen to draw the line.&lt;br /&gt;
|-&lt;br /&gt;
| COMPLEMENT&lt;br /&gt;
| Change the pixels within the lines to their complement color.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
; Count&lt;br /&gt;
: Specify the number of data points used in this border. Each data point is described by two words of data in the XY array.&lt;br /&gt;
&lt;br /&gt;
; XY&lt;br /&gt;
: A pointer to an array of coordinate pairs, one pair for each point. These coordinates are measured relative to the position of the border.&lt;br /&gt;
&lt;br /&gt;
; NextBorder&lt;br /&gt;
: This field is a pointer to another instance of a Border structure. Set this field to NULL if this is the last Border structure in the linked list.&lt;br /&gt;
&lt;br /&gt;
= Directly Drawing the Borders =&lt;br /&gt;
&lt;br /&gt;
Borders may be directly drawn by the application by calling the function DrawBorder().&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
VOID DrawBorder( struct RastPort *rp, struct Border *border,&lt;br /&gt;
                 LONG leftOffset, LONG topOffset );&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The rp argument is a pointer to the RastPort into which the border should be drawn. This rastport may come from a Window or Screen structure.&lt;br /&gt;
&lt;br /&gt;
The border argument is a pointer to a list of Border structures which are to be rendered. The list may contain a single Border structure.&lt;br /&gt;
&lt;br /&gt;
The leftOffset and topOffset arguments are the external component, or base position, for this list of Borders. The LeftEdge and TopEdge values of each Border structure are added to these to determine the Border position.&lt;br /&gt;
&lt;br /&gt;
Borders may also be indirectly drawn by attaching them to gadgets, menus or requesters.&lt;br /&gt;
&lt;br /&gt;
= Border Example =&lt;br /&gt;
&lt;br /&gt;
The following example draws a double border using two pens to create a shadow effect. The border is drawn in two positions to show the flexibility in positioning borders, note that it could also be attached to a menu, gadget or requester.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
** shadowborder.c - program to show the use of an Intuition Border.&lt;br /&gt;
*/&lt;br /&gt;
#include &amp;lt;exec/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;intuition/intuition.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;proto/exec.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/dos.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/intuition.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
struct Library *IntuitionBase = NULL;&lt;br /&gt;
&lt;br /&gt;
#define MYBORDER_LEFT   (0)&lt;br /&gt;
#define MYBORDER_TOP    (0)&lt;br /&gt;
&lt;br /&gt;
/* This is the border data. */&lt;br /&gt;
int16 myBorderData[] =&lt;br /&gt;
{&lt;br /&gt;
  0,0, 50,0, 50,30, 0,30, 0,0,&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
** main routine. Open required library and window and draw the images.&lt;br /&gt;
** This routine opens a very simple window with no IDCMP.  See the&lt;br /&gt;
** articles on &amp;quot;Windows&amp;quot; and &amp;quot;Input and Output Methods&amp;quot; for more info.&lt;br /&gt;
** Free all resources when done.&lt;br /&gt;
*/&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
  struct Screen   *screen;&lt;br /&gt;
  struct DrawInfo *drawinfo;&lt;br /&gt;
  struct Window   *win;&lt;br /&gt;
  struct Border    shineBorder;&lt;br /&gt;
  struct Border    shadowBorder;&lt;br /&gt;
&lt;br /&gt;
  uint32 mySHADOWPEN = 1;  /* set default values for pens */&lt;br /&gt;
  uint32 mySHINEPEN  = 2;  /* in case can&#039;t get info...   */&lt;br /&gt;
&lt;br /&gt;
  struct Library *IntuitionBase = IExec-&amp;gt;OpenLibrary(&amp;quot;intuition.library&amp;quot;, 50);&lt;br /&gt;
  IIntuition = (struct IntuitionIFace*)IExec-&amp;gt;GetInterface(IntuitionBase, &amp;quot;main&amp;quot;, 1, NULL);&lt;br /&gt;
  &lt;br /&gt;
  if (IIntuition != NULL)&lt;br /&gt;
  {&lt;br /&gt;
    if (screen = IIntuition-&amp;gt;LockPubScreen(NULL))&lt;br /&gt;
    {&lt;br /&gt;
      if (drawinfo = IIntuition-&amp;gt;GetScreenDrawInfo(screen))&lt;br /&gt;
      {&lt;br /&gt;
        /* Get a copy of the correct pens for the screen.&lt;br /&gt;
        ** This is very important in case the user or the&lt;br /&gt;
        ** application has the pens set in a unusual way.&lt;br /&gt;
        */&lt;br /&gt;
        mySHADOWPEN = drawinfo-&amp;gt;dri_Pens[SHADOWPEN];&lt;br /&gt;
        mySHINEPEN  = drawinfo-&amp;gt;dri_Pens[SHINEPEN];&lt;br /&gt;
&lt;br /&gt;
        IIntuition-&amp;gt;FreeScreenDrawInfo(screen,drawinfo);&lt;br /&gt;
      }&lt;br /&gt;
      &lt;br /&gt;
      IIntuition-&amp;gt;UnlockPubScreen(NULL,screen);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /* open a simple window on the workbench screen for displaying&lt;br /&gt;
    ** a border.  An application would probably never use such a&lt;br /&gt;
    ** window, but it is useful for demonstrating graphics...&lt;br /&gt;
    */&lt;br /&gt;
    if (win = IIntuition-&amp;gt;OpenWindowTags(NULL,&lt;br /&gt;
                        WA_PubScreen,  screen,&lt;br /&gt;
                        WA_RMBTrap,      TRUE,&lt;br /&gt;
                        TAG_END))&lt;br /&gt;
    {&lt;br /&gt;
      /* set information specific to the shadow component of the border */&lt;br /&gt;
      shadowBorder.LeftEdge   = MYBORDER_LEFT + 1;&lt;br /&gt;
      shadowBorder.TopEdge    = MYBORDER_TOP + 1;&lt;br /&gt;
      shadowBorder.FrontPen   = mySHADOWPEN;&lt;br /&gt;
      shadowBorder.NextBorder = &amp;amp;shineBorder;&lt;br /&gt;
&lt;br /&gt;
      /* set information specific to the shine component of the border */&lt;br /&gt;
      shineBorder.LeftEdge    = MYBORDER_LEFT;&lt;br /&gt;
      shineBorder.TopEdge     = MYBORDER_TOP;&lt;br /&gt;
      shineBorder.FrontPen    = mySHINEPEN;&lt;br /&gt;
      shineBorder.NextBorder  = NULL;&lt;br /&gt;
&lt;br /&gt;
      /* the following attributes are the same for both borders. */&lt;br /&gt;
      shadowBorder.BackPen    = shineBorder.BackPen   = 0;&lt;br /&gt;
      shadowBorder.DrawMode   = shineBorder.DrawMode  = JAM1;&lt;br /&gt;
      shadowBorder.Count      = shineBorder.Count     = 5;&lt;br /&gt;
      shadowBorder.XY         = shineBorder.XY        = myBorderData;&lt;br /&gt;
&lt;br /&gt;
      /* Draw the border at 10,10 */&lt;br /&gt;
      IIntuition-&amp;gt;DrawBorder(win-&amp;gt;RPort,&amp;amp;shadowBorder,10,10);&lt;br /&gt;
&lt;br /&gt;
      /* Draw the border again at 100,10 */&lt;br /&gt;
      IIntuition-&amp;gt;DrawBorder(win-&amp;gt;RPort,&amp;amp;shadowBorder,100,10);&lt;br /&gt;
&lt;br /&gt;
      /* Wait a bit, then quit.&lt;br /&gt;
      ** In a real application, this would be an event loop, like the&lt;br /&gt;
      ** one described in the Intuition Input and Output Methods article.&lt;br /&gt;
      */&lt;br /&gt;
      IDOS-&amp;gt;Delay(200);&lt;br /&gt;
&lt;br /&gt;
      IIntuition-&amp;gt;CloseWindow(win);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  IExec-&amp;gt;DropInterface((struct Interface*)IIntuition);&lt;br /&gt;
  IExec-&amp;gt;CloseLibrary(IntuitionBase);&lt;br /&gt;
&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Border Colors and Drawing Modes =&lt;br /&gt;
&lt;br /&gt;
Borders can select their colors from the values set in the color registers for the screen in which they are rendered. The available number of colors and palette settings are screen attributes and may not be changed through border rendering.&lt;br /&gt;
&lt;br /&gt;
Two drawing modes pertain to border lines: JAM1 and COMPLEMENT. To draw the line in a specific color, use the JAM1 draw mode. This mode converts each pixel in the line to the color set in the FrontPen field.&lt;br /&gt;
&lt;br /&gt;
Selecting the COMPLEMENT draw mode causes the line to be drawn in an exclusive-or mode that inverts the color of each pixel within the line. The data bits of the pixel are changed to their binary complement. This complement is formed by reversing all bits in the binary representation of the color register number. In a three bitplane display, for example, color 6 is 110 in binary. In COMPLEMENT draw mode, if a pixel is color 6, it will be changed to the 001 (binary), which is color 1. Note that a border drawn in COMPLEMENT mode can be removed from a static display by drawing the border again in the same position.&lt;br /&gt;
&lt;br /&gt;
= Border Coordinates =&lt;br /&gt;
&lt;br /&gt;
Intuition draws lines between points that are specified as sets of X, Y coordinates. Border data does not have to be in Chip memory.&lt;br /&gt;
&lt;br /&gt;
The XY field contains a pointer to an array of coordinate pairs. All of these coordinates are offsets relative to the Border position, which is determined by the sum of the external and internal position components as described above. The coordinate pairs are ordered sequentially. The first two numbers make up the first coordinate pair, the next two numbers make up the second pair, and so on. Within a coordinate pair, the first number is the X offset and the second number is the Y offset.&lt;br /&gt;
&lt;br /&gt;
The first coordinate pair describes the starting point of the first line. When the Border is rendered, a line is drawn between each pair of points. The first line is drawn from point one to point two, the second line is drawn from point two to point three, and so on, until the final point is reached.&lt;br /&gt;
&lt;br /&gt;
The numbers specified in the XY array may be positive or negative. Negative values move up and to the left relative to the Border position, positive values move down and to the right. Again, the Border position is determined by adding the external position component and the internal position component. For example, a Border attached to a Gadget has an external component equal to the upper left corner of the gadget’s select box. The internal component is set within the Border structure itself. These two components are added together and offsets from the resulting position, specified within the XY array, determine where the lines of the Border will appear.&lt;br /&gt;
&lt;br /&gt;
Suppose the top left corner of the select box of the gadget is at window position (10,5). If the Border has LeftEdge set to 10 and TopEdge set to 10, then the Border is positioned at (10+10,5+10), that is (20,15). All XY coordinates will be relative to this Border position. If the XY array contains ‘0,5, 15,5, 15,0’, then the relative coordinates will be (0,5), (15,5) and (15,0). Adding each coordinate to the Border position gives the absolute position of the lines within the window. This Border will draw two lines in the window, one from (20,20) to (35,20) and the second from (35,20) to (35,15).&lt;br /&gt;
&lt;br /&gt;
[[File:LibFig8-3.png|frame|center|Example of Border Relative Position]]&lt;br /&gt;
&lt;br /&gt;
To create a border that is outside the select box of a gadget, specify negative values in the internal component or use negative values for the initial XY values. For example, setting LeftEdge to -1 and TopEdge to -1 moves the position of the Border one pixel above and one pixel to the left of the gadget’s select box.&lt;br /&gt;
&lt;br /&gt;
= Linking Borders =&lt;br /&gt;
&lt;br /&gt;
The NextBorder field can point to another instance of a Border structure. This allows complex graphic objects to be created by linking together Border structures, each with its own data points, color and draw mode. This might be used, for instance, to draw a double border around a requester or gadget where the outer border is a second Border structure, linked to the first inner border.&lt;br /&gt;
&lt;br /&gt;
Note that the borders can share data. For instance, to create a border with a shadow, link two borders together each of which points to the same XY data. Set the first border to draw in a dark pen (such as the SHADOWPEN from the screen’s DrawInfo structure) and position the border down and to the right a few pixels by changing LeftEdge and TopEdge in the Border structure.&lt;br /&gt;
&lt;br /&gt;
The second border should be set to a bright pen (such as the SHINEPEN in the screen’s DrawInfo structure). When the border is drawn, the first border will draw in a dark color and then the second border will be drawn over it in a light color. Since they use the same data set, and the dark border is shifted down and to the right, the border will have a three dimensional appearance. This technique is demonstrated in the example listed earlier in this section.&lt;/div&gt;</summary>
		<author><name>Costel Mincea</name></author>
	</entry>
	<entry>
		<id>https://wiki.amigaos.net/w/index.php?title=Gameport_Device&amp;diff=12557</id>
		<title>Gameport Device</title>
		<link rel="alternate" type="text/html" href="https://wiki.amigaos.net/w/index.php?title=Gameport_Device&amp;diff=12557"/>
		<updated>2025-01-26T19:32:20Z</updated>

		<summary type="html">&lt;p&gt;Costel Mincea: Text replacement - &amp;quot;&amp;lt;syntaxhighlight&amp;gt;&amp;quot; to &amp;quot;&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Devices|Gameport]]{{NeedUpdate}}&lt;br /&gt;
== Gameport Device ==&lt;br /&gt;
&lt;br /&gt;
The gameport device manages access to the Amiga gameport connectors for the operating system. It enables the Amiga to interface with various external pointing devices like mice (two and three button), joysticks, trackballs and light pens. There are two units in the gameport device, unit 0 and unit 1.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Amiga Gameport Controllers&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!&lt;br /&gt;
! Unit 0&lt;br /&gt;
! Unit 1&lt;br /&gt;
|-&lt;br /&gt;
| A3000&lt;br /&gt;
| Front Connector&lt;br /&gt;
| Back Connector&lt;br /&gt;
|-&lt;br /&gt;
| A2000&lt;br /&gt;
| Left Connector&lt;br /&gt;
| Right Connector&lt;br /&gt;
|-&lt;br /&gt;
| A1000&lt;br /&gt;
| 1&lt;br /&gt;
| 2&lt;br /&gt;
|-&lt;br /&gt;
| A500&lt;br /&gt;
| 1 JOYSTICK&lt;br /&gt;
| 2 JOYSTICK&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Gameport Device Commands and Functions ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Command&lt;br /&gt;
! Command Operation&lt;br /&gt;
|-&lt;br /&gt;
| CMD_CLEAR&lt;br /&gt;
| Clear the gameport input buffer.&lt;br /&gt;
|-&lt;br /&gt;
| GPD_ASKCTYPE&lt;br /&gt;
| Return the type of gameport controller being used.&lt;br /&gt;
|-&lt;br /&gt;
| GPD_ASKTRIGGER&lt;br /&gt;
| Return the conditions that have been preset for triggering.&lt;br /&gt;
|-&lt;br /&gt;
| GPD_READEVENT&lt;br /&gt;
| Read one or more gameport events.&lt;br /&gt;
|-&lt;br /&gt;
| GPD_SETCTYPE&lt;br /&gt;
| Set the type of the controller to be used.&lt;br /&gt;
|-&lt;br /&gt;
| GPD_SETTRIGGER&lt;br /&gt;
| Preset the conditions that will trigger a gameport event.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{{Note|title=Who Runs The Mouse?|text=When the input device or Intution is operating, unit 0 is usually dedicated to gathering mouse events. The input device uses the gameport device to read the mouse events. (For applications that take over the machine without starting up the input device or Intuition, unit 0 can perform the same functions as unit 1.) See [[Input_Device|Input Device]] for more information on the input device.}}&lt;br /&gt;
&lt;br /&gt;
== Device Interface ==&lt;br /&gt;
&lt;br /&gt;
The gameport device operates like the other Amiga devices. To use it, you must first open the gameport device, then send I/O requests to it, and then close it when finished. See [[Exec_Device_I/O|Exec Device I/O]] for general information on device usage.&lt;br /&gt;
&lt;br /&gt;
The I/O request used by the gameport device is called IOStdReq.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct IOStdReq&lt;br /&gt;
{&lt;br /&gt;
    struct  Message io_Message;&lt;br /&gt;
    struct  Device  *io_Device;     /* device node pointer  */&lt;br /&gt;
    struct  Unit    *io_Unit;       /* unit (driver private)*/&lt;br /&gt;
    UWORD   io_Command;             /* device command */&lt;br /&gt;
    UBYTE   io_Flags;&lt;br /&gt;
    BYTE    io_Error;               /* error or warning num */&lt;br /&gt;
    ULONG   io_Actual;              /* actual number of bytes transferred */&lt;br /&gt;
    ULONG   io_Length;              /* requested number bytes transferred*/&lt;br /&gt;
    APTR    io_Data;                /* points to data area */&lt;br /&gt;
    ULONG   io_Offset;              /* offset for block structured devices */&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See the include file exec/io.h for the complete structure definition.&lt;br /&gt;
&lt;br /&gt;
=== Opening the Gameport Device ===&lt;br /&gt;
&lt;br /&gt;
Three primary steps are required to open the gameport device:&lt;br /&gt;
&lt;br /&gt;
* Create a message port using CreatePort(). Reply messages from the device must be directed to a message port.&lt;br /&gt;
* Create an I/O request structure of type IOStdReq. The IOStdReq structure is created by the CreateExtIO() function. CreateExtIO() will initialize the I/O request with your reply port.&lt;br /&gt;
* Open the gameport device. Call OpenDevice(), passing the I/O request and and indicating the unit you wish to use.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;struct MsgPort *GameMP;   /* Message port pointer */&lt;br /&gt;
struct IOStdReq *GameIO;  /* I/O request pointer */&lt;br /&gt;
&lt;br /&gt;
  /* Create port for gameport device communications */&lt;br /&gt;
if (!(GameMP = CreatePort(&amp;amp;quot;RKM_game_port&amp;amp;quot;,0)))&lt;br /&gt;
    cleanexit(&amp;amp;quot; Error: Can&#039;t create port\n&amp;amp;quot;,RETURN_FAIL);&lt;br /&gt;
&lt;br /&gt;
  /* Create message block for device I/O */&lt;br /&gt;
if (!(GameIO = CreateExtIO(GameMP,sizeof(struct IOStdReq))))&lt;br /&gt;
    cleanexit(&amp;amp;quot; Error: Can&#039;t create I/O request\n&amp;amp;quot;,RETURN_FAIL);&lt;br /&gt;
&lt;br /&gt;
  /* Open the right/back (unit 1, number 2) gameport.device unit */&lt;br /&gt;
if (error=OpenDevice(&amp;amp;quot;gameport.device&amp;amp;quot;,1,GameIO,0))&lt;br /&gt;
    cleanexit(&amp;amp;quot; Error: Can&#039;t open gameport.device\n&amp;amp;quot;,RETURN_FAIL);&amp;lt;/pre&amp;gt;&lt;br /&gt;
The gameport commands are unit specific. The unit number specified in the call to OpenDevice() determines which unit is acted upon.&lt;br /&gt;
&lt;br /&gt;
=== Gameport Device Controllers ===&lt;br /&gt;
&lt;br /&gt;
The Amiga has five gameport device controller types.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Gameport Device Controllers&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Controller Type&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| GPCT_MOUSE&lt;br /&gt;
| Mouse controller&lt;br /&gt;
|-&lt;br /&gt;
| GPCT_ABSJOYSTICK&lt;br /&gt;
| Absolute (digital) joystick&lt;br /&gt;
|-&lt;br /&gt;
| GPCT_RELJOYSTICK&lt;br /&gt;
| Relative (digital) joystick&lt;br /&gt;
|-&lt;br /&gt;
| GPCT_ALLOCATED&lt;br /&gt;
| Custom controller&lt;br /&gt;
|-&lt;br /&gt;
| GPCT_NOCONTROLLER&lt;br /&gt;
| No controller&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
To use the gameport device, you must define the type of device connected to the gameport and define how the device is to respond. The gameport device can be set up to return the controller status immediately or only when certain conditions have been met.&lt;br /&gt;
&lt;br /&gt;
When a gameport device unit reponds to a request for input, it creates an input event. The contents of the input event will vary based on the type of device and the trigger conditions you have declared.&lt;br /&gt;
&lt;br /&gt;
* A mouse controller can report input events for one, two, or three buttons and for positive or negative (x,y) movements. A trackball controller or car-driving controller is generally of the same type and can be declared as a mouse controller.&lt;br /&gt;
&lt;br /&gt;
* An absolute joystick reports one single event for each change of its current location. If, for example, the joystick is centered and the user pushes the stick forward and holds it in that position, only one single forward-switch event will be generated.&lt;br /&gt;
&lt;br /&gt;
* A relative joystick, on the other hand, is comparable to an absolute joystick with “autorepeat” installed. As long as the user holds the stick in a position other than centered, the gameport device continues to generate position reports.&lt;br /&gt;
&lt;br /&gt;
* There is currently no system software support for proportional joysticks or proportional controllers (e.g., paddles). If you write custom code to read proportional controllers or other controllers (e.g., light pen) make certain that you issue GPD_SETCTYPE (explained below) with controller type GPCT_ALLOCATED to insure that other applications know the connector is being used.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| &#039;&#039;GPCT_NOCONTROLLER&#039;&#039; The controller type GPCT_NOCONTROLLER is not a controller at all, but a flag to indicate that the unit is not being used at the present time.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Closing the Gameport Device ===&lt;br /&gt;
&lt;br /&gt;
Each OpenDevice() must eventually be matched by a call to CloseDevice().&lt;br /&gt;
&lt;br /&gt;
All I/O requests must be complete before CloseDevice(). If any requests are still pending, abort them with AbortIO() and remove them with WaitIO().&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;if (!(CheckIO(GameIO)))&lt;br /&gt;
    {&lt;br /&gt;
    AbortIO(GameIO);  /* Ask device to abort request, if pending */&lt;br /&gt;
    }&lt;br /&gt;
WaitIO((GameIO);   /* Wait for abort, then clean up */&lt;br /&gt;
CloseDevice(GameIO);&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Gameport Events ==&lt;br /&gt;
&lt;br /&gt;
A gameport event is an InputEvent structure which describes the following:&lt;br /&gt;
&lt;br /&gt;
* The class of the event - always set to IECLASS_RAWMOUSE for the gameport device.&lt;br /&gt;
* The subclass of the event - 0 for the left port; 1 for the right port.&lt;br /&gt;
* The code - which button and its state. (No report = 0xFF)&lt;br /&gt;
* The qualifier - only button and relative mouse bits are set.&lt;br /&gt;
* The position - either a data address or mouse position count.&lt;br /&gt;
* The time stamp - delta time since last report, returned as frame count in tv_secs field.&lt;br /&gt;
* The next event - pointer to next event.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;struct InputEvent GameEV&lt;br /&gt;
{&lt;br /&gt;
    struct InputEvent *ie_NextEvent;  /* next event */&lt;br /&gt;
    UBYTE    ie_Class;                /* input event class */&lt;br /&gt;
    UBYTE    ie_SubClass;             /* subclass of the class */&lt;br /&gt;
    UWORD    ie_Code;                 /* input event code */&lt;br /&gt;
    UWORD    ie_Qualifier;            /* event qualifiers in effect */&lt;br /&gt;
       union&lt;br /&gt;
       {&lt;br /&gt;
         struct&lt;br /&gt;
         {&lt;br /&gt;
          WORD   ie_x;                /* x position for the event */&lt;br /&gt;
          WORD   ie_y;                /* y position for the event */&lt;br /&gt;
         }  ie_xy;&lt;br /&gt;
         APTR ie_addr;&lt;br /&gt;
       } ie_position;&lt;br /&gt;
    struct timeval ie_TimeStamp;      /* delta time since last report&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
See the include file devices/inputevent.h for the complete structure definition and listing of input event fields.&lt;br /&gt;
&lt;br /&gt;
=== Reading Gameport Events ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You read gameport events by passing an I/O request to the device with GPD_READEVENT set in io_Command, the address of the InputEvent structure to store events set in io_Data and the size of the structure set in io_Length.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;struct InputEvent  GameEV;&lt;br /&gt;
struct IOStdRequest *GameIO;  /* Must be initialized prior to using */&lt;br /&gt;
&lt;br /&gt;
void send_read_request()&lt;br /&gt;
{&lt;br /&gt;
GameIO-&amp;amp;gt;io_Command = GPD_READEVENT;  /* Read events */&lt;br /&gt;
GameIO-&amp;amp;gt;io_Length = sizeof (struct InputEvent);&lt;br /&gt;
GameIO-&amp;amp;gt;io_Data = (APTR)&amp;amp;amp;GameEV;     /* put events in GameEV*/&lt;br /&gt;
SendIO(GameIO);                      /* Asynchronous */&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
=== Setting Gameport Event Trigger Conditions ===&lt;br /&gt;
&lt;br /&gt;
You set the conditions that can trigger a gameport event by passing an I/O request to the device with GPD_SETTRIGGER set in io_Command and the address of a GamePortTrigger structure set in io_Data.&lt;br /&gt;
&lt;br /&gt;
The information needed for gameport trigger setting is placed into a GamePortTrigger data structure which is defined in the include file devices/gameport.h.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct GamePortTrigger&lt;br /&gt;
{&lt;br /&gt;
    UWORD    gpt_Keys;      /* key transition triggers */&lt;br /&gt;
    UWORD    gpt_Timeout;   /* time trigger (vertical blank units) */&lt;br /&gt;
    UWORD    gpt_XDelta;    /* X distance trigger */&lt;br /&gt;
    UWORD    gpt_YDelta;    /* Y distance trigger */&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A few points to keep in mind with the GPD_SETTRIGGER command are:&lt;br /&gt;
&lt;br /&gt;
* Setting GPTF_UPKEYS enables the reporting of upward transitions. Setting GPTF_DOWNKEYS enables the reporting of downward transitions. These flags may both be specified.&lt;br /&gt;
&lt;br /&gt;
* The field gpt_Timeout specifies the time interval (in vertical blank units) between reports in the absence of another trigger condition. In other words, an event is generated every gpt_Timeout ticks. Vertical blank units may differ from country to country (e.g 60 Hz NTSC, 50 Hz PAL). To find out the exact frequency use this code fragment:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;exec/execbase.h&amp;gt;&lt;br /&gt;
extern struct ExecBase *SysBase;&lt;br /&gt;
&lt;br /&gt;
UBYTE get_frequency(void)&lt;br /&gt;
{&lt;br /&gt;
  return((UBYTE)SysBase-&amp;gt;VBlankFrequency);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* The gpt_XDelta and gpt_YDelta fields specify the x and y distances which, if exceeded, trigger a report.&lt;br /&gt;
&lt;br /&gt;
For a mouse controller, you can trigger on a certain minimum-sized move in either the x or y direction, on up or down transitions of the mouse buttons, on a timed basis, or any combination of these conditions.&lt;br /&gt;
&lt;br /&gt;
For example, suppose you normally signal mouse events if the mouse moves at least 10 counts in either the x or y directions. If you are moving the cursor to keep up with mouse movements and the user moves the mouse less than 10 counts, after a period of time you will want to update the position of the cursor to exactly match the mouse position. Thus the timed report of current mouse counts would be preferred. The following structure would be used:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#define XMOVE 10&lt;br /&gt;
#define YMOVE 10&lt;br /&gt;
&lt;br /&gt;
struct GamePortTrigger GameTR =&lt;br /&gt;
{&lt;br /&gt;
    GPTF_UPKEYS | GPTF_DOWNKEYS,   /* trigger on all key transitions */&lt;br /&gt;
    1800,                          /* and every 36(PAL) or 30(NTSC) seconds */&lt;br /&gt;
    XMOVE,                         /* for any 10 in an x or y direction */&lt;br /&gt;
    YMOVE&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For a joystick controller, you can select timed reports as well as button-up and button-down report trigger conditions. For an absolute joystick specify a value of one (1) for the GameTR_XDelta and GameTR_YDelta fields or you will not get any direction events. You set the trigger conditions by using the following code or its equivalent:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
struct IOStdReq *GameIO;&lt;br /&gt;
&lt;br /&gt;
void set_trigger_conditions(struct GamePortTrigger *GameTR)&lt;br /&gt;
{&lt;br /&gt;
GameIO-&amp;amp;gt;io_Command = GPD_SETTRIGGER;    /* set trigger conditions */&lt;br /&gt;
GameIO-&amp;amp;gt;io_Data = (APTR)GameTR;         /* from GameTR */&lt;br /&gt;
GameIO-&amp;amp;gt;io_Length = sizeof(struct GamePortTrigger);&lt;br /&gt;
DoIO(GameIO);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| &#039;&#039;Triggers and Reads.&#039;&#039; If a task sets trigger conditions and does not ask for the position reports the gameport device will queue them up anyway. If the trigger conditions occur again and the gameport device buffer is filled, the additional triggers will be ignored until the buffer is read by a device read request (GPD_READEVENT) or a system CMD_CLEAR command flushes the buffer.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Determining the Trigger Conditions ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You determine the conditions required for triggering gameport events by passing an I/O request to the device with GPD_ASKTRIGGER set in io_Command, the length of the GamePortTrigger structure set in io_Length and the address of the structure set in io_Data. The gameport device will respond with the event trigger conditions currently set.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;struct IOStdReq *GameIO;  /* Must be initialized prior to using */&lt;br /&gt;
&lt;br /&gt;
struct GamePortTrigger GameTR;&lt;br /&gt;
&lt;br /&gt;
void get_trigger_conditions(struct GamePortTrigger *GameTR)&lt;br /&gt;
{&lt;br /&gt;
GameIO-&amp;amp;gt;io_Command = GPD_ASKTRIGGER;    /* get type of triggers */&lt;br /&gt;
GameIO-&amp;amp;gt;io_Data = (APTR)GameTR;         /* place data here */&lt;br /&gt;
GameIO-&amp;amp;gt;io_Length= sizeof(GameTR);&lt;br /&gt;
DoIO(GameIO);&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Setting and Reading the Controller Type ==&lt;br /&gt;
&lt;br /&gt;
=== Determining the Controller Type ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You determine the type of controller being used by passing an I/O request to the device with GPD_ASKCTYPE set in io_Command, 1 set in io_Length and the number of the unit set in io_Unit. The gameport device will respond with the type of controller being used.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;struct IOStdReq *GameIO;  /* Must be initialized prior to using */&lt;br /&gt;
&lt;br /&gt;
BYTE GetControllerType()&lt;br /&gt;
{&lt;br /&gt;
BYTE controller_type = 0;&lt;br /&gt;
&lt;br /&gt;
GameIO-&amp;amp;gt;io_Command = GPD_ASKCTYPE;         /* get type of controller */&lt;br /&gt;
GameIO-&amp;amp;gt;io_Data = (APTR)&amp;amp;amp;controller_type;  /* place data here */&lt;br /&gt;
GameIO-&amp;amp;gt;io_Length = 1;&lt;br /&gt;
DoIO(GameIO);&lt;br /&gt;
return (controller_type);&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
The BYTE value returned corresponds to one of the five controller types noted above.&lt;br /&gt;
&lt;br /&gt;
=== Setting the Controller Type ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You set the type of gameport controller by passing an I/O request to the device with GPD_SETCTYPE set in io_Command, 1 set in io_Length and the address of the byte variable describing the controller type set in io_Data.&lt;br /&gt;
&lt;br /&gt;
The gameport device is a shared device; many tasks may have it open at any given time. Hence, a high level protocol has been established to prevent multiple tasks from reading the same unit at the same time.&lt;br /&gt;
&lt;br /&gt;
==== Three Step Protocol for Using the Gameport Device ====&lt;br /&gt;
&lt;br /&gt;
Send GPD_ASKCTYPE to the device and check for a GPCT_NOCONTROLLER return. &#039;&#039;Never&#039;&#039; issue GPD_SETCTYPE without checking whether the desired gameport unit is in use.&lt;br /&gt;
&lt;br /&gt;
If GPCT_NOCONTROLLER is returned, you have access to the gameport. Set the allocation flag to GPCT_MOUSE, GPCT_ABSJOYSTICK or GPCT_RELJOYSTICK if you use a system supported controller, or GPCT_ALLOCATED if you use a custom controller.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
struct IOStdReq *GameIO;  /* Must be initialized prior to using */&lt;br /&gt;
&lt;br /&gt;
BOOL set_controller_type(type)&lt;br /&gt;
BYTE type;&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
BOOL success = FALSE;&lt;br /&gt;
BYTE controller_type = 0;&lt;br /&gt;
&lt;br /&gt;
Forbid();                           /*critical section start */&lt;br /&gt;
GameIO-&amp;amp;gt;io_Command = GPD_ASKCTYPE;  /* inquire current status */&lt;br /&gt;
GameIO-&amp;amp;gt;io_Length = 1;&lt;br /&gt;
GameIO-&amp;amp;gt;io_Flags = IOF_QUICK;&lt;br /&gt;
GameIO-&amp;amp;gt;io_Data = (APTR)&amp;amp;amp;controller_type; /* put answer in here */&lt;br /&gt;
DoIO(GameIO);&lt;br /&gt;
&lt;br /&gt;
/* No one is using this device unit, let&#039;s claim it */&lt;br /&gt;
if (controller_type == GPCT_NOCONTROLLER)&lt;br /&gt;
    {&lt;br /&gt;
    GameIO-&amp;amp;gt;io_Command = GPD_SETCTYPE;/* set controller type */&lt;br /&gt;
    GameIO-&amp;amp;gt;io_Length = 1;&lt;br /&gt;
    GameIO-&amp;amp;gt;io_Data = (APTR)&amp;amp;amp;type;  /* set to input param */&lt;br /&gt;
    DoIO( GameIO);&lt;br /&gt;
    success = TRUE;&lt;br /&gt;
    UnitOpened = TRUE;&lt;br /&gt;
    }&lt;br /&gt;
Permit(); /* critical section end */&lt;br /&gt;
&lt;br /&gt;
/* success can be TRUE or FALSE, see above */&lt;br /&gt;
return(success);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The program must set the controller type back to GPCT_NOCONTROLLER upon exiting your program:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
struct IOStdReq *GameIO;  /* Must be initialized prior to using */&lt;br /&gt;
&lt;br /&gt;
void free_gp_unit()&lt;br /&gt;
{&lt;br /&gt;
BYTE type = GPCT_NOCONTROLLER;&lt;br /&gt;
GameIO-&amp;amp;gt;io_Command = GPD_SETCTYPE;  /* set controller type */&lt;br /&gt;
GameIO-&amp;amp;gt;io_Length = 1;&lt;br /&gt;
GameIO-&amp;amp;gt;io_Data = (APTR)&amp;amp;amp;type;      /* set to unused */&lt;br /&gt;
DoIO( GameIO);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This three step protocol allows applications to share the gameport device in a system compatible way.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| &#039;&#039;A Word About The Functions.&#039;&#039; The functions shown above are designed to be included in any application using the gameport device. The first function, set_controller_type(), would be the first thing done after opening the gameport device. The second function, free_gp_unit(), would be the last thing done before closing the device.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Joystick Example Program ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;/*&lt;br /&gt;
 * Absolute_Joystick.c&lt;br /&gt;
 *&lt;br /&gt;
 * Gameport device absolute joystick example&lt;br /&gt;
 *&lt;br /&gt;
 * Compile with SAS 5.10  lc -b1 -cfistq -v -y -L&lt;br /&gt;
 *&lt;br /&gt;
 * Run from CLI only&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
#include &amp;amp;lt;exec/types.h&amp;amp;gt;&lt;br /&gt;
#include &amp;amp;lt;exec/io.h&amp;amp;gt;&lt;br /&gt;
#include &amp;amp;lt;exec/memory.h&amp;amp;gt;&lt;br /&gt;
#include &amp;amp;lt;intuition/intuition.h&amp;amp;gt;&lt;br /&gt;
#include &amp;amp;lt;exec/exec.h&amp;amp;gt;&lt;br /&gt;
#include &amp;amp;lt;dos/dos.h&amp;amp;gt;&lt;br /&gt;
#include &amp;amp;lt;devices/gameport.h&amp;amp;gt;&lt;br /&gt;
#include &amp;amp;lt;devices/inputevent.h&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;amp;lt;clib/exec_protos.h&amp;amp;gt;&lt;br /&gt;
#include &amp;amp;lt;clib/alib_protos.h&amp;amp;gt;&lt;br /&gt;
#include &amp;amp;lt;clib/dos_protos.h&amp;amp;gt;&lt;br /&gt;
#include &amp;amp;lt;clib/intuition_protos.h&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;amp;lt;stdio.h&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
#ifdef LATTICE&lt;br /&gt;
int CXBRK(void) { return(0); }     /* Disable SAS CTRL/C handling */&lt;br /&gt;
int chkabort(void) { return(0); }  /* really */&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#define JOY_X_DELTA (1)&lt;br /&gt;
#define JOY_Y_DELTA (1)&lt;br /&gt;
#define TIMEOUT_SECONDS (10)&lt;br /&gt;
&lt;br /&gt;
extern struct ExecBase *SysBase;&lt;br /&gt;
&lt;br /&gt;
/*-----------------------------------------------------------------------&lt;br /&gt;
** Routine to print out some information for the user.&lt;br /&gt;
*/&lt;br /&gt;
VOID printInstructions(VOID)&lt;br /&gt;
{&lt;br /&gt;
printf(&amp;amp;quot;\n &amp;amp;gt;&amp;amp;gt;&amp;amp;gt; gameport.device Absolute Joystick Demo &amp;amp;lt;&amp;amp;lt;&amp;amp;lt;\n\n&amp;amp;quot;);&lt;br /&gt;
&lt;br /&gt;
if (SysBase-&amp;amp;gt;VBlankFrequency==60)&lt;br /&gt;
    printf(&amp;amp;quot; Running on NTSC system (60 Hz).\n&amp;amp;quot;);&lt;br /&gt;
else if (SysBase-&amp;amp;gt;VBlankFrequency==50)&lt;br /&gt;
    printf(&amp;amp;quot; Running on PAL system (50 Hz).\n&amp;amp;quot;);&lt;br /&gt;
&lt;br /&gt;
printf( &amp;amp;quot; Attach joystick to rear connector (A3000) and (A1000).\n&amp;amp;quot;&lt;br /&gt;
        &amp;amp;quot; Attach joystick to right connector (A2000).\n&amp;amp;quot;&lt;br /&gt;
        &amp;amp;quot; Attach joystick to left connector (A500).\n&amp;amp;quot;&lt;br /&gt;
        &amp;amp;quot; Then move joystick and click its button(s).\n\n&amp;amp;quot;&lt;br /&gt;
        &amp;amp;quot; To exit program press and release fire button 3 consecutive times. \n&amp;amp;quot;&lt;br /&gt;
        &amp;amp;quot; The program also exits if no activity occurs for 1 minute.\n\n&amp;amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*-----------------------------------------------------------------------&lt;br /&gt;
** print out information on the event received.&lt;br /&gt;
*/&lt;br /&gt;
BOOL check_move(struct InputEvent *game_event)&lt;br /&gt;
{&lt;br /&gt;
WORD xmove, ymove;&lt;br /&gt;
BOOL timeout=FALSE;&lt;br /&gt;
&lt;br /&gt;
xmove = game_event-&amp;amp;gt;ie_X;&lt;br /&gt;
ymove = game_event-&amp;amp;gt;ie_Y;&lt;br /&gt;
&lt;br /&gt;
if (xmove == 1)&lt;br /&gt;
    {&lt;br /&gt;
    if (ymove == 1) printf(&amp;amp;quot;RIGHT DOWN\n&amp;amp;quot;);&lt;br /&gt;
    else if (ymove == 0) printf(&amp;amp;quot;RIGHT\n&amp;amp;quot;);&lt;br /&gt;
    else if (ymove ==-1) printf(&amp;amp;quot;RIGHT UP\n&amp;amp;quot;);&lt;br /&gt;
    else printf(&amp;amp;quot;UNKNOWN Y\n&amp;amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
else if (xmove ==-1)&lt;br /&gt;
    {&lt;br /&gt;
    if (ymove == 1) printf(&amp;amp;quot;LEFT DOWN\n&amp;amp;quot;);&lt;br /&gt;
    else if (ymove == 0) printf(&amp;amp;quot;LEFT\n&amp;amp;quot;);&lt;br /&gt;
    else if (ymove ==-1) printf(&amp;amp;quot;LEFT UP\n&amp;amp;quot;);&lt;br /&gt;
    else printf(&amp;amp;quot;UNKNOWN Y\n&amp;amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
else if (xmove == 0)&lt;br /&gt;
    {&lt;br /&gt;
    if (ymove == 1) printf(&amp;amp;quot;DOWN\n&amp;amp;quot;);&lt;br /&gt;
    /* note that 0,0 can be a timeout, or a direction release. */&lt;br /&gt;
    else if (ymove == 0)&lt;br /&gt;
        {&lt;br /&gt;
        if (game_event-&amp;amp;gt;ie_TimeStamp.tv_secs &amp;amp;gt;=&lt;br /&gt;
                        (UWORD)(SysBase-&amp;amp;gt;VBlankFrequency) * TIMEOUT_SECONDS)&lt;br /&gt;
            {&lt;br /&gt;
            printf(&amp;amp;quot;TIMEOUT\n&amp;amp;quot;);&lt;br /&gt;
            timeout=TRUE;&lt;br /&gt;
            }&lt;br /&gt;
        else printf(&amp;amp;quot;RELEASE\n&amp;amp;quot;);&lt;br /&gt;
        }&lt;br /&gt;
    else if (ymove ==-1) printf(&amp;amp;quot;UP\n&amp;amp;quot;);&lt;br /&gt;
    else printf(&amp;amp;quot;UNKNOWN Y\n&amp;amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
else&lt;br /&gt;
    {&lt;br /&gt;
    printf(&amp;amp;quot;UNKNOWN X &amp;amp;quot;);&lt;br /&gt;
    if (ymove == 1) printf(&amp;amp;quot;unknown action\n&amp;amp;quot;);&lt;br /&gt;
    else if (ymove == 0) printf(&amp;amp;quot;unknown action\n&amp;amp;quot;);&lt;br /&gt;
    else if (ymove ==-1) printf(&amp;amp;quot;unknown action\n&amp;amp;quot;);&lt;br /&gt;
    else printf(&amp;amp;quot;UNKNOWN Y\n&amp;amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
return(timeout);&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*-----------------------------------------------------------------------&lt;br /&gt;
** send a request to the gameport to read an event.&lt;br /&gt;
*/&lt;br /&gt;
VOID send_read_request( struct InputEvent *game_event,&lt;br /&gt;
                        struct IOStdReq *game_io_msg)&lt;br /&gt;
{&lt;br /&gt;
game_io_msg-&amp;amp;gt;io_Command = GPD_READEVENT;&lt;br /&gt;
game_io_msg-&amp;amp;gt;io_Flags   = 0;&lt;br /&gt;
game_io_msg-&amp;amp;gt;io_Data    = (APTR)game_event;&lt;br /&gt;
game_io_msg-&amp;amp;gt;io_Length  = sizeof(struct InputEvent);&lt;br /&gt;
SendIO(game_io_msg);  /* Asynchronous - message will return later */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*-----------------------------------------------------------------------&lt;br /&gt;
** simple loop to process gameport events.&lt;br /&gt;
*/&lt;br /&gt;
VOID processEvents( struct IOStdReq *game_io_msg,&lt;br /&gt;
                    struct MsgPort  *game_msg_port)&lt;br /&gt;
{&lt;br /&gt;
BOOL timeout;&lt;br /&gt;
SHORT timeouts;&lt;br /&gt;
SHORT button_count;&lt;br /&gt;
BOOL  not_finished;&lt;br /&gt;
struct InputEvent game_event;   /* where input event will be stored */&lt;br /&gt;
&lt;br /&gt;
/* From now on, just read input events into the event buffer,&lt;br /&gt;
** one at a time.  READEVENT waits for the preset conditions.&lt;br /&gt;
*/&lt;br /&gt;
timeouts = 0;&lt;br /&gt;
button_count = 0;&lt;br /&gt;
not_finished = TRUE;&lt;br /&gt;
&lt;br /&gt;
while ((timeouts &amp;amp;lt; 6) &amp;amp;amp;&amp;amp;amp; (not_finished))&lt;br /&gt;
    {&lt;br /&gt;
    /* Send the read request */&lt;br /&gt;
    send_read_request(&amp;amp;amp;game_event,game_io_msg);&lt;br /&gt;
&lt;br /&gt;
    /* Wait for joystick action */&lt;br /&gt;
    Wait(1L &amp;amp;lt;&amp;amp;lt; game_msg_port-&amp;amp;gt;mp_SigBit);&lt;br /&gt;
    while (NULL != GetMsg(game_msg_port))&lt;br /&gt;
        {&lt;br /&gt;
        timeout=FALSE;&lt;br /&gt;
        switch(game_event.ie_Code)&lt;br /&gt;
            {&lt;br /&gt;
            case IECODE_LBUTTON:&lt;br /&gt;
                printf(&amp;amp;quot; FIRE BUTTON PRESSED \n&amp;amp;quot;);&lt;br /&gt;
                break;&lt;br /&gt;
&lt;br /&gt;
            case (IECODE_LBUTTON | IECODE_UP_PREFIX):&lt;br /&gt;
                printf(&amp;amp;quot; FIRE BUTTON RELEASED \n&amp;amp;quot;);&lt;br /&gt;
                if (3 == ++button_count)&lt;br /&gt;
                    not_finished = FALSE;&lt;br /&gt;
                break;&lt;br /&gt;
&lt;br /&gt;
            case IECODE_RBUTTON:&lt;br /&gt;
                printf(&amp;amp;quot; ALT BUTTON PRESSED \n&amp;amp;quot;);&lt;br /&gt;
                button_count = 0;&lt;br /&gt;
                break;&lt;br /&gt;
&lt;br /&gt;
            case (IECODE_RBUTTON | IECODE_UP_PREFIX):&lt;br /&gt;
                printf(&amp;amp;quot; ALT BUTTON RELEASED \n&amp;amp;quot;);&lt;br /&gt;
                button_count = 0;&lt;br /&gt;
                break;&lt;br /&gt;
&lt;br /&gt;
            case IECODE_NOBUTTON:&lt;br /&gt;
                /* Check for change in position */&lt;br /&gt;
                timeout = check_move(&amp;amp;amp;game_event);&lt;br /&gt;
                button_count = 0;&lt;br /&gt;
                break;&lt;br /&gt;
&lt;br /&gt;
            default:&lt;br /&gt;
                break;&lt;br /&gt;
            }&lt;br /&gt;
&lt;br /&gt;
        if (timeout)&lt;br /&gt;
            timeouts++;&lt;br /&gt;
        else&lt;br /&gt;
            timeouts=0;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*-----------------------------------------------------------------------&lt;br /&gt;
** allocate the controller if it is available.&lt;br /&gt;
** you allocate the controller by setting its type to something&lt;br /&gt;
** other than GPCT_NOCONTROLLER.  Before you allocate the thing&lt;br /&gt;
** you need to check if anyone else is using it (it is free if&lt;br /&gt;
** it is set to GPCT_NOCONTROLLER).&lt;br /&gt;
*/&lt;br /&gt;
BOOL set_controller_type(BYTE type, struct IOStdReq *game_io_msg)&lt;br /&gt;
{&lt;br /&gt;
BOOL success = FALSE;&lt;br /&gt;
BYTE controller_type = 0;&lt;br /&gt;
&lt;br /&gt;
/* begin critical section&lt;br /&gt;
** we need to be sure that between the time we check that the controller&lt;br /&gt;
** is available and the time we allocate it, no one else steals it.&lt;br /&gt;
*/&lt;br /&gt;
Forbid();&lt;br /&gt;
&lt;br /&gt;
game_io_msg-&amp;amp;gt;io_Command = GPD_ASKCTYPE;    /* inquire current status */&lt;br /&gt;
game_io_msg-&amp;amp;gt;io_Flags   = IOF_QUICK;&lt;br /&gt;
game_io_msg-&amp;amp;gt;io_Data    = (APTR)&amp;amp;amp;controller_type; /* put answer in here */&lt;br /&gt;
game_io_msg-&amp;amp;gt;io_Length  = 1;&lt;br /&gt;
DoIO(game_io_msg);&lt;br /&gt;
&lt;br /&gt;
/* No one is using this device unit, let&#039;s claim it */&lt;br /&gt;
if (controller_type == GPCT_NOCONTROLLER)&lt;br /&gt;
    {&lt;br /&gt;
    game_io_msg-&amp;amp;gt;io_Command = GPD_SETCTYPE;&lt;br /&gt;
    game_io_msg-&amp;amp;gt;io_Flags   = IOF_QUICK;&lt;br /&gt;
    game_io_msg-&amp;amp;gt;io_Data    = (APTR)&amp;amp;amp;type;&lt;br /&gt;
    game_io_msg-&amp;amp;gt;io_Length  = 1;&lt;br /&gt;
    DoIO( game_io_msg);&lt;br /&gt;
    success = TRUE;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
Permit(); /* critical section end */&lt;br /&gt;
return(success);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*-----------------------------------------------------------------------&lt;br /&gt;
** tell the gameport when to trigger.&lt;br /&gt;
*/&lt;br /&gt;
VOID set_trigger_conditions(struct GamePortTrigger *gpt,&lt;br /&gt;
                            struct IOStdReq *game_io_msg)&lt;br /&gt;
{&lt;br /&gt;
/* trigger on all joystick key transitions */&lt;br /&gt;
gpt-&amp;amp;gt;gpt_Keys   = GPTF_UPKEYS | GPTF_DOWNKEYS;&lt;br /&gt;
gpt-&amp;amp;gt;gpt_XDelta = JOY_X_DELTA;&lt;br /&gt;
gpt-&amp;amp;gt;gpt_YDelta = JOY_Y_DELTA;&lt;br /&gt;
/* timeout trigger every TIMEOUT_SECONDS second(s) */&lt;br /&gt;
gpt-&amp;amp;gt;gpt_Timeout = (UWORD)(SysBase-&amp;amp;gt;VBlankFrequency) * TIMEOUT_SECONDS;&lt;br /&gt;
&lt;br /&gt;
game_io_msg-&amp;amp;gt;io_Command = GPD_SETTRIGGER;&lt;br /&gt;
game_io_msg-&amp;amp;gt;io_Flags   = IOF_QUICK;&lt;br /&gt;
game_io_msg-&amp;amp;gt;io_Data    = (APTR)gpt;&lt;br /&gt;
game_io_msg-&amp;amp;gt;io_Length  = (LONG)sizeof(struct GamePortTrigger);&lt;br /&gt;
DoIO(game_io_msg);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*-----------------------------------------------------------------------&lt;br /&gt;
** clear the buffer.  do this before you begin to be sure you&lt;br /&gt;
** start in a known state.&lt;br /&gt;
*/&lt;br /&gt;
VOID flush_buffer(struct IOStdReq *game_io_msg)&lt;br /&gt;
{&lt;br /&gt;
game_io_msg-&amp;amp;gt;io_Command = CMD_CLEAR;&lt;br /&gt;
game_io_msg-&amp;amp;gt;io_Flags   = IOF_QUICK;&lt;br /&gt;
game_io_msg-&amp;amp;gt;io_Data    = NULL;&lt;br /&gt;
game_io_msg-&amp;amp;gt;io_Length  = 0;&lt;br /&gt;
DoIO(game_io_msg);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*-----------------------------------------------------------------------&lt;br /&gt;
** free the unit by setting its type back to GPCT_NOCONTROLLER.&lt;br /&gt;
*/&lt;br /&gt;
VOID free_gp_unit(struct IOStdReq *game_io_msg)&lt;br /&gt;
{&lt;br /&gt;
BYTE type = GPCT_NOCONTROLLER;&lt;br /&gt;
&lt;br /&gt;
game_io_msg-&amp;amp;gt;io_Command = GPD_SETCTYPE;&lt;br /&gt;
game_io_msg-&amp;amp;gt;io_Flags   = IOF_QUICK;&lt;br /&gt;
game_io_msg-&amp;amp;gt;io_Data    = (APTR)&amp;amp;amp;type;&lt;br /&gt;
game_io_msg-&amp;amp;gt;io_Length  = 1;&lt;br /&gt;
DoIO(game_io_msg);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*-----------------------------------------------------------------------&lt;br /&gt;
** allocate everything and go.  On failure, free any resources that&lt;br /&gt;
** have been allocated.  this program fails quietly--no error messages.&lt;br /&gt;
*/&lt;br /&gt;
VOID main(int argc,char **argv)&lt;br /&gt;
{&lt;br /&gt;
struct GamePortTrigger   joytrigger;&lt;br /&gt;
struct IOStdReq         *game_io_msg;&lt;br /&gt;
struct MsgPort          *game_msg_port;&lt;br /&gt;
&lt;br /&gt;
/* Create port for gameport device communications */&lt;br /&gt;
if (game_msg_port = CreatePort(&amp;amp;quot;RKM_game_port&amp;amp;quot;,0))&lt;br /&gt;
    {&lt;br /&gt;
    /* Create message block for device IO */&lt;br /&gt;
    if (game_io_msg = (struct IOStdReq *)&lt;br /&gt;
                      CreateExtIO(game_msg_port,sizeof(*game_io_msg)))&lt;br /&gt;
        {&lt;br /&gt;
        game_io_msg-&amp;amp;gt;io_Message.mn_Node.ln_Type = NT_UNKNOWN;&lt;br /&gt;
&lt;br /&gt;
        /* Open the right/back (unit 1, number 2) gameport.device unit */&lt;br /&gt;
        if (!OpenDevice(&amp;amp;quot;gameport.device&amp;amp;quot;,1,game_io_msg,0))&lt;br /&gt;
            {&lt;br /&gt;
            /* Set controller type to joystick */&lt;br /&gt;
            if (set_controller_type(GPCT_ABSJOYSTICK,game_io_msg))&lt;br /&gt;
                {&lt;br /&gt;
                /* Specify the trigger conditions */&lt;br /&gt;
                set_trigger_conditions(&amp;amp;amp;joytrigger,game_io_msg);&lt;br /&gt;
&lt;br /&gt;
                printInstructions();&lt;br /&gt;
&lt;br /&gt;
                /* Clear device buffer to start from a known state.&lt;br /&gt;
                ** There might still be events left&lt;br /&gt;
                */&lt;br /&gt;
                flush_buffer(game_io_msg);&lt;br /&gt;
&lt;br /&gt;
                processEvents(game_io_msg,game_msg_port);&lt;br /&gt;
&lt;br /&gt;
                /* Free gameport unit so other applications can use it ! */&lt;br /&gt;
                free_gp_unit(game_io_msg);&lt;br /&gt;
                }&lt;br /&gt;
            CloseDevice(game_io_msg);&lt;br /&gt;
            }&lt;br /&gt;
        DeleteExtIO(game_io_msg);&lt;br /&gt;
        }&lt;br /&gt;
    DeletePort(game_msg_port);&lt;br /&gt;
    }&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Additional Information on the Gameport Device ==&lt;br /&gt;
&lt;br /&gt;
Additional programming information on the gameport device can be found in the include files and the Autodocs for the gameport and input devices. Both are contained in the SDK.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Includes&lt;br /&gt;
|-&lt;br /&gt;
| devices/gameport.h&lt;br /&gt;
|-&lt;br /&gt;
| devices/inputevent.h&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! AutoDocs&lt;br /&gt;
|-&lt;br /&gt;
| gameport.doc&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Costel Mincea</name></author>
	</entry>
	<entry>
		<id>https://wiki.amigaos.net/w/index.php?title=AmiWest_2013_Lesson_4&amp;diff=12556</id>
		<title>AmiWest 2013 Lesson 4</title>
		<link rel="alternate" type="text/html" href="https://wiki.amigaos.net/w/index.php?title=AmiWest_2013_Lesson_4&amp;diff=12556"/>
		<updated>2025-01-26T19:31:42Z</updated>

		<summary type="html">&lt;p&gt;Costel Mincea: Text replacement - &amp;quot;&amp;lt;syntaxhighlight&amp;gt;&amp;quot; to &amp;quot;&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Simple IP Clients &amp;amp; Servers =&lt;br /&gt;
&lt;br /&gt;
Simple network access is easy!&lt;br /&gt;
&lt;br /&gt;
Developing applications that use TCP/IP &amp;quot;sockets&amp;quot; for network communications&lt;br /&gt;
have a reputation of being a challenging task.  But AmigaOS and its Roadshow &lt;br /&gt;
TCP/IP stack provides a couple of built-in shorthand mechanisms for easily&lt;br /&gt;
creating simple network clients and servers: the TCP: handler and Roadshow&#039;s&lt;br /&gt;
Superserver.&lt;br /&gt;
&lt;br /&gt;
Using these Roadshow shortcuts, creating simple network client and server&lt;br /&gt;
applications for single user or light-duty uses is no more complicated than&lt;br /&gt;
reading or writing a file.  The real challenge is understanding the protocol&lt;br /&gt;
to be used (f.e. HTTP communications with web browsers) and being careful not&lt;br /&gt;
to create a security risk on your or another user&#039;s Amiga.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==An Internet Client==&lt;br /&gt;
&lt;br /&gt;
First, we will look at creating a small client to retrieve some simple&lt;br /&gt;
information from an Internet website.  Such applications could be made&lt;br /&gt;
to retrieve basic information like stock quotes, email contents, &lt;br /&gt;
server conditions or other basic interactions.&lt;br /&gt;
&lt;br /&gt;
The Roadshow shortcut we will use is its built-in TCP: handler.  This is&lt;br /&gt;
mechanism that creates a virtual file system device  (&amp;quot;TCP:&amp;quot;) whenever&lt;br /&gt;
Roadhsow gets online.  To interact with a remote server, one3 opens a&lt;br /&gt;
file with the name being the URL of the server and port to be accessed.&lt;br /&gt;
&lt;br /&gt;
===Connect to the Server===&lt;br /&gt;
&lt;br /&gt;
When Roadshow gets online, it creates a virtual TCP: device.  To open&lt;br /&gt;
a connection, one opens a virtual file on the TCP: device to the URL and&lt;br /&gt;
port in question using this format:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
TCP:&amp;lt;server URL&amp;gt;/&amp;lt;port number&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For example, to connect to the website &amp;quot;www.wunderground.com&amp;quot; one would&lt;br /&gt;
use:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
	fileh = fopen(&amp;quot;TCP:www.wunderground.com/80&amp;quot;,&amp;quot;r+&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The file name starts with TCP:, then the website URL and finally the&lt;br /&gt;
port number - here &amp;quot;80&amp;quot; is site&#039;s HTTP port (used by almost all websites).&lt;br /&gt;
&lt;br /&gt;
Typically, the port number reflects the type of port or protocol that&lt;br /&gt;
is to be used.  Such protocols could be FTP (file transfer), POP/SMTP&lt;br /&gt;
(email) or many others.  Port 80 is usually used for HTTP communications&lt;br /&gt;
with websites.&lt;br /&gt;
&lt;br /&gt;
If the file open request is successful, your Amiga is then connected to&lt;br /&gt;
that server and any further interaction with the &amp;quot;fileh&amp;quot; file handle&lt;br /&gt;
communicates directly with that port on that server.  In this case,&lt;br /&gt;
we would have connected to a web server of the &amp;quot;Weather Underground&amp;quot;&lt;br /&gt;
website.&lt;br /&gt;
&lt;br /&gt;
===Talk to the Server===&lt;br /&gt;
&lt;br /&gt;
Once one has connected to a server, knowledge of the communications&lt;br /&gt;
protocol for that type of connection is required.   &lt;br /&gt;
&lt;br /&gt;
For each of those, a server expects a certain format of interaction to&lt;br /&gt;
proceed and respond.  Fortunately, common protocols are publicly&lt;br /&gt;
documented.&lt;br /&gt;
&lt;br /&gt;
	http://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers&lt;br /&gt;
&lt;br /&gt;
For each protocol there is usually an &amp;quot;RFC&amp;quot; document that describes how one&lt;br /&gt;
uses the protocol, interacts with the port and accomplishes that protocol&#039;s&lt;br /&gt;
goals.&lt;br /&gt;
&lt;br /&gt;
In the case of an  &amp;quot;HTTP&amp;quot; (or a &amp;quot;Hypertext Transfer Protocol&amp;quot;) connection to&lt;br /&gt;
a web server, we are usually expected to submit a &amp;quot;GET&amp;quot; request.  Here are&lt;br /&gt;
a couple more complete references on the HTTP protocol:&lt;br /&gt;
&lt;br /&gt;
	http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol&lt;br /&gt;
&lt;br /&gt;
	http://tools.ietf.org/html/rfc2616&lt;br /&gt;
&lt;br /&gt;
To keep things simple, lets mimic submitting a &amp;quot;GET&amp;quot; request (as if from IBrowse).&lt;br /&gt;
A simple HTTP version 1.1 GET request would include the following lines:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
	GET /&amp;lt;path&amp;gt; HTTP/1.1&lt;br /&gt;
	host: &amp;lt;domain&amp;gt;&lt;br /&gt;
	user-agent: IBrowse/2.4 (AmigaOS 4.1; PPC; 68K build)&lt;br /&gt;
	Pragma: no-cache&lt;br /&gt;
	Accept-Language: en, *&lt;br /&gt;
	Accept: text/html;level=3&lt;br /&gt;
	Accept: text/html;version=3.0&lt;br /&gt;
	Accept: */*&lt;br /&gt;
	&amp;lt;blank line&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;&amp;lt;path&amp;gt;&#039;&#039;&#039; would be the rest of the URL (if any) on that system and&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;domain&amp;gt;&#039;&#039;&#039; is the name of the server.  &lt;br /&gt;
&lt;br /&gt;
Using the &amp;quot;WeatherUnderground&amp;quot; website URL from above and their path name for&lt;br /&gt;
searching for airport conditions, we can find the current conditions at&lt;br /&gt;
Washington&#039;s Dulles International Airport with these domain &amp;amp; path values:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
   URL = www.wunderground.com&lt;br /&gt;
   PATH = cgi-bin/findweather/getForecast?query=IAD&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Such a GET request syntax can be transcribed into C code which builds the entire&lt;br /&gt;
request in a string and then sends it to the server with a simple &amp;quot;fprintf&amp;quot; to our open&lt;br /&gt;
TCP: file handle, as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
	// build web req text&lt;br /&gt;
	strcpy(line,&amp;quot;GET /&amp;quot;);&lt;br /&gt;
	strcat(line,path);&lt;br /&gt;
	strcat(line,&amp;quot; HTTP/1.1\r\n&amp;quot;);&lt;br /&gt;
	strcat(line,&amp;quot;host: &amp;quot;);&lt;br /&gt;
	strcat(line,domain);&lt;br /&gt;
	strcat(line,&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
	strcat(line,&amp;quot;user-agent: IBrowse/2.4 (AmigaOS 4.1; PPC; 68K build)\r\n&amp;quot;);&lt;br /&gt;
	strcat(line,&amp;quot;Pragma: no-cache\r\n&amp;quot;);&lt;br /&gt;
	strcat(line,&amp;quot;Accept-Language: en, *\r\n&amp;quot;);&lt;br /&gt;
	strcat(line,&amp;quot;Accept: text/html;level=3\r\n&amp;quot;);&lt;br /&gt;
	strcat(line,&amp;quot;Accept: text/html;version=3.0\r\n&amp;quot;);&lt;br /&gt;
	strcat(line,&amp;quot;Accept: */*\r\n&amp;quot;);&lt;br /&gt;
	strcat(line,&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	// send web req line to server&lt;br /&gt;
	fprintf(fileh,&amp;quot;%s&amp;quot;,line);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see, the variables &amp;quot;path&amp;quot; and &amp;quot;domain&amp;quot; are used to fill in some&lt;br /&gt;
blanks in the request.  The empty line at the end (with just a &amp;quot;\r\n&amp;quot;) completes the&lt;br /&gt;
GET request, after which the server will reply to your program.&lt;br /&gt;
&lt;br /&gt;
===Listen to the Server===&lt;br /&gt;
&lt;br /&gt;
Once the GET request has been sent to the web server, the server will start&lt;br /&gt;
sending back either the requested webpage (or other content) or an error page.&lt;br /&gt;
To see what sort of content is returned by the server in this example, you can&lt;br /&gt;
combine the domain and path values above and enter them in your web&lt;br /&gt;
browser&#039;s URL string gadget, like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
   www.wunderground.com/cgi-bin/findweather/getForecast?query=IAD&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once the page is loaded in your browser, viewing the page source (f.e., IBrowse&lt;br /&gt;
menu item &amp;quot;Page/Display Source...&amp;quot;) will show you the same HTML text that your&lt;br /&gt;
program will receive after sending the GET request.&lt;br /&gt;
&lt;br /&gt;
As such, your program needs to start reading from the file handle&lt;br /&gt;
the request was sent with.  This loop will print out the first hundred&lt;br /&gt;
lines returned:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
	// read in the response&lt;br /&gt;
	count = 0;&lt;br /&gt;
	while( (fgets(inStr,MAX_STR,fileh) != NULL) &amp;amp;&amp;amp; (count&amp;lt;100) )&lt;br /&gt;
	{&lt;br /&gt;
		++ count;&lt;br /&gt;
		printf(&amp;quot;line %ld = %s\n&amp;quot;,count,inStr);&lt;br /&gt;
		&lt;br /&gt;
		// process lines received here !&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Within this loop your application can parse the received lines for whatever&lt;br /&gt;
data your application is trying to obtain.  In the case of our example program below,&lt;br /&gt;
the program searches for a string precedes the weather information we want to find.&lt;br /&gt;
&lt;br /&gt;
After the returned content has been read, output or otherwise processed,&lt;br /&gt;
simply closing the file handle will close the connection to the server:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
	fclose(fileh);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===EXAMPLE ONE: IPClient.c===&lt;br /&gt;
&lt;br /&gt;
All of the above elements are combined in the following example program&lt;br /&gt;
&amp;quot;IPClient.c&amp;quot; that asks you for an IATA airport code (f.e., IAD = Washington&lt;br /&gt;
Dulles, FRA=Frankfurt, SYD=Sydney), then parses &amp;amp; prints out the weather&lt;br /&gt;
conditions from the returned WeatherUnderground.com web page.  &lt;br /&gt;
&lt;br /&gt;
Please Note: this example program worked with the wunderground.com&lt;br /&gt;
website in 2013-2014, as the served webpages change over time, it is &lt;br /&gt;
likely the parsing in this example is likely to fail and the program&lt;br /&gt;
no longer return useful information.  Should this happen, you get to use what&lt;br /&gt;
you learned above to upgrade or replace this example.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
************************************************************&lt;br /&gt;
**&lt;br /&gt;
** Created by: CodeBench 0.41 (12.10.2013)&lt;br /&gt;
** Project: IPclient&lt;br /&gt;
** Date: 12-10-2013 18:51:10&lt;br /&gt;
**&lt;br /&gt;
************************************************************&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;proto/exec.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/dos.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*****************************************************************************&lt;br /&gt;
 *		GLOBAL VARIABLES&lt;br /&gt;
 *****************************************************************************/&lt;br /&gt;
&lt;br /&gt;
STATIC CONST_STRPTR version USED = &amp;quot;$VER: IPclient v.02 (12.10.2013)&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
char URL[200] = &amp;quot;www.wunderground.com/cgi-bin/findweather/getForecast?query=&amp;quot;;&lt;br /&gt;
char domain[200];&lt;br /&gt;
char path[200];&lt;br /&gt;
char fname[256] = &amp;quot;&amp;quot;;&lt;br /&gt;
#define MAX_STR 2056&lt;br /&gt;
char line[MAX_STR] = &amp;quot;&amp;quot;;&lt;br /&gt;
char inStr[MAX_STR];&lt;br /&gt;
uint16 uLen;&lt;br /&gt;
uint16 dLen;&lt;br /&gt;
uint16 count = 0;&lt;br /&gt;
char *found;&lt;br /&gt;
FILE *fileh;&lt;br /&gt;
&lt;br /&gt;
/*****************************************************************************&lt;br /&gt;
 *		PROGRAM START&lt;br /&gt;
 *****************************************************************************/&lt;br /&gt;
&lt;br /&gt;
int main(int argc,char **argv)&lt;br /&gt;
{&lt;br /&gt;
	// get URL from user&lt;br /&gt;
	printf(&amp;quot;IPclient example\n&amp;quot;);&lt;br /&gt;
	printf(&amp;quot;======================\n&amp;quot;);&lt;br /&gt;
	&lt;br /&gt;
	printf(&amp;quot;   enter airport code &amp;gt;&amp;quot;);&lt;br /&gt;
	fgets(line,sizeof(line),stdin);&lt;br /&gt;
	line[strlen(line)-1] = &#039;\0&#039;;		// strip \n off end of string&lt;br /&gt;
	printf(&amp;quot;======================\n&amp;quot;);&lt;br /&gt;
	&lt;br /&gt;
	// append airport code on URLprefix&lt;br /&gt;
	strcat(URL,line);&lt;br /&gt;
	&lt;br /&gt;
	// parse domain from path&lt;br /&gt;
	uLen = strlen(URL) - 2;&lt;br /&gt;
	strcpy(domain,strtok(URL,&amp;quot;/\n&amp;quot;));&lt;br /&gt;
	dLen = strlen(domain);&lt;br /&gt;
	if (uLen&amp;gt;dLen)&lt;br /&gt;
		strcpy(path,strtok(NULL,&amp;quot;\n&amp;quot;));&lt;br /&gt;
	else&lt;br /&gt;
		printf(&amp;quot;   No chars remain for path\n&amp;quot;);&lt;br /&gt;
	printf(&amp;quot;   URL domain &amp;gt;%s&amp;lt;\n&amp;quot;,domain);&lt;br /&gt;
	printf(&amp;quot;   URL path &amp;gt;%s&amp;lt;\n&amp;quot;,path);&lt;br /&gt;
	&lt;br /&gt;
	// build URL filename from domain name&lt;br /&gt;
	strcpy(fname,&amp;quot;TCP:&amp;quot;);&lt;br /&gt;
	strcat(fname,domain);&lt;br /&gt;
	strcat(fname,&amp;quot;/80&amp;quot;);&lt;br /&gt;
	&lt;br /&gt;
	// open file access to URL&lt;br /&gt;
	printf(&amp;quot;      Opening URL &amp;gt;%s&amp;lt;\n&amp;quot;,fname);&lt;br /&gt;
	fileh = fopen(fname,&amp;quot;r+&amp;quot;);&lt;br /&gt;
	if (fileh == NULL)&lt;br /&gt;
	{&lt;br /&gt;
		printf(&amp;quot;Couldn&#039;t open connection domain server via \&amp;quot;%s\&amp;quot;\n&amp;quot;,fname);&lt;br /&gt;
		return RETURN_ERROR;&lt;br /&gt;
	};&lt;br /&gt;
	printf(&amp;quot;      TCP: file opened\n&amp;quot;);&lt;br /&gt;
	&lt;br /&gt;
	// build web req text&lt;br /&gt;
	strcpy(line,&amp;quot;GET /&amp;quot;);&lt;br /&gt;
	strcat(line,path);&lt;br /&gt;
	strcat(line,&amp;quot; HTTP/1.1\r\n&amp;quot;);&lt;br /&gt;
	strcat(line,&amp;quot;host: &amp;quot;);&lt;br /&gt;
	strcat(line,domain);&lt;br /&gt;
	strcat(line,&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
	strcat(line,&amp;quot;user-agent: IBrowse/2.4 (AmigaOS 4.1; PPC; 68K build)\r\n&amp;quot;);&lt;br /&gt;
	strcat(line,&amp;quot;Pragma: no-cache\r\n&amp;quot;);&lt;br /&gt;
	strcat(line,&amp;quot;Accept-Language: en, *\r\n&amp;quot;);&lt;br /&gt;
	strcat(line,&amp;quot;Accept: text/html;level=3\r\n&amp;quot;);&lt;br /&gt;
	strcat(line,&amp;quot;Accept: text/html;version=3.0\r\n&amp;quot;);&lt;br /&gt;
	strcat(line,&amp;quot;Accept: */*\r\n&amp;quot;);&lt;br /&gt;
	strcat(line,&amp;quot;\r\n&amp;quot;);&lt;br /&gt;
	&lt;br /&gt;
	// send web req line to server&lt;br /&gt;
	fprintf(fileh,&amp;quot;%s&amp;quot;,line);&lt;br /&gt;
	strcpy(line,&amp;quot;&amp;quot;);&lt;br /&gt;
	printf(&amp;quot;      Web req sent\n&amp;quot;);&lt;br /&gt;
	printf(&amp;quot;======================\n&amp;quot;);&lt;br /&gt;
	&lt;br /&gt;
	// read in the response&lt;br /&gt;
	while( (fgets(inStr,MAX_STR,fileh) != NULL) &amp;amp;&amp;amp; (count&amp;lt;100) )&lt;br /&gt;
	{&lt;br /&gt;
		++ count;&lt;br /&gt;
		//printf(&amp;quot;line %d = %s\n&amp;quot;,count,inStr);&lt;br /&gt;
		&lt;br /&gt;
		// look for name of airport&lt;br /&gt;
		found = strstr(inStr,&amp;quot;og:title&amp;quot;);&lt;br /&gt;
		if (found != NULL)&lt;br /&gt;
		{&lt;br /&gt;
			found = strtok(inStr,&amp;quot;=&amp;quot;);&lt;br /&gt;
			found = strtok(NULL,&amp;quot;=&amp;quot;);&lt;br /&gt;
			printf(&amp;quot;WeatherUnderground.com reports:\n&amp;quot;);&lt;br /&gt;
			printf(&amp;quot;   Airport   = %s\n&amp;quot;,strtok(NULL,&amp;quot;|&amp;quot;)+1);&lt;br /&gt;
			printf(&amp;quot;   Temp      =%s F\n&amp;quot;,strtok(NULL,&amp;quot;&amp;amp;&amp;quot;));&lt;br /&gt;
			found = strtok(NULL,&amp;quot;|&amp;quot;);&lt;br /&gt;
			printf(&amp;quot;   Condition =%s\n&amp;quot;,strtok(NULL,&amp;quot;\&amp;quot;&amp;quot;));			&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	printf(&amp;quot;======================\n&amp;quot;);&lt;br /&gt;
	&lt;br /&gt;
	// close file&lt;br /&gt;
	fclose(fileh);&lt;br /&gt;
	&lt;br /&gt;
	return RETURN_OK;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Designing Your Network Client===&lt;br /&gt;
&lt;br /&gt;
As you see, the above code and the example program, the mechanics&lt;br /&gt;
of connecting to a internet server and obtaining data are relatively&lt;br /&gt;
trivial.  The real challenge for the developer lies in understanding&lt;br /&gt;
the protocol used, in formatting the request and processing&lt;br /&gt;
received data.&lt;br /&gt;
&lt;br /&gt;
Public web servers make for fairly rich and easy targets to interact&lt;br /&gt;
with.  You can explore simple interaction with any web browser and mimic&lt;br /&gt;
that interaction with your code.  In many cases, you can control the&lt;br /&gt;
feedback just by crafting the web request as we did above and then&lt;br /&gt;
parse the results.&lt;br /&gt;
&lt;br /&gt;
Naturally, the more complicated the interactions, like logging into&lt;br /&gt;
a website, would require much more knowledge of the protocols used&lt;br /&gt;
and more complicated code that is beyond the scope of this tutorial.&lt;br /&gt;
&lt;br /&gt;
But there are a number of basic topics you should consider when&lt;br /&gt;
designing a web client!&lt;br /&gt;
&lt;br /&gt;
====Server Suitability:====&lt;br /&gt;
&lt;br /&gt;
Unless you are connecting to your own server or one which invites such&lt;br /&gt;
connections (some even publish API&#039;s and example code for you to use),&lt;br /&gt;
your application&#039;s &amp;quot;visit&amp;quot; may not be welcome or even legal.&lt;br /&gt;
&lt;br /&gt;
At the very least, your program should &amp;quot;tread lightly&amp;quot; - do not abuse&lt;br /&gt;
the server with unnecessary or intrusive requests.  Furthermore, if &lt;br /&gt;
your client uses the resources of someone else&#039;s server, you should&lt;br /&gt;
credit the server within your application and documentation.&lt;br /&gt;
&lt;br /&gt;
====Server Changes:====&lt;br /&gt;
&lt;br /&gt;
As with any programming that interacts with external elements, your&lt;br /&gt;
code should provide for the possibility things may not&lt;br /&gt;
succeed or the returned results may not be what was expected.&lt;br /&gt;
&lt;br /&gt;
As servers and websites change over time, the processing and&lt;br /&gt;
parsing of your program may often have to change accordingly.  &lt;br /&gt;
To maintain your program and deal with such changes, you may want&lt;br /&gt;
to consider how to make modifying those things easy as possible (even&lt;br /&gt;
by the user?).&lt;br /&gt;
&lt;br /&gt;
For example, the parsing strings could be kept in the program&#039;s tooltype&lt;br /&gt;
or a config text file, you could provide a GUI for managing the strings, or&lt;br /&gt;
employ an external, editable ARexx macro for processing.&lt;br /&gt;
&lt;br /&gt;
====Protocol Details &amp;amp; Vagaries:====&lt;br /&gt;
&lt;br /&gt;
Our example code presented a very simple interaction with a web&lt;br /&gt;
server using the a widely supported version of the HTTP protocol.&lt;br /&gt;
As one develops an application and uses a protocol, one should get&lt;br /&gt;
familiar with the details of that protocol.  Typically a &amp;quot;RFC&amp;quot;&lt;br /&gt;
document (as linked above) will describe the details of how things&lt;br /&gt;
are to work and how they might fail.  Your application should be&lt;br /&gt;
careful to comply with the details of the protocol (&amp;quot;Are we sending&lt;br /&gt;
a CR-LF or LF-CR?!&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
===Ideas===&lt;br /&gt;
&lt;br /&gt;
The above example was just a quick, simple exercise in demonstrating&lt;br /&gt;
the use of the AmigaOS Roadshow TCP: handler to access a web server.&lt;br /&gt;
There are many ways applications could be created to have simple&lt;br /&gt;
interactions with all sorts internet services, such as:&lt;br /&gt;
&lt;br /&gt;
* Check stock quotes from a financial site.&lt;br /&gt;
* Get package tracking information from a shipping site.&lt;br /&gt;
* Check for new emails on a POP email server.&lt;br /&gt;
* Convert currencies with a financial or travel web site.&lt;br /&gt;
* Check for files on an FTP server.&lt;br /&gt;
* Send messages with a SMTP email server.&lt;br /&gt;
* Look up words on a dictionary website.&lt;br /&gt;
&lt;br /&gt;
You could also write your own server for another Amiga and interact&lt;br /&gt;
with your own client.   A remote controlled media player?  The AmiNet &lt;br /&gt;
also has many examples of simple clients (with C source code or in&lt;br /&gt;
readable ARexx) that can be studied for means and methods.&lt;br /&gt;
&lt;br /&gt;
==An Internet Server==&lt;br /&gt;
&lt;br /&gt;
Next we will look at creating a simple internet server program that relies on AmigaOS Roadshow&#039;s &amp;quot;SuperServer&amp;quot; to receive the incoming&lt;br /&gt;
internet connection and share it with our application.&lt;br /&gt;
&lt;br /&gt;
Simply speaking, once Roadshow is configured to recognize the incoming&lt;br /&gt;
request and that your application is there to handle it; our program&lt;br /&gt;
just has to deal with another case of simple file-like interaction.&lt;br /&gt;
&lt;br /&gt;
For this example, we will create a simple server that accepts an HTTP&lt;br /&gt;
protocol request (like from IBrowse) and then responds to it with a&lt;br /&gt;
simple webpage.  Of course, you could write a server to serve an&lt;br /&gt;
interactive webpage, some machine information, media files, etc.&lt;br /&gt;
Just be careful.&lt;br /&gt;
&lt;br /&gt;
===Receive the Request===&lt;br /&gt;
&lt;br /&gt;
When Roadshow receives an internet request on the designated port that&lt;br /&gt;
corresponds to our server, it starts our server program and routes the&lt;br /&gt;
network connection to our program using the &amp;quot;standard&amp;quot; input stream&lt;br /&gt;
(otherwise known as &amp;quot;stdin&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
Our application then reads the stream almost like reading from any&lt;br /&gt;
other file or user input, like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
	// read in the response&lt;br /&gt;
	while( (fgets(inStr,MAX_STR,(FILE *)stdin) != NULL) &amp;amp;&amp;amp; (count&amp;lt;100) )&lt;br /&gt;
	{&lt;br /&gt;
		if (strlen(inStr)&amp;lt;3)&lt;br /&gt;
		{&lt;br /&gt;
			IExec-&amp;gt;DebugPrintF(&amp;quot;   received nearly empty line, ending read loop.\n&amp;quot;,NULL,NULL);&lt;br /&gt;
			break;&lt;br /&gt;
		}&lt;br /&gt;
		++ count;&lt;br /&gt;
		IExec-&amp;gt;DebugPrintF(&amp;quot;   %s\n&amp;quot;,inStr,NULL,NULL,NULL);&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
		&lt;br /&gt;
As you can see, we loop reading incoming lines until we encounter a&lt;br /&gt;
line with two or fewer characters (essentially an empty line with&lt;br /&gt;
what should be a CR-LF).  There is also a counter that kicks us out&lt;br /&gt;
of the loop if we read 100 lines - that&#039;s a sign something else is &lt;br /&gt;
wrong, we should never see so long a request with the HTTP protocol.&lt;br /&gt;
&lt;br /&gt;
With the HTTP protocol, the first line is where we would see what is&lt;br /&gt;
being requested.  Were our server to use another protocol, the processing of&lt;br /&gt;
the received data would likely happe3n elsewhere.&lt;br /&gt;
&lt;br /&gt;
As you see, we do all our diagnostics output using the &amp;quot;DebugPrintf&amp;quot;. Which&lt;br /&gt;
means we either need to run Sashimi or watch output on the serial port&lt;br /&gt;
(with your second Amiga, naturally).  With the above code, the diagnostics&lt;br /&gt;
output will show the entire incoming request on the serial port.  Of course,&lt;br /&gt;
there&#039;s a reason why we have to use &amp;quot;DebugPrintf&amp;quot; for diagnostics output...&lt;br /&gt;
&lt;br /&gt;
===Respond to the Visitor===&lt;br /&gt;
&lt;br /&gt;
Once we&#039;ve read the (almost) empty line at the end of the incoming&lt;br /&gt;
web request, we will use another &amp;quot;standard&amp;quot; stream (know as &amp;quot;stdout&amp;quot;) to respond to our&lt;br /&gt;
internet visitor.&lt;br /&gt;
&lt;br /&gt;
Anything we output to &amp;quot;stdout&amp;quot; will be sent by Roadshow back to our&lt;br /&gt;
internet visitor.  This is the reason why we used the serial port for&lt;br /&gt;
diagnostic print outs, since a simple &amp;quot;printf&amp;quot; would have gone to&lt;br /&gt;
our web visitor.&lt;br /&gt;
&lt;br /&gt;
In this example, we create a basic loop that feeds a predefined series of strings (in the &#039;&#039;&#039;lines&#039;&#039;&#039; array)&lt;br /&gt;
of a very simple webpage through Roadshow, to our web visitor:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
	//loop thru text writing to stdout&lt;br /&gt;
	do&lt;br /&gt;
	{&lt;br /&gt;
		if (strlen(lines[l]) &amp;gt; 0)&lt;br /&gt;
		{&lt;br /&gt;
			IExec-&amp;gt;DebugPrintF(&amp;quot;   printing line = %s\n&amp;quot;,lines[l],NULL,NULL);			&lt;br /&gt;
			if (fprintf(stdout,&amp;quot;%s\n&amp;quot;,lines[l]) &amp;lt; 0)&lt;br /&gt;
			{&lt;br /&gt;
				IExec-&amp;gt;DebugPrintF(&amp;quot;ERROR printing line\n&amp;quot;,NULL,NULL);&lt;br /&gt;
				break;&lt;br /&gt;
			}&lt;br /&gt;
			fflush(stdout);&lt;br /&gt;
		}&lt;br /&gt;
		else&lt;br /&gt;
		{&lt;br /&gt;
			IExec-&amp;gt;DebugPrintF(&amp;quot;   empty line, loop end\n&amp;quot;,NULL,NULL);&lt;br /&gt;
			break;&lt;br /&gt;
		}&lt;br /&gt;
		++l;&lt;br /&gt;
	} while (l &amp;lt; 25);		// emergency loop escape to stop endlessness&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see, our loop ends when we hit an empty line in our webpage&lt;br /&gt;
definition or a maximum of 25 lines (a fail-safe).  Then we &amp;quot;flush&amp;quot; the output&lt;br /&gt;
stream and quit our program.&lt;br /&gt;
&lt;br /&gt;
While our two samples of code simply receive and respond to an incoming web request,&lt;br /&gt;
one can imagine where this code can be expanded provide useful service and more&lt;br /&gt;
complex interactions.&lt;br /&gt;
&lt;br /&gt;
===EXAMPLE TWO:  IPserver.c===&lt;br /&gt;
&lt;br /&gt;
We can see all these pieces and the definition of our simple webpage in&lt;br /&gt;
the full program here:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
************************************************************&lt;br /&gt;
**&lt;br /&gt;
** Created by: CodeBench 0.41 (12.10.2013)&lt;br /&gt;
** Project: IPserver&lt;br /&gt;
** Date: 13-10-2013 23:41:17&lt;br /&gt;
**&lt;br /&gt;
************************************************************&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/exec.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/dos.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*****************************************************************************&lt;br /&gt;
 *		GLOBAL VARIABLES&lt;br /&gt;
 *****************************************************************************/&lt;br /&gt;
&lt;br /&gt;
STATIC CONST_STRPTR version USED = &amp;quot;$VER: IPserver 0.14 (13.10.2013)&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
// define maximum web request lines &amp;amp; length&lt;br /&gt;
#define MAX_STR 2048&lt;br /&gt;
&lt;br /&gt;
// ARS path &amp;amp; file name&lt;br /&gt;
uint16 count = 0;&lt;br /&gt;
char inStr[MAX_STR];&lt;br /&gt;
&lt;br /&gt;
CONST_STRPTR lines[] =&lt;br /&gt;
{&lt;br /&gt;
	&amp;quot;HTTP/1.0\015&amp;quot;,&lt;br /&gt;
	&amp;quot;Content-Type: text/html\015&amp;quot;,&lt;br /&gt;
	&amp;quot;\015&amp;quot;,&lt;br /&gt;
	&amp;quot;&amp;lt;HTML&amp;gt;&amp;lt;HEAD&amp;gt;&amp;lt;TITLE&amp;gt;IPserver&amp;lt;/TITLE&amp;gt;&amp;lt;/HEAD&amp;gt;&amp;lt;BODY BGCOLOR=\&amp;quot;cccccc\&amp;quot;&amp;gt;\015&amp;quot;,&lt;br /&gt;
	&amp;quot;&amp;lt;TABLE WIDTH=100%&amp;gt;&amp;lt;TD ALIGN=\&amp;quot;center\&amp;quot; BGCOLOR=\&amp;quot;cccccc\&amp;quot;&amp;gt;\015&amp;quot;,&lt;br /&gt;
	&amp;quot;&amp;lt;BR&amp;gt;&amp;lt;TABLE WIDTH=90%&amp;gt;&amp;lt;TR&amp;gt;&amp;lt;TD&amp;gt;&amp;lt;B&amp;gt;&amp;lt;H1&amp;gt;WELCOME&amp;lt;/H1&amp;gt;&amp;lt;/B&amp;gt;&amp;lt;BR&amp;gt;&amp;lt;/TD&amp;gt;&amp;lt;/TR&amp;gt;&amp;lt;/TABLE&amp;gt;\015&amp;quot;,&lt;br /&gt;
	&amp;quot;&amp;lt;TR&amp;gt;&amp;lt;TD BGCOLOR=\&amp;quot;6688ee\&amp;quot;&amp;gt;&amp;lt;H3&amp;gt;&amp;lt;P&amp;gt;&amp;lt;P&amp;gt;&amp;lt;FONT COLOR=\&amp;quot;white\&amp;quot;&amp;gt;&amp;lt;B&amp;gt;AmigaOS IPserver example&amp;lt;/B&amp;gt;&amp;lt;/FONT&amp;gt;&amp;lt;/TD&amp;gt;&amp;lt;/TR&amp;gt;\015&amp;quot;,&lt;br /&gt;
	&amp;quot;&amp;lt;TR&amp;gt;&amp;lt;TD ALIGN=\&amp;quot;center\&amp;quot; BGCOLOR=\&amp;quot;cccccc\&amp;quot;&amp;gt;\015&amp;quot;,&lt;br /&gt;
	&amp;quot;&amp;lt;BR&amp;gt;&amp;lt;TABLE CELLSPACING=0 WIDTH=90%&amp;gt;&amp;lt;TR BGCOLOR=\&amp;quot;ffffff\&amp;quot;&amp;gt;&amp;lt;TD WIDTH=100&amp;gt;&amp;lt;H4&amp;gt;&amp;lt;B&amp;gt;And so it begins...&amp;lt;/B&amp;gt;&amp;lt;/TD&amp;gt;&amp;lt;TD&amp;gt; Your Amiga internet server! &amp;lt;/TD&amp;gt;&amp;lt;/TR&amp;gt;&amp;lt;/TABLE&amp;gt;\015&amp;quot;,&lt;br /&gt;
	&amp;quot;&amp;lt;/TR&amp;gt;&amp;lt;/TD&amp;gt;&amp;lt;/TABLE&amp;gt;&amp;lt;/BODY&amp;gt;&amp;lt;/HTML&amp;gt;\015&amp;quot;,&lt;br /&gt;
	&amp;quot;&amp;quot;&lt;br /&gt;
};&lt;br /&gt;
uint16 l = 0;&lt;br /&gt;
&lt;br /&gt;
/*****************************************************************************&lt;br /&gt;
 *		PROGRAM START&lt;br /&gt;
 *****************************************************************************/&lt;br /&gt;
&lt;br /&gt;
// Starting program&lt;br /&gt;
int main(int argc,char **argv)&lt;br /&gt;
{&lt;br /&gt;
	&lt;br /&gt;
	IExec-&amp;gt;DebugPrintF(&amp;quot;======================================\n&amp;quot;);&lt;br /&gt;
	IExec-&amp;gt;DebugPrintF(&amp;quot;IPserver starting\n&amp;quot;);&lt;br /&gt;
	IExec-&amp;gt;DebugPrintF(&amp;quot;======================================\n&amp;quot;);&lt;br /&gt;
	&lt;br /&gt;
	//		Was program started from shell or WB ?&lt;br /&gt;
	if (argc &amp;gt; 0)&lt;br /&gt;
	{&lt;br /&gt;
		&lt;br /&gt;
		// read in the response&lt;br /&gt;
		while( (fgets(inStr,MAX_STR,(FILE *)stdin) != NULL) &amp;amp;&amp;amp; (count&amp;lt;100) )&lt;br /&gt;
		{&lt;br /&gt;
			//  ####   Test for CR-LR only line&lt;br /&gt;
			if (strlen(inStr)&amp;lt;3)&lt;br /&gt;
			{&lt;br /&gt;
				IExec-&amp;gt;DebugPrintF(&amp;quot;   received nearly empty line, ending read loop.\n&amp;quot;,NULL,NULL);&lt;br /&gt;
				break;&lt;br /&gt;
			}&lt;br /&gt;
			&lt;br /&gt;
			++ count;&lt;br /&gt;
			IExec-&amp;gt;DebugPrintF(&amp;quot;   %s\n&amp;quot;,inStr,NULL,NULL,NULL);&lt;br /&gt;
		}&lt;br /&gt;
		&lt;br /&gt;
		IExec-&amp;gt;DebugPrintF(&amp;quot;======================================\n&amp;quot;);&lt;br /&gt;
		IExec-&amp;gt;DebugPrintF(&amp;quot;FINISHED READING WEB REQUEST\n&amp;quot;);&lt;br /&gt;
		IExec-&amp;gt;DebugPrintF(&amp;quot;SERVING WEB PAGE...\n&amp;quot;);&lt;br /&gt;
		IExec-&amp;gt;DebugPrintF(&amp;quot;======================================\n&amp;quot;);&lt;br /&gt;
		&lt;br /&gt;
		//loop thru text writing to stdout&lt;br /&gt;
		do&lt;br /&gt;
		{&lt;br /&gt;
			if (strlen(lines[l]) &amp;gt; 0)&lt;br /&gt;
			{&lt;br /&gt;
				IExec-&amp;gt;DebugPrintF(&amp;quot;   printing line = %s\n&amp;quot;,lines[l],NULL,NULL);&lt;br /&gt;
				&lt;br /&gt;
				if (fprintf(stdout,&amp;quot;%s\n&amp;quot;,lines[l]) &amp;lt; 0)&lt;br /&gt;
				{&lt;br /&gt;
					IExec-&amp;gt;DebugPrintF(&amp;quot;ERROR printing line\n&amp;quot;,NULL,NULL);&lt;br /&gt;
					break;&lt;br /&gt;
				}&lt;br /&gt;
				&lt;br /&gt;
				fflush(stdout);&lt;br /&gt;
			}&lt;br /&gt;
			else&lt;br /&gt;
			{&lt;br /&gt;
				IExec-&amp;gt;DebugPrintF(&amp;quot;   empty line, loop end\n&amp;quot;,NULL,NULL);&lt;br /&gt;
				break;&lt;br /&gt;
			}&lt;br /&gt;
			++l;&lt;br /&gt;
		} while (l &amp;lt; 25);		// emergency loop escape to stop endlessness&lt;br /&gt;
		&lt;br /&gt;
		IExec-&amp;gt;DebugPrintF(&amp;quot;======================================\n&amp;quot;);&lt;br /&gt;
		IExec-&amp;gt;DebugPrintF(&amp;quot;Web service finished... \n&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
		printf(&amp;quot;IPserver started from Workbench - Don&#039;t do it again, this is a Roadshow app!\n&amp;quot;);&lt;br /&gt;
	&lt;br /&gt;
	IExec-&amp;gt;DebugPrintF(&amp;quot;IPserver Quitting!\n&amp;quot;);&lt;br /&gt;
	IExec-&amp;gt;DebugPrintF(&amp;quot;======================================\n&amp;quot;);&lt;br /&gt;
	&lt;br /&gt;
	return RETURN_OK;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see there&#039;s also a bit of housekeeping code at the beginning&lt;br /&gt;
to check if the program was run from the Workbench and to tell the user not to.&lt;br /&gt;
As it stands, this is program is only meant to be used by Roadshow for&lt;br /&gt;
serving your Amiga&#039;s internet visitors.&lt;br /&gt;
&lt;br /&gt;
But how do we test this server out?  First we have to let Roadshow know that&lt;br /&gt;
we&#039;ve created this server and where visitors will find it.&lt;br /&gt;
&lt;br /&gt;
===Roadshow Configuration===&lt;br /&gt;
&lt;br /&gt;
There are two areas where Roadshow needs to be told about your server&lt;br /&gt;
and the service it is going to provide, as described below.  Both of these can&lt;br /&gt;
be configured using Internet Prefs.  You can also make this configuration by&lt;br /&gt;
manually editing the &amp;quot;servers&amp;quot; and &amp;quot;services&amp;quot; files in the &amp;quot;DEVS:internet/&amp;quot; directory.&lt;br /&gt;
Configuration of these files is described in the file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
   SYS:Documentation/Roadshow/README&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If you would like to spare your user from having to do either of those&lt;br /&gt;
chores, your application can even modify those files.  As soon as&lt;br /&gt;
Roadshow sees those files have been modified, it will reconfigure itself&lt;br /&gt;
accordingly.&lt;br /&gt;
&lt;br /&gt;
====Services====&lt;br /&gt;
&lt;br /&gt;
First, we need to tell Roadshow about the &amp;quot;service&amp;quot; we are providing.&lt;br /&gt;
If one opens Internet Prefs and clicks on the &amp;quot;Services&amp;quot; page, one will&lt;br /&gt;
see a list of standard internet services with their TCPIP port numbers,&lt;br /&gt;
types and aliases.&lt;br /&gt;
&lt;br /&gt;
Click the &amp;quot;New...&amp;quot; button to define a new Service.  An &amp;quot;Add service&amp;quot;&lt;br /&gt;
window will open where we can define how our server will be accessed.&lt;br /&gt;
Critically, we need to pick a port number that is not already in use.&lt;br /&gt;
Such settings could be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
   Name = IPserver&lt;br /&gt;
   Port = 7600&lt;br /&gt;
   Type = tcp&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then we click &amp;quot;Use&amp;quot; to accept our new values.  As soon as one clicks&lt;br /&gt;
&amp;quot;Save&amp;quot; in Internet Prefs, this service will be recognized by Roadshow.&lt;br /&gt;
&lt;br /&gt;
The same configuration could manually be added to Roadshow by adding this line&lt;br /&gt;
(in port number location) into the file &amp;quot;DEVS:Internet/Services&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
   IPServer         7600/tcp&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As soon as one saves the file, Roadshow will be notified and adjust&lt;br /&gt;
itself for the service.&lt;br /&gt;
&lt;br /&gt;
====Servers====&lt;br /&gt;
&lt;br /&gt;
Before we can use the service above, we also need to tell Roadshow&lt;br /&gt;
about our server app and where to find it.  Again, this can be done&lt;br /&gt;
while in Internet Prefs.  Click on the &amp;quot;Servers&amp;quot; page and one will see&lt;br /&gt;
any servers configured with the services they provide (as set above),&lt;br /&gt;
their type, wait method and program path.&lt;br /&gt;
&lt;br /&gt;
Click on the &amp;quot;New...&amp;quot; button to define a new Server.  In the &amp;quot;Add server&amp;quot;&lt;br /&gt;
window we can define what sort of service our server is for, the&lt;br /&gt;
characteristics of how it will be called and where it is located on&lt;br /&gt;
our Amiga system.  Such settings could be:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
   Service = IPserver&lt;br /&gt;
   Type = Stream&lt;br /&gt;
   Stack = 65536&lt;br /&gt;
   Program = data:Projects/C/OS4ex-IPserver/IPserver.debug&lt;br /&gt;
   Arguments = &amp;lt;empty&amp;gt;&lt;br /&gt;
   Active = &amp;lt;checked&amp;gt;&lt;br /&gt;
   Wait for completion = &amp;lt;not checked&amp;gt;&lt;br /&gt;
   Use socket I/O streams = &amp;lt;checked&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Naturally, you should enter the server program path &amp;amp; name for your own system.&lt;br /&gt;
Again we click &amp;quot;Use&amp;quot; to accept our new Server entry and saving Internet&lt;br /&gt;
Prefs will adjust Roadshow.&lt;br /&gt;
&lt;br /&gt;
We can otherwise make this adjustment to Roadshow&#039;s server list by manually adding the&lt;br /&gt;
following line to the &amp;quot;DEVS:Internet/servers&amp;quot; file:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
   IPServer        stream     dos stack=65536 data:Projects/C/OS4ex-IPserver/IPserver.debug&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Again, saving the file is automatically noticed by Roadhsow.&lt;br /&gt;
&lt;br /&gt;
Once both the service and server are correctly configured, Roadshow is ready&lt;br /&gt;
to use our new server.&lt;br /&gt;
&lt;br /&gt;
===Let&#039;s See Our Server!===&lt;br /&gt;
&lt;br /&gt;
To test our new server example, you can access it by connecting to your&lt;br /&gt;
Amiga and the designated IP port number.  On the same machine, you can&lt;br /&gt;
enter this in your browser URL line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
   http://localhost:7600/&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
From another machine, you will need to have the IP address or defined host&lt;br /&gt;
name for your Amiga running the test server program.  The URL should&lt;br /&gt;
look something like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
   http://192.168.1.07:7600/&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In any case, the browser will connect to your Amiga (at the port number&lt;br /&gt;
following the colon - &amp;quot;:&amp;quot;) and Roadshow will call up your server program&lt;br /&gt;
and let it talk to your browser and send it the preset webpage.&lt;br /&gt;
&lt;br /&gt;
===Where to go?   Webpages?  More?===&lt;br /&gt;
&lt;br /&gt;
Clearly the above example does little more than say &amp;quot;Hello World&amp;quot; to a&lt;br /&gt;
visiting web browser user.  It offers no interactivity, performs no task&lt;br /&gt;
and serves no media.  &lt;br /&gt;
&lt;br /&gt;
When this web server receives the incoming web request, the first line&lt;br /&gt;
(starting with &amp;quot;GET&amp;quot;) tells the server what the browser is looking for.&lt;br /&gt;
For example, if you watch the serial output and connect with a newer browser than&lt;br /&gt;
IBrowse, you can see most browsers actually make two connections to the&lt;br /&gt;
server, with one of them saying:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
   GET /favicon.ico HTTP/1.1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In that case, the browser is requesting your server send an image file&lt;br /&gt;
that it can display on the browser tab.  Just like that, anything in the URL&lt;br /&gt;
after the machine&#039;s network name (or IP address) and the port number&lt;br /&gt;
is taken as a requested path and your server will receive it after &amp;quot;GET&amp;quot; in&lt;br /&gt;
the first line of the request.&lt;br /&gt;
&lt;br /&gt;
This just scratches the surface of requests your server may receive and&lt;br /&gt;
how it can process them and respond to web visitors.  To dig deeper you can&lt;br /&gt;
search the many sources online or in your local bookstore on HTTP communications&lt;br /&gt;
and the formatting of HTML webpages.  Of course, you should make sure your&lt;br /&gt;
server can optionally send diagnostics output so you know what requests are&lt;br /&gt;
being received and how they are responded to.&lt;br /&gt;
&lt;br /&gt;
===Just Webpages?===&lt;br /&gt;
&lt;br /&gt;
There&#039;s also no reason why your server needs to be limited to dealing&lt;br /&gt;
with browsers and sending webpages.  The internet is full of other&lt;br /&gt;
protocols and services that you could write a server for.  Or you could&lt;br /&gt;
create your own online client and server pair of applications that&lt;br /&gt;
talked with each other.&lt;br /&gt;
&lt;br /&gt;
Just as we discussed with creating an Internet client, there are many&lt;br /&gt;
topics you should consider when designing an internet server program.&lt;br /&gt;
It&#039;s not just about the coding!&lt;br /&gt;
&lt;br /&gt;
====Security====&lt;br /&gt;
&lt;br /&gt;
Obviously, opening your Amiga with an internet server represents more of a&lt;br /&gt;
risk than if you had done nothing.  So it is critically important one&lt;br /&gt;
considers security when creating a server.  While it&#039;s beyond the scope&lt;br /&gt;
of this article to inclusively discuss all the issues involved, here are some&lt;br /&gt;
basics to consider.&lt;br /&gt;
&lt;br /&gt;
Don&#039;t blindly serve sensitive information to visitors.  How can you be&lt;br /&gt;
sure who&#039;s at the other end of the connection and who might be watching&lt;br /&gt;
along the way?  Even if randomized path names and requests are used by&lt;br /&gt;
your server, there&#039;s no guarantee the connection is 100% secure.&lt;br /&gt;
&lt;br /&gt;
Limit commands and functions served to visitors.  Obviously, creating a&lt;br /&gt;
means of offering anything like command line access or unfettered file &lt;br /&gt;
editing/deleting powers to a web visitor would represent dangerous hole&lt;br /&gt;
in any system&#039;s security.  But one also has to make sure no whatsoever holes&lt;br /&gt;
or bugs exist in the server design that would let such access slip&lt;br /&gt;
through.&lt;br /&gt;
&lt;br /&gt;
====Server Instances &amp;amp; Load====&lt;br /&gt;
&lt;br /&gt;
One has to keep in mind the &amp;quot;SuperServer&amp;quot; method where Roadshow runs&lt;br /&gt;
your server also means your server program will be executed with each and every&lt;br /&gt;
request Roadshow receives for that port.  In each case, your server&lt;br /&gt;
will do its duty and then be expected to quit.  That should be fine for&lt;br /&gt;
light duty, personal server tasks.&lt;br /&gt;
&lt;br /&gt;
But one should focus server development on keeping things as&lt;br /&gt;
&amp;quot;lightweight&amp;quot; and simple as possible.  If the server needs to&lt;br /&gt;
read data files or perform other complicated initialization, this may&lt;br /&gt;
slow reaction time for each incoming request to an unacceptable level.&lt;br /&gt;
&lt;br /&gt;
To avoid time consuming chores, one might considering using inter-process&lt;br /&gt;
communications (such as ARexx messages) to interact with a separate&lt;br /&gt;
master program that handles all the housekeeping and remains continuously running&lt;br /&gt;
while each instance of the internet server handles each incoming request, quickly&lt;br /&gt;
relays the necessary information from the master program and quits.  &lt;br /&gt;
&lt;br /&gt;
Naturally, at some point usage requirements may require one bypasses the&lt;br /&gt;
Roadshow  SuperServer method of running servers and goes to using &lt;br /&gt;
longhand socket programming that is better suited to heavy duty use&lt;br /&gt;
- like running a serious public server.  That&#039;s beyond the scope of this tutorial.&lt;br /&gt;
&lt;br /&gt;
Furthermore, there are whole areas of study and technology involved with the&lt;br /&gt;
handling of network user load that should be explored in implementing a serious&lt;br /&gt;
server system.&lt;br /&gt;
&lt;br /&gt;
====Protocols and Compatibility====&lt;br /&gt;
&lt;br /&gt;
As one develops a more a complex or interactive server meant to handle&lt;br /&gt;
a wider group of users (even those on lesser platforms!), one needs&lt;br /&gt;
to pay much closer attention to the protocols involved.  With each new client&lt;br /&gt;
and platform encountered, the more important implementation details of a&lt;br /&gt;
protocol are likely to be.&lt;br /&gt;
&lt;br /&gt;
As mentioned in elsewhere in this text, there are RFC&#039;s that describe the&lt;br /&gt;
formal protocols and there are likely countless webpages that address&lt;br /&gt;
idiosyncrasies of implementing the protocols.&lt;br /&gt;
&lt;br /&gt;
Beyond all those, a developer will need to do serious testing with as&lt;br /&gt;
wide a pool of possible clients to refine a server&#039;s operation.  &amp;quot;You&lt;br /&gt;
aren&#039;t in Kansas anymore!&amp;quot;&lt;br /&gt;
&lt;br /&gt;
==General Issues==&lt;br /&gt;
&lt;br /&gt;
Whether creating a server or a client program, there are many general&lt;br /&gt;
issues that one should consider in developing such programs.&lt;br /&gt;
&lt;br /&gt;
====Complexity and Speed====&lt;br /&gt;
&lt;br /&gt;
These days it seems like few developers on lesser platforms care terribly&lt;br /&gt;
much about optimization and speed.  Those platforms typically just throw&lt;br /&gt;
more horsepower &amp;amp; memory at their chores and try to go about their business.&lt;br /&gt;
&lt;br /&gt;
In the Amiga world, without the glut of idle horsepower, development of&lt;br /&gt;
any applications and internet clients &amp;amp; servers in particular should be&lt;br /&gt;
mindful of overhead.  For every client or server transaction, there is&lt;br /&gt;
likely some user that clicked a button and is waiting for an answer.&lt;br /&gt;
Keep things simple and optimize!&lt;br /&gt;
&lt;br /&gt;
====Incomplete transactions====&lt;br /&gt;
&lt;br /&gt;
Since all these programs are dependent on communications over many links,&lt;br /&gt;
these programs need to have a robustness for failed links.  Transfers can&lt;br /&gt;
be interrupted mid-stream.  Received data can be incomplete or corrupted.&lt;br /&gt;
These applications need to have the error trapping to deal with such real&lt;br /&gt;
possibilities - that isn&#039;t reflected in the simple examples above.&lt;br /&gt;
&lt;br /&gt;
====Statelessness====&lt;br /&gt;
&lt;br /&gt;
Given the nature of internet communications and web browsing in particular,&lt;br /&gt;
servers and clients need to be &amp;quot;stateless&amp;quot; as possible.  While a visitor&lt;br /&gt;
may have just &amp;quot;logged in&amp;quot; to your server, it&#039;s not guaranteed &lt;br /&gt;
the next transaction your server receives is that logged-in user, that&lt;br /&gt;
the user hasn&#039;t left or hit the back or reload button on their browser&lt;br /&gt;
(reloading the log-in page again).  So a server should avoid making&lt;br /&gt;
assumptions about the state of the connection and status of a&lt;br /&gt;
visitor whenever possible or provide explicit means for addressing such&lt;br /&gt;
things, if possible.&lt;/div&gt;</summary>
		<author><name>Costel Mincea</name></author>
	</entry>
	<entry>
		<id>https://wiki.amigaos.net/w/index.php?title=Programming_AmigaOS_4:_GUI_Toolkit_ReAction&amp;diff=12555</id>
		<title>Programming AmigaOS 4: GUI Toolkit ReAction</title>
		<link rel="alternate" type="text/html" href="https://wiki.amigaos.net/w/index.php?title=Programming_AmigaOS_4:_GUI_Toolkit_ReAction&amp;diff=12555"/>
		<updated>2025-01-26T19:31:21Z</updated>

		<summary type="html">&lt;p&gt;Costel Mincea: Text replacement - &amp;quot;&amp;lt;syntaxhighlight&amp;gt;&amp;quot; to &amp;quot;&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;This article was adapted from Amiga Future magazine&#039;s series on developing for AmigaOS....&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
We mainly worked with shell programs or simple windows in the previous parts of this workshop. However, today&#039;s topic will be how to create a completely interactive GUI.&lt;br /&gt;
&lt;br /&gt;
For this purpose we will use ReAction, which provides great flexibility for defined windows and controls that lay themselves out automatically. But before we dive into this subject, let us take a look at the past and see how interface development on the Amiga has changed over the years.&lt;br /&gt;
&lt;br /&gt;
= History =&lt;br /&gt;
&lt;br /&gt;
With Kickstart 1.x you had to create gadgets (the controls, which were back then - a button, a panel and a slide bar) directly as a structure and connect them with each other as well as calculate their positions. This procedure was very time consuming and a different font or another window size could sometimes cause significant trouble. Therefore, the gadtools.library, which was supplied with Kickstart 2.x, greatly simplified the creation of gadgets and menus. Additionally, a great number of new gadget types (e.g. ListView, Checkbox, Cycle) was launched. However, there was still a problem with the fixed positions. In this step the BOOPSI (Basic Object Oriented Programming System for Intuition) was also created. It offered an object-orientated approach, that could readily be used with Workbench 3.5 in the form of ReAction gadgets. This made it possible for windows to lay themselves out correctly automatically. That means that the gadgets automatically re-position themselves and their size is adjusted, if needed, when the window size is changed. The calculation of the minimized window size when opening a window is handled automatically by the system.&lt;br /&gt;
&lt;br /&gt;
= The end of Gadtools =&lt;br /&gt;
&lt;br /&gt;
By introducing ReAction all gadget types from the gadtools.library became superfluous. The same procedure is still used with AmigaOS 4, but this time it is used to create menus. All the functions required to create and layout menus are now available in the window class and no longer need to be made automatically. In other words, gadtools.library no longer has this role to perform!&lt;br /&gt;
&lt;br /&gt;
A side note: the MUI (Magic User Interface) is used as a second GUI library and it is provided with the Operating System since AmigaOS 4. However, it remains an external toolkit. Its standard appearance has been made in the style of AmigaOS 4 so it would not look like an &#039;alien element&#039;. In principle, it applies the same approach as for ReAction, but it is programmed differently.&lt;br /&gt;
&lt;br /&gt;
= ReAction step by step =&lt;br /&gt;
&lt;br /&gt;
After that brief introduction it is now time for our first example, a window with a gadget and a menu. What used to take a long time, is now done in just a few steps. These necessary steps will be explained here in detail, because you can create big applications with them as well.&lt;br /&gt;
&lt;br /&gt;
All ReAction objects (gadgets, window and Requester) are set up with IIntuition-&amp;gt;NewObject(). The result is a generic &#039;Object&#039; pointer. However, most of the old functions still expect a pointer on a gadget structure (or a window structure), so that you must decide whether you want to cast the return value immediately, or once you activate the respective functions. There is no standard notation in SDK at the moment. Right now, casting the result pointer is the best option. This way you can immediately see what it is about, in case you have selected an unfavourable name for the variable. You can create a button as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
  struct Gadget *gb_ButtonGad;&lt;br /&gt;
  #define GAD_ID_Quit 2&lt;br /&gt;
&lt;br /&gt;
  if((gb_ButtonGad = (struct Gadget *) IIntuition-&amp;gt;NewObject(IButton-&amp;gt;BUTTON_GetClass(),NULL,&lt;br /&gt;
      GA_ID,        GAD_ID_Quit,&lt;br /&gt;
      GA_RelVerify, TRUE,&lt;br /&gt;
      GA_Text,      &amp;quot;_end&amp;quot;,&lt;br /&gt;
      TAG_DONE)))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There is an example for various gadget classes at the end of this article. The GA_xxx tags are general and applicable to all kinds of gadgets. A specific gadget for a button would be, for instance, BUTTON_BevelStyle, which you can find under &amp;quot;gadgets/...&amp;quot;.  With the underscore in the button text the shortcut is defined, which can start the button without a mouse.&lt;br /&gt;
&lt;br /&gt;
You can also use the same procedure to create a window, but this time you must use the WINDOW_xxx Defines from &amp;quot;classes/window.h&amp;quot;. In addition, you can also use a great number of old WA tags.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
  Object *gb_WindowObj;&lt;br /&gt;
  if((gb_WindowObj = (Object *) IIntuition-&amp;gt;NewObject(IWindow-&amp;gt;WINDOW_GetClass(),NULL,&lt;br /&gt;
    WA_IDCMP,        IDCMP_GADGETUP | IDCMP_CLOSEWINDOW | IDCMP_MENUPICK,&lt;br /&gt;
    WA_SizeGadget,   TRUE,&lt;br /&gt;
    WA_DepthGadget,  TRUE,&lt;br /&gt;
    WA_DragBar,      TRUE,&lt;br /&gt;
    WA_CloseGadget,  TRUE,&lt;br /&gt;
    WA_Activate,     TRUE,&lt;br /&gt;
    WA_Title,        &amp;quot;Example with reaction gadgets and window class&amp;quot;,&lt;br /&gt;
    WINDOW_Position, WPOS_CENTERSCREEN,&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A ReAction window requires implicitly a layout object, which automatically handles the size adjustment and distribution of the individual gadgets. In our example with only one gadget we need a central layout method. The layout object serves the horizontal and vertical arrangement of several gadgets within the window. This way, you can also realise very complex layouts by dividing them into horizontal and vertical groups.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
  struct Gadget *gb_MainLayout;&lt;br /&gt;
  WINDOW_ParentGroup,   gb_MainLayout = (struct Gadget *)&lt;br /&gt;
                    IIntuition-&amp;gt;NewObject(ILayout-&amp;gt;LAYOUT_GetClass(),NULL,&lt;br /&gt;
    LAYOUT_Orientation, LAYOUT_ORIENT_VERT,&lt;br /&gt;
    LAYOUT_SpaceOuter,  TRUE,&lt;br /&gt;
    LAYOUT_SpaceInner,  TRUE,&lt;br /&gt;
    LAYOUT_AddChild,    gb_ButtonGad,&lt;br /&gt;
    TAG_DONE),&lt;br /&gt;
  TAG_DONE)))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As already mentioned, creating menus has become a very simple task in the meantime. All you need to do is create the NewMenu structure (from &amp;quot;libraries/gadtools.h&amp;quot;) dating from gadtools times, which describes the individual menu points. This structure is given then when you create the window object. You no longer need to take care of deleting the menu structure; this happens automatically when the window object is released.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
  struct NewMenu gb_MenuDescribe[] =&lt;br /&gt;
  {&lt;br /&gt;
    { NM_TITLE, &amp;quot;Project&amp;quot;,   NULL, 0, 0, NULL },&lt;br /&gt;
    { NM_ITEM,  &amp;quot;Quit&amp;quot;,      NULL, 0, 0, NULL },&lt;br /&gt;
    { NM_END, NULL, NULL, 0, 0, NULL }&lt;br /&gt;
  };&lt;br /&gt;
&lt;br /&gt;
  #define MENU_ID_Quit FULLMENUNUM(0,0,NOSUB)&lt;br /&gt;
&lt;br /&gt;
  IIntuition-&amp;gt;NewObject(IWindow-&amp;gt;WINDOW_GetClass(),&lt;br /&gt;
      WINDOW_NewMenu, gb_MenuDescribe,&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Since AmigaOS 4&#039;s release the ReAction gadgets have been included in the BubbleHelp. If you move the mouse cursor over such an element, a bubble with help text will be displayed soon afterwards.  You need to do just a little bit of programming for this. Mainly, you must fill out the HintInfo structure from &amp;quot;classes/window.h&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
  struct HintInfo gb_HintInfo[] =&lt;br /&gt;
  {&lt;br /&gt;
    { GAD_ID_Help, -1, &amp;quot;activate/deactivate the BubbleHelp hints&amp;quot;, 0 },&lt;br /&gt;
    { GAD_ID_Quit, -1, &amp;quot;quit program&amp;quot;, 0 },&lt;br /&gt;
    { -1, -1, NULL, 0 }&lt;br /&gt;
  };&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The fourth value is reserved for the future flags and a 0 is assigned to it at the moment. The structure must be indicated when you create the window object.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
  IIntuition-&amp;gt;NewObject(IWindow-&amp;gt;WINDOW_GetClass(),&lt;br /&gt;
    WINDOW_HintInfo,      gb_HintInfo,&lt;br /&gt;
    WINDOW_GadgetHelp,    TRUE,&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
With the WINDOW_GadgetHelp you can turn on/off the help. With &#039;WINDOW_GadgetHelp, FALSE&#039; you can deactivate it, so it will not be displayed again. With TRUE you can re-activate it. You can change this tag during runtime. Other settings such as influencing the waiting time until the display, the display duration, the colour, etc. are still not possible, but users should be able to change them by using a global Prefs adjuster in the future.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
IIntuition-&amp;gt;SetAttrs(gb_WindowObj, WINDOW_GadgetHelp, FALSE, TAG_DONE);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We will add a checkbox to the sample program in order to put this possibility to use. We can turn on and off the help any time with it. In reality, you will set this option on a menu point or in the program settings, if there are any. A tooltype in the icon information is also an alternative.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
  struct Gadget *gb_CheckboxGad;&lt;br /&gt;
  #define GAD_ID_Help 1&lt;br /&gt;
&lt;br /&gt;
  if((gb_CheckboxGad = (struct Gadget *) IIntuition-&amp;gt;NewObject(ICheckBox-&amp;gt;CHECKBOX_GetClass(),NULL,&lt;br /&gt;
      GA_ID,          GAD_ID_Help,&lt;br /&gt;
      GA_RelVerify,   TRUE,&lt;br /&gt;
      GA_Text,        &amp;quot;Bubble_Help active&amp;quot;,&lt;br /&gt;
      TAG_DONE)))&lt;br /&gt;
&lt;br /&gt;
  WINDOW_ParentGroup,&lt;br /&gt;
    LAYOUT_AddChild,     gb_CheckboxGad,&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All GUI elements are now created, but they are still not visible. You should certainly check, whether the window pointer is present. If not, a gadget could probably not be created. To display the window you can use the RA_OpenWindow() macros from &amp;quot;reaction/reaction_macros.h&amp;quot;, to close it RA_CloseWindow() and to edit news RA_HandleInput().&lt;br /&gt;
&lt;br /&gt;
Since these are macros, you cannot use the typical interface notation. The news editing loop looks in practice as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
  if((gb_Win = RA_OpenWindow(gb_WindowObj)))&lt;br /&gt;
  {&lt;br /&gt;
    ULONG winsig;&lt;br /&gt;
    IIntuition-&amp;gt;GetAttr(WINDOW_SigMask,gb_WindowObj,&amp;amp;winsig);&lt;br /&gt;
&lt;br /&gt;
    BOOL run = TRUE;&lt;br /&gt;
    while(run)&lt;br /&gt;
    {&lt;br /&gt;
      ULONG result, code, val;&lt;br /&gt;
      &lt;br /&gt;
      const ULONG sigs = IExec-&amp;gt;Wait(winsig | SIGBREAKF_CTRL_C);&lt;br /&gt;
&lt;br /&gt;
      while((result = RA_HandleInput(gb_WindowObj,&amp;amp;code)) != WMHI_LASTMSG)&lt;br /&gt;
      {&lt;br /&gt;
        switch(result &amp;amp; WMHI_CLASSMASK)&lt;br /&gt;
        {&lt;br /&gt;
          case WMHI_GADGETUP:&lt;br /&gt;
               switch(result &amp;amp; WMHI_GADGETMASK)&lt;br /&gt;
               {&lt;br /&gt;
                 case GAD_ID_Help:&lt;br /&gt;
                      IIntuition-&amp;gt;GetAttr(CHECKBOX_Checked,gb_CheckboxGad,(ULONG*)&amp;amp;val);&lt;br /&gt;
                      IIntuition-&amp;gt;SetAttrs(gb_WindowObj,&lt;br /&gt;
                                           WINDOW_GadgetHelp, val,&lt;br /&gt;
                                           TAG_DONE);&lt;br /&gt;
                      break;&lt;br /&gt;
&lt;br /&gt;
                 case GAD_ID_Quit:&lt;br /&gt;
                      run = FALSE;&lt;br /&gt;
                      break;&lt;br /&gt;
               }&lt;br /&gt;
               break;&lt;br /&gt;
&lt;br /&gt;
          case WMHI_CLOSEWINDOW:&lt;br /&gt;
               run = FALSE;&lt;br /&gt;
               break;&lt;br /&gt;
&lt;br /&gt;
          case WMHI_MENUPICK:&lt;br /&gt;
               switch(result &amp;amp; WMHI_MENUMASK)&lt;br /&gt;
               {&lt;br /&gt;
                 case MENU_ID_Quit:&lt;br /&gt;
                      run = FALSE;&lt;br /&gt;
                      break;&lt;br /&gt;
               }&lt;br /&gt;
               break;&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
&lt;br /&gt;
      if(sigs &amp;amp; SIGBREAKF_CTRL_C) run = FALSE;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    RA_CloseWindow(gb_WindowObj);&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can see the various news types like press gadget (WMHI_GADGETUP), select menu (WMHI_MENUPICK) and the closing symbol for the window (WMHI_CLOSEWINDOW). But you can only get news, which has been defined explicitly as IDCMP_xxx Bits when creating the window.&lt;br /&gt;
&lt;br /&gt;
To close the program, that is, to release all created objects all you need to do is activate IIntuition-&amp;gt;DisposeObject(). It automatically makes sure that all elements included in the object are also released. If you specify the window pointer here, all included gadgets, menus and helptexts will be also deleted and can no longer be used!&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
IIntuition-&amp;gt;DisposeObject(gb_WindowObj);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
What is missing now are only the Includes and a main function. Then the program is complete and can be found as an example below.&lt;br /&gt;
&lt;br /&gt;
== ReAction Example ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
/* Michael Christoph&lt;br /&gt;
 * ReActionEx.c&lt;br /&gt;
 *&lt;br /&gt;
 * gcc ReActionEx.c -o ReActionEx -l auto&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
/******************************* INCLUDES *************************************/&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;intuition/gadgetclass.h&amp;gt;&lt;br /&gt;
#include &amp;lt;classes/window.h&amp;gt;&lt;br /&gt;
#include &amp;lt;reaction/reaction_macros.h&amp;gt;&lt;br /&gt;
#include &amp;lt;libraries/gadtools.h&amp;gt;&lt;br /&gt;
#include &amp;lt;gadgets/checkbox.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;proto/exec.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/dos.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/intuition.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/window.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/layout.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/button.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/checkbox.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define MENU_ID_Quit       FULLMENUNUM(0,0,NOSUB)&lt;br /&gt;
&lt;br /&gt;
#define GAD_ID_Help        1&lt;br /&gt;
#define GAD_ID_Quit        2&lt;br /&gt;
&lt;br /&gt;
/******************************************************************************/&lt;br /&gt;
&lt;br /&gt;
static const char *version USED = &amp;quot;\0$VER: ReActionEx 1.00 (16.12.2004) - (c) Dec.2004 by Meicky-Soft\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
/******************************************************************************/&lt;br /&gt;
&lt;br /&gt;
Object        *gb_WindowObj;&lt;br /&gt;
struct Window *gb_Win;&lt;br /&gt;
struct Gadget *gb_MainLayout;&lt;br /&gt;
struct Gadget *gb_ButtonGad;&lt;br /&gt;
struct Gadget *gb_CheckboxGad;&lt;br /&gt;
&lt;br /&gt;
struct NewMenu gb_MenuDescribe[] =&lt;br /&gt;
{&lt;br /&gt;
  { NM_TITLE, &amp;quot;Project&amp;quot;,   NULL, 0, 0, NULL },&lt;br /&gt;
  { NM_ITEM,  &amp;quot;Quit&amp;quot;,      NULL, 0, 0, NULL },&lt;br /&gt;
&lt;br /&gt;
  { NM_END, NULL, NULL, 0, 0, NULL }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct HintInfo gb_HintInfo[] =&lt;br /&gt;
{&lt;br /&gt;
 	{ GAD_ID_Help, -1, &amp;quot;Activate/Deactive BubbleHelp Tips&amp;quot;, 0 },&lt;br /&gt;
 	{ GAD_ID_Quit, -1, &amp;quot;Quit Program&amp;quot;, 0 },&lt;br /&gt;
 	{ -1, -1, NULL, 0 }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/******************************************************************************/&lt;br /&gt;
&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
  /* create a Checkbox Gadget */&lt;br /&gt;
  if((gb_CheckboxGad = (struct Gadget *) IIntuition-&amp;gt;NewObject(ICheckBox-&amp;gt;CHECKBOX_GetClass(),NULL,&lt;br /&gt;
      GA_ID,          GAD_ID_Help,&lt;br /&gt;
      GA_RelVerify,   TRUE,&lt;br /&gt;
      GA_Text,        &amp;quot;Bubble_Help Active&amp;quot;,&lt;br /&gt;
      TAG_DONE)))&lt;br /&gt;
  {&lt;br /&gt;
    /* create the Button */&lt;br /&gt;
    if((gb_ButtonGad = (struct Gadget *) IIntuition-&amp;gt;NewObject(IButton-&amp;gt;BUTTON_GetClass(),NULL,&lt;br /&gt;
        GA_ID,          GAD_ID_Quit,&lt;br /&gt;
        GA_RelVerify,   TRUE,&lt;br /&gt;
        GA_Text,        &amp;quot;_Quit&amp;quot;,&lt;br /&gt;
        TAG_DONE)))&lt;br /&gt;
    {&lt;br /&gt;
      /* create the Window Object */&lt;br /&gt;
      if((gb_WindowObj = (Object *) IIntuition-&amp;gt;NewObject(IWindow-&amp;gt;WINDOW_GetClass(),NULL,&lt;br /&gt;
        WA_IDCMP,             IDCMP_GADGETUP | IDCMP_CLOSEWINDOW | IDCMP_MENUPICK,&lt;br /&gt;
        WA_SizeGadget,        TRUE,&lt;br /&gt;
        WA_DepthGadget,       TRUE,&lt;br /&gt;
        WA_DragBar,           TRUE,&lt;br /&gt;
        WA_CloseGadget,       TRUE,&lt;br /&gt;
        WA_Activate,          TRUE,&lt;br /&gt;
        WA_Title,             &amp;quot;Example with ReAction gadgets and window class&amp;quot;,&lt;br /&gt;
        WINDOW_Position,      WPOS_CENTERSCREEN,&lt;br /&gt;
        WINDOW_NewMenu,       gb_MenuDescribe,&lt;br /&gt;
        WINDOW_HintInfo,      gb_HintInfo,&lt;br /&gt;
        WINDOW_GadgetHelp,    FALSE,&lt;br /&gt;
  &lt;br /&gt;
        /* create the Layout Object and include it into the Window */&lt;br /&gt;
        WINDOW_ParentGroup,   gb_MainLayout = (struct Gadget *)&lt;br /&gt;
                          IIntuition-&amp;gt;NewObject(ILayout-&amp;gt;LAYOUT_GetClass(),NULL,&lt;br /&gt;
          LAYOUT_Orientation,  LAYOUT_ORIENT_VERT,&lt;br /&gt;
          LAYOUT_SpaceOuter,   TRUE,&lt;br /&gt;
          LAYOUT_SpaceInner,   TRUE,&lt;br /&gt;
          LAYOUT_AddChild,     gb_CheckboxGad,&lt;br /&gt;
          LAYOUT_AddChild,     gb_ButtonGad,&lt;br /&gt;
          TAG_DONE),&lt;br /&gt;
        TAG_DONE)))&lt;br /&gt;
      {&lt;br /&gt;
        /* open the Window */&lt;br /&gt;
        if((gb_Win = RA_OpenWindow(gb_WindowObj)))&lt;br /&gt;
        {&lt;br /&gt;
          /* query the Signal Bit of the Window */&lt;br /&gt;
          ULONG winsig;&lt;br /&gt;
          IIntuition-&amp;gt;GetAttr(WINDOW_SigMask,gb_WindowObj,&amp;amp;winsig);&lt;br /&gt;
  &lt;br /&gt;
          BOOL laufen = TRUE;&lt;br /&gt;
          while(laufen)&lt;br /&gt;
          {&lt;br /&gt;
            ULONG result, code, val;&lt;br /&gt;
            &lt;br /&gt;
            /* wait till either Button or Close Icon are clicked */&lt;br /&gt;
            const ULONG sigs = IExec-&amp;gt;Wait(winsig | SIGBREAKF_CTRL_C);&lt;br /&gt;
  &lt;br /&gt;
            /* process the received Messages */&lt;br /&gt;
            while((result = RA_HandleInput(gb_WindowObj,&amp;amp;code)) != WMHI_LASTMSG)&lt;br /&gt;
            {&lt;br /&gt;
              /* mask out the Messages part */&lt;br /&gt;
              switch(result &amp;amp; WMHI_CLASSMASK)&lt;br /&gt;
              {&lt;br /&gt;
                /* process the Gadget Messages */&lt;br /&gt;
                case WMHI_GADGETUP:&lt;br /&gt;
                     switch(result &amp;amp; WMHI_GADGETMASK)&lt;br /&gt;
                     {&lt;br /&gt;
                       case GAD_ID_Help:&lt;br /&gt;
                            IIntuition-&amp;gt;GetAttr(CHECKBOX_Checked,&lt;br /&gt;
                                                (Object*)gb_CheckboxGad,&lt;br /&gt;
                                                (ULONG*)&amp;amp;val);&lt;br /&gt;
                            IIntuition-&amp;gt;SetAttrs(gb_WindowObj,&lt;br /&gt;
                                                 WINDOW_GadgetHelp, val,&lt;br /&gt;
                                                 TAG_DONE);&lt;br /&gt;
                            break;&lt;br /&gt;
&lt;br /&gt;
                       case GAD_ID_Quit:&lt;br /&gt;
                            laufen = FALSE;&lt;br /&gt;
                            break;&lt;br /&gt;
                     }&lt;br /&gt;
                     break;&lt;br /&gt;
  &lt;br /&gt;
                /* query the Window Close Icon */&lt;br /&gt;
                case WMHI_CLOSEWINDOW:&lt;br /&gt;
                     laufen = FALSE;&lt;br /&gt;
                     break;&lt;br /&gt;
  &lt;br /&gt;
                /* query the Menu Selection */&lt;br /&gt;
                case WMHI_MENUPICK:&lt;br /&gt;
                     switch(result &amp;amp; WMHI_MENUMASK)&lt;br /&gt;
                     {&lt;br /&gt;
                       case MENU_ID_Quit:&lt;br /&gt;
                            laufen = FALSE;&lt;br /&gt;
                            break;&lt;br /&gt;
                     }&lt;br /&gt;
                     break;&lt;br /&gt;
              }&lt;br /&gt;
            }&lt;br /&gt;
  &lt;br /&gt;
            /* query if CTRL-C received from the Shell */&lt;br /&gt;
            if(sigs &amp;amp; SIGBREAKF_CTRL_C) laufen = FALSE;&lt;br /&gt;
          }&lt;br /&gt;
  &lt;br /&gt;
          /* close the Window */&lt;br /&gt;
          RA_CloseWindow(gb_WindowObj);&lt;br /&gt;
        }&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    /* release Window Object, dump also Layout and Gadget Objects */&lt;br /&gt;
    IIntuition-&amp;gt;DisposeObject(gb_WindowObj);&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:AF110_reactionex.png|frame|center]]&lt;br /&gt;
&lt;br /&gt;
= AllGadgets Example =&lt;br /&gt;
&lt;br /&gt;
We can deal with programming with ReAction here only in theory. But for this purpose we have put &amp;quot;AllGadgets.c&amp;quot; as a bonus. Here all available gadgets are used and you can see how they can be created and queried. The use of page gadgets is also shown. In conjunction with the Clicktab gadget you can also realise tabs, which always show another &#039;page&#039; with gadgets.  For instance, you can divide comprehensive setting windows into individual pages.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
/* Michael Christoph&lt;br /&gt;
 * AllGadgets.c&lt;br /&gt;
 *&lt;br /&gt;
 * gcc AllGadgets.c -o AllGadgets -l auto&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
/******************************* INCLUDES *************************************/&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;exec/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;intuition/gadgetclass.h&amp;gt;&lt;br /&gt;
#include &amp;lt;intuition/icclass.h&amp;gt;&lt;br /&gt;
#include &amp;lt;classes/window.h&amp;gt;&lt;br /&gt;
#include &amp;lt;classes/requester.h&amp;gt;&lt;br /&gt;
#include &amp;lt;reaction/reaction_macros.h&amp;gt;&lt;br /&gt;
#include &amp;lt;libraries/gadtools.h&amp;gt;&lt;br /&gt;
#include &amp;lt;clib/macros.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;gadgets/button.h&amp;gt;&lt;br /&gt;
#include &amp;lt;gadgets/space.h&amp;gt;&lt;br /&gt;
#include &amp;lt;gadgets/checkbox.h&amp;gt;&lt;br /&gt;
#include &amp;lt;gadgets/listbrowser.h&amp;gt;&lt;br /&gt;
#include &amp;lt;gadgets/string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;gadgets/integer.h&amp;gt;&lt;br /&gt;
#include &amp;lt;gadgets/radiobutton.h&amp;gt;&lt;br /&gt;
#include &amp;lt;gadgets/scroller.h&amp;gt;&lt;br /&gt;
#include &amp;lt;gadgets/slider.h&amp;gt;&lt;br /&gt;
#include &amp;lt;gadgets/getfile.h&amp;gt;&lt;br /&gt;
#include &amp;lt;gadgets/getfont.h&amp;gt;&lt;br /&gt;
#include &amp;lt;gadgets/getscreenmode.h&amp;gt;&lt;br /&gt;
#include &amp;lt;gadgets/getcolor.h&amp;gt;&lt;br /&gt;
#include &amp;lt;gadgets/chooser.h&amp;gt;&lt;br /&gt;
#include &amp;lt;gadgets/texteditor.h&amp;gt;&lt;br /&gt;
#include &amp;lt;gadgets/colorwheel.h&amp;gt;&lt;br /&gt;
#include &amp;lt;gadgets/gradientslider.h&amp;gt;&lt;br /&gt;
#include &amp;lt;gadgets/datebrowser.h&amp;gt;&lt;br /&gt;
#include &amp;lt;gadgets/fuelgauge.h&amp;gt;&lt;br /&gt;
#include &amp;lt;gadgets/listview.h&amp;gt;&lt;br /&gt;
#include &amp;lt;gadgets/layout.h&amp;gt;&lt;br /&gt;
#include &amp;lt;gadgets/clicktab.h&amp;gt;&lt;br /&gt;
#include &amp;lt;gadgets/page.h&amp;gt;&lt;br /&gt;
#include &amp;lt;gadgets/palette.h&amp;gt;&lt;br /&gt;
#include &amp;lt;gadgets/virtual.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;images/label.h&amp;gt;&lt;br /&gt;
#include &amp;lt;images/bevel.h&amp;gt;&lt;br /&gt;
#include &amp;lt;images/bitmap.h&amp;gt;&lt;br /&gt;
#include &amp;lt;images/drawlist.h&amp;gt;&lt;br /&gt;
#include &amp;lt;images/filler.h&amp;gt;&lt;br /&gt;
#include &amp;lt;images/glyph.h&amp;gt;&lt;br /&gt;
#include &amp;lt;images/penmap.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;proto/exec.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/dos.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/intuition.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/graphics.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/utility.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/asl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/locale.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/application.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/timer.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/window.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/layout.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/button.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/slider.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/scroller.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/space.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/label.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/integer.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/listbrowser.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/clicktab.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/chooser.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/radiobutton.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/checkbox.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/palette.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/datebrowser.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/fuelgauge.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/getfile.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/getfont.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/getscreenmode.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/getcolor.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/texteditor.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/colorwheel.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/label.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/bevel.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/bitmap.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/drawlist.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/filler.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/glyph.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/penmap.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/******************************************************************************/&lt;br /&gt;
&lt;br /&gt;
static const char *version USED = &amp;quot;\0$VER: AllGadgets 1.01 (14.04.2014) - (c) Apr.2014 by Meicky-Soft\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
/******************************************************************************/&lt;br /&gt;
&lt;br /&gt;
enum GADIDs&lt;br /&gt;
{&lt;br /&gt;
  GAD_ID_ButtonV,&lt;br /&gt;
  GAD_ID_Button,&lt;br /&gt;
  GAD_ID_String,&lt;br /&gt;
  GAD_ID_Integer,&lt;br /&gt;
  GAD_ID_Slider,&lt;br /&gt;
  GAD_ID_Scroller,&lt;br /&gt;
&lt;br /&gt;
  GAD_ID_Chooser,&lt;br /&gt;
  GAD_ID_Chooser2,&lt;br /&gt;
  GAD_ID_Chooser3,&lt;br /&gt;
  GAD_ID_Checkbox,&lt;br /&gt;
  GAD_ID_Radio,&lt;br /&gt;
  GAD_ID_Listbrowser,&lt;br /&gt;
  GAD_ID_Palette,&lt;br /&gt;
&lt;br /&gt;
  GAD_ID_File,&lt;br /&gt;
  GAD_ID_Font,&lt;br /&gt;
  GAD_ID_Screenmode,&lt;br /&gt;
  GAD_ID_Color,&lt;br /&gt;
&lt;br /&gt;
  GAD_ID_Fuelgauge,&lt;br /&gt;
  GAD_ID_Colorwheel,&lt;br /&gt;
  GAD_ID_Gradientslider,&lt;br /&gt;
  GAD_ID_Texteditor,&lt;br /&gt;
  GAD_ID_Datebrowser,&lt;br /&gt;
&lt;br /&gt;
  GAD_ID_Space,&lt;br /&gt;
  GAD_ID_Page,&lt;br /&gt;
  GAD_ID_Clicktab,&lt;br /&gt;
&lt;br /&gt;
  GAD_ID_Pages,&lt;br /&gt;
  GAD_ID_PagesClicktab,&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/******************************************************************************/&lt;br /&gt;
&lt;br /&gt;
struct List gb_List;&lt;br /&gt;
&lt;br /&gt;
struct ColumnInfo gb_ListbrowserColumn[] =&lt;br /&gt;
{&lt;br /&gt;
   {   30, &amp;quot;Nummer&amp;quot;, 0 },&lt;br /&gt;
   {  170, &amp;quot;Eintrag&amp;quot;, 0 },&lt;br /&gt;
   { -1, (STRPTR)~0, (ULONG)-1 }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct Hook gb_RenderHook;&lt;br /&gt;
struct Hook gb_IDCMPHook;&lt;br /&gt;
&lt;br /&gt;
STRPTR gb_ChooserLabels[] = { &amp;quot;Amiga 1000&amp;quot;, &amp;quot;Amiga 1200&amp;quot;, &amp;quot;AmigaOne&amp;quot;, NULL };&lt;br /&gt;
STRPTR gb_Chooser2Labels[] = { &amp;quot;Amiga 1000&amp;quot;, &amp;quot;Amiga 1200&amp;quot;, &amp;quot;AmigaOne&amp;quot;, NULL };&lt;br /&gt;
STRPTR gb_Chooser3Labels[] = { &amp;quot;Amiga 1000&amp;quot;, &amp;quot;Amiga 1200&amp;quot;, &amp;quot;AmigaOne&amp;quot;, NULL };&lt;br /&gt;
&lt;br /&gt;
STRPTR gb_RadioLabels[] = { &amp;quot;Amiga 1000&amp;quot;, &amp;quot;Amiga 1200&amp;quot;, &amp;quot;AmigaOne&amp;quot;, NULL };&lt;br /&gt;
&lt;br /&gt;
STRPTR gb_ClicktabLabels[] = { &amp;quot;Amiga 1000&amp;quot;, &amp;quot;Amiga 1200&amp;quot;, &amp;quot;AmigaOne&amp;quot;, NULL };&lt;br /&gt;
&lt;br /&gt;
STRPTR gb_PagesLabels[] = { &amp;quot;_Grundtypen&amp;quot;, &amp;quot;_Auswahllisten&amp;quot;, &amp;quot;ASL-Aus_wahl&amp;quot;,&lt;br /&gt;
                            &amp;quot;Sonstige _Typen&amp;quot;, &amp;quot;_Seitengestalltung&amp;quot;,&lt;br /&gt;
                            &amp;quot;_Images&amp;quot;, NULL };&lt;br /&gt;
&lt;br /&gt;
UWORD gb_GradientArray[] = { ~0, ~0, ~0, ~0, ~0, ~0, ~0 };&lt;br /&gt;
&lt;br /&gt;
/******************************************************************************/&lt;br /&gt;
&lt;br /&gt;
struct Gadget *gb_ButtonVGad;&lt;br /&gt;
struct Gadget *gb_ButtonGad;&lt;br /&gt;
struct Gadget *gb_StringGad;&lt;br /&gt;
struct Gadget *gb_IntegerGad;&lt;br /&gt;
struct Gadget *gb_SliderGad;&lt;br /&gt;
struct Gadget *gb_ScrollerGad;&lt;br /&gt;
struct Gadget *gb_ChooserGad;&lt;br /&gt;
struct Gadget *gb_Chooser2Gad;&lt;br /&gt;
struct Gadget *gb_Chooser3Gad;&lt;br /&gt;
struct Gadget *gb_CheckboxGad;&lt;br /&gt;
struct Gadget *gb_RadioGad;&lt;br /&gt;
struct Gadget *gb_ListbrowserGad;&lt;br /&gt;
struct Gadget *gb_PaletteGad;&lt;br /&gt;
struct Gadget *gb_FileGad;&lt;br /&gt;
struct Gadget *gb_FontGad;&lt;br /&gt;
struct Gadget *gb_ScreenmodeGad;&lt;br /&gt;
struct Gadget *gb_ColorGad;&lt;br /&gt;
struct Gadget *gb_FuelgaugeGad;&lt;br /&gt;
struct Gadget *gb_GradientsliderGad;&lt;br /&gt;
struct Gadget *gb_ColorwheelGad;&lt;br /&gt;
struct Gadget *gb_TexteditorGad;&lt;br /&gt;
struct Gadget *gb_DatebrowserGad;&lt;br /&gt;
struct Gadget *gb_SpaceGad;&lt;br /&gt;
struct Gadget *gb_PageGad;&lt;br /&gt;
struct Gadget *gb_ClicktabGad;&lt;br /&gt;
&lt;br /&gt;
struct Image  *gb_LabelImg;&lt;br /&gt;
struct Image  *gb_BevelImg;&lt;br /&gt;
struct Image  *gb_BitmapImg;&lt;br /&gt;
struct Image  *gb_BitmapSImg;&lt;br /&gt;
struct Image  *gb_BitmapDImg;&lt;br /&gt;
struct Image  *gb_DrawlistImg;&lt;br /&gt;
struct Image  *gb_FillerImg;&lt;br /&gt;
struct Image  *gb_GlyphImg[27];&lt;br /&gt;
struct Image  *gb_PenmapImg;&lt;br /&gt;
&lt;br /&gt;
struct Gadget *gb_MainLayout;&lt;br /&gt;
struct Gadget *gb_Page1Layout;&lt;br /&gt;
struct Gadget *gb_Page2Layout;&lt;br /&gt;
struct Gadget *gb_Page3Layout;&lt;br /&gt;
struct Gadget *gb_Page4Layout;&lt;br /&gt;
struct Gadget *gb_Page5Layout;&lt;br /&gt;
struct Gadget *gb_Page6Layout;&lt;br /&gt;
struct Gadget *gb_PagesLayout;&lt;br /&gt;
struct Gadget *gb_PagesClicktab;&lt;br /&gt;
&lt;br /&gt;
Object        *gb_WindowObj;&lt;br /&gt;
struct Window *gb_Win;&lt;br /&gt;
struct Screen *gb_Scr;&lt;br /&gt;
&lt;br /&gt;
ULONG   image_object_palette[] =&lt;br /&gt;
{&lt;br /&gt;
   2,&lt;br /&gt;
   0x00000000, 0x00000000, 0x00000000,&lt;br /&gt;
   0xEEEEEEEE, 0xDDDDDDDD, 0x00000000&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
UBYTE   happy_data[] =&lt;br /&gt;
{&lt;br /&gt;
   0,16, 0,14,&lt;br /&gt;
   0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,&lt;br /&gt;
   0,0,0,1,1,2,2,2,2,2,2,1,1,0,0,0,&lt;br /&gt;
   0,0,1,2,2,2,2,2,2,2,2,2,2,1,0,0,&lt;br /&gt;
   0,1,2,2,2,2,2,2,2,2,2,2,2,2,1,0,&lt;br /&gt;
   0,1,2,2,2,1,1,2,2,1,1,2,2,2,1,0,&lt;br /&gt;
   1,2,2,2,2,1,1,2,2,1,1,2,2,2,2,1,&lt;br /&gt;
   1,2,2,2,2,1,1,2,2,1,1,2,2,2,2,1,&lt;br /&gt;
   1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,&lt;br /&gt;
   1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,&lt;br /&gt;
   0,1,2,2,2,1,2,2,2,2,1,2,2,2,1,0,&lt;br /&gt;
   0,1,2,2,2,2,1,1,1,1,2,2,2,2,1,0,&lt;br /&gt;
   0,0,1,2,2,2,2,2,2,2,2,2,2,1,0,0,&lt;br /&gt;
   0,0,0,1,1,2,2,2,2,2,2,1,1,0,0,0,&lt;br /&gt;
   0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
UBYTE   scared_data[] =&lt;br /&gt;
{&lt;br /&gt;
   0,16, 0,14,&lt;br /&gt;
   0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,&lt;br /&gt;
   0,0,0,1,1,2,2,2,2,2,2,1,1,0,0,0,&lt;br /&gt;
   0,0,1,2,2,2,2,2,2,2,2,2,2,1,0,0,&lt;br /&gt;
   0,1,2,2,2,1,1,2,2,1,1,2,2,2,1,0,&lt;br /&gt;
   0,1,2,2,1,2,2,2,2,2,2,1,2,2,1,0,&lt;br /&gt;
   1,2,2,2,2,1,1,2,2,1,1,2,2,2,2,1,&lt;br /&gt;
   1,2,2,2,2,1,1,2,2,1,1,2,2,2,2,1,&lt;br /&gt;
   1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,&lt;br /&gt;
   1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1,&lt;br /&gt;
   0,1,2,2,2,2,1,1,1,1,2,2,2,2,1,0,&lt;br /&gt;
   0,1,2,2,2,1,1,1,1,1,1,2,2,2,1,0,&lt;br /&gt;
   0,0,1,2,2,2,2,2,2,2,2,2,2,1,0,0,&lt;br /&gt;
   0,0,0,1,1,2,2,2,2,2,2,1,1,0,0,0,&lt;br /&gt;
   0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct DrawList gb_DrawList[] =&lt;br /&gt;
{&lt;br /&gt;
  { DLST_LINE, 0,30,15,0, 1},&lt;br /&gt;
  { DLST_LINE, 30,30,15,0, 1},&lt;br /&gt;
  { DLST_LINE, 9,15,23,15, 1},&lt;br /&gt;
  { DLST_END }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/******************************************************************************/&lt;br /&gt;
&lt;br /&gt;
BOOL CreateEntry(ULONG num, CONST_STRPTR number, CONST_STRPTR text)&lt;br /&gt;
{&lt;br /&gt;
  /* create a List entry */&lt;br /&gt;
&lt;br /&gt;
  /* ATTENTION:&lt;br /&gt;
  ** Use this function only if the List is *not* assigned to the ListView!&lt;br /&gt;
  ** If applicable, deselect via&lt;br /&gt;
  ** SetGadgetAttrs(gad,win,NULL, LISTBROWSER_Labels,~0, TAG_END);&lt;br /&gt;
  ** then modify the List, then assign the List via&lt;br /&gt;
  ** SetGadgetAttrs(gad,win,NULL, LISTBROWSER_Labels,liste, TAG_END);&lt;br /&gt;
  ** back to the ListView.&lt;br /&gt;
&lt;br /&gt;
  struct Node *node;&lt;br /&gt;
&lt;br /&gt;
  if((node = IListBrowser-&amp;gt;AllocListBrowserNode(2,&lt;br /&gt;
              LBNA_Column,   0,&lt;br /&gt;
                      LBNCA_Text,          number,&lt;br /&gt;
                      LBNCA_Justification, LCJ_LEFT,&lt;br /&gt;
                      LBNCA_Editable,      FALSE,&lt;br /&gt;
                      LBNCA_CopyText,      TRUE,&lt;br /&gt;
                      LBNCA_MaxChars,      4,&lt;br /&gt;
              LBNA_Column,   1,&lt;br /&gt;
                      LBNCA_Text,          text,&lt;br /&gt;
                      LBNCA_Justification, LCJ_LEFT,&lt;br /&gt;
                      LBNCA_Editable,      FALSE,&lt;br /&gt;
                      LBNCA_CopyText,      TRUE,&lt;br /&gt;
                      LBNCA_MaxChars,      100,&lt;br /&gt;
              TAG_END)))&lt;br /&gt;
  {&lt;br /&gt;
    node-&amp;gt;ln_Pri = num;&lt;br /&gt;
    IExec-&amp;gt;AddTail(&amp;amp;gb_List,node);&lt;br /&gt;
  }&lt;br /&gt;
  else&lt;br /&gt;
  {&lt;br /&gt;
    IDOS-&amp;gt;Printf(&amp;quot;Out of memory while creating list entry\n&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return( node ? TRUE : FALSE );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/******************************************************************************/&lt;br /&gt;
&lt;br /&gt;
void FreigebenList()&lt;br /&gt;
{&lt;br /&gt;
  /* release the List with all its data */&lt;br /&gt;
&lt;br /&gt;
  /* ATTENTION:&lt;br /&gt;
  ** Use this function only if the List is *not* assigned to the ListView!&lt;br /&gt;
  ** If applicable, deselect via&lt;br /&gt;
  ** SetGadgetAttrs(gad,win,NULL, LISTBROWSER_Labels,~0, TAG_END);&lt;br /&gt;
  ** then modify the List, then assign the (empty) List via&lt;br /&gt;
  ** SetGadgetAttrs(gad,win,NULL, LISTBROWSER_Labels,liste, TAG_END);&lt;br /&gt;
  ** back to the ListView.&lt;br /&gt;
  */&lt;br /&gt;
&lt;br /&gt;
  struct Node *node, *nextnode;&lt;br /&gt;
  node = gb_List.lh_Head;&lt;br /&gt;
&lt;br /&gt;
  while((nextnode = node-&amp;gt;ln_Succ))&lt;br /&gt;
  {&lt;br /&gt;
    IExec-&amp;gt;Remove(node);&lt;br /&gt;
    IListBrowser-&amp;gt;FreeListBrowserNode(node);&lt;br /&gt;
&lt;br /&gt;
    node = nextnode;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/******************************************************************************/&lt;br /&gt;
&lt;br /&gt;
void RenderHookFunc(struct Hook *hook, Object *obj, struct gpRender *gpr)&lt;br /&gt;
{&lt;br /&gt;
  /*&lt;br /&gt;
  ** Hook Function to refresh the Space Gadgets&lt;br /&gt;
  */&lt;br /&gt;
&lt;br /&gt;
  /* only if the Window is visible we can draw into it */&lt;br /&gt;
  if(gb_Win)&lt;br /&gt;
  {&lt;br /&gt;
    /* determine the size of our Output Area */&lt;br /&gt;
    struct IBox *gb_DrawArea;&lt;br /&gt;
    IIntuition-&amp;gt;GetAttr(SPACE_AreaBox,(Object*)gb_SpaceGad,(ULONG *)&amp;amp;gb_DrawArea);&lt;br /&gt;
&lt;br /&gt;
    /* empty the complete Area with Background Color */&lt;br /&gt;
    IGraphics-&amp;gt;SetAPen(gpr-&amp;gt;gpr_RPort,0);&lt;br /&gt;
    IGraphics-&amp;gt;RectFill(gpr-&amp;gt;gpr_RPort,gb_DrawArea-&amp;gt;Left,gb_DrawArea-&amp;gt;Top,&lt;br /&gt;
     gb_DrawArea-&amp;gt;Left+gb_DrawArea-&amp;gt;Width-1,gb_DrawArea-&amp;gt;Top+gb_DrawArea-&amp;gt;Height-1);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/******************************************************************************/&lt;br /&gt;
&lt;br /&gt;
void IDCMPHookFunc(struct Hook *hook, Object *winobj, struct IntuiMessage *msg)&lt;br /&gt;
{&lt;br /&gt;
  /*&lt;br /&gt;
  ** Hook Function for listening to IDCMP_UPDATE Messages&lt;br /&gt;
  */&lt;br /&gt;
&lt;br /&gt;
  struct TagItem *taglist = (struct TagItem *) msg-&amp;gt;IAddress;&lt;br /&gt;
  const LONG gadid = IUtility-&amp;gt;GetTagData(GA_ID,-1,taglist);&lt;br /&gt;
&lt;br /&gt;
  if(msg-&amp;gt;Class == IDCMP_GADGETDOWN)&lt;br /&gt;
  {&lt;br /&gt;
    /* Press Mouse Button: Set start position without drawing */&lt;br /&gt;
    IGraphics-&amp;gt;SetAPen(gb_Win-&amp;gt;RPort,4);&lt;br /&gt;
    IGraphics-&amp;gt;Move(gb_Win-&amp;gt;RPort,msg-&amp;gt;MouseX,msg-&amp;gt;MouseY);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  if(msg-&amp;gt;Class == IDCMP_IDCMPUPDATE &amp;amp;&amp;amp; gadid == GAD_ID_Space)&lt;br /&gt;
  {&lt;br /&gt;
    //ULONG mx, my;&lt;br /&gt;
    //IIntuition-&amp;gt;GetAttr(SPACE_MouseX,gb_SpaceGad,(ULONG*)&amp;amp;mx);&lt;br /&gt;
    //IIntuition-&amp;gt;GetAttr(SPACE_MouseY,gb_SpaceGad,(ULONG*)&amp;amp;my);&lt;br /&gt;
&lt;br /&gt;
    /* determine the size of our Output Area */&lt;br /&gt;
    /* so we don&#039;t draw outside of this area */&lt;br /&gt;
    struct IBox *gb_DrawArea;&lt;br /&gt;
    IIntuition-&amp;gt;GetAttr(SPACE_AreaBox,(Object*)gb_SpaceGad,(ULONG *)&amp;amp;gb_DrawArea);&lt;br /&gt;
&lt;br /&gt;
    const LONG mx = msg-&amp;gt;MouseX;&lt;br /&gt;
    const LONG my = msg-&amp;gt;MouseY;&lt;br /&gt;
&lt;br /&gt;
    if(mx &amp;gt;= gb_DrawArea-&amp;gt;Left &amp;amp;&amp;amp;&lt;br /&gt;
       my &amp;gt;= gb_DrawArea-&amp;gt;Top &amp;amp;&amp;amp;&lt;br /&gt;
       mx &amp;lt;= gb_DrawArea-&amp;gt;Left+gb_DrawArea-&amp;gt;Width-1 &amp;amp;&amp;amp;&lt;br /&gt;
       my &amp;lt;= gb_DrawArea-&amp;gt;Top+gb_DrawArea-&amp;gt;Height-1)&lt;br /&gt;
    {&lt;br /&gt;
      IGraphics-&amp;gt;Draw(gb_Win-&amp;gt;RPort,msg-&amp;gt;MouseX,msg-&amp;gt;MouseY);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/******************************************************************************/&lt;br /&gt;
&lt;br /&gt;
BOOL CreateAll()&lt;br /&gt;
{&lt;br /&gt;
  int i;&lt;br /&gt;
&lt;br /&gt;
  /* Screen Pointer is needed for single Gadgets */&lt;br /&gt;
  gb_Scr = IIntuition-&amp;gt;LockPubScreen(NULL);&lt;br /&gt;
&lt;br /&gt;
  if(gb_Scr)&lt;br /&gt;
  {&lt;br /&gt;
    /* request and set pens for the Gradient Slider */&lt;br /&gt;
    struct ColorMap *cm = gb_Scr-&amp;gt;ViewPort.ColorMap;&lt;br /&gt;
&lt;br /&gt;
    gb_GradientArray[0] = IGraphics-&amp;gt;ObtainPen(cm,~0,0xFF,0xFF,0xFF,PENF_EXCLUSIVE);&lt;br /&gt;
    gb_GradientArray[1] = IGraphics-&amp;gt;ObtainPen(cm,~0,0xCC,0xCC,0xCC,PENF_EXCLUSIVE);&lt;br /&gt;
    gb_GradientArray[2] = IGraphics-&amp;gt;ObtainPen(cm,~0,0x99,0x99,0x99,PENF_EXCLUSIVE);&lt;br /&gt;
    gb_GradientArray[3] = IGraphics-&amp;gt;ObtainPen(cm,~0,0x66,0x66,0x66,PENF_EXCLUSIVE);&lt;br /&gt;
    gb_GradientArray[4] = IGraphics-&amp;gt;ObtainPen(cm,~0,0x33,0x33,0x33,PENF_EXCLUSIVE);&lt;br /&gt;
    gb_GradientArray[5] = IGraphics-&amp;gt;ObtainPen(cm,~0,0x00,0x00,0x00,PENF_EXCLUSIVE);&lt;br /&gt;
&lt;br /&gt;
    struct ViewPort *vp = &amp;amp;gb_Scr-&amp;gt;ViewPort;&lt;br /&gt;
&lt;br /&gt;
    if((WORD)gb_GradientArray[0] != ~0) IGraphics-&amp;gt;SetRGB4(vp,gb_GradientArray[0],0xFF,0xFF,0xFF);&lt;br /&gt;
    if((WORD)gb_GradientArray[1] != ~0) IGraphics-&amp;gt;SetRGB4(vp,gb_GradientArray[1],0xCC,0xCC,0xCC);&lt;br /&gt;
    if((WORD)gb_GradientArray[2] != ~0) IGraphics-&amp;gt;SetRGB4(vp,gb_GradientArray[2],0x99,0x99,0x99);&lt;br /&gt;
    if((WORD)gb_GradientArray[3] != ~0) IGraphics-&amp;gt;SetRGB4(vp,gb_GradientArray[3],0x66,0x66,0x66);&lt;br /&gt;
    if((WORD)gb_GradientArray[4] != ~0) IGraphics-&amp;gt;SetRGB4(vp,gb_GradientArray[4],0x33,0x33,0x33);&lt;br /&gt;
    if((WORD)gb_GradientArray[5] != ~0) IGraphics-&amp;gt;SetRGB4(vp,gb_GradientArray[5],0x00,0x00,0x00);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  /* create Listbrowser entries */&lt;br /&gt;
  IExec-&amp;gt;NewList(&amp;amp;gb_List);&lt;br /&gt;
  CreateEntry(0,&amp;quot;1&amp;quot;,&amp;quot;Amiga 1000&amp;quot;);&lt;br /&gt;
  CreateEntry(1,&amp;quot;2&amp;quot;,&amp;quot;Amiga 1200&amp;quot;);&lt;br /&gt;
  CreateEntry(2,&amp;quot;3&amp;quot;,&amp;quot;AmigaOne&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  /* initialize RenderHook */&lt;br /&gt;
  gb_RenderHook.h_Entry    = (ULONG (*)())RenderHookFunc;&lt;br /&gt;
  gb_RenderHook.h_SubEntry = NULL;&lt;br /&gt;
&lt;br /&gt;
  /* initialize IDCMPHook for listening to IDCMP_UPDATE Messages */&lt;br /&gt;
  gb_IDCMPHook.h_Entry    = (ULONG (*)())IDCMPHookFunc;&lt;br /&gt;
  gb_IDCMPHook.h_SubEntry = NULL;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  /* create Gadget Object */&lt;br /&gt;
  gb_ButtonVGad = (struct Gadget *) IIntuition-&amp;gt;NewObject(IButton-&amp;gt;BUTTON_GetClass(),NULL,&lt;br /&gt;
      BUTTON_BevelStyle,          BVS_THIN,&lt;br /&gt;
      BUTTON_Justification,       BCJ_LEFT,&lt;br /&gt;
      GA_ID,                      GAD_ID_ButtonV,&lt;br /&gt;
      GA_Text,                    &amp;quot;Info-Anzeige&amp;quot;,&lt;br /&gt;
      GA_ReadOnly,                TRUE,&lt;br /&gt;
      TAG_END);&lt;br /&gt;
&lt;br /&gt;
  gb_ButtonGad = (struct Gadget *) IIntuition-&amp;gt;NewObject(IButton-&amp;gt;BUTTON_GetClass(),NULL,&lt;br /&gt;
      GA_ID,                      GAD_ID_Button,&lt;br /&gt;
      GA_Text,                    &amp;quot;Button&amp;quot;,&lt;br /&gt;
      TAG_END);&lt;br /&gt;
&lt;br /&gt;
  gb_StringGad = (struct Gadget *) IIntuition-&amp;gt;NewObject(IString-&amp;gt;STRING_GetClass(),NULL,&lt;br /&gt;
      GA_ID,                      GAD_ID_String,&lt;br /&gt;
      GA_RelVerify,               TRUE,&lt;br /&gt;
      GA_TabCycle,                TRUE,&lt;br /&gt;
      STRINGA_MaxChars,           30+1,&lt;br /&gt;
      STRINGA_MinVisible,         30,&lt;br /&gt;
      STRINGA_TextVal,            &amp;quot;Amiga 1000&amp;quot;,&lt;br /&gt;
      TAG_END);&lt;br /&gt;
&lt;br /&gt;
  gb_IntegerGad = (struct Gadget *) IIntuition-&amp;gt;NewObject(IInteger-&amp;gt;INTEGER_GetClass(),NULL,&lt;br /&gt;
      GA_ID,                      GAD_ID_Integer,&lt;br /&gt;
      GA_RelVerify,               TRUE,&lt;br /&gt;
      GA_TabCycle,                TRUE,&lt;br /&gt;
      INTEGER_MaxChars,           4,&lt;br /&gt;
      INTEGER_Arrows,             TRUE,&lt;br /&gt;
      INTEGER_MinVisible,         3,&lt;br /&gt;
      INTEGER_Minimum,            1,&lt;br /&gt;
      INTEGER_Maximum,            100,&lt;br /&gt;
      TAG_END);&lt;br /&gt;
&lt;br /&gt;
  gb_SliderGad = (struct Gadget *) IIntuition-&amp;gt;NewObject(ISlider-&amp;gt;SLIDER_GetClass(),NULL,&lt;br /&gt;
      GA_ID,                      GAD_ID_Slider,&lt;br /&gt;
      GA_Immediate,               TRUE,&lt;br /&gt;
      GA_RelVerify,               TRUE,&lt;br /&gt;
      SLIDER_Min,                 0,&lt;br /&gt;
      SLIDER_Max,                 100,&lt;br /&gt;
      SLIDER_Level,               10,&lt;br /&gt;
      SLIDER_Orientation,         SLIDER_HORIZONTAL,&lt;br /&gt;
      SLIDER_Ticks,               11,&lt;br /&gt;
      SLIDER_KnobDelta,           50,&lt;br /&gt;
      SLIDER_LevelFormat,         &amp;quot;%3ld&amp;quot;,&lt;br /&gt;
      SLIDER_LevelMaxLen,         3+1,&lt;br /&gt;
      SLIDER_LevelPlace,          PLACETEXT_IN,&lt;br /&gt;
      TAG_END);&lt;br /&gt;
&lt;br /&gt;
  gb_ScrollerGad = (struct Gadget *) IIntuition-&amp;gt;NewObject(IScroller-&amp;gt;SCROLLER_GetClass(),NULL,&lt;br /&gt;
      GA_ID,                      GAD_ID_Scroller,&lt;br /&gt;
      GA_Immediate,               TRUE,&lt;br /&gt;
      GA_RelVerify,               TRUE,&lt;br /&gt;
      SCROLLER_Top,               1,&lt;br /&gt;
      SCROLLER_Visible,           5,&lt;br /&gt;
      SCROLLER_Total,             105,&lt;br /&gt;
      SCROLLER_Orientation,       SCROLLER_HORIZONTAL,&lt;br /&gt;
      SCROLLER_Arrows,            TRUE,&lt;br /&gt;
      SCROLLER_Stretch,           TRUE,&lt;br /&gt;
      SCROLLER_ArrowDelta,        10,&lt;br /&gt;
      TAG_END);&lt;br /&gt;
&lt;br /&gt;
  gb_ChooserGad = (struct Gadget *) IIntuition-&amp;gt;NewObject(IChooser-&amp;gt;CHOOSER_GetClass(),NULL,&lt;br /&gt;
      GA_ID,                      GAD_ID_Chooser,&lt;br /&gt;
      GA_RelVerify,               TRUE,&lt;br /&gt;
      GA_Underscore,              &#039;#&#039;,&lt;br /&gt;
      CHOOSER_PopUp,              TRUE,&lt;br /&gt;
      CHOOSER_DropDown,           FALSE,&lt;br /&gt;
      CHOOSER_LabelArray,         gb_ChooserLabels,&lt;br /&gt;
      CHOOSER_Selected,           0,&lt;br /&gt;
      CHOOSER_MaxLabels,          10,&lt;br /&gt;
      TAG_END);&lt;br /&gt;
&lt;br /&gt;
  gb_Chooser2Gad = (struct Gadget *) IIntuition-&amp;gt;NewObject(IChooser-&amp;gt;CHOOSER_GetClass(),NULL,&lt;br /&gt;
      GA_ID,                      GAD_ID_Chooser2,&lt;br /&gt;
      GA_RelVerify,               TRUE,&lt;br /&gt;
      GA_Underscore,              &#039;#&#039;,&lt;br /&gt;
      CHOOSER_PopUp,              FALSE,&lt;br /&gt;
      CHOOSER_DropDown,           TRUE,&lt;br /&gt;
      CHOOSER_Title,              &amp;quot;Eintrâ°ge&amp;quot;,&lt;br /&gt;
      CHOOSER_LabelArray,         gb_Chooser2Labels,&lt;br /&gt;
      CHOOSER_Selected,           0,&lt;br /&gt;
      CHOOSER_MaxLabels,          10,&lt;br /&gt;
      TAG_END);&lt;br /&gt;
&lt;br /&gt;
  gb_Chooser3Gad = (struct Gadget *) IIntuition-&amp;gt;NewObject(IChooser-&amp;gt;CHOOSER_GetClass(),NULL,&lt;br /&gt;
      GA_ID,                      GAD_ID_Chooser3,&lt;br /&gt;
      GA_RelVerify,               TRUE,&lt;br /&gt;
      GA_Underscore,              &#039;#&#039;,&lt;br /&gt;
      CHOOSER_PopUp,              FALSE,&lt;br /&gt;
      CHOOSER_DropDown,           TRUE,&lt;br /&gt;
      CHOOSER_LabelArray,         gb_Chooser3Labels,&lt;br /&gt;
      CHOOSER_Selected,           0,&lt;br /&gt;
      CHOOSER_MaxLabels,          10,&lt;br /&gt;
      TAG_END);&lt;br /&gt;
&lt;br /&gt;
  gb_CheckboxGad = (struct Gadget *) IIntuition-&amp;gt;NewObject(ICheckBox-&amp;gt;CHECKBOX_GetClass(),NULL,&lt;br /&gt;
      GA_ID,                      GAD_ID_Checkbox,&lt;br /&gt;
      GA_Text,                    &amp;quot;Anwahl&amp;quot;,&lt;br /&gt;
      CHECKBOX_TextPlace,         PLACETEXT_RIGHT,&lt;br /&gt;
      CHECKBOX_Checked,           TRUE,&lt;br /&gt;
      TAG_END);&lt;br /&gt;
&lt;br /&gt;
  gb_RadioGad = (struct Gadget *) IIntuition-&amp;gt;NewObject(IRadioButton-&amp;gt;RADIOBUTTON_GetClass(),NULL,&lt;br /&gt;
      GA_ID,                      GAD_ID_Radio,&lt;br /&gt;
      GA_RelVerify,               TRUE,&lt;br /&gt;
      GA_Text,                    gb_RadioLabels,&lt;br /&gt;
      //RADIOBUTTON_LabelArray,     gb_RadioLabels,&lt;br /&gt;
      RADIOBUTTON_Selected,       2,&lt;br /&gt;
      RADIOBUTTON_LabelPlace,     PLACETEXT_RIGHT,&lt;br /&gt;
      RADIOBUTTON_Spacing,        4,&lt;br /&gt;
      TAG_END);&lt;br /&gt;
&lt;br /&gt;
  gb_ListbrowserGad = (struct Gadget *) IIntuition-&amp;gt;NewObject(IListBrowser-&amp;gt;LISTBROWSER_GetClass(),NULL,&lt;br /&gt;
      GA_ReadOnly,                FALSE,&lt;br /&gt;
      GA_ID,                      GAD_ID_Listbrowser,&lt;br /&gt;
      GA_RelVerify,               TRUE,&lt;br /&gt;
      LISTBROWSER_ColumnInfo,     &amp;amp;gb_ListbrowserColumn,&lt;br /&gt;
      LISTBROWSER_ColumnTitles,   TRUE,&lt;br /&gt;
      LISTBROWSER_Labels,         &amp;amp;gb_List,&lt;br /&gt;
      LISTBROWSER_VertSeparators, TRUE,&lt;br /&gt;
      LISTBROWSER_Spacing,        1,&lt;br /&gt;
      LISTBROWSER_ShowSelected,   TRUE,&lt;br /&gt;
      LISTBROWSER_AutoFit,        TRUE,&lt;br /&gt;
      LISTBROWSER_Editable,       FALSE,&lt;br /&gt;
      LISTBROWSER_MinVisible,     2,&lt;br /&gt;
      TAG_END);&lt;br /&gt;
&lt;br /&gt;
  gb_PaletteGad = (struct Gadget *) IIntuition-&amp;gt;NewObject(IPalette-&amp;gt;PALETTE_GetClass(),NULL,&lt;br /&gt;
      GA_ReadOnly,                FALSE,&lt;br /&gt;
      GA_ID,                      GAD_ID_Palette,&lt;br /&gt;
      GA_RelVerify,               TRUE,&lt;br /&gt;
      PALETTE_Colour,             1,&lt;br /&gt;
      PALETTE_ColourOffset,       0,&lt;br /&gt;
      PALETTE_NumColours,         8,&lt;br /&gt;
      TAG_END);&lt;br /&gt;
&lt;br /&gt;
  gb_FileGad = (struct Gadget *) IIntuition-&amp;gt;NewObject(IGetFile-&amp;gt;GETFILE_GetClass(),NULL,&lt;br /&gt;
      GA_ID,                      GAD_ID_File,&lt;br /&gt;
      GA_RelVerify,               TRUE,&lt;br /&gt;
      GA_TabCycle,                TRUE,&lt;br /&gt;
      GETFILE_TitleText,          &amp;quot;&amp;quot;Select File ...&amp;quot;,&lt;br /&gt;
      GETFILE_Pattern,            &amp;quot;#?&amp;quot;,&lt;br /&gt;
      GETFILE_DoSaveMode,         FALSE,&lt;br /&gt;
      GETFILE_RejectIcons,        TRUE,&lt;br /&gt;
      GETFILE_ReadOnly,           TRUE,&lt;br /&gt;
      GETFILE_DrawersOnly,        FALSE,&lt;br /&gt;
      TAG_END);&lt;br /&gt;
&lt;br /&gt;
  gb_FontGad = (struct Gadget *) IIntuition-&amp;gt;NewObject(IGetFont-&amp;gt;GETFONT_GetClass(),NULL,&lt;br /&gt;
      GA_ID,                      GAD_ID_Font,&lt;br /&gt;
      GA_RelVerify,               TRUE,&lt;br /&gt;
      GETFONT_TitleText,          &amp;quot;Select Font ...&amp;quot;,&lt;br /&gt;
      GETFONT_MinHeight,          6,&lt;br /&gt;
      GETFONT_MaxHeight,          30,&lt;br /&gt;
      TAG_END);&lt;br /&gt;
&lt;br /&gt;
  gb_ScreenmodeGad = (struct Gadget *) IIntuition-&amp;gt;NewObject(IGetScreenMode-&amp;gt;GETSCREENMODE_GetClass(),NULL,&lt;br /&gt;
      GA_ID,                      GAD_ID_Screenmode,&lt;br /&gt;
      GA_RelVerify,               TRUE,&lt;br /&gt;
      GETSCREENMODE_TitleText,    &amp;quot;Select Screen Mode ...&amp;quot;,&lt;br /&gt;
      GETSCREENMODE_MinDepth,     2,&lt;br /&gt;
      GETSCREENMODE_MaxDepth,     8,&lt;br /&gt;
      TAG_END);&lt;br /&gt;
&lt;br /&gt;
  gb_ColorGad = (struct Gadget *) IIntuition-&amp;gt;NewObject(IGetColor-&amp;gt;GETCOLOR_GetClass(),NULL,&lt;br /&gt;
      GA_ID,                      GAD_ID_Color,&lt;br /&gt;
      GA_RelVerify,               TRUE,&lt;br /&gt;
      GETCOLOR_TitleText,         &amp;quot;Choose Color ...&amp;quot;,&lt;br /&gt;
      GETCOLOR_Screen,            gb_Scr,&lt;br /&gt;
      GETCOLOR_Color,             0x00aaccee,&lt;br /&gt;
      GETCOLOR_ColorWheel,        TRUE,&lt;br /&gt;
      GETCOLOR_RGBSliders,        TRUE,&lt;br /&gt;
      GETCOLOR_ShowRGB,           TRUE,&lt;br /&gt;
      TAG_END);&lt;br /&gt;
&lt;br /&gt;
  gb_FuelgaugeGad = (struct Gadget *) IIntuition-&amp;gt;NewObject(IFuelGauge-&amp;gt;FUELGAUGE_GetClass(),NULL,&lt;br /&gt;
      GA_ReadOnly,                FALSE,&lt;br /&gt;
      GA_ID,                      GAD_ID_Fuelgauge,&lt;br /&gt;
      GA_RelVerify,               TRUE,&lt;br /&gt;
      FUELGAUGE_Min,              0,&lt;br /&gt;
      FUELGAUGE_Max,              100,&lt;br /&gt;
      FUELGAUGE_Level,            10,&lt;br /&gt;
      FUELGAUGE_Orientation,      FGORIENT_HORIZ,&lt;br /&gt;
      FUELGAUGE_Percent,          TRUE,&lt;br /&gt;
      FUELGAUGE_Ticks,            10,&lt;br /&gt;
      FUELGAUGE_ShortTicks,       10,&lt;br /&gt;
      FUELGAUGE_Justification,    FGJ_CENTER,&lt;br /&gt;
      TAG_END);&lt;br /&gt;
&lt;br /&gt;
  gb_GradientsliderGad = (struct Gadget *) IIntuition-&amp;gt;NewObject(NULL,&amp;quot;gradientslider.gadget&amp;quot;,&lt;br /&gt;
      GA_ID,                      GAD_ID_Gradientslider,&lt;br /&gt;
      GA_RelVerify,               TRUE,&lt;br /&gt;
      GA_TabCycle,                TRUE,&lt;br /&gt;
      GRAD_PenArray,              gb_GradientArray,&lt;br /&gt;
      PGA_Freedom,                LORIENT_VERT,&lt;br /&gt;
      TAG_END);&lt;br /&gt;
&lt;br /&gt;
  /* set Color Wheel to this RGB value */&lt;br /&gt;
  struct ColorWheelRGB rgbval = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF };&lt;br /&gt;
&lt;br /&gt;
  gb_ColorwheelGad = (struct Gadget *) IIntuition-&amp;gt;NewObject(NULL,&amp;quot;colorwheel.gadget&amp;quot;,&lt;br /&gt;
      GA_ID,                      GAD_ID_Colorwheel,&lt;br /&gt;
      GA_RelVerify,               TRUE,&lt;br /&gt;
      GA_TabCycle,                TRUE,&lt;br /&gt;
      WHEEL_Screen,               gb_Scr,&lt;br /&gt;
      //WHEEL_GradientSlider,       gb_GradientsliderGad,&lt;br /&gt;
      WHEEL_BevelBox,             FALSE,&lt;br /&gt;
      WHEEL_RGB,                  rgbval,&lt;br /&gt;
      TAG_END);&lt;br /&gt;
&lt;br /&gt;
  gb_TexteditorGad = (struct Gadget *) IIntuition-&amp;gt;NewObject(ITextEditor-&amp;gt;TEXTEDITOR_GetClass(),NULL,&lt;br /&gt;
      GA_ID,                      GAD_ID_Texteditor,&lt;br /&gt;
      GA_RelVerify,               TRUE,&lt;br /&gt;
      GA_TabCycle,                TRUE,&lt;br /&gt;
      GA_TEXTEDITOR_FixedFont,    FALSE,&lt;br /&gt;
      TAG_END);&lt;br /&gt;
&lt;br /&gt;
  gb_DatebrowserGad = (struct Gadget *) IIntuition-&amp;gt;NewObject(IDateBrowser-&amp;gt;DATEBROWSER_GetClass(),NULL,&lt;br /&gt;
      GA_ID,                      GAD_ID_Datebrowser,&lt;br /&gt;
      GA_RelVerify,               TRUE,&lt;br /&gt;
      GA_TabCycle,                TRUE,&lt;br /&gt;
      DATEBROWSER_Day,            27,&lt;br /&gt;
      DATEBROWSER_Month,          10,&lt;br /&gt;
      DATEBROWSER_Year,           2007,&lt;br /&gt;
      DATEBROWSER_ShowTitle,      TRUE,&lt;br /&gt;
      DATEBROWSER_ShowWeek,       TRUE,&lt;br /&gt;
      DATEBROWSER_MultiSelect,    FALSE,&lt;br /&gt;
      TAG_END);&lt;br /&gt;
&lt;br /&gt;
  gb_SpaceGad = (struct Gadget *) IIntuition-&amp;gt;NewObject(ISpace-&amp;gt;SPACE_GetClass(),NULL,&lt;br /&gt;
      GA_ID,                      GAD_ID_Space,&lt;br /&gt;
      GA_RelVerify,               TRUE,  /* send Gadget Up */&lt;br /&gt;
      GA_Immediate,               TRUE,  /* send Gadget Down */&lt;br /&gt;
      GA_ReadOnly,                FALSE,&lt;br /&gt;
      SPACE_Transparent,          TRUE,  /* Background not deleted automatically */&lt;br /&gt;
      SPACE_MinWidth,             10,&lt;br /&gt;
      SPACE_MinHeight,            10,&lt;br /&gt;
      SPACE_BevelStyle,           BVS_DROPBOX,&lt;br /&gt;
      SPACE_RenderHook,           &amp;amp;gb_RenderHook,&lt;br /&gt;
      ICA_TARGET,                 ICTARGET_IDCMP,  /* send a Message to the Program */&lt;br /&gt;
      TAG_END);&lt;br /&gt;
&lt;br /&gt;
  gb_PageGad = (struct Gadget *) IIntuition-&amp;gt;NewObject(ILayout-&amp;gt;PAGE_GetClass(),NULL,&lt;br /&gt;
      GA_ID,                      GAD_ID_Page,&lt;br /&gt;
      LAYOUT_Orientation,         LAYOUT_VERTICAL,&lt;br /&gt;
      LAYOUT_FixedHoriz,          FALSE,&lt;br /&gt;
      LAYOUT_FixedVert,           FALSE,&lt;br /&gt;
      LAYOUT_SpaceInner,          TRUE,&lt;br /&gt;
&lt;br /&gt;
      PAGE_Add, IIntuition-&amp;gt;NewObject(ILayout-&amp;gt;LAYOUT_GetClass(),NULL,&lt;br /&gt;
          LAYOUT_AddChild, IIntuition-&amp;gt;NewObject(IButton-&amp;gt;BUTTON_GetClass(),NULL,&lt;br /&gt;
              BUTTON_BevelStyle, BVS_NONE, BUTTON_Transparent, TRUE, GA_Text, &amp;quot;Amiga 1000&amp;quot;, GA_ReadOnly, TRUE, TAG_END),&lt;br /&gt;
              TAG_END),&lt;br /&gt;
      PAGE_Add, IIntuition-&amp;gt;NewObject(ILayout-&amp;gt;LAYOUT_GetClass(),NULL,&lt;br /&gt;
          LAYOUT_AddChild, IIntuition-&amp;gt;NewObject(IButton-&amp;gt;BUTTON_GetClass(),NULL,&lt;br /&gt;
              BUTTON_BevelStyle, BVS_NONE, BUTTON_Transparent, TRUE, GA_Text, &amp;quot;Amiga 1200&amp;quot;, GA_ReadOnly, TRUE, TAG_END),&lt;br /&gt;
              TAG_END),&lt;br /&gt;
      PAGE_Add, IIntuition-&amp;gt;NewObject(ILayout-&amp;gt;LAYOUT_GetClass(),NULL,&lt;br /&gt;
          LAYOUT_AddChild, IIntuition-&amp;gt;NewObject(IButton-&amp;gt;BUTTON_GetClass(),NULL,&lt;br /&gt;
              BUTTON_BevelStyle, BVS_NONE, BUTTON_Transparent, TRUE, GA_Text, &amp;quot;AmigaOne&amp;quot;, GA_ReadOnly, TRUE, TAG_END),&lt;br /&gt;
              TAG_END),&lt;br /&gt;
      TAG_END);&lt;br /&gt;
&lt;br /&gt;
  gb_ClicktabGad = (struct Gadget *) IIntuition-&amp;gt;NewObject(IClickTab-&amp;gt;CLICKTAB_GetClass(),NULL,&lt;br /&gt;
      GA_ID,                      GAD_ID_Clicktab,&lt;br /&gt;
      GA_Text,                    &amp;amp;gb_ClicktabLabels,&lt;br /&gt;
      GA_RelVerify,               TRUE,&lt;br /&gt;
      CLICKTAB_PageGroup,         gb_PageGad,&lt;br /&gt;
      TAG_END);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  gb_LabelImg = (struct Image *) IIntuition-&amp;gt;NewObject(ILabel-&amp;gt;LABEL_GetClass(),NULL,&lt;br /&gt;
      LABEL_Text,                 &amp;quot;Beschriftung&amp;quot;,&lt;br /&gt;
      //LABEL_SoftStyle,            FSF_BOLD,&lt;br /&gt;
      //LABEL_Justification,        LJ_LEFT,&lt;br /&gt;
      TAG_END);&lt;br /&gt;
&lt;br /&gt;
  gb_BevelImg = (struct Image *) IIntuition-&amp;gt;NewObject(IBevel-&amp;gt;BEVEL_GetClass(),NULL,&lt;br /&gt;
      BEVEL_Style,                BVS_BOX,&lt;br /&gt;
      TAG_END);&lt;br /&gt;
&lt;br /&gt;
  gb_BitmapImg = (struct Image *) IIntuition-&amp;gt;NewObject(IBitMap-&amp;gt;BITMAP_GetClass(),NULL,&lt;br /&gt;
      BITMAP_Screen,              gb_Scr,&lt;br /&gt;
      BITMAP_Masking,             FALSE,&lt;br /&gt;
      BITMAP_SourceFile,          &amp;quot;amiga1000-normal.iff&amp;quot;,&lt;br /&gt;
      BITMAP_SelectSourceFile,    &amp;quot;amiga1000-selected.iff&amp;quot;,&lt;br /&gt;
      BITMAP_DisabledSourceFile,  &amp;quot;amiga1000-disabled.iff&amp;quot;,&lt;br /&gt;
      IA_SupportsDisable,         TRUE,&lt;br /&gt;
      TAG_END);&lt;br /&gt;
&lt;br /&gt;
  gb_BitmapSImg = (struct Image *) IIntuition-&amp;gt;NewObject(IBitMap-&amp;gt;BITMAP_GetClass(),NULL,&lt;br /&gt;
      BITMAP_Screen,              gb_Scr,&lt;br /&gt;
      BITMAP_Masking,             FALSE,&lt;br /&gt;
      BITMAP_SourceFile,          &amp;quot;amiga1000-selected.iff&amp;quot;,&lt;br /&gt;
      IA_SupportsDisable,         TRUE,&lt;br /&gt;
      TAG_END);&lt;br /&gt;
&lt;br /&gt;
  gb_BitmapDImg = (struct Image *) IIntuition-&amp;gt;NewObject(IBitMap-&amp;gt;BITMAP_GetClass(),NULL,&lt;br /&gt;
      BITMAP_Screen,              gb_Scr,&lt;br /&gt;
      BITMAP_Masking,             FALSE,&lt;br /&gt;
      BITMAP_SourceFile,          &amp;quot;amiga1000-disabled.iff&amp;quot;,&lt;br /&gt;
      TAG_END);&lt;br /&gt;
&lt;br /&gt;
  gb_DrawlistImg = (struct Image *) IIntuition-&amp;gt;NewObject(IDrawList-&amp;gt;DRAWLIST_GetClass(),NULL,&lt;br /&gt;
      DRAWLIST_Directives,        gb_DrawList,&lt;br /&gt;
      TAG_END);&lt;br /&gt;
&lt;br /&gt;
  gb_FillerImg = (struct Image *) IIntuition-&amp;gt;NewObject(IFiller-&amp;gt;FILLER_GetClass(),NULL,&lt;br /&gt;
      FILLER_Screen,              gb_Scr,&lt;br /&gt;
      FILLER_BackgroundColor,     0xffaaaaaa,&lt;br /&gt;
      FILLER_ImageFilename,       &amp;quot;amigaball.iff&amp;quot;,&lt;br /&gt;
      FILLER_ImageMode,           FILLER_MODE_TILED,&lt;br /&gt;
      IA_Width,                   30,&lt;br /&gt;
      IA_Height,                  30,&lt;br /&gt;
      TAG_END);&lt;br /&gt;
&lt;br /&gt;
  gb_PenmapImg = (struct Image *) IIntuition-&amp;gt;NewObject(IPenMap-&amp;gt;PENMAP_GetClass(),NULL,&lt;br /&gt;
      PENMAP_RenderData,          happy_data,&lt;br /&gt;
      PENMAP_Palette,             image_object_palette,&lt;br /&gt;
      PENMAP_Screen,              gb_Scr,&lt;br /&gt;
      PENMAP_Transparent,         TRUE,&lt;br /&gt;
      TAG_END);&lt;br /&gt;
&lt;br /&gt;
  for(i=1; i&amp;lt;=26; i++)&lt;br /&gt;
  {&lt;br /&gt;
    /* 13-17 and 19 do not exist */&lt;br /&gt;
    gb_GlyphImg[i] = (struct Image *) IIntuition-&amp;gt;NewObject(IGlyph-&amp;gt;GLYPH_GetClass(),NULL,&lt;br /&gt;
        GLYPH_Glyph,                i, /*GLYPH_xxx */&lt;br /&gt;
        IA_Width,                   20,&lt;br /&gt;
        IA_Height,                  20,&lt;br /&gt;
        TAG_END);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  /* create the single pages of the Drag Bar */&lt;br /&gt;
  gb_Page1Layout = (struct Gadget *) IIntuition-&amp;gt;NewObject(ILayout-&amp;gt;LAYOUT_GetClass(),NULL,&lt;br /&gt;
      LAYOUT_Orientation,   LAYOUT_ORIENT_VERT,&lt;br /&gt;
      LAYOUT_SpaceOuter,    TRUE,&lt;br /&gt;
      LAYOUT_SpaceInner,    TRUE,&lt;br /&gt;
      LAYOUT_BevelStyle,    BVS_GROUP,&lt;br /&gt;
      LAYOUT_Label,         &amp;quot;Grundtypen&amp;quot;,&lt;br /&gt;
      LAYOUT_LabelPlace,    BVJ_TOP_CENTER,&lt;br /&gt;
&lt;br /&gt;
      LAYOUT_AddChild,      gb_ButtonVGad,&lt;br /&gt;
      CHILD_WeightedHeight, 80,&lt;br /&gt;
      LAYOUT_AddChild,      gb_ButtonGad,&lt;br /&gt;
      CHILD_WeightedHeight, 10,&lt;br /&gt;
      LAYOUT_AddChild,      gb_StringGad,&lt;br /&gt;
      LAYOUT_AddChild,      gb_IntegerGad,&lt;br /&gt;
      LAYOUT_AddChild,      gb_SliderGad,&lt;br /&gt;
      CHILD_WeightedHeight, 10,&lt;br /&gt;
      LAYOUT_AddChild,      gb_ScrollerGad,&lt;br /&gt;
      TAG_END);&lt;br /&gt;
&lt;br /&gt;
  gb_Page2Layout = (struct Gadget *) IIntuition-&amp;gt;NewObject(ILayout-&amp;gt;LAYOUT_GetClass(),NULL,&lt;br /&gt;
      LAYOUT_Orientation,   LAYOUT_ORIENT_VERT,&lt;br /&gt;
      LAYOUT_SpaceOuter,    TRUE,&lt;br /&gt;
      LAYOUT_SpaceInner,    TRUE,&lt;br /&gt;
      LAYOUT_BevelStyle,    BVS_GROUP,&lt;br /&gt;
      LAYOUT_Label,         &amp;quot;Auswahllisten&amp;quot;,&lt;br /&gt;
      LAYOUT_LabelPlace,    BVJ_TOP_CENTER,&lt;br /&gt;
&lt;br /&gt;
      LAYOUT_AddChild,      IIntuition-&amp;gt;NewObject(ILayout-&amp;gt;LAYOUT_GetClass(),NULL,&lt;br /&gt;
          LAYOUT_Orientation,   LAYOUT_ORIENT_HORIZ,&lt;br /&gt;
          LAYOUT_AddChild,      gb_ChooserGad,&lt;br /&gt;
          LAYOUT_AddChild,      gb_Chooser2Gad,&lt;br /&gt;
          LAYOUT_AddChild,      gb_Chooser3Gad,&lt;br /&gt;
          TAG_END),&lt;br /&gt;
      CHILD_WeightedHeight, 0,&lt;br /&gt;
&lt;br /&gt;
      LAYOUT_AddChild,      gb_CheckboxGad,&lt;br /&gt;
      CHILD_WeightedHeight, 0,&lt;br /&gt;
      LAYOUT_AddChild,      gb_RadioGad,&lt;br /&gt;
      CHILD_WeightedHeight, 0,&lt;br /&gt;
      LAYOUT_AddChild,      gb_ListbrowserGad,&lt;br /&gt;
      CHILD_WeightedHeight, 90,&lt;br /&gt;
      LAYOUT_AddChild,      gb_PaletteGad,&lt;br /&gt;
      CHILD_WeightedHeight, 10,&lt;br /&gt;
      TAG_END);&lt;br /&gt;
&lt;br /&gt;
  gb_Page3Layout = (struct Gadget *) IIntuition-&amp;gt;NewObject(ILayout-&amp;gt;LAYOUT_GetClass(),NULL,&lt;br /&gt;
      LAYOUT_Orientation,   LAYOUT_ORIENT_VERT,&lt;br /&gt;
      LAYOUT_SpaceOuter,    TRUE,&lt;br /&gt;
      LAYOUT_SpaceInner,    TRUE,&lt;br /&gt;
      LAYOUT_BevelStyle,    BVS_GROUP,&lt;br /&gt;
      LAYOUT_Label,         &amp;quot;ASL-Auswahl&amp;quot;,&lt;br /&gt;
      LAYOUT_LabelPlace,    BVJ_TOP_CENTER,&lt;br /&gt;
&lt;br /&gt;
      LAYOUT_AddChild,      gb_FileGad,&lt;br /&gt;
      CHILD_WeightedHeight, 0,&lt;br /&gt;
      LAYOUT_AddChild,      gb_FontGad,&lt;br /&gt;
      CHILD_WeightedHeight, 0,&lt;br /&gt;
      LAYOUT_AddChild,      gb_ScreenmodeGad,&lt;br /&gt;
      CHILD_WeightedHeight, 0,&lt;br /&gt;
      LAYOUT_AddChild,      gb_ColorGad,&lt;br /&gt;
      CHILD_WeightedHeight, 0,&lt;br /&gt;
      TAG_END);&lt;br /&gt;
&lt;br /&gt;
  gb_Page4Layout = (struct Gadget *) IIntuition-&amp;gt;NewObject(ILayout-&amp;gt;LAYOUT_GetClass(),NULL,&lt;br /&gt;
      LAYOUT_Orientation,   LAYOUT_ORIENT_VERT,&lt;br /&gt;
      LAYOUT_SpaceOuter,    TRUE,&lt;br /&gt;
      LAYOUT_SpaceInner,    TRUE,&lt;br /&gt;
      LAYOUT_BevelStyle,    BVS_GROUP,&lt;br /&gt;
      LAYOUT_Label,         &amp;quot;Sonstige Typen&amp;quot;,&lt;br /&gt;
      LAYOUT_LabelPlace,    BVJ_TOP_CENTER,&lt;br /&gt;
&lt;br /&gt;
      LAYOUT_AddChild,      gb_FuelgaugeGad,&lt;br /&gt;
      CHILD_WeightedHeight, 10,&lt;br /&gt;
&lt;br /&gt;
      LAYOUT_AddChild,      IIntuition-&amp;gt;NewObject(ILayout-&amp;gt;LAYOUT_GetClass(),NULL,&lt;br /&gt;
          LAYOUT_Orientation,   LAYOUT_ORIENT_HORIZ,&lt;br /&gt;
          LAYOUT_AddChild,      gb_ColorwheelGad,&lt;br /&gt;
          //CHILD_WeightedWidth,  0,&lt;br /&gt;
          //CHILD_WeightedHeight, 0,&lt;br /&gt;
          LAYOUT_AddChild,      gb_GradientsliderGad,&lt;br /&gt;
          LAYOUT_AddChild,      IIntuition-&amp;gt;NewObject(ISpace-&amp;gt;SPACE_GetClass(),NULL,&lt;br /&gt;
              SPACE_Transparent,          FALSE,&lt;br /&gt;
              SPACE_MinWidth,             10,&lt;br /&gt;
              SPACE_MinHeight,            10,&lt;br /&gt;
              TAG_END),&lt;br /&gt;
          TAG_END),&lt;br /&gt;
      CHILD_WeightedHeight, 70,&lt;br /&gt;
&lt;br /&gt;
      LAYOUT_AddChild,      gb_TexteditorGad,&lt;br /&gt;
      CHILD_WeightedHeight, 10,&lt;br /&gt;
      LAYOUT_AddChild,      gb_DatebrowserGad,&lt;br /&gt;
      CHILD_WeightedHeight, 10,&lt;br /&gt;
      TAG_END);&lt;br /&gt;
&lt;br /&gt;
  gb_Page5Layout = (struct Gadget *) IIntuition-&amp;gt;NewObject(ILayout-&amp;gt;LAYOUT_GetClass(),NULL,&lt;br /&gt;
      LAYOUT_Orientation,   LAYOUT_ORIENT_VERT,&lt;br /&gt;
      LAYOUT_SpaceOuter,    TRUE,&lt;br /&gt;
      LAYOUT_SpaceInner,    TRUE,&lt;br /&gt;
      LAYOUT_BevelStyle,    BVS_GROUP,&lt;br /&gt;
      LAYOUT_Label,         &amp;quot;Seitengestalltung&amp;quot;,&lt;br /&gt;
      LAYOUT_LabelPlace,    BVJ_TOP_CENTER,&lt;br /&gt;
&lt;br /&gt;
      LAYOUT_AddChild,      gb_SpaceGad,&lt;br /&gt;
      LAYOUT_AddChild,      gb_ClicktabGad,&lt;br /&gt;
      TAG_END);&lt;br /&gt;
&lt;br /&gt;
  gb_Page6Layout = (struct Gadget *) IIntuition-&amp;gt;NewObject(ILayout-&amp;gt;LAYOUT_GetClass(),NULL,&lt;br /&gt;
      LAYOUT_Orientation,   LAYOUT_ORIENT_VERT,&lt;br /&gt;
      LAYOUT_SpaceOuter,    TRUE,&lt;br /&gt;
      LAYOUT_SpaceInner,    TRUE,&lt;br /&gt;
      LAYOUT_BevelStyle,    BVS_GROUP,&lt;br /&gt;
      LAYOUT_Label,         &amp;quot;Images&amp;quot;,&lt;br /&gt;
      LAYOUT_LabelPlace,    BVJ_TOP_CENTER,&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
      LAYOUT_AddImage,      gb_LabelImg,&lt;br /&gt;
&lt;br /&gt;
      LAYOUT_AddImage,      gb_BevelImg,&lt;br /&gt;
      CHILD_MinHeight,      10,&lt;br /&gt;
&lt;br /&gt;
      LAYOUT_AddChild,      IIntuition-&amp;gt;NewObject(ILayout-&amp;gt;LAYOUT_GetClass(),NULL,&lt;br /&gt;
          LAYOUT_Orientation,   LAYOUT_ORIENT_HORIZ,&lt;br /&gt;
          LAYOUT_AddImage,      gb_BitmapImg,&lt;br /&gt;
          LAYOUT_AddImage,      gb_BitmapSImg,&lt;br /&gt;
          LAYOUT_AddImage,      gb_BitmapDImg,&lt;br /&gt;
          TAG_END),&lt;br /&gt;
      CHILD_WeightedHeight, 0,&lt;br /&gt;
&lt;br /&gt;
      LAYOUT_AddImage,      gb_DrawlistImg,&lt;br /&gt;
      CHILD_MinWidth,       30,&lt;br /&gt;
      CHILD_MinHeight,      30,&lt;br /&gt;
      CHILD_WeightedWidth,  0,&lt;br /&gt;
      CHILD_WeightedHeight, 0,&lt;br /&gt;
&lt;br /&gt;
      LAYOUT_AddImage,      gb_FillerImg,&lt;br /&gt;
      CHILD_MinWidth,       30,&lt;br /&gt;
      CHILD_MinHeight,      30,&lt;br /&gt;
      CHILD_MaxWidth,       200,&lt;br /&gt;
      CHILD_MaxHeight,      60,&lt;br /&gt;
&lt;br /&gt;
      LAYOUT_AddImage,      gb_PenmapImg,&lt;br /&gt;
      CHILD_WeightedWidth,  0,&lt;br /&gt;
      CHILD_WeightedHeight, 0,&lt;br /&gt;
&lt;br /&gt;
      LAYOUT_AddChild,      IIntuition-&amp;gt;NewObject(ILayout-&amp;gt;LAYOUT_GetClass(),NULL,&lt;br /&gt;
          LAYOUT_Orientation,   LAYOUT_ORIENT_HORIZ,&lt;br /&gt;
&lt;br /&gt;
          LAYOUT_AddImage,      gb_GlyphImg[ 1],&lt;br /&gt;
      CHILD_MinWidth,       20,&lt;br /&gt;
          LAYOUT_AddImage,      gb_GlyphImg[ 2],&lt;br /&gt;
      CHILD_MinWidth,       20,&lt;br /&gt;
          LAYOUT_AddImage,      gb_GlyphImg[ 3],&lt;br /&gt;
      CHILD_MinWidth,       20,&lt;br /&gt;
          LAYOUT_AddImage,      gb_GlyphImg[ 4],&lt;br /&gt;
      CHILD_MinWidth,       20,&lt;br /&gt;
          LAYOUT_AddImage,      gb_GlyphImg[ 5],&lt;br /&gt;
      CHILD_MinWidth,       20,&lt;br /&gt;
          LAYOUT_AddImage,      gb_GlyphImg[ 6],&lt;br /&gt;
      CHILD_MinWidth,       20,&lt;br /&gt;
          LAYOUT_AddImage,      gb_GlyphImg[ 7],&lt;br /&gt;
      CHILD_MinWidth,       20,&lt;br /&gt;
          LAYOUT_AddImage,      gb_GlyphImg[ 8],&lt;br /&gt;
      CHILD_MinWidth,       20,&lt;br /&gt;
          LAYOUT_AddImage,      gb_GlyphImg[ 9],&lt;br /&gt;
      CHILD_MinWidth,       20,&lt;br /&gt;
          LAYOUT_AddImage,      gb_GlyphImg[10],&lt;br /&gt;
      CHILD_MinWidth,       20,&lt;br /&gt;
          LAYOUT_AddImage,      gb_GlyphImg[11],&lt;br /&gt;
      CHILD_MinWidth,       20,&lt;br /&gt;
          LAYOUT_AddImage,      gb_GlyphImg[12],&lt;br /&gt;
      CHILD_MinWidth,       20,&lt;br /&gt;
          LAYOUT_AddImage,      gb_GlyphImg[18],&lt;br /&gt;
      CHILD_MinWidth,       20,&lt;br /&gt;
          LAYOUT_AddImage,      gb_GlyphImg[20],&lt;br /&gt;
      CHILD_MinWidth,       20,&lt;br /&gt;
          LAYOUT_AddImage,      gb_GlyphImg[21],&lt;br /&gt;
      CHILD_MinWidth,       20,&lt;br /&gt;
          LAYOUT_AddImage,      gb_GlyphImg[22],&lt;br /&gt;
      CHILD_MinWidth,       20,&lt;br /&gt;
          LAYOUT_AddImage,      gb_GlyphImg[23],&lt;br /&gt;
      CHILD_MinWidth,       20,&lt;br /&gt;
          LAYOUT_AddImage,      gb_GlyphImg[24],&lt;br /&gt;
      CHILD_MinWidth,       20,&lt;br /&gt;
          LAYOUT_AddImage,      gb_GlyphImg[25],&lt;br /&gt;
      CHILD_MinWidth,       20,&lt;br /&gt;
          LAYOUT_AddImage,      gb_GlyphImg[26],&lt;br /&gt;
      CHILD_MinWidth,       20,&lt;br /&gt;
          TAG_END),&lt;br /&gt;
      CHILD_MinHeight,      20,&lt;br /&gt;
      CHILD_WeightedHeight, 10,&lt;br /&gt;
&lt;br /&gt;
      TAG_END);&lt;br /&gt;
&lt;br /&gt;
  gb_PagesLayout = (struct Gadget *) IIntuition-&amp;gt;NewObject(ILayout-&amp;gt;PAGE_GetClass(),NULL,&lt;br /&gt;
      GA_ID,                GAD_ID_Pages,&lt;br /&gt;
      LAYOUT_Orientation,   LAYOUT_VERTICAL,&lt;br /&gt;
      LAYOUT_FixedHoriz,    FALSE,&lt;br /&gt;
      LAYOUT_FixedVert,     FALSE,&lt;br /&gt;
      LAYOUT_SpaceInner,    TRUE,&lt;br /&gt;
&lt;br /&gt;
      PAGE_Add,             gb_Page1Layout,&lt;br /&gt;
      PAGE_Add,             gb_Page2Layout,&lt;br /&gt;
      PAGE_Add,             gb_Page3Layout,&lt;br /&gt;
      PAGE_Add,             gb_Page4Layout,&lt;br /&gt;
      PAGE_Add,             gb_Page5Layout,&lt;br /&gt;
      PAGE_Add,             gb_Page6Layout,&lt;br /&gt;
&lt;br /&gt;
      TAG_END);&lt;br /&gt;
&lt;br /&gt;
  gb_PagesClicktab = (struct Gadget *) IIntuition-&amp;gt;NewObject(IClickTab-&amp;gt;CLICKTAB_GetClass(),NULL,&lt;br /&gt;
      GA_ID,                GAD_ID_PagesClicktab,&lt;br /&gt;
      GA_Text,              &amp;amp;gb_PagesLabels,&lt;br /&gt;
      CLICKTAB_PageGroup,   gb_PagesLayout,&lt;br /&gt;
      TAG_END);&lt;br /&gt;
&lt;br /&gt;
  IIntuition-&amp;gt;UnlockPubScreen(NULL,gb_Scr);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  /* create Layout Object */&lt;br /&gt;
  gb_MainLayout = (struct Gadget *) IIntuition-&amp;gt;NewObject(ILayout-&amp;gt;LAYOUT_GetClass(),NULL,&lt;br /&gt;
    LAYOUT_Orientation,  LAYOUT_ORIENT_VERT,&lt;br /&gt;
    LAYOUT_SpaceOuter,   TRUE,&lt;br /&gt;
    LAYOUT_SpaceInner,   TRUE,&lt;br /&gt;
&lt;br /&gt;
    LAYOUT_AddChild,     gb_PagesClicktab,&lt;br /&gt;
&lt;br /&gt;
    TAG_END);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  if(gb_MainLayout)&lt;br /&gt;
  {&lt;br /&gt;
&lt;br /&gt;
    /* create the Window Object */&lt;br /&gt;
    if((gb_WindowObj = (Object *) IIntuition-&amp;gt;NewObject(IWindow-&amp;gt;WINDOW_GetClass(),NULL,&lt;br /&gt;
      WA_IDCMP,             IDCMP_GADGETUP | IDCMP_GADGETDOWN |&lt;br /&gt;
                            IDCMP_MOUSEMOVE |&lt;br /&gt;
                            IDCMP_VANILLAKEY | IDCMP_RAWKEY |&lt;br /&gt;
                            IDCMP_CLOSEWINDOW,&lt;br /&gt;
      WA_SizeGadget,        TRUE,&lt;br /&gt;
      WA_DepthGadget,       TRUE,&lt;br /&gt;
      WA_DragBar,           TRUE,&lt;br /&gt;
      WA_Activate,          TRUE,&lt;br /&gt;
      WA_Title,             &amp;quot;All ReAction Gadgets&amp;quot;,&lt;br /&gt;
      WA_InnerWidth,        100,&lt;br /&gt;
      WA_InnerHeight,       100,&lt;br /&gt;
      WA_AutoAdjust,        TRUE,&lt;br /&gt;
      WA_CloseGadget,       TRUE,&lt;br /&gt;
      WA_RMBTrap,           TRUE,&lt;br /&gt;
      WINDOW_ParentGroup,   gb_MainLayout,&lt;br /&gt;
      WINDOW_IDCMPHook,     &amp;amp;gb_IDCMPHook,&lt;br /&gt;
      WINDOW_IDCMPHookBits, IDCMP_IDCMPUPDATE | IDCMP_GADGETDOWN,&lt;br /&gt;
      TAG_END)))&lt;br /&gt;
    {&lt;br /&gt;
      /* everything created correctly */&lt;br /&gt;
&lt;br /&gt;
      /* the Window can be shown now */&lt;br /&gt;
      gb_Win = RA_OpenWindow(gb_WindowObj);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return gb_WindowObj ? TRUE : FALSE;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/******************************************************************************/&lt;br /&gt;
&lt;br /&gt;
void DestroyAll()&lt;br /&gt;
{&lt;br /&gt;
  /* close Window and release included Objects */&lt;br /&gt;
  RA_CloseWindow(gb_WindowObj);&lt;br /&gt;
  IIntuition-&amp;gt;DisposeObject(gb_WindowObj);&lt;br /&gt;
&lt;br /&gt;
  /* release Listview entries */&lt;br /&gt;
  FreigebenList();&lt;br /&gt;
&lt;br /&gt;
  /* release the reserved pens */&lt;br /&gt;
  struct ColorMap *cm = (gb_Scr ? gb_Scr-&amp;gt;ViewPort.ColorMap : NULL);&lt;br /&gt;
&lt;br /&gt;
  if((WORD)gb_GradientArray[0] != ~0) IGraphics-&amp;gt;ReleasePen(cm,gb_GradientArray[0]);&lt;br /&gt;
  if((WORD)gb_GradientArray[1] != ~0) IGraphics-&amp;gt;ReleasePen(cm,gb_GradientArray[1]);&lt;br /&gt;
  if((WORD)gb_GradientArray[2] != ~0) IGraphics-&amp;gt;ReleasePen(cm,gb_GradientArray[2]);&lt;br /&gt;
  if((WORD)gb_GradientArray[3] != ~0) IGraphics-&amp;gt;ReleasePen(cm,gb_GradientArray[3]);&lt;br /&gt;
  if((WORD)gb_GradientArray[4] != ~0) IGraphics-&amp;gt;ReleasePen(cm,gb_GradientArray[4]);&lt;br /&gt;
  if((WORD)gb_GradientArray[5] != ~0) IGraphics-&amp;gt;ReleasePen(cm,gb_GradientArray[5]);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/******************************************************************************/&lt;br /&gt;
&lt;br /&gt;
void MsgLoop()&lt;br /&gt;
{&lt;br /&gt;
  ULONG winsig;&lt;br /&gt;
  ULONG result, code;&lt;br /&gt;
  BOOL laufen = TRUE;&lt;br /&gt;
&lt;br /&gt;
  /* save Signal Bits of the Window */&lt;br /&gt;
  IIntuition-&amp;gt;GetAttr(WINDOW_SigMask,gb_WindowObj,&amp;amp;winsig);&lt;br /&gt;
&lt;br /&gt;
  while(laufen)&lt;br /&gt;
  {&lt;br /&gt;
    /* wait for user actions */&lt;br /&gt;
    const ULONG sigs = IExec-&amp;gt;Wait(winsig | SIGBREAKF_CTRL_C);&lt;br /&gt;
&lt;br /&gt;
    /* process the received Messages */&lt;br /&gt;
    while((result = RA_HandleInput(gb_WindowObj,&amp;amp;code)) != WMHI_LASTMSG)&lt;br /&gt;
    {&lt;br /&gt;
      /* mask out the Messages part */&lt;br /&gt;
      switch(result &amp;amp; WMHI_CLASSMASK)&lt;br /&gt;
      {&lt;br /&gt;
        /* process Gadget Messages */&lt;br /&gt;
        case WMHI_GADGETUP:&lt;br /&gt;
             switch(result &amp;amp; WMHI_GADGETMASK)&lt;br /&gt;
             {&lt;br /&gt;
               case GAD_ID_ButtonV:&lt;br /&gt;
                    {&lt;br /&gt;
                    }&lt;br /&gt;
                    break;&lt;br /&gt;
&lt;br /&gt;
               case GAD_ID_Button:&lt;br /&gt;
                    {&lt;br /&gt;
                      IDOS-&amp;gt;Printf(&amp;quot;Button: [released]\n&amp;quot;);&lt;br /&gt;
                    }&lt;br /&gt;
                    break;&lt;br /&gt;
&lt;br /&gt;
               case GAD_ID_String:&lt;br /&gt;
                    {&lt;br /&gt;
                      STRPTR val;&lt;br /&gt;
                      IIntuition-&amp;gt;GetAttr(STRINGA_TextVal,(Object*)gb_StringGad,(ULONG*)&amp;amp;val);&lt;br /&gt;
                      IDOS-&amp;gt;Printf(&amp;quot;String: [%s]\n&amp;quot;,val);&lt;br /&gt;
                    }&lt;br /&gt;
                    break;&lt;br /&gt;
&lt;br /&gt;
               case GAD_ID_Integer:&lt;br /&gt;
                    {&lt;br /&gt;
                      ULONG val;&lt;br /&gt;
                      IIntuition-&amp;gt;GetAttr(INTEGER_Number,(Object*)gb_IntegerGad,(ULONG*)&amp;amp;val);&lt;br /&gt;
                      IDOS-&amp;gt;Printf(&amp;quot;Integer: [%ld]\n&amp;quot;,val);&lt;br /&gt;
                    }&lt;br /&gt;
                    break;&lt;br /&gt;
&lt;br /&gt;
               case GAD_ID_Slider:&lt;br /&gt;
                    {&lt;br /&gt;
                      ULONG val;&lt;br /&gt;
                      IIntuition-&amp;gt;GetAttr(SLIDER_Level,(Object*)gb_SliderGad,(ULONG*)&amp;amp;val);&lt;br /&gt;
                      IDOS-&amp;gt;Printf(&amp;quot;Slieder: [%ld]\n&amp;quot;,val);&lt;br /&gt;
                    }&lt;br /&gt;
                    break;&lt;br /&gt;
&lt;br /&gt;
               case GAD_ID_Scroller:&lt;br /&gt;
                    {&lt;br /&gt;
                      ULONG val;&lt;br /&gt;
                      IIntuition-&amp;gt;GetAttr(SCROLLER_Top,(Object*)gb_ScrollerGad,(ULONG*)&amp;amp;val);&lt;br /&gt;
                      IDOS-&amp;gt;Printf(&amp;quot;Scroller: [%ld]\n&amp;quot;,val);&lt;br /&gt;
                    }&lt;br /&gt;
                    break;&lt;br /&gt;
&lt;br /&gt;
               case GAD_ID_Chooser:&lt;br /&gt;
                    {&lt;br /&gt;
                      ULONG val;&lt;br /&gt;
                      IIntuition-&amp;gt;GetAttr(CHOOSER_Selected,(Object*)gb_ChooserGad,(ULONG*)&amp;amp;val);&lt;br /&gt;
                      IDOS-&amp;gt;Printf(&amp;quot;Chooser: [%ld]\n&amp;quot;,val);&lt;br /&gt;
                    }&lt;br /&gt;
                    break;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
               case GAD_ID_Chooser2:&lt;br /&gt;
                    {&lt;br /&gt;
                      ULONG val;&lt;br /&gt;
                      IIntuition-&amp;gt;GetAttr(CHOOSER_Selected,(Object*)gb_Chooser2Gad,(ULONG*)&amp;amp;val);&lt;br /&gt;
                      IDOS-&amp;gt;Printf(&amp;quot;Chooser2: [%ld]\n&amp;quot;,val);&lt;br /&gt;
                    }&lt;br /&gt;
                    break;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
               case GAD_ID_Chooser3:&lt;br /&gt;
                    {&lt;br /&gt;
                      ULONG val;&lt;br /&gt;
                      IIntuition-&amp;gt;GetAttr(CHOOSER_Selected,(Object*)gb_Chooser3Gad,(ULONG*)&amp;amp;val);&lt;br /&gt;
                      IDOS-&amp;gt;Printf(&amp;quot;Chooser3: [%ld]\n&amp;quot;,val);&lt;br /&gt;
                    }&lt;br /&gt;
                    break;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
               case GAD_ID_Checkbox:&lt;br /&gt;
                    {&lt;br /&gt;
                      ULONG val;&lt;br /&gt;
                      IIntuition-&amp;gt;GetAttr(GA_Selected,(Object*)gb_CheckboxGad,(ULONG*)&amp;amp;val);&lt;br /&gt;
                      IDOS-&amp;gt;Printf(&amp;quot;Checkbox: [%s]\n&amp;quot;,(val ? &amp;quot;selectet&amp;quot; : &amp;quot;not selected&amp;quot;));&lt;br /&gt;
                    }&lt;br /&gt;
                    break;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
               case GAD_ID_Radio:&lt;br /&gt;
                    {&lt;br /&gt;
                      ULONG val;&lt;br /&gt;
                      IIntuition-&amp;gt;GetAttr(RADIOBUTTON_Selected,(Object*)gb_RadioGad,(ULONG*)&amp;amp;val);&lt;br /&gt;
                      IDOS-&amp;gt;Printf(&amp;quot;Radio: [%ld]\n&amp;quot;,val);&lt;br /&gt;
                    }&lt;br /&gt;
                    break;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
               case GAD_ID_Listbrowser:&lt;br /&gt;
                    {&lt;br /&gt;
                      //ULONG action, column;&lt;br /&gt;
                      struct Node *node;&lt;br /&gt;
                      //IIntuition-&amp;gt;GetAttr(LISTBROWSER_RelEvent,(Object*)gb_WordlistGad,(ULONG*)&amp;amp;action);&lt;br /&gt;
                      //IIntuition-&amp;gt;GetAttr(LISTBROWSER_RelColumn,(Object*)gb_WordlistGad,(ULONG*)&amp;amp;column);&lt;br /&gt;
                      IIntuition-&amp;gt;GetAttr(LISTBROWSER_SelectedNode,(Object*)gb_ListbrowserGad,(ULONG*)&amp;amp;node);&lt;br /&gt;
                      //struct UserDictEntry *ude = LBNode2UserDictNode(node);&lt;br /&gt;
                      IDOS-&amp;gt;Printf(&amp;quot;Listview: [%ld]\n&amp;quot;,node-&amp;gt;ln_Pri);&lt;br /&gt;
                    }&lt;br /&gt;
                    break;&lt;br /&gt;
&lt;br /&gt;
               case GAD_ID_Palette:&lt;br /&gt;
                    {&lt;br /&gt;
                      ULONG val;&lt;br /&gt;
                      IIntuition-&amp;gt;GetAttr(PALETTE_Colour,(Object*)gb_PaletteGad,(ULONG*)&amp;amp;val);&lt;br /&gt;
                      IDOS-&amp;gt;Printf(&amp;quot;Palette: [%ld]\n&amp;quot;,val);&lt;br /&gt;
                    }&lt;br /&gt;
                    break;&lt;br /&gt;
&lt;br /&gt;
               case GAD_ID_File:&lt;br /&gt;
                    {&lt;br /&gt;
                      STRPTR val;&lt;br /&gt;
                      ULONG res = gfRequestFile((Object *)gb_FileGad,gb_Win);&lt;br /&gt;
                      IIntuition-&amp;gt;GetAttr(GETFILE_FullFile,(Object*)gb_FileGad,(ULONG*)&amp;amp;val);&lt;br /&gt;
                      if(res) IDOS-&amp;gt;Printf(&amp;quot;File: [%s]\n&amp;quot;,val);&lt;br /&gt;
                    }&lt;br /&gt;
                    break;&lt;br /&gt;
&lt;br /&gt;
               case GAD_ID_Font:&lt;br /&gt;
                    {&lt;br /&gt;
                      struct TextAttr *val;&lt;br /&gt;
                      ULONG res = gfRequestFont((Object *)gb_FontGad,gb_Win);&lt;br /&gt;
                      IIntuition-&amp;gt;GetAttr(GETFONT_TextAttr,(Object*)gb_FontGad,(ULONG*)&amp;amp;val);&lt;br /&gt;
                      if(res) IDOS-&amp;gt;Printf(&amp;quot;Font: [%s %ld]\n&amp;quot;,val-&amp;gt;ta_Name,val-&amp;gt;ta_YSize);&lt;br /&gt;
                    }&lt;br /&gt;
                    break;&lt;br /&gt;
&lt;br /&gt;
               case GAD_ID_Screenmode:&lt;br /&gt;
                    {&lt;br /&gt;
                      ULONG id, width, height, depth;&lt;br /&gt;
                      ULONG res = RequestScreenMode((Object *)gb_ScreenmodeGad,gb_Win);&lt;br /&gt;
                      IIntuition-&amp;gt;GetAttr(GETSCREENMODE_DisplayID,(Object*)gb_ScreenmodeGad,(ULONG*)&amp;amp;id);&lt;br /&gt;
                      IIntuition-&amp;gt;GetAttr(GETSCREENMODE_DisplayWidth,(Object*)gb_ScreenmodeGad,(ULONG*)&amp;amp;width);&lt;br /&gt;
                      IIntuition-&amp;gt;GetAttr(GETSCREENMODE_DisplayHeight,(Object*)gb_ScreenmodeGad,(ULONG*)&amp;amp;height);&lt;br /&gt;
                      IIntuition-&amp;gt;GetAttr(GETSCREENMODE_DisplayDepth,(Object*)gb_ScreenmodeGad,(ULONG*)&amp;amp;depth);&lt;br /&gt;
                      if(res) IDOS-&amp;gt;Printf(&amp;quot;Screenmode: [$%lx %ld x %ld x %ld]\n&amp;quot;,id,width,height,depth);&lt;br /&gt;
                    }&lt;br /&gt;
                    break;&lt;br /&gt;
&lt;br /&gt;
               case GAD_ID_Color:&lt;br /&gt;
                    {&lt;br /&gt;
                      ULONG val;&lt;br /&gt;
                      ULONG res = RequestColor((Object *)gb_ColorGad,gb_Win);&lt;br /&gt;
                      IIntuition-&amp;gt;GetAttr(GETCOLOR_Color,(Object*)gb_ColorGad,(ULONG*)&amp;amp;val);&lt;br /&gt;
                      if(res) IDOS-&amp;gt;Printf(&amp;quot;Color: [$%08lx]\n&amp;quot;,val);&lt;br /&gt;
                    }&lt;br /&gt;
                    break;&lt;br /&gt;
&lt;br /&gt;
               case GAD_ID_Fuelgauge:&lt;br /&gt;
                    {&lt;br /&gt;
                      ULONG val;&lt;br /&gt;
                      IIntuition-&amp;gt;GetAttr(FUELGAUGE_Level,(Object*)gb_FuelgaugeGad,(ULONG*)&amp;amp;val);&lt;br /&gt;
                      IDOS-&amp;gt;Printf(&amp;quot;Fuelgauge: [%ld]\n&amp;quot;,val);&lt;br /&gt;
                    }&lt;br /&gt;
                    break;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
               case GAD_ID_Colorwheel:&lt;br /&gt;
                    {&lt;br /&gt;
                      struct ColorWheelRGB val;&lt;br /&gt;
                      IIntuition-&amp;gt;GetAttr(WHEEL_RGB,(Object*)gb_ColorwheelGad,(ULONG*)&amp;amp;val);&lt;br /&gt;
                      IDOS-&amp;gt;Printf(&amp;quot;Colorwheel: [red=%08lx green=%08lx blue=%08lx]\n&amp;quot;,val.cw_Red,val.cw_Green,val.cw_Blue);&lt;br /&gt;
&lt;br /&gt;
                      /* reset the Gradient Slider depending on the new color selection */&lt;br /&gt;
                      struct ViewPort *vp = &amp;amp;gb_Scr-&amp;gt;ViewPort;&lt;br /&gt;
&lt;br /&gt;
                      if((WORD)gb_GradientArray[0] != ~0)&lt;br /&gt;
                       IGraphics-&amp;gt;SetRGB32(vp,gb_GradientArray[0],val.cw_Red,val.cw_Green,val.cw_Blue);&lt;br /&gt;
                      if((WORD)gb_GradientArray[1] != ~0)&lt;br /&gt;
                       IGraphics-&amp;gt;SetRGB32(vp,gb_GradientArray[1],val.cw_Red/15*12,val.cw_Green/15*12,val.cw_Blue/15*12);&lt;br /&gt;
                      if((WORD)gb_GradientArray[2] != ~0)&lt;br /&gt;
                       IGraphics-&amp;gt;SetRGB32(vp,gb_GradientArray[2],val.cw_Red/15*9,val.cw_Green/15*9,val.cw_Blue/15*9);&lt;br /&gt;
                      if((WORD)gb_GradientArray[3] != ~0)&lt;br /&gt;
                       IGraphics-&amp;gt;SetRGB32(vp,gb_GradientArray[3],val.cw_Red/15*6,val.cw_Green/15*6,val.cw_Blue/15*6);&lt;br /&gt;
                      if((WORD)gb_GradientArray[4] != ~0)&lt;br /&gt;
                       IGraphics-&amp;gt;SetRGB32(vp,gb_GradientArray[4],val.cw_Red/15*3,val.cw_Green/15*3,val.cw_Blue/15*3);&lt;br /&gt;
                      IIntuition-&amp;gt;RefreshGadgets(gb_GradientsliderGad,gb_Win,NULL);&lt;br /&gt;
                    }&lt;br /&gt;
                    break;&lt;br /&gt;
&lt;br /&gt;
               case GAD_ID_Gradientslider:&lt;br /&gt;
                    {&lt;br /&gt;
                      ULONG val;&lt;br /&gt;
                      IIntuition-&amp;gt;GetAttr(GRAD_CurVal,(Object*)gb_GradientsliderGad,(ULONG*)&amp;amp;val);&lt;br /&gt;
                      IDOS-&amp;gt;Printf(&amp;quot;Gradientslieder: [%ld]\n&amp;quot;,val);&lt;br /&gt;
                    }&lt;br /&gt;
                    break;&lt;br /&gt;
&lt;br /&gt;
               case GAD_ID_Texteditor:&lt;br /&gt;
                    {&lt;br /&gt;
                      STRPTR val;&lt;br /&gt;
                      val = (STRPTR) IIntuition-&amp;gt;DoGadgetMethod(gb_TexteditorGad,gb_Win,NULL,GM_TEXTEDITOR_ExportText,NULL);&lt;br /&gt;
                      if(val) IDOS-&amp;gt;Printf(&amp;quot;Texteditor: [%s]\n&amp;quot;,val);&lt;br /&gt;
                    }&lt;br /&gt;
                    break;&lt;br /&gt;
&lt;br /&gt;
               case GAD_ID_Datebrowser:&lt;br /&gt;
                    {&lt;br /&gt;
                      ULONG day, month, year;&lt;br /&gt;
                      IIntuition-&amp;gt;GetAttr(DATEBROWSER_Day,(Object*)gb_DatebrowserGad,(ULONG*)&amp;amp;day);&lt;br /&gt;
                      IIntuition-&amp;gt;GetAttr(DATEBROWSER_Month,(Object*)gb_DatebrowserGad,(ULONG*)&amp;amp;month);&lt;br /&gt;
                      IIntuition-&amp;gt;GetAttr(DATEBROWSER_Year,(Object*)gb_DatebrowserGad,(ULONG*)&amp;amp;year);&lt;br /&gt;
                      IDOS-&amp;gt;Printf(&amp;quot;Datebrowser: [%ld.%ld.%ld]\n&amp;quot;,day,month,year);&lt;br /&gt;
                    }&lt;br /&gt;
                    break;&lt;br /&gt;
&lt;br /&gt;
               case GAD_ID_Space:&lt;br /&gt;
                    {&lt;br /&gt;
                    //  ULONG mx, my;&lt;br /&gt;
                    //  IIntuition-&amp;gt;GetAttr(SPACE_MouseX,(Object*)gb_SpaceGad,(ULONG*)&amp;amp;mx);&lt;br /&gt;
                    //  IIntuition-&amp;gt;GetAttr(SPACE_MouseY,(Object*)gb_SpaceGad,(ULONG*)&amp;amp;my);&lt;br /&gt;
                    //  IDOS-&amp;gt;Printf(&amp;quot;Space: [%ld : %ld]\n&amp;quot;,mx,my);&lt;br /&gt;
                    }&lt;br /&gt;
                    break;&lt;br /&gt;
&lt;br /&gt;
               case GAD_ID_Page:&lt;br /&gt;
                    {&lt;br /&gt;
                      ULONG val;&lt;br /&gt;
                      IIntuition-&amp;gt;GetAttr(PAGE_Current,(Object*)gb_PageGad,(ULONG*)&amp;amp;val);&lt;br /&gt;
                      IDOS-&amp;gt;Printf(&amp;quot;Page: [%ld]\n&amp;quot;,val);&lt;br /&gt;
                    }&lt;br /&gt;
                    break;&lt;br /&gt;
&lt;br /&gt;
               case GAD_ID_Clicktab:&lt;br /&gt;
                    {&lt;br /&gt;
                      ULONG val;&lt;br /&gt;
                      IIntuition-&amp;gt;GetAttr(CLICKTAB_Current,(Object*)gb_ClicktabGad,(ULONG*)&amp;amp;val);&lt;br /&gt;
                      IDOS-&amp;gt;Printf(&amp;quot;Clicktab: [%ld]\n&amp;quot;,val);&lt;br /&gt;
                    }&lt;br /&gt;
                    break;&lt;br /&gt;
&lt;br /&gt;
             }&lt;br /&gt;
             break;&lt;br /&gt;
&lt;br /&gt;
        /* RawKey of pressed key */&lt;br /&gt;
        case WMHI_RAWKEY:&lt;br /&gt;
             {&lt;br /&gt;
               //struct InputEvent *ie;&lt;br /&gt;
               //IIntuition-&amp;gt;GetAttr(WINDOW_InputEvent,gb_WindowObj,(ULONG *)&amp;amp;ie);&lt;br /&gt;
               // code = result &amp;amp; WMHI_KEYMASK&lt;br /&gt;
               // qualifier = ie-&amp;gt;ie_Qualifier&lt;br /&gt;
             }&lt;br /&gt;
             break;&lt;br /&gt;
&lt;br /&gt;
        /* ASCII code of pressed key */&lt;br /&gt;
        case WMHI_MENUPICK:&lt;br /&gt;
             switch(result &amp;amp; WMHI_MENUMASK)&lt;br /&gt;
             {&lt;br /&gt;
               //case MENU_ID_xxx:&lt;br /&gt;
               //     break;&lt;br /&gt;
             }&lt;br /&gt;
             break;&lt;br /&gt;
&lt;br /&gt;
        /* Window Close Icon clicked */&lt;br /&gt;
        case WMHI_CLOSEWINDOW:&lt;br /&gt;
             {&lt;br /&gt;
               /* Window Close Icon executed */&lt;br /&gt;
               laufen = FALSE;&lt;br /&gt;
             }&lt;br /&gt;
             break;&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    /* CTRL-C typed into the Shell or received as signal */&lt;br /&gt;
    if(sigs &amp;amp; SIGBREAKF_CTRL_C) laufen = FALSE;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/******************************************************************************/&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[])&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
  if( CreateAll() )&lt;br /&gt;
  {&lt;br /&gt;
    MsgLoop();&lt;br /&gt;
&lt;br /&gt;
    DestroyAll();&lt;br /&gt;
  }&lt;br /&gt;
  else IDOS-&amp;gt;Printf(&amp;quot;Createing GUI failed !\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here are the support graphics files to go with it: [[Media:allgadgets-gfx.lha|allgadgets-gfx.lha]]&lt;br /&gt;
&lt;br /&gt;
[[File:AF110_allgadgets.png|frame|center]]&lt;br /&gt;
&lt;br /&gt;
Reactor&#039;s approach, which you could use to &#039;click together&#039; graphically a GUI under the Workbench 3.5 and 3.9, hasn&#039;t been developed any further. However, as shown in the previous example, you can basically copy the required GUI elements in your own sources with copy &amp;amp; paste.&lt;br /&gt;
&lt;br /&gt;
= ClickTab-Test Example =&lt;br /&gt;
&lt;br /&gt;
Another bonus is &amp;quot;ClickTab-Test&amp;quot; which deals exclusively with the Clicktab gadget. As I already mentioned, you can use it to create tabs. The tabs can in the meantime be dynamically added and deleted again. Moreover, you can use both tags, so all tags have the same width and the tab labeling is not shortened.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
/* Michael Christoph&lt;br /&gt;
 * ClickTab-Test.c&lt;br /&gt;
 *&lt;br /&gt;
 * gcc ClickTab-Test.c -o ClickTab-Test -l auto&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/******************************* INCLUDES *************************************/&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;exec/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;intuition/gadgetclass.h&amp;gt;&lt;br /&gt;
#include &amp;lt;classes/window.h&amp;gt;&lt;br /&gt;
#include &amp;lt;classes/requester.h&amp;gt;&lt;br /&gt;
#include &amp;lt;reaction/reaction_macros.h&amp;gt;&lt;br /&gt;
#include &amp;lt;libraries/gadtools.h&amp;gt;&lt;br /&gt;
#include &amp;lt;gadgets/button.h&amp;gt;&lt;br /&gt;
#include &amp;lt;gadgets/checkbox.h&amp;gt;&lt;br /&gt;
#include &amp;lt;gadgets/string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;gadgets/clicktab.h&amp;gt;&lt;br /&gt;
#include &amp;lt;gadgets/layout.h&amp;gt;&lt;br /&gt;
#include &amp;lt;gadgets/page.h&amp;gt;&lt;br /&gt;
#include &amp;lt;images/label.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;proto/exec.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/dos.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/intuition.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/utility.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/window.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/layout.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/button.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/label.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/clicktab.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/checkbox.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/label.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/******************************************************************************/&lt;br /&gt;
&lt;br /&gt;
static const char *version USED = &amp;quot;\0$VER: ClickTab-Test 1.0 (13.02.2009) - (c) Feb.2009 by Meicky-Soft\n&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
/******************************************************************************/&lt;br /&gt;
&lt;br /&gt;
enum GADID&lt;br /&gt;
{&lt;br /&gt;
  GAD_ID_Name = 1,&lt;br /&gt;
  GAD_ID_Add,&lt;br /&gt;
  GAD_ID_Del,&lt;br /&gt;
&lt;br /&gt;
  GAD_ID_Evensize,&lt;br /&gt;
  GAD_ID_Labeltruncate,&lt;br /&gt;
&lt;br /&gt;
  GAD_ID_Clicktab,&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct Gadget *gb_NameGad;&lt;br /&gt;
struct Gadget *gb_AddGad;&lt;br /&gt;
struct Gadget *gb_DelGad;&lt;br /&gt;
struct Gadget *gb_EvensizeGad;&lt;br /&gt;
struct Gadget *gb_LabeltruncateGad;&lt;br /&gt;
struct Gadget *gb_ClicktabGad;&lt;br /&gt;
struct Gadget *gb_MainLayout;&lt;br /&gt;
&lt;br /&gt;
#define MAX_CLICKTABS 15&lt;br /&gt;
STRPTR gb_ClicktabLabels[MAX_CLICKTABS + 1] = { NULL };&lt;br /&gt;
&lt;br /&gt;
Object        *gb_WindowObj;&lt;br /&gt;
struct Window *gb_Win;&lt;br /&gt;
struct Screen *gb_Scr;&lt;br /&gt;
&lt;br /&gt;
/******************************************************************************/&lt;br /&gt;
&lt;br /&gt;
BOOL CreateGUI()&lt;br /&gt;
{&lt;br /&gt;
  if((gb_ClicktabLabels[0] = (STRPTR) IExec-&amp;gt;AllocVecTags(31, AVT_Type, MEMF_SHARED, TAG_END)))&lt;br /&gt;
  {&lt;br /&gt;
    IUtility-&amp;gt;Strlcpy(gb_ClicktabLabels[0], &amp;quot;_Muster&amp;quot;, 30);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  gb_NameGad = (struct Gadget *) IIntuition-&amp;gt;NewObject(IString-&amp;gt;STRING_GetClass(),NULL,&lt;br /&gt;
      GA_ID,                  GAD_ID_Name,&lt;br /&gt;
      GA_RelVerify,           TRUE,&lt;br /&gt;
      GA_TabCycle,            TRUE,&lt;br /&gt;
      STRINGA_MaxChars,       30+1,&lt;br /&gt;
      STRINGA_MinVisible,     30,&lt;br /&gt;
      TAG_END);&lt;br /&gt;
&lt;br /&gt;
  gb_AddGad = (struct Gadget *) IIntuition-&amp;gt;NewObject(IButton-&amp;gt;BUTTON_GetClass(),NULL,&lt;br /&gt;
      GA_ID,                  GAD_ID_Add,&lt;br /&gt;
      GA_RelVerify,           TRUE,&lt;br /&gt;
      GA_Text,                &amp;quot;_Add&amp;quot;,&lt;br /&gt;
      TAG_END);&lt;br /&gt;
&lt;br /&gt;
  gb_DelGad = (struct Gadget *) IIntuition-&amp;gt;NewObject(IButton-&amp;gt;BUTTON_GetClass(),NULL,&lt;br /&gt;
      GA_ID,                  GAD_ID_Del,&lt;br /&gt;
      GA_RelVerify,           TRUE,&lt;br /&gt;
      GA_Text,                &amp;quot;_Del&amp;quot;,&lt;br /&gt;
      TAG_END);&lt;br /&gt;
&lt;br /&gt;
  gb_EvensizeGad = (struct Gadget *) IIntuition-&amp;gt;NewObject(ICheckBox-&amp;gt;CHECKBOX_GetClass(),NULL,&lt;br /&gt;
      GA_ID,                  GAD_ID_Evensize,&lt;br /&gt;
      GA_Text,                &amp;quot;EvenSize&amp;quot;,&lt;br /&gt;
      GA_RelVerify,           TRUE,&lt;br /&gt;
      CHECKBOX_TextPlace,     PLACETEXT_RIGHT,&lt;br /&gt;
      CHECKBOX_Checked,       FALSE,&lt;br /&gt;
      TAG_END);&lt;br /&gt;
&lt;br /&gt;
  gb_LabeltruncateGad = (struct Gadget *) IIntuition-&amp;gt;NewObject(ICheckBox-&amp;gt;CHECKBOX_GetClass(),NULL,&lt;br /&gt;
      GA_ID,                  GAD_ID_Labeltruncate,&lt;br /&gt;
      GA_Text,                &amp;quot;LabelTruncate&amp;quot;,&lt;br /&gt;
      GA_RelVerify,           TRUE,&lt;br /&gt;
      CHECKBOX_TextPlace,     PLACETEXT_RIGHT,&lt;br /&gt;
      CHECKBOX_Checked,       TRUE,&lt;br /&gt;
      TAG_END);&lt;br /&gt;
&lt;br /&gt;
  gb_ClicktabGad = (struct Gadget *) IIntuition-&amp;gt;NewObject(IClickTab-&amp;gt;CLICKTAB_GetClass(),NULL,&lt;br /&gt;
      GA_ID,                  GAD_ID_Clicktab,&lt;br /&gt;
      GA_Text,                &amp;amp;gb_ClicktabLabels,&lt;br /&gt;
      GA_RelVerify,           TRUE,&lt;br /&gt;
      CLICKTAB_EvenSize,      FALSE,&lt;br /&gt;
      CLICKTAB_LabelTruncate, TRUE,&lt;br /&gt;
      //CLICKTAB_PageGroup,   gb_PagesLayout,&lt;br /&gt;
      TAG_END);&lt;br /&gt;
&lt;br /&gt;
  gb_MainLayout = (struct Gadget *) IIntuition-&amp;gt;NewObject(ILayout-&amp;gt;LAYOUT_GetClass(),NULL,&lt;br /&gt;
    LAYOUT_Orientation,  LAYOUT_VERTICAL,&lt;br /&gt;
    LAYOUT_SpaceOuter,   TRUE,&lt;br /&gt;
    LAYOUT_SpaceInner,   TRUE,&lt;br /&gt;
&lt;br /&gt;
    LAYOUT_AddChild,     gb_NameGad,&lt;br /&gt;
    LAYOUT_AddChild,     gb_AddGad,&lt;br /&gt;
    LAYOUT_AddChild,     gb_DelGad,&lt;br /&gt;
    LAYOUT_AddChild,     gb_EvensizeGad,&lt;br /&gt;
    LAYOUT_AddChild,     gb_LabeltruncateGad,&lt;br /&gt;
    LAYOUT_AddChild,     gb_ClicktabGad,&lt;br /&gt;
&lt;br /&gt;
    TAG_END);&lt;br /&gt;
&lt;br /&gt;
  if(gb_MainLayout)&lt;br /&gt;
  {&lt;br /&gt;
&lt;br /&gt;
    /* Create the window object */&lt;br /&gt;
    if((gb_WindowObj = (Object *) IIntuition-&amp;gt;NewObject(IWindow-&amp;gt;WINDOW_GetClass(),NULL,&lt;br /&gt;
      WA_IDCMP,             IDCMP_GADGETUP |&lt;br /&gt;
                            IDCMP_VANILLAKEY |&lt;br /&gt;
                            IDCMP_CLOSEWINDOW,&lt;br /&gt;
      WA_SizeGadget,        TRUE,&lt;br /&gt;
      WA_DepthGadget,       TRUE,&lt;br /&gt;
      WA_DragBar,           TRUE,&lt;br /&gt;
      WA_Activate,          TRUE,&lt;br /&gt;
      WA_Title,             &amp;quot;Variable Number of Tabs&amp;quot;,&lt;br /&gt;
      WA_InnerWidth,        150,&lt;br /&gt;
      WA_InnerHeight,       100,&lt;br /&gt;
      WA_AutoAdjust,        TRUE,&lt;br /&gt;
      WA_CloseGadget,       TRUE,&lt;br /&gt;
      WINDOW_ParentGroup,   gb_MainLayout,&lt;br /&gt;
      TAG_END)))&lt;br /&gt;
    {&lt;br /&gt;
      /* Everything created successfully */&lt;br /&gt;
&lt;br /&gt;
      /* The window can be opened now */&lt;br /&gt;
      gb_Win = RA_OpenWindow(gb_WindowObj);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return ( gb_Win ? TRUE : FALSE );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/******************************************************************************/&lt;br /&gt;
&lt;br /&gt;
void FreeGUI()&lt;br /&gt;
{&lt;br /&gt;
  RA_CloseWindow(gb_WindowObj);&lt;br /&gt;
  IIntuition-&amp;gt;DisposeObject(gb_WindowObj);&lt;br /&gt;
&lt;br /&gt;
  ULONG i;&lt;br /&gt;
  for(i=0; i&amp;lt;MAX_CLICKTABS; i++)&lt;br /&gt;
  {&lt;br /&gt;
    if(gb_ClicktabLabels[i]) IExec-&amp;gt;FreeVec(gb_ClicktabLabels[i]);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/******************************************************************************/&lt;br /&gt;
&lt;br /&gt;
void MsgLoop()&lt;br /&gt;
{&lt;br /&gt;
  ULONG winsig;&lt;br /&gt;
  ULONG result, code;&lt;br /&gt;
  BOOL running = TRUE;&lt;br /&gt;
&lt;br /&gt;
  /* Get the window signal bit mask */&lt;br /&gt;
  IIntuition-&amp;gt;GetAttr(WINDOW_SigMask, gb_WindowObj, &amp;amp;winsig);&lt;br /&gt;
&lt;br /&gt;
  while(running)&lt;br /&gt;
  {&lt;br /&gt;
    /* Wait for user actions */&lt;br /&gt;
    const ULONG sigs = IExec-&amp;gt;Wait(winsig | SIGBREAKF_CTRL_C);&lt;br /&gt;
&lt;br /&gt;
    /* Process all messages */&lt;br /&gt;
    while((result = RA_HandleInput(gb_WindowObj, &amp;amp;code)) != WMHI_LASTMSG)&lt;br /&gt;
    {&lt;br /&gt;
      /* Mask out the message class ! */&lt;br /&gt;
      switch(result &amp;amp; WMHI_CLASSMASK)&lt;br /&gt;
      {&lt;br /&gt;
        /* Handle gadget message */&lt;br /&gt;
        case WMHI_GADGETUP:&lt;br /&gt;
             switch(result &amp;amp; WMHI_GADGETMASK)&lt;br /&gt;
             {&lt;br /&gt;
               case GAD_ID_Name:&lt;br /&gt;
                    {&lt;br /&gt;
                      /* Update caption */&lt;br /&gt;
                      ULONG val;&lt;br /&gt;
                      IIntuition-&amp;gt;GetAttr(CLICKTAB_Current,(Object*)gb_ClicktabGad,(ULONG*)&amp;amp;val);&lt;br /&gt;
                      STRPTR name;&lt;br /&gt;
                      IIntuition-&amp;gt;GetAttr(STRINGA_TextVal,(Object*)gb_NameGad,(ULONG*)&amp;amp;name);&lt;br /&gt;
                      IUtility-&amp;gt;Strlcpy(gb_ClicktabLabels[val],name,30);&lt;br /&gt;
                      IDOS-&amp;gt;Printf(&amp;quot;Update CT [%ld] &amp;lt;%s&amp;gt;\n&amp;quot;,val,name);&lt;br /&gt;
                      IIntuition-&amp;gt;RefreshSetGadgetAttrs(gb_ClicktabGad,gb_Win,NULL, GA_Text,gb_ClicktabLabels, TAG_END);&lt;br /&gt;
                    }&lt;br /&gt;
                    break;&lt;br /&gt;
&lt;br /&gt;
               case GAD_ID_Add:&lt;br /&gt;
                    {&lt;br /&gt;
                      /* Add a new tab */&lt;br /&gt;
                      ULONG max;&lt;br /&gt;
                      IIntuition-&amp;gt;GetAttr(CLICKTAB_Total,(Object*)gb_ClicktabGad,(ULONG*)&amp;amp;max);&lt;br /&gt;
                      if(max &amp;lt; MAX_CLICKTABS-1)&lt;br /&gt;
                      {&lt;br /&gt;
                        STRPTR name;&lt;br /&gt;
                        IIntuition-&amp;gt;GetAttr(STRINGA_TextVal,(Object*)gb_NameGad,(ULONG*)&amp;amp;name);&lt;br /&gt;
                        if(name[0])&lt;br /&gt;
                        {&lt;br /&gt;
                          IDOS-&amp;gt;Printf(&amp;quot;Add CT [%ld] &amp;lt;%s&amp;gt;\n&amp;quot;,max,name);&lt;br /&gt;
                          if((gb_ClicktabLabels[max] = (STRPTR) IExec-&amp;gt;AllocVecTags(31,AVT_Type,MEMF_SHARED,TAG_END)))&lt;br /&gt;
                          {&lt;br /&gt;
                            IUtility-&amp;gt;Strlcpy(gb_ClicktabLabels[max],name,30);&lt;br /&gt;
                          }&lt;br /&gt;
                          else IDOS-&amp;gt;Printf(&amp;quot;out of memory\n&amp;quot;);&lt;br /&gt;
                          IIntuition-&amp;gt;RefreshSetGadgetAttrs(gb_ClicktabGad,gb_Win,NULL, GA_Text,gb_ClicktabLabels, TAG_END);&lt;br /&gt;
                        }&lt;br /&gt;
                        else IDOS-&amp;gt;Printf(&amp;quot;Name for tab required\n&amp;quot;);&lt;br /&gt;
                      }&lt;br /&gt;
                      else IDOS-&amp;gt;Printf(&amp;quot;No more tabs possible\n&amp;quot;);&lt;br /&gt;
                    }&lt;br /&gt;
                    break;&lt;br /&gt;
&lt;br /&gt;
               case GAD_ID_Del:&lt;br /&gt;
                    {&lt;br /&gt;
                      /* Erase the current tab */&lt;br /&gt;
                      ULONG val, i;&lt;br /&gt;
                      IIntuition-&amp;gt;GetAttr(CLICKTAB_Current,(Object*)gb_ClicktabGad,(ULONG*)&amp;amp;val);&lt;br /&gt;
                      IDOS-&amp;gt;Printf(&amp;quot;Del CT [%ld] &amp;lt;%s&amp;gt;\n&amp;quot;,val,gb_ClicktabLabels[val]);&lt;br /&gt;
                      IExec-&amp;gt;FreeVec(gb_ClicktabLabels[val]);&lt;br /&gt;
                      for(i=val; i&amp;lt;MAX_CLICKTABS; i++)&lt;br /&gt;
                      {&lt;br /&gt;
                        gb_ClicktabLabels[i] = gb_ClicktabLabels[i + 1];&lt;br /&gt;
                      }&lt;br /&gt;
                      IIntuition-&amp;gt;RefreshSetGadgetAttrs(gb_ClicktabGad,gb_Win,NULL, GA_Text,gb_ClicktabLabels, TAG_END);&lt;br /&gt;
                    }&lt;br /&gt;
                    break;&lt;br /&gt;
&lt;br /&gt;
               case GAD_ID_Evensize:&lt;br /&gt;
                    {&lt;br /&gt;
                      /* All tabs have the same width */&lt;br /&gt;
                      /* V53: WORKS ONLY DURING INITIALIZATION ! */&lt;br /&gt;
                      ULONG val;&lt;br /&gt;
                      IIntuition-&amp;gt;GetAttr(GA_Selected,(Object*)gb_EvensizeGad,(ULONG*)&amp;amp;val);&lt;br /&gt;
                      IIntuition-&amp;gt;RefreshSetGadgetAttrs(gb_ClicktabGad,gb_Win,NULL, CLICKTAB_EvenSize,val, TAG_END);&lt;br /&gt;
                      /* !!! MUST DO to layout the changed tag !!! */&lt;br /&gt;
                      IIntuition-&amp;gt;RefreshSetGadgetAttrs(gb_ClicktabGad,gb_Win,NULL, GA_Text,gb_ClicktabLabels, TAG_END);&lt;br /&gt;
                    }&lt;br /&gt;
                    break;&lt;br /&gt;
&lt;br /&gt;
               case GAD_ID_Labeltruncate:&lt;br /&gt;
                    {&lt;br /&gt;
                      /* Truncates label if necessary */&lt;br /&gt;
                      /* V53: WORKS ONLY DURING INITIALIZATION ! */&lt;br /&gt;
                      ULONG val;&lt;br /&gt;
                      IIntuition-&amp;gt;GetAttr(GA_Selected,(Object*)gb_LabeltruncateGad,(ULONG*)&amp;amp;val);&lt;br /&gt;
                      IIntuition-&amp;gt;RefreshSetGadgetAttrs(gb_ClicktabGad,gb_Win,NULL, CLICKTAB_LabelTruncate,val, TAG_END);&lt;br /&gt;
                      /* !!! MUST DO to layout the changed tag !!! */&lt;br /&gt;
                      IIntuition-&amp;gt;RefreshSetGadgetAttrs(gb_ClicktabGad,gb_Win,NULL, GA_Text,gb_ClicktabLabels, TAG_END);&lt;br /&gt;
                    }&lt;br /&gt;
                    break;&lt;br /&gt;
&lt;br /&gt;
               case GAD_ID_Clicktab:&lt;br /&gt;
                    {&lt;br /&gt;
                      /* Use tab name for editing */&lt;br /&gt;
                      ULONG val;&lt;br /&gt;
                      IIntuition-&amp;gt;GetAttr(CLICKTAB_Current,(Object*)gb_ClicktabGad, (ULONG*)&amp;amp;val);&lt;br /&gt;
                      IDOS-&amp;gt;Printf(&amp;quot;Update STR [%ld] &amp;lt;%s&amp;gt;\n&amp;quot;, val, gb_ClicktabLabels[val]);&lt;br /&gt;
                      IIntuition-&amp;gt;SetGadgetAttrs(gb_NameGad,gb_Win,NULL, STRINGA_TextVal,gb_ClicktabLabels[val], TAG_END);&lt;br /&gt;
                    }&lt;br /&gt;
                    break;&lt;br /&gt;
             }&lt;br /&gt;
             break;&lt;br /&gt;
&lt;br /&gt;
        case WMHI_VANILLAKEY:&lt;br /&gt;
             {&lt;br /&gt;
               const LONG code = result &amp;amp; WMHI_KEYMASK;&lt;br /&gt;
&lt;br /&gt;
               if(code == &#039; &#039;)&lt;br /&gt;
               {&lt;br /&gt;
                 IDOS-&amp;gt;Printf(&amp;quot;---- Label List:\n&amp;quot;);&lt;br /&gt;
                 ULONG i;&lt;br /&gt;
                 for(i=0; i&amp;lt;MAX_CLICKTABS; i++)&lt;br /&gt;
                 {&lt;br /&gt;
                   if(gb_ClicktabLabels[i]) IDOS-&amp;gt;Printf(&amp;quot;[%ld] &amp;lt;%s&amp;gt; $%lx\n&amp;quot;,i,gb_ClicktabLabels[i],gb_ClicktabLabels[i]);&lt;br /&gt;
                 }&lt;br /&gt;
                 IDOS-&amp;gt;Printf(&amp;quot;----------------\n&amp;quot;);&lt;br /&gt;
               }&lt;br /&gt;
             }&lt;br /&gt;
             break;&lt;br /&gt;
&lt;br /&gt;
        /* Window close gadget clicked */&lt;br /&gt;
        case WMHI_CLOSEWINDOW:&lt;br /&gt;
             {&lt;br /&gt;
               running = FALSE;&lt;br /&gt;
             }&lt;br /&gt;
             break;&lt;br /&gt;
      }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    /* CTRL-C typed in the shell or via a signal */&lt;br /&gt;
    if(sigs &amp;amp; SIGBREAKF_CTRL_C) laufen = FALSE;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/******************************************************************************/&lt;br /&gt;
&lt;br /&gt;
int main(int argc, char *argv[])&lt;br /&gt;
{&lt;br /&gt;
  /* AmigaOS 4.1 is required */&lt;br /&gt;
  if(SysBase-&amp;gt;lib_Version &amp;lt; 53)&lt;br /&gt;
  {&lt;br /&gt;
    IDOS-&amp;gt;Printf(&amp;quot;Program requires AmigaOS 4.1\n&amp;quot;);&lt;br /&gt;
    return( 20 );&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  if( CreateGUI() )&lt;br /&gt;
  {&lt;br /&gt;
    MsgLoop();&lt;br /&gt;
&lt;br /&gt;
    FreeGUI();&lt;br /&gt;
  }&lt;br /&gt;
  else IDOS-&amp;gt;Printf(&amp;quot;GUI creation failed !\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:AF110_clicktab-test.png|frame|center]]&lt;br /&gt;
&lt;br /&gt;
Irrespective of the programing side, the user can influence the appearance and partly the behaviour of gadgets and windows system-wide using the Prefs options. Angular or rounded edges, the thickness of the window frame, and also the complex colour scheme are all widely configurable. There are ready-made styles so everything works perfectly in the visual sense.&lt;br /&gt;
&lt;br /&gt;
= Authors =&lt;br /&gt;
&lt;br /&gt;
Written by Michael Christoph and Aleksandra Schmidt-Pendarovska&amp;lt;br/&amp;gt;&lt;br /&gt;
Copyright (c) 2013 Michael Christoph&lt;/div&gt;</summary>
		<author><name>Costel Mincea</name></author>
	</entry>
	<entry>
		<id>https://wiki.amigaos.net/w/index.php?title=ANIM_IFF_CEL_Animations&amp;diff=12554</id>
		<title>ANIM IFF CEL Animations</title>
		<link rel="alternate" type="text/html" href="https://wiki.amigaos.net/w/index.php?title=ANIM_IFF_CEL_Animations&amp;diff=12554"/>
		<updated>2025-01-26T19:30:52Z</updated>

		<summary type="html">&lt;p&gt;Costel Mincea: Text replacement - &amp;quot;&amp;lt;syntaxhighlight&amp;gt;&amp;quot; to &amp;quot;&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= ANIM =&lt;br /&gt;
&lt;br /&gt;
An IFF Format For CEL Animations&lt;br /&gt;
&lt;br /&gt;
Revision date:  6 June 2013&lt;br /&gt;
&lt;br /&gt;
Originally prepared by:&lt;br /&gt;
: SPARTA Inc.&lt;br /&gt;
: 23041 de la Carlota&lt;br /&gt;
: Laguna Hills, Calif 92653&lt;br /&gt;
: (714) 768-8161&lt;br /&gt;
: Contact: Gary Bonham&lt;br /&gt;
&lt;br /&gt;
Also by:&lt;br /&gt;
: Aegis Development Co.&lt;br /&gt;
: 2115 Pico Blvd.&lt;br /&gt;
: Santa Monica, Calif 90405&lt;br /&gt;
: (213) 392-9972&lt;br /&gt;
&lt;br /&gt;
= Introduction =&lt;br /&gt;
   &lt;br /&gt;
The ANIM IFF format was developed at Sparta originally for the production of animated video sequences on the Amiga computer.  The intent was to be able to store, and play back, sequences of frames and to minimize both the storage space on disk (through compression) and playback time (through efficient decompression algorithms). It was desired to maintain maximum compatibility with existing IFF formats and to be able to display the initial frame as a normal still IFF picture.&lt;br /&gt;
   &lt;br /&gt;
Several compression schemes have been introduced in the ANIM format. Most of these are strictly of historical interest as the only one currently being placed in new code is the vertical run length encoded byte encoding developed by Jim Kent.&lt;br /&gt;
   &lt;br /&gt;
== ANIM Format Overview ==&lt;br /&gt;
      &lt;br /&gt;
The general philosophy of ANIMs is to present the initial frame as a normal, run-length-encoded, IFF picture.  Subsequent&lt;br /&gt;
frames are then described by listing only their differences from a previous frame.  Normally, the &amp;amp;quot;previous&amp;amp;quot; frame is two frames back as that is the frame remaining in the hidden screen buffer when double-buffering is used.  To better understand this, suppose one has two screens, called A and B, and the ability to instantly switch the display from one to the other.  The normal playback mode is to load the initial frame into A and duplicate it into B.  Then frame A is displayed on the screen.  Then the differences for frame 2 are used to alter screen B and it is displayed.  Then the differences for frame 3 are used to alter screen A and it is displayed, and so on.  Note that frame 2 is stored as differences from frame 1, but all other frames are stored as differences from two frames back.&lt;br /&gt;
      &lt;br /&gt;
ANIM is an IFF FORM and its basic format is as follows (this assumes the reader has a basic understanding of IFF format&lt;br /&gt;
files):&lt;br /&gt;
                      FORM ANIM&lt;br /&gt;
                      . FORM ILBM         first frame&lt;br /&gt;
                      . . BMHD                normal type IFF data&lt;br /&gt;
                      . . ANHD                optional animation header&lt;br /&gt;
                                              chunk for timing of 1st frame.&lt;br /&gt;
                      . . CMAP&lt;br /&gt;
                      . . BODY&lt;br /&gt;
                      . FORM ILBM         frame 2&lt;br /&gt;
                      . . ANHD                animation header chunk&lt;br /&gt;
                      . . DLTA                delta mode data&lt;br /&gt;
                      . FORM ILBM         frame 3&lt;br /&gt;
                      . . ANHD&lt;br /&gt;
                      . . DLTA&lt;br /&gt;
                           ...&lt;br /&gt;
      &lt;br /&gt;
The initial FORM ILBM can contain all the normal ILBM chunks, such as CRNG, etc.  The BODY will normally be a standard&lt;br /&gt;
run-length-encoded data chunk (but may be any other legal compression mode as indicated by the BMHD).  If desired, an ANHD&lt;br /&gt;
chunk can appear here to provide timing data for the first frame.  If it is here, the operation field should be =0.&lt;br /&gt;
      &lt;br /&gt;
The subsequent FORMs ILBM contain an ANHD, instead of a BMHD, which duplicates some of BMHD and has additional parameters&lt;br /&gt;
pertaining to the animation frame.  The DLTA chunk contains the data for the delta compression modes.  If the older XOR compression mode is used, then a BODY chunk will be here.  In addition, other chunks may be placed in each of these as deemed necessary (and as code is placed in player programs to utilize them).  A good example would be CMAP chunks to alter the color palette.  A basic assumption in ANIMs is that the size of the bitmap, and the display mode (e.g. HAM) will not change through the animation.  Take care when playing an ANIM that if a CMAP occurs with a frame, then the change must be applied to both buffers.&lt;br /&gt;
      &lt;br /&gt;
Note that the DLTA chunks are not interleaved bitmap representations, thus the use of the ILBM form is inappropriate for these frames. However, this inconsistency was not noted until there were a number of commercial products either released or close to release which generated/played this format.  Therefore, this is probably an inconsistency which will have to stay with us.&lt;br /&gt;
&lt;br /&gt;
== Recording ANIMs ==&lt;br /&gt;
&lt;br /&gt;
To record an ANIM will require three bitmaps - one for creation of the next frame, and two more for a &amp;amp;quot;history&amp;amp;quot; of the previous two frames for performing the compression calculations (e.g. the delta mode calculations).&lt;br /&gt;
&lt;br /&gt;
There are five frame-to-frame compression methods currently defined.  The first three are mainly for historical interest.&lt;br /&gt;
The product Aegis VideoScape 3D utilizes the third method in version 1.0, but switched to method 5 on 2.0.  This is the only instance known of a commercial product generating ANIMs of any of the first three methods.  The fourth method is a general short or long word compression scheme which has several options including whether the compression is horizontal or vertical, and whether or not it is XOR format.  This offers a choice to the user for the optimization of file size and/or playback speed.  The fifth method is the byte vertical run length encoding as designed by Jim Kent.  Do not confuse this with Jim&#039;s RIFF file format which is different than ANIM. Here we utilized his compression/decompression routines within the ANIM file structure.&lt;br /&gt;
&lt;br /&gt;
The following paragraphs give a general outline of each of the methods of compression currently included in this spec.&lt;br /&gt;
&lt;br /&gt;
=== XOR mode ===&lt;br /&gt;
    &lt;br /&gt;
This mode is the original and is included here for historical interest.  In general, the delta modes are far superior. The creation of XOR mode is quite simple.  One simply performs an exclusive-or (XOR) between all corresponding bytes of the new frame and two frames back.  This results in a new bitmap with 0 bits wherever the two frames were identical, and 1 bits where they are different.  Then this new bitmap is saved using run-length-encoding.  A major obstacle of this mode is in the time consumed in performing the XOR upon reconstructing the image.&lt;br /&gt;
    &lt;br /&gt;
=== Long Delta mode ===&lt;br /&gt;
    &lt;br /&gt;
This mode stores the actual new frame long-words which are different, along with the offset in the bitmap.  The exact format is shown and discussed in section 2 below. Each plane is handled separately, with no data being saved if no changes take place in a given plane.  Strings of 2 or more long-words in a row which change can be run together so offsets do not have to be saved for each one.&lt;br /&gt;
&lt;br /&gt;
Constructing this data chunk usually consists of having a buffer to hold the data, and calculating the data as one compares the new frame, long-word by long-word, with two frames back.&lt;br /&gt;
   &lt;br /&gt;
=== Short Delta mode ===&lt;br /&gt;
   &lt;br /&gt;
This mode is identical to the Long Delta mode except that short-words are saved instead of long-words.  In most instances, this mode results in a smaller DLTA chunk. The Long Delta mode is mainly of interest in improving the playback speed when used on a 32-bit 68020 Turbo Amiga.&lt;br /&gt;
   &lt;br /&gt;
=== General Delta mode ===&lt;br /&gt;
&lt;br /&gt;
The above two delta compression modes were hastily put together. This mode was an attempt to provide a well-thought-out delta compression scheme.  Options provide for both short and long word compression, either vertical or horizontal compression, XOR mode (which permits reverse playback), etc.  About the time this was being finalized, the fifth mode, below, was developed by Jim Kent.  In practice the short-vertical-run-length-encoded deltas in this mode play back faster than the fifth mode (which is in essence a byte-vertical-run-length-encoded delta mode) but does not compress as well - especially for very noisy data such as digitized images.  In most cases, playback speed not being terrifically slower, the better compression (sometimes 2x) is preferable due to limited storage media in most machines.&lt;br /&gt;
&lt;br /&gt;
Details on this method are contained in section 2.2.2 below.&lt;br /&gt;
&lt;br /&gt;
=== Byte Vertical Compression ===&lt;br /&gt;
&lt;br /&gt;
This method does not offer the many options that method 4 offers, but is very successful at producing decent compression even for very noisy data such as digitized images.  The method was devised by Jim Kent and is utilized in his RIFF file format which is different than the ANIM format.  The description of this method in this document is taken from Jim&#039;s writings.  Further, he has released both compression and decompression code to public domain.&lt;br /&gt;
&lt;br /&gt;
Details on this method are contained in section 2.2.3 below.&lt;br /&gt;
&lt;br /&gt;
== Playing ANIMs ==&lt;br /&gt;
   &lt;br /&gt;
Playback of ANIMs will usually require two buffers, as mentioned above, and double-buffering between them.  The frame data from the ANIM file is used to modify the hidden frame to the next frame to be shown.  When using the XOR mode, the usual run-length-decoding routine can be easily modified to do the exclusive-or operation required.  Note that runs of zero bytes,&lt;br /&gt;
which will be very common, can be ignored, as an exclusive or of any byte value to a byte of zero will not alter the original byte value.&lt;br /&gt;
&lt;br /&gt;
The general procedure, for all compression techniques, is to first decode the initial ILBM picture into the hidden buffer and double-buffer it into view.  Then this picture is copied to the other (now hidden) buffer.  At this point each frame is displayed with the same procedure.  The next frame is formed in the hidden buffer by applying the DLTA data (or the XOR data from the BODY chunk in the case of the first XOR method) and the new frame is double-buffered into view.  This process continues to the end of the file.&lt;br /&gt;
&lt;br /&gt;
A master colormap should be kept for the entire ANIM which would be initially set from the CMAP chunk in the initial ILBM.  This colormap should be used for each frame.  If a CMAP chunk appears in one of the frames, then this master colormap is updated and the new colormap applies to all frames until the occurrance of another CMAP chunk.&lt;br /&gt;
&lt;br /&gt;
Looping ANIMs may be constructed by simply making the last two frames identical to the first two.  Since the first two frames are special cases (the first being a normal ILBM and the second being a delta from the first) one can continually loop the animation by repeating from frame three.  In this case the delta for creating frame three will modify the next to the last frame which is in the hidden buffer (which is identical to the first frame), and the delta for creating frame four will modify the last frame which is identical to the second frame.&lt;br /&gt;
&lt;br /&gt;
Multi-File ANIMs are also supported so long as the first two frames of a subsequent file are identical to the last two frames of the preceeding file.  Upon reading subsequent files, the ILBMs for the first two frames are simply ignored, and the remaining frames are simply appended to the preceding frames.  This permits splitting ANIMs across multiple floppies and also permits playing each section independently and/or editing it independent of the rest of the ANIM.&lt;br /&gt;
      &lt;br /&gt;
Timing of ANIM playback is easily achieved using the vertical blank interrupt of the Amiga.  There is an example of setting up such a timer in the SDK.  Be sure to remember the timer value when a frame is flipped up, so the next frame can be flipped up relative to that time.  This will make the playback independent of how long it takes to decompress a frame (so long as there is enough time between frames to accomplish this decompression).&lt;br /&gt;
&lt;br /&gt;
= Chunk Formats =&lt;br /&gt;
&lt;br /&gt;
== ANHD Chunk ==&lt;br /&gt;
&lt;br /&gt;
The ANHD chunk consists of the following data structure:&lt;br /&gt;
&lt;br /&gt;
; UBYTE operation&lt;br /&gt;
: The compression method:&lt;br /&gt;
:{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| 0 || set directly (normal ILBM BODY)&lt;br /&gt;
|-&lt;br /&gt;
| 1 || XOR ILBM mode&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Long Delta mode&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Short Delta mode&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Generalized short/long Delta mode&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Byte Vertical Delta mode&lt;br /&gt;
|-&lt;br /&gt;
| 6 || Stereo op 5 (third party)&lt;br /&gt;
|-&lt;br /&gt;
| 7 || short/long Vertical Delta mode&lt;br /&gt;
|-&lt;br /&gt;
| 74 (ASCII &#039;J&#039;) || reserved for Eric Graham&#039;s compression technique (details to be released later).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
; UBYTE mask&lt;br /&gt;
: (XOR mode only - plane mask where each bit is set =1 if there is data and =0 if not.)&lt;br /&gt;
&lt;br /&gt;
; UWORD w,h&lt;br /&gt;
: (XOR mode only - width and height of the area represented by the BODY to eliminate unnecessary unchanged data)&lt;br /&gt;
&lt;br /&gt;
; WORD  x,y&lt;br /&gt;
: (XOR mode only - position of rectangular area represented by the BODY)&lt;br /&gt;
&lt;br /&gt;
; ULONG abstime&lt;br /&gt;
: (currently unused - timing for a frame relative to the time the first frame was displayed - in jiffies (1/60 sec))&lt;br /&gt;
&lt;br /&gt;
; ULONG reltime&lt;br /&gt;
: (timing for frame relative to time previous frame was displayed - in jiffies (1/60 sec))&lt;br /&gt;
&lt;br /&gt;
; UBYTE interleave&lt;br /&gt;
: (unused so far - indicates how may frames back this data is to modify.  =0 defaults to indicate two frames back (for double buffering). =n indicates n frames back. The main intent here is to allow values of =1 for special applications where frame data would modify the immediately previous frame)&lt;br /&gt;
&lt;br /&gt;
; UBYTE pad0&lt;br /&gt;
: Pad byte, not used at present.&lt;br /&gt;
&lt;br /&gt;
; ULONG bits&lt;br /&gt;
: 32 option bits used by options=4 and 5. At present only 6 are identified, but the rest are set =0 so they can be used to implement future ideas. These are defined for option 4 only at this point. It is recommended that all bits be set =0 for option 5 and that any bit settings used in the future (such as for XOR mode) be compatible with the option 4 bit settings.   Player code should check undefined bits in options 4 and 5 to assure they are zero.&lt;br /&gt;
&lt;br /&gt;
: The six bits for current use are:&lt;br /&gt;
:{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! bit # !! set =0 !! set =1&lt;br /&gt;
|-&lt;br /&gt;
| 0 || short data || long data&lt;br /&gt;
|-&lt;br /&gt;
| 1 || set || XOR&lt;br /&gt;
|-&lt;br /&gt;
| 2 || separate info for each plane || one info list for all planes&lt;br /&gt;
|-&lt;br /&gt;
| 3 || not RLC || RLC (run length coded)&lt;br /&gt;
|-&lt;br /&gt;
| 4 || horizontal || vertical&lt;br /&gt;
|-&lt;br /&gt;
| 5 || short info offsets || long info offsets&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
; UBYTE pad[16]&lt;br /&gt;
: This is a pad for future use for future compression modes.&lt;br /&gt;
&lt;br /&gt;
== DLTA Chunk ==&lt;br /&gt;
      &lt;br /&gt;
This chunk is the basic data chunk used to hold delta compression data. The format of the data will be dependent upon the exact compression format selected.  At present there are two basic formats for the overall structure of this chunk.&lt;br /&gt;
&lt;br /&gt;
=== Format for methods 2 &amp;amp; 3 ===&lt;br /&gt;
&lt;br /&gt;
This chunk is a basic data chunk used to hold the delta compression data.  The minimum size of this chunk is 32 bytes as the first 8 long-words are byte pointers into the chunk for the data for each of up to 8 bit planes.  The pointer for the&lt;br /&gt;
plane data starting immediately following these 8 pointers will have a value of 32 as the data starts in the 33-rd byte of the chunk (index value of 32 due to zero-base indexing).&lt;br /&gt;
&lt;br /&gt;
The data for a given plane consists of groups of data words.  In&lt;br /&gt;
Long Delta mode, these groups consist of both short and long&lt;br /&gt;
words - short words for offsets and numbers, and long words for&lt;br /&gt;
the actual data.  In Short Delta mode, the groups are identical&lt;br /&gt;
except data words are also shorts so all data is short words.&lt;br /&gt;
Each group consists of a starting word which is an offset.  If&lt;br /&gt;
the offset is positive then it indicates the increment in long&lt;br /&gt;
or short words (whichever is appropriate) through the bit plane.&lt;br /&gt;
In other words, if you were reconstructing the plane, you would&lt;br /&gt;
start a pointer (to shorts or longs depending on the mode) to&lt;br /&gt;
point to the first word of the bit plane.  Then the offset would&lt;br /&gt;
be added to it and the following data word would be placed at&lt;br /&gt;
that position.  Then the next offset would be added to the&lt;br /&gt;
pointer and the following data word would be placed at that&lt;br /&gt;
position.  And so on...  The data terminates with an offset&lt;br /&gt;
equal to 0xFFFF.&lt;br /&gt;
&lt;br /&gt;
A second interpretation is given if the offset is negative.  In&lt;br /&gt;
that case, the absolute value is the offset+2.  Then the &lt;br /&gt;
following short-word indicates the number of data words that&lt;br /&gt;
follow.  Following that is the indicated number of contiguous&lt;br /&gt;
data words (longs or shorts depending on mode) which are to&lt;br /&gt;
be placed in contiguous locations of the bit plane.&lt;br /&gt;
&lt;br /&gt;
If there are no changed words in a given plane, then the pointer&lt;br /&gt;
in the first 32 bytes of the chunk is =0.&lt;br /&gt;
&lt;br /&gt;
=== Format for method 4 ===&lt;br /&gt;
         &lt;br /&gt;
The DLTA chunk is modified slightly to have 16 long pointers at&lt;br /&gt;
the start.  The first 8 are as before - pointers to the start of&lt;br /&gt;
the data for each of the bit planes (up to a theoretical max of 8&lt;br /&gt;
planes).  The next 8 are pointers to the start of the offset/numbers&lt;br /&gt;
data list.  If there is only one list of offset/numbers for all&lt;br /&gt;
planes, then the pointer to that list is repeated in all positions&lt;br /&gt;
so the playback code need not even be aware of it.  In fact, one&lt;br /&gt;
could get fancy and have some bit planes share lists while others&lt;br /&gt;
have different lists, or no lists (the problems in these schemes&lt;br /&gt;
lie in the generation, not in the playback).&lt;br /&gt;
&lt;br /&gt;
The best way to show the use of this format is in a sample playback&lt;br /&gt;
routine.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
   SetDLTAshort(bm,deltaword)&lt;br /&gt;
   struct BitMap *bm;&lt;br /&gt;
   WORD *deltaword;&lt;br /&gt;
   {&lt;br /&gt;
      int i;&lt;br /&gt;
      LONG *deltadata;&lt;br /&gt;
      WORD *ptr,*planeptr;&lt;br /&gt;
      register int s,size,nw;&lt;br /&gt;
      register WORD *data,*dest;&lt;br /&gt;
&lt;br /&gt;
      deltadata = (LONG *)deltaword;&lt;br /&gt;
      nw = bm-&amp;amp;gt;BytesPerRow &amp;amp;gt;&amp;amp;gt;1;&lt;br /&gt;
&lt;br /&gt;
      for (i=0;i&amp;amp;lt;bm-&amp;amp;gt;Depth;i++) {&lt;br /&gt;
         planeptr = (WORD *)(bm-&amp;amp;gt;Planes[i]);&lt;br /&gt;
         data = deltaword + deltadata[i];&lt;br /&gt;
         ptr  = deltaword + deltadata[i+8];&lt;br /&gt;
         while (*ptr != 0xFFFF) {&lt;br /&gt;
            dest = planeptr + *ptr++;&lt;br /&gt;
            size = *ptr++;&lt;br /&gt;
            if (size &amp;amp;lt; 0) {&lt;br /&gt;
               for (s=size;s&amp;amp;lt;0;s++) {&lt;br /&gt;
                  *dest = *data;&lt;br /&gt;
                  dest += nw;&lt;br /&gt;
               }&lt;br /&gt;
               data++;&lt;br /&gt;
            }&lt;br /&gt;
            else {&lt;br /&gt;
               for (s=0;s&amp;amp;lt;size;s++) {&lt;br /&gt;
                  *dest = *data++;&lt;br /&gt;
                  dest += nw;&lt;br /&gt;
               }&lt;br /&gt;
            }&lt;br /&gt;
         }&lt;br /&gt;
      }&lt;br /&gt;
      return(0);&lt;br /&gt;
   }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The above routine is for short word vertical compression with&lt;br /&gt;
run length compression.  The most efficient way to support &lt;br /&gt;
the various options is to replicate this routine and make &lt;br /&gt;
alterations for, say, long word or XOR.  The variable nw&lt;br /&gt;
indicates the number of words to skip to go down the vertical&lt;br /&gt;
column.  This one routine could easily handle horizontal&lt;br /&gt;
compression by simply setting nw=1.  For ultimate playback&lt;br /&gt;
speed, the core, at least, of this routine should be coded in&lt;br /&gt;
assembly language.&lt;br /&gt;
&lt;br /&gt;
=== Format for method 5 ===&lt;br /&gt;
&lt;br /&gt;
In this method the same 16 pointers are used as in option 4.&lt;br /&gt;
The first 8 are pointers to the data for up to 8 planes.&lt;br /&gt;
The second set of 8 are not used but were retained for several&lt;br /&gt;
reasons.  First to be somewhat compatible with code for option&lt;br /&gt;
4 (although this has not proven to be of any benefit) and &lt;br /&gt;
second, to allow extending the format for more bit planes (code&lt;br /&gt;
has been written for up to 12 planes).  &lt;br /&gt;
&lt;br /&gt;
Compression/decompression is performed on a plane-by-plane basis.&lt;br /&gt;
For each plane, compression can be handled by the skip.c code&lt;br /&gt;
(provided Public Domain by Jim Kent) and decompression can be&lt;br /&gt;
handled by unvscomp.asm (also provided Public Domain by Jim Kent).&lt;br /&gt;
&lt;br /&gt;
Compression/decompression is performed on a plane-by-plane basis.&lt;br /&gt;
The following description of the method is taken directly from&lt;br /&gt;
Jim Kent&#039;s code with minor re-wording.  Please refer to Jim&#039;s&lt;br /&gt;
code (skip.c and unvscomp.asm) for more details:&lt;br /&gt;
&lt;br /&gt;
Each column of the bit plane is compressed separately.&lt;br /&gt;
A 320x200 bit plane would have 40 columns of 200 bytes each.&lt;br /&gt;
Each column starts with an op-count followed by a number&lt;br /&gt;
of ops.  If the op-count is zero, that&#039;s OK, it just means&lt;br /&gt;
there&#039;s no change in this column from the last frame.&lt;br /&gt;
The ops are of three classes, and followed by a varying&lt;br /&gt;
amount of data depending on which class:&lt;br /&gt;
&lt;br /&gt;
# Skip ops - this is a byte with the hi bit clear that says how many rows to move the &amp;amp;quot;dest&amp;amp;quot; pointer forward, i.e. to skip. It is non-zero.&lt;br /&gt;
# Uniq ops - this is a byte with the hi bit set. The hi bit is masked down and the remainder is a count of the number of bytes of data to copy literally. It&#039;s of course followed by the data to copy.&lt;br /&gt;
# Same ops - this is a 0 byte followed by a count byte, followed by a byte value to repeat count times.&lt;br /&gt;
&lt;br /&gt;
Do bear in mind that the data is compressed vertically rather&lt;br /&gt;
than horizontally, so to get to the next byte in the destination&lt;br /&gt;
we add the number of bytes per row instead of one!&lt;br /&gt;
&lt;br /&gt;
= ANIM.op6 =&lt;br /&gt;
&lt;br /&gt;
== OpCode 6 Addition to ANIM IFF Format ==&lt;br /&gt;
&lt;br /&gt;
Stereo (3D) Animations&lt;br /&gt;
&lt;br /&gt;
Submitted by William J. Coldwell (08/23/91)&lt;br /&gt;
&lt;br /&gt;
Revision Date: 20.8.91&lt;br /&gt;
&lt;br /&gt;
Prepared by:&lt;br /&gt;
: Cryogenic Software&lt;br /&gt;
: 13045 SouthEast Stark St&lt;br /&gt;
: Suite 144&lt;br /&gt;
: Portland, OR 97233-1557&lt;br /&gt;
: Contact:  William J. Coldwell&lt;br /&gt;
&lt;br /&gt;
: Voice: (503) 254-8147 (11a-4p PDT/PST)&lt;br /&gt;
: Data: (503) 257-4823 (EMail to SYSOP)&lt;br /&gt;
: Portal: Cryogenic&lt;br /&gt;
: UUCP: uunet!m2xenix!percy!cryo!billc&lt;br /&gt;
: Internet: billc@cryo.rain.com&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
In 1989, we added support into one of our commercial products to&lt;br /&gt;
support the Haitex X-Specs glasses.  This documentation will not&lt;br /&gt;
go into a detailed description of this product.  Contact Haitex&lt;br /&gt;
for more information concerning the hardware:&lt;br /&gt;
&lt;br /&gt;
: Haitex Resources, Inc.&lt;br /&gt;
: Post Office Box 20609&lt;br /&gt;
: Charleston, SC 29413&lt;br /&gt;
: Voice: (803) 881-7518&lt;br /&gt;
: Fax: (803) 881-7522&lt;br /&gt;
: Contact: Shawn Glisson&lt;br /&gt;
&lt;br /&gt;
We found that there was not a supported way to display stereo&lt;br /&gt;
animations using the current IFF ANIM OpCode 5 specification.&lt;br /&gt;
&lt;br /&gt;
Cryogenic supported OpCode 6 as an internal format in our&lt;br /&gt;
commercial programs (see below) and provided Public Domain&lt;br /&gt;
players.  It is our intention at this time, to release this&lt;br /&gt;
format to other developers wishing to support stereo animations&lt;br /&gt;
using this OpCode.&lt;br /&gt;
&lt;br /&gt;
When we first started this project, the current Amiga machines&lt;br /&gt;
had a 512K of CHIP RAM maximum.  This caused some memory problems&lt;br /&gt;
with some of the higher resolution stereo animations, since the&lt;br /&gt;
Quad Buffers were in CHIP RAM for our players.  It was our&lt;br /&gt;
intention to attempt to do some memory magic to require only&lt;br /&gt;
two of the four bitmaps to be in CHIP RAM at one time.  It was&lt;br /&gt;
our feeling that this would have caused the animations to slow&lt;br /&gt;
down, due to data swapping that may or may not have needed to&lt;br /&gt;
be done.  By the end of 1989, all development had stopped on&lt;br /&gt;
OpCode 6.  This left all buffers in CHIP, and the format has&lt;br /&gt;
remained the same since then.&lt;br /&gt;
&lt;br /&gt;
== OpCode 6 Additions to OpCode 5 ==&lt;br /&gt;
&lt;br /&gt;
The format is exactly the same as OpCode 5 but is QUAD buffered&lt;br /&gt;
instead of DOUBLE buffered.  This allows the player to show 2&lt;br /&gt;
screens at one time for the X-Specs Glasses.  Each picture MUST&lt;br /&gt;
be viewed for 1/60th of a second, therefore to see a 3-D Picture&lt;br /&gt;
the viewer can only play ANIMs at 30 frames per second.&lt;br /&gt;
(2 pictures = 1 frame).&lt;br /&gt;
&lt;br /&gt;
The IFF file is stored exactly the same except that instead&lt;br /&gt;
of having each DLTA (delta) modify bitmap two frames back, it&lt;br /&gt;
modifies the bitmap four frames back.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 ------------------------&lt;br /&gt;
 |                      |&lt;br /&gt;
 |   BMHD               |&lt;br /&gt;
 |                      |&lt;br /&gt;
 ------------------------&lt;br /&gt;
 |   DLTA  (1)          |&lt;br /&gt;
 ------------------------&lt;br /&gt;
 |   DLTA  (2)          |&lt;br /&gt;
 ------------------------&lt;br /&gt;
 |   DLTA  (3)          |&lt;br /&gt;
 ------------------------&lt;br /&gt;
 |   DLTA  (4)          |&lt;br /&gt;
 ------------------------&lt;br /&gt;
 |   DLTA  (5)          |&lt;br /&gt;
 ------------------------&lt;br /&gt;
 |   DLTA  (6)          |&lt;br /&gt;
 ------------------------&lt;br /&gt;
            .&lt;br /&gt;
            .&lt;br /&gt;
            .&lt;br /&gt;
 ------------------------&lt;br /&gt;
 |   DLTA  (x)          |&lt;br /&gt;
 ------------------------&lt;br /&gt;
&lt;br /&gt;
== Playing OpCode 6 ANIMs ==&lt;br /&gt;
&lt;br /&gt;
Four bitmaps are allocated.  Bitmaps 1 and 3 are the left views,&lt;br /&gt;
and bitmaps 2 and 4 are the right.&lt;br /&gt;
&lt;br /&gt;
The First bitmap is gets its image from the bitmap in the file&lt;br /&gt;
(BMHD).  The Second bitmap is a copy of the first with DLTA (1)&lt;br /&gt;
performed on it.  The Third Bitmap is a copy of the first with&lt;br /&gt;
DLTA (2) performed on it.  The Fourth Bitmap is a copy of the&lt;br /&gt;
first with DLTA (3) performed on it.&lt;br /&gt;
&lt;br /&gt;
We now have the first two 3-D Pictures:&lt;br /&gt;
&lt;br /&gt;
One in bitmaps 1 and 2 and the other in bitmaps 3 and 4&lt;br /&gt;
&lt;br /&gt;
DLTA (6) is used to create the third left view from bitmap 1.&lt;br /&gt;
&lt;br /&gt;
DLTA (7) is used to create the third right view from bitmap 2.&lt;br /&gt;
&lt;br /&gt;
DLTA (8) is used to create the forth left view from bitmap 3.&lt;br /&gt;
&lt;br /&gt;
DLTA (9) is used to create the forth right view from bitmap 4.&lt;br /&gt;
&lt;br /&gt;
NOTE:  This technique requires 4 Loop frames at the end to&lt;br /&gt;
perform looping.&lt;br /&gt;
&lt;br /&gt;
== Chunk Changes ==&lt;br /&gt;
&lt;br /&gt;
In the ANHDChunk structure the only differences between OpCode&lt;br /&gt;
5 and OpCode 6 are the _Operation_ field which should be set to&lt;br /&gt;
6, and the _Interleave_ field which should be set to 4.&lt;br /&gt;
&lt;br /&gt;
== Supporting Software ==&lt;br /&gt;
&lt;br /&gt;
* 3-D Professional 1.0+ (Progressive Peripherals and Software)&lt;br /&gt;
* View 1.7 and above (Public Domain) on a Fred Fish Disk&lt;br /&gt;
* MSA: Make Stereo ANIM (internal) Available upon request.&lt;br /&gt;
* PSA: Play Stereo ANIM (internal) Available upon request.&lt;br /&gt;
&lt;br /&gt;
= ANIM.op7 =&lt;br /&gt;
&lt;br /&gt;
== Appendix for Anim7 Formats ==&lt;br /&gt;
&lt;br /&gt;
Anim7 (July 92) by:&lt;br /&gt;
: Wolfgang Hofer&lt;br /&gt;
: A-2722 Winzendorf&lt;br /&gt;
: Wr. Neustaedterstr. 140&lt;br /&gt;
&lt;br /&gt;
Anim method 7 is designed for maximum playback speed and acceptable packing rates (packing usually not as good as method 5, but more efficient than methods 1 -- 4)&lt;br /&gt;
&lt;br /&gt;
Method 7 was not originally in the IFF specification but supported by the Public Domain Programs AAP/AAC.&lt;br /&gt;
&lt;br /&gt;
== Chunk Sequence ==&lt;br /&gt;
&lt;br /&gt;
Method 7 Anims should use the same Chunk Sequence as methods 1..5. Alternatively the first frame may have a DLTA chunk instead of the BODY chunk.&lt;br /&gt;
&lt;br /&gt;
In that case the DLTA is the difference to a &#039;black frame&#039;. A player has to clear all bit planes of the first bitmap to zero, and then call his DLTA unpack routines for this frame.&lt;br /&gt;
&lt;br /&gt;
      FORM ANIM&lt;br /&gt;
      . FORM ILBM         first frame&lt;br /&gt;
      . . BMHD                normal type IFF data&lt;br /&gt;
      . . ANHD                optional animation header chunk for timing of 1st frame.&lt;br /&gt;
      . . CMAP&lt;br /&gt;
      . . { BODY | DLTA }     full picture or difference to &#039;black frame&#039;&lt;br /&gt;
      . FORM ILBM         frame 2&lt;br /&gt;
      . . ANHD                animation header chunk&lt;br /&gt;
      . . DLTA                delta mode data&lt;br /&gt;
      . . [CMAP]&lt;br /&gt;
      . FORM ILBM         frame 3&lt;br /&gt;
      . . ANHD&lt;br /&gt;
      . . DLTA&lt;br /&gt;
      . . [CMAP]&lt;br /&gt;
          ...&lt;br /&gt;
&lt;br /&gt;
The initial FORM ILBM can contain all the normal ILBM chunks, such as CRNG, etc.  The BODY will normally be a standard&lt;br /&gt;
run-length-encoded data chunk (but may be any other legal compression mode as indicated by the BMHD).  If desired, an ANHD chunk can appear here to provide timing data for the first frame.  If it is here, the operation field should be =0.&lt;br /&gt;
&lt;br /&gt;
If the initial FORM ILBM uses a DLTA chunk, the ANHD chunk must appear, and the operation field must be set to the according anim method.&lt;br /&gt;
&lt;br /&gt;
== Chunk Formats ==&lt;br /&gt;
&lt;br /&gt;
=== ANHD Chunk for method 7 ===&lt;br /&gt;
&lt;br /&gt;
The ANHD chunk consists of the following data structure:&lt;br /&gt;
&lt;br /&gt;
  UBYTE operation    The compression method=7 short/long Vertical Delta mode&lt;br /&gt;
  UBYTE mask         unused&lt;br /&gt;
  UWORD w,h          unused&lt;br /&gt;
  WORD  x,y          unused&lt;br /&gt;
  ULONG abstime      unused&lt;br /&gt;
  ULONG reltime      (timing for frame relative to time previous frame was displayed - in jiffies (1/60 sec))&lt;br /&gt;
  UBYTE interleave   = 0 (see ANHD description above)&lt;br /&gt;
  UBYTE pad0         unused&lt;br /&gt;
  ULONG bits         32 option bits used by method=4 and 5.&lt;br /&gt;
                     method 7 uses only bit #0&lt;br /&gt;
&lt;br /&gt;
                     bit #          set =0               set =1&lt;br /&gt;
                     ===============================================&lt;br /&gt;
                     0              short data           long data&lt;br /&gt;
&lt;br /&gt;
  UBYTE pad[16]       unused&lt;br /&gt;
&lt;br /&gt;
=== DLTA Chunk ===&lt;br /&gt;
&lt;br /&gt;
The DLTA Chunks of method 7 consists of&lt;br /&gt;
* 8 pointers    to opcode lists&lt;br /&gt;
* 8 pointers    to data lists&lt;br /&gt;
* data lists    (long/short)&lt;br /&gt;
* opcode lists  (bytes)&lt;br /&gt;
&lt;br /&gt;
In this method the DLTA Chunk begins with 16 pointers. The first 8 longwords are pointers to the opcode lists for up to 8 planes. The second set of 8 longwords are pointers to the corresponding data lists. If there are less than 8 Planes all unused pointers are set to zero.&lt;br /&gt;
&lt;br /&gt;
Compression/decompression is performed on a plane-by-plane basis. The following description of the method is similar to&lt;br /&gt;
Jim Kent&#039;s method 5, except that data is stored in a separated data list (long or short, depending on bit#0 of the ANHD bits) and doesn&#039;t follow immediate after the opcode.&lt;br /&gt;
&lt;br /&gt;
In method 7 the bit plane is split into vertical columns. Each column of the bit plane is compressed separately. A 320x200 bitplane would have 20 columns of 200 short datas each. (or 10 columns of 200 long datas)&lt;br /&gt;
&lt;br /&gt;
Each column starts with an op-count followed by a number of ops.  If the op-count is zero, that&#039;s OK, it just means&lt;br /&gt;
there&#039;s no change in this column from the last frame. The ops are of three classes. The ops refer to a varying&lt;br /&gt;
amount of data (to fetch from the corresponding data list) depending on which class:&lt;br /&gt;
&lt;br /&gt;
# Skip ops - this is a byte with the hi bit clear that says how many rows to move the &amp;quot;dest&amp;quot; pointer forward, i.e. to skip. It is non-zero. Skip ops have no corresponding data-items in the data list.&lt;br /&gt;
# Uniq ops - this is a byte with the hi bit set.  The hi bit is masked down and the remainder is a count of the number of data to copy literally from the data list to the &amp;quot;dest&amp;quot; pointer column. (Each data item to the next destination row) Data items may be long or short organized.&lt;br /&gt;
# Same ops - this is a 0 byte followed by a count byte. The count byte says how many rows of the current column are to be set to the same data-item. the data-item (long or short) is fetched from the data list.&lt;br /&gt;
&lt;br /&gt;
{{Note|text=Do bear in mind that the data is compressed vertically rather than horizontally, so to get to the next address in the destination we have to add the number of bytes per row instead of 2 (or 4)!}}&lt;br /&gt;
&lt;br /&gt;
= ANIM.op8 =&lt;br /&gt;
&lt;br /&gt;
== Appendix for Anim8 ==&lt;br /&gt;
&lt;br /&gt;
Joe Porkka 10-jan-92&lt;br /&gt;
&lt;br /&gt;
Anim method 8 is designed for maximum playback speed and acceptable packing rates (packing usually not as good as method 5, but more efficient than methods 1 -- 4). In addition, it is easier to convert existing Anim5 code to support Anim8 than Anim7.&lt;br /&gt;
&lt;br /&gt;
== Chunk Sequence ==&lt;br /&gt;
&lt;br /&gt;
Method 8 Anims should use the same Chunk Sequence as methods 1..5. Alternatively the first frame may have a DLTA chunk instead of the BODY chunk.&lt;br /&gt;
&lt;br /&gt;
In that case the DLTA is the difference to a &#039;black frame&#039;. A player has to clear all bit planes of the first bitmap to zero, and then call his DLTA unpack routines for this frame. The same rules about copying the first frame into both frame buffers still applies in this case.&lt;br /&gt;
&lt;br /&gt;
                   FORM ANIM&lt;br /&gt;
                   . FORM ILBM         first frame&lt;br /&gt;
                   . . BMHD                normal type IFF data&lt;br /&gt;
                   . . ANHD                optional animation header chunk for timing of 1st frame.&lt;br /&gt;
                   . . CMAP&lt;br /&gt;
                   . . { BODY | DLTA }     full picture or difference to &#039;black frame&#039;&lt;br /&gt;
                   . FORM ILBM         frame 2&lt;br /&gt;
                   . . ANHD                animation header chunk&lt;br /&gt;
                   . . DLTA                delta mode data&lt;br /&gt;
                   . . [CMAP]&lt;br /&gt;
                   . FORM ILBM         frame 3&lt;br /&gt;
                   . . ANHD&lt;br /&gt;
                   . . DLTA&lt;br /&gt;
                   . . [CMAP]&lt;br /&gt;
                        ...&lt;br /&gt;
&lt;br /&gt;
The initial FORM ILBM can contain all the normal ILBM chunks, such as CRNG, etc.  The BODY will normally be a standard run-length-encoded data chunk (but may be any other legal compression mode as indicated by the BMHD).  If desired, an ANHD chunk can appear here to provide timing data for the first frame.  If it is here, the operation field should be =0.&lt;br /&gt;
&lt;br /&gt;
If the initial FORM ILBM uses a DLTA chunk, the ANHD chunk must appear, and the operation field must be set to the&lt;br /&gt;
according anim method.&lt;br /&gt;
&lt;br /&gt;
Each of the frames from frame 2 on up may use an anhd-&amp;gt;operation of 0, 5 or 8. Note that only for the first frame in the file do you copy the image data into two buffers, not every time you get an ANHD-&amp;gt;operation==0.&lt;br /&gt;
&lt;br /&gt;
== Chunk Formats ==&lt;br /&gt;
&lt;br /&gt;
=== ANHD Chunk for method 8 ===&lt;br /&gt;
&lt;br /&gt;
The ANHD chunk consists of the following data structure:&lt;br /&gt;
&lt;br /&gt;
     UBYTE operation  The compression method=8 short/long Vertical Delta mode&lt;br /&gt;
     UBYTE mask         unused&lt;br /&gt;
     UWORD w,h          unused&lt;br /&gt;
     WORD  x,y          unused&lt;br /&gt;
     ULONG abstime      unused&lt;br /&gt;
     ULONG reltime     (timing for frame relative to time previous frame was displayed - in jiffies (1/60 sec))&lt;br /&gt;
     UBYTE interleave = 0 (see ANHD description above)&lt;br /&gt;
     UBYTE pad0         unused&lt;br /&gt;
     ULONG bits         32 option bits used by method=4 and 5.&lt;br /&gt;
                        method 8 uses only bit #0&lt;br /&gt;
                       bit #              set =0              set =1&lt;br /&gt;
                       =============================================&lt;br /&gt;
                       0              short data           long data&lt;br /&gt;
     UBYTE pad[16]       unused&lt;br /&gt;
&lt;br /&gt;
=== DLTA Chunk ===&lt;br /&gt;
&lt;br /&gt;
The DLTA Chunks of method8 consists of&lt;br /&gt;
* 16 pointers   same as in method 5&lt;br /&gt;
&lt;br /&gt;
In this method the DLTA Chunk begins with 16 pointers. The first 8 longwords are pointers to the opcode lists for up to 8&lt;br /&gt;
planes. The  second set of 8 longwords are unused.  If there are less than 8 Planes all unused pointers are set to zero.&lt;br /&gt;
&lt;br /&gt;
Compression/decompression is performed on a plane-by-plane basis. The following description of the method is similar to Jim Kent&#039;s methode 5, except that data is either in WORDs or LONGS, depending on bit 0 of the ANHD bits.&lt;br /&gt;
&lt;br /&gt;
In method 8 the bit plane is split into vertical columns. Each column of the bit plane is compressed separately. A 320x200 bit plane would have 20 columns of 200 short data each (or 10 columns of 200 long data).&lt;br /&gt;
&lt;br /&gt;
Each column of the bit plane is compressed separately.  A 320x200 bit plane would have 20 (WORD) or 10 (LONG)columns of 200 bytes each. Each column starts with an op-count followed by a number of ops.  If the op-count is zero, that&#039;s OK, it just means there&#039;s no change in this column from the last frame.  The ops are of three classes, and followed by a varying amount of data depending on which class:&lt;br /&gt;
&lt;br /&gt;
# Skip ops - this is a word or long with the hi bit clear that says how many rows to move the &amp;quot;dest&amp;quot; pointer forward, i.e. to skip. It is non-zero. Note that the range of values is much larger for word and long data, 0x7fff and 0x7fffffff.&lt;br /&gt;
# Uniq ops - this is a word or long with the hi bit set. The hi bit is masked down and the remainder is a count of the number of bytes of data to copy literally. It&#039;s of course followed by the data to copy. Note that the range of values is much larger for word and long data, 0x7fff and 0x7fffffff.&lt;br /&gt;
# Same ops - this is a 0 word or long followed by a count word or long, followed by a word or long value to repeat count times. Note that the range of values is much larger for word and long data, 0xffff and 0xffffffff.&lt;br /&gt;
&lt;br /&gt;
{{Note|text=Do bear in mind that the data is compressed vertically rather than horizontally, so to get to the next word or long in the destination we add the number of bytes per row instead of one!}}&lt;br /&gt;
&lt;br /&gt;
There is a slight complication in the case of long data. Normally an Amiga BitMap is and even number of 16bit WORDs wide, so it is possible to have an image which is not an even number or LONGs wide. For example, an image which is 336 pixels wide is 42 bytes wide, 21 words wide, and 10.5 longs wide. In the case that the data is not an even number of longs wide, and the data is to be long compressed, then the last column of data is to be word compressed instead. So, that 336 pixel wide image would be compress as 10 long columns and 1 word column.&lt;br /&gt;
&lt;br /&gt;
= ANIM.brush =&lt;br /&gt;
&lt;br /&gt;
Dpaint Anim Brush IFF Format&lt;br /&gt;
&lt;br /&gt;
From a description by the author of DPaint, Dan Silva, Electronic Arts.&lt;br /&gt;
&lt;br /&gt;
The &amp;amp;quot;Anim Brushes&amp;amp;quot; of DPaint III are saved on disk in the IFF &amp;amp;quot;ANIM&amp;amp;quot; format.  Basically, an ANIM Form consists of an initial ILBM which is the first frame of the animation, and any number of subsequent &amp;amp;quot;ILBM&amp;amp;quot;S (which aren&#039;t really ILBM&#039;s) each of which contains an ANHD animation header chunk and a DLTA chunk comprised of the encoded difference between a frame and a previous one.&lt;br /&gt;
&lt;br /&gt;
To use ANIM terminology (for a description of the ANIM format, see the IFF Anim Spec, by Gary Bonham). Anim Brushes use a &amp;amp;quot;type 5&amp;amp;quot; encoding, which is a vertical, byte-oriented delta encoding (based on Jim Kent&#039;s RIFF).  The deltas have an interleave of 1, meaning deltas are computed between adjacent frames, rather than between frames 2 apart, which is the usual ANIM custom for the purpose of fast hardware page-flipping.  Also, the deltas use Exclusive Or to allow reversable play.&lt;br /&gt;
&lt;br /&gt;
However, to my knowledge, all the existing Anim players in the Amiga world will only play type 5 &amp;amp;quot;Anim&amp;amp;quot;s which have an interleave of 0 (i.e. 2) and which use a Store operation rather than Exclusive Or, so no existing programs will read Anim Brushes anyway.  The job of modifying existing Anim readers to read Anim Brushes should be simplified, however.&lt;br /&gt;
&lt;br /&gt;
Here is an outline of the structure of the IFF Form output by DPaint III as an &amp;amp;quot;Anim Brush&amp;amp;quot;. The IFF Reader should of course be flexible enough to tolerate variation in what chunks actually appear in the initial ILBM.&lt;br /&gt;
&lt;br /&gt;
 FORM ANIM&lt;br /&gt;
     . FORM ILBM         first frame&lt;br /&gt;
     . . BMHD        &lt;br /&gt;
     . . CMAP&lt;br /&gt;
     . . DPPS&lt;br /&gt;
     . . GRAB&lt;br /&gt;
     . . CRNG&lt;br /&gt;
     . . CRNG&lt;br /&gt;
     . . CRNG&lt;br /&gt;
     . . CRNG&lt;br /&gt;
     . . CRNG&lt;br /&gt;
     . . CRNG&lt;br /&gt;
     . . DPAN     my own little chunk.&lt;br /&gt;
     . . CAMG&lt;br /&gt;
     . . BODY&lt;br /&gt;
     &lt;br /&gt;
     . FORM ILBM         frame 2&lt;br /&gt;
     . . ANHD                animation header chunk&lt;br /&gt;
     . . DLTA                delta mode data&lt;br /&gt;
     &lt;br /&gt;
     . FORM ILBM         frame 3&lt;br /&gt;
     . . ANHD                animation header chunk&lt;br /&gt;
     . . DLTA                delta mode data&lt;br /&gt;
     &lt;br /&gt;
     . FORM ILBM         frame 4&lt;br /&gt;
     . . ANHD                animation header chunk&lt;br /&gt;
     . . DLTA                delta mode data&lt;br /&gt;
     &lt;br /&gt;
     ...&lt;br /&gt;
     &lt;br /&gt;
  . FORM ILBM         frame N&lt;br /&gt;
     . . ANHD                animation header chunk&lt;br /&gt;
     . . DLTA                delta mode data&lt;br /&gt;
&lt;br /&gt;
== DPAN ==&lt;br /&gt;
&lt;br /&gt;
Here is the format of the DPAN chunk:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
 UWORD version;   /* current version=4 */&lt;br /&gt;
 UWORD nframes;   /* number of frames in the animation.*/&lt;br /&gt;
 ULONG flags;   /* Not used */&lt;br /&gt;
 } DPAnimChunk;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The version number was necessary during development. At present all I look at is &amp;amp;quot;nframes&amp;amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== ANHD ==&lt;br /&gt;
&lt;br /&gt;
Here is the ANHD chunk format:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
typedef struct {&lt;br /&gt;
 UBYTE operation;  /* =0  set directly&lt;br /&gt;
       =1  XOR ILBM mode,&lt;br /&gt;
       =2 Long Delta mode,&lt;br /&gt;
       =3 Short Delta mode&lt;br /&gt;
       =4 Generalize short/long Delta mode,&lt;br /&gt;
       =5 Byte Vertical Delta (riff)&lt;br /&gt;
       =74 (Eric Grahams compression mode)&lt;br /&gt;
   */&lt;br /&gt;
 UBYTE mask;      /* XOR ILBM only: plane mask where data is*/&lt;br /&gt;
 UWORD w,h;  &lt;br /&gt;
 WORD x,y;&lt;br /&gt;
 ULONG abstime;&lt;br /&gt;
 ULONG reltime;&lt;br /&gt;
 UBYTE interleave; /* 0 defaults to 2 */&lt;br /&gt;
 UBYTE pad0;   /* not used */&lt;br /&gt;
 ULONG bits;   /* meaning of bits:&lt;br /&gt;
     bit#    =0         =1&lt;br /&gt;
    0  short data      long data&lt;br /&gt;
    1  store         XOR&lt;br /&gt;
    2  separate info       one info for&lt;br /&gt;
      for each plane     for all planes&lt;br /&gt;
    3  not RLC    RLC (run length encoded)&lt;br /&gt;
    4  horizontal   vertical&lt;br /&gt;
    5  short info offsets long info offsets&lt;br /&gt;
   -------------------------*/&lt;br /&gt;
 UBYTE pad[16];&lt;br /&gt;
 } AnimHdr;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
for Anim Brushes, I set:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
animHdr.operation = 5;  /* RIFF encoding */&lt;br /&gt;
animHdr.interleave = 1;&lt;br /&gt;
animHdr.w = curAnimBr.bmob.pict.box.w; &lt;br /&gt;
animHdr.h = curAnimBr.bmob.pict.box.h; &lt;br /&gt;
animHdr.reltime = 1;&lt;br /&gt;
animHdr.abstime = 0;&lt;br /&gt;
animHdr.bits = 4; /* indicating XOR */&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
everything else is set to 0.&lt;br /&gt;
&lt;br /&gt;
{{Note|text=The &amp;amp;quot;bits&amp;amp;quot; field was actually intended ( by the original creator of the ANIM format, Gary Bonham of SPARTA, Inc.) for use with only with compression method 4. I am using bit 2 of the bits field to indicate the Exclusive OR operation in the context of method 5, which seems like a reasonable generalization.}}&lt;br /&gt;
&lt;br /&gt;
== DLTA ==&lt;br /&gt;
&lt;br /&gt;
For an Anim Brush with 10 frames, there will be an initial frame followed by 10 Delta&#039;s (i.e ILBMS containing ANHD and DLTA &lt;br /&gt;
chunks).  Applying the first Delta to the initial frame generates the second frame, applying the second Delta to the second frame &lt;br /&gt;
generates the third frame, etc.  Applying the last Delta thus brings back the first frame.  &lt;br /&gt;
&lt;br /&gt;
The DLTA chunk begins with 16 LONG plane offets, of which DPaint only uses the first 6 (at most).  These plane offsets are either &lt;br /&gt;
the offset (in bytes ) from the beginning of the DLTA chunk to the data for the corresponding plane, or Zero, if there was no &lt;br /&gt;
change in that plane.  Thus the first plane offset is either 0 or 64.&lt;br /&gt;
&lt;br /&gt;
(The following description of the method is based on Gary Bonham&#039;s rewording of Jim Kent&#039;s RIFF documentation.)&lt;br /&gt;
&lt;br /&gt;
Compression/decompression is performed on a plane-by-plane basis.  &lt;br /&gt;
&lt;br /&gt;
Each byte-column of the bit plane is compressed separately.  A 320x200 bit plane would have 40 columns of 200 bytes each.  In &lt;br /&gt;
general, the bit planes are always an even number of bytes wide, so for instance a 17x20 bit plane would have 4 columns of 20 &lt;br /&gt;
bytes each.&lt;br /&gt;
&lt;br /&gt;
Each column starts with an op-count followed by a number of ops.  If the op-count is zero, that&#039;s OK, it just means there&#039;s no change in this column from the last frame.  The ops are of three kinds, and followed by a varying amount of data depending on which kind:&lt;br /&gt;
&lt;br /&gt;
# SKIP - this is a byte with the hi bit clear that says how many rows to move the &amp;amp;quot;dest&amp;amp;quot; pointer forward, i.e. to skip. It is non-zero.&lt;br /&gt;
# DUMP - this is a byte with the hi bit set. The hi bit is masked off and the remainder is a count of the number of bytes of data to XOR directly. It is followed by the bytes to copy.&lt;br /&gt;
# RUN - this is a 0 byte followed by a count byte, followed by a byte value to repeat &amp;amp;quot;count&amp;amp;quot; times, XOR&#039;ing it into the destination.&lt;br /&gt;
&lt;br /&gt;
{{Note|text=Bear in mind that the data is compressed vertically rather than horizontally, so to get to the next byte in the destination you add the number of bytes per row instead of one.}}&lt;br /&gt;
&lt;br /&gt;
The Format of DLTA chunks is as described in section 2.2.2 of the Anim Spec. The encoding for type 5 is described in section 2.2.3 of the Anim Spec.&lt;/div&gt;</summary>
		<author><name>Costel Mincea</name></author>
	</entry>
	<entry>
		<id>https://wiki.amigaos.net/w/index.php?title=Window_Display_Preservation&amp;diff=12553</id>
		<title>Window Display Preservation</title>
		<link rel="alternate" type="text/html" href="https://wiki.amigaos.net/w/index.php?title=Window_Display_Preservation&amp;diff=12553"/>
		<updated>2025-01-26T19:30:48Z</updated>

		<summary type="html">&lt;p&gt;Costel Mincea: Text replacement - &amp;quot;&amp;lt;syntaxhighlight&amp;gt;&amp;quot; to &amp;quot;&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Preserving the Window Display =&lt;br /&gt;
&lt;br /&gt;
The layers library is what allows the display and manipulation of multiple overlapping rectangles, or &#039;&#039;layers&#039;&#039;. Intuition uses the layers library to manage its windows, by associating a layer to each window.&lt;br /&gt;
&lt;br /&gt;
Each window is a virtual display. When rendering, the application does not have to worry about the current size or position of its window, and what other windows might be partly or fully obscuring its window. The window&#039;s RastPort is the handle to the its virtual display space. Intuition and graphics library rendering calls will recognize that this RastPort belongs to a layer, and act accordingly.&lt;br /&gt;
&lt;br /&gt;
As windows are moved, resized, rearranged, opened, or closed, the on-screen representation changes. When part of a window which was visible now needs to appear in a new location, the layers library will move that imagery without involving the application. However, when part of a window that was previously obscured is revealed, or when a window is made larger, the imagery for the newly-visible part of the window needs to be redrawn. Intuition, through layers, offers three choices for how this is managed, trading off speed, memory usage, and application complexity.&lt;br /&gt;
&lt;br /&gt;
* The most basic type of window is called &#039;&#039;Simple Refresh&#039;&#039;. When any graphics operation takes place in this kind of window, the visible parts are updated, but rendering to the obscured parts is discarded. When the window arrangement changes to reveal a previously obscured part of such a window, the application must refresh that area.&lt;br /&gt;
&lt;br /&gt;
* Alternately, a window may be made &#039;&#039;Smart Refresh&#039;&#039;, which means that when rendering occurs, the system will not only update the visible parts of the window, but it will maintain the obscured parts as well, by using off-screen buffers. This means that when an obscured part of the window is revealed, the system will restore the imagery that belongs there. The application needs only to refresh parts of the window that appear when the window is made bigger. Smart Refresh windows use more memory than Simple Refresh windows (for the storage of obscured areas), but they are faster.&lt;br /&gt;
&lt;br /&gt;
* The third kind of window is called &#039;&#039;SuperBitMap&#039;&#039;. In such a window, the system can refresh the window even when it is sized bigger. For this to work, the application must store a complete bitmap for the window&#039;s maximum size. Such a window is more work to manage, and uses yet more memory. SuperBitMap windows are used less often than the other two types.&lt;br /&gt;
&lt;br /&gt;
Intuition helps your application manage window refresh. First, Intuition will take care of redrawing the window border and any system and application gadgets in the window. Your application never has to worry about that. Second, Intuition will notify your application when it needs to refresh its window (by sending the IDCMP_REFRESHWINDOW event). Third, Intuition provides functions that restrict your rendering to the newly-revealed (damaged) areas only, which speeds up your refresh rendering and makes it look cleaner.&lt;br /&gt;
&lt;br /&gt;
The Intuition, layers, and graphics libraries work together to make rendering into and managing windows easy. You obtain your windows through Intuition, which uses the Layers library to manage the overlapping, resizing, and re-positioning of the window layers. The layers library is responsible for identifying the areas of each window that are visible, obscured but preserved off-screen, or obscured and not preserved. The rendering functions in the graphics library and Intuition library know how to render into the multiple areas that layers library establishes.&lt;br /&gt;
&lt;br /&gt;
Note that you may not directly manipulate layers on an Intuition screen. You cannot create your own layers on an Intuition screen, nor can you use the layers movement, sizing, or arrangement functions on Intuition windows. Use the corresponding Intuition calls instead. Some other Layers library calls (such as the locking calls) are sometimes used on Intuition screens and windows.&lt;br /&gt;
&lt;br /&gt;
= Damage Regions =&lt;br /&gt;
&lt;br /&gt;
The layers library and Intuition maintain a &#039;&#039;damage region&#039;&#039; for each window, which is the part of the window whose imagery is in need of repair, or refreshing. Several things can add areas of the window to the damage region:&lt;br /&gt;
&lt;br /&gt;
* Revealing an obscured part of a Simple Refresh window adds that area to the damage region&lt;br /&gt;
* Sizing a Simple or Smart Refresh window bigger along either axis adds the new area to the damage region&lt;br /&gt;
* Resizing a Simple or Smart Refresh window (smaller or bigger) adds the old and new border areas, and the areas occupied by certain gadgets (those whose position or size depend on window size) to the damage region.&lt;br /&gt;
&lt;br /&gt;
= Refreshing Intuition Windows =&lt;br /&gt;
&lt;br /&gt;
When the user or an application performs an Intuition operation which causes damage to a window, Intuition notifies that window&#039;s application. It does this by sending a message of the class IDCMP_REFRESHWINDOW to that window&#039;s IDCMP.&lt;br /&gt;
&lt;br /&gt;
In response to this message, your application should update the damaged areas. Rendering proceeds faster and looks cleaner if it is restricted to the damaged areas only. The BeginRefresh()/EndRefresh() pair achieve that. The application should call BeginRefresh() for the window, and then do its rendering. Any rendering that would have gone into undamaged areas of the window is automatically discarded; only the area in need of repair is affected. Finally, the application should call EndRefresh(), which removes the restriction on rendering, and informs the system that the damage region has been dealt with. Even if your application intends to do no rendering, it must at least call BeginRefresh()/EndRefresh(), to inform the system that the damage region is no longer needed. If your application never needs to render in response to a refresh event, it can avoid having to call BeginRefresh()/EndRefresh() by setting the WFLG_NOCAREREFRESH flag or the WA_NoCareRefresh tag in the OpenWindowTagList() call.&lt;br /&gt;
&lt;br /&gt;
Note that by the time that your application receives notification that refresh is needed, Intuition will have already refreshed your window&#039;s border and all gadgets in the window, as needed. Thus, it is unnecessary to use any of the gadget-refreshing functions in response to an IDCMP_REFRESHWINDOW event.&lt;br /&gt;
&lt;br /&gt;
Operations performed between the BeginRefresh()/EndRefresh() pair should be restricted to simple rendering. All of the rendering functions in Intuition library and Graphics library are safe. Avoid RefreshGList() or RefreshGadgets(), or you risk deadlocking the computer. Avoid calls that may lock the LayerInfo or get complicated in Intuition, since BeginRefresh() leaves the window&#039;s layer or layers locked. Avoid AutoRequest() and EasyRequest(), and therefore all direct or indirect disk related DOS calls. See the [[Intuition_Gadgets|Intuition Gadgets]] section for more information on gadget restrictions with BeginRefresh() and EndRefresh().&lt;br /&gt;
&lt;br /&gt;
== Simple Refresh ==&lt;br /&gt;
&lt;br /&gt;
For a Simple Refresh window, only those pixels actually on-screen are maintained by the system. When part of a Simple Refresh window is obscured, the imagery that was there is lost. As well, any rendering into obscured portions of such a window is discarded.&lt;br /&gt;
&lt;br /&gt;
When part of the window is newly revealed (either because the window was just made larger, or because that part used to be obscured by another window), the application must refresh any rendering it wishes to appear into that part. The application will learn that refresh is needed because Intuition sends an IDCMP_REFRESHWINDOW event.&lt;br /&gt;
&lt;br /&gt;
== Smart Refresh ==&lt;br /&gt;
&lt;br /&gt;
If a window is of the Smart Refresh type, then the system will not only preserve those pixels which are actually on-screen, but it will save all obscured pixels that are within the current window&#039;s size. The system will refresh those parts of the window revealed by changes in the overlapping with other windows on the screen, without involving the application. However, any part of the window revealed through the sizing of the window must be redrawn by the application. Again, Intuition will notify the application through the IDCMP_REFRESHWINDOW event.&lt;br /&gt;
&lt;br /&gt;
Because the obscured areas are kept in off-screen buffers, Smart Refresh windows are refreshed faster than Simple Refresh windows are, and often without involving the application. Of course, for the same reason, they use more display memory.&lt;br /&gt;
&lt;br /&gt;
== SuperBitMap Refresh ==&lt;br /&gt;
&lt;br /&gt;
The SuperBitMap refresh type allows the application to provide and maintain bitmap memory for graphics in the window. The bitmap can be any size as long as the window sizing limits respect the maximum size of the bitmap.&lt;br /&gt;
&lt;br /&gt;
SuperBitMap windows have their own memory for maintaining all obscured parts of the window up to the size of the defined bitmap, including those parts outside of the current window. Intuition will update all parts of the window that are revealed through changes in sizing and changes in window overlapping. The application never needs to redraw portions of the window that were revealed by sizing or positioning windows in the screen.&lt;br /&gt;
&lt;br /&gt;
SuperBitMap windows require the application to allocate a bitmap for use as off-screen memory, instead of using Intuition managed buffers. This bitmap must be as large as, or larger than, the inner window&#039;s maximum dimensions (that is, the window&#039;s outside dimensions less the border sizes).&lt;br /&gt;
&lt;br /&gt;
SuperBitMap windows are almost always WFLG_GIMMEZEROZERO, which renders the borders and system gadgets in a separate bitmap. If the application wishes to create a SuperBitMap window that is not GimmeZeroZero, it must make the window borderless with no system gadgets, so that no border imagery is rendered by Intuition into the application&#039;s bitmap.&lt;br /&gt;
&lt;br /&gt;
= Intuition Refresh Events =&lt;br /&gt;
&lt;br /&gt;
When using a Simple Refresh or a Smart Refresh windows, the program may receive refresh events, informing it to update the display. See the above discussion for information on when refresh events are sent.&lt;br /&gt;
&lt;br /&gt;
A message of the class IDCMP_REFRESHWINDOW arrives at the IDCMP, informing the program of the need to update the display. The program must take some action when it receives a refresh event, even if it is just the acceptable minimum action described below.&lt;br /&gt;
&lt;br /&gt;
On receiving a refresh event, BeginRefresh() must be called, then the program should redraw its display, and, finally, call EndRefresh(). The minimum required action is to call the BeginRefresh()/EndRefresh() pair. This allows Intuition and the Layers library keep things sorted and organized.&lt;br /&gt;
&lt;br /&gt;
= Optimized Window Refreshing =&lt;br /&gt;
&lt;br /&gt;
Bracketing the display updating in the BeginRefresh()/EndRefresh() pair automatically restricts all rendering to the &amp;quot;damaged&amp;quot; areas.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
VOID BeginRefresh( struct Window *window );&lt;br /&gt;
VOID EndRefresh  ( struct Window *window, LONG complete );&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These functions makes sure that refreshing is done in the most efficient way, only redrawing those portions of the window that really need to be redrawn. The rest of the rendering commands are discarded.&lt;br /&gt;
&lt;br /&gt;
Operations performed between the BeginRefresh()/EndRefresh() pair should be restricted to simple rendering. All of the rendering functions in Intuition library and Graphics library are safe. Calls to RefreshGadgets() are not permitted. Avoid calls that may lock the LayerInfo, or get complicated in Intuition, since BeginRefresh() leaves the window&#039;s layer or layers locked. Avoid AutoRequest(), and therefore all direct or indirect disk related DOS calls. See [[Intuition_Gadgets|Intuition Gadgets]] for more information on gadget restrictions with BeginRefresh()/EndRefresh().&lt;br /&gt;
&lt;br /&gt;
Certain applications do not need to receive refresh events, and can avoid having to call BeginRefresh() and EndRefresh() by setting the WFLG_NOCAREREFRESH flag or the WA_NoCareRefresh tag in the OpenWindowTagList() call.&lt;br /&gt;
&lt;br /&gt;
The EndRefresh() function takes a boolean value as an argument (complete in the prototype above). This value determines whether refreshing is completely finished. When set to FALSE, further refreshing may be performed between subsequent BeginRefresh()/ EndRefresh() pairs. Set the boolean to TRUE for the last call to EndRefresh().&lt;br /&gt;
&lt;br /&gt;
It is critical that applications performing multiple BeginRefresh() and EndRefresh() pairs using EndRefresh(win,FALSE) hold layers locked through the entire process. The layer lock may only be released after the final call to EndRefresh(win,TRUE). See [[Layers_Library|Layers Library]] for more details.&lt;br /&gt;
&lt;br /&gt;
The procedures outlined in this section take care of refreshing what is inside the window. Another function named RefreshWindowFrame() refreshes window borders, including the title region and gadgets:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
VOID RefreshWindowFrame( struct Window *window );&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Applications can use this function to update window borders after overwriting them with graphics.&lt;br /&gt;
&lt;br /&gt;
= Setting up a SuperBitMap Window =&lt;br /&gt;
&lt;br /&gt;
SuperBitMap windows are created by setting the WFLG_SUPER_BITMAP flag, or by specifying the WA_SuperBitMap tag in the OpenWindowTagList() call. A pointer to an allocated and initialized BitMap structure must be provided.&lt;br /&gt;
&lt;br /&gt;
A SuperBitMap window requires the application to allocate and initialize its own bitmap. This entails allocating a BitMap structure, initializing the structure and allocating memory for the bit planes.&lt;br /&gt;
&lt;br /&gt;
Allocate a BitMap structure with the Exec AllocMem() function. Then use the graphics function InitBitMap() to initialize the BitMap structure:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
VOID InitBitMap( struct BitMap *bitMap, LONG depth, LONG width, LONG height );&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
InitBitMap() fills in fields in the BitMap structure describing how a linear memory area is organized as a series of one or more rectangular bit-planes.&lt;br /&gt;
&lt;br /&gt;
Once you have allocated and initialized the BitMap structure, use the graphics library function AllocRaster() to allocate the memory space for all the bit planes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
PLANEPTR AllocRaster( ULONG width, ULONG height );&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The example listed in the next section shows how to allocate a BitMap structure, initialize it with InitBitMap() and use AllocRaster() function to set up memory for the bitplanes.&lt;br /&gt;
&lt;br /&gt;
= Graphics and Layers Functions for SuperBitMap Windows =&lt;br /&gt;
&lt;br /&gt;
The portion of the bitmap showing within a SuperBitMap window is controlled by the application. Initially, the window shows the bitmap starting from its origin (0,0) and clipped to fit within the window layer. The visible portion of the bitmap can be scrolled around within the window using the layers library ScrollLayer() function:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
VOID ScrollLayer(LONG unused, struct Layer *layer, LONG dx, LONG dy)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pass this function a pointer to the window&#039;s layer in layer and the scroll offsets in dx and dy. (A pointer to the window&#039;s layer can be obtained from Window.RPort-&amp;amp;gt;Layer.)&lt;br /&gt;
&lt;br /&gt;
When rendering operations are performed in a SuperBitMap window, any rendering that falls outside window boundaries is done in the application&#039;s bitmap. Rendering that falls within window bounds is done in the screen&#039;s bitmap. Before performing an operation such as a save on the application bitmap, the graphics library function SyncSBitMap() should be called:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
VOID SyncSBitMap(struct Layer *layer)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pass this function a pointer to the window&#039;s layer. SyncSBitMap() copies the window contents to the corresponding part of the application bitmap, bringing it up to date. (If no rendering operations have been performed this call is not necessary.)&lt;br /&gt;
&lt;br /&gt;
Similarly, after making any changes to the application bitmap such as loading a new one, the window&#039;s layer should be locked and the CopySBitMap() function should be called.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
VOID CopySBitMap(struct Layer *)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This function copies the new information in the appropriate area of the underlying bitmap to the window&#039;s layer.&lt;br /&gt;
&lt;br /&gt;
For more information about bitmaps and layers, see the [[Graphics_Primitives|Graphics Primitives]] and [[Layers_Library|Layers Library]]. Also see the &amp;amp;lt;graphics/clip.h&amp;amp;gt;, &amp;amp;lt;graphics/gfx.h&amp;amp;gt;, &amp;amp;lt;graphics/layers.h &amp;amp;gt; files in the SDK.&lt;br /&gt;
&lt;br /&gt;
== SuperBitMap Window Example ==&lt;br /&gt;
&lt;br /&gt;
This example shows how to implement a superbitmap, and uses a host of Intuition facilities. Further reading of other Intuition, BOOPSI and graphics chapters may be required for a complete understanding of this example.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 **  lines.c -- Window SuperBitMap example.&lt;br /&gt;
 **&lt;br /&gt;
 **  gcc -o lines lines.c&lt;br /&gt;
 ** &lt;br /&gt;
 **/&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;dos/dos.h&amp;gt;&lt;br /&gt;
#include &amp;lt;intuition/icclass.h&amp;gt;&lt;br /&gt;
#include &amp;lt;classes/window.h&amp;gt;&lt;br /&gt;
#include &amp;lt;gadgets/scroller.h&amp;gt;&lt;br /&gt;
#include &amp;lt;gadgets/layout.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;proto/intuition.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/exec.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/utility.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/layers.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/graphics.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define WIDTH_SUPER (800)&lt;br /&gt;
#define HEIGHT_SUPER (600)&lt;br /&gt;
#define MINWIDTH (150)&lt;br /&gt;
#define MINHEIGHT (150)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define LAYERXOFFSET(x) (x-&amp;gt;RPort-&amp;gt;Layer-&amp;gt;Scroll_X)&lt;br /&gt;
#define LAYERYOFFSET(x) (x-&amp;gt;RPort-&amp;gt;Layer-&amp;gt;Scroll_Y)&lt;br /&gt;
&lt;br /&gt;
enum&lt;br /&gt;
{&lt;br /&gt;
    WID_MAIN = 0,&lt;br /&gt;
    WID_LAST&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
enum&lt;br /&gt;
{&lt;br /&gt;
    OID_MAIN = 0,&lt;br /&gt;
    OID_VPROP,&lt;br /&gt;
    OID_HPROP,&lt;br /&gt;
    OID_LAST&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
struct IntuitionIFace *IIntuition;&lt;br /&gt;
struct GraphicsIFace *IGraphics;&lt;br /&gt;
struct LayersIFace *ILayers;&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
static struct Window *windows[WID_LAST];&lt;br /&gt;
static Object *objects[OID_LAST];&lt;br /&gt;
static struct Hook idcmphook;&lt;br /&gt;
&lt;br /&gt;
/* Prototypes for our functions */&lt;br /&gt;
&lt;br /&gt;
void initBorderProps(struct Screen *screen);&lt;br /&gt;
void doNewSize();&lt;br /&gt;
void doDrawStuff();&lt;br /&gt;
void doMsgLoop();&lt;br /&gt;
void superWindow(struct Screen *screen);&lt;br /&gt;
void slideBitMap(struct Window *win, int16 dX, int16 dY);&lt;br /&gt;
&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
    struct Screen *screen;&lt;br /&gt;
&lt;br /&gt;
    struct Library *IntuitionBase = IExec-&amp;gt;OpenLibrary(&amp;quot;intuition.library&amp;quot;, 50);&lt;br /&gt;
    IIntuition = (struct IntuitionIFace *) IExec-&amp;gt;GetInterface(IntuitionBase,&lt;br /&gt;
        &amp;quot;main&amp;quot;, 1, NULL);&lt;br /&gt;
&lt;br /&gt;
    struct Library *GfxBase = IExec-&amp;gt;OpenLibrary(&amp;quot;graphics.library&amp;quot;, 50);&lt;br /&gt;
    IGraphics = (struct GraphicsIFace *) IExec-&amp;gt;GetInterface(GfxBase, &amp;quot;main&amp;quot;, 1, NULL);&lt;br /&gt;
&lt;br /&gt;
    struct Library *LayersBase = IExec-&amp;gt;OpenLibrary(&amp;quot;layers.library&amp;quot;, 50);&lt;br /&gt;
    ILayers = (struct LayersIFace *) IExec-&amp;gt;GetInterface(LayersBase, &amp;quot;main&amp;quot;, 1, NULL);&lt;br /&gt;
&lt;br /&gt;
    if (IIntuition != NULL &amp;amp;&amp;amp; IGraphics != NULL &amp;amp;&amp;amp; ILayers != NULL) {&lt;br /&gt;
        if ((screen = IIntuition-&amp;gt;LockPubScreen(NULL)) != NULL) {&lt;br /&gt;
            superWindow(screen);&lt;br /&gt;
            IIntuition-&amp;gt;UnlockPubScreen(NULL, screen);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    IExec-&amp;gt;DropInterface((struct Interface *) ILayers);&lt;br /&gt;
    IExec-&amp;gt;CloseLibrary(LayersBase);&lt;br /&gt;
&lt;br /&gt;
    IExec-&amp;gt;DropInterface((struct Interface *) IGraphics);&lt;br /&gt;
    IExec-&amp;gt;CloseLibrary(GfxBase);&lt;br /&gt;
&lt;br /&gt;
    IExec-&amp;gt;DropInterface((struct Interface *) IIntuition);&lt;br /&gt;
    IExec-&amp;gt;CloseLibrary(IntuitionBase);&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void IDCMPHook(struct Hook *hook, Object *object, struct IntuiMessage *msg)&lt;br /&gt;
{&lt;br /&gt;
    if (msg-&amp;gt;Class == IDCMP_IDCMPUPDATE) {&lt;br /&gt;
        int16 dX = 0;&lt;br /&gt;
        int16 dY = 0;&lt;br /&gt;
        int32 pos;&lt;br /&gt;
&lt;br /&gt;
        struct Window *win = windows[WID_MAIN];&lt;br /&gt;
        if (win != NULL) {&lt;br /&gt;
            uint32 gadgetid = IUtility-&amp;gt;GetTagData(GA_ID, 0, (struct TagItem *) msg-&amp;gt;IAddress);&lt;br /&gt;
            if (IIntuition-&amp;gt;GetAttr(SCROLLER_Top, objects[gadgetid], (uint32 *) &amp;amp;pos)) {&lt;br /&gt;
                switch (gadgetid) {&lt;br /&gt;
                case OID_VPROP:&lt;br /&gt;
                    dY = pos - LAYERYOFFSET(win);&lt;br /&gt;
                    break;&lt;br /&gt;
                case OID_HPROP:&lt;br /&gt;
                    dX = pos - LAYERXOFFSET(win);&lt;br /&gt;
                    break;&lt;br /&gt;
                }&lt;br /&gt;
                if (dX || dY) {&lt;br /&gt;
                    slideBitMap(win, dX, dY);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void superWindow(struct Screen *myscreen)&lt;br /&gt;
{&lt;br /&gt;
    struct BitMap *bigBitMap = IGraphics-&amp;gt;AllocBitMapTags(WIDTH_SUPER, HEIGHT_SUPER, myscreen-&amp;gt;BitMap.Depth,&lt;br /&gt;
            BMATags_Friend, myscreen-&amp;gt;BitMap, BMATags_Displayable, TRUE, BMATags_Clear, 0, TAG_END);&lt;br /&gt;
&lt;br /&gt;
    if (bigBitMap != NULL) {&lt;br /&gt;
        struct MsgPort *AppPort = IExec-&amp;gt;AllocSysObjectTags(ASOT_PORT, TAG_DONE);&lt;br /&gt;
&lt;br /&gt;
        if ( AppPort != NULL )&lt;br /&gt;
        {&lt;br /&gt;
            idcmphook.h_Entry = (uint32 (*)())IDCMPHook;&lt;br /&gt;
            idcmphook.h_SubEntry = NULL;&lt;br /&gt;
&lt;br /&gt;
            if ((objects[OID_MAIN] = IIntuition-&amp;gt;NewObject(NULL, &amp;quot;window.class&amp;quot;,&lt;br /&gt;
                WA_ScreenTitle, &amp;quot;SuperBitmap&amp;quot;,&lt;br /&gt;
                WA_Title, &amp;quot;Lines&amp;quot;,&lt;br /&gt;
                WA_Activate, TRUE,&lt;br /&gt;
                WA_DepthGadget, TRUE,&lt;br /&gt;
                WA_DragBar, TRUE,&lt;br /&gt;
                WA_CloseGadget, TRUE,&lt;br /&gt;
                WA_SizeGadget, TRUE,&lt;br /&gt;
                WA_Top, 10,&lt;br /&gt;
                WA_Left, 10,&lt;br /&gt;
                WA_MinWidth, MINWIDTH,&lt;br /&gt;
                WA_MinHeight, MINHEIGHT,&lt;br /&gt;
                WA_Width, MINWIDTH,&lt;br /&gt;
                WA_Height, MINHEIGHT,&lt;br /&gt;
                WA_IDCMP, IDCMP_NEWSIZE | IDCMP_IDCMPUPDATE,&lt;br /&gt;
                WA_PubScreen, myscreen, WA_SuperBitMap, bigBitMap,&lt;br /&gt;
                WA_NoCareRefresh, TRUE,&lt;br /&gt;
                WA_GimmeZeroZero, TRUE,     &lt;br /&gt;
                WINDOW_IDCMPHook, &amp;amp;idcmphook,&lt;br /&gt;
                WINDOW_IDCMPHookBits, IDCMP_IDCMPUPDATE,&lt;br /&gt;
                WINDOW_HorizProp, 1,&lt;br /&gt;
                WINDOW_VertProp, 1,&lt;br /&gt;
                WINDOW_AppPort, AppPort, TAG_DONE)) != NULL) {&lt;br /&gt;
                //  Open the window.&lt;br /&gt;
                if (windows[WID_MAIN] = (struct Window *) IIntuition-&amp;gt;IDoMethod(objects[OID_MAIN], WM_OPEN)) {   &lt;br /&gt;
                    /* adjust props to represent portion visible */&lt;br /&gt;
                    doNewSize();&lt;br /&gt;
                    doDrawStuff();&lt;br /&gt;
                    /* process the window, return on IDCMP_CLOSEWINDOW */&lt;br /&gt;
                    doMsgLoop();&lt;br /&gt;
                }&lt;br /&gt;
                IIntuition-&amp;gt;DisposeObject(objects[OID_MAIN]);&lt;br /&gt;
            }&lt;br /&gt;
            IExec-&amp;gt;FreeSysObject(ASOT_PORT, AppPort);&lt;br /&gt;
        }   &lt;br /&gt;
        IGraphics-&amp;gt;FreeBitMap(bigBitMap);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void slideBitMap(struct Window *win, int16 Dx, int16 Dy)&lt;br /&gt;
{&lt;br /&gt;
    ILayers-&amp;gt;ScrollLayer(0, win-&amp;gt;RPort-&amp;gt;Layer, Dx, Dy);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
** Update the prop gadgets and bitmap positioning when the size changes.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
void doNewSize()&lt;br /&gt;
{&lt;br /&gt;
    struct Window *win = windows[WID_MAIN];&lt;br /&gt;
    if (win != NULL) {&lt;br /&gt;
        IIntuition-&amp;gt;GetAttr(WINDOW_HorizObject, objects[OID_MAIN], (uint32 *) &amp;amp;objects[OID_HPROP]);&lt;br /&gt;
        if (objects[OID_HPROP]) {       &lt;br /&gt;
            if (win-&amp;gt;GZZWidth &amp;gt;= WIDTH_SUPER)&lt;br /&gt;
                slideBitMap(win, -LAYERXOFFSET(win), 0);&lt;br /&gt;
            IIntuition-&amp;gt;RefreshSetGadgetAttrs((APTR) objects[OID_HPROP], win, NULL,&lt;br /&gt;
                GA_ID, OID_HPROP,&lt;br /&gt;
                SCROLLER_Top, LAYERXOFFSET(win),&lt;br /&gt;
                SCROLLER_Total, WIDTH_SUPER,&lt;br /&gt;
                SCROLLER_Visible, win-&amp;gt;GZZWidth,&lt;br /&gt;
                ICA_TARGET, ICTARGET_IDCMP,&lt;br /&gt;
                TAG_DONE); &lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        IIntuition-&amp;gt;GetAttr(WINDOW_VertObject, objects[OID_MAIN], (uint32 *) &amp;amp;objects[OID_VPROP]);&lt;br /&gt;
        if (objects[OID_VPROP]) {&lt;br /&gt;
            if (win-&amp;gt;GZZHeight &amp;gt;= HEIGHT_SUPER)&lt;br /&gt;
                slideBitMap(win, 0, -LAYERYOFFSET(win));&lt;br /&gt;
&lt;br /&gt;
            IIntuition-&amp;gt;RefreshSetGadgetAttrs((APTR) objects[OID_VPROP], win, NULL,&lt;br /&gt;
                GA_ID, OID_VPROP,&lt;br /&gt;
                SCROLLER_Top, LAYERYOFFSET(win),&lt;br /&gt;
                SCROLLER_Total, HEIGHT_SUPER,&lt;br /&gt;
                SCROLLER_Visible, win-&amp;gt;GZZHeight,&lt;br /&gt;
                ICA_TARGET, ICTARGET_IDCMP,&lt;br /&gt;
                TAG_DONE);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int16 RangeRand(uint32 maxValue)&lt;br /&gt;
{&lt;br /&gt;
    static struct RandomState range = {0xFFFF, 0};&lt;br /&gt;
    return IUtility-&amp;gt;Random(&amp;amp;range) % maxValue;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void doDrawStuff()&lt;br /&gt;
{&lt;br /&gt;
    struct Window *win = windows[WID_MAIN];&lt;br /&gt;
    if (win != NULL) {&lt;br /&gt;
        /* clear the bitplanes */&lt;br /&gt;
        IGraphics-&amp;gt;SetRast(win-&amp;gt;RPort, 0);&lt;br /&gt;
        IGraphics-&amp;gt;SetDrMd(win-&amp;gt;RPort, JAM1);&lt;br /&gt;
        int16 x1, y1, x2, y2;&lt;br /&gt;
        int16 pen, ncolors, deltx, delty;&lt;br /&gt;
        ncolors = 1 &amp;lt;&amp;lt; win-&amp;gt;WScreen-&amp;gt;BitMap.Depth;&lt;br /&gt;
        deltx = RangeRand(6) + 2;&lt;br /&gt;
        delty = RangeRand(6) + 2;&lt;br /&gt;
        pen = RangeRand(ncolors - 1) + 1;&lt;br /&gt;
        IGraphics-&amp;gt;SetAPen(win-&amp;gt;RPort, pen);&lt;br /&gt;
        for (x1 = 0, y1 = 0, x2 = WIDTH_SUPER - 1, y2 = HEIGHT_SUPER - 1;&lt;br /&gt;
            x1 &amp;lt; WIDTH_SUPER; x1 += deltx, x2 -= deltx) {&lt;br /&gt;
            IGraphics-&amp;gt;Move(win-&amp;gt;RPort, x1, y1);&lt;br /&gt;
            IGraphics-&amp;gt;Draw(win-&amp;gt;RPort, x2, y2);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        pen = RangeRand(ncolors - 1) + 1;&lt;br /&gt;
        IGraphics-&amp;gt;SetAPen(win-&amp;gt;RPort, pen);&lt;br /&gt;
        for (x1 = 0, y1 = 0, x2 = WIDTH_SUPER - 1, y2 = HEIGHT_SUPER - 1;&lt;br /&gt;
             y1 &amp;lt; HEIGHT_SUPER; y1 += delty, y2 -= delty) {&lt;br /&gt;
            IGraphics-&amp;gt;Move(win-&amp;gt;RPort, x1, y1);&lt;br /&gt;
            IGraphics-&amp;gt;Draw(win-&amp;gt;RPort, x2, y2);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void doMsgLoop()&lt;br /&gt;
{                   &lt;br /&gt;
    uint32 signal = 0;&lt;br /&gt;
    BOOL done = FALSE;&lt;br /&gt;
    &lt;br /&gt;
    // Obtain the window wait signal mask.&lt;br /&gt;
    IIntuition-&amp;gt;GetAttr(WINDOW_SigMask, objects[OID_MAIN], &amp;amp;signal);&lt;br /&gt;
&lt;br /&gt;
    // Input Event Loop&lt;br /&gt;
    while (!done) {&lt;br /&gt;
        uint32 wait = IExec-&amp;gt;Wait(signal | SIGBREAKF_CTRL_C);&lt;br /&gt;
        if ( wait &amp;amp; SIGBREAKF_CTRL_C ) {&lt;br /&gt;
            done = TRUE;&lt;br /&gt;
            break;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if ( wait &amp;amp; signal ) {&lt;br /&gt;
            uint32 result = WMHI_LASTMSG;&lt;br /&gt;
            int16 code = 0;&lt;br /&gt;
            while ((result = IIntuition-&amp;gt;IDoMethod(objects[OID_MAIN], WM_HANDLEINPUT, &amp;amp;code)) != WMHI_LASTMSG) {&lt;br /&gt;
                switch (result &amp;amp; WMHI_CLASSMASK) {&lt;br /&gt;
                case WMHI_NEWSIZE:&lt;br /&gt;
                    doNewSize();&lt;br /&gt;
                    doDrawStuff();&lt;br /&gt;
                    break;&lt;br /&gt;
                case WMHI_CLOSEWINDOW:&lt;br /&gt;
                    windows[WID_MAIN] = NULL;&lt;br /&gt;
                    done = TRUE;&lt;br /&gt;
                    break;&lt;br /&gt;
                case WMHI_ICONIFY:&lt;br /&gt;
                    IIntuition-&amp;gt;IDoMethod(objects[OID_MAIN], WM_ICONIFY);&lt;br /&gt;
                    windows[WID_MAIN] = NULL;&lt;br /&gt;
                    break;&lt;br /&gt;
                case WMHI_UNICONIFY:&lt;br /&gt;
                    windows[WID_MAIN] = (struct Window *) IIntuition-&amp;gt;IDoMethod(objects[OID_MAIN], WM_OPEN);&lt;br /&gt;
                    doNewSize();&lt;br /&gt;
                    doDrawStuff();     &lt;br /&gt;
                    break;&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Costel Mincea</name></author>
	</entry>
	<entry>
		<id>https://wiki.amigaos.net/w/index.php?title=Graphics_Sprites,_Bobs_and_Animation&amp;diff=12552</id>
		<title>Graphics Sprites, Bobs and Animation</title>
		<link rel="alternate" type="text/html" href="https://wiki.amigaos.net/w/index.php?title=Graphics_Sprites,_Bobs_and_Animation&amp;diff=12552"/>
		<updated>2025-01-26T19:30:36Z</updated>

		<summary type="html">&lt;p&gt;Costel Mincea: Text replacement - &amp;quot;&amp;lt;syntaxhighlight&amp;gt;&amp;quot; to &amp;quot;&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{WIP}}&lt;br /&gt;
== Graphics Sprites, Bobs and Animation ==&lt;br /&gt;
&lt;br /&gt;
This article describes how to use the functions provided by the graphics library to manipulate and animate Graphic Elements (also called GELs). It is divided into six sections:&lt;br /&gt;
&lt;br /&gt;
* An overview of the GELs animation system, including fundamental terms and structures&lt;br /&gt;
* Explanation of simple (hardware) Sprites and an example showing their usage&lt;br /&gt;
* Explanation of VSprites and an example showing their usage&lt;br /&gt;
* Explanation of Bobs and an example showing their usage&lt;br /&gt;
* Discussion of topics that apply to all GELs such as collision detection and data structure extensions.&lt;br /&gt;
* Discussion of animation, using AnimComps and AnimObs and an example showing their usage&lt;br /&gt;
&lt;br /&gt;
== About the GELs System ==&lt;br /&gt;
&lt;br /&gt;
Before going into details, a quick glossary is in order. A &#039;&#039;playfield&#039;&#039; forms the background that GELs operate in. It encompasses the View, ViewPort, and RastPort data structures. (VSprites appear &#039;&#039;over&#039;&#039;, and Bobs appear &#039;&#039;in&#039;&#039; the playfield.) Playfields can be created and controlled at several levels. Refer to [[Graphics_Primitives|Graphics Primitives]] and [[Layers_Library|Layers Library]] for details on lower-level playfield control. [[Intuition_Screens|Intuition Screens]] explains how to get higher-level access to playfields.&lt;br /&gt;
&lt;br /&gt;
GELs, or graphic elements, are special graphic objects that appear in the foreground and can be moved easily around the display. They are software constructs based on the Amiga&#039;s sprite and blitter hardware. The GELs system is compatible with all playfield modes, including dual-playfield. All the various types of GELs are defined by data structures found in &amp;amp;lt;graphics/gels.h&amp;amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Types of GELs ===&lt;br /&gt;
&lt;br /&gt;
The GEL types are (in order of increasing complexity):&lt;br /&gt;
&lt;br /&gt;
; VSprites&lt;br /&gt;
: for Virtual Sprites. These are represented by the VSprite data structure and implemented with sprite hardware.&lt;br /&gt;
&lt;br /&gt;
; Bobs&lt;br /&gt;
: Blitter Objects. These are represented by the VSprite and Bob data structures and implemented with blitter hardware.&lt;br /&gt;
&lt;br /&gt;
; AnimComps&lt;br /&gt;
: Animation Components. These are represented by the VSprite, Bob and AnimComp data structures and implemented with blitter hardware.&lt;br /&gt;
&lt;br /&gt;
; AnimObjs&lt;br /&gt;
: Animation Objects. These are used to group AnimComps. They are not strictly GELs, but are described here.&lt;br /&gt;
&lt;br /&gt;
==== Simple Sprites ====&lt;br /&gt;
&lt;br /&gt;
Simple Sprites (also known as hardware sprites) are not really part of the GELs system but are the basis for VSprites. Simple Sprites are graphic objects implemented in hardware that are easy to define and easy to animate. The Amiga hardware has the ability to handle up to eight such sprite objects. Each Simple Sprite is produced by one of the Amiga&#039;s eight sprite DMA channels. They are 16-bits wide and arbitrarily tall.&lt;br /&gt;
&lt;br /&gt;
The Amiga system software offers a choice of how to use these hardware sprites. After a sprite DMA channel has displayed the last line of a Simple Sprite, the system can reuse the channel for a different sprite lower on the screen. This is how VSprites are implemented; as a software construct based on the sprite hardware.&lt;br /&gt;
&lt;br /&gt;
Hence, Simple Sprites are not really part of the animation system (they are &#039;&#039;not&#039;&#039; GELs). In fact, if Simple Sprites and GELs are used in the same display, the GELs system must be told specifically which Simple Sprites to avoid. Simple Sprites are described in this article because they are alternatives to VSprites.&lt;br /&gt;
&lt;br /&gt;
==== VSprites ====&lt;br /&gt;
&lt;br /&gt;
The VSprite, or virtual sprite, is the simplest type of GEL. The VSprite data structure contains just a bit more information than is needed to define a hardware sprite. VSprites take advantage of the system&#039;s ability to reuse sprite DMA channels - each VSprite can be temporarily assigned to a hardware sprite, as needed. This makes it appear to an application program that it has a &#039;&#039;virtually&#039;&#039; unlimited supply of VSprites.&lt;br /&gt;
&lt;br /&gt;
Since VSprites are based on hardware sprites, rules that apply to hardware sprites apply to VSprites too. VSprites are not rendered into the underlying BitMap of the playfield and so do not affect any bits in the BitMap. Because they are hardware based, &#039;&#039;they are positioned at absolute display coordinates and are not affected by the movement of screens&#039;&#039;. The starting position of a sprite must not occur before scanline 20, because of certain hardware DMA time constraints. VSprites have the same size limitations as hardware sprites, they are 16-bits wide and arbitrarily tall.&lt;br /&gt;
&lt;br /&gt;
The VSprite data structure also serves as the root structure of more complex GEL types: Bobs and AnimComps.&lt;br /&gt;
&lt;br /&gt;
==== Bobs and AnimComps ====&lt;br /&gt;
&lt;br /&gt;
Like VSprites, Bobs and AnimComps are graphics objects that make animation easier. They are rendered using the blitter. The blitter is a special Amiga hardware component used to move data quickly and efficiently, optionally performing logical operations as it does. It can be used to move any kind of data but is especially well suited to moving rectangular blocks of display data.&lt;br /&gt;
&lt;br /&gt;
It is important to keep in mind that Bobs and AnimComps are based on the blitter hardware while VSprites use the sprite hardware. However all three GEL types use the VSprite structure as their root data structure. The system uses pointers to link the VSprite, Bob and AnimComp structures, &amp;quot;extending&amp;quot; the VSprite structure to include all GEL types.&lt;br /&gt;
&lt;br /&gt;
Since Bobs and AnimComps are rendered with the blitter they actually change the underlying playfield BitMap. The BitMap area where the GEL is rendered can be saved. By moving the GEL to new locations in small increments while also saving and restoring the Bitmap as you proceed, you can create an animation effect. Bobs and AnimComps use the same coordinates as the playfield and can be any size.&lt;br /&gt;
&lt;br /&gt;
==== AnimObs ====&lt;br /&gt;
&lt;br /&gt;
The AnimOb (Animation Object) is a data structure that is used to group one or more AnimComps for convenient movement. For example, an AnimOb could be created that consists of two AnimComps, one that looks like a planet and another containing a sequence that describes orbiting moons. By moving just the AnimOb the image of the planet can be moved across the display and the moons will travel along with it, orbiting the planet the entire time. The system automatically manages the movement of all the AnimComps associated with the AnimOb.&lt;br /&gt;
&lt;br /&gt;
==== VSprites vs. Bobs ====&lt;br /&gt;
&lt;br /&gt;
If you are going to manage the movement and sequencing of GELS yourself, you need to decide if sprite animation (VSprites) or blitter animation (Bobs, AnimComps and AnimObs) best suit your needs. If you&#039;ve got simple requirements or lots of coding time, you may even opt to use only Simple Sprites, and control them yourself. On the other hand if you want the system to manage your animations, AnimComps &#039;&#039;must&#039;&#039; be used and they are Bobs at heart.&lt;br /&gt;
&lt;br /&gt;
Some fundamental differences between VSprites and Bobs are:&lt;br /&gt;
&lt;br /&gt;
* VSprite images and coordinates currently low-resolution pixels, even on a high resolution display. Bob images and coordinates have the same resolution as the playfield they are rendered into.&lt;br /&gt;
&lt;br /&gt;
* VSprites have a maximum width of 16 (low resolution) pixels. Bobs can be any width (although large Bobs tend to slow down the system). The height of either VSprites or Bobs can be as tall as the display.&lt;br /&gt;
&lt;br /&gt;
* VSprites have a maximum of three colors (Simple Sprites can have fifteen if they&#039;re attached). Because the system uses the Copper to control VSprite colors on the fly, the colors are not necessarily the same as those in the background playfield. Bobs can use any or all of the colors in the background playfield. Limiting factors include playfield resolution and display time. Bobs with more colors take longer to display.&lt;br /&gt;
&lt;br /&gt;
* VSprites are positioned using absolute display coordinates, and don&#039;t move with screens. Bobs follow screen movement.&lt;br /&gt;
&lt;br /&gt;
In general, VSprites offer speed, while Bobs offer flexibility.&lt;br /&gt;
&lt;br /&gt;
The following figure shows how the various GEL data structures, VSprites, Bobs and AnimComps are linked together.&lt;br /&gt;
&lt;br /&gt;
[[File:LibFig28-1.png|frame|center|GEL Structure Layout]]&lt;br /&gt;
&lt;br /&gt;
=== The GELs System ===&lt;br /&gt;
&lt;br /&gt;
Before you can use the GELs system, you must set up a playfield. The GELs system requires access to a View, ViewPort, and RastPort structure. These structures may be set up through the graphics library or Intuition. For most examples in this article, the Intuition library is used for this purpose.&lt;br /&gt;
&lt;br /&gt;
All GELs have a VSprite structure at their core. The system keeps track of all the GELs that it will display (the active GELs) by using a standard Exec list structure to link the VSprites. This list is accessed via the GelsInfo data structure, which in turn is associated with the RastPort. The GelsInfo structure is defined in the file &amp;amp;lt;graphics/rastport.h&amp;amp;gt;.&lt;br /&gt;
&lt;br /&gt;
A new GEL is introduced to the system by calling AddGel() to link it into the GelsInfo list. The new GEL is added immediately ahead of the first existing GEL whose &#039;&#039;x,y&#039;&#039; value is greater than or equal to that of the new GEL, always trying to keep the list sorted.&lt;br /&gt;
&lt;br /&gt;
As GELs are moved about the screen, their &#039;&#039;x,y&#039;&#039; values are constantly changing. SortGList() re-sorts this list by the &#039;&#039;x,y&#039;&#039; values. (Although this is a list of VSprite structures, bear in mind that some or all may really be Bobs or AnimComps.)&lt;br /&gt;
&lt;br /&gt;
The basic set up of the GelsInfo structure requires three important fields: sprRsrvd, gelHead and gelTail. The sprRsrvd field tells the system which hardware sprites not to use when managing true VSprites. For instance, Intuition uses sprite 0 for the mouse pointer so this hardware sprite is not available for assignment to a VSprite. The gelHead and gelTail are VSprite structures that are used to manage the list of GELs. They are never displayed. To activate or deactivate a GEL, a system call is made to add it to or delete it from this list.&lt;br /&gt;
&lt;br /&gt;
Other fields must be set up to provide for collision detection, color optimization, and other features. A complete example for setting up the GelsInfo structure is shown in the animtools.c lisitng at the end of this article.&lt;br /&gt;
&lt;br /&gt;
==== Initializing the GEL System ====&lt;br /&gt;
&lt;br /&gt;
To initialize the animation system, call the system function InitGels(). It takes the form:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct VSprite  *vsHead;&lt;br /&gt;
struct VSprite  *vsTail;&lt;br /&gt;
struct GelsInfo *gInfo;&lt;br /&gt;
&lt;br /&gt;
IGraphics-&amp;gt;InitGels(vsHead, vsTail, gInfo);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The vsHead argument is a pointer to the VSprite structure to be used as the GEL list head. (You must allocate an actual VSprite structure for vsHead to point to.) The vsTail argument is a pointer to the VSprite structure to be used as the GEL list tail. (You must allocate an actual VSprite structure for vsTail to point to.) The gInfo argument is a pointer to the GelsInfo structure to be initialized.&lt;br /&gt;
&lt;br /&gt;
InitGels() forms these structures into a linked list of GELs that is empty except for these two dummy elements (the head and tail). It gives the head VSprite the maximum negative &#039;&#039;x&#039;&#039; and &#039;&#039;y&#039;&#039; positions and the tail VSprite the maximum positive &#039;&#039;x&#039;&#039; and &#039;&#039;y&#039;&#039; positions. This is to aid the system in keeping the list sorted by &#039;&#039;x, y&#039;&#039; values, so GELs that are closer to the top and left of the display are nearer the head of the list. The memory space that the VSprites and Gelsinfo structures take up must already have been allocated. This can be done either by declaring them statically or explicitly allocating memory for them.&lt;br /&gt;
&lt;br /&gt;
Once the GelsInfo structure has been allocated and initialized, GELs can be added to the system. Refer to the setupGelSys() and cleanupGelsys() functions in the &amp;quot;animtools.c&amp;quot; lisitng at the end of the article for examples of allocating, initializing and freeing a GelsInfo structure.&lt;br /&gt;
&lt;br /&gt;
== Collisions and GEL Structure Extensions ==&lt;br /&gt;
&lt;br /&gt;
This section covers two topics that are applicable to all GELs: how to extend GEL data structures for your own purposes and how to detect collisions between GELs and other graphics objects.&lt;br /&gt;
&lt;br /&gt;
==== Detecting GEL Collisions ====&lt;br /&gt;
&lt;br /&gt;
All GELs, including VSprites, can participate in the software collision detection features of the graphics library. Simple Sprites must use &#039;&#039;hardware&#039;&#039; collision detection. See the &#039;&#039;Amiga Hardware Reference Manual&#039;&#039; for information about hardware collision detection.&lt;br /&gt;
&lt;br /&gt;
Two kinds of collisions are handled by the system routines: GEL-to-boundary hits and GEL-to-GEL hits. You can set up as many as 16 different routines to handle different collision combinations; one routine to handle the boundary hits, and up to fifteen more to handle different inter-GEL hits.&lt;br /&gt;
&lt;br /&gt;
You supply the actual collision handling routines, and provide their addresses to the system so that it can call them as needed (when the hits are detected). These addresses are kept in a collision handler table pointed to by the CollHandler field of the GelsInfo list. Which routine is called depends on the 16-bit MeMask and HitMask members of the VSprite structures involved in the collision.&lt;br /&gt;
&lt;br /&gt;
When you call DoCollision(), the system goes through the GelsInfo list which, is constantly kept sorted by &#039;&#039;x,y&#039;&#039; position. If a GEL intersects the display boundaries and the GELs HitMask indicates it is appropriate, the boundary collision routine is called. When DoCollision() finds that two GELs overlap, it compares the MeMask of one with the HitMask of the other. If corresponding bits are set in both, it calls the appropriate inter-GEL collision routine at the table position corresponding to the bits in the HitMask and MeMask, as outlined below.&lt;br /&gt;
&lt;br /&gt;
==== Preparing for Collision Detection ====&lt;br /&gt;
&lt;br /&gt;
Before you can use the system to detect collisions between GELS, you must allocate and initialize a table of collision-detection routines and place the address of the table in the GelsInfo.CollHandler field. This table is an array of pointers to the actual routines that you have provided for your collision types. You must also prepare some members of the VSprite structure: CollMask, BorderLine, HitMask, and MeMask.&lt;br /&gt;
&lt;br /&gt;
==== Building a Table of Collision Routines ====&lt;br /&gt;
&lt;br /&gt;
The collision handler table is a structure, CollTable, defined in &amp;amp;lt;graphics/gels.h&amp;amp;gt;. It is accessed as the CollHandler member of the GelsInfo structure. The table only needs to be as large as the number of bits for which you wish to provide collision processing. It is safest, though, to allocate space for all 16 entries, considering the small amount of space required.&lt;br /&gt;
&lt;br /&gt;
Call the routine SetCollision() to initialize the table entries that correspond to the HitMask and MeMask bits that you plan to use. Do not set any of the table entries directly, instead give the address to SetCollision() routine and let it handle the set up of the GelsInfo.CollTable field.&lt;br /&gt;
&lt;br /&gt;
For example, SetCollision() could be called as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
ULONG            num;&lt;br /&gt;
VOID           (*routine)();&lt;br /&gt;
struct GelsInfo *GInfo;&lt;br /&gt;
&lt;br /&gt;
VOID myCollisionRoutine(GELA, GELB)   /* sample collision routine */&lt;br /&gt;
struct VSprite *GELA;&lt;br /&gt;
struct VSprite *GELB;&lt;br /&gt;
{&lt;br /&gt;
    /* process GELs here - GELA and GELB point to the base VSprites of */&lt;br /&gt;
    /* the GELs, you can use the user extensions to identify what hit  */&lt;br /&gt;
    /* (if you need the info).                                         */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* GelsInfo must be allocated and initialized */&lt;br /&gt;
&lt;br /&gt;
routine = myCollisionRoutine;&lt;br /&gt;
&lt;br /&gt;
IGraphics-&amp;gt;SetCollision(num, routine, GInfo)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The num argument is the collision table vector number (0-15). The (*routine)() argument is a pointer to your collision routine. And the GInfo argument is a pointer to the GelsInfo structure.&lt;br /&gt;
&lt;br /&gt;
==== VSprite Collision Mask ====&lt;br /&gt;
&lt;br /&gt;
The CollMask member of the VSprite is a pointer to a memory area allocated for holding the collision mask of that GEL. This area must be in Chip memory and its size is the equivalent of one bitplane of the GEL&#039;s image. The collision mask is &#039;&#039;usually&#039;&#039; the same as the shadow mask of the GEL, formed from a logical-&#039;&#039;&#039;OR&#039;&#039;&#039; combination of all planes of the image. The following figure shows an example collision mask.&lt;br /&gt;
&lt;br /&gt;
[[File:LibFig28-3.png|frame|center|A Collision Mask]]&lt;br /&gt;
&lt;br /&gt;
Alternatively, you may have a collision mask that is not derived from the image. In this case, the actual image isn&#039;t relevant. The system will not register collisions unless the other objects touch the collision mask. If the collision mask is smaller than the image, other objects will pass through the edges without a collision.&lt;br /&gt;
&lt;br /&gt;
==== VSprite BorderLine ====&lt;br /&gt;
&lt;br /&gt;
For faster collision detection, the system uses the BorderLine member of the VSprite structure. BorderLine specifies the location of the horizontal logical-&#039;&#039;&#039;OR&#039;&#039;&#039; combination of all of the bits of the object. It may be compared to taking the whole object&#039;s shadow/collision mask and squishing it down into a single horizontal line. You provide the system with a place to store this line. The size of the data area you allocate must be at least as large as the image width.&lt;br /&gt;
&lt;br /&gt;
In other words, if it takes three 16-bit words to hold one line of a GEL, then you must reserve three words for the BorderLine. In the VSprite examples, the routine makeVSprite() correctly allocates and initializes the collision mask and borderline. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
WORD myBorderLineData[3];    /* reserve space for BorderLine for this Bob */&lt;br /&gt;
&lt;br /&gt;
myVSprite.BorderLine = myBorderLineData;   /* tell the system where it is */&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here is a sample of an object and its BorderLine image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
011000001100    Object&lt;br /&gt;
001100011000&lt;br /&gt;
001100011000&lt;br /&gt;
000110110000&lt;br /&gt;
000010100000&lt;br /&gt;
&lt;br /&gt;
011110111100    BorderLine image&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Using this squished image, the system can quickly determine if the image is touching the left or rightmost boundary of the drawing area.&lt;br /&gt;
&lt;br /&gt;
To establish default BorderLine and CollMask data, call the InitMasks() function.&lt;br /&gt;
&lt;br /&gt;
==== VSprite HitMask and MeMask ====&lt;br /&gt;
&lt;br /&gt;
Software collision detection is independently enabled and disabled for each GEL. Further, you can specify which of 16 possible collision routines you wish to have automatically executed. DoCollision(), in addition to sensing an overlap between objects, uses these masks to determine which routine (if any) the system will call when a collision occurs.&lt;br /&gt;
&lt;br /&gt;
When the system determines a collision, it performs a logical-&#039;&#039;&#039;AND&#039;&#039;&#039; of the HitMask of the upper-leftmost object in the colliding pair with the MeMask of the lower-rightmost object of the pair. The bits that are 1s after the logical-&#039;&#039;&#039;AND&#039;&#039;&#039; operation choose which one of the 16 possible collision routines to perform.&lt;br /&gt;
&lt;br /&gt;
* If the collision is with the boundary, bit 0 is always a 1 and the system calls the collision handling routine number 0. Always assign the routine that handles boundary collisions to vector 0 in the collision handling table.&lt;br /&gt;
&lt;br /&gt;
* The system uses the flag called BORDERHIT to indicate that an object has landed on or moved beyond the outermost bounds of the drawing area (the edge of the clipping region). The VSprite example earlier in this article uses collision detection to check for border hits.&lt;br /&gt;
&lt;br /&gt;
* If any one of the other bits (1 to 15) is set, then the system calls your collision handling routine corresponding to the bit set.&lt;br /&gt;
&lt;br /&gt;
* If more than one bit is set in both masks, the system calls the vector corresponding to the rightmost (the least significant) bit &#039;&#039;only&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== Using HitMask and MeMask ====&lt;br /&gt;
&lt;br /&gt;
This section illustrates the use of the HitMask and MeMask to define one type of collision.&lt;br /&gt;
&lt;br /&gt;
Suppose there are two classes of objects that you wish to control on the display: ENEMYTANK and MYMISSILE. Objects of class ENEMYTANK should be able to pass across one another without registering any collisions. Objects of class MYMISSILE should also be able to pass across one another without collisions. However, when MYMISSILE and ENEMYTANK collide, the system should generate a call to a collision routine.&lt;br /&gt;
&lt;br /&gt;
Choose a pair of collision detect bits not yet assigned within MeMask, one to represent ENEMYTANK, the other to represent MYMISSILE. You will use the same two bits in the corresponding HitMask. In this example, bit 1 represents ENEMYTANK objects and bit 2 represents MYMISSLE objects.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot;|MeMask&lt;br /&gt;
! colspan=&amp;quot;2&amp;quot;|HitMask&lt;br /&gt;
|-&lt;br /&gt;
! Bit Number !! 2 !! 1 !! 2 !! 1&lt;br /&gt;
|-&lt;br /&gt;
| ENEMYTANK 1 || align=&amp;quot;center&amp;quot;|0 || align=&amp;quot;center&amp;quot;|1 || align=&amp;quot;center&amp;quot;|1 || align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|-&lt;br /&gt;
| ENEMYTANK 2 || align=&amp;quot;center&amp;quot;|0 || align=&amp;quot;center&amp;quot;|1 || align=&amp;quot;center&amp;quot;|1 || align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|-&lt;br /&gt;
| MYMISSLE || align=&amp;quot;center&amp;quot;|1 || align=&amp;quot;center&amp;quot;|0 || align=&amp;quot;center&amp;quot;|0 || align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In the MeMask, bit 1 is set to indicate that this object is an ENEMYTANK. Bit 2 is clear (zero) indicating this object is &#039;&#039;not&#039;&#039; a MYMISSILE object. In the HitMask for ENEMYTANK objects, bit 1 is clear (zero) which means, &amp;quot;I will not register collisions with other ENEMYTANK objects.&amp;quot; However, bit 2 is set (one) which means, &amp;quot;I &#039;&#039;will&#039;&#039; register collisions with MYMISSILE objects.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Thus when a call to DoCollision() occurs, for any objects that appear to be colliding, the system &#039;&#039;&#039;AND&#039;&#039;&#039;s the MeMask of one object with the HitMask of the other object. If there are non-zero bits present, the system will call one of your collision routines.&lt;br /&gt;
&lt;br /&gt;
In this example, suppose that the system senses a collision between ENEMYTANK 1 and ENEMYTANK 2. Suppose also that ENEMYTANK 1 is the top/leftmost object of the pair. Here is the way that the collision testing routine performs the test to see if the system will call any collision-handling routines:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Bit Number !! 2 !! 1&lt;br /&gt;
|-&lt;br /&gt;
| ENEMYTANK 1 MeMask || 0 || 1&lt;br /&gt;
|-&lt;br /&gt;
| ENEMYTANK 2 HitMask || 1 || 0&lt;br /&gt;
|-&lt;br /&gt;
| Result of logical-AND || 0 || 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Therefore, the system does not call a collision routine. But suppose that DoCollision() finds an overlap between ENEMYTANK 1 and MYMISSILE, where MYMISSILE is the top/leftmost of the pair:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Bit Number !! 2 !! 1&lt;br /&gt;
|-&lt;br /&gt;
| MYMISSLE MeMask || 1 || 0&lt;br /&gt;
|-&lt;br /&gt;
| ENEMYTANK 2 HitMask || 1 || 0&lt;br /&gt;
|-&lt;br /&gt;
| Result of logical-AND || 1 || 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Therefore, the system calls the collision routine at position 2 in the table of collision-handling routines.&lt;br /&gt;
&lt;br /&gt;
=== Setting up for Boundary Collisions ===&lt;br /&gt;
&lt;br /&gt;
To specify the region in the playfield that the system will use to define the outermost limits of the GEL boundaries, you use these GelsInfo members: topmost, bottommost, leftmost, and rightmost.&lt;br /&gt;
&lt;br /&gt;
The DoCollision() routine tests these boundaries when determining boundary collisions within this RastPort. They have nothing whatsoever to do with graphical clipping. Graphical clipping makes use of the RastPort&#039;s clipping rectangle.&lt;br /&gt;
&lt;br /&gt;
Here is a typical program segment that assigns the members correctly (for boundaries 50, 100, 80, 240). It assumes that you already have a RastPort structure pointer named myRastPort.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
myRastPort-&amp;gt;GelsInfo-&amp;gt;topmost    = 50;&lt;br /&gt;
myRastPort-&amp;gt;GelsInfo-&amp;gt;bottommost = 100;&lt;br /&gt;
myRastPort-&amp;gt;GelsInfo-&amp;gt;leftmost   = 80;&lt;br /&gt;
myRastPort-&amp;gt;GelsInfo-&amp;gt;rightmost  = 240;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Parameters To Your Boundary Collision Routine ====&lt;br /&gt;
&lt;br /&gt;
During the operation of the DoCollision() routine, if you have enabled boundary collisions for a GEL (by setting the least significant bit of its HitMask) and it has crossed a boundary, the system calls the boundary routine you have defined. The system will call the routine once for every GEL that has hit, or gone outside of the boundary. The system will call your routine with the following two arguments:&lt;br /&gt;
&lt;br /&gt;
* A pointer to the VSprite structure of the GEL that hit the boundary&lt;br /&gt;
* A flag word containing one to four bits set, representing top, bottom, left and right boundaries, telling you which of the boundaries it has hit or exceeded.&lt;br /&gt;
* To test these bits, compare to the constants TOPHIT, BOTTOMHIT, LEFTHIT, and RIGHTHIT.&lt;br /&gt;
&lt;br /&gt;
See the VSprite example given earlier for an example of using boundary collision.&lt;br /&gt;
&lt;br /&gt;
==== Parameters To Your Inter-GEL Collision Routines ====&lt;br /&gt;
&lt;br /&gt;
If, instead of a GEL-to-boundary collision, DoCollision() senses a GEL-to-GEL collision, the system calls your collision routine with the following two arguments:&lt;br /&gt;
&lt;br /&gt;
* Address of the VSprite that is the uppermost (or leftmost if &#039;&#039;y&#039;&#039; coordinates are identical) GEL of a colliding pair.&lt;br /&gt;
* Address of the VSprite that is the lowermost (or rightmost if &#039;&#039;y&#039;&#039; coordinates are identical) GEL of the pair.&lt;br /&gt;
&lt;br /&gt;
==== Handling Multiple Collisions ====&lt;br /&gt;
&lt;br /&gt;
When multiple elements collide within the same display field, the following set of sequential calls to the collision routines occurs:&lt;br /&gt;
&lt;br /&gt;
* The system issues each call in a sorted order for GELs starting at the upper left-hand corner of the screen and proceeding to the right and down the screen.&lt;br /&gt;
* For any colliding GEL pair, the system issues only one call, to the collision routine for the object that is the topmost and leftmost of the pair.&lt;br /&gt;
&lt;br /&gt;
=== Adding User Extensions to GEL Data Structures ===&lt;br /&gt;
&lt;br /&gt;
This section describes how to expand the size and scope of the VSprite, Bob and AnimOb data structures. In the definition for these structures, there is an item called UserExt at the end of each. If you want to expand these structures (to hold your own special data), you define the UserExt member before the &amp;amp;lt;graphics/gels.h&amp;amp;gt; file is included. If this member has already been defined when the &amp;amp;lt;graphics/gels.h&amp;amp;gt; file is parsed, the compiler preprocessor will extend the structure definition automatically. If these members have not been defined, the system will make them SHORTs, and you may still consider these as being reserved for your private use.&lt;br /&gt;
&lt;br /&gt;
To show the kind of use you can make of this feature, the example below adds speed and acceleration figures to each GEL by extending the VSprite structure. When your collision routine is called, it could use these values to transfer energy between the two colliding objects (say, billiard balls). You would have to set up additional routines, executed between calls to DoCollision(), that would add the values to the GELs position appropriately. You could do this with code similar o the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct myInfo&lt;br /&gt;
    {&lt;br /&gt;
    short xvelocity;&lt;br /&gt;
    short yvelocity;&lt;br /&gt;
    short xaccel;&lt;br /&gt;
    short yaccel;&lt;br /&gt;
    };&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These members are for example only. You may use any definition for your user extensions. You would then also provide the following line, to extend the VSprites structure, use:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
/* Redefine VUserStuff for my own use. */&lt;br /&gt;
#define VUserStuff struct myInfo&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To extend the Bobs structure, use:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
#define BUserStuff struct myInfo&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To extend the AnimObs structure, use:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
#define AUserStuff struct myInfo&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When the system is compiling the &amp;amp;lt;graphics/gels.h&amp;amp;gt; file with your program, the compiler preprocessor substitutes &amp;quot;struct myInfo&amp;quot; everywhere that UserExt is used in the header. The structure is thereby customized to include the items you wish to associate with it.&lt;br /&gt;
&lt;br /&gt;
{{Note|title=Typedef Cannot Be Used|text=You cannot use the C-language construct typedef for the above statements. If you want to substitute your own data type for one of the UserStuff variables, you must use a #define.}}&lt;br /&gt;
&lt;br /&gt;
== Animation with GELs ==&lt;br /&gt;
&lt;br /&gt;
An animation sequence is composed of a series of drawings. Each drawing differs from the preceding one so that when they are arranged in a stack and viewed sequentially, the images appear to flow naturally.&lt;br /&gt;
&lt;br /&gt;
In classic film animation, image drawing is done in two stages. The background for each scene is painted just once. Then, the cartoon characters and any other foreground objects are painted on transparent sheets of celluloid called &#039;&#039;cells&#039;&#039; which are placed over the background. With cells, animation can be achieved by redrawing only the parts of the scene that move while the background stays the same. Animation on the Amiga works similarly. The background is formed by the playfield while the objects that move can be conveniently handled with the GELs system.&lt;br /&gt;
&lt;br /&gt;
=== Animation Data Structures ===&lt;br /&gt;
&lt;br /&gt;
There are two main data structures involved in Amiga animation: AnimComp and AnimOb.&lt;br /&gt;
&lt;br /&gt;
The AnimComp (Animation Component), is an extension of the Bob structure discussed in the previous section. An AnimComp provides a convenient way to link together a series of images so that they can be sequenced automatically, and so multiple sequences can be grouped together. An AnimComp is analogous to one sheet of celluloid representing a single image to be placed over the background.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct AnimComp&lt;br /&gt;
{&lt;br /&gt;
    WORD Flags;                 /* AnimComp flags for system &amp;amp;amp; user */&lt;br /&gt;
    WORD Timer;&lt;br /&gt;
    WORD TimeSet;&lt;br /&gt;
    struct AnimComp  *NextComp;&lt;br /&gt;
    struct AnimComp  *PrevComp;&lt;br /&gt;
    struct AnimComp  *NextSeq;&lt;br /&gt;
    struct AnimComp  *PrevSeq;&lt;br /&gt;
    WORD (*AnimCRoutine)();&lt;br /&gt;
    WORD YTrans;&lt;br /&gt;
    WORD XTrans;&lt;br /&gt;
    struct AnimOb    *HeadOb;   /* Pointer back to the controlling AnimOb     */&lt;br /&gt;
    struct Bob       *AnimBob;  /* Underlying Bob structure for this AnimComp */&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The AnimComp structure contains pointers, PrevSeq and NextSeq, that lets you group these cells into stacks that will be viewed sequentially. The AnimComp structure also has PrevComp and NextComp pointers that let you group stacks into complex objects containing multiple independently moving parts.&lt;br /&gt;
&lt;br /&gt;
The second animation data structure is the AnimOb which provides the variables needed for overall control over a group of AnimComps. The AnimOb itself contains no imagery; it simply provides a common reference point for the sequenced images and specifies how the system should move that point.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct AnimOb&lt;br /&gt;
{&lt;br /&gt;
    struct AnimOb    *NextOb, *PrevOb;&lt;br /&gt;
    LONG Clock;&lt;br /&gt;
    WORD AnOldY, AnOldX;            /* old y,x coordinates          */&lt;br /&gt;
    WORD AnY, AnX;                  /* y,x coordinates of the AnimOb*/&lt;br /&gt;
    WORD YVel, XVel;                /* velocities of this object    */&lt;br /&gt;
    WORD YAccel, XAccel;            /* accelerations of this object */&lt;br /&gt;
    WORD RingYTrans, RingXTrans;    /* ring translation values      */&lt;br /&gt;
    WORD (*AnimORoutine)();         /* address of user procedure    */&lt;br /&gt;
    struct AnimComp  *HeadComp;     /* pointer to first component   */&lt;br /&gt;
    AUserStuff AUserExt;            /* AnimOb user extension        */&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These structures can be used in various ways. A simple animation of a rotating ball could be created with three or four AnimComps linked together in a circular list by their NextSeq and PrevSeq fields. The system displays the initial AnimComp (the &amp;quot;top of the stack&amp;quot;), then switches to the AnimComp pointed to by NextSeq, and then switches to &#039;&#039;its&#039;&#039; NextSeq and so on until it reaches the end of the sequence. The sequence starts over again automatically if the last AnimComp.NextSeq points back to the first AnimComp in the stack.&lt;br /&gt;
&lt;br /&gt;
For a more complex animation of a walking human, you could use five stacks, i.e., five circular lists of AnimComps; four stacks for the arms and legs and a single stack for the head and torso. To group these stacks into one cohesive unit showing a human figure, you use the PrevComp and NextComp pointers in the AnimComp structure. All the stacks would also share a common AnimOb, so that the combined sequences can be moved as a single object.&lt;br /&gt;
&lt;br /&gt;
[[File:LibFig28-4.png|frame|center|Linking AnimComps For a Multiple Component AnimOb]]&lt;br /&gt;
&lt;br /&gt;
=== Animation Types ===&lt;br /&gt;
&lt;br /&gt;
The GELs system provides several ways of setting up automatic animation, loosely based on some categories of movement in real life. Some things (like balls or arrows) can move independently of the background, and look even more realistic if they tumble or rotate as they move; other things (like worms, wheels, and people) must be anchored to the background, or they will appear to &#039;&#039;slide&#039;&#039; unnaturally.&lt;br /&gt;
&lt;br /&gt;
The system software allows these types of animation through simple motion control, motion control with sequenced drawing, and sequenced drawing using Ring Motion Control.&lt;br /&gt;
&lt;br /&gt;
==== Simple Motion Control ====&lt;br /&gt;
&lt;br /&gt;
To produce motion of a simple object, such as a ball, the object is simply moved relative to a background display, a little at a time. This is simple motion control, and can be accomplished with one AnimComp and one AnimOb, by simply changing the AnimOb&#039;s position every N video frames. The apparent speed of the object is a combination of how often it is moved (every frame, every other frame, etc.) and how far it is moved (how much the AnimOb&#039;s AnX and AnY are changed).&lt;br /&gt;
&lt;br /&gt;
==== Sequenced Drawing ====&lt;br /&gt;
&lt;br /&gt;
To make the ball appear to rotate is a little more complex. To produce apparent movement within the image, sequencing is used. This is done by having a stack of AnimComp&#039;s that are laid down one after the other, a frame at a time. The stack can be arranged in a circular list for repeating movement. So, when you combine a sequence of drawings using AnimComps with simple motion control using an AnimOb, you can perform more complex animations such as having a rotating ball bounce around.&lt;br /&gt;
&lt;br /&gt;
==== Ring Motion Control ====&lt;br /&gt;
&lt;br /&gt;
Making a worm appear to crawl is similar to the rotating ball. There is still a stack of AnimComps that are sequenced automatically, and one controlling AnimOb. But each AnimCop image is drawn so that it appears to move relative to an internal point that remains stationary throughout the stack. So instead of the Anim&#039;s common reference point moving in each frame, you tell the system how far to move only &#039;&#039;at the end&#039;&#039; of each AnimComp sequence.&lt;br /&gt;
&lt;br /&gt;
[[File:LibFig28-5.png|frame|center|Ring Motion Control]]&lt;br /&gt;
&lt;br /&gt;
As illustrated in the figure, the sequence of events for Ring Motion Control look like this:&lt;br /&gt;
&lt;br /&gt;
Draw AnimComp1, Draw AnimComp2, Draw AnimComp3, Move AnimOb,&amp;lt;br /&amp;gt;&lt;br /&gt;
Draw AnimComp1, Draw AnimComp2, Draw AnimComp3, Move AnimOb,&amp;lt;br /&amp;gt;&lt;br /&gt;
Draw AnimComp1 ...&lt;br /&gt;
&lt;br /&gt;
=== Specifying Animation Components ===&lt;br /&gt;
&lt;br /&gt;
For each AnimComp, you initially specify:&lt;br /&gt;
&lt;br /&gt;
* A pointer to the AnimComp&#039;s controlling AnimOb.&lt;br /&gt;
* Initial and alternate views, their timing and order.&lt;br /&gt;
* The initial inter-component drawing priorities (for multiple AnimComp sequences, this specifies which sequence to display frontmost).&lt;br /&gt;
* A pointer to a special animation routine related to this component (optional).&lt;br /&gt;
* Your own extensions to this structure (optional).&lt;br /&gt;
&lt;br /&gt;
==== Sequencing AnimComps ====&lt;br /&gt;
&lt;br /&gt;
To specify the sequencing of AnimComp images, the pointers called PrevSeq and NextSeq are used to build a doubly-linked list. The sequence can be made circular (and usually is) by linking the first and last AnimComps in the sequence: the NextSeq of the last AnimComp must point back to the first AnimComp, and the PrevSeq of the first AnimComp must point to the last AnimComp. If the list is a loop, then the system will continue to cycle through the list until it is stopped. If the list is not a loop, then the program must act to restart the sequence after the last item is displayed. The AnimCRoutine field of the last AnimComp can be used to do this.&lt;br /&gt;
&lt;br /&gt;
==== Position of an AnimComp ====&lt;br /&gt;
&lt;br /&gt;
To specify the placement of each AnimComp relative to its controlling AnimOb, you set the AnimComp members XTrans and YTrans. These values can be positive or negative.&lt;br /&gt;
&lt;br /&gt;
The system is designed so that only one of the AnimComps in any given sequence is &amp;quot;active&amp;quot; (being displayed) at a given point in time. It is the only image in the sequence that is (or is about to be) linked into the GelsInfo list. The Timer determines how long each Component in the sequence remains active, as described below.&lt;br /&gt;
&lt;br /&gt;
==== Specifying Time for Each Image ====&lt;br /&gt;
&lt;br /&gt;
The AnimComp members Timer and TimeSet are used to specify how long the system should keep each sequential image on the screen.&lt;br /&gt;
&lt;br /&gt;
When the system makes an animation component active, it copies the value you have put in the TimeSet member into the Timer member. As the animation proceeds, the system decrements Timer; as long as it is greater than zero, then that AnimComp remains active. When the Timer value reaches zero, the system makes the next AnimComp in the sequence active, and the process repeats.&lt;br /&gt;
&lt;br /&gt;
If you initialize the value in TimeSet to zero, the system will &#039;&#039;not sequence this component at all&#039;&#039; (and Timer will remain zero).&lt;br /&gt;
&lt;br /&gt;
==== Linking Multiple AnimComp Sequences ====&lt;br /&gt;
&lt;br /&gt;
When an AnimOb is built from multiple AnimComp sequences, the sequences are linked together by the the PrevComp and NextComp fields of the AnimComps. These pointers must be initialized &#039;&#039;only in the initial&#039;&#039; AnimComp &#039;&#039;of each sequence&#039;&#039;. The other components that are not initially active should have their PrevComp and NextComp pointers set to NULL.&lt;br /&gt;
&lt;br /&gt;
{{Note|title=Do Not Use Empty Fields|text=You cannot store data in the empty PrevComp and NextComp fields. As the system cycles through the AnimComps, the NextComp and PrevComp fields are set to NULL when an old AnimComps is replaced by a new AnimComp. The new AnimComp is then linked in to the list of sequences &#039;&#039;in place of the old one&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
==== Component Ordering ====&lt;br /&gt;
&lt;br /&gt;
The PrevSeq, NextSeq, PrevComp and NextComp linkages have no bearing on the order in which AnimComps in any given video frame are drawn. To specify the inter-component priorities (so that the closest objects appear frontmost) the Before and After pointers in the initially active AnimComp&#039;s underlying Bob structure are linked in to the rest of the system, as described previously in the discussion of Bobs.&lt;br /&gt;
&lt;br /&gt;
This setup needs to be done once, &#039;&#039;for the initially active AnimComps of the AnimOb only&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The animation system adjusts the Before and After pointers of all the underlying Bob structures to constantly maintain the inter-component drawing sequence, even though different components are being made active as sequencing occurs.&lt;br /&gt;
&lt;br /&gt;
These pointers also assure that one complete &#039;&#039;object&#039;&#039; always has priority over another object. The Bob Before and After pointers are used to link together the last AnimComp&#039;s Bob of one AnimOb to the first AnimComp&#039;s Bob of the next AnimOb.&lt;br /&gt;
&lt;br /&gt;
=== Specifying the Animation Object ===&lt;br /&gt;
&lt;br /&gt;
For each AnimOb, you initially specify:&lt;br /&gt;
&lt;br /&gt;
* The starting position of this object&lt;br /&gt;
* Its velocity and acceleration (optional).&lt;br /&gt;
* A pointer to the first of its AnimComps.&lt;br /&gt;
* A pointer to a special animation routine related to this object (optional).&lt;br /&gt;
* Your own extensions to this structure (optional).&lt;br /&gt;
&lt;br /&gt;
==== Linking the AnimComp Sequences to the AnimOb ====&lt;br /&gt;
&lt;br /&gt;
Within each AnimOb there may be one or more AnimComp sequences. The HeadComp of the AnimOb points to the first AnimComp in the list of sequences.&lt;br /&gt;
&lt;br /&gt;
Each sequence is identified by its &amp;quot;active&amp;quot; AnimComp. There can only be one active AnimComp in each sequence. The sequences are linked together by their active AnimComps; for each of these the NextComp and PrevComp fields link the sequences together to create a list. The first sequence in the list (HeadComp of the AnimOb), has its PrevComp set to NULL. The last sequence in the list has its NextComp set to NULL. None of the inactive AnimComps should have NextComp or PrevComp fields set.&lt;br /&gt;
&lt;br /&gt;
To find the active AnimComp at run time, you can look in the AnimOb&#039;s HeadComp field. To find the active AnimComp from any another AnimComp, use the HeadOb field to find the controlling AnimOb first and then look in its HeadComp field to find the active AnimComp.&lt;br /&gt;
&lt;br /&gt;
The figure below shows all the linkages in data structures needed to create the animation GELs.&lt;br /&gt;
&lt;br /&gt;
[[File:LibFig28-6.png|frame|center|Linking of an AnimOb]]&lt;br /&gt;
&lt;br /&gt;
==== Position of an AnimOb ====&lt;br /&gt;
&lt;br /&gt;
To position the object and its component parts, use the AnimOb structure members AnX and AnY. The following figure illustrates how each component has its own offset from the AnimOb&#039;s common reference point.&lt;br /&gt;
&lt;br /&gt;
[[File:LibFig28-7.png|frame|center|Specifying an AnimOb Position]]&lt;br /&gt;
&lt;br /&gt;
When you change the animation object&#039;s AnX and AnY, all of the component parts will be redrawn relative to it the next time DrawGList() is called.&lt;br /&gt;
&lt;br /&gt;
==== Setting Up Simple Motion Control ====&lt;br /&gt;
&lt;br /&gt;
In this form of animation, you can specify objects that have independently controllable velocities and accelerations in the &#039;&#039;X&#039;&#039; and &#039;&#039;Y&#039;&#039; directions. Components can still sequence.&lt;br /&gt;
&lt;br /&gt;
The variables that control this motion are located in the AnimOb structure and are called:&lt;br /&gt;
&lt;br /&gt;
; YVel, XVel&lt;br /&gt;
: the velocities in the &#039;&#039;y&#039;&#039; and &#039;&#039;x&#039;&#039; directions. These values are added to the position values on each call to Animate() (see below).&lt;br /&gt;
&lt;br /&gt;
; YAccel, XAccel&lt;br /&gt;
: the accelerations in the &#039;&#039;x&#039;&#039; and &#039;&#039;y&#039;&#039; directions. These values are added to the velocity values on each call to Animate() (see below). The velocity values are updated &#039;&#039;before&#039;&#039; the position values.&lt;br /&gt;
&lt;br /&gt;
==== Setting Up Ring Motion Control ====&lt;br /&gt;
&lt;br /&gt;
To make a given component &#039;&#039;trigger&#039;&#039; a move of the AnimOb you set the RINGTRIGGER bit of that AnimComp&#039;s Flags field.&lt;br /&gt;
&lt;br /&gt;
When the system software encounters this flag, it adds the values of RingXTrans and RingYTrans to the AnX and AnY values of the controlling AnimOb. The &#039;&#039;next&#039;&#039; time you execute DrawGList(), the drawing sequence will use the new position.&lt;br /&gt;
&lt;br /&gt;
You usually set RINGTRIGGER in only one of the animation components in a sequence (the last one); however, you can use this flag and the translation variables any way you wish.&lt;br /&gt;
&lt;br /&gt;
==== Using Sequenced Drawing and Motion Control ====&lt;br /&gt;
&lt;br /&gt;
If you are using Ring Motion Control, you will probably set the velocity and acceleration variables to zero. For instance, consider the example of a person walking. With Ring Motion Control, as each foot falls it is positioned on the ground exactly where originally drawn. If you included a velocity value, the person&#039;s foot would not be stationary with respect to the ground, and the person would appear to &amp;quot;skate&amp;quot; rather than walk. If you set the velocity and acceleration variables at zero, you avoid this problem.&lt;br /&gt;
&lt;br /&gt;
When the system activates a new AnimComp, it checks the Flags field to see if the RINGTRIGGER bit is set. If so, the system adds RingYTrans and RingXTrans to AnY and AnX respectively.&lt;br /&gt;
&lt;br /&gt;
=== The AnimKey ===&lt;br /&gt;
&lt;br /&gt;
The system uses one pointer, known as the AnimKey, to keep track of all the AnimObs via their PrevOb and NextOb linkage fields. The AnimKey acts as the anchor for the list of AnimObs you are using and is initialized with code such as the following:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct AnimOb *animKey;&lt;br /&gt;
&lt;br /&gt;
IGraphics-&amp;gt;InitAnimate(&amp;amp;animKey);  /* Only do this once to initialize the AnimOb list */&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As each new object is added (via AddAnimOb()), it is linked in at the beginning of the list, so AnimKey will always point to the object most recently added to the list. To search forward through the list, start with the AnimKey and move forward on the NextOb link. Continue to move forward until the NextOb is NULL, indicating the end of the list. The PrevOb link will allow you to move back to a previous object.&lt;br /&gt;
&lt;br /&gt;
{{Note|title=Set Up PrevOb and NextOb Correctly|text=It is important that the NextOb link of the last object is NULL, and that the PrevOb of the first object is NULL. In fact, the system expects the animation object lists to be &#039;&#039;exactly&#039;&#039; the way that they are described above. If they are not, the system will produce unexpected results.}}&lt;br /&gt;
&lt;br /&gt;
=== Adding Animation Objects ===&lt;br /&gt;
&lt;br /&gt;
Use the routine AddAnimOb() to add animation objects to the controlled object list. This routine will link the PrevOb and NextOb pointers to chain all the AnimObs that the system is controlling.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct RastPort myRPort;&lt;br /&gt;
struct AnimOb myAnimOb;&lt;br /&gt;
struct AnimOb *animKey;  /* Must be initialized with InitAnimate() */&lt;br /&gt;
&lt;br /&gt;
IGraphics-&amp;gt;AddAnimOb(&amp;amp;myAnimOb, &amp;amp;animKey, &amp;amp;myRPort);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Moving the Objects ===&lt;br /&gt;
&lt;br /&gt;
When you have defined all of the structures and have established all of the links, you can call the Animate() routine to move the objects. Animate() adjusts the positions of the objects as described above, and calls the various subroutines (AnimCRoutines and AnimORoutines) that you have specified.&lt;br /&gt;
&lt;br /&gt;
After the system has completed the Animate() routine, some GELs may have been moved, so the GelsInfo list order may possibly be incorrect. Therefore, the list must be re-sorted with SortGList() before passing it to a system routine.&lt;br /&gt;
&lt;br /&gt;
If you are using collision detection, you then perform DoCollision(). Your collision routines may also have an effect on the relative position of the GELs. Therefore, you should again call SortGList() to assure that the system correctly orders the objects before you call DrawGList().&lt;br /&gt;
&lt;br /&gt;
When you call DrawGList(), the system renders all the GELs it finds in the GelsInfo list and any changes caused by the previous call to Animate() can then be seen.&lt;br /&gt;
&lt;br /&gt;
This is illustrated in the following typical call sequence:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct AnimOb **myAnimKey;&lt;br /&gt;
struct RastPort *rp;&lt;br /&gt;
struct ViewPort *vp;&lt;br /&gt;
&lt;br /&gt;
/* ... setup of graphics elements and objects */&lt;br /&gt;
&lt;br /&gt;
IGraphics-&amp;gt;Animate(myAnimKey, rp);       /* &amp;amp;quot;move&amp;amp;quot; objects per instructions */&lt;br /&gt;
IGraphics-&amp;gt;SortGList(rp);                /*  put them in order */&lt;br /&gt;
IGraphics-&amp;gt;DoCollision(rp);              /*  software collision detect/action */&lt;br /&gt;
IGraphics-&amp;gt;SortGList(rp);                /*  put them back into right order */&lt;br /&gt;
IGraphics-&amp;gt;DrawGList(vp, rp);            /*  draw into current RastPort */&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Your own Animation Routine Calls ====&lt;br /&gt;
&lt;br /&gt;
The AnimOb and AnimComp structures can include pointers for your own routines that you want the system to call. These pointers are stored in the AnimOb&#039;s AnimORoutine field and in the AnimComp&#039;s AnimCRoutine field, respectively.&lt;br /&gt;
&lt;br /&gt;
When Animate() is called, the system performs the following steps for every AnimOb in the AnimKey list:&lt;br /&gt;
&lt;br /&gt;
* Updates the AnimOb&#039;s location and velocities.&lt;br /&gt;
* Calls the AnimOb.AnimORoutine routine if one is supplied.&lt;br /&gt;
* Then for each AnimComp of the AnimOb:&lt;br /&gt;
** If this sequence times out, switches to the new AnimComp.&lt;br /&gt;
** Calls the AnimComp.AnimCRoutine if one is supplied.&lt;br /&gt;
** Sets the underlying VSprite&#039;s &#039;&#039;x,y&#039;&#039; coordinates.&lt;br /&gt;
&lt;br /&gt;
If you want a routine to be called, you put the address of the routine in either AnimComp.AnimCRoutine or AnimOb.AnimORoutine member as needed. If no routine is to be called, you must set these fields to NULL. Your routines will be passed one parameter, a pointer to the AnimOb or AnimComp it was related to. You can use the user structure extensions discussed earlier to hold the variables you need for your own routines.&lt;br /&gt;
&lt;br /&gt;
For example, if you provide a routine such as this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
VOID MyOCode(struct AnimOb *anOb)&lt;br /&gt;
{&lt;br /&gt;
/* whatever needs to be done */&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then, if you put the address of the routine in an AnimOb structure:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
myAnimOb.AnimORoutine = MyOCode;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MyOCode() will be called with the address of this AnimOb when Animate() processes this AnimOb.&lt;br /&gt;
&lt;br /&gt;
=== Standard GEL Rules Still Apply ===&lt;br /&gt;
&lt;br /&gt;
Before you use the animation system, you must have called the routine InitGels(). The section called &amp;quot;Bob Priorities&amp;quot; describes how the system maintains the list of GELs to draw on the screen according to their various data fields. The animation system selectively adds GELs to and removes GELs from this list of screen objects during the Animate() routine. On the next call to DrawGList(), the system will draw the GELs in the list into the selected RastPort.&lt;br /&gt;
&lt;br /&gt;
=== Animations Special Numbering System ===&lt;br /&gt;
&lt;br /&gt;
Velocities and accelerations can be either positive or negative. The system treats the velocity, acceleration and Ring values as fixed-point binary fractions, with the decimal point at position 6 in the word. That is: vvvvvvvvvv.ffffff where v stands for actual values that you add to the x or y (AnX, AnY) positions of the object for each call to Animate(), and f stands for the fractional part. By using a fractional part, you can specify the speed of an object in increments as precise as 1/64th of an interval.&lt;br /&gt;
&lt;br /&gt;
If you set the value of XVel at 0x0001, it will take 64 calls to the Animate() routine before the system will modify the object&#039;s &#039;&#039;x&#039;&#039; coordinate position by a step of one.&lt;br /&gt;
&lt;br /&gt;
The system constant ANFRACSIZE can be used to shift values correctly. So if you set the value to (1 &amp;lt;&amp;lt; ANFRACSIZE), it will be set to 0x0040, the value required to move the object one step per call to Animate().&lt;br /&gt;
&lt;br /&gt;
The system constant ANIMHALF can be used if you want the object to move every other call to Animate().&lt;br /&gt;
&lt;br /&gt;
Each call you make to Animate() simply adds the value of XAccel to the current value of XVel, and YAccel to the current value of YVel, modifying these values accordingly.&lt;br /&gt;
&lt;br /&gt;
=== &amp;quot;animtools.h&amp;quot; and &amp;quot;animtools.c&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
Here is the listing of the &amp;quot;animtools.h&amp;quot; header file and the &amp;quot;animtools.c&amp;quot; link file used by the examples in this article. The makeSeq() and makeComp() subroutines here demonstrate how to use the GELs animation system.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* animtools.h */&lt;br /&gt;
#ifndef GELTOOLS_H&lt;br /&gt;
#define GELTOOLS_H&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
** These data structures are used by the functions in animtools.c to&lt;br /&gt;
** allow for an easier interface to the animation system.&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
/* Data structure to hold information for a new VSprite.                */&lt;br /&gt;
typedef struct newVSprite {&lt;br /&gt;
        WORD           *nvs_Image;      /* image data for the vsprite   */&lt;br /&gt;
        WORD           *nvs_ColorSet;   /* color array for the vsprite  */&lt;br /&gt;
        SHORT           nvs_WordWidth;  /* width in words               */&lt;br /&gt;
        SHORT           nvs_LineHeight; /* height in lines              */&lt;br /&gt;
        SHORT           nvs_ImageDepth; /* depth of the image           */&lt;br /&gt;
        SHORT           nvs_X;          /* initial x position           */&lt;br /&gt;
        SHORT           nvs_Y;          /* initial y position           */&lt;br /&gt;
        SHORT           nvs_Flags;      /* vsprite flags                */&lt;br /&gt;
        USHORT          nvs_HitMask;    /* Hit mask.                    */&lt;br /&gt;
        USHORT          nvs_MeMask;     /* Me mask.                     */&lt;br /&gt;
        } NEWVSPRITE;&lt;br /&gt;
&lt;br /&gt;
/* Data structure to hold information for a new Bob.                */&lt;br /&gt;
typedef struct newBob {&lt;br /&gt;
        WORD       *nb_Image;       /* image data for the bob       */&lt;br /&gt;
        SHORT       nb_WordWidth;   /* width in words               */&lt;br /&gt;
        SHORT       nb_LineHeight;  /* height in lines              */&lt;br /&gt;
        SHORT       nb_ImageDepth;  /* depth of the image           */&lt;br /&gt;
        SHORT       nb_PlanePick;   /* planes that get image data   */&lt;br /&gt;
        SHORT       nb_PlaneOnOff;  /* unused planes to turn on     */&lt;br /&gt;
        SHORT       nb_BFlags;      /* bob flags                    */&lt;br /&gt;
        SHORT       nb_DBuf;        /* 1=double buf, 0=not          */&lt;br /&gt;
        SHORT       nb_RasDepth;    /* depth of the raster          */&lt;br /&gt;
        SHORT       nb_X;           /* initial x position           */&lt;br /&gt;
        SHORT       nb_Y;           /* initial y position           */&lt;br /&gt;
        USHORT      nb_HitMask;     /* Hit mask.                    */&lt;br /&gt;
        USHORT      nb_MeMask;      /* Me mask.                     */&lt;br /&gt;
        } NEWBOB ;&lt;br /&gt;
&lt;br /&gt;
/* Data structure to hold information for a new animation component.       */&lt;br /&gt;
typedef struct newAnimComp {&lt;br /&gt;
        WORD  (*nac_Routine)(); /* routine called when Comp is displayed.   */&lt;br /&gt;
        SHORT   nac_Xt;         /* initial delta offset position.           */&lt;br /&gt;
        SHORT   nac_Yt;         /* initial delta offset position.           */&lt;br /&gt;
        SHORT   nac_Time;       /* Initial Timer value.                     */&lt;br /&gt;
        SHORT   nac_CFlags;     /* Flags for the Component.                 */&lt;br /&gt;
        } NEWANIMCOMP;&lt;br /&gt;
&lt;br /&gt;
/* Data structure to hold information for a new animation sequence.         */&lt;br /&gt;
typedef struct newAnimSeq {&lt;br /&gt;
        struct AnimOb  *nas_HeadOb; /* common Head of Object.               */&lt;br /&gt;
        WORD   *nas_Images;         /* array of Comp image data             */&lt;br /&gt;
        SHORT  *nas_Xt;             /* arrays of initial offsets.           */&lt;br /&gt;
        SHORT  *nas_Yt;             /* arrays of initial offsets.           */&lt;br /&gt;
        SHORT  *nas_Times;          /* array of Initial Timer value.        */&lt;br /&gt;
        WORD (**nas_Routines)();    /* Array of fns called when comp drawn  */&lt;br /&gt;
        SHORT   nas_CFlags;         /* Flags for the Component.             */&lt;br /&gt;
        SHORT   nas_Count;          /* Num Comps in seq (= arrays size)     */&lt;br /&gt;
        SHORT   nas_SingleImage;    /* one (or count) images.               */&lt;br /&gt;
        } NEWANIMSEQ;&lt;br /&gt;
&lt;br /&gt;
#define INTUITIONNAME &amp;amp;quot;intuition.library&amp;amp;quot; /* intuitionbase.h does not define a library name. */&lt;br /&gt;
&lt;br /&gt;
#include &amp;amp;quot;animtools_proto.h&amp;amp;quot;              /* Include Prototyping. */&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/* animtools_proto.h */&lt;br /&gt;
#include        &amp;amp;lt;clib/dos_protos.h&amp;amp;gt;&lt;br /&gt;
#include        &amp;amp;lt;clib/exec_protos.h&amp;amp;gt;&lt;br /&gt;
#include        &amp;amp;lt;clib/graphics_protos.h&amp;amp;gt;&lt;br /&gt;
#include        &amp;amp;lt;clib/intuition_protos.h&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
struct GelsInfo *setupGelSys(struct RastPort *rPort, BYTE reserved);&lt;br /&gt;
VOID            cleanupGelSys(struct GelsInfo *gInfo, struct RastPort *rPort);&lt;br /&gt;
struct VSprite  *makeVSprite(NEWVSPRITE *nVSprite);&lt;br /&gt;
struct Bob      *makeBob(NEWBOB *nBob);&lt;br /&gt;
struct AnimComp *makeComp(NEWBOB *nBob, NEWANIMCOMP *nAnimComp);&lt;br /&gt;
struct AnimComp *makeSeq(NEWBOB *nBob, NEWANIMSEQ *nAnimSeq);&lt;br /&gt;
VOID            freeVSprite(struct VSprite *vsprite);&lt;br /&gt;
VOID            freeBob(struct Bob *bob, LONG rasdepth);&lt;br /&gt;
VOID            freeComp(struct AnimComp *myComp, LONG rasdepth);&lt;br /&gt;
VOID            freeSeq(struct AnimComp *headComp, LONG rasdepth);&lt;br /&gt;
VOID            freeOb(struct AnimOb *headOb, LONG rasdepth);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/* animtools.c&lt;br /&gt;
**&lt;br /&gt;
** This file is a collection of tools which are used with the VSprite, Bob and Animation&lt;br /&gt;
** system software. It is intended as a useful EXAMPLE, and while it shows what must be&lt;br /&gt;
** done, it is not the only way to do it.  If Not Enough Memory, or error return, each&lt;br /&gt;
** cleans up after itself before returning.  NOTE that these routines assume a very specific&lt;br /&gt;
** structure to the GEL lists.  Make sure that you use the correct pairs together&lt;br /&gt;
** (i.e. makeOb()/freeOb(), etc.)&lt;br /&gt;
**&lt;br /&gt;
** Compile with SAS/C 5.10b: lc -b1 -cfist -v -y -oanimtools.o animtools.c&lt;br /&gt;
*/&lt;br /&gt;
#include &amp;amp;lt;exec/types.h&amp;amp;gt;&lt;br /&gt;
#include &amp;amp;lt;exec/memory.h&amp;amp;gt;&lt;br /&gt;
#include &amp;amp;lt;graphics/gfx.h&amp;amp;gt;&lt;br /&gt;
#include &amp;amp;lt;graphics/gels.h&amp;amp;gt;&lt;br /&gt;
#include &amp;amp;lt;graphics/clip.h&amp;amp;gt;&lt;br /&gt;
#include &amp;amp;lt;graphics/rastport.h&amp;amp;gt;&lt;br /&gt;
#include &amp;amp;lt;graphics/view.h&amp;amp;gt;&lt;br /&gt;
#include &amp;amp;lt;graphics/gfxbase.h&amp;amp;gt;&lt;br /&gt;
#include &amp;amp;quot;animtools.h&amp;amp;quot;&lt;br /&gt;
&lt;br /&gt;
/* Setup the GELs system.  After this call is made you can use VSprites, Bobs, AnimComps&lt;br /&gt;
** and AnimObs.  Note that this links the GelsInfo structure into the RastPort, and calls&lt;br /&gt;
** InitGels().  It uses information in your RastPort structure to establish boundary collision&lt;br /&gt;
** defaults at the outer edges of the raster.  This routine sets up for everything - collision&lt;br /&gt;
** detection and all. You must already have run LoadView before ReadyGelSys is called.&lt;br /&gt;
*/&lt;br /&gt;
struct GelsInfo *setupGelSys(struct RastPort *rPort, BYTE reserved)&lt;br /&gt;
{&lt;br /&gt;
struct GelsInfo *gInfo;&lt;br /&gt;
struct VSprite  *vsHead;&lt;br /&gt;
struct VSprite  *vsTail;&lt;br /&gt;
&lt;br /&gt;
if (NULL != (gInfo = (struct GelsInfo *)AllocMem(sizeof(struct GelsInfo), MEMF_CLEAR)))&lt;br /&gt;
        {&lt;br /&gt;
        if (NULL != (gInfo-&amp;amp;gt;nextLine = (WORD *)AllocMem(sizeof(WORD) * 8, MEMF_CLEAR)))&lt;br /&gt;
            {&lt;br /&gt;
            if (NULL != (gInfo-&amp;amp;gt;lastColor = (WORD **)AllocMem(sizeof(LONG) * 8, MEMF_CLEAR)))&lt;br /&gt;
                {&lt;br /&gt;
                if (NULL != (gInfo-&amp;amp;gt;collHandler = (struct collTable *)&lt;br /&gt;
                        AllocMem(sizeof(struct collTable),MEMF_CLEAR)))&lt;br /&gt;
                    {&lt;br /&gt;
                    if (NULL != (vsHead = (struct VSprite *)&lt;br /&gt;
                            AllocMem((LONG)sizeof(struct VSprite), MEMF_CLEAR)))&lt;br /&gt;
                        {&lt;br /&gt;
                        if (NULL != (vsTail = (struct VSprite *)&lt;br /&gt;
                                AllocMem(sizeof(struct VSprite), MEMF_CLEAR)))&lt;br /&gt;
                            {&lt;br /&gt;
                            gInfo-&amp;amp;gt;sprRsrvd   = reserved;&lt;br /&gt;
                            /* Set left- and top-most to 1 to better keep items */&lt;br /&gt;
                            /* inside the display boundaries.                   */&lt;br /&gt;
                            gInfo-&amp;amp;gt;leftmost   = gInfo-&amp;amp;gt;topmost    = 1;&lt;br /&gt;
                            gInfo-&amp;amp;gt;rightmost  = (rPort-&amp;amp;gt;BitMap-&amp;amp;gt;BytesPerRow &amp;amp;lt;&amp;amp;lt; 3) - 1;&lt;br /&gt;
                            gInfo-&amp;amp;gt;bottommost = rPort-&amp;amp;gt;BitMap-&amp;amp;gt;Rows - 1;&lt;br /&gt;
                            rPort-&amp;amp;gt;GelsInfo = gInfo;&lt;br /&gt;
                            InitGels(vsHead, vsTail, gInfo);&lt;br /&gt;
                            return(gInfo);&lt;br /&gt;
                            }&lt;br /&gt;
                        FreeMem(vsHead, (LONG)sizeof(*vsHead));&lt;br /&gt;
                        }&lt;br /&gt;
                    FreeMem(gInfo-&amp;amp;gt;collHandler, (LONG)sizeof(struct collTable));&lt;br /&gt;
                    }&lt;br /&gt;
                FreeMem(gInfo-&amp;amp;gt;lastColor, (LONG)sizeof(LONG) * 8);&lt;br /&gt;
                }&lt;br /&gt;
            FreeMem(gInfo-&amp;amp;gt;nextLine, (LONG)sizeof(WORD) * 8);&lt;br /&gt;
            }&lt;br /&gt;
        FreeMem(gInfo, (LONG)sizeof(*gInfo));&lt;br /&gt;
        }&lt;br /&gt;
return(NULL);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/* Free all of the stuff allocated by setupGelSys().  Only call this routine if&lt;br /&gt;
** setupGelSys() returned successfully.  The GelsInfo structure is the one returned&lt;br /&gt;
** by setupGelSys().   It also unlinks the GelsInfo from the RastPort.&lt;br /&gt;
*/&lt;br /&gt;
VOID cleanupGelSys(struct GelsInfo *gInfo, struct RastPort *rPort)&lt;br /&gt;
{&lt;br /&gt;
rPort-&amp;amp;gt;GelsInfo = NULL;&lt;br /&gt;
FreeMem(gInfo-&amp;amp;gt;collHandler, (LONG)sizeof(struct collTable));&lt;br /&gt;
FreeMem(gInfo-&amp;amp;gt;lastColor, (LONG)sizeof(LONG) * 8);&lt;br /&gt;
FreeMem(gInfo-&amp;amp;gt;nextLine, (LONG)sizeof(WORD) * 8);&lt;br /&gt;
FreeMem(gInfo-&amp;amp;gt;gelHead, (LONG)sizeof(struct VSprite));&lt;br /&gt;
FreeMem(gInfo-&amp;amp;gt;gelTail, (LONG)sizeof(struct VSprite));&lt;br /&gt;
FreeMem(gInfo, (LONG)sizeof(*gInfo));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/* Create a VSprite from the information given in nVSprite.  Use freeVSprite()&lt;br /&gt;
** to free this GEL.&lt;br /&gt;
*/&lt;br /&gt;
struct VSprite *makeVSprite(NEWVSPRITE *nVSprite)&lt;br /&gt;
{&lt;br /&gt;
struct VSprite *vsprite;&lt;br /&gt;
LONG            line_size;&lt;br /&gt;
LONG            plane_size;&lt;br /&gt;
&lt;br /&gt;
line_size = sizeof(WORD) * nVSprite-&amp;amp;gt;nvs_WordWidth;&lt;br /&gt;
plane_size = line_size * nVSprite-&amp;amp;gt;nvs_LineHeight;&lt;br /&gt;
&lt;br /&gt;
if (NULL != (vsprite = (struct VSprite *)AllocMem((LONG)sizeof(struct VSprite), MEMF_CLEAR)))&lt;br /&gt;
        {&lt;br /&gt;
        if (NULL != (vsprite-&amp;amp;gt;BorderLine = (WORD *)AllocMem(line_size, MEMF_CHIP)))&lt;br /&gt;
            {&lt;br /&gt;
            if (NULL != (vsprite-&amp;amp;gt;CollMask = (WORD *)AllocMem(plane_size, MEMF_CHIP)))&lt;br /&gt;
                {&lt;br /&gt;
                vsprite-&amp;amp;gt;Y          = nVSprite-&amp;amp;gt;nvs_Y;&lt;br /&gt;
                vsprite-&amp;amp;gt;X          = nVSprite-&amp;amp;gt;nvs_X;&lt;br /&gt;
                vsprite-&amp;amp;gt;Flags      = nVSprite-&amp;amp;gt;nvs_Flags;&lt;br /&gt;
                vsprite-&amp;amp;gt;Width      = nVSprite-&amp;amp;gt;nvs_WordWidth;&lt;br /&gt;
                vsprite-&amp;amp;gt;Depth      = nVSprite-&amp;amp;gt;nvs_ImageDepth;&lt;br /&gt;
                vsprite-&amp;amp;gt;Height     = nVSprite-&amp;amp;gt;nvs_LineHeight;&lt;br /&gt;
                vsprite-&amp;amp;gt;MeMask     = nVSprite-&amp;amp;gt;nvs_MeMask;&lt;br /&gt;
                vsprite-&amp;amp;gt;HitMask    = nVSprite-&amp;amp;gt;nvs_HitMask;&lt;br /&gt;
                vsprite-&amp;amp;gt;ImageData  = nVSprite-&amp;amp;gt;nvs_Image;&lt;br /&gt;
                vsprite-&amp;amp;gt;SprColors  = nVSprite-&amp;amp;gt;nvs_ColorSet;&lt;br /&gt;
                vsprite-&amp;amp;gt;PlanePick  = vsprite-&amp;amp;gt;PlaneOnOff = 0x00;&lt;br /&gt;
                InitMasks(vsprite);&lt;br /&gt;
                return(vsprite);&lt;br /&gt;
                }&lt;br /&gt;
            FreeMem(vsprite-&amp;amp;gt;BorderLine, line_size);&lt;br /&gt;
            }&lt;br /&gt;
        FreeMem(vsprite, (LONG)sizeof(*vsprite));&lt;br /&gt;
        }&lt;br /&gt;
return(NULL);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/* Create a Bob from the information given in nBob.  Use freeBob() to free this GEL.&lt;br /&gt;
** A VSprite is created for this bob.  This routine properly allocates all double&lt;br /&gt;
** buffered information if it is required.&lt;br /&gt;
*/&lt;br /&gt;
struct Bob *makeBob(NEWBOB *nBob)&lt;br /&gt;
{&lt;br /&gt;
struct Bob         *bob;&lt;br /&gt;
struct VSprite     *vsprite;&lt;br /&gt;
NEWVSPRITE          nVSprite ;&lt;br /&gt;
LONG                rassize;&lt;br /&gt;
&lt;br /&gt;
rassize = (LONG)sizeof(UWORD) * nBob-&amp;amp;gt;nb_WordWidth * nBob-&amp;amp;gt;nb_LineHeight * nBob-&amp;amp;gt;nb_RasDepth;&lt;br /&gt;
&lt;br /&gt;
if (NULL != (bob = (struct Bob *)AllocMem((LONG)sizeof(struct Bob), MEMF_CLEAR)))&lt;br /&gt;
        {&lt;br /&gt;
        if (NULL != (bob-&amp;amp;gt;SaveBuffer = (WORD *)AllocMem(rassize, MEMF_CHIP)))&lt;br /&gt;
            {&lt;br /&gt;
            nVSprite.nvs_WordWidth  = nBob-&amp;amp;gt;nb_WordWidth;&lt;br /&gt;
            nVSprite.nvs_LineHeight = nBob-&amp;amp;gt;nb_LineHeight;&lt;br /&gt;
            nVSprite.nvs_ImageDepth = nBob-&amp;amp;gt;nb_ImageDepth;&lt;br /&gt;
            nVSprite.nvs_Image      = nBob-&amp;amp;gt;nb_Image;&lt;br /&gt;
            nVSprite.nvs_X          = nBob-&amp;amp;gt;nb_X;&lt;br /&gt;
            nVSprite.nvs_Y          = nBob-&amp;amp;gt;nb_Y;&lt;br /&gt;
            nVSprite.nvs_ColorSet   = NULL;&lt;br /&gt;
            nVSprite.nvs_Flags      = nBob-&amp;amp;gt;nb_BFlags;&lt;br /&gt;
            /* Push the values into the NEWVSPRITE structure for use in makeVSprite(). */&lt;br /&gt;
            nVSprite.nvs_MeMask     = nBob-&amp;amp;gt;nb_MeMask;&lt;br /&gt;
            nVSprite.nvs_HitMask    = nBob-&amp;amp;gt;nb_HitMask;&lt;br /&gt;
&lt;br /&gt;
            if ((vsprite = makeVSprite(&amp;amp;amp;nVSprite)) != NULL)&lt;br /&gt;
                {&lt;br /&gt;
                vsprite-&amp;amp;gt;PlanePick = nBob-&amp;amp;gt;nb_PlanePick;&lt;br /&gt;
                vsprite-&amp;amp;gt;PlaneOnOff = nBob-&amp;amp;gt;nb_PlaneOnOff;&lt;br /&gt;
                vsprite-&amp;amp;gt;VSBob   = bob;&lt;br /&gt;
                bob-&amp;amp;gt;BobVSprite  = vsprite;&lt;br /&gt;
                bob-&amp;amp;gt;ImageShadow = vsprite-&amp;amp;gt;CollMask;&lt;br /&gt;
                bob-&amp;amp;gt;Flags       = 0;&lt;br /&gt;
                bob-&amp;amp;gt;Before      = NULL;&lt;br /&gt;
                bob-&amp;amp;gt;After       = NULL;&lt;br /&gt;
                bob-&amp;amp;gt;BobComp     = NULL;&lt;br /&gt;
&lt;br /&gt;
                if (nBob-&amp;amp;gt;nb_DBuf)&lt;br /&gt;
                    {&lt;br /&gt;
                    if (NULL != (bob-&amp;amp;gt;DBuffer = (struct DBufPacket *)&lt;br /&gt;
                            AllocMem((LONG)sizeof(struct DBufPacket), MEMF_CLEAR)))&lt;br /&gt;
                        {&lt;br /&gt;
                        if (NULL != (bob-&amp;amp;gt;DBuffer-&amp;amp;gt;BufBuffer = (WORD *)AllocMem(rassize, MEMF_CHIP)))&lt;br /&gt;
                            return(bob);&lt;br /&gt;
                        FreeMem(bob-&amp;amp;gt;DBuffer, (LONG)sizeof(struct DBufPacket));&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
                else&lt;br /&gt;
                    {&lt;br /&gt;
                    bob-&amp;amp;gt;DBuffer = NULL;&lt;br /&gt;
                    return(bob);&lt;br /&gt;
                    }&lt;br /&gt;
                freeVSprite(vsprite);&lt;br /&gt;
                }&lt;br /&gt;
            FreeMem(bob-&amp;amp;gt;SaveBuffer, rassize);&lt;br /&gt;
            }&lt;br /&gt;
        FreeMem(bob, (LONG)sizeof(*bob));&lt;br /&gt;
        }&lt;br /&gt;
return(NULL);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
** Create a Animation Component from the information given in nAnimComp and nBob.  Use&lt;br /&gt;
** freeComp() to free this GEL.  makeComp() calls makeBob(), and links the Bob into an AnimComp.&lt;br /&gt;
*/&lt;br /&gt;
struct AnimComp *makeComp(NEWBOB *nBob, NEWANIMCOMP *nAnimComp)&lt;br /&gt;
{&lt;br /&gt;
struct Bob      *compBob;&lt;br /&gt;
struct AnimComp *aComp;&lt;br /&gt;
&lt;br /&gt;
if ((aComp = AllocMem((LONG)sizeof(struct AnimComp),MEMF_CLEAR)) != NULL)&lt;br /&gt;
        {&lt;br /&gt;
        if ((compBob = makeBob(nBob)) != NULL)&lt;br /&gt;
            {&lt;br /&gt;
            compBob-&amp;amp;gt;After   = compBob-&amp;amp;gt;Before  = NULL;&lt;br /&gt;
            compBob-&amp;amp;gt;BobComp = aComp;   /* Link &#039;em up. */&lt;br /&gt;
            aComp-&amp;amp;gt;AnimBob      = compBob;&lt;br /&gt;
            aComp-&amp;amp;gt;TimeSet      = nAnimComp-&amp;amp;gt;nac_Time; /* Num ticks active. */&lt;br /&gt;
            aComp-&amp;amp;gt;YTrans       = nAnimComp-&amp;amp;gt;nac_Yt; /* Offset rel to HeadOb */&lt;br /&gt;
            aComp-&amp;amp;gt;XTrans       = nAnimComp-&amp;amp;gt;nac_Xt;&lt;br /&gt;
            aComp-&amp;amp;gt;AnimCRoutine = nAnimComp-&amp;amp;gt;nac_Routine;&lt;br /&gt;
            aComp-&amp;amp;gt;Flags        = nAnimComp-&amp;amp;gt;nac_CFlags;&lt;br /&gt;
            aComp-&amp;amp;gt;Timer        = 0;&lt;br /&gt;
            aComp-&amp;amp;gt;NextSeq      = aComp-&amp;amp;gt;PrevSeq  = NULL;&lt;br /&gt;
            aComp-&amp;amp;gt;NextComp     = aComp-&amp;amp;gt;PrevComp = NULL;&lt;br /&gt;
            aComp-&amp;amp;gt;HeadOb       = NULL;&lt;br /&gt;
            return(aComp);&lt;br /&gt;
            }&lt;br /&gt;
        FreeMem(aComp, (LONG)sizeof(struct AnimComp));&lt;br /&gt;
        }&lt;br /&gt;
return(NULL);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/* Create an Animation Sequence from the information given in nAnimSeq and nBob.  Use&lt;br /&gt;
** freeSeq() to free this GEL.  This routine creates a linked list of animation components&lt;br /&gt;
** which make up the animation sequence.  It links them all up, making a circular list of&lt;br /&gt;
** the PrevSeq and NextSeq pointers. That is to say, the first component of the sequences&#039;&lt;br /&gt;
** PrevSeq points to the last component; the last component of * the sequences&#039; NextSeq&lt;br /&gt;
** points back to the first component.  If dbuf is on, the underlying Bobs will be set up&lt;br /&gt;
** for double buffering.  If singleImage is non-zero, the pImages pointer is assumed to&lt;br /&gt;
** point to an array of only one image, instead of an array of &#039;count&#039; images, and all&lt;br /&gt;
** Bobs will use the same image.&lt;br /&gt;
*/&lt;br /&gt;
struct AnimComp *makeSeq(NEWBOB *nBob, NEWANIMSEQ *nAnimSeq)&lt;br /&gt;
{&lt;br /&gt;
int seq;&lt;br /&gt;
struct AnimComp *firstCompInSeq = NULL;&lt;br /&gt;
struct AnimComp *seqComp = NULL;&lt;br /&gt;
struct AnimComp *lastCompMade = NULL;&lt;br /&gt;
LONG image_size;&lt;br /&gt;
NEWANIMCOMP nAnimComp;&lt;br /&gt;
&lt;br /&gt;
/* get the initial image.  this is the only image that is used&lt;br /&gt;
** if nAnimSeq-&amp;amp;gt;nas_SingleImage is non-zero.&lt;br /&gt;
*/&lt;br /&gt;
nBob-&amp;amp;gt;nb_Image = nAnimSeq-&amp;amp;gt;nas_Images;&lt;br /&gt;
image_size = nBob-&amp;amp;gt;nb_LineHeight * nBob-&amp;amp;gt;nb_ImageDepth * nBob-&amp;amp;gt;nb_WordWidth;&lt;br /&gt;
&lt;br /&gt;
/* for each comp in the sequence */&lt;br /&gt;
for (seq = 0; seq &amp;amp;lt; nAnimSeq-&amp;amp;gt;nas_Count; seq++)&lt;br /&gt;
        {&lt;br /&gt;
        nAnimComp.nac_Xt        = *(nAnimSeq-&amp;amp;gt;nas_Xt + seq);&lt;br /&gt;
        nAnimComp.nac_Yt        = *(nAnimSeq-&amp;amp;gt;nas_Yt + seq);&lt;br /&gt;
        nAnimComp.nac_Time      = *(nAnimSeq-&amp;amp;gt;nas_Times + seq);&lt;br /&gt;
        nAnimComp.nac_Routine   = nAnimSeq-&amp;amp;gt;nas_Routines[seq];&lt;br /&gt;
        nAnimComp.nac_CFlags    = nAnimSeq-&amp;amp;gt;nas_CFlags;&lt;br /&gt;
        if ((seqComp = makeComp(nBob, &amp;amp;amp;nAnimComp)) == NULL)&lt;br /&gt;
            {&lt;br /&gt;
            if (firstCompInSeq != NULL)&lt;br /&gt;
                freeSeq(firstCompInSeq, (LONG)nBob-&amp;amp;gt;nb_RasDepth);&lt;br /&gt;
            return(NULL);&lt;br /&gt;
            }&lt;br /&gt;
        seqComp-&amp;amp;gt;HeadOb = nAnimSeq-&amp;amp;gt;nas_HeadOb;&lt;br /&gt;
        /* Make a note of where the first component is. */&lt;br /&gt;
        if (firstCompInSeq == NULL) firstCompInSeq = seqComp;&lt;br /&gt;
        /* link the component into the list */&lt;br /&gt;
        if (lastCompMade != NULL) lastCompMade-&amp;amp;gt;NextSeq = seqComp;&lt;br /&gt;
        seqComp-&amp;amp;gt;NextSeq = NULL;&lt;br /&gt;
        seqComp-&amp;amp;gt;PrevSeq = lastCompMade;&lt;br /&gt;
        lastCompMade = seqComp;&lt;br /&gt;
        /* If nAnimSeq-&amp;amp;gt;nas_SingleImage is zero, the image array has nAnimSeq-&amp;amp;gt;nas_Count images. */&lt;br /&gt;
        if (!nAnimSeq-&amp;amp;gt;nas_SingleImage)&lt;br /&gt;
            nBob-&amp;amp;gt;nb_Image += image_size;&lt;br /&gt;
        }&lt;br /&gt;
/* On The last component in the sequence, set Next/Prev to make */&lt;br /&gt;
/* the linked list a loop of components.                        */&lt;br /&gt;
lastCompMade-&amp;amp;gt;NextSeq = firstCompInSeq;&lt;br /&gt;
firstCompInSeq-&amp;amp;gt;PrevSeq = lastCompMade;&lt;br /&gt;
&lt;br /&gt;
return(firstCompInSeq);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/* Free the data created by makeVSprite().  Assumes images deallocated elsewhere. */&lt;br /&gt;
VOID freeVSprite(struct VSprite *vsprite)&lt;br /&gt;
{&lt;br /&gt;
LONG    line_size;&lt;br /&gt;
LONG    plane_size;&lt;br /&gt;
&lt;br /&gt;
line_size = (LONG)sizeof(WORD) * vsprite-&amp;amp;gt;Width;&lt;br /&gt;
plane_size = line_size * vsprite-&amp;amp;gt;Height;&lt;br /&gt;
FreeMem(vsprite-&amp;amp;gt;BorderLine, line_size);&lt;br /&gt;
FreeMem(vsprite-&amp;amp;gt;CollMask, plane_size);&lt;br /&gt;
FreeMem(vsprite, (LONG)sizeof(*vsprite));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/* Free the data created by makeBob().  It&#039;s important that rasdepth match the depth you */&lt;br /&gt;
/* passed to makeBob() when this GEL was made. Assumes images deallocated elsewhere.     */&lt;br /&gt;
VOID freeBob(struct Bob *bob, LONG rasdepth)&lt;br /&gt;
{&lt;br /&gt;
LONG    rassize =  sizeof(UWORD) * bob-&amp;amp;gt;BobVSprite-&amp;amp;gt;Width * bob-&amp;amp;gt;BobVSprite-&amp;amp;gt;Height * rasdepth;&lt;br /&gt;
&lt;br /&gt;
if (bob-&amp;amp;gt;DBuffer != NULL)&lt;br /&gt;
        {&lt;br /&gt;
        FreeMem(bob-&amp;amp;gt;DBuffer-&amp;amp;gt;BufBuffer, rassize);&lt;br /&gt;
        FreeMem(bob-&amp;amp;gt;DBuffer, (LONG)sizeof(struct DBufPacket));&lt;br /&gt;
        }&lt;br /&gt;
FreeMem(bob-&amp;amp;gt;SaveBuffer, rassize);&lt;br /&gt;
freeVSprite(bob-&amp;amp;gt;BobVSprite);&lt;br /&gt;
FreeMem(bob, (LONG)sizeof(*bob));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/* Free the data created by makeComp().  It&#039;s important that rasdepth match the depth you */&lt;br /&gt;
/* passed to makeComp() when this GEL was made. Assumes images deallocated elsewhere.    */&lt;br /&gt;
VOID freeComp(struct AnimComp *myComp, LONG rasdepth)&lt;br /&gt;
{&lt;br /&gt;
freeBob(myComp-&amp;amp;gt;AnimBob, rasdepth);&lt;br /&gt;
FreeMem(myComp, (LONG)sizeof(struct AnimComp));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/* Free the data created by makeSeq().  Complimentary to makeSeq(), this routine goes through&lt;br /&gt;
** the NextSeq pointers and frees the Components.  This routine only goes forward through the&lt;br /&gt;
** list, and so it must be passed the first component in the sequence, or the sequence must&lt;br /&gt;
** be circular (which is guaranteed if you use makeSeq()).  It&#039;s important that rasdepth match&lt;br /&gt;
** the depth you passed to makeSeq() when this GEL was made.   Assumes images deallocated elsewhere!&lt;br /&gt;
*/&lt;br /&gt;
VOID freeSeq(struct AnimComp *headComp, LONG rasdepth)&lt;br /&gt;
{&lt;br /&gt;
struct AnimComp *curComp;&lt;br /&gt;
struct AnimComp *nextComp;&lt;br /&gt;
&lt;br /&gt;
/* Break the NextSeq loop, so we get a NULL at the end of the list. */&lt;br /&gt;
headComp-&amp;amp;gt;PrevSeq-&amp;amp;gt;NextSeq = NULL;&lt;br /&gt;
&lt;br /&gt;
curComp = headComp;         /* get the start of the list */&lt;br /&gt;
while (curComp != NULL)&lt;br /&gt;
        {&lt;br /&gt;
        nextComp = curComp-&amp;amp;gt;NextSeq;&lt;br /&gt;
        freeComp(curComp, rasdepth);&lt;br /&gt;
        curComp = nextComp;&lt;br /&gt;
        }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/* Free an animation object (list of sequences).  freeOb() goes through the NextComp&lt;br /&gt;
** pointers, starting at the AnimObs&#039; HeadComp, and frees every sequence.  It only&lt;br /&gt;
** goes forward. It then frees the Object itself.  Assumes images deallocated elsewhere!&lt;br /&gt;
*/&lt;br /&gt;
VOID freeOb(struct AnimOb *headOb, LONG rasdepth)&lt;br /&gt;
{&lt;br /&gt;
struct AnimComp *curSeq;&lt;br /&gt;
struct AnimComp *nextSeq;&lt;br /&gt;
&lt;br /&gt;
curSeq = headOb-&amp;amp;gt;HeadComp;          /* get the start of the list */&lt;br /&gt;
while (curSeq != NULL)&lt;br /&gt;
        {&lt;br /&gt;
        nextSeq = curSeq-&amp;amp;gt;NextComp;&lt;br /&gt;
        freeSeq(curSeq, rasdepth);&lt;br /&gt;
        curSeq = nextSeq;&lt;br /&gt;
        }&lt;br /&gt;
FreeMem(headOb, sizeof(struct AnimOb));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Function Reference ==&lt;br /&gt;
&lt;br /&gt;
The following are brief descriptions of the Amiga&#039;s graphics animation functions. See the SDK for details on each function call.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Animation Function&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| AddAnimOb()&lt;br /&gt;
| Add an AnimOb to the linked list of AnimObs.&lt;br /&gt;
|-&lt;br /&gt;
| AddBob()&lt;br /&gt;
| Add a Bob to the current GEL list.&lt;br /&gt;
|-&lt;br /&gt;
| AddVSprite()&lt;br /&gt;
| Add a VSprite to the current GEL list.&lt;br /&gt;
|-&lt;br /&gt;
| Animate()&lt;br /&gt;
| Process every AnimOb in the current animation list.&lt;br /&gt;
|-&lt;br /&gt;
| ChangeSprite()&lt;br /&gt;
| Change the sprite image pointer.&lt;br /&gt;
|-&lt;br /&gt;
| DoCollision()&lt;br /&gt;
| Test every GEL in a GEL list for collisions.&lt;br /&gt;
|-&lt;br /&gt;
| DrawGList()&lt;br /&gt;
| Process the GEL list, queueing VSprites, drawing Bobs.&lt;br /&gt;
|-&lt;br /&gt;
| FreeGBuffers()&lt;br /&gt;
| Deallocate memory obtained by GetGBuffers().&lt;br /&gt;
|-&lt;br /&gt;
| FreeSprite()&lt;br /&gt;
| Return sprite for use by others and virtual sprite machine.&lt;br /&gt;
|-&lt;br /&gt;
| GetGBuffers()&lt;br /&gt;
| Attempt to allocate all buffers of an entire AnimOb.&lt;br /&gt;
|-&lt;br /&gt;
| GetSprite()&lt;br /&gt;
| Attempt to get a sprite for the simple sprite manager.&lt;br /&gt;
|-&lt;br /&gt;
| InitGels()&lt;br /&gt;
| Initialize a GEL list; must be called before using GELs.&lt;br /&gt;
|-&lt;br /&gt;
| InitGMasks()&lt;br /&gt;
| Initialize all of the masks of an AnimOb.&lt;br /&gt;
|-&lt;br /&gt;
| InitMasks()&lt;br /&gt;
| Initialize the BorderLine and CollMask masks of a VSprite.&lt;br /&gt;
|-&lt;br /&gt;
| MoveSprite()&lt;br /&gt;
| Move sprite to a point relative to top of ViewPort.&lt;br /&gt;
|-&lt;br /&gt;
| RemBob()&lt;br /&gt;
| Remove a Bob from the GEL list.&lt;br /&gt;
|-&lt;br /&gt;
| RemIBob()&lt;br /&gt;
| Immediately remove a Bob from the GEL list and the RastPort.&lt;br /&gt;
|-&lt;br /&gt;
| RemVSprite()&lt;br /&gt;
| Remove a VSprite from the current GEL list.&lt;br /&gt;
|-&lt;br /&gt;
| SetCollision()&lt;br /&gt;
| Set a pointer to a user collision routine.&lt;br /&gt;
|-&lt;br /&gt;
| SortGList()&lt;br /&gt;
| Sort the current GEL list, ordering its &#039;&#039;x,y&#039;&#039; coordinates.&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Costel Mincea</name></author>
	</entry>
	<entry>
		<id>https://wiki.amigaos.net/w/index.php?title=Cooperative_Record_Locking&amp;diff=12551</id>
		<title>Cooperative Record Locking</title>
		<link rel="alternate" type="text/html" href="https://wiki.amigaos.net/w/index.php?title=Cooperative_Record_Locking&amp;diff=12551"/>
		<updated>2025-01-26T19:30:20Z</updated>

		<summary type="html">&lt;p&gt;Costel Mincea: Text replacement - &amp;quot;&amp;lt;syntaxhighlight&amp;gt;&amp;quot; to &amp;quot;&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Description ==&lt;br /&gt;
&lt;br /&gt;
The Amiga&#039;s cooperative record locking scheme allows an application to lock regions of a file rather than locking an entire file. These regions are known as records.&lt;br /&gt;
&lt;br /&gt;
The Amiga thinks of a record in terms of size and offset. The size refers to the length of the record in bytes. The offset refers to&lt;br /&gt;
the starting position of the record from the beginning of the file. The size and offset can vary from record to record. The only limit&lt;br /&gt;
on a record&#039;s size and offset are the limits the file system has on the size of the file.&lt;br /&gt;
&lt;br /&gt;
== File System or DOS? ==&lt;br /&gt;
&lt;br /&gt;
Starting with version 53.x of the DOS Library (dos.library), the record locking feature is handled entirely by AmigaDOS. DOS record locking is independent of the file system and is always available. Prior to this version, record locking was available only if each individual file system implemented the feature. If a file system does not record locking, the record locking functions described below will always fail.&lt;br /&gt;
&lt;br /&gt;
== Record Lock Types ==&lt;br /&gt;
&lt;br /&gt;
There are two basic types of record lock, exclusive and shared. An exclusive lock gives an application exclusive access to a record. While an application holds an exclusive record lock, no other process can obtain a record lock that overlaps the exclusively locked region. The file system can only grant an exclusive record lock on a region that is not part of an existing record lock.&lt;br /&gt;
&lt;br /&gt;
The other type of record lock, the shared lock, gives an application shared access to a record. While an application holds a shared&lt;br /&gt;
record lock, other applications can also obtain a shared record lock that overlaps the original shared record lock, but no other process can obtain an exclusive record lock that overlaps the shared record lock.&lt;br /&gt;
&lt;br /&gt;
== Locking and Unlocking Records ==&lt;br /&gt;
&lt;br /&gt;
To lock (or unlock) a record within a file, an application needs a valid file handle on the file. Two DOS Library functions handle&lt;br /&gt;
individual record locks:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
BOOL LockRecord(BPTR myFH, ULONG my_offset, ULONG my_length, ULONG my_mode, ULONG my_timeout);&lt;br /&gt;
BOOL UnLockRecord(BPTR myFH, ULONG my_offset, ULONG my_length);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In both functions, the myFH field refers to the valid file handle mentioned above, and the my_offset and my_length fields refer to the&lt;br /&gt;
record&#039;s offset and size.&lt;br /&gt;
&lt;br /&gt;
The LockRecord() function has two additional parameters: my_mode and my_timeout. The my_mode field refers to the type of record. DOS supports four record types:&lt;br /&gt;
&lt;br /&gt;
; REC_EXCLUSIVE&lt;br /&gt;
: Create an exclusive record lock. If the record is not immediately available, the file system will make a second record lock attempt when the timeout expires. The timeout (the my_timeout field from the RecordLock() prototype above) is in DOS ticks (1/50 of a second).&lt;br /&gt;
&lt;br /&gt;
; REC_EXCLUSIVE_IMMED&lt;br /&gt;
: This record type is like REC_EXCLUSIVE, but the attempt to lock a record will fail if the record is not immediately available. In this case the file system ignores the timeout.&lt;br /&gt;
&lt;br /&gt;
; REC_SHARED&lt;br /&gt;
: Create a shared record lock. If the record is not immediately available, the file system will make a second record lock attempt when the timeout expires. The timeout (the my_timeout field from the RecordLock() prototype above) is in DOS ticks (1/50th of a second).&lt;br /&gt;
&lt;br /&gt;
; REC_SHARED_IMMED&lt;br /&gt;
: This record type is like REC_SHARED, but the attempt to lock a record will fail if the record is not immediately available. In this case the file system ignores the timeout.&lt;br /&gt;
&lt;br /&gt;
The Amiga record locking scheme is cooperative--the file system does not prevent any process from accessing any part of a data&lt;br /&gt;
file. The record locking scheme has nothing to do with other actions of a file system. The file system will let other processes read and write a data file regardless of any existing record locks on the data file.&lt;br /&gt;
&lt;br /&gt;
Also, when an application attempts to create a record lock, the file system&#039;s record locking mechanism only makes sure the record won&#039;t&lt;br /&gt;
conflict with any existing record locks on the same data file. The file system doesn&#039;t check the validity of the locked region. This&lt;br /&gt;
makes it possible to lock records in an empty data file and also to lock records that are well beyond the end of a data file. This&lt;br /&gt;
feature may be useful to an application that needs to lock records that don&#039;t exist yet.&lt;br /&gt;
&lt;br /&gt;
When releasing a record lock, an application must provide exactly the same parameters it used when it locked the record. Attempting to&lt;br /&gt;
unlock a record using a different offset or length will fail. If the application does not successfully unlock a record, the record lock&lt;br /&gt;
will remain in effect. This means further requests to lock that record can fail, depending on the type of record lock. The record&lt;br /&gt;
lock will remain in effect until the data file is removed or the system restarted. As with most Amiga resources, an application&lt;br /&gt;
should release a record lock as quickly as possible. This helps out other applications that might be waiting to access the locked record.&lt;br /&gt;
&lt;br /&gt;
== Locking Multiple Records ==&lt;br /&gt;
&lt;br /&gt;
DOS Library offers a function to lock an array of record locks:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
BOOL LockRecords(struct RecordLock *recordarray, ULONG multi_timeout);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
LockRecords() locks a group of records using one function call. LockRecords() accepts a pointer to an array of RecordLock structures&lt;br /&gt;
(as defined in &amp;lt;dos/record.h&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct RecordLock {&lt;br /&gt;
        BPTR    rec_FH; /* The file handle of the data file */&lt;br /&gt;
        ULONG   rec_Offset;     /* The record offset in the data file */&lt;br /&gt;
        ULONG   rec_Length;     /* The length of the record */&lt;br /&gt;
        ULONG   rec_Mode;       /* The mode of the record lock */&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The fields in each RecordLock structure correspond to the parameters from the LockRecord() function. The records do not have to be in the same file. The array is terminated by a dummy RecordLock with a NULL file handle (rec_FH).&lt;br /&gt;
&lt;br /&gt;
The RecordLock structure does not include a timeout. Instead, LockRecords() applies the same timeout (multi_timeout from the LockRecords() prototype above) to each RecordLock in the array. If LockRecords() fails to lock any of the records in its array, LockRecords() releases any successful record locks from the array, and return DOSFALSE.&lt;br /&gt;
&lt;br /&gt;
To unlock records locked by LockRecords(), use the dos.library function UnLockRecords():&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
BOOL UnLockRecords(struct RecordLock *recordarray);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This function accepts the same array used to lock the records with LockRecords().&lt;br /&gt;
&lt;br /&gt;
Note that it is possible to use UnLockRecord() on a record locked by LockRecords(). However, if an application uses UnLockRecord() to&lt;br /&gt;
unlock one record in the RecordLock array, it should use UnLockRecord() to unlock all of the records in the array.&lt;br /&gt;
&lt;br /&gt;
== Locking Records Using DOS Packets ==&lt;br /&gt;
&lt;br /&gt;
{{Note|title=Don&#039;t use DOS Packets|text=DOS Library now handles record locking as of version 53.?? so that file systems are no longer burdened with implementing this functionality. The information below is being provided for reference and for users of previous versions of the DOS Library.}}&lt;br /&gt;
&lt;br /&gt;
To lock a record using the DOS packet interface, send an ACTION_LOCK_RECORD (2008) packet to the file system. This packet uses the following arguments:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ARG1: BTPR   The file handle of the data file in which you wish to lock a record.&lt;br /&gt;
ARG2: ULONG  The offset (in bytes) in the file of the record.&lt;br /&gt;
ARG3: ULONG  The length (in bytes) of the record.&lt;br /&gt;
ARG4: ULONG  The mode with which you wish to lock record.&lt;br /&gt;
ARG5: ULONG  Time (in ticks) you are will to wait for the record to become available.&lt;br /&gt;
&lt;br /&gt;
RES1: BOOL   Upon return RES1 will contain the success/failure status:&lt;br /&gt;
             DOSTRUE if the record lock was successfully locked.&lt;br /&gt;
             DOSFALSE if the record lock failed.&lt;br /&gt;
RES2: CODE   Failure code if the record lock failed for a reason other than denied&lt;br /&gt;
             access (collision for example).&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To unlock a record using the DOS packet interface, send an ACTION_FREE_RECORD (2009) packet. This packet uses the following arguments:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ARG1: BPTR   The file handle of the data file in which you locked the record.&lt;br /&gt;
ARG2: ULONG  The offset (in bytes) in the file of the record with which you locked&lt;br /&gt;
             the record.&lt;br /&gt;
ARG3: ULONG  The length (in bytes) of the record with which you locked the record.&lt;br /&gt;
&lt;br /&gt;
RES1: BOOL   Upon return RES1 will contain the success/failure status:&lt;br /&gt;
             DOSTRUE if the record lock was successfully unlocked.&lt;br /&gt;
             DOSFALSE if there was no lock to unlock.&lt;br /&gt;
RES2: CODE   Possible failure code if the record lock could not be unlocked.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Examples ==&lt;br /&gt;
&lt;br /&gt;
=== LockRecord.c ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
// LockRecord.c&lt;br /&gt;
//&lt;br /&gt;
// LockRecord()/UnLockRecord() example.&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;exec/memory.h&amp;gt;&lt;br /&gt;
#include &amp;lt;exec/lists.h&amp;gt;&lt;br /&gt;
#include &amp;lt;dos/dosextens.h&amp;gt;&lt;br /&gt;
#include &amp;lt;dos/rdargs.h&amp;gt;&lt;br /&gt;
#include &amp;lt;dos/record.h&amp;gt;&lt;br /&gt;
#include &amp;lt;utility/tagitem.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;proto/dos.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/exec.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/utility.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
void GetCommandLine(BPTR, struct RDArgs *rdargs, UBYTE *cmdbuffer);&lt;br /&gt;
void DoLockRecord(BPTR, struct RDArgs *rdargs);&lt;br /&gt;
void DoUnLockRecord(BPTR fh, struct RDArgs *rdargs);&lt;br /&gt;
void ListRecordLocks(void);&lt;br /&gt;
struct LockNode *FindRecordLock(ULONG offset, ULONG length);&lt;br /&gt;
&lt;br /&gt;
/* List and node structures to keep track of record locks */&lt;br /&gt;
struct LockNode {&lt;br /&gt;
    struct LockNode *ln_Succ;&lt;br /&gt;
    struct LockNode *ln_Pred;&lt;br /&gt;
    ULONG ln_Counter;&lt;br /&gt;
    ULONG ln_Offset;&lt;br /&gt;
    ULONG ln_Length;&lt;br /&gt;
    ULONG ln_Mode;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct LockList {&lt;br /&gt;
    struct LockNode *lh_Head;&lt;br /&gt;
    struct LockNode *lh_Tail;&lt;br /&gt;
    struct LockNode *lh_TailPred;&lt;br /&gt;
    ULONG lh_Counter;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
/* Pseudo data file */&lt;br /&gt;
#define TESTFILE &amp;quot;t:locktest&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#define LOCK_TEMPLATE &amp;quot;OFFSET/K/N,LENGTH/K/N,EXCLUSIVE/S,IMMEDIATE/S,TIMEOUT/K/N&amp;quot;&lt;br /&gt;
#define UNLOCK_TEMPLATE &amp;quot;OFFSET/K/N,LENGTH/K/N&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#define OFFSET_POS      0&lt;br /&gt;
#define LENGTH_POS      1&lt;br /&gt;
#define EXCLUSIVE_POS   2&lt;br /&gt;
#define IMMEDIATE_POS   3&lt;br /&gt;
#define TIMEOUT_POS     4&lt;br /&gt;
&lt;br /&gt;
struct LockList *locklist;&lt;br /&gt;
&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
    BPTR fh;&lt;br /&gt;
    struct RDArgs *rdargs;&lt;br /&gt;
    struct CSource *csource;&lt;br /&gt;
    UBYTE *cmdbuffer;&lt;br /&gt;
    struct LockNode *lnode, *nnode;&lt;br /&gt;
    LONG error = RETURN_OK;&lt;br /&gt;
&lt;br /&gt;
    if (locklist = AllocVecTags(sizeof(struct LockList), AVT_ClearWithValue, 0, TAG_END))&lt;br /&gt;
    {&lt;br /&gt;
        IExec-&amp;gt;NewList((struct List *)locklist);&lt;br /&gt;
&lt;br /&gt;
        /* Allocate RDArgs structure to parse command lines */&lt;br /&gt;
        if (rdargs = IDOS-&amp;gt;AllocDosObject(DOS_RDARGS, TAG_END))&lt;br /&gt;
        {&lt;br /&gt;
            csource = &amp;amp;rdargs-&amp;gt;RDA_Source;&lt;br /&gt;
&lt;br /&gt;
            /* Get buffer to read command lines in */&lt;br /&gt;
            if (csource-&amp;gt;CS_Buffer = IExec-&amp;gt;AllocVecTags(512, AVT_ClearWithValue, 0, TAG_END))&lt;br /&gt;
            {&lt;br /&gt;
                csource-&amp;gt;CS_Length = 512;&lt;br /&gt;
                csource-&amp;gt;CS_CurChr = 0;&lt;br /&gt;
&lt;br /&gt;
                /* Buffer to isolate command keyword */&lt;br /&gt;
                if (cmdbuffer = IExec-&amp;gt;AllocVecTags(80, AVT_ClearWithValue, 0, TAG_END))&lt;br /&gt;
                {&lt;br /&gt;
                    /* Open a testfile, create it if necessary */&lt;br /&gt;
                    if (fh = IDOS-&amp;gt;Open(TESTFILE, MODE_READWRITE))&lt;br /&gt;
                    {&lt;br /&gt;
                        /* Process command lines */&lt;br /&gt;
                        GetCommandLine(fh, rdargs, cmdbuffer);&lt;br /&gt;
&lt;br /&gt;
                        /* Try to get rid of outstanding record locks */&lt;br /&gt;
                        lnode = locklist-&amp;gt;lh_Head;&lt;br /&gt;
                        while (nnode = lnode-&amp;gt;ln_Succ)&lt;br /&gt;
                        {&lt;br /&gt;
                            /* Try to unlock pending locks */&lt;br /&gt;
                            if ((IDOS-&amp;gt;UnLockRecord(fh,&lt;br /&gt;
                                              lnode-&amp;gt;ln_Offset,&lt;br /&gt;
                                              lnode-&amp;gt;ln_Length)) == DOSFALSE)&lt;br /&gt;
                            {&lt;br /&gt;
                                IDOS-&amp;gt;Printf(&amp;quot;Error unlocking record %ld with offset %ld length %ld\n&amp;quot;,&lt;br /&gt;
                                        lnode-&amp;gt;ln_Counter,&lt;br /&gt;
                                        lnode-&amp;gt;ln_Offset,&lt;br /&gt;
                                        lnode-&amp;gt;ln_Length);&lt;br /&gt;
                                if (IDOS-&amp;gt;IoErr())&lt;br /&gt;
                                    IDOS-&amp;gt;PrintFault(IDOS-&amp;gt;IoErr(), NULL);&lt;br /&gt;
                            }&lt;br /&gt;
                            /* Remove node no matter what */&lt;br /&gt;
                            IExec-&amp;gt;FreeVec(lnode);&lt;br /&gt;
                            lnode = nnode;&lt;br /&gt;
                        };&lt;br /&gt;
&lt;br /&gt;
                        IDOS-&amp;gt;Close(fh);&lt;br /&gt;
                    }&lt;br /&gt;
                    IExec-&amp;gt;FreeVec(cmdbuffer);&lt;br /&gt;
                } else&lt;br /&gt;
                    IDOS-&amp;gt;SetIoErr(ERROR_NO_FREE_STORE);&lt;br /&gt;
&lt;br /&gt;
                IExec-&amp;gt;FreeVec(csource-&amp;gt;CS_Buffer);&lt;br /&gt;
            } else&lt;br /&gt;
                IDOS-&amp;gt;SetIoErr(ERROR_NO_FREE_STORE);&lt;br /&gt;
&lt;br /&gt;
            IDOS-&amp;gt;FreeDosObject(DOS_RDARGS, rdargs);&lt;br /&gt;
        } else&lt;br /&gt;
            IDOS-&amp;gt;SetIoErr(ERROR_NO_FREE_STORE);&lt;br /&gt;
&lt;br /&gt;
        IExec-&amp;gt;FreeVec(locklist);&lt;br /&gt;
    } else&lt;br /&gt;
        IDOS-&amp;gt;SetIoErr(ERROR_NO_FREE_STORE);&lt;br /&gt;
&lt;br /&gt;
    error = IDOS-&amp;gt;IoErr();&lt;br /&gt;
    if (error)&lt;br /&gt;
    {&lt;br /&gt;
        IDOS-&amp;gt;PrintFault(IDOS-&amp;gt;IoErr(), NULL);&lt;br /&gt;
        error = RETURN_FAIL;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return(error);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void GetCommandLine(BPTR fh, struct RDArgs *rdargs, UBYTE *cmdbuffer)&lt;br /&gt;
{&lt;br /&gt;
    struct CSource *csource = &amp;amp;rdargs-&amp;gt;RDA_Source;&lt;br /&gt;
    UBYTE *cmdlinebuffer = csource-&amp;gt;CS_Buffer;&lt;br /&gt;
    LONG error;&lt;br /&gt;
&lt;br /&gt;
    /* Prompt for command line */&lt;br /&gt;
    IDOS-&amp;gt;Write(IDOS-&amp;gt;Output(), &amp;quot;Cmd&amp;gt; &amp;quot;, 5);&lt;br /&gt;
&lt;br /&gt;
    /* Loop forever, waiting for commands */&lt;br /&gt;
    for (;;)&lt;br /&gt;
    {&lt;br /&gt;
        /* Get command line */&lt;br /&gt;
        if ((IDOS-&amp;gt;FGets(IDOS-&amp;gt;Input(), cmdlinebuffer, 512)) != NULL)&lt;br /&gt;
        {&lt;br /&gt;
            /* Use ReadItem() to isolate actual command */&lt;br /&gt;
            error = IDOS-&amp;gt;ReadItem(cmdbuffer, 80, csource);&lt;br /&gt;
&lt;br /&gt;
            /* Break on error */&lt;br /&gt;
            if (error == ITEM_ERROR)&lt;br /&gt;
                break;&lt;br /&gt;
&lt;br /&gt;
            /* Make sure I&#039;ve got something */&lt;br /&gt;
            else if (error != ITEM_NOTHING)&lt;br /&gt;
            {&lt;br /&gt;
                /* cmdbuffer now contains the command:&lt;br /&gt;
                 *&lt;br /&gt;
                 * KNOWN COMMANDS:&lt;br /&gt;
                 * QUIT&lt;br /&gt;
                 * LIST&lt;br /&gt;
                 * LOCKRECORD&lt;br /&gt;
                 * UNLOCKRECORD&lt;br /&gt;
                 */&lt;br /&gt;
                if ((IUtility-&amp;gt;Stricmp(&amp;quot;QUIT&amp;quot;, cmdbuffer)) == 0)&lt;br /&gt;
                    break;&lt;br /&gt;
                else if ((IUtility-&amp;gt;Stricmp(&amp;quot;HELP&amp;quot;, cmdbuffer)) == 0)&lt;br /&gt;
                {&lt;br /&gt;
                    IDOS-&amp;gt;Printf(&amp;quot;Available commands:\n&amp;quot;);&lt;br /&gt;
                    IDOS-&amp;gt;Printf(&amp;quot;LOCKRECORD %s\n&amp;quot;, LOCK_TEMPLATE);&lt;br /&gt;
                    IDOS-&amp;gt;Printf(&amp;quot;UNLOCKRECORD %s\n&amp;quot;, UNLOCK_TEMPLATE);&lt;br /&gt;
                    IDOS-&amp;gt;Printf(&amp;quot;LIST\n&amp;quot;);&lt;br /&gt;
                    IDOS-&amp;gt;Printf(&amp;quot;QUIT\n&amp;quot;);&lt;br /&gt;
                }&lt;br /&gt;
                else if ((IUtility-&amp;gt;Stricmp(&amp;quot;LIST&amp;quot;, cmdbuffer)) == 0)&lt;br /&gt;
                    ListRecordLocks();  /* Show all current locks */&lt;br /&gt;
                else&lt;br /&gt;
                {&lt;br /&gt;
                    /* Note that I&#039;ve already isolated the command&lt;br /&gt;
                     * keyword, so I&#039;m using Source-&amp;gt;CS_CurChr to point&lt;br /&gt;
                     * after it.&lt;br /&gt;
                     */&lt;br /&gt;
                    csource-&amp;gt;CS_Buffer += csource-&amp;gt;CS_CurChr;&lt;br /&gt;
                    csource-&amp;gt;CS_CurChr = 0;&lt;br /&gt;
&lt;br /&gt;
                    if ((IUtility-&amp;gt;Stricmp(&amp;quot;LOCKRECORD&amp;quot;, cmdbuffer)) == 0)&lt;br /&gt;
                        DoLockRecord(fh, rdargs);&lt;br /&gt;
                    else if ((IUtility-&amp;gt;Stricmp(&amp;quot;UNLOCKRECORD&amp;quot;, cmdbuffer)) == 0)&lt;br /&gt;
                        DoUnLockRecord(fh, rdargs);&lt;br /&gt;
                    else&lt;br /&gt;
                        IDOS-&amp;gt;PrintFault(ERROR_NOT_IMPLEMENTED, cmdbuffer);&lt;br /&gt;
&lt;br /&gt;
                    /* Reset CSource */&lt;br /&gt;
                    csource-&amp;gt;CS_Buffer = cmdlinebuffer;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                /* Output new prompt. Make sure csource is OK. */&lt;br /&gt;
                IDOS-&amp;gt;Write(IDOS-&amp;gt;Output(), &amp;quot;Cmd&amp;gt; &amp;quot;, 5);&lt;br /&gt;
                csource-&amp;gt;CS_CurChr = 0;&lt;br /&gt;
            }&lt;br /&gt;
        } else&lt;br /&gt;
            break;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void DoLockRecord(BPTR fh, struct RDArgs *rdargs)&lt;br /&gt;
{&lt;br /&gt;
    struct RDArgs *readargs;&lt;br /&gt;
    LONG rargs[5];&lt;br /&gt;
    ULONG offset, length, timeout, mode;&lt;br /&gt;
    ULONG result;&lt;br /&gt;
    struct LockNode *lnode;&lt;br /&gt;
&lt;br /&gt;
    offset = length = timeout = mode = 0;&lt;br /&gt;
    rargs[0] = rargs[1] = rargs[2] = rargs[3] = rargs[4] = 0;&lt;br /&gt;
&lt;br /&gt;
    if (readargs = IDOS-&amp;gt;ReadArgs(LOCK_TEMPLATE, rargs, rdargs))&lt;br /&gt;
    {&lt;br /&gt;
        if (rargs[OFFSET_POS])&lt;br /&gt;
            offset = *((LONG *)rargs[OFFSET_POS]);&lt;br /&gt;
        if (rargs[LENGTH_POS])&lt;br /&gt;
            length = *((LONG *)rargs[LENGTH_POS]);&lt;br /&gt;
        if (rargs[TIMEOUT_POS])&lt;br /&gt;
            timeout = *((LONG *)rargs[TIMEOUT_POS]);&lt;br /&gt;
&lt;br /&gt;
        /* Type of locking */&lt;br /&gt;
        if (rargs[EXCLUSIVE_POS])&lt;br /&gt;
        {&lt;br /&gt;
            if (rargs[IMMEDIATE_POS])&lt;br /&gt;
                mode = REC_EXCLUSIVE_IMMED;&lt;br /&gt;
            else&lt;br /&gt;
                mode = REC_EXCLUSIVE;&lt;br /&gt;
        }&lt;br /&gt;
        else&lt;br /&gt;
        {&lt;br /&gt;
            if (rargs[IMMEDIATE_POS])&lt;br /&gt;
                mode = REC_SHARED_IMMED;&lt;br /&gt;
            else&lt;br /&gt;
                mode = REC_SHARED;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        rargs[0] = offset;&lt;br /&gt;
        rargs[1] = length;&lt;br /&gt;
        switch (mode)&lt;br /&gt;
        {&lt;br /&gt;
            case REC_EXCLUSIVE_IMMED:&lt;br /&gt;
                rargs[2] = (LONG)&amp;quot;REC_EXCLUSIVE_IMMED&amp;quot;;&lt;br /&gt;
                break;&lt;br /&gt;
            case REC_EXCLUSIVE:&lt;br /&gt;
                rargs[2] = (LONG)&amp;quot;REC_EXCLUSIVE&amp;quot;;&lt;br /&gt;
                break;&lt;br /&gt;
            case REC_SHARED_IMMED:&lt;br /&gt;
                rargs[2] = (LONG)&amp;quot;REC_SHARED_IMMED&amp;quot;;&lt;br /&gt;
                break;&lt;br /&gt;
            case REC_SHARED:&lt;br /&gt;
                rargs[2] = (LONG)&amp;quot;REC_SHARED&amp;quot;;&lt;br /&gt;
                break;&lt;br /&gt;
        }&lt;br /&gt;
        rargs[3] = timeout;&lt;br /&gt;
&lt;br /&gt;
        /* Show what I&#039;m going to do */&lt;br /&gt;
        IUtility-&amp;gt;VFPrintf(Output(),&lt;br /&gt;
            &amp;quot;LockRecord: Offset %ld, Length %ld, Mode %s, Timeout %ld...&amp;quot;,&lt;br /&gt;
            rargs);&lt;br /&gt;
        IDOS-&amp;gt;FFlush(IDOS-&amp;gt;Output());&lt;br /&gt;
&lt;br /&gt;
        /* Lock the record. Parameters are not checked. It is f.e. possible to&lt;br /&gt;
         * specify an offset larger than the size of the file. Possible since&lt;br /&gt;
         * Record Locks are not related to the file itself, only the means for&lt;br /&gt;
         * you to do arbitration.&lt;br /&gt;
         *&lt;br /&gt;
         * Note that the timeout value is in ticks...&lt;br /&gt;
         */&lt;br /&gt;
        result = IDOS-&amp;gt;LockRecord(fh, offset, length, mode, timeout);&lt;br /&gt;
&lt;br /&gt;
        if (result == DOSTRUE)&lt;br /&gt;
        {&lt;br /&gt;
            IDOS-&amp;gt;Write(IDOS-&amp;gt;Output(), &amp;quot;OK\n&amp;quot;, 3);&lt;br /&gt;
&lt;br /&gt;
            /* Add a node to track this record lock */&lt;br /&gt;
            if (lnode = IExec-&amp;gt;AllocVec(sizeof(struct LockNode), AVT_ClearWithValue, 0, TAG_END))&lt;br /&gt;
            {&lt;br /&gt;
                lnode-&amp;gt;ln_Counter = locklist-&amp;gt;lh_Counter++;&lt;br /&gt;
                lnode-&amp;gt;ln_Offset = offset;&lt;br /&gt;
                lnode-&amp;gt;ln_Length = length;&lt;br /&gt;
                lnode-&amp;gt;ln_Mode = mode;&lt;br /&gt;
&lt;br /&gt;
                IExec-&amp;gt;AddTail((struct List *)locklist, (struct Node *)lnode);&lt;br /&gt;
            }&lt;br /&gt;
            else&lt;br /&gt;
            {&lt;br /&gt;
                /* Not enough memory for node. You&#039;re on your own... */&lt;br /&gt;
                IDOS-&amp;gt;Write(IDOS-&amp;gt;Output(), &amp;quot;Not enough memory to track record lock.\n&amp;quot;, 40);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        else&lt;br /&gt;
        {&lt;br /&gt;
            IDOS-&amp;gt;Write(IDOS-&amp;gt;Output(), &amp;quot;FAILED\n&amp;quot;, 7);&lt;br /&gt;
            if (IDOS-&amp;gt;IoErr())&lt;br /&gt;
                IDOS-&amp;gt;PrintFault(IDOS-&amp;gt;IoErr(), NULL);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        /* Release memory associated with readargs */&lt;br /&gt;
        IDOS-&amp;gt;FreeArgs(readargs);&lt;br /&gt;
    } else&lt;br /&gt;
        IDOS-&amp;gt;PrintFault(IDOS-&amp;gt;IoErr(), NULL);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void DoUnLockRecord(BPTR fh, struct RDArgs *rdargs)&lt;br /&gt;
{&lt;br /&gt;
    struct RDArgs *readargs;&lt;br /&gt;
    LONG rargs[2];&lt;br /&gt;
    ULONG offset, length;&lt;br /&gt;
    ULONG result;&lt;br /&gt;
    struct LockNode *lnode;&lt;br /&gt;
&lt;br /&gt;
    offset = length = 0;&lt;br /&gt;
    rargs[0] = rargs[1] = 0;&lt;br /&gt;
&lt;br /&gt;
    if (readargs = IDOS-&amp;gt;ReadArgs(LOCK_TEMPLATE, rargs, rdargs))&lt;br /&gt;
    {&lt;br /&gt;
        if (rargs[OFFSET_POS])&lt;br /&gt;
            offset = *((LONG *)rargs[OFFSET_POS]);&lt;br /&gt;
        if (rargs[LENGTH_POS])&lt;br /&gt;
            length = *((LONG *)rargs[LENGTH_POS]);&lt;br /&gt;
&lt;br /&gt;
        rargs[0] = offset;&lt;br /&gt;
        rargs[1] = length;&lt;br /&gt;
&lt;br /&gt;
        /* Show what I&#039;m going to do */&lt;br /&gt;
        IUtility-&amp;gt;VFPrintf(Output(), &amp;quot;UnLockRecord: Offset %ld, Length %ld...&amp;quot;, rargs);&lt;br /&gt;
        IDOS-&amp;gt;FFlush(IDOS-&amp;gt;Output());&lt;br /&gt;
&lt;br /&gt;
        /* Unlock indicated record with indicated offset and length.&lt;br /&gt;
         * If the same record (same offset/length) is locked multiple times,&lt;br /&gt;
         * only one, the first one in the list , will be unlocked.&lt;br /&gt;
         */&lt;br /&gt;
        result = IDOS-&amp;gt;UnLockRecord(fh, offset, length);&lt;br /&gt;
&lt;br /&gt;
        if (result == DOSTRUE) {&lt;br /&gt;
            IDOS-&amp;gt;Write(IDOS-&amp;gt;Output(), &amp;quot;OK\n&amp;quot;, 3);&lt;br /&gt;
&lt;br /&gt;
            /* Remove node associated with this lock */&lt;br /&gt;
            if (lnode = FindRecordLock(offset, length))&lt;br /&gt;
            {&lt;br /&gt;
                IExec-&amp;gt;Remove((struct Node *)lnode);&lt;br /&gt;
                FreeVec(lnode);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
        else&lt;br /&gt;
        {&lt;br /&gt;
            IDOS-&amp;gt;Write(IDOS-&amp;gt;Output(), &amp;quot;FAILED\n&amp;quot;, 7); /* Keep locknode */&lt;br /&gt;
            if (IDOS-&amp;gt;IoErr())&lt;br /&gt;
                IDOS-&amp;gt;PrintFault(IDOS-&amp;gt;IoErr(), NULL);&lt;br /&gt;
        }&lt;br /&gt;
        /* Release memory associated with readargs */&lt;br /&gt;
        IDOS-&amp;gt;FreeArgs(readargs);&lt;br /&gt;
    } else&lt;br /&gt;
        IDOS-&amp;gt;PrintFault(IDOS-&amp;gt;IoErr(), NULL);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void ListRecordLocks(void)&lt;br /&gt;
{&lt;br /&gt;
    struct LockNode *lnode;&lt;br /&gt;
    LONG rargs[4];&lt;br /&gt;
&lt;br /&gt;
    for (lnode = locklist-&amp;gt;lh_Head; lnode-&amp;gt;ln_Succ; lnode = lnode-&amp;gt;ln_Succ)&lt;br /&gt;
    {&lt;br /&gt;
        rargs[0] = lnode-&amp;gt;ln_Counter;&lt;br /&gt;
        rargs[1] = lnode-&amp;gt;ln_Offset;&lt;br /&gt;
        rargs[2] = lnode-&amp;gt;ln_Length;&lt;br /&gt;
&lt;br /&gt;
        switch (lnode-&amp;gt;ln_Mode)&lt;br /&gt;
        {&lt;br /&gt;
            case REC_EXCLUSIVE_IMMED:&lt;br /&gt;
                rargs[3] = (LONG)&amp;quot;REC_EXCLUSIVE_IMMED&amp;quot;;&lt;br /&gt;
                break;&lt;br /&gt;
            case REC_EXCLUSIVE:&lt;br /&gt;
                rargs[3] = (LONG)&amp;quot;REC_EXCLUSIVE&amp;quot;;&lt;br /&gt;
                break;&lt;br /&gt;
            case REC_SHARED_IMMED:&lt;br /&gt;
                rargs[3] = (LONG)&amp;quot;REC_SHARED_IMMED&amp;quot;;&lt;br /&gt;
                break;&lt;br /&gt;
            case REC_SHARED:&lt;br /&gt;
                rargs[3] = (LONG)&amp;quot;REC_SHARED&amp;quot;;&lt;br /&gt;
                break;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        IUtility-&amp;gt;VFPrintf(IDOS-&amp;gt;Output(), &amp;quot;RecordLock #%ld: Offset %ld Length %ld Mode %s\n&amp;quot;, rargs);&lt;br /&gt;
    }&lt;br /&gt;
    IDOS-&amp;gt;FFlush(IDOS-&amp;gt;Output());&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
struct LockNode *FindRecordLock(ULONG offset, ULONG length)&lt;br /&gt;
{&lt;br /&gt;
    struct LockNode *lnode;&lt;br /&gt;
&lt;br /&gt;
    for (lnode = locklist-&amp;gt;lh_Head; lnode-&amp;gt;ln_Succ; lnode = lnode-&amp;gt;ln_Succ)&lt;br /&gt;
    {&lt;br /&gt;
        if ((lnode-&amp;gt;ln_Offset == offset) &amp;amp;&amp;amp; lnode-&amp;gt;ln_Length == length)&lt;br /&gt;
            return(lnode);&lt;br /&gt;
    }&lt;br /&gt;
    return(NULL);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ExRecLock1.c ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
// ExRecLock1.c&lt;br /&gt;
//&lt;br /&gt;
// This is a simple example of using record locking to create an exclusive record&lt;br /&gt;
// lock on a file, and writing to that record.  The example ExRecLock2 is almost&lt;br /&gt;
// exactly the same as this example, except ExRecLock2 uses the record lock directly&lt;br /&gt;
// after ExRecLock1&#039;s record.  If you try to run ExRecLock1 (or ExRecLock2) while&lt;br /&gt;
// another instance of ExRecLock1 (or ExRecLock2) is running, the second record lock&lt;br /&gt;
// attempt will fail.&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;protob/dos.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define RECORDSIZE   12&lt;br /&gt;
#define RECORDOFFSET 0&lt;br /&gt;
&lt;br /&gt;
UBYTE *string = &amp;quot;ExRecLock1\n&amp;quot;;                           /* This string will be the */&lt;br /&gt;
                                                          /* contents of the record. */&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
    BPTR fh;&lt;br /&gt;
&lt;br /&gt;
    if (fh = IDOS-&amp;gt;Open(&amp;quot;t:testRLock&amp;quot;, MODE_READWRITE))     /* Open the file, creating */&lt;br /&gt;
    {                                                 /*        it if necessary. */&lt;br /&gt;
        if (DOSTRUE == IDOS-&amp;gt;LockRecord(fh,           /* Lock the record as exclusive, */&lt;br /&gt;
                                  RECORDOFFSET, /* and do not wait if it is not  */&lt;br /&gt;
                                  RECORDSIZE,   /* available immediately.        */&lt;br /&gt;
                                  REC_EXCLUSIVE_IMMED, 0))&lt;br /&gt;
        {&lt;br /&gt;
            LONG error = RECORDOFFSET;&lt;br /&gt;
&lt;br /&gt;
                                 /* If the record is beyond the end of the file, */&lt;br /&gt;
            if (IDOS-&amp;gt;Seek(fh, 0, OFFSET_END) &amp;lt; RECORDOFFSET)    /* lengthen the file. */&lt;br /&gt;
                error = IDOS-&amp;gt;SetFileSize(fh, RECORDOFFSET, OFFSET_BEGINNING);&lt;br /&gt;
&lt;br /&gt;
            if (error == RECORDOFFSET)    /* If there was no error with the file */&lt;br /&gt;
            {                             /*                file size, continue. */&lt;br /&gt;
                if (IDOS-&amp;gt;Seek(fh, RECORDOFFSET, OFFSET_BEGINNING) &amp;lt; 0)&lt;br /&gt;
                    IDOS-&amp;gt;PrintFault(IDOS-&amp;gt;IoErr(), &amp;quot;Seek() error&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
                if (IDOS-&amp;gt;Write(fh, string, RECORDSIZE) &amp;lt; 0)&lt;br /&gt;
                    IDOS-&amp;gt;PrintFault(IDOS-&amp;gt;IoErr(), &amp;quot;Write() error&amp;quot;);&lt;br /&gt;
                else&lt;br /&gt;
                    IDOS-&amp;gt;PutStr(&amp;quot;Write successful, &amp;quot;);&lt;br /&gt;
            }&lt;br /&gt;
            IDOS-&amp;gt;PutStr(&amp;quot;Waiting 10 seconds...\n&amp;quot;);&lt;br /&gt;
            IDOS-&amp;gt;Delay(10 * 50);&lt;br /&gt;
            IDOS-&amp;gt;UnLockRecord(fh, RECORDOFFSET, RECORDSIZE);&lt;br /&gt;
        }&lt;br /&gt;
        else IDOS-&amp;gt;PrintFault(IDOS-&amp;gt;IoErr(), &amp;quot;Record Lock Failed&amp;quot;);&lt;br /&gt;
        IDOS-&amp;gt;Close(fh);&lt;br /&gt;
    }&lt;br /&gt;
    else IDOS-&amp;gt;PrintFault(IDOS-&amp;gt;IoErr(), &amp;quot;Open Failed&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== ExRecLock2.c ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
// ExRecLock2.c&lt;br /&gt;
//&lt;br /&gt;
// This is a simple example of using record locking to create an exclusive record&lt;br /&gt;
// lock on a file, and writing to that record.  The example ExRecLock1 is almost&lt;br /&gt;
// exactly the same as this example, except ExRecLock1 uses the record lock directly&lt;br /&gt;
// before ExRecLock2&#039;s record.  If you try to run ExRecLock2 (or ExRecLock1) while&lt;br /&gt;
// another instance of ExRecLock2 (or ExRecLock1) is running, the second record lock&lt;br /&gt;
// attempt will fail.&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;proto/dos.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define RECORDSIZE   12&lt;br /&gt;
#define RECORDOFFSET 12&lt;br /&gt;
&lt;br /&gt;
UBYTE *string = &amp;quot;ExRecLock2\n&amp;quot;;                           /* This string will be the */&lt;br /&gt;
                                                          /* contents of the record. */&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
    BPTR fh;&lt;br /&gt;
&lt;br /&gt;
    if (fh = IDOS-&amp;gt;Open(&amp;quot;t:testRLock&amp;quot;, MODE_READWRITE))     /* Open the file, creating */&lt;br /&gt;
    {                                                 /*        it if necessary. */&lt;br /&gt;
        if (DOSTRUE == IDOS-&amp;gt;LockRecord(fh,           /* Lock the record as exclusive, */&lt;br /&gt;
                                  RECORDOFFSET, /* and do not wait if it is not  */&lt;br /&gt;
                                  RECORDSIZE,   /* available immediately.        */&lt;br /&gt;
                                  REC_EXCLUSIVE_IMMED, 0))&lt;br /&gt;
        {&lt;br /&gt;
            LONG error = RECORDOFFSET;&lt;br /&gt;
&lt;br /&gt;
                                 /* If the record is beyond the end of the file, */&lt;br /&gt;
            if (IDOS-&amp;gt;Seek(fh, 0, OFFSET_END) &amp;lt; RECORDOFFSET)    /* lengthen the file. */&lt;br /&gt;
                error = IDOS-&amp;gt;SetFileSize(fh, RECORDOFFSET, OFFSET_BEGINNING);&lt;br /&gt;
&lt;br /&gt;
            if (error == RECORDOFFSET)    /* If there was no error with the file */&lt;br /&gt;
            {                             /*                file size, continue. */&lt;br /&gt;
                if (IDOS-&amp;gt;Seek(fh, RECORDOFFSET, OFFSET_BEGINNING) &amp;lt; 0)&lt;br /&gt;
                    IDOS-&amp;gt;PrintFault(IDOS-&amp;gt;IoErr(), &amp;quot;Seek() error&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
                if (IDOS-&amp;gt;Write(fh, string, RECORDSIZE) &amp;lt; 0)&lt;br /&gt;
                    IDOS-&amp;gt;PrintFault(IDOS-&amp;gt;IoErr(), &amp;quot;Write() error&amp;quot;);&lt;br /&gt;
                else&lt;br /&gt;
                    IDOS-&amp;gt;PutStr(&amp;quot;Write successful, &amp;quot;);&lt;br /&gt;
            }&lt;br /&gt;
            IDOS-&amp;gt;PutStr(&amp;quot;Waiting 10 seconds...\n&amp;quot;);&lt;br /&gt;
            IDOS-&amp;gt;Delay(10 * 50);&lt;br /&gt;
            IDOS-&amp;gt;UnLockRecord(fh, RECORDOFFSET, RECORDSIZE);&lt;br /&gt;
        }&lt;br /&gt;
        else IDOS-&amp;gt;PrintFault(IDOS-&amp;gt;IoErr(), &amp;quot;Record Lock Failed&amp;quot;);&lt;br /&gt;
        IDOS-&amp;gt;Close(fh);&lt;br /&gt;
    }&lt;br /&gt;
    else IDOS-&amp;gt;PrintFault(IDOS-&amp;gt;IoErr(), &amp;quot;Open Failed&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Costel Mincea</name></author>
	</entry>
	<entry>
		<id>https://wiki.amigaos.net/w/index.php?title=Exec_Interrupts&amp;diff=12550</id>
		<title>Exec Interrupts</title>
		<link rel="alternate" type="text/html" href="https://wiki.amigaos.net/w/index.php?title=Exec_Interrupts&amp;diff=12550"/>
		<updated>2025-01-26T19:30:08Z</updated>

		<summary type="html">&lt;p&gt;Costel Mincea: Text replacement - &amp;quot;&amp;lt;syntaxhighlight&amp;gt;&amp;quot; to &amp;quot;&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{NeedUpdate}}{{CodeReview}}&lt;br /&gt;
== Exec Interrupts ==&lt;br /&gt;
&lt;br /&gt;
== Interrupts ==&lt;br /&gt;
&lt;br /&gt;
Exec manages the decoding, dispatching, and sharing of all system interrupts. This includes control of hardware interrupts, software interrupts, task-relative interrupts (see the discussion of exceptions in [[Exec_Tasks|Exec Tasks]]), and interrupt disabling and enabling. In addition, Exec supports a more extended prioritization of interrupts than that provided in the CPU.&lt;br /&gt;
&lt;br /&gt;
The proper operation of multitasking depends heavily on the consistent management of the interrupt system. Task activities are often driven by inter-system communication that is originated by various interrupts.&lt;br /&gt;
&lt;br /&gt;
=== Sequence of Events During an Interrupt ===&lt;br /&gt;
&lt;br /&gt;
Before useful interrupt handling code can be executed, a considerable amount of hardware and software activity must occur. Each interrupt must propagate through several hardware and software interfaces before application code is finally dispatched:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;A hardware device decides to cause an interrupt and sends a signal to the interrupt control portions of the &#039;&#039;4703&#039;&#039; (Paula) custom chip.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;The &#039;&#039;4703&#039;&#039; interrupt control logic notices this new signal and performs two primary operations. First, it records that the interrupt has been requested by setting a flag bit in the INTREQ register. Second, it examines the INTENA register to determine whether the corresponding interrupt and the interrupt master are enabled. If both are enabled, the &#039;&#039;4703&#039;&#039; generates an interrupt request by placing the priority level of the request onto the three &#039;&#039;68000&#039;&#039; interrupt control input lines (IPL0, IPL1, IPL2).&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;These three signals correspond to seven interrupt priority levels in the 68000. If the priority of the new interrupt is &#039;&#039;greater&#039;&#039; than the current processor priority, an interrupt sequence is initiated. The priority level of the new interrupt is used to index into the top seven words of the processor address space. The odd byte (a vector number) of the indexed word is fetched and then shifted left by two to create an offset into the processor&#039;s auto-vector interrupt table. The vector offsets used are in the range of $064 to $07C. These are labeled as &#039;&#039;interrupt autovectors&#039;&#039; in the &#039;&#039;68000&#039;&#039; manual. The auto-vector table appears in low memory on a &#039;&#039;68000&#039;&#039; system, but its location for other &#039;&#039;68000&#039;&#039; family processors is determined by the processor&#039;s CPU &#039;&#039;Vector Base Register&#039;&#039; (VBR). VBR can be accessed from supervisor mode with the MOVEC instruction.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;The processor then switches into &#039;&#039;supervisor&#039;&#039; mode (if it is not already in that mode), and saves copies of the status register and program counter (PC) onto the top of the &#039;&#039;system&#039;&#039; stack (additional information may be saved by processors other than the &#039;&#039;68000&#039;&#039;). The processor priority is then raised to the level of the active interrupt.&amp;lt;/p&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;From the low memory vector address (calculated in step three above), a 32-bit &#039;&#039;autovector&#039;&#039; address is fetched and loaded into the program counter. This is an entry point into Exec&#039;s interrupt dispatcher.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Exec must now further decode the interrupt by examining the INTREQ and INTENA &#039;&#039;4703&#039;&#039; chip registers. Once the active interrupt has been determined, Exec indexes into an ExecBase array to fetch the interrupt&#039;s handler entry point and handler data pointer addresses.&amp;lt;/p&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;li&amp;gt;&amp;lt;p&amp;gt;Exec now turns control over to the interrupt handler by calling it as if it were a subroutine. This handler may deal with the interrupt directly or may propagate control further by invoking interrupt server chain processing.&amp;lt;/p&amp;gt;&amp;lt;/li&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/ul&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You can see from the above discussion that the interrupt autovectors &#039;&#039;should never be altered by the user&#039;&#039;. If you wish to provide your own system interrupt handler, you must use the Exec SetIntVector() function. You should not change the contents of any autovector location.&lt;br /&gt;
&lt;br /&gt;
Task multiplexing usually occurs as the result of an interrupt. When an interrupt has finished and the processor is about to return to user mode, Exec determines whether task-scheduling attention is required. If a task was signaled during interrupt processing, the task scheduler will be invoked. Because Exec uses preemptive task scheduling, it can be said that the interrupt subsystem is the heart of task multiplexing. If, for some reason, interrupts do not occur, a task might execute forever because it cannot be forced to relinquish the CPU.&lt;br /&gt;
&lt;br /&gt;
[[File:LibTable26-1.png|frame|center|Interrupts by Priority]]&lt;br /&gt;
&lt;br /&gt;
=== Interrupt Priorities ===&lt;br /&gt;
&lt;br /&gt;
Interrupts are prioritized in hardware and software. The 68000 CPU priority at which an interrupt executes is determined strictly by hardware. In addition to this, the software imposes a finer level of &#039;&#039;pseudo-priorities&#039;&#039; on interrupts with the same CPU priority. These pseudo-priorities determine the order in which simultaneous interrupts of the same CPU priority are processed. Multiple interrupts with the same CPU priority but a different pseudo-priority will not interrupt one another. Interrupts are serviced by either an exclusive handler or by server chains to which many servers may be attached, as shown in the Type field of the next table. The table above summarizes all interrupts by priority.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;8520&#039;&#039;s (also called &#039;&#039;CIA&#039;&#039;s) are Amiga peripheral interface adapter chips that generate the INT2 and INT6 interrupts. For more information about them, see the &#039;&#039;Amiga Hardware Reference Manual&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
As described in the Motorola &#039;&#039;68000 Programmer&#039;s Manual&#039;&#039;, interrupts may nest only in the direction of higher priority. Because of the time-critical nature of many interrupts on the Amiga, the CPU priority level &#039;&#039;must never be changed&#039;&#039; by user or system code. When the system is running in user mode (multitasking), the CPU priority level must remain set at zero. When an interrupt occurs, the CPU priority is raised to the level appropriate for that interrupt. Lowering the CPU priority would permit unlimited interrupt recursion on the system stack and would &amp;quot;short-circuit&amp;quot; the interrupt-priority scheme.&lt;br /&gt;
&lt;br /&gt;
Because it is dangerous on the Amiga to hold off interrupts for any period of time, higher-level interrupt code must perform its business and exit promptly. If it is necessary to perform a time-consuming operation as the result of a high-priority interrupt, the operation should be deferred either by posting a &#039;&#039;software interrupt&#039;&#039; or by signalling a task. In this way, interrupt response time is kept to a minimum. Software interrupts are described in a later section.&lt;br /&gt;
&lt;br /&gt;
=== Nonmaskable Interrupt ===&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;68000&#039;&#039; provides a nonmaskable interrupt (NMI) of CPU priority 7. Although this interrupt cannot be generated by the Amiga hardware itself, it can be generated on the expansion bus by external hardware. Because this interrupt does not pass through the &#039;&#039;4703&#039;&#039; interrupt controller circuitry, it is capable of violating system code critical sections. In particular, it short-circuits the DISABLE mutual-exclusion mechanism. Code that uses NMI must not assume that it can access system data structures.&lt;br /&gt;
&lt;br /&gt;
Interrupts are serviced on the Amiga through the use of interrupt &#039;&#039;handlers&#039;&#039; and &#039;&#039;servers&#039;&#039;. An interrupt handler is a system routine that exclusively handles all processing related to a particular &#039;&#039;4703&#039;&#039; interrupt. An interrupt server is one of possibly many system routines that are invoked as the result of a single &#039;&#039;4703&#039;&#039; interrupt. Interrupt servers provide a means of interrupt sharing. This concept is useful for general-purpose interrupts such as vertical blanking.&lt;br /&gt;
&lt;br /&gt;
At system start, Exec designates certain interrupts as handlers and others as server chains. The PORTS, COPER, VERTB, EXTER, and NMI interrupts are initialized as server chains. Therefore, each of these may execute multiple interrupt routines per each interrupt. All other interrupts are designated as handlers and are always used exclusively.&lt;br /&gt;
&lt;br /&gt;
=== Interrupt Data Structure ===&lt;br /&gt;
&lt;br /&gt;
Interrupt handlers and servers are defined by the Exec Interrupt structure. This structure specifies an interrupt routine entry point and data pointer. The C definition of this structure is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct Interrupt&lt;br /&gt;
{&lt;br /&gt;
    struct Node is_Node;&lt;br /&gt;
    APTR        is_Data;&lt;br /&gt;
    VOID      (*is_Code)();&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Once this structure has been properly initialized, it can be used for either a handler or a server.&lt;br /&gt;
&lt;br /&gt;
=== Environment ===&lt;br /&gt;
&lt;br /&gt;
Interrupts execute in an environment different from that of tasks. All interrupts execute in &#039;&#039;supervisor mode&#039;&#039; and utilize the single &#039;&#039;system stack&#039;&#039;. This stack is large enough to handle extreme cases of nested interrupts (of higher priorities). Interrupt processing has no effect on task stack usage.&lt;br /&gt;
&lt;br /&gt;
All interrupt processing code, both handlers and servers, is invoked as assembly code subroutines. Normal assembly code register conventions dictate that the D0, D1, A0 and A1 registers be free for scratch use. In the case of an interrupt handler, some of these registers also contain data that may be useful to the handler code. See the section on handlers below.&lt;br /&gt;
&lt;br /&gt;
Because interrupt processing executes outside the context of most system activities, certain data structures will not be self-consistent and must be considered off limits for all practical purposes. This happens because certain system operations are not atomic in nature and might be interrupted only after executing part of an important instruction sequence. For example, memory allocation and deallocation routines do not disable interrupts. This results in the possibility of interrupting a memory-related routine. In such a case, a memory linked list may be inconsistent during and interrupt. Therefore, interrupt routines must not use any memory allocation or deallocation functions.&lt;br /&gt;
&lt;br /&gt;
In addition, interrupts may not call any system function which might allocate memory, wait, manipulate unprotected lists, or modify ExecBase-&amp;amp;gt;ThisTask data (for example Forbid(), Permit(), and mathieee libraries). In practice, this means that very few system calls may be used within interrupt code. The following functions may generally be used safely within interrupts:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| Alert()&lt;br /&gt;
|-&lt;br /&gt;
| Disable()&lt;br /&gt;
|-&lt;br /&gt;
| Enable()&lt;br /&gt;
|-&lt;br /&gt;
| Signal()&lt;br /&gt;
|-&lt;br /&gt;
| Cause()&lt;br /&gt;
|-&lt;br /&gt;
| GetMsg()&lt;br /&gt;
|-&lt;br /&gt;
| PutMsg()&lt;br /&gt;
|-&lt;br /&gt;
| ReplyMsg()&lt;br /&gt;
|-&lt;br /&gt;
| FindPort()&lt;br /&gt;
|-&lt;br /&gt;
| FindTask()&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
and if you are manipulating your &#039;&#039;own&#039;&#039; List structures while in an interrupt:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| AddHead()&lt;br /&gt;
|-&lt;br /&gt;
| AddTail()&lt;br /&gt;
|-&lt;br /&gt;
| RemHead()&lt;br /&gt;
|-&lt;br /&gt;
| RemTail()&lt;br /&gt;
|-&lt;br /&gt;
| FindName()&lt;br /&gt;
|-&lt;br /&gt;
| FindIName()&lt;br /&gt;
|-&lt;br /&gt;
| GetHead()&lt;br /&gt;
|-&lt;br /&gt;
| GetTail()&lt;br /&gt;
|-&lt;br /&gt;
| GetSucc()&lt;br /&gt;
|-&lt;br /&gt;
| GetPred()&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In addition, certain devices (notably the timer device) specifically allow limited use of SendIO() and BeginIO() within interrupts.&lt;br /&gt;
&lt;br /&gt;
=== Interrupt Handlers ===&lt;br /&gt;
&lt;br /&gt;
As described above, an interrupt handler is a system routine that exclusively handles all processing related to a particular &#039;&#039;4703&#039;&#039; interrupt. There can only be one handler per &#039;&#039;4703&#039;&#039; interrupt. Every interrupt handler consists of an Interrupt structure (as defined above) and a single assembly code routine. Optionally, a data structure pointer may also be provided. This is particularly useful for ROM-resident interrupt code.&lt;br /&gt;
&lt;br /&gt;
An interrupt handler is passed control as if it were a subroutine of Exec. Once the handler has finished its business, it must return to Exec by executing an RTS (return from subroutine) instruction rather than an RTE (return from exception) instruction. Interrupt handlers should be kept very short to minimize service-time overhead and thus minimize the possibilities of interrupt overruns. As described above, an interrupt handler has the normal scratch registers at its disposal. In addition, A5 and A6 are free for use. These registers are saved by Exec as part of the interrupt initiation cycle.&lt;br /&gt;
&lt;br /&gt;
For the sake of efficiency, Exec passes certain register parameters to the handler (see the list below). These register values may be utilized to trim a few microseconds off the execution time of a handler. All of the following registers (D0/D1/A0/A1/A5/A6) may be used as scratch registers by an interrupt handler, and need not be restored prior to returning.&lt;br /&gt;
&lt;br /&gt;
{{Note|title=Don&#039;t Make Assumptions About Registers|text=Interrupt servers have different register usage rules (see the &amp;quot;Interrupt Servers&amp;quot; section).}}&lt;br /&gt;
&lt;br /&gt;
==== Interrupt Handler Register Usage ====&lt;br /&gt;
&lt;br /&gt;
Here are the register conventions for interrupt handlers.&lt;br /&gt;
&lt;br /&gt;
; D0&lt;br /&gt;
: Contains no valid information.&lt;br /&gt;
&lt;br /&gt;
; D1&lt;br /&gt;
: Contains the &#039;&#039;4703&#039;&#039; INTENAR and INTREQR registers values &#039;&#039;&#039;AND&#039;&#039;&#039;&#039;ed together. This results in an indication of which interrupts are enabled &#039;&#039;and&#039;&#039; active.&lt;br /&gt;
&lt;br /&gt;
; A0&lt;br /&gt;
: Points to the base address of the Amiga custom chips. This information is useful for performing indexed instruction access to the chip registers.&lt;br /&gt;
&lt;br /&gt;
; A1&lt;br /&gt;
: Points to the data area specified by the is_Data field of the Interrupt structure. Because this pointer is always fetched (regardless of whether you use it), it is to your advantage to make some use of it.&lt;br /&gt;
&lt;br /&gt;
; A5&lt;br /&gt;
: Is used as a vector to your interrupt code.&lt;br /&gt;
&lt;br /&gt;
; A6&lt;br /&gt;
: Points to the Exec library base (SysBase). You may use this register to call Exec functions or set it up as a base register to access your own library or device.&lt;br /&gt;
&lt;br /&gt;
Interrupt handlers are established by passing the Exec function SetIntVector(), your initialized Interrupt structure, and the &#039;&#039;4703&#039;&#039; interrupt bit number of interest. The parameters for this function are as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
SetIntVector(ULONG intNumber, struct Interrupt *interrupt)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first argument is the bit number for which this interrupt server is to respond (example INTB_VERTB). The possible bits for interrupts are defined in &amp;amp;lt;hardware/intbits.h&amp;amp;gt;. The second argument is the address of an interrupt server node as described earlier in this article. Keep in mind that certain interrupts are established as server chains and should not be accessed as handlers.&lt;br /&gt;
&lt;br /&gt;
The following example demonstrates initialization and installation of an assembler interrupt handler. See the [[Resources|Resources]] for more information on allocating resources, and [[Serial_Device|Serial Device]] for the more common method of serial communications.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
;/* rbf.c - Execute me to compile me with SAS C 5.10&lt;br /&gt;
LC -d0 -b1 -cfistq -v -y -j73 rbf.c&lt;br /&gt;
Blink FROM LIB:c.o,rbf.o,rbfhandler.o TO rbf LIBRARY LIB:LC.lib,LIB:Amiga.lib&lt;br /&gt;
quit&lt;br /&gt;
&lt;br /&gt;
** rbf.c - serial receive buffer full interrupt handler example.&lt;br /&gt;
** Must be linked with assembler handler rbfhandler.o&lt;br /&gt;
**&lt;br /&gt;
** To receive characters, this example requires ASCII serial input&lt;br /&gt;
** at your Amiga&#039;s current serial hardware baud rate (ie. 9600 after&lt;br /&gt;
** reboot, else last baud rate used)&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#include &amp;amp;lt;exec/execbase.h&amp;amp;gt;&lt;br /&gt;
#include &amp;amp;lt;exec/memory.h&amp;amp;gt;&lt;br /&gt;
#include &amp;amp;lt;exec/interrupts.h&amp;amp;gt;&lt;br /&gt;
#include &amp;amp;lt;resources/misc.h&amp;amp;gt;&lt;br /&gt;
#include &amp;amp;lt;hardware/custom.h&amp;amp;gt;&lt;br /&gt;
#include &amp;amp;lt;hardware/intbits.h&amp;amp;gt;&lt;br /&gt;
#include &amp;amp;lt;dos/dos.h&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;amp;lt;clib/exec_protos.h&amp;amp;gt;&lt;br /&gt;
#include &amp;amp;lt;clib/misc_protos.h&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;amp;lt;stdio.h&amp;amp;gt;&lt;br /&gt;
#include &amp;amp;lt;string.h&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
#ifdef LATTICE&lt;br /&gt;
int CXBRK(void)  { return(0); }  /* Disable Lattice CTRL/C handling */&lt;br /&gt;
void chkabort(void) { return; }  /* really */&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#define BUFFERSIZE 256&lt;br /&gt;
&lt;br /&gt;
extern void RBFHandler();   /* proto for asm interrupt handler */&lt;br /&gt;
void main(void);&lt;br /&gt;
&lt;br /&gt;
struct MiscResource *MiscBase;&lt;br /&gt;
extern struct ExecBase *SysBase;&lt;br /&gt;
extern struct Custom far custom;    /* defined in amiga.lib */&lt;br /&gt;
&lt;br /&gt;
static UBYTE *allocname = &amp;amp;quot;rbf-example&amp;amp;quot;;&lt;br /&gt;
&lt;br /&gt;
struct RBFData {&lt;br /&gt;
    struct Task *rd_Task;&lt;br /&gt;
    ULONG rd_Signal;&lt;br /&gt;
    ULONG rd_BufferCount;&lt;br /&gt;
    UBYTE rd_CharBuffer[BUFFERSIZE + 2];&lt;br /&gt;
    UBYTE rd_FlagBuffer[BUFFERSIZE + 2];&lt;br /&gt;
    UBYTE rd_Name[32];&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
void main(void)&lt;br /&gt;
{&lt;br /&gt;
    struct RBFData *rbfdata;&lt;br /&gt;
    UBYTE *currentuser;&lt;br /&gt;
    BYTE signr;&lt;br /&gt;
    struct Device *serdevice;&lt;br /&gt;
    struct Interrupt *rbfint, *priorint;&lt;br /&gt;
    BOOL priorenable;&lt;br /&gt;
    ULONG signal;&lt;br /&gt;
&lt;br /&gt;
    if (MiscBase = OpenResource(&amp;amp;quot;misc.resource&amp;amp;quot;))&lt;br /&gt;
    {&lt;br /&gt;
        currentuser = AllocMiscResource(MR_SERIALPORT, allocname);        /* Allocate the serial */&lt;br /&gt;
        if (currentuser)                                                  /* port registers.     */&lt;br /&gt;
        {&lt;br /&gt;
            printf(&amp;amp;quot;serial hardware allocated by %s. Trying to remove it\n&amp;amp;quot;,&lt;br /&gt;
                   currentuser);                                         /* Hey! someone got it! */&lt;br /&gt;
            Forbid();&lt;br /&gt;
            if (serdevice = (struct Device *)FindName(&amp;amp;amp;SysBase-&amp;amp;gt;DeviceList, currentuser))&lt;br /&gt;
                RemDevice(serdevice);&lt;br /&gt;
            Permit();&lt;br /&gt;
&lt;br /&gt;
            currentuser = AllocMiscResource(MR_SERIALPORT, allocname);          /* and try again */&lt;br /&gt;
        }&lt;br /&gt;
        if (currentuser == NULL)&lt;br /&gt;
        {                                                                      /* Get the serial */&lt;br /&gt;
            currentuser = AllocMiscResource(MR_SERIALBITS, allocname);         /* control bits.  */&lt;br /&gt;
            if (currentuser)&lt;br /&gt;
            {&lt;br /&gt;
                printf(&amp;amp;quot;serial control allocated by %s\n&amp;amp;quot;, currentuser);            /* Give up. */&lt;br /&gt;
                FreeMiscResource(MR_SERIALPORT);&lt;br /&gt;
            }&lt;br /&gt;
            else&lt;br /&gt;
            {                                                                  /* Got them both. */&lt;br /&gt;
                printf(&amp;amp;quot;serial hardware allocated\n&amp;amp;quot;);&lt;br /&gt;
                if ((signr = AllocSignal(-1)) != -1)          /* Allocate a signal bit for the   */&lt;br /&gt;
                {                                             /* interrupt handler to signal us. */&lt;br /&gt;
                    if (rbfint = AllocMem(sizeof(struct Interrupt), MEMF_PUBLIC|MEMF_CLEAR))&lt;br /&gt;
                    {&lt;br /&gt;
                        if (rbfdata = AllocMem(sizeof(struct RBFData), MEMF_PUBLIC|MEMF_CLEAR))&lt;br /&gt;
                        {&lt;br /&gt;
                            rbfdata-&amp;amp;gt;rd_Task = FindTask(NULL);        /* Init rfbdata structure. */&lt;br /&gt;
                            rbfdata-&amp;amp;gt;rd_Signal = 1L &amp;amp;lt;&amp;amp;lt; signr;&lt;br /&gt;
&lt;br /&gt;
                            rbfint-&amp;amp;gt;is_Node.ln_Type = NT_INTERRUPT;      /* Init interrupt node. */&lt;br /&gt;
                            strcpy(rbfdata-&amp;amp;gt;rd_Name, allocname);&lt;br /&gt;
                            rbfint-&amp;amp;gt;is_Node.ln_Name = rbfdata-&amp;amp;gt;rd_Name;&lt;br /&gt;
                            rbfint-&amp;amp;gt;is_Data = (APTR)rbfdata;&lt;br /&gt;
                            rbfint-&amp;amp;gt;is_Code = RBFHandler;&lt;br /&gt;
                                                                        /* Save state of RBF and */&lt;br /&gt;
                            priorenable = custom.intenar &amp;amp;amp; INTF_RBF ? TRUE : FALSE; /* interrupt */&lt;br /&gt;
                            custom.intena = INTF_RBF;                             /* disable it. */&lt;br /&gt;
                            priorint = SetIntVector(INTB_RBF, rbfint);&lt;br /&gt;
&lt;br /&gt;
                            if (priorint) printf(&amp;amp;quot;replaced the %s RBF interrupt handler\n&amp;amp;quot;,&lt;br /&gt;
                                                 priorint-&amp;amp;gt;is_Node.ln_Name);&lt;br /&gt;
                            printf(&amp;amp;quot;enabling RBF interrupt\n&amp;amp;quot;);&lt;br /&gt;
                            custom.intena = INTF_SETCLR | INTF_RBF;&lt;br /&gt;
&lt;br /&gt;
                            printf(&amp;amp;quot;waiting for buffer to fill up. Use CTRL-C to break\n&amp;amp;quot;);&lt;br /&gt;
                            signal = Wait(1L &amp;amp;lt;&amp;amp;lt; signr | SIGBREAKF_CTRL_C);&lt;br /&gt;
&lt;br /&gt;
                            if (signal &amp;amp;amp; SIGBREAKF_CTRL_C) printf(&amp;amp;quot;&amp;amp;gt;break&amp;amp;lt;\n&amp;amp;quot;);&lt;br /&gt;
                            printf(&amp;amp;quot;Character buffer contains:\n%s\n&amp;amp;quot;, rbfdata-&amp;amp;gt;rd_CharBuffer);&lt;br /&gt;
&lt;br /&gt;
                            custom.intena = INTF_RBF;               /* Restore previous handler. */&lt;br /&gt;
                            SetIntVector(INTB_RBF, priorint);&lt;br /&gt;
                                                                  /* Enable it if it was enabled */&lt;br /&gt;
                            if (priorenable) custom.intena = INTF_SETCLR|INTF_RBF;    /* before. */&lt;br /&gt;
&lt;br /&gt;
                            FreeMem(rbfdata, sizeof(struct RBFData));&lt;br /&gt;
                        }&lt;br /&gt;
                        else  printf(&amp;amp;quot;can&#039;t allocate memory for rbf data\n&amp;amp;quot;);&lt;br /&gt;
                        FreeMem(rbfint, sizeof(struct Interrupt));&lt;br /&gt;
                    }&lt;br /&gt;
                    else printf(&amp;amp;quot;can&#039;t allocate memory for interrupt structure\n&amp;amp;quot;);&lt;br /&gt;
                    FreeSignal(signr);&lt;br /&gt;
                }&lt;br /&gt;
                else printf(&amp;amp;quot;can&#039;t allocate signal\n&amp;amp;quot;);&lt;br /&gt;
&lt;br /&gt;
                FreeMiscResource(MR_SERIALBITS);   /* release serial hardware */&lt;br /&gt;
                FreeMiscResource(MR_SERIALPORT);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    } /* There is no &#039;CloseResource()&#039; function */&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The assembler interrupt handler code, RBFHandler, reads the complete word of serial input data from the serial hardware and then separates the character and flag bytes into separate buffers. When the buffers are full, the handler signals the main process causing main to print the character buffer contents, remove the handler, and exit.&lt;br /&gt;
&lt;br /&gt;
{{Note|text=The data structure containing the signal to use, task address pointer, and buffers is allocated and initialized in main(), and passed to the handler (shown below) via the is_Data pointer of the Interrupt structure.}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
* rbfhandler.asm. Example interrupt handler for rbf.&lt;br /&gt;
*&lt;br /&gt;
* Assembled with Howesoft Adapt 680x0 Macro Assembler Rel. 1.0&lt;br /&gt;
* hx68 from: rbfhandler.asm to rbfhandler.o INCDIR include:&lt;br /&gt;
* blink from lib:c.o rbf.o rbfhandler.o to rbf lib lib:lc.lib lib:amiga.lib&lt;br /&gt;
*&lt;br /&gt;
    INCLUDE &amp;amp;quot;exec/types.i&amp;amp;quot;&lt;br /&gt;
    INCLUDE &amp;amp;quot;hardware/custom.i&amp;amp;quot;&lt;br /&gt;
    INCLUDE &amp;amp;quot;hardware/intbits.i&amp;amp;quot;&lt;br /&gt;
&lt;br /&gt;
        XDEF    _RBFHandler&lt;br /&gt;
&lt;br /&gt;
JSRLIB MACRO&lt;br /&gt;
       XREF _LVO\1&lt;br /&gt;
       JSR  _LVO\1(A6)&lt;br /&gt;
       ENDM&lt;br /&gt;
&lt;br /&gt;
BUFLEN    EQU    256&lt;br /&gt;
&lt;br /&gt;
       STRUCTURE RBFDATA,0&lt;br /&gt;
        APTR   rd_task&lt;br /&gt;
        ULONG  rd_signal&lt;br /&gt;
        UWORD  rd_buffercount&lt;br /&gt;
        STRUCT rd_charbuffer,BUFLEN+2&lt;br /&gt;
        STRUCT rd_flagbuffer,BUFLEN+2&lt;br /&gt;
        STRUCT rd_name,32&lt;br /&gt;
        LABEL RBFDATA_SIZEOF&lt;br /&gt;
&lt;br /&gt;
* Entered with:&lt;br /&gt;
*  D0 == scratch&lt;br /&gt;
*  D1 == INTENAT &amp;amp;amp; INTREQR (scratch)&lt;br /&gt;
*  A0 == custom chips (scratch)&lt;br /&gt;
*  A1 == is_Data which is RBFDATA structure (scratch)&lt;br /&gt;
*  A5 == vector to our code (scratch)&lt;br /&gt;
*  A6 == pointer to ExecBase (scratch)&lt;br /&gt;
*&lt;br /&gt;
* Note - This simple handler just receives one buffer full of serial&lt;br /&gt;
* input data, signals main, then ignores all subsequent serial data.&lt;br /&gt;
*&lt;br /&gt;
    section code&lt;br /&gt;
&lt;br /&gt;
_RBFHandler:                            ;entry to our interrupt handler&lt;br /&gt;
&lt;br /&gt;
        MOVE.W  serdatr(A0),D1          ;get the input word (flags and char)&lt;br /&gt;
&lt;br /&gt;
        MOVE.W  rd_buffercount(A1),D0   ;get our buffer index&lt;br /&gt;
        CMPI.W  #BUFLEN,D0              ;no more room in our buffer ?&lt;br /&gt;
        BEQ.S   ExitHandler             ;yes - just exit (ignore new char)&lt;br /&gt;
        LEA.L   rd_charbuffer(A1),A5    ;else get our character buffer address&lt;br /&gt;
        MOVE.B  D1,0(A5,D0.W)           ;store character in our character buffer&lt;br /&gt;
        LEA.L   rd_flagbuffer(A1),A5    ;get our flag buffer address&lt;br /&gt;
        LSR.W   #8,d1                   ;shift flags down&lt;br /&gt;
        MOVE.B  D1,0(A5,D0.W)           ;store flags in flagbuffer&lt;br /&gt;
&lt;br /&gt;
        ADDQ.W  #1,D0                   ;increment our buffer index&lt;br /&gt;
        MOVE.W  D0,rd_buffercount(A1)   ;   and replace it&lt;br /&gt;
        CMPI.W  #BUFLEN,D0              ;did our buffer just become full ?&lt;br /&gt;
        BNE.S   ExitHandler             ;no - we can exit&lt;br /&gt;
        MOVE.L  A0,-(SP)                ;yes - save custom&lt;br /&gt;
        MOVE.L  rd_signal(A1),D0        ;get signal allocated in main()&lt;br /&gt;
        MOVE.L  rd_task(A1),A1          ;and pointer to main task&lt;br /&gt;
        JSRLIB  Signal                  ;tell main we are full&lt;br /&gt;
        MOVE.L  (SP)+,A0                ;restore custom&lt;br /&gt;
                                        ;Note: system call trashed D0-D1/A0-A1&lt;br /&gt;
ExitHandler:&lt;br /&gt;
        MOVE.W  #INTF_RBF,intreq(A0)    ;clear the interrupt&lt;br /&gt;
        RTS                             ;return to exec&lt;br /&gt;
&lt;br /&gt;
        END&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Interrupt Servers ===&lt;br /&gt;
&lt;br /&gt;
As mentioned above, an interrupt server is one of possibly many system interrupt routines that are invoked as the result of a single &#039;&#039;4703&#039;&#039; interrupt. Interrupt servers provide an essential mechanism for interrupt sharing.&lt;br /&gt;
&lt;br /&gt;
Interrupt servers must be used for PORTS, COPER, VERTB, EXTER, or NMI interrupts. For these interrupts, all servers are linked together in a chain. Every server in the chain will be called in turn as long as the previous server returned with the processor&#039;s Z (zero) flag set. If you determine that an interrupt was specifically for your server, you should return with the processor&#039;s Z flag cleared (non-zero condition) so that the remaining servers on the chain will be skipped.&lt;br /&gt;
&lt;br /&gt;
{{Note|title=Use The Z Flag|text=VERTB (vertical blank) servers should &#039;&#039;always&#039;&#039; return with the Z (zero) flag set. The processor Z flag is used rather than the normal function convention of returning a result in D0 because it may be tested more quickly by Exec upon the server&#039;s return.}}&lt;br /&gt;
&lt;br /&gt;
The easiest way to set the condition code register is to do an immediate move to the D0 register as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SetZflag_Calls_Next:&lt;br /&gt;
        MOVEQ   #0,D0&lt;br /&gt;
        RTS&lt;br /&gt;
&lt;br /&gt;
ClrZflag_Ends_Chain:&lt;br /&gt;
        MOVEQ   #1,D0&lt;br /&gt;
        RTS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The same Exec Interrupt structure used for handlers is also used for servers. Also, like interrupt handlers, servers must terminate their code with an RTS instruction.&lt;br /&gt;
&lt;br /&gt;
Interrupt servers are called in priority order. The priority of a server is specified in its is_Node.ln_Pri field. Higher-priority servers are called earlier than lower-priority servers. Adding and removing interrupt servers from a particular chain is accomplished with the Exec AddIntServer() and RemIntServer() functions. These functions require you to specify both the &#039;&#039;4703&#039;&#039; interrupt number and a properly initialized Interrupt structure.&lt;br /&gt;
&lt;br /&gt;
Servers have different register values passed than handlers do. A server cannot count on the D0, D1, A0, or A6 registers containing any useful information. However, the highest priority system vertical blank server currently expects to receive a pointer to the custom chips A0. Therefore, if you install a vertical blank server at priority 10 or greater, you must place custom ($DF¬†F000) in A0 before exiting. Other than that, a server is free to use D0-D1 and A0-A1/A5-A6 as scratch.&lt;br /&gt;
&lt;br /&gt;
==== Interrupt Server Register Usage ====&lt;br /&gt;
&lt;br /&gt;
; D0&lt;br /&gt;
: Scratch.&lt;br /&gt;
&lt;br /&gt;
; D1&lt;br /&gt;
: Scratch.&lt;br /&gt;
&lt;br /&gt;
; A0&lt;br /&gt;
: Scratch except in certain cases (see note above).&lt;br /&gt;
&lt;br /&gt;
; A1&lt;br /&gt;
: Points to the data area specified by the is_Data field of the Interrupt structure. Because this pointer is always fetched (regardless of whether you use it), it is to your advantage to make some use of it (scratch).&lt;br /&gt;
&lt;br /&gt;
; A5&lt;br /&gt;
: Points to your interrupt code (scratch).&lt;br /&gt;
&lt;br /&gt;
; A6&lt;br /&gt;
: Scratch.&lt;br /&gt;
&lt;br /&gt;
In a server chain, the interrupt is cleared automatically by the system. Having a server clear its interrupt is not recommended and not necessary (clearing could cause the loss of an interrupt on PORTS or EXTER).&lt;br /&gt;
&lt;br /&gt;
Here is an example of a program to install and remove a low-priority vertical blank interrupt server:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
;/* vertb.c - Execute me to compile me with SAS C 5.10&lt;br /&gt;
LC -d0 -b1 -cfistq -v -y -j73 vertb.c&lt;br /&gt;
Blink FROM LIB:c.o,vertb.o,vertbserver.o TO vertb LIBRARY LIB:LC.lib,LIB:Amiga.lib&lt;br /&gt;
quit ; */&lt;br /&gt;
/* vertb.c - Vertical blank interrupt server example.  Must be linked with vertbserver.o. */&lt;br /&gt;
&lt;br /&gt;
#include &amp;amp;lt;exec/memory.h&amp;amp;gt;&lt;br /&gt;
#include &amp;amp;lt;exec/interrupts.h&amp;amp;gt;&lt;br /&gt;
#include &amp;amp;lt;dos/dos.h&amp;amp;gt;&lt;br /&gt;
#include &amp;amp;lt;hardware/custom.h&amp;amp;gt;&lt;br /&gt;
#include &amp;amp;lt;hardware/intbits.h&amp;amp;gt;&lt;br /&gt;
#include &amp;amp;lt;clib/exec_protos.h&amp;amp;gt;&lt;br /&gt;
#include &amp;amp;lt;stdio.h&amp;amp;gt;&lt;br /&gt;
&lt;br /&gt;
#ifdef LATTICE&lt;br /&gt;
int CXBRK(void)  { return(0); }  /* Disable Lattice CTRL/C handling */&lt;br /&gt;
void chkabort(void) { return; }  /* really */&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
extern void VertBServer();  /* proto for asm interrupt server */&lt;br /&gt;
&lt;br /&gt;
void main(void)&lt;br /&gt;
{&lt;br /&gt;
    struct Interrupt *vbint;&lt;br /&gt;
    ULONG counter = 0;&lt;br /&gt;
    ULONG endcount;&lt;br /&gt;
                                                       /* Allocate memory for  */&lt;br /&gt;
    if (vbint = AllocMem(sizeof(struct Interrupt),     /* interrupt node. */&lt;br /&gt;
                         MEMF_PUBLIC|MEMF_CLEAR))&lt;br /&gt;
    {&lt;br /&gt;
        vbint-&amp;amp;gt;is_Node.ln_Type = NT_INTERRUPT;         /* Initialize the node. */&lt;br /&gt;
        vbint-&amp;amp;gt;is_Node.ln_Pri = -60;&lt;br /&gt;
        vbint-&amp;amp;gt;is_Node.ln_Name = &amp;amp;quot;VertB-Example&amp;amp;quot;;&lt;br /&gt;
        vbint-&amp;amp;gt;is_Data = (APTR)&amp;amp;amp;counter;&lt;br /&gt;
        vbint-&amp;amp;gt;is_Code = VertBServer;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        AddIntServer(INTB_VERTB, vbint); /* Kick this interrupt server to life. */&lt;br /&gt;
&lt;br /&gt;
        printf(&amp;amp;quot;VBlank server will increment a counter every frame.\n&amp;amp;quot;);&lt;br /&gt;
        printf(&amp;amp;quot;counter started at zero, CTRL-C to remove server\n&amp;amp;quot;);&lt;br /&gt;
&lt;br /&gt;
        Wait(SIGBREAKF_CTRL_C);&lt;br /&gt;
        endcount = counter;&lt;br /&gt;
        printf(&amp;amp;quot;%ld vertical blanks occurred\nRemoving server\n&amp;amp;quot;, endcount);&lt;br /&gt;
&lt;br /&gt;
        RemIntServer(INTB_VERTB, vbint);&lt;br /&gt;
        FreeMem(vbint, sizeof(struct Interrupt));&lt;br /&gt;
    }&lt;br /&gt;
    else printf(&amp;amp;quot;Can&#039;t allocate memory for interrupt node\n&amp;amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is the assembler VertBServer installed by the C example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
* vertbserver.asm. Example simple interrupt server for vertical blank&lt;br /&gt;
*&lt;br /&gt;
* Assembled with Howesoft Adapt 680x0 Macro Assembler Rel. 1.0&lt;br /&gt;
* hx68 from: vertbserver.asm to vertbserver.o INCDIR include:&lt;br /&gt;
* blink from lib:c.o vertb.o vertbserver.o to vertb lib lib:lc.lib lib:amiga.lib&lt;br /&gt;
*&lt;br /&gt;
    INCLUDE &amp;amp;quot;exec/types.i&amp;amp;quot;&lt;br /&gt;
    INCLUDE &amp;amp;quot;hardware/custom.i&amp;amp;quot;&lt;br /&gt;
    INCLUDE &amp;amp;quot;hardware/intbits.i&amp;amp;quot;&lt;br /&gt;
&lt;br /&gt;
        XDEF    _VertBServer&lt;br /&gt;
&lt;br /&gt;
* Entered with:       A0 == scratch (execpt for highest pri vertb server)&lt;br /&gt;
*  D0 == scratch      A1 == is_Data&lt;br /&gt;
*  D1 == scratch      A5 == vector to interrupt code (scratch)&lt;br /&gt;
*                     A6 == scratch&lt;br /&gt;
*&lt;br /&gt;
    section code&lt;br /&gt;
&lt;br /&gt;
_VertBServer:&lt;br /&gt;
        ADDI.L  #1,(a1)           ; increments counter is_Data points to&lt;br /&gt;
        MOVEQ.L #0,d0             ; set Z flag to continue to process other vb-servers&lt;br /&gt;
        RTS                       ;return to exec&lt;br /&gt;
        END&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Software Interrupts ==&lt;br /&gt;
&lt;br /&gt;
Exec provides a means of generating &#039;&#039;software interrupts&#039;&#039;. Software interrupts execute at a priority higher than that of tasks but lower than that of hardware interrupts, so they are often used to defer hardware interrupt processing to a lower priority. Software interrupts use the same Interrupt data structure as hardware interrupts. As described above, this structure contains pointers to both interrupt code and data, and should be initialized as node type NT_INTERRUPT (not NT_SOFTINT which is an internal Exec flag).&lt;br /&gt;
&lt;br /&gt;
A software interrupt is usually activated with the Cause() function. If this function is called from a task, the task will be interrupted and the software interrupt will occur. If it is called from a hardware interrupt, the software interrupt will not be processed until the system exits from its last hardware interrupt. If a software interrupt occurs from within another software interrupt, it is not processed until the current one is completed. However, individual software interrupts do not nest, and will not be caused if already running as a software interrupt.&lt;br /&gt;
&lt;br /&gt;
Software interrupts are prioritized. Unlike interrupt servers, software interrupts have only five allowable priority levels: -32, -16, 0, +16, and +32. The priority should be put into the ln_Pri field prior to calling Cause().&lt;br /&gt;
&lt;br /&gt;
Software interrupts can also be generated by message arrival at a PA_SOFTINT message port. The applications of this technique are limited since it is not permissible, with most devices, to send IO requests from within interrupt code. However, the timer.device does allow such interactions, so a self-perpetuating PA_SOFTINT timer port can provide an application with quite consistent timing under varying multitasking loads. The following example demonstrates use of a software interrupt and a PA_SOFTINT port. See the [[Exec_Messages_and_Ports|Exec Messages and Ports]] for more information about messages and ports.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
/* timersoftint.c - Timer device software interrupt message port example. */&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;exec/memory.h&amp;gt;&lt;br /&gt;
#include &amp;lt;exec/interrupts.h&amp;gt;&lt;br /&gt;
#include &amp;lt;devices/timer.h&amp;gt;&lt;br /&gt;
#include &amp;lt;dos/dos.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/exec.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/dos.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define MICRO_DELAY 1000&lt;br /&gt;
#define OFF     0&lt;br /&gt;
#define ON      1&lt;br /&gt;
#define STOPPED 2&lt;br /&gt;
&lt;br /&gt;
struct TSIData {&lt;br /&gt;
    uint32 tsi_Counter;&lt;br /&gt;
    uint32 tsi_Flag;&lt;br /&gt;
    struct MsgPort *tsi_Port;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct TSIData *tsidata;&lt;br /&gt;
&lt;br /&gt;
void tsoftcode(void);    /* Prototype for our software interrupt code */&lt;br /&gt;
&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
    uint32 endcount;&lt;br /&gt;
&lt;br /&gt;
    /* Allocate message port, data &amp;amp; interrupt structures. */&lt;br /&gt;
    tsidata = IExec-&amp;gt;AllocVecTags(sizeof(struct TSIData),&lt;br /&gt;
      AVT_Type, MEMF_SHARED,&lt;br /&gt;
      AVT_Lock, TRUE,&lt;br /&gt;
      TAG_END);&lt;br /&gt;
&lt;br /&gt;
    /* Set up the (software)interrupt structure. Note that this task runs at  */&lt;br /&gt;
    /* priority 0. Software interrupts may only be priority -32, -16, 0, +16, */&lt;br /&gt;
    /* +32. Also note that the correct node type for a software interrupt is   */&lt;br /&gt;
    /* NT_INTERRUPT. (NT_SOFTINT is an internal Exec flag). This is the same  */&lt;br /&gt;
    /* setup as that for a software interrupt which you Cause(). */&lt;br /&gt;
    struct Interrupt *softint = IExec-&amp;gt;AllocSysObjectTags(ASOT_INTERRUPT,&lt;br /&gt;
      ASOINTR_Code, tsoftcode,&lt;br /&gt;
      ASOINTR_Data, tsidata,&lt;br /&gt;
      TAG_END);&lt;br /&gt;
&lt;br /&gt;
    struct MsgPort *port = IExec-&amp;gt;AllocSysObjectTags(ASOT_PORT,&lt;br /&gt;
      ASOPORT_AllocSig, FALSE,&lt;br /&gt;
      ASOPORT_Action, PA_SOFTINT,&lt;br /&gt;
      ASOPORT_Target, softint,&lt;br /&gt;
      TAG_END);&lt;br /&gt;
&lt;br /&gt;
    if(tsidata != NULL &amp;amp;&amp;amp; softint != NULL &amp;amp;&amp;amp; port != NULL)&lt;br /&gt;
    {&lt;br /&gt;
      softint-&amp;gt;is_Node.ln_Pri = 0;&lt;br /&gt;
&lt;br /&gt;
      /* Allocate timerequest */&lt;br /&gt;
      struct TimeRequest *tr = IExec-&amp;gt;AllocSysObjectTags(ASOT_IOREQUEST,&lt;br /&gt;
        ASOIOR_Size, sizeof(struct TimeRequest),&lt;br /&gt;
        ASOIOR_ReplyPort, port,&lt;br /&gt;
        TAG_END);&lt;br /&gt;
&lt;br /&gt;
      if (tr != NULL)&lt;br /&gt;
      {&lt;br /&gt;
        /* Open timer.device. NULL is success. */&lt;br /&gt;
        if (!(IExec-&amp;gt;OpenDevice(&amp;quot;timer.device&amp;quot;, UNIT_MICROHZ, (struct IORequest *)tr, 0)))&lt;br /&gt;
        {&lt;br /&gt;
          tsidata-&amp;gt;tsi_Flag = ON;        /* Init data structure to share globally. */&lt;br /&gt;
          tsidata-&amp;gt;tsi_Port = port;&lt;br /&gt;
&lt;br /&gt;
          /* Send of the first timerequest to start. IMPORTANT: Do NOT   */&lt;br /&gt;
          /* BeginIO() to any device other than audio or timer from      */&lt;br /&gt;
          /* within a software or hardware interrupt. The BeginIO() code */&lt;br /&gt;
          /* may allocate memory, wait or perform other functions which  */&lt;br /&gt;
          /* are illegal or dangerous during interrupts.                 */&lt;br /&gt;
          IDOS-&amp;gt;Printf(&amp;quot;starting softint. CTRL-C to break...\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
          tr-&amp;gt;Request.io_Command = TR_ADDREQUEST;    /* Initial iorequest to start */&lt;br /&gt;
          tr-&amp;gt;Time.Microseconds = MICRO_DELAY;        /* software interrupt.        */&lt;br /&gt;
          IExec-&amp;gt;BeginIO((struct IORequest *)tr);&lt;br /&gt;
&lt;br /&gt;
          IExec-&amp;gt;Wait(SIGBREAKF_CTRL_C);&lt;br /&gt;
          endcount = tsidata-&amp;gt;tsi_Counter;&lt;br /&gt;
          IDOS-&amp;gt;Printf(&amp;quot;timer softint counted %lu milliseconds.\n&amp;quot;, endcount);&lt;br /&gt;
&lt;br /&gt;
          IDOS-&amp;gt;Printf(&amp;quot;Stopping timer...\n&amp;quot;);&lt;br /&gt;
          tsidata-&amp;gt;tsi_Flag = OFF;&lt;br /&gt;
&lt;br /&gt;
          while (tsidata-&amp;gt;tsi_Flag != STOPPED) IDOS-&amp;gt;Delay(10);&lt;br /&gt;
&lt;br /&gt;
          IExec-&amp;gt;CloseDevice((struct IORequest *)tr);&lt;br /&gt;
        }&lt;br /&gt;
        else IDOS-&amp;gt;Printf(&amp;quot;couldn&#039;t open timer.device\n&amp;quot;);&lt;br /&gt;
      }&lt;br /&gt;
      else IDOS-&amp;gt;Printf(&amp;quot;couldn&#039;t create timerequest\n&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
      IExec-&amp;gt;FreeSysObject(ASOT_IOREQUEST, tr);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    IExec-&amp;gt;FreeSysObject(ASOT_INTERRUPT, softint);&lt;br /&gt;
    IExec-&amp;gt;FreeSysObject(ASOT_PORT, port);&lt;br /&gt;
    IExec-&amp;gt;FreeVec(tsidata);&lt;br /&gt;
    &lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void tsoftcode(void)&lt;br /&gt;
{&lt;br /&gt;
    /* Remove the message from the port. */&lt;br /&gt;
    struct TimeRequest *tr = (struct TimeRequest *)IExec-&amp;gt;GetMsg(tsidata-&amp;gt;tsi_Port);&lt;br /&gt;
&lt;br /&gt;
    /* Keep on going if main() hasn&#039;t set flag to OFF. */&lt;br /&gt;
    if ((tr) &amp;amp;&amp;amp; (tsidata-&amp;gt;tsi_Flag == ON))&lt;br /&gt;
    {&lt;br /&gt;
        /* increment counter and re-send timerequest--IMPORTANT: This         */&lt;br /&gt;
        /* self-perpetuating technique of calling BeginIO() during a software */&lt;br /&gt;
        /* interrupt may only be used with the audio and timer device.        */&lt;br /&gt;
        tsidata-&amp;gt;tsi_Counter++;&lt;br /&gt;
        tr-&amp;gt;Request.io_Command = TR_ADDREQUEST;&lt;br /&gt;
        tr-&amp;gt;Time.Microseconds = MICRO_DELAY;&lt;br /&gt;
        IExec-&amp;gt;BeginIO((struct IORequest *)tr);&lt;br /&gt;
    }&lt;br /&gt;
    /* Tell main() we&#039;re out of here. */&lt;br /&gt;
    else tsidata-&amp;gt;tsi_Flag = STOPPED;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Disabling Interrupts ==&lt;br /&gt;
&lt;br /&gt;
As mentioned in [[Exec_Tasks|Exec Tasks]], it is sometimes necessary to disable interrupts when examining or modifying certain shared system data structures. However, for proper system operation, interrupts should never be disabled unless absolutely necessary, and &#039;&#039;never for more than 250 microseconds&#039;&#039;. Interrupt disabling is controlled with the Disable() and Enable() functions.&lt;br /&gt;
&lt;br /&gt;
In some system code, there are nested disabled sections. Such code requires that interrupts be disabled with the first Disable() and not re-enabled until the &#039;&#039;last&#039;&#039; Enable(). The system Enable() and Disable() functions are designed to permit this sort of nesting.&lt;br /&gt;
&lt;br /&gt;
Disable() increments a counter to track how many levels of disable have been issued. Only 126 levels of nesting are permitted. Enable() decrements the counter, and reenables interrupts when the last disable level has been exited.&lt;br /&gt;
&lt;br /&gt;
== Quick Interrupts ==&lt;br /&gt;
&lt;br /&gt;
One of the features of the Zorro III bus is the Quick Interrupt, also known as the vectored interrupt. This feature allows Zorro III&lt;br /&gt;
hardware to supply a vector number to the system when an interrupt occurs. The system uses this vector number to go directly to an&lt;br /&gt;
interrupt routine.&lt;br /&gt;
&lt;br /&gt;
=== Conventional Amiga Interrupts ===&lt;br /&gt;
&lt;br /&gt;
The Amiga handles normal interrupts from Zorro II cards using an interrupt server chain. There are two interrupts available from the&lt;br /&gt;
Zorro II bus, the PORTS and EXTER interrupt server chains. If a driver for a Zorro II card needs to use an interrupt, it adds an interrupt routine to the appropriate chain. When the interrupt occurs, Exec calls each routine in the interrupt chain, which are sorted in priority order. Exec continues until it finds the routine that corresponds to the device that triggered the interrupt.&lt;br /&gt;
&lt;br /&gt;
The server chain allows several routines to share a single interrupt. This means that several devices trigger the same interrupt, so each interrupt routine must do some processing to determine if its card triggered the interrupt or if some other source caused the interrupt. For example, an interrupt routine might examine a register on its card to determine that the card triggered the interrupt.&lt;br /&gt;
&lt;br /&gt;
Although this scheme allows unrelated pieces of software to easily share an interrupt, it can make the interrupt overhead rather high.&lt;br /&gt;
These two interrupt server chains also handle interrupts from the CIA chips, which are used to trigger a variety of events. As a result, these server chains can contain a multitude of interrupt routines.&lt;br /&gt;
&lt;br /&gt;
Consider what happens when a Zorro II card generates a PORTS interrupt. Exec has to perform some set up and then step through the PORTS server chain. Exec calls each interrupt routine in priority order looking for the routine that services this interrupt. If there are 20 interrupt routines of higher priority than the card&#039;s interrupt routine in the server chain, Exec has to call 20 other routines before it gets to the correct routine.&lt;br /&gt;
&lt;br /&gt;
=== Zorro III Quick Interrupts ===&lt;br /&gt;
&lt;br /&gt;
Quick interrupts avoid the overhead involved in Exec&#039;s interrupt server chains. Exec only helps set up the quick interrupt, which it does via the exec.library function ObtainQuickVector(). Once Exec has set up the quick interrupt routine, it does not intervene. Unlike conventional Amiga interrupt routines, which are called as subroutines from Exec&#039;s main interrupt code, the Amiga jumps directly to the quick interrupt routine using a private vector. This behavior requires quick interrupt routines to take some special precautions.&lt;br /&gt;
&lt;br /&gt;
There are two important differences between a conventional Amiga interrupt routine and a quick quick interrupt routine. A quick&lt;br /&gt;
interrupt routine must save and restore all of the registers it changes, including D0, D1, A0, and A1. It must do this because, unlike&lt;br /&gt;
regular interrupt routines, Exec doesn&#039;t do it for you. Also, a quick interrupt routine ends with a RTE (return from exception) instruction.&lt;br /&gt;
&lt;br /&gt;
If your quick interrupt routine is 100% self-contained and does not access any operating system structures or routines, then the work is rather simple. Just save the registers you use, perform your interrupt processing, restore the registers, and end with an RTE. If, however, the routine needs to call the OS or use an OS structure, it must check if the interrupt has been delayed. This is necessary in case the interrupt hit the CPU just after the CPU had told the hardware to hold off interrupts (see the Autodoc for ObtainQuickVector() to find out how to perform this test).&lt;br /&gt;
&lt;br /&gt;
As the Amiga OS is a dynamic operating system, quick interrupts are allocated by the OS. If your hardware/software wants to use a quick&lt;br /&gt;
interrupt, it must allocate a vector with ObtainQuickVector(). This routine accepts a pointer to the quick interrupt code (not a pointer to an Interrupt structure). If Exec installed the vector, ObtainQuickVector() returns the vector number. When the quick&lt;br /&gt;
interrupt occurs, the Zorro III card sends this vector number to the CPU, which tells the CPU where the interrupt code is.&lt;br /&gt;
&lt;br /&gt;
ObtainQuickVector() returns 0 if there are no more vectors. Since the number of vectors is limited, any Zorro III device that uses quick interrupts must be able to fall back to the Amiga&#039;s conventional interrupt scheme.&lt;br /&gt;
&lt;br /&gt;
== Function Reference ==&lt;br /&gt;
&lt;br /&gt;
The following chart gives a brief description of the Exec functions that control interrupts. See the SDK for details about each call.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Interrupt Function&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| AddIntServer()&lt;br /&gt;
| Add an interrupt server to a system server chain.&lt;br /&gt;
|-&lt;br /&gt;
| Cause()&lt;br /&gt;
| Cause a software interrupt.&lt;br /&gt;
|-&lt;br /&gt;
| Disable()&lt;br /&gt;
| Disable interrupt processing.&lt;br /&gt;
|-&lt;br /&gt;
| Enable()&lt;br /&gt;
| Restart system interrupt processing.&lt;br /&gt;
|-&lt;br /&gt;
| RemIntServer()&lt;br /&gt;
| Remove an interrupt server from a system server chain.&lt;br /&gt;
|-&lt;br /&gt;
| SetIntVector()&lt;br /&gt;
| Set a new handler for a system interrupt vector.&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Costel Mincea</name></author>
	</entry>
	<entry>
		<id>https://wiki.amigaos.net/w/index.php?title=Intuition_Special_Functions&amp;diff=12549</id>
		<title>Intuition Special Functions</title>
		<link rel="alternate" type="text/html" href="https://wiki.amigaos.net/w/index.php?title=Intuition_Special_Functions&amp;diff=12549"/>
		<updated>2025-01-26T19:29:48Z</updated>

		<summary type="html">&lt;p&gt;Costel Mincea: Text replacement - &amp;quot;&amp;lt;syntaxhighlight&amp;gt;&amp;quot; to &amp;quot;&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Intuition Special Functions ==&lt;br /&gt;
&lt;br /&gt;
There are several Intuition topics which, while not large enough to fill articles of their own, nonetheless deserve to be discussed. The subjects covered here include locking IntuitionBase, the Intuition memory functions AllocRemember() and FreeRemember(), using sprites with Intuition, and Intuition&#039;s special internal functions.&lt;br /&gt;
&lt;br /&gt;
== Locking IntuitionBase ==&lt;br /&gt;
&lt;br /&gt;
It is sometimes necessary to examine the IntuitionBase structure. Items such as the address of the active screen and window, current mouse coordinates and more can be found there. It is never a good idea to simply read these fields, as they are prone to sudden change. The IntuitionBase structure must always be locked before looking at its fields.&lt;br /&gt;
&lt;br /&gt;
It is necessary to inform Intuition that an application is about to examine IntuitionBase so that Intuition will not change any variables and IntuitionBase will remain static during the access. The call LockIBase() will lock the state of IntuitionBase so that it may be examined. During the time that the application has IntuitionBase locked, all Intuition input processing is frozen. Make every effort to examine IntuitionBase and release the lock as quickly as possible. The values in IntuitionBase are read-only. Applications should never write values to IntuitionBase.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
ULONG LockIBase( ULONG dontknow );&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
LockIBase() is passed a ULONG (dontknow in the prototype above) indicating the Intuition lock desired. For all foreseeable uses of the call this value should be 0. LockIBase() returns a ULONG, that must be passed to UnlockIBase() later to allow IntuitionBase to change once again.&lt;br /&gt;
&lt;br /&gt;
Every call to LockIBase() must be matched by a subsequent call to UnlockIBase():&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
VOID UnlockIBase( ULONG ibLock );&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set the ibLock argument to the value returned by the previous call to LockIBase().&lt;br /&gt;
&lt;br /&gt;
{{Note|title=About LockIBase()|text=This function should not be called while holding any other system locks such as Layer and LayerInfo locks. Between calls to LockIBase() and UnlockIBase(), you may not call any Intuition or other high-level system functions so it is best to copy the information you need and release the lock as quickly as possible.}}&lt;br /&gt;
&lt;br /&gt;
{{Note|title=About IntuitionBase|text=Never, ever, modify any of the fields in IntuitionBase directly. Also, there are fields in IntuitionBase that are considered system private that should not be accessed, even for reading. (Refer to the &amp;lt;intuition/intuitionbase.h&amp;gt; include file.) Application programs cannot depend on (and should not use) the contents of these fields; their usage is subject to change in future revisions of Intuition.}}&lt;br /&gt;
&lt;br /&gt;
== Easy Memory Allocation and Deallocation ==&lt;br /&gt;
&lt;br /&gt;
Intuition has a pair of routines that enable applications to make multiple memory allocations which are easily deallocated with a single call. The Intuition routines for memory management are AllocRemember() and FreeRemember(). These routines rely upon the Remember structure to track allocations.&lt;br /&gt;
&lt;br /&gt;
=== Intuition Helps You Remember ===&lt;br /&gt;
&lt;br /&gt;
The AllocRemember() routine calls the Exec AllocMem() function to perform the memory allocation. (Of course, the application may directly call Exec memory functions, see [[Exec_Memory_Allocation|Exec Memory Allocation]] for details.)&lt;br /&gt;
&lt;br /&gt;
AllocRemember() performs two allocations each time it is called. The first allocation is the actual memory requested by the application. This memory is of the size and type specified in the call and is independent of the second block of memory. The second allocation is memory for a Remember structure which is used to save the specifics of the allocation in a linked list. When FreeRemember() is called it uses the information in this linked list to free all previous memory allocations at once. This is convenient since normally you would have to free each memory block one at a time which requires knowing the size and base address of each one.&lt;br /&gt;
&lt;br /&gt;
The AllocRemember() call takes three arguments:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
APTR AllocRemember( struct Remember **rememberKey, ULONG size, ULONG flags );&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The rememberKey is the address of a pointer to a Remember structure. Note that this is a double indirection, not just a simple pointer. The size is the size, in bytes, of the requested allocation. The flags argument is the specification for the memory allocation. These are the same as the specifications for the Exec AllocMem() function described in [[Exec_Memory_Allocation|Exec Memory Allocation]].&lt;br /&gt;
&lt;br /&gt;
If AllocRemember() succeeds, it returns the address of the allocated memory block. It returns a NULL if the allocation fails.&lt;br /&gt;
&lt;br /&gt;
The FreeRemember() function gives the option of freeing memory in either of two ways. The first (and most useful) option is to free both the link nodes that AllocRemember() created and the memory blocks to which they correspond. The second option is to free only the link nodes, leaving the memory blocks for further use (and later deallocation via Exec&#039;s FreeMem() function). But, as a general rule, the application should never free only the link nodes as this can greatly fragment memory. If the link nodes are not required, use the Exec memory allocation functions.&lt;br /&gt;
&lt;br /&gt;
The FreeRemember() call is as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
VOID FreeRemember( struct Remember **rememberKey, LONG reallyForget );&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Set the rememberKey argument to the address of a pointer to a Remember structure. This is the same value that was passed to previous calls to AllocRemember(). The reallyForget argument is a boolean that should be set to TRUE. If TRUE, then both the link nodes and the memory blocks are freed. If FALSE, then only the link nodes are freed. Again, applications should avoid using the FALSE value since it can lead to highly fragmented memory.&lt;br /&gt;
&lt;br /&gt;
=== How to Remember ===&lt;br /&gt;
&lt;br /&gt;
To use Intuition&#039;s memory functions, first create an anchor for the memory to be allocated by declaring a variable that is a pointer to a Remember structure and initializing that pointer to NULL. This variable is called the &#039;&#039;remember key&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct Remember *rememberKey = NULL;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Call AllocRemember() with the address of the remember key, along with the memory requirements for the specific allocation. Multiple allocations may be made before a call to FreeRemember().&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
memBlockA = IIntuition-&amp;gt;AllocRemember(&amp;amp;rememberKey, SIZE_A, MEMF_CLEAR | MEMF_PRIVATE);&lt;br /&gt;
if (memBlockA == NULL)&lt;br /&gt;
    {&lt;br /&gt;
    /* error: allocation failed */&lt;br /&gt;
    IDOS-&amp;gt;Printf(&amp;quot;Memory allocation failed.\n&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
else&lt;br /&gt;
    {&lt;br /&gt;
    /* use the memory here */&lt;br /&gt;
    IDOS-&amp;gt;Printf(&amp;quot;Memory allocation succeeded.\n&amp;quot;);&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
AllocRemember() actually performs two memory allocations per call, one for the memory requested and the other for a Remember structure. The Remember structure is filled in with data describing the allocation, and is linked into the list to which the &#039;&#039;remember key&#039;&#039; points.&lt;br /&gt;
&lt;br /&gt;
To free memory that has been allocated, simply call FreeRemember() with the correct remember key.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
IIntuition-&amp;gt;FreeRemember(&amp;amp;rememberKey, TRUE);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This will free all the memory blocks previously allocated with AllocRemember() in a single call.&lt;br /&gt;
&lt;br /&gt;
=== The Remember Structure ===&lt;br /&gt;
&lt;br /&gt;
The Remember structure is defined in &amp;amp;lt;intuition/intuition.h&amp;amp;gt; as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct Remember&lt;br /&gt;
    {&lt;br /&gt;
    struct Remember *NextRemember;&lt;br /&gt;
    ULONG RememberSize;&lt;br /&gt;
    UBYTE *Memory;&lt;br /&gt;
    };&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Generally, the Remember structure is handled only by the system. Here are its fields:&lt;br /&gt;
&lt;br /&gt;
; NextRemember&lt;br /&gt;
: The link to the next Remember structure.&lt;br /&gt;
&lt;br /&gt;
; RememberSize&lt;br /&gt;
: The size of the memory tracked by this node.&lt;br /&gt;
&lt;br /&gt;
; Memory&lt;br /&gt;
: A pointer to the memory tracked by this node.&lt;br /&gt;
&lt;br /&gt;
=== An Example of Remembering ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
** RememberTest - Illustrates the use of AllocRemember() and FreeRemember().&lt;br /&gt;
*/&lt;br /&gt;
#define INTUI_V36_NAMES_ONLY&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;exec/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;exec/memory.h&amp;gt;&lt;br /&gt;
#include &amp;lt;dos/dos.h&amp;gt;&lt;br /&gt;
#include &amp;lt;intuition/intuition.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;proto/exec.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/intuition.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/* our function prototypes */&lt;br /&gt;
VOID methodOne(VOID);&lt;br /&gt;
VOID methodTwo(VOID);&lt;br /&gt;
&lt;br /&gt;
struct IntuitionIFace *IIntuition = 0;&lt;br /&gt;
&lt;br /&gt;
/* random sizes to demonstrate the Remember functions. */&lt;br /&gt;
#define SIZE_A 100L&lt;br /&gt;
#define SIZE_B 200L&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
** main() - Initialize everything.&lt;br /&gt;
*/&lt;br /&gt;
int main(int argc, char **argv)&lt;br /&gt;
{&lt;br /&gt;
  LONG exitVal = RETURN_OK;&lt;br /&gt;
&lt;br /&gt;
  struct Library *IntuitionBase = IExec-&amp;gt;OpenLibrary(&amp;quot;intuition.library&amp;quot;, 50);&lt;br /&gt;
  IIntuition = (struct IntutitionIFace*)IExec-&amp;gt;GetInterface(IntuitionBase, &amp;quot;main&amp;quot;, 1, NULL);&lt;br /&gt;
  if (IIntuition == NULL)&lt;br /&gt;
    exitVal = RETURN_FAIL;&lt;br /&gt;
  else&lt;br /&gt;
  {&lt;br /&gt;
    methodOne();&lt;br /&gt;
    methodTwo();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  IExec-&amp;gt;DropInterface((struct Interface*)IIntuition);&lt;br /&gt;
  IExec-&amp;gt;CloseLibrary(IntuitionBase);&lt;br /&gt;
    &lt;br /&gt;
  return exitVal;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
** MethodOne&lt;br /&gt;
** Illustrates using AllocRemember() to allocate all memory and&lt;br /&gt;
** FreeRemember() to free it all.&lt;br /&gt;
*/&lt;br /&gt;
VOID methodOne(VOID)&lt;br /&gt;
{&lt;br /&gt;
  struct Remember *rememberKey = NULL;&lt;br /&gt;
&lt;br /&gt;
  APTR memBlockA = IIntuition-&amp;gt;AllocRemember(&amp;amp;rememberKey, SIZE_A, MEMF_CLEAR | MEMF_SHARED);&lt;br /&gt;
  if (memBlockA)&lt;br /&gt;
  {&lt;br /&gt;
    /*  The memBlockA allocation succeeded; try for memBlockB.  */&lt;br /&gt;
    APTR memBlockB = IIntuition-&amp;gt;AllocRemember(&amp;amp;rememberKey, SIZE_B, MEMF_CLEAR | MEMF_SHARED);&lt;br /&gt;
    if (memBlockB)&lt;br /&gt;
    {&lt;br /&gt;
      /*  Both memory allocations succeeded.&lt;br /&gt;
       **  The program may now use this memory.&lt;br /&gt;
       */&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  /* It is not necessary to keep track of the status of each allocation.&lt;br /&gt;
  ** Intuition has kept track of all successful allocations by updating its&lt;br /&gt;
  ** linked list of Remember nodes.  The following call to FreeRemember() will&lt;br /&gt;
  ** deallocate any and all of the memory that was successfully allocated.&lt;br /&gt;
  ** The memory blocks as well as the link nodes will be deallocated because&lt;br /&gt;
  ** the &amp;quot;ReallyForget&amp;quot; parameter is TRUE.&lt;br /&gt;
  **&lt;br /&gt;
  ** It is possible to have reached the call to FreeRemember()&lt;br /&gt;
  ** in one of three states.  Here they are, along with their results.&lt;br /&gt;
  **&lt;br /&gt;
  ** 1. Both memory allocations failed.&lt;br /&gt;
  **       RememberKey is still NULL.  FreeRemember() will do nothing.&lt;br /&gt;
  ** 2. The memBlockA allocation succeeded but the memBlockB allocation failed.&lt;br /&gt;
  **       FreeRemember() will free the memory block pointed to by memBlockA.&lt;br /&gt;
  ** 3. Both memory allocations were successful.&lt;br /&gt;
  **       FreeRemember() will free the memory blocks pointed to by&lt;br /&gt;
  **       memBlockA and memBlockB.&lt;br /&gt;
  */&lt;br /&gt;
  IIntuition-&amp;gt;FreeRemember(&amp;amp;rememberKey, TRUE);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
** MethodTwo&lt;br /&gt;
** Illustrates using AllocRemember() to allocate all memory,&lt;br /&gt;
** FreeRemember() to free the link nodes, and FreeMem() to&lt;br /&gt;
** free the actual memory blocks.&lt;br /&gt;
*/&lt;br /&gt;
VOID methodTwo(VOID)&lt;br /&gt;
{&lt;br /&gt;
  struct Remember *rememberKey = NULL;&lt;br /&gt;
&lt;br /&gt;
  APTR memBlockA = IIntuition-&amp;gt;AllocRemember(&amp;amp;rememberKey, SIZE_A, MEMF_CLEAR | MEMF_SHARED);&lt;br /&gt;
  if (memBlockA)&lt;br /&gt;
  {&lt;br /&gt;
    /*  The memBlockA allocation succeeded; try for memBlockB.  */&lt;br /&gt;
    APTR memBlockB = AllocRemember(&amp;amp;rememberKey, SIZE_B, MEMF_CLEAR | MEMF_SHARED);&lt;br /&gt;
    if (memBlockB)&lt;br /&gt;
    {&lt;br /&gt;
      /* Both memory allocations succeeded.&lt;br /&gt;
      ** For the purpose of illustration, FreeRemember() is called at&lt;br /&gt;
      ** this point, but only to free the link nodes.  The memory pointed&lt;br /&gt;
      ** to by memBlockA and memBlockB is retained.&lt;br /&gt;
      */&lt;br /&gt;
     IIntuition-&amp;gt;FreeRemember(&amp;amp;rememberKey, FALSE);&lt;br /&gt;
&lt;br /&gt;
      /* Individually free the two memory blocks. The Exec FreeMem()&lt;br /&gt;
      ** call must be used, as the link nodes are no longer available.&lt;br /&gt;
      */&lt;br /&gt;
      IExec-&amp;gt;FreeMem(memBlockA, SIZE_A);&lt;br /&gt;
      IExec-&amp;gt;FreeMem(memBlockB, SIZE_B);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  /* It is possible to have reached the call to FreeRemember()&lt;br /&gt;
  ** in one of three states.  Here they are, along with their results.&lt;br /&gt;
  **&lt;br /&gt;
  ** 1. Both memory allocations failed.&lt;br /&gt;
  **    RememberKey is still NULL.  FreeRemember() will do nothing.&lt;br /&gt;
  ** 2. The memBlockA allocation succeeded but the memBlockB allocation failed.&lt;br /&gt;
  **    FreeRemember() will free the memory block pointed to by memBlockA.&lt;br /&gt;
  ** 3. Both memory allocations were successful.&lt;br /&gt;
  **    If this is the case, the program has already freed the link nodes&lt;br /&gt;
  **    with FreeRemember() and the memory blocks with FreeMem().&lt;br /&gt;
  **    When FreeRemember() freed the link nodes, it reset RememberKey&lt;br /&gt;
  **    to NULL.  This (second) call to FreeRemember() will do nothing.&lt;br /&gt;
  */&lt;br /&gt;
  IIntuition-&amp;gt;FreeRemember(&amp;amp;rememberKey, TRUE);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Current Time Values ==&lt;br /&gt;
&lt;br /&gt;
The function CurrentTime() gets the current time values. To use this function, first declare the variables Seconds and Micros. Then, when the application call the function, the current time is copied into the argument pointers.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
VOID CurrentTime( ULONG *seconds, ULONG *micros );&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See the DOS library Autodocs for more information on functions dealing with the date and time. The DOS library includes such functions as DateToStr(), StrToDate(), SetFileDate() and CompareDates().&lt;br /&gt;
&lt;br /&gt;
== Using Sprites in Intuition Windows and Screens ==&lt;br /&gt;
&lt;br /&gt;
Sprite functionality has limitations under Intuition. The hardware and graphics library sprite systems manage sprites independently of the Intuition display. In particular:&lt;br /&gt;
&lt;br /&gt;
* Sprites cannot be attached to any particular screen. Instead, they always appear in front of every screen.&lt;br /&gt;
&lt;br /&gt;
* When a screen is moved, the sprites do not automatically move with it. The sprites move to their correct locations only when the appropriate function is called (either DrawGList() or MoveSprite()).&lt;br /&gt;
&lt;br /&gt;
Hardware sprites are of limited use under the Intuition paradigm. They travel out of windows and out of screens, unlike all other Intuition mechanisms (except the Intuition pointer, which is meant to be global).&lt;br /&gt;
&lt;br /&gt;
Remember that sprite data must be in Chip memory to be accessible to the custom chips on classic Amiga hardware. This may be done with a compiler specific feature, such as the __chip keyword of SAS/C. Otherwise, Chip memory can be allocated with the Exec AllocMem() function or the Intuition AllocRemember() function, setting the memory requirement flag to MEMF_CHIP. The sprite data may then be copied to Chip memory using a function like CopyMem() in the Exec library. See [[Graphics_Sprites,_Bobs_and_Animation|Graphics Sprites, Bobs and Animation]] for more information.&lt;br /&gt;
&lt;br /&gt;
== Intuition and Preferences ==&lt;br /&gt;
&lt;br /&gt;
The SetPrefs() function is used to configure Intuition&#039;s internal data states according to a given Preferences structure. This call relies on the Preferences system used in V34 and earlier versions of the OS. The old system has been superceded. See the [[Preferences|Preferences]] for details. This routine is called only by:&lt;br /&gt;
&lt;br /&gt;
* The Preferences program itself after the user changes Preferences settings (under V34 and earlier).&lt;br /&gt;
&lt;br /&gt;
* AmigaDOS when the system is being booted up. AmigaDOS opens the devs:system-configuration file and passes the information found there to the SetPrefs() routine. This way, the user can create an environment and have that environment restored every time the system is booted.&lt;br /&gt;
&lt;br /&gt;
The function takes three arguments:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
struct Preferences *SetPrefs( struct Preferences *prefbuf, LONG size,&lt;br /&gt;
                              LONG realThing );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The prefbuf argument is a pointer to a Preferences structure that will be used for Intuition&#039;s internal settings. The size is the number of bytes contained in your Preferences structure. Typically, you will use sizeof(struct Preferences) for this argument. The realThing argument is a boolean TRUE or FALSE designating whether or not this is an intermediate or final version of the Preferences. The difference is that final changes to Intuition&#039;s internal Preferences settings cause a global broadcast of NEWPREFS events to every application that is listening for this event. Intermediate changes may be used, for instance, to update the screen colors while the user is playing with the color gadgets.&lt;br /&gt;
&lt;br /&gt;
{{Note|title=About SetPrefs()|text=The intended use for the SetPrefs() call is entirely to serve the user. You should never use this routine to make your programming or design job easier at the cost of yanking the rug out from beneath the user.}}&lt;br /&gt;
&lt;br /&gt;
Refer to [[Preferences|Preferences]] for information about the Preferences structure and the preferred Preferences procedure calls.&lt;br /&gt;
&lt;br /&gt;
== Function Reference ==&lt;br /&gt;
&lt;br /&gt;
The following are brief descriptions of the Intuition functions discussed in this article. See the SDK for details on each function call.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Function&lt;br /&gt;
! Description&lt;br /&gt;
|-&lt;br /&gt;
| AllocRemember()&lt;br /&gt;
| Allocate memory and track the allocation.&lt;br /&gt;
|-&lt;br /&gt;
| FreeRemember()&lt;br /&gt;
| Free memory allocated with AllocRemember().&lt;br /&gt;
|-&lt;br /&gt;
| LockIBase()&lt;br /&gt;
| Lock IntuitionBase for reading.&lt;br /&gt;
|-&lt;br /&gt;
| UnlockIBase()&lt;br /&gt;
| Unlock IntuitionBase when done reading.&lt;br /&gt;
|-&lt;br /&gt;
| CurrentTime()&lt;br /&gt;
| Get the system time in seconds and micro-seconds.&lt;br /&gt;
|-&lt;br /&gt;
| SetPrefs()&lt;br /&gt;
| An Intuition internal function you should try to avoid.&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Costel Mincea</name></author>
	</entry>
	<entry>
		<id>https://wiki.amigaos.net/w/index.php?title=Virtual_Sprites&amp;diff=12548</id>
		<title>Virtual Sprites</title>
		<link rel="alternate" type="text/html" href="https://wiki.amigaos.net/w/index.php?title=Virtual_Sprites&amp;diff=12548"/>
		<updated>2025-01-26T19:29:08Z</updated>

		<summary type="html">&lt;p&gt;Costel Mincea: Text replacement - &amp;quot;&amp;lt;syntaxhighlight&amp;gt;&amp;quot; to &amp;quot;&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Using Virtual Sprites ==&lt;br /&gt;
&lt;br /&gt;
This section describes how to set up the VSprite structure so that it represents a true VSprite. True VSprites are managed by the GELs system which converts them to Simple Sprites and displays them. (Later sections describe how a VSprite structure can be set up for Bobs and AnimComps.)&lt;br /&gt;
&lt;br /&gt;
Before the system is told of a VSprite&#039;s existence, space for the VSprite data structure must be allocated and initialized to &amp;quot;correctly&amp;quot; represent a VSprite. Since the system does no validity checking on the VSprite structure, the result of using a bogus structure is usually a fireworks display, followed by a system failure.&lt;br /&gt;
&lt;br /&gt;
The system software provides a way to detect collisions between VSprites and other on-screen objects. There is also a method of extending the VSprite structure to incorporate user defined variables. These subjects are applicable to all GELs and are explained in [[Graphics_Sprites,_Bobs_and_Animation#Collisions_and_GEL_Structure_Extensions|Collisions and GEL Structure Extensions]].&lt;br /&gt;
&lt;br /&gt;
=== Specification of VSprite Structure ===&lt;br /&gt;
&lt;br /&gt;
The VSprite structure is defined in the include file &amp;amp;lt;graphics/gels.h&amp;amp;gt; as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
/* VSprite structure definition */&lt;br /&gt;
struct VSprite {&lt;br /&gt;
    struct VSprite *NextVSprite;&lt;br /&gt;
    struct VSprite *PrevVSprite;&lt;br /&gt;
    struct VSprite *DrawPath;&lt;br /&gt;
    struct VSprite *ClearPath;&lt;br /&gt;
    WORD            OldY, OldX;&lt;br /&gt;
    WORD            Flags;&lt;br /&gt;
    WORD            Y, X;&lt;br /&gt;
    WORD            Height;&lt;br /&gt;
    WORD            Width;&lt;br /&gt;
    WORD            Depth;&lt;br /&gt;
    WORD            MeMask;&lt;br /&gt;
    WORD            HitMask;&lt;br /&gt;
    WORD           *ImageData;&lt;br /&gt;
    WORD           *BorderLine;&lt;br /&gt;
    WORD           *CollMask;&lt;br /&gt;
    WORD           *SprColors;&lt;br /&gt;
    struct Bob     *VSBob;&lt;br /&gt;
    BYTE            PlanePick;&lt;br /&gt;
    BYTE            PlaneOnOff;&lt;br /&gt;
    VUserStuff      VUserExt;&lt;br /&gt;
    };&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are two primary ways to allocate and fill in space for VSprite data. They can be statically declared, or a memory allocation function can be called and they can be filled in programmatically. The declaration to statically set up a VSprite structure is listed below.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
/* VSprite static data definition.&lt;br /&gt;
** must set the following for TRUE VSprites:&lt;br /&gt;
**    VSPRITE flag.&lt;br /&gt;
**    Width to 1.&lt;br /&gt;
**    Depth to 2.&lt;br /&gt;
**    VSBob to NULL.&lt;br /&gt;
*/&lt;br /&gt;
struct VSprite myVSprite =&lt;br /&gt;
    {&lt;br /&gt;
    NULL, NULL, NULL, NULL, 0, 0, VSPRITE, 0, 0, 5, 1, 2, 0, 0,&lt;br /&gt;
    &amp;amp;myImage, 0, 0, &amp;amp;mySpriteColors, NULL, 0x3, 0, 0&lt;br /&gt;
    };&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This static allocation gives the required VSprite structure, but does not allocate or set up collision masks for the VSprite. Note that the VSprite structure itself does not need to reside in Chip memory.&lt;br /&gt;
&lt;br /&gt;
Refer to the makeVSprite() and freeVSprite() functions in the animtools.c listing at the end of the article for an example of dynamically allocating, initializing and freeing a VSprite structure.&lt;br /&gt;
&lt;br /&gt;
=== Reserved VSprite Members ===&lt;br /&gt;
&lt;br /&gt;
These VSprite structure members are reserved for system use (do not write to them):&lt;br /&gt;
&lt;br /&gt;
; NextVSprite and PrevVSprite&lt;br /&gt;
: These are used as links in the GelsInfo list.&lt;br /&gt;
&lt;br /&gt;
; DrawPath and ClearPath&lt;br /&gt;
: These are used for Bobs, not true VSprites.&lt;br /&gt;
&lt;br /&gt;
; OldY and OldX&lt;br /&gt;
: Previous position holder, the system uses these for double buffered Bobs, but application programs can read them too.&lt;br /&gt;
&lt;br /&gt;
The values can be set like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
myVSprite.NextVSprite = NULL;&lt;br /&gt;
myVSprite.PrevVSprite = NULL;&lt;br /&gt;
myVSprite.DrawPath  = NULL;&lt;br /&gt;
myVSprite.ClearPath = NULL;&lt;br /&gt;
myVSprite.OldY = 0;&lt;br /&gt;
myVSprite.OldX = 0;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Using VSprite Flags ===&lt;br /&gt;
&lt;br /&gt;
The Flags member of the VSprite structure is both read and written by the system. Some bits are used by the application to inform the system; others are used by the system to indicate things to the application.&lt;br /&gt;
&lt;br /&gt;
The only Flags bits that are used by true VSprites are:&lt;br /&gt;
&lt;br /&gt;
; VSPRITE&lt;br /&gt;
: This may be set to indicate to the system that it should treat the structure as a true VSprite, not part of a Bob. This affects the interpretation of the data layout and the use of various system variables.&lt;br /&gt;
&lt;br /&gt;
; VSOVERFLOW&lt;br /&gt;
: The system sets this bit in the true VSprites that it is unable to display. This happens when there are too many in the same scan line, and the system has run out of Simple Sprites to assign. It indicates that this VSprite has not been displayed. If no sprites are reserved, this means that more than eight sprites touch one scan line. This bit will not be set for Bobs and should not be changed by the application.&lt;br /&gt;
&lt;br /&gt;
; GELGONE&lt;br /&gt;
: If the system has set GELGONE bit in the Flags member, then the GEL associated with this VSprite is not on the display at all, it is entirely outside the GEL boundaries. This area is defined by the GelsInfo members topmost, bottommost, leftmost and rightmost (see the &amp;amp;lt;graphics/rastport.h&amp;amp;gt; include file).&lt;br /&gt;
&lt;br /&gt;
On the basis of that information, the application may decide that the object need no longer be part of the GEL list and may decide to remove it to speed up the consideration of other objects. Use RemVSprite() (or RemBob(), if it&#039;s a Bob) to do this. This bit should not be changed by the application.&lt;br /&gt;
&lt;br /&gt;
The VSprite.Flags value should be initialized like this for a VSprite GEL:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
myVSprite.Flags = VSPRITE;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== VSprite Position ===&lt;br /&gt;
&lt;br /&gt;
To control the position of a VSprite, the x and y variables in the VSprite structure are used. These specify where the upper left corner of the VSprite will be, relative to the upper left corner of the playfield area it appears over. So if VSprites are used under Intuition and within a screen, they will be positioned relative to the upper left-hand corner of the screen.&lt;br /&gt;
&lt;br /&gt;
In a 320x200 screen, a y value of 0 puts the VSprite at the top of that display, a y value of (200 - VSprite height) puts the VSprite at the bottom. And an x value of 0 puts the VSprite at the left edge of that display, while an x value of (320 - VSprite width) puts the VSprite at the far right. Values of less than (0,0) or greater than (320, 200) may be used to move the VSprite partially or entirely off the screen, if desired.&lt;br /&gt;
&lt;br /&gt;
See [[Graphics_Primitives|Graphics Primitives]] for more information on display coordinates and display size. See the &amp;quot;Amiga Hardware Reference Manual&amp;quot; for more information on hardware sprites.&lt;br /&gt;
&lt;br /&gt;
{{Note|title=Position VSprites Properly|text=It is important that the starting position of true VSprites is not less than -20 in the y direction, which is the start of the active display area for sprites. Also, if they are moved too far to the left, true VSprites may not have enough DMA time to be displayed.}}&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;x, y&#039;&#039; values may be set like this to put the VSprite in the upper-left:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
myVSprite.Y = 0;&lt;br /&gt;
myVSprite.X = 0;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== VSprite Image Size ===&lt;br /&gt;
&lt;br /&gt;
A true VSprite is always one word (16 pixels) wide and may be any number of lines high. It can be made to appear thinner by making some pixels transparent. Like Simple Sprites, VSprite pixels are always the size of a pixel in low-resolution mode (320x200); regardless of the resolution the display is set to. To specify how many lines make up the VSprite image, the VSprite structure member, Height, is used.&lt;br /&gt;
&lt;br /&gt;
VSprites always have a Depth of two, allowing for three colors. The values may be set like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
myVSprite.Width  = 1;      /* ALWAYS 1 for true VSprites. */&lt;br /&gt;
myVSprite.Height = 5;      /* The example height. */&lt;br /&gt;
myVSprite.Depth  = 2;      /* ALWAYS 2 for true VSprites. */&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== VSprites and Collision Detection ===&lt;br /&gt;
&lt;br /&gt;
Some members of the VSprite data structure are used for special purposes such as collision detection, user extensions or for system extensions (such as Bobs and AnimComps). For most applications these fields are set to zero:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
myVSprite.HitMask    = 0;  /* These are all used for collision detection */&lt;br /&gt;
myVSprite.MeMask     = 0;&lt;br /&gt;
myVSprite.BorderLine = 0;&lt;br /&gt;
myVSprite.CollMask   = 0;&lt;br /&gt;
&lt;br /&gt;
myVSprite.VUserExt = 0;    /* Only use this for user extensions to VSprite */&lt;br /&gt;
&lt;br /&gt;
myVSprite.VSBob = NULL;    /* Only Bobs and AnimComps need this */&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The special uses of this fields are explained further in the sections that follow.&lt;br /&gt;
&lt;br /&gt;
=== VSprite Image Data ===&lt;br /&gt;
&lt;br /&gt;
The ImageData pointer of the VSprite structure must be initialized with the address of the first word of the image data array. The image data array must be in Chip memory. It takes two sequential 16-bit words to define each line of a VSprite. This means that the data area containing the VSprite image is always &amp;quot;Heightx2&amp;quot; (10 in the example case) words long.&lt;br /&gt;
&lt;br /&gt;
A VSprite image is defined just like a real hardware sprite. The combination of bits in corresponding locations in the two data words that define each line select the color for that pixel. The first of the pair of words supplies the low-order bit of the color selector for that pixel; the second word supplies the high-order bit.&lt;br /&gt;
&lt;br /&gt;
These binary values select colors as follows:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| 00 || selects &amp;quot;transparent&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| 01 || selects the first of three VSprite colors&lt;br /&gt;
|-&lt;br /&gt;
| 10 || selects the second VSprite color&lt;br /&gt;
|-&lt;br /&gt;
| 11 || selects the third VSprite color&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In those areas where the combination of bits yields a value of 0, the VSprite is transparent. This means that the playfield, and all Bobs and AnimComps, and any VSprite whose priority is lower than this VSprite will all show through in transparent sections. For example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(&amp;amp;VSprite-&amp;gt;ImageData)      1010 0000 0000 0000&lt;br /&gt;
(&amp;amp;VSprite-&amp;gt;ImageData + 1)  0110 0000 0000 0000&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Reading from top to bottom, left to right, the combinations of these two sequential data words form the binary values of 01, 10, 11, and then all 00s. This VSprite&#039;s first pixel will be color 1, the next color 2, the third color 3. The rest will be transparent, making this VSprite appear to be three pixels wide. Thus, a three-color image, with some transparent areas, can be formed from a data set like the following sample:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Address    Binary Data            VSprite Image Data&lt;br /&gt;
-------    -----------            ------------------&lt;br /&gt;
mem        1111 1111 1111 1111    Defines top line&lt;br /&gt;
mem + 1    1111 1111 1111 1111    3333 3333 3333 3333&lt;br /&gt;
&lt;br /&gt;
mem + 2    0011 1100 0011 1100    Defines second line&lt;br /&gt;
mem + 3    0011 0000 0000 1100    0033 1100 0011 3300&lt;br /&gt;
&lt;br /&gt;
mem + 4    0000 1100 0011 0000    Defines third line&lt;br /&gt;
mem + 5    0000 1111 1111 0000    0000 3322 2233 0000&lt;br /&gt;
&lt;br /&gt;
mem + 6    0000 0010 0100 0000    Defines fourth line&lt;br /&gt;
mem + 7    0000 0011 1100 0000    0000 0032 2300 0000&lt;br /&gt;
&lt;br /&gt;
mem + 8    0000 0001 1000 0000    Defines fifth line&lt;br /&gt;
mem + 9    0000 0001 1000 0000    0000 0003 3000 0000&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The VSprite.Height for this sample image is 5.&lt;br /&gt;
&lt;br /&gt;
=== Specifying the Colors of a VSprite ===&lt;br /&gt;
&lt;br /&gt;
The system software provides a great deal of versatility in the choice of colors for Virtual Sprites. Each VSprite has &amp;quot;its own set&amp;quot; of three colors, pointed to by SprColors, which the system jams into the display&#039;s Copper list as needed.&lt;br /&gt;
&lt;br /&gt;
SprColors points to the first of three 16-bit values. The first value represents the color used for the VSprite bits that select color 1, the second value is color 2, and the third value is color 3. When the system assigns a hardware sprite to carry the VSprite&#039;s image, it jams these color values into the Copper list (the intermediate Copper list, &amp;quot;not&amp;quot; the color table), so that the View&#039;s colors will be correct for this VSprite at the time the VSprite is displayed. It doesn&#039;t jam the original palette&#039;s colors back after the VSprite is done. If there is another VSprite later, that VSprite&#039;s colors will get jammed; if there is not another VSprite, the colors will remain the same until the next ViewPort&#039;s colors get loaded.&lt;br /&gt;
&lt;br /&gt;
If the SprColors pointer is set to NULL, that VSprite does not generate a color-change instruction stream for the Copper. Instead, the VSprite appears drawn in whatever color set that the hardware sprite happens to have in it already.&lt;br /&gt;
&lt;br /&gt;
Since the registers are initially loaded with the colors from the ViewPort&#039;s ColorMap, if all VSprites have NULL SprColors, they will appear in the ViewPort&#039;s colors.&lt;br /&gt;
&lt;br /&gt;
To continue our example, a set of colors can be declared and the VSprite colors set with the following statements:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
uint16 mySpriteColors[] = { 0x0000, 0x00f0, 0x0f00 }; /* Declare colors statically */&lt;br /&gt;
&lt;br /&gt;
myVSprite.SprColors = mySpriteColors;                 /* Assign colors to VSprite */&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Adding and Removing VSprites ===&lt;br /&gt;
&lt;br /&gt;
Once a true VSprite has been set up and initialized, the obvious next step is to give it to the system by adding it to the GEL list. The VSprite may then be manipulated as needed. Before the program ends, the VSprite should be removed from the GELs list by calling RemVSprite().&lt;br /&gt;
&lt;br /&gt;
A typical calling sequence could be performed like so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct VSprite  myVSprite = {0};&lt;br /&gt;
struct RastPort myRastPort = {0};&lt;br /&gt;
&lt;br /&gt;
IGraphics-&amp;gt;AddVSprite(&amp;amp;myVSprite, &amp;amp;myRastPort);&lt;br /&gt;
&lt;br /&gt;
/* Manipulate the VSprite as needed here */&lt;br /&gt;
&lt;br /&gt;
IGraphics-&amp;gt;RemVSprite(&amp;amp;myVSprite);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;amp;amp;myVSprite argument is a fully initialized VSprite structure and &amp;amp;amp;myRastPort is the RastPort with which this VSprite is to be associated. Note that you will probably not like the results if you try to RemVSprite() a VSprite that has not been added to the system with AddVSprite(). See the SDK for additional information on these functions.&lt;br /&gt;
&lt;br /&gt;
=== Changing VSprites ===&lt;br /&gt;
&lt;br /&gt;
Once the VSprite has been added to the GELs list and is in the display, some of its characteristics can be changed dynamically by:&lt;br /&gt;
&lt;br /&gt;
* Changing y, x to a new VSprite position&lt;br /&gt;
* Changing ImageData to point to a new VSprite image&lt;br /&gt;
* Changing SprColors to point to a new VSprite color set&lt;br /&gt;
&lt;br /&gt;
Study the next two sections to find out how to reserve hardware Sprites for use outside the VSprite system and how to assign the VSprites.&lt;br /&gt;
&lt;br /&gt;
=== Getting the VSprite List in Order ===&lt;br /&gt;
&lt;br /&gt;
When the system has displayed the last line of a VSprite, it is able to reassign the hardware sprite to another VSprite located at a lower position on the screen. The system allocates hardware sprites in the order in which it encounters the VSprites in the list. Therefore, the list of VSprites must be sorted before the system can assign the use of the hardware Sprites correctly.&lt;br /&gt;
&lt;br /&gt;
The function SortGList() must be used to get the GELs in the correct order before the system is asked to display them. &#039;&#039;This sorting step is essential!&#039;&#039; It should be done before calling DrawGList(), whenever a GEL has changed position. This function is called as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct RastPort myRastPort = {0};&lt;br /&gt;
&lt;br /&gt;
IGraphics-&amp;gt;SortGList(&amp;amp;myRastPort);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The only argument is a pointer to the RastPort structure containing the GelsInfo.&lt;br /&gt;
&lt;br /&gt;
=== Displaying the VSprites ===&lt;br /&gt;
&lt;br /&gt;
The next few sections explain how to display the VSprites. The following system functions are used:&lt;br /&gt;
&lt;br /&gt;
; DrawGList()&lt;br /&gt;
: Draws the VSprites into the current RastPort.&lt;br /&gt;
&lt;br /&gt;
; MrgCop()&lt;br /&gt;
: Installs the VSprites into the display.&lt;br /&gt;
&lt;br /&gt;
; LoadView()&lt;br /&gt;
: Asks the system to display the new View.&lt;br /&gt;
&lt;br /&gt;
; WaitTOF()&lt;br /&gt;
: Synchronizes the functions with the display.&lt;br /&gt;
&lt;br /&gt;
==== Drawing the Graphics Elements ====&lt;br /&gt;
&lt;br /&gt;
The system function called DrawGList() looks through the list of GELS and prepares the necessary Copper instructions and memory areas to display the data. This function is called as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct RastPort myRastPort = {0};&lt;br /&gt;
struct ViewPort myViewPort = {0};&lt;br /&gt;
&lt;br /&gt;
IGraphics-&amp;gt;DrawGList(&amp;amp;myRastPort, &amp;amp;myViewPort);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The myRastPort argument specifies the RastPort containing the GelsInfo list with the VSprites that you want to display. The &amp;amp;amp;myViewPort argument is a pointer to the ViewPort for which the VSprites will be created.&lt;br /&gt;
&lt;br /&gt;
==== Merging VSprite Instructions ====&lt;br /&gt;
&lt;br /&gt;
Once DrawGList() has prepared the necessary instructions and memory areas to display the data, the VSprites are installed into the display with MrgCop(). (DrawGList() does not actually draw the VSprites, it only prepares the Copper instructions.)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct View *view;&lt;br /&gt;
&lt;br /&gt;
IGraphics-&amp;gt;MrgCop(view);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The view is a pointer to the View structure whose Copper instructions are to be merged.&lt;br /&gt;
&lt;br /&gt;
==== Loading the New View ====&lt;br /&gt;
&lt;br /&gt;
Now that the display instructions include the definition of the VSprites, the system can display this newly configured View with the LoadView() function:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct View *view;&lt;br /&gt;
&lt;br /&gt;
IGraphics-&amp;gt;LoadView(view);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Again, view is a pointer to the View that contains the the new Copper instruction list (if you are using GELs in an Intuition Screen, do not call LoadView().)&lt;br /&gt;
&lt;br /&gt;
The Copper instruction lists are double-buffered, so this instruction does not actually take effect until the next display field occurs. This avoids the possibility of some function trying to update the Copper instruction list while the Copper is trying to use it to create the display.&lt;br /&gt;
&lt;br /&gt;
==== Synchronizing with the Display ====&lt;br /&gt;
&lt;br /&gt;
To synchronize application functions with the display, call the system function WaitTOF().&lt;br /&gt;
&lt;br /&gt;
WaitTOF() holds your task until the vertical-blanking interval (blank area at the top of the screen) has begun. At that time, the system has retrieved the current Copper instruction list and is ready to allow generation of a new list.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
WaitTOF();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
WaitTOF() takes no arguments and returns no values. It simply suspends your task until the video beam is at the top of field.&lt;br /&gt;
&lt;br /&gt;
== Complete VSprite Example ==&lt;br /&gt;
&lt;br /&gt;
The listing given here shows a complete VSprite example. This program requires the &amp;quot;animtools.c&amp;quot;, &amp;quot;animtools.h&amp;quot; and &amp;quot;animtools_proto.h&amp;quot; support files in order to compile and run. These files are listed at the end of this article.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* vsprite.c&lt;br /&gt;
**&lt;br /&gt;
** SAS/C V5.10a&lt;br /&gt;
** lc -b1 -cfist -v -y vsprite.c&lt;br /&gt;
** blink FROM LIB:c.o vsprite.o animtools.o LIB LIB:lc.lib LIB:amiga.lib TO vsprite&lt;br /&gt;
*/&lt;br /&gt;
#include &amp;amp;lt;exec/types.h&amp;amp;gt;&lt;br /&gt;
#include &amp;amp;lt;exec/memory.h&amp;amp;gt;&lt;br /&gt;
#include &amp;amp;lt;intuition/intuitionbase.h&amp;amp;gt;&lt;br /&gt;
#include &amp;amp;lt;graphics/gfx.h&amp;amp;gt;&lt;br /&gt;
#include &amp;amp;lt;graphics/gfxbase.h&amp;amp;gt;&lt;br /&gt;
#include &amp;amp;lt;graphics/gels.h&amp;amp;gt;&lt;br /&gt;
#include &amp;amp;lt;graphics/collide.h&amp;amp;gt;&lt;br /&gt;
#include &amp;amp;lt;libraries/dos.h&amp;amp;gt;&lt;br /&gt;
#include &amp;amp;lt;stdlib.h&amp;amp;gt;&lt;br /&gt;
#include &amp;amp;quot;animtools.h&amp;amp;quot;&lt;br /&gt;
&lt;br /&gt;
VOID borderCheck(struct VSprite *hitVSprite, LONG borderflags);&lt;br /&gt;
VOID process_window(struct Window *win, struct RastPort *myRPort, struct VSprite *MyVSprite);&lt;br /&gt;
VOID do_VSprite(struct Window *win, struct RastPort *myRPort);&lt;br /&gt;
VOID vspriteDrawGList(struct Window *win, struct RastPort *myRPort);&lt;br /&gt;
&lt;br /&gt;
struct GfxBase           *GfxBase;   /* pointer to Graphics library  */&lt;br /&gt;
struct IntuitionBase *IntuitionBase; /* pointer to Intuition library */&lt;br /&gt;
&lt;br /&gt;
int return_code;&lt;br /&gt;
#define GEL_SIZE        4 /* number of lines in the vsprite */&lt;br /&gt;
&lt;br /&gt;
/* VSprite data - there are two sets that are alternated between. */&lt;br /&gt;
/* note that this data is always displayed as low resolution.     */&lt;br /&gt;
WORD chip vsprite_data1[] = { 0x7ffe, 0x80ff,&lt;br /&gt;
                              0x7c3e, 0x803f,&lt;br /&gt;
                              0x7c3e, 0x803f,&lt;br /&gt;
                              0x7ffe, 0x80ff,&lt;br /&gt;
                              0, 0 };&lt;br /&gt;
&lt;br /&gt;
WORD chip vsprite_data2[] = { 0x7ffe, 0xff01,&lt;br /&gt;
                              0x7c3e, 0xfc01,&lt;br /&gt;
                              0x7c3e, 0xfc01,&lt;br /&gt;
                              0x7ffe, 0xff01,&lt;br /&gt;
                              0, 0 };&lt;br /&gt;
&lt;br /&gt;
WORD mySpriteColors[] =     { 0x0000, 0x00f0, 0x0f00 };&lt;br /&gt;
WORD mySpriteAltColors[] =  { 0x000f, 0x0f00, 0x0ff0 };&lt;br /&gt;
&lt;br /&gt;
NEWVSPRITE myNewVSprite = {              /* information for the new VSprite       */&lt;br /&gt;
        /* Image data, sprite color array word width (must be 1 for true VSprite) */&lt;br /&gt;
        vsprite_data1, mySpriteColors,1,&lt;br /&gt;
        /* Line height, image depth (must be 2 for true VSprite), x, y position   */&lt;br /&gt;
        GEL_SIZE, 2, 160, 100,&lt;br /&gt;
        /* Flags (VSPRITE == true VSprite), hit mask and me mask                  */&lt;br /&gt;
        VSPRITE, 1 &amp;amp;lt;&amp;amp;lt; BORDERHIT, 0&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
struct NewWindow myNewWindow = {        /* information for the new window */&lt;br /&gt;
    80, 20, 400, 150, -1, -1, CLOSEWINDOW | INTUITICKS,&lt;br /&gt;
    ACTIVATE | WINDOWCLOSE | WINDOWDEPTH | RMBTRAP | WINDOWDRAG,&lt;br /&gt;
    NULL, NULL, &amp;amp;quot;VSprite&amp;amp;quot;, NULL, NULL, 0, 0, 0, 0, WBENCHSCREEN&lt;br /&gt;
    };&lt;br /&gt;
&lt;br /&gt;
/* Basic VSprite display subroutine */&lt;br /&gt;
VOID vspriteDrawGList(struct Window *win, struct RastPort *myRPort)&lt;br /&gt;
{&lt;br /&gt;
SortGList(myRPort);&lt;br /&gt;
DrawGList(myRPort, ViewPortAddress(win));&lt;br /&gt;
RethinkDisplay();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Collision routine for vsprite hitting border.  Note that when the collision is VSprite to */&lt;br /&gt;
/* VSprite (or Bob to Bob, Bob to AnimOb, etc), then the parameters are both pointers to a VSprite. */&lt;br /&gt;
VOID borderCheck(struct VSprite *hitVSprite, LONG borderflags)&lt;br /&gt;
{&lt;br /&gt;
if (borderflags &amp;amp;amp; RIGHTHIT)&lt;br /&gt;
    {&lt;br /&gt;
    hitVSprite-&amp;amp;gt;SprColors = mySpriteAltColors;&lt;br /&gt;
    hitVSprite-&amp;amp;gt;VUserExt  = -40;&lt;br /&gt;
    }&lt;br /&gt;
if (borderflags &amp;amp;amp; LEFTHIT)&lt;br /&gt;
    {&lt;br /&gt;
    hitVSprite-&amp;amp;gt;SprColors = mySpriteColors;&lt;br /&gt;
    hitVSprite-&amp;amp;gt;VUserExt  = 20;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Process window and dynamically change vsprite. Get messages. Go away on           */&lt;br /&gt;
/* CLOSEWINDOW.  Update and redisplay vsprite on INTUITICKS. Wait for more messages. */&lt;br /&gt;
VOID process_window(struct Window *win, struct RastPort *myRPort, struct VSprite *myVSprite)&lt;br /&gt;
{&lt;br /&gt;
struct IntuiMessage *msg;&lt;br /&gt;
&lt;br /&gt;
FOREVER&lt;br /&gt;
    {&lt;br /&gt;
    Wait(1L &amp;amp;lt;&amp;amp;lt; win-&amp;amp;gt;UserPort-&amp;amp;gt;mp_SigBit);&lt;br /&gt;
    while (NULL != (msg = (struct IntuiMessage *)GetMsg(win-&amp;amp;gt;UserPort)))&lt;br /&gt;
        {&lt;br /&gt;
        /* Only CLOSEWINDOW and INTUITICKS are active */&lt;br /&gt;
        if (msg-&amp;amp;gt;Class == CLOSEWINDOW)&lt;br /&gt;
            {&lt;br /&gt;
            ReplyMsg((struct Message *)msg);&lt;br /&gt;
            return;&lt;br /&gt;
            }&lt;br /&gt;
        /* Must be an INTUITICKS:  change x and y values on the fly.  Note offset by&lt;br /&gt;
        ** window left and top edge--sprite relative to the screen, not window.  Divide&lt;br /&gt;
        ** the MouseY in half to adjust for Lores movement increments on a Hires screen.&lt;br /&gt;
        */&lt;br /&gt;
        myVSprite-&amp;amp;gt;X = win-&amp;amp;gt;LeftEdge + msg-&amp;amp;gt;MouseX + myVSprite-&amp;amp;gt;VUserExt;&lt;br /&gt;
        myVSprite-&amp;amp;gt;Y = win-&amp;amp;gt;TopEdge  + msg-&amp;amp;gt;MouseY/2 + 1;&lt;br /&gt;
        ReplyMsg((struct Message *)msg);&lt;br /&gt;
        }&lt;br /&gt;
    /* Got a message, change image data on the fly */&lt;br /&gt;
    myVSprite-&amp;amp;gt;ImageData = (myVSprite-&amp;amp;gt;ImageData == vsprite_data1) ? vsprite_data2 : vsprite_data1;&lt;br /&gt;
    SortGList(myRPort);&lt;br /&gt;
    DoCollision(myRPort);&lt;br /&gt;
    vspriteDrawGList(win, myRPort);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Working with the VSprite.  Setup the GEL system and get a new VSprite (makeVSprite()).   */&lt;br /&gt;
/* Add VSprite to the system and display.  Use the vsprite.  When done, remove VSprite and  */&lt;br /&gt;
/* update the display without the VSprite.  Cleanup everything.                             */&lt;br /&gt;
VOID do_VSprite(struct Window *win, struct RastPort *myRPort)&lt;br /&gt;
{&lt;br /&gt;
struct VSprite       *myVSprite;&lt;br /&gt;
struct GelsInfo       *my_ginfo;&lt;br /&gt;
&lt;br /&gt;
if (NULL == (my_ginfo = setupGelSys(myRPort, 0xfc)))&lt;br /&gt;
    return_code = RETURN_WARN;&lt;br /&gt;
else&lt;br /&gt;
    {&lt;br /&gt;
    if (NULL == (myVSprite = makeVSprite(&amp;amp;amp;myNewVSprite)))&lt;br /&gt;
        return_code = RETURN_WARN;&lt;br /&gt;
    else&lt;br /&gt;
        {&lt;br /&gt;
        AddVSprite(myVSprite, myRPort);&lt;br /&gt;
        vspriteDrawGList(win, myRPort);&lt;br /&gt;
        myVSprite-&amp;amp;gt;VUserExt = 20;&lt;br /&gt;
        SetCollision(BORDERHIT, borderCheck, myRPort-&amp;amp;gt;GelsInfo);&lt;br /&gt;
        process_window(win, myRPort, myVSprite);&lt;br /&gt;
        RemVSprite(myVSprite);&lt;br /&gt;
        freeVSprite(myVSprite);&lt;br /&gt;
        }&lt;br /&gt;
    vspriteDrawGList(win, myRPort);&lt;br /&gt;
    cleanupGelSys(my_ginfo, myRPort);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Example VSprite program.  First open up the libraries and a window. */&lt;br /&gt;
VOID main(int argc, char **argv)&lt;br /&gt;
{&lt;br /&gt;
struct Window       *win;&lt;br /&gt;
struct RastPort    myRPort = {0};&lt;br /&gt;
&lt;br /&gt;
return_code = RETURN_OK;&lt;br /&gt;
&lt;br /&gt;
if (NULL == (GfxBase = (struct GfxBase *)OpenLibrary(GRAPHICSNAME,37L)))&lt;br /&gt;
    return_code = RETURN_FAIL;&lt;br /&gt;
else&lt;br /&gt;
    {&lt;br /&gt;
    if (NULL == (IntuitionBase = (struct IntuitionBase *)OpenLibrary(INTUITIONNAME,37L)))&lt;br /&gt;
        return_code = RETURN_FAIL;&lt;br /&gt;
    else&lt;br /&gt;
        {&lt;br /&gt;
        if (NULL == (win = OpenWindow(&amp;amp;amp;myNewWindow)))&lt;br /&gt;
            return_code = RETURN_WARN;&lt;br /&gt;
        else&lt;br /&gt;
            {&lt;br /&gt;
            InitRastPort(&amp;amp;amp;myRPort);&lt;br /&gt;
            myRPort = win-&amp;amp;gt;WScreen-&amp;amp;gt;RastPort;       /* Copy the structure. */&lt;br /&gt;
            do_VSprite(win, &amp;amp;amp;myRPort);&lt;br /&gt;
            CloseWindow(win);&lt;br /&gt;
            }&lt;br /&gt;
        CloseLibrary((struct Library *)IntuitionBase);&lt;br /&gt;
        }&lt;br /&gt;
    CloseLibrary((struct Library *)GfxBase);&lt;br /&gt;
    }&lt;br /&gt;
exit(return_code);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== VSprite Advanced Topics ==&lt;br /&gt;
&lt;br /&gt;
This section describes advanced topics pertaining to VSprites. It contains details about reserving hardware sprites for use outside of the GELs VSprite system, information about how VSprites are assigned, and more information about VSprite colors.&lt;br /&gt;
&lt;br /&gt;
=== Reserving Hardware Sprites ===&lt;br /&gt;
&lt;br /&gt;
To prevent the VSprite system from using specific hardware sprites, set the sprRsrvd member of the GelsInfo structure. The pointer to the GelsInfo structure is contained in the RastPort structure. If all of the bits of this 8-bit value are ones (0xFF), then all of the hardware sprites may be used by the VSprite system. If any of the bits is a 0, the sprite corresponding to that bit will not be utilized by VSprites.&lt;br /&gt;
&lt;br /&gt;
{{Note|title=Reserving Can Cause Problems|text=Reserving sprites increases the likelihood of the system not being able to display a VSprite (VSOVERFLOW). See the next section, &amp;quot;How VSprites are Assigned&amp;quot;, for further details on this topic.}}&lt;br /&gt;
&lt;br /&gt;
You reserve a sprite by setting its corresponding bit in sprRsrvd. For instance, to reserve sprite zero only, set sprRsrvd to 0x01. To reserve sprite three only, set sprRsrvd to 0x08.&lt;br /&gt;
&lt;br /&gt;
If a hardware sprite is reserved, the system will not consider it when it makes VSprite assignments. Remember, hardware sprite pairs share color register sets. If a hardware sprite is reserved, its mate should probably be reserved too, otherwise the reserved sprite&#039;s colors will change as the unreserved mate is assigned different VSprites. For example, it is common practice to reserve Sprites 0 and 1, so that the Intuition pointer (Sprite 0) is left alone. This could be accomplished with the following statements:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
struct RastPort myRastPort = {0};   /* the View structure is defined */&lt;br /&gt;
&lt;br /&gt;
myRastPort.GelsInfo-&amp;gt;sprRsrvd = 0x03;   /* reserve 0 and 1 */&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The GfxBase structure may be examined to find which sprites are already in use. This may, at your option, impact what sprites you reserve. If Intuition is running, sprite 0 will already be in use as its pointer.&lt;br /&gt;
&lt;br /&gt;
The reserved sprite status is accessible as&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot; line&amp;gt;&lt;br /&gt;
currentreserved = GfxBase-&amp;gt;SpriteReserved;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The next section presents a few trouble-shooting techniques for VSprite assignment.&lt;br /&gt;
&lt;br /&gt;
=== How VSprites Are Assigned ===&lt;br /&gt;
&lt;br /&gt;
Although VSprites are managed for you by the GELs system there are some underlying limitations which could cause the system to run out of VSprites.&lt;br /&gt;
&lt;br /&gt;
As the system goes through the GEL list during DrawGList(), whenever it finds a true VSprite, it goes through the following procedure. If there is a Simple Sprite available (after the reserved sprites and preceding VSprites are accounted for), Copper instructions are added that will load the sprite hardware with this VSprite&#039;s data at the right point on the screen. It may need to add a Copper instruction sequence to load the display&#039;s colors associated with the sprite as well.&lt;br /&gt;
&lt;br /&gt;
There are only 8 &#039;&#039;real&#039;&#039; sprite DMA channels. The system will run out of hardware sprites if it is asked to display more than eight VSprites on one scan line. This limit goes down to four when the VSprites have different SprColor pointers. During the time that there is a conflict, the VSprites that could not be put into Simple Sprites will disappear. They will reappear when (as the VSprites are moved about the screen) circumstances permit.&lt;br /&gt;
&lt;br /&gt;
These problems can be alleviated by taking some precautions:&lt;br /&gt;
&lt;br /&gt;
* Minimize the number of VSprites to appear on a single horizontal line.&lt;br /&gt;
* If colors for some Virtual Sprites are the same, make sure that the pointer for each of the VSprite structures for these Virtual Sprites points to the same memory location, rather than to a duplicate set of colors elsewhere in memory. The system will know to map these into Sprite pairs.&lt;br /&gt;
&lt;br /&gt;
If a VSprite&#039;s SprColors are set to NULL, the VSprite will appear in the ViewPort&#039;s ColorMap colors. The system will display the VSprite in any one of a set of four different possible color groupings as indicated in the Simple Sprite section above.&lt;br /&gt;
&lt;br /&gt;
If SprColors points to a color set, the system will jam SprColors into the display hardware (via the Copper list), effectively overriding those ColorMap registers. The values in the ColorMap are &#039;&#039;not&#039;&#039; overwritten, but anything in the background display that used to appear in the ColorMap colors will appear in SprColors colors.&lt;br /&gt;
&lt;br /&gt;
=== How VSprite and Playfield Colors Interact ===&lt;br /&gt;
&lt;br /&gt;
At the start of each display, the system loads the colors from the ViewPort&#039;s color table into the display&#039;s hardware registers, so whatever is rendered into the BitMap is displayed correctly. But if the VSprite system is used, and the colors are specified (via SprColors) for each VSprite, the SprColors will be loaded by the system into the display hardware, as needed.&lt;br /&gt;
&lt;br /&gt;
The system does this by generating Copper instructions that will jam the colors into the hardware at specific moments in the display cycle. Any BitMap rendering, including Bobs, which share colors with VSprites, may change colors constantly as the video display beam progresses down the screen.&lt;br /&gt;
&lt;br /&gt;
This color changing can be avoided by taking one of the following precautions:&lt;br /&gt;
&lt;br /&gt;
* Use a four bitplane playfield, which only allows the lower 16 colors to be rendered into the BitMap (and allows Hires display mode).&lt;br /&gt;
* If a 32-color playfield display is being used, avoid rendering in colors 17-19, 21-23, 25-27, and 29-32, which are the colors affected by the VSprite system.&lt;br /&gt;
* Specify the VSprite SprColors pointer as a value of NULL to avoid changing the contents of any of the hardware sprite color registers. This may cause the VSprites to change colors depending on their positions relative to each other, as described in the previous section.&lt;/div&gt;</summary>
		<author><name>Costel Mincea</name></author>
	</entry>
</feed>