AMOS BASIC tokenized file

From Just Solve the File Format Problem
(Difference between revisions)
Jump to: navigation, search
(AMOS Picture Bank format)
(Specially sized tokens)
(11 intermediate revisions by 2 users not shown)
Line 3: Line 3:
 
|subcat2=Tokenized BASIC
 
|subcat2=Tokenized BASIC
 
|released=1990
 
|released=1990
|extensions={{ext|amos}}, {{ext|abk}}
+
|extensions={{ext|amos}}
 
}}
 
}}
 
+
AMOS BASIC is a family of [[BASIC]] dialects for the Amiga computer. They were written by François Lionet, who also wrote AMOS's predecessor, STOS BASIC for the Atari ST (see [[STOS memory bank]]).
AMOS BASIC is a family of [[BASIC]] dialects for the Amiga computer. They were written by François Lionet, who also wrote AMOS"s predecessor, STOS BASIC for the Atari ST.
+
  
 
There are several versions of AMOS published: ''AMOS The Creator'', ''Easy AMOS'' and ''AMOS Professional''.
 
There are several versions of AMOS published: ''AMOS The Creator'', ''Easy AMOS'' and ''AMOS Professional''.
Line 28: Line 27:
  
 
=== Banks ===
 
=== Banks ===
In order to work with multimedia such as pictures and music, AMOS has the concept of a ''memory bank''. An AMOS program can have up to 15 memory banks. For example, you can load several pieces of music into different memory banks, and then identify which one you want to play by a number: <code>Track Play 5</code> will play music in bank 5. Or you could load a packed picture into bank 4 and say <code>Unpack 4 to 0</code>, which will unpack the picture onto screen 0.
+
In order to work with multimedia such as pictures and music, AMOS has the concept of a ''bank'' or ''memory bank'' (see [[AMOS Memory Bank#Disambiguation]] for a note about terminology). An AMOS program can have up to 15 banks. For example, you can load several pieces of music into different banks, and then identify which one you want to play by a number: <code>Track Play 5</code> will play music in bank 5. Or you could load a packed picture into bank 4 and say <code>Unpack 4 to 0</code>, which will unpack the picture onto screen 0.
  
 
While you can load anything into any bank, some instructions can only take their data from specific bank numbers. Bank 1 is used for Sprites, which are controlled with instructions beginning <code>Sprite</code> or <code>Bob</code>. Bank 2 is for Icons, which are controlled with instructions beginning <code>Icon</code>. Bank 3 is used for music in AMOS's native music format.
 
While you can load anything into any bank, some instructions can only take their data from specific bank numbers. Bank 1 is used for Sprites, which are controlled with instructions beginning <code>Sprite</code> or <code>Bob</code>. Bank 2 is for Icons, which are controlled with instructions beginning <code>Icon</code>. Bank 3 is used for music in AMOS's native music format.
  
If memory banks are in use while saving source code, the contents of the banks are included in the saved source code. This makes it easy to bundle code with the data it works on. The exception to this rule is banks created using the <code>Reserve As Work</code> instruction.
+
If banks are in use while saving source code, the contents of the banks are included in the saved source code. This makes it easy to bundle code with the data it works on. The exception to this rule is banks created using the <code>Reserve As Work</code> instruction.
  
 
== AMOS source code ==
 
== AMOS source code ==
All multi-byte integer values are in big-endian (Motorola) format.
+
All multi-byte integer values are in big-[[Endianness|endian]] (Motorola) format.
  
 
AMOS source code is stored in a file with the extension <samp>.AMOS</samp>. It has the following structure:
 
AMOS source code is stored in a file with the extension <samp>.AMOS</samp>. It has the following structure:
  
 
{|class="wikitable"
 
{|class="wikitable"
!Section!!Length
+
!colspan="2"| Section
 +
!Length
 
|-
 
|-
|Header identifying which version of AMOS saved the file
+
|colspan="2"| Header identifying which version of AMOS saved the file
*"<samp>AMOS Pro101V\0\0\0\0</samp>" (AMOS Professional, source tested)
+
*"<samp>AMOS Pro111V</samp>" and 4 more bytes (AMOS Professional, source tested)
*"<samp>AMOS Pro101v\0\0\0\0</samp>" (AMOS Professional, source not tested)
+
*"<samp>AMOS Pro111v</samp>" and 4 more bytes (AMOS Professional, source not tested)
 +
*"<samp>AMOS Pro101V</samp>" and 4 more bytes (AMOS Professional, source tested)
 +
*"<samp>AMOS Pro101v</samp>" and 4 more bytes (AMOS Professional, source not tested)
 
*"<samp>AMOS Basic V134 </samp>" (AMOS Pro compatible with AMOS 1.3, source tested)
 
*"<samp>AMOS Basic V134 </samp>" (AMOS Pro compatible with AMOS 1.3, source tested)
 
*"<samp>AMOS Basic v134 </samp>" (AMOS Pro compatible with AMOS 1.3, source not tested)
 
*"<samp>AMOS Basic v134 </samp>" (AMOS Pro compatible with AMOS 1.3, source not tested)
 
*"<samp>AMOS Basic V1.3 </samp>" (AMOS The Creator v1.3, source tested)
 
*"<samp>AMOS Basic V1.3 </samp>" (AMOS The Creator v1.3, source tested)
 
*"<samp>AMOS Basic v1.3 </samp>" (AMOS The Creator v1.3, source not tested)
 
*"<samp>AMOS Basic v1.3 </samp>" (AMOS The Creator v1.3, source not tested)
*"<samp>AMOS Basic V1.00</samp>" (AMOS The Creator v1.0 - v1.2, source tested)
+
*"<samp>AMOS Basic V1.23</samp>" (AMOS The Creator v1.2, source tested)
*"<samp>AMOS Basic v1.00</samp>" (AMOS The Creator v1.0 - v1.2, source not tested)
+
*"<samp>AMOS Basic v1.23</samp>" (AMOS The Creator v1.2, source not tested)
 +
*"<samp>AMOS Basic V1.00</samp>" (AMOS The Creator v1.0 v1.1, source tested)
 +
*"<samp>AMOS Basic v1.00</samp>" (AMOS The Creator v1.0 v1.1, source not tested)
 
|16 bytes
 
|16 bytes
 
|-
 
|-
|Length in bytes of tokenized BASIC code to follow
+
|colspan="2"| Length in bytes of tokenized BASIC code to follow
 
|4 bytes
 
|4 bytes
 
|-
 
|-
|Tokenized BASIC code
+
|colspan="2"| Tokenized BASIC code
 
|varies
 
|varies
 
|-
 
|-
 +
|rowspan="3"| [[AMOS AmBs]] segment
 
|ASCII identifier "<samp>AmBs</samp>"
 
|ASCII identifier "<samp>AmBs</samp>"
 
|4 bytes
 
|4 bytes
 
|-
 
|-
|Count of AMOS memory banks to follow (0-16)
+
|Count of AMOS banks to follow (0–16)
 
|2 bytes
 
|2 bytes
 
|-
 
|-
|AMOS memory banks. Each bank's length must be individually determined.
+
|AMOS banks. Each bank's length must be individually determined.
 
|varies
 
|varies
 
|}
 
|}
Line 90: Line 95:
 
Each token starts with a signed 16-bit number. Token values between 0x0000 and 0x004E have special printing and size rules, all other tokens are a signed offset into AMOS's internal token table. The instruction name in the internal token table is what should be printed.
 
Each token starts with a signed 16-bit number. Token values between 0x0000 and 0x004E have special printing and size rules, all other tokens are a signed offset into AMOS's internal token table. The instruction name in the internal token table is what should be printed.
  
==== Specially printed tokens ====
+
=== Specially printed tokens ===
 
{|class="wikitable"
 
{|class="wikitable"
 
!Token!!Type!!Interpretation
 
!Token!!Type!!Interpretation
Line 96: Line 101:
 
|0x0000
 
|0x0000
 
|null token
 
|null token
|Marks the end of line. Always 2 bytes long
+
|Marks the end of line. Always 2 bytes long.
 
|-
 
|-
 
|0x0006
 
|0x0006
Line 103: Line 108:
 
* 2 bytes: token
 
* 2 bytes: token
 
* 2 bytes: unknown purpose
 
* 2 bytes: unknown purpose
* 1 byte: length of ISO-8859-1 string for the variable or label name
+
* 1 byte: length of [[ISO 8859-1|ISO-8859-1]] string for the variable or label name
 
* 1 byte: flags, for tokens 0x0006, 0x0012 and 0x0018:
 
* 1 byte: flags, for tokens 0x0006, 0x0012 and 0x0018:
 
**bit 1 set: this is a floating point reference, e.g. <code>XYZ#</code>
 
**bit 1 set: this is a floating point reference, e.g. <code>XYZ#</code>
 
**bit 2 set: this is a string reference, e.g. <code>XYZ$</code>
 
**bit 2 set: this is a string reference, e.g. <code>XYZ$</code>
* variable length: ISO-8859-1 string, with the above given length. The string is null terminated and its length is rounded up to a multiple of two
+
* variable length: ISO-8859-1 string, with the above given length. The string is null terminated and its length is rounded up to a multiple of two bytes.
 
|-
 
|-
 
|0x000C
 
|0x000C
Line 123: Line 128:
 
* 2 bytes: token
 
* 2 bytes: token
 
* 2 bytes: length of ISO-8859-1 string to follow
 
* 2 bytes: length of ISO-8859-1 string to follow
* variable length: ISO-8859-1 string, with the above given length. The string is null terminated and its length is rounded up to a multiple of two
+
* variable length: ISO-8859-1 string, with the above given length, rounded up to a multiple of two. The string should be null-terminated, but sometimes isn't.
 
|-
 
|-
 
|0x002E
 
|0x002E
Line 144: Line 149:
 
|
 
|
 
* 2 bytes: token
 
* 2 bytes: token
* 4 bytes: the single-precision floating point value.
+
* 4 bytes: a single-precision floating point value
**bits 31-8: mantissa (24 bits)
+
** bits 31-8: mantissa (24 bits), most significant bit is always set
**bit 7: sign bit. Positive if 0, negative if 1
+
** bit 7: ignore (should be sign bit, but all AMOS floats are positive)
**bits 6-0: exponent
+
** bits 6-0: exponent (from 0x00 to 0x7F)
  
An exponent of 0 means 0.0, regardless of mantissa. Counting from MSB (23) to LSB (0), each bit set in the mantissa is 2^(<var>mantissa bit</bar> + <var>exponent</var> - 88)
+
An exponent of 0 means 0.0, regardless of mantissa.
 +
 
 +
Each set bit in the mantissa has the value 2<sup>''m''+''e''-88</sup> where ''m'' is from 23 (MSB) to 0 (LSB) and ''e'' is the exponent
 +
|-
 +
|0x2B6A
 +
|Double-precision float, e.g. <code>'''3.1415926543'''</code>
 +
|
 +
* 2 bytes: token
 +
* 8 bytes: a double-precision floating point value
 +
** bit 63: ignore (should be sign bit, but all AMOS floats are positive)
 +
** bits 62-51: exponent (from 0x000 to 0x7FF)
 +
** bits 50-0: mantissa (52 bits), most significant bit is not stored but implicitly set
 +
 
 +
An exponent of 0 means 0.0, regardless of mantissa.
 +
 
 +
Each set bit in the mantissa has the value 2<sup>''m''+''e''-1074</sup> where ''m'' is from 51 (implicit MSB) to 0 (LSB) and ''e'' is the exponent
 
|-
 
|-
 
|0x004E
 
|0x004E
Line 160: Line 180:
 
|}
 
|}
  
==== Specially sized tokens ====
+
=== Specially sized tokens ===
 
{|class="wikitable"
 
{|class="wikitable"
 
!Token!!Type!!Interpretation
 
!Token!!Type!!Interpretation
Line 170: Line 190:
 
* 1 byte: unused
 
* 1 byte: unused
 
* 1 byte: length of ISO-8859-1 string to follow
 
* 1 byte: length of ISO-8859-1 string to follow
* variable length: ISO-8859-1 string, with the above-given length. The string is null terminated and its length is rounded up to a multiple of two. The string should be printed after the remark token.
+
* variable length: ISO-8859-1 string, with the above-given length.
 +
 
 +
The string is null terminated and its length is rounded up to a multiple of two.
 +
 
 +
The string should be printed after the remark token.
 
|-
 
|-
 
|0x0652
 
|0x0652
Line 177: Line 201:
 
|0x023C
 
|0x023C
 
|<code>For</code>
 
|<code>For</code>
| rowspan="7" |
+
| rowspan="8" |
 
* 2 bytes: token
 
* 2 bytes: token
 
* 2 bytes: unknown purpose
 
* 2 bytes: unknown purpose
Line 192: Line 216:
 
|-
 
|-
 
|0x0404||<code>Data</code>
 
|0x0404||<code>Data</code>
 +
|-
 +
|0x25A4||<code>Else If</code>
 
|-
 
|-
 
|0x0290
 
|0x0290
Line 215: Line 241:
 
** bit 4: if set, procedure contains compiled code and not tokens
 
** bit 4: if set, procedure contains compiled code and not tokens
 
* 1 byte: part of seed for encryption
 
* 1 byte: part of seed for encryption
 +
|-
 +
|0x2A40||<code>Equ</code>
 +
| rowspan="4"|
 +
* 2 bytes: token
 +
* 4 bytes: stored equate value
 +
* 1 byte: equate type (0-7)
 +
* 1 byte: unknown purpose
 +
|-
 +
|0x2A40||<code>Lvo</code>
 +
|-
 +
|0x2A54||<code>Struc</code>
 +
|-
 +
|0x2A64||<code>Struct</code>
 
|}
 
|}
  
Line 220: Line 259:
 
If you should find a procedure (0x0376) token with the "is encrypted" bit set, run this C function on the code and it will decrypt the contents of the procedure.
 
If you should find a procedure (0x0376) token with the "is encrypted" bit set, run this C function on the code and it will decrypt the contents of the procedure.
  
  /* fetches a 4-byte integer in big-endian format */
+
  /* read 16-bit big-endian word from unsigned char[] */
  #define EndGetM32(a) ((((a)[0])<<24)|(((a)[1])<<16)|(((a)[2])<<8)|((a)[3]))
+
  #define amos_deek(a) ((((a)[0])<<8)|((a)[1]))
/* fetches a 2-byte integer in big-endian format */
+
/* read 32-bit big-endian word from unsigned char[] */
#define EndGetM16(a)  ((((a)[0])<<8)|((a)[1]))
+
#define amos_leek(a) ((((a)[0])<<24)|(((a)[1])<<16)|(((a)[2])<<8)|((a)[3]))
 
   
 
   
  void decrypt_procedure(unsigned char *src) {
+
  void AMOS_decrypt_procedure(unsigned char *src) {
 
     unsigned char *line, *next, *endline;
 
     unsigned char *line, *next, *endline;
 
     unsigned int key, key2, key3, size;
 
     unsigned int key, key2, key3, size;
 
   
 
   
     /* ensure src is a pointer to a line with the PROCEDURE token on it */
+
     /* src should be a pointer to a line with the PROCEDURE token on it */
     if (EndGetM16(&src[2]) != 0x0376) return;
+
     if (amos_deek(&src[2]) != 0x0376) return;
 
   
 
   
 
     /* do not operate on compiled procedures */
 
     /* do not operate on compiled procedures */
 
     if (src[10] & 0x10) return;
 
     if (src[10] & 0x10) return;
 
   
 
   
    /* size + 8 + 6 is the start of the line after END PROC */
+
     size = amos_leek(&src[4]);
     size = EndGetM32(&src[4]);
+
     line = next = &src[src[0] * 2]; /* the line after PROCEDURE */
    endline = &src[size + 8 + 6];
+
    endline = &src[size + 8 + 6]; /* the start of the line after END PROC */
     line = next = &src[src[0] * 2];
+
 
   
 
   
     /* initialise encryption keys */
+
     /* initialise keys */
 
     key = (size << 8) | src[11];
 
     key = (size << 8) | src[11];
 
     key2 = 1;
 
     key2 = 1;
     key3 = EndGetM16(&src[8]);
+
     key3 = amos_deek(&src[8]);
 
   
 
   
 
     while (line < endline) {
 
     while (line < endline) {
         line = next;
+
         line = next; next = &line[line[0] * 2];
        next = &line[line[0] * 2];
+
+
        /* decrypt one line */
+
 
         for (line += 4; line < next;) {
 
         for (line += 4; line < next;) {
 
             *line++ ^= (key >> 8) & 0xFF;
 
             *line++ ^= (key >> 8) & 0xFF;
 
             *line++ ^=  key      & 0xFF;
 
             *line++ ^=  key      & 0xFF;
             key = (key & 0xFFFF0000) | ((key+key2) & 0x0000FFFF);
+
             key += key2;
 
             key2 += key3;
 
             key2 += key3;
             key = (key >> 1) | (key << 31);
+
             key = (key >> 1) | (key << 31); /* rotate right one bit */
 
         }
 
         }
 
     }
 
     }
Line 261: Line 296:
 
  }
 
  }
  
== AMOS Memory Banks ==
+
== AMOS Banks ==
AMOS memory banks can be found either included with AMOS source code, saved individually on disk, where they typically have the file extension <samp>.ABK</samp>
+
AMOS banks can be found either included with AMOS source code, saved individually on disk, where they typically have the file extension <samp>.ABK</samp>.
  
AMOS allows for 15 banks in an program. Each bank can be located in "chip" memory, which is accessible to the Amiga's custom graphics and sound processors, or it can be located in "fast" memory, which is only accessible to the CPU.  
+
AMOS allows for 15 banks in an program. Each bank can be located in "chip" memory, which is accessible to the Amiga's custom graphics and sound processors, or it can be located in "fast" memory, which is only accessible to the CPU.
  
Memory banks are identified by their first four bytes. They are either Sprite/Icon banks (using the ASCII identifier <samp>AmSp</samp> or <samp>AmIc</samp>), or they are "normal" memory banks, which covers all other possible bank formats (using the identifier <samp>AmBk</samp>)
+
Banks are identified by their first four bytes. They are either Sprite/Icon banks (using the ASCII identifier <samp>AmSp</samp> or <samp>AmIc</samp>), or they are "normal" memory banks, which covers all other possible bank formats (using the identifier <samp>AmBk</samp>).
  
 
=== AMOS Sprite/Icon Bank format ===
 
=== AMOS Sprite/Icon Bank format ===
:''See also: [[AMOS Sprite Bank]] and [[AMOS Icon Bank]]
+
Refer to [[AMOS Sprite Bank]]. See also [[AMOS Icon Bank]].
 
+
A sprite bank and an icon bank share very similar attributes. They define graphic data which can be drawn onscreen. They have this format:
+
 
+
{|class="wikitable"
+
!Field!!Length
+
|-
+
|Bank identifier: <samp>AmSp</samp> for sprites (bank 1) or <samp>AmIc</samp> for icons (bank 2)
+
|4 bytes
+
|-
+
|Count of sprites/icons to follow
+
|2 bytes
+
|-
+
|Sprites/Icons. Each sprite or icon has this format:
+
* 2 bytes: <var>width</var>, in 16-bit words (multiply by 16 to get width in pixels)
+
* 2 bytes: <var>height</var>, in raster lines (pixels)
+
* 2 bytes: <var>depth</var>, in bitplanes (1 to 5)
+
* 2 bytes: hot-spot X co-ordinate
+
* 2 bytes: hot-spot Y co-ordinate
+
* <var>width</var> * <var>height</var> * <var>depth</var> * 2 bytes: Amiga planar graphic data
+
|-
+
|Color palette: 32 16-bit colors in 0x0RGB form, the Amiga COLORx hardware register format
+
|64 bytes
+
|}
+
  
 
=== AMOS Memory Bank format ===
 
=== AMOS Memory Bank format ===
Apart from Sprite and Icon banks, each bank has a standard header
+
Refer to the main article: [[AMOS Memory Bank]].
  
{|class="wikitable"
+
== Software ==
!Field!!Length
+
* [https://github.com/kyz/amostools/ amostools]
|-
+
|ASCII identifier <samp>AmBk</samp>
+
|4 bytes
+
|-
+
|Bank number (1-15)
+
|2 bytes
+
|-
+
|Memory type: 0 for chip memory, 1 for fast memory
+
|2 bytes
+
|-
+
|Bank length (bits 27-0). Bits 28 and 29 are undefined, not part of the length field. Bit 30 means "try chip memory", bit 31 means "try fast memory" if set
+
|4 bytes
+
|-
+
|Bank name. Unterminated ASCII text padded with spaces
+
|8 bytes
+
|-
+
|Bank data
+
|<var>bank length</var> - 8 bytes
+
|}
+
  
==== AMOS Music Bank format ====
+
== Sample files ==
:''See also: [[AMOS Music Bank]]
+
* http://cd.textfiles.com/amospd/SourceCode/
 
+
This bank has the name "<samp>Music  </samp>" and is created with various conversion utilities shipped with AMOS. It is played back with the Music extension.
+
 
+
==== AMOS AMAL Bank format ====
+
 
+
This bank has the name "<samp>Amal    </samp>". It contains instructions in AMOS Animation Language format.
+
 
+
==== AMOS Menu Bank format ====
+
 
+
This bank has the name "<samp>Menu    </samp>". It contains pull-down menu definitions.
+
 
+
==== AMOS Data Bank format ====
+
 
+
This bank has the name "<samp>Datas  </samp>". It is created in AMOS using the <code>Reserve As Data</code> instruction, and has no specific format.
+
 
+
==== AMOS Work Bank format ====
+
 
+
This bank has the name "<samp>Work    </samp>". It is created in AMOS using the <code>Reserve As Work</code> instruction, and has no specific format. As a Work bank, it is not saved as part of the source code, unlike normal data banks.
+
 
+
==== AMOS Asm Bank format ====
+
 
+
This bank has the name "<samp>Asm    </samp>". It contains Amiga machine code that was loaded into a bank using the <code>Pload</code> instruction and has no specific format, other than containing MC680x0 binary code.
+
 
+
The <code>Pload</code> instruction takes the first code hunk out of an Amiga executable and copies it into the bank, without even applying its relocations, therefore all code needs to use PC-relative addressing. The <code>Call</code> instruction jumps directly to the start of the bank. The registers (A0, A1, D0, D1, ...) can be set in preparation for a call by setting the <code>Areg()</code> and <code>Dreg()</code> arrays. Extra parameters can also be included with the <code>Call</code> instruction, these are made available to the called function via a stack pointed to by the A3 register.
+
 
+
==== AMOS Picture Bank format ====
+
:''See also: [http://www.exotica.org.uk/wiki/AMOS_Pac.Pic._format AMOS Pac.Pic. format]''
+
 
+
This bank has the name "<samp>Pac.Pic.</samp>" and is created with the Compact extension's <code>Pack</code> instruction.
+
 
+
==== AMOS Samples Bank format ====
+
 
+
This bank has the name "<samp>Samples </samp>" and is created with the Sample Bank Editor shipped with AMOS. The samples can be played back with the Music extension. The format of the bank data is as follows:
+
 
+
{|class="wikitable"
+
!Field!!Length
+
|-
+
|Count of samples
+
|2 bytes
+
|-
+
|32-bit offset to each sample, relative to the <var>count of samples</var> field above
+
|<var>count of samples</var> * 4 bytes
+
|}
+
 
+
The format of each sample is as follows:
+
 
+
{|class="wikitable"
+
!Field!!Length
+
|-
+
|Sample name, in ISO-8859-1
+
|8 bytes
+
|-
+
|Sample frequency in Hertz
+
|2 bytes
+
|-
+
|Sample length in bytes
+
|4 bytes
+
|-
+
|Sample data: twos complement 8-bit signed PCM samples
+
|varies
+
|}
+
  
 
== Links and references ==
 
== Links and references ==
 +
* [https://www.exotica.org.uk/wiki/AMOS_file_formats AMOS file formats - ExoticA]
 
* [http://www.amigacoding.com/index.php/AMOS:Extensions AMOS Extensions - Amiga Coding wiki]
 
* [http://www.amigacoding.com/index.php/AMOS:Extensions AMOS Extensions - Amiga Coding wiki]
* [http://www.exotica.org.uk/wiki/AMOS_file_formats AMOS file formats - ExoticA]
 
 
* [http://www.triumphoverchallenges.com/stos-and-amos-game-creators/ STOS and AMOS publishing history]
 
* [http://www.triumphoverchallenges.com/stos-and-amos-game-creators/ STOS and AMOS publishing history]
 +
 +
[[Category:Amiga]]

Revision as of 02:29, 18 January 2019

File Format
Name AMOS BASIC tokenized file
Ontology
Extension(s) .amos
Released 1990

AMOS BASIC is a family of BASIC dialects for the Amiga computer. They were written by François Lionet, who also wrote AMOS's predecessor, STOS BASIC for the Atari ST (see STOS memory bank).

There are several versions of AMOS published: AMOS The Creator, Easy AMOS and AMOS Professional.

AMOS has its own integrated development environment, and it uses its own custom file formats for everything, from source code to graphics and sound.

Contents

Overview

AMOS is an interpreted BASIC dialect where code is edited and run in an integrated development environment. Every time the programmer finishes editing a line of code, it is immediately parsed into tokens. For example, typing procedure foobar and pressing the return key will change the line into Procedure FOOBAR.

Before a program can run, it will be tested to ensure it is free of syntax errors. Source code can be saved even if it is untested or fails testing, but AMOS includes a tested flag in the saved file. This is used by external software, for example the AMOS Compiler will refuse to compile an untested source code file.

Extensions

AMOS tokens are split between instructions in the core language and instructions in extensions.

Extensions are external files, written in 68000 assembler, which begin with a token table listing all the instructions they add to the language.

Each extension is intended to be loaded into a specific slot. AMOS has 25 slots for extensions. The configuration of extensions and their slots are saved in AMOS's global config file.

To load other people's source code, AMOS needs to be configured with the same versions of the same extensions that they used, in the same slots.

Banks

In order to work with multimedia such as pictures and music, AMOS has the concept of a bank or memory bank (see AMOS Memory Bank#Disambiguation for a note about terminology). An AMOS program can have up to 15 banks. For example, you can load several pieces of music into different banks, and then identify which one you want to play by a number: Track Play 5 will play music in bank 5. Or you could load a packed picture into bank 4 and say Unpack 4 to 0, which will unpack the picture onto screen 0.

While you can load anything into any bank, some instructions can only take their data from specific bank numbers. Bank 1 is used for Sprites, which are controlled with instructions beginning Sprite or Bob. Bank 2 is for Icons, which are controlled with instructions beginning Icon. Bank 3 is used for music in AMOS's native music format.

If banks are in use while saving source code, the contents of the banks are included in the saved source code. This makes it easy to bundle code with the data it works on. The exception to this rule is banks created using the Reserve As Work instruction.

AMOS source code

All multi-byte integer values are in big-endian (Motorola) format.

AMOS source code is stored in a file with the extension .AMOS. It has the following structure:

Section Length
Header identifying which version of AMOS saved the file
  • "AMOS Pro111V" and 4 more bytes (AMOS Professional, source tested)
  • "AMOS Pro111v" and 4 more bytes (AMOS Professional, source not tested)
  • "AMOS Pro101V" and 4 more bytes (AMOS Professional, source tested)
  • "AMOS Pro101v" and 4 more bytes (AMOS Professional, source not tested)
  • "AMOS Basic V134 " (AMOS Pro compatible with AMOS 1.3, source tested)
  • "AMOS Basic v134 " (AMOS Pro compatible with AMOS 1.3, source not tested)
  • "AMOS Basic V1.3 " (AMOS The Creator v1.3, source tested)
  • "AMOS Basic v1.3 " (AMOS The Creator v1.3, source not tested)
  • "AMOS Basic V1.23" (AMOS The Creator v1.2, source tested)
  • "AMOS Basic v1.23" (AMOS The Creator v1.2, source not tested)
  • "AMOS Basic V1.00" (AMOS The Creator v1.0 – v1.1, source tested)
  • "AMOS Basic v1.00" (AMOS The Creator v1.0 – v1.1, source not tested)
16 bytes
Length in bytes of tokenized BASIC code to follow 4 bytes
Tokenized BASIC code varies
AMOS AmBs segment ASCII identifier "AmBs" 4 bytes
Count of AMOS banks to follow (0–16) 2 bytes
AMOS banks. Each bank's length must be individually determined. varies

Tokenised BASIC code

Tokenised BASIC code is a sequence of tokenised lines. Each tokenised line has the following format:

Field Length
Length of this line in words (2 bytes), including this byte. To get the length of the line in bytes, double this value 1 byte
Indent level of this line. Prefix indent level + 1 spaces at the beginning of the line, or no spaces if the value is less than 2 1 byte
Sequence of tokens. Each token is at least two bytes, and all tokens are rounded to to a multiple of two bytes. Each token is individually sized. The tokens always end with a compulsory null token varies

Some tokens have special size rules, but most are exactly 2 bytes in size.

Each token starts with a signed 16-bit number. Token values between 0x0000 and 0x004E have special printing and size rules, all other tokens are a signed offset into AMOS's internal token table. The instruction name in the internal token table is what should be printed.

Specially printed tokens

Token Type Interpretation
0x0000 null token Marks the end of line. Always 2 bytes long.
0x0006 Variable reference, e.g. Print XYZ
  • 2 bytes: token
  • 2 bytes: unknown purpose
  • 1 byte: length of ISO-8859-1 string for the variable or label name
  • 1 byte: flags, for tokens 0x0006, 0x0012 and 0x0018:
    • bit 1 set: this is a floating point reference, e.g. XYZ#
    • bit 2 set: this is a string reference, e.g. XYZ$
  • variable length: ISO-8859-1 string, with the above given length. The string is null terminated and its length is rounded up to a multiple of two bytes.
0x000C Label, e.g. XYZ: or 190 at the start of a line
0x0012 Procedure call reference, e.g. XYZ["hello"]
0x0018 Label reference, e.g. Goto XYZ
0x0026 String with double quotes, e.g. "XYZ"
  • 2 bytes: token
  • 2 bytes: length of ISO-8859-1 string to follow
  • variable length: ISO-8859-1 string, with the above given length, rounded up to a multiple of two. The string should be null-terminated, but sometimes isn't.
0x002E String with single quotes, e.g. 'XYZ'
0x001E Binary integer value, e.g. %100101
  • 2 bytes: token
  • 4 bytes: the integer value
0x0036 Hexidecimal integer value, e.g. $80FAA010
0x003E Decimal integer value, e.g. 1234567890
0x0046 Floating point value, e.g. 3.1452
  • 2 bytes: token
  • 4 bytes: a single-precision floating point value
    • bits 31-8: mantissa (24 bits), most significant bit is always set
    • bit 7: ignore (should be sign bit, but all AMOS floats are positive)
    • bits 6-0: exponent (from 0x00 to 0x7F)

An exponent of 0 means 0.0, regardless of mantissa.

Each set bit in the mantissa has the value 2m+e-88 where m is from 23 (MSB) to 0 (LSB) and e is the exponent

0x2B6A Double-precision float, e.g. 3.1415926543
  • 2 bytes: token
  • 8 bytes: a double-precision floating point value
    • bit 63: ignore (should be sign bit, but all AMOS floats are positive)
    • bits 62-51: exponent (from 0x000 to 0x7FF)
    • bits 50-0: mantissa (52 bits), most significant bit is not stored but implicitly set

An exponent of 0 means 0.0, regardless of mantissa.

Each set bit in the mantissa has the value 2m+e-1074 where m is from 51 (implicit MSB) to 0 (LSB) and e is the exponent

0x004E Extension instruction
  • 2 bytes: token
  • 1 byte: extension slot (1 to 26)
  • 1 byte: unused
  • 2 bytes: signed 16-bit offset into extension's token table

Specially sized tokens

Token Type Interpretation
0x064A Rem
  • 2 bytes: token (0x064A or 0x0652)
  • 1 byte: unused
  • 1 byte: length of ISO-8859-1 string to follow
  • variable length: ISO-8859-1 string, with the above-given length.

The string is null terminated and its length is rounded up to a multiple of two.

The string should be printed after the remark token.

0x0652 '
0x023C For
  • 2 bytes: token
  • 2 bytes: unknown purpose
0x0250 Repeat
0x0268 While
0x027E Do
0x02BE If
0x02D0 Else
0x0404 Data
0x25A4 Else If
0x0290 Exit If
  • 2 bytes: token
  • 4 bytes: unknown purpose
0x029E Exit
0x0316 On
0x0376 Procedure
  • 2 bytes: token
  • 4 bytes: number of bytes to corresponding End Proc line
(start of line + 8 + above = start of End Proc line)
(start of line + 8 + 6 + above = line after End Proc line)
  • 2 bytes: part of seed for encryption
  • 1 byte: flags
    • bit 7: if set, procedure is folded
    • bit 6: if set, procedure is locked and shouldn't be unfolded
    • bit 5: if set, procedure is currently encrypted
    • bit 4: if set, procedure contains compiled code and not tokens
  • 1 byte: part of seed for encryption
0x2A40 Equ
  • 2 bytes: token
  • 4 bytes: stored equate value
  • 1 byte: equate type (0-7)
  • 1 byte: unknown purpose
0x2A40 Lvo
0x2A54 Struc
0x2A64 Struct

Encrypted procedures

If you should find a procedure (0x0376) token with the "is encrypted" bit set, run this C function on the code and it will decrypt the contents of the procedure.

/* read 16-bit big-endian word from unsigned char[] */
#define amos_deek(a) ((((a)[0])<<8)|((a)[1]))
/* read 32-bit big-endian word from unsigned char[] */
#define amos_leek(a) ((((a)[0])<<24)|(((a)[1])<<16)|(((a)[2])<<8)|((a)[3]))

void AMOS_decrypt_procedure(unsigned char *src) {
    unsigned char *line, *next, *endline;
    unsigned int key, key2, key3, size;

    /* src should be a pointer to a line with the PROCEDURE token on it */
    if (amos_deek(&src[2]) != 0x0376) return;

    /* do not operate on compiled procedures */
    if (src[10] & 0x10) return;

    size = amos_leek(&src[4]);
    line = next = &src[src[0] * 2]; /* the line after PROCEDURE */
    endline = &src[size + 8 + 6]; /* the start of the line after END PROC */

    /* initialise keys */
    key = (size << 8) | src[11];
    key2 = 1;
    key3 = amos_deek(&src[8]);

    while (line < endline) {
        line = next; next = &line[line[0] * 2];
        for (line += 4; line < next;) {
            *line++ ^= (key >> 8) & 0xFF;
            *line++ ^=  key       & 0xFF;
            key  += key2;
            key2 += key3;
            key = (key >> 1) | (key << 31); /* rotate right one bit */
        }
    }
    src[10] ^= 0x20; /* toggle "is encrypted" bit */
}

AMOS Banks

AMOS banks can be found either included with AMOS source code, saved individually on disk, where they typically have the file extension .ABK.

AMOS allows for 15 banks in an program. Each bank can be located in "chip" memory, which is accessible to the Amiga's custom graphics and sound processors, or it can be located in "fast" memory, which is only accessible to the CPU.

Banks are identified by their first four bytes. They are either Sprite/Icon banks (using the ASCII identifier AmSp or AmIc), or they are "normal" memory banks, which covers all other possible bank formats (using the identifier AmBk).

AMOS Sprite/Icon Bank format

Refer to AMOS Sprite Bank. See also AMOS Icon Bank.

AMOS Memory Bank format

Refer to the main article: AMOS Memory Bank.

Software

Sample files

Links and references

Personal tools
Namespaces

Variants
Actions
Navigation
Toolbox