AMOS file formats
AMOS is the name of a family of BASIC-like programming languages created for the Amiga by François Lionet, who is also known for STOS for the Atari ST and ClickPlay for the IBM PC.
This article attempts to cover all file formats defined by AMOS itself.
All multi-byte integers are stored in big-endian format (the Amiga's native format) unless otherwise specified. All numbers are decimal, except for hexadecimal numbers prefixed by '$'.
Introduction to AMOS
AMOS is an interpreted, BASIC-like language. You work in AMOS's built-in source code editor. Your code is stored in memory as tokens; each BASIC keyword is represented by a 2-byte number. You edit each line in your program as text, but once you finish editing any line in your program and move onto the next, the line is (re-)converted to tokens.
Extensions
- Main article: AMOS extensions
AMOS not only includes the core language, but allows loading extensions. These are written in assembly code, not AMOS, and they add more instructions and functions to the AMOS language. Extensions must be loaded into one of 25 "slots", each extension has a specific slot.
Sometimes, two extensions want to use the same slot; they can't do this, you can only have one or the other. Your choice of extensions, along with all other global settings, are stored in AMOS's config file. This is AMOS1_3_PAL.env, AMOS1_3_NTSC.env in AMOS 1.3, or AMOSPro_Interpreter_Config in AMOS Pro.
When you use extension instructions, the slot number and instruction offset gets saved into your source code. Without the correct version of the extension loaded in the correct slot, your program stops working; AMOS says "Extension Not Loaded" at you. Your source code has "Extension Z" or another letter of the alphabet where the extension's instruction once was.
Memory Banks
In order to work with multimedia such as pictures and music, AMOS uses the concept of memory banks. AMOS 1.x allows up to 15 banks per AMOS program, while AMOS Professional allows up to 65535.
For example, you can load several pieces of music into different memory banks, and then identify which one you want to play by bank 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 to unpack it to 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 you have memory banks in use while saving your source code, the contents of the banks get saved along with them. This makes it easy to bundle your code with the data it works on.
Banks can also be loaded from and saved to disk using the Load and Save commands. For example:
- Save "all_banks.abs" saves all banks to disk
- Save "single_bank.abk", 6 saves a single bank to disk
- Load "single_bank.abk" loads the file into same slot it was saved from, bank 6
- Load "single_bank.abk", 11 loads the file into slot 11
- Load "all_banks.abs" clears existing banks from the program and loads the banks from the file
AMOS source code file format
AMOS source code is normally stored in a file with the extension ".AMOS". The file on disk has this format:
Offset | Length | Description |
---|---|---|
0 | 16 bytes | ASCII text describing which version of AMOS is used, and whether the program has been tested.
One of the following:
If the 12th character is uppercase "V", the program is tested. If the 12th character is lowercase "v", the program is not tested. |
20 | 4 bytes | Length of tokenised BASIC code to follow (n) |
24 | n bytes | Tokenised BASIC code, as described below |
24+n | ? bytes | Memory banks saved with the program
This section is always present, even if the number of memory banks saved is zero. The format is always the AmBs multiple memory banks format |
The tokenised BASIC code is a sequence of lines. Each line has this format:
Offset | Length | Description |
---|---|---|
0 | 1 byte | length of this line in 2-byte words (n) |
1 | 1 byte | indent level of this line |
2 | (n-1)*2 bytes | a sequence of tokens on this line, described below |
If the indent level is 2 or more, there are {indent level + 1} space characters as the beginning of the line.
Most tokens are exactly two bytes in size. A small number of tokens have special size rules and are larger than two bytes.
Token values $0000-$004E and $2B6A must be special printed, all others are simply a signed offset into AMOS's internal token table.
- The only negative offsets are "operator" tokens ($FF3E to $FFF6, or -$00C2 to -$000A when interpreted as signed values); AMOS 1.3 resolves these by having operator tokens before the start of its token table. AMOS Pro has a separate list of the operator tokens, as its real token table does not have any negative offsets. Extensions are not allowed to have negative offsets in their token table.
- All offsets are even, so the highest offset is $7FFE
Each line always ends with a compulsory null token ($0000).
Specially printed tokens
Token | Type | Interpretation |
---|---|---|
$0000 | null token | Marks the end of line. Always 2 bytes long. |
$0006 | Variable reference, e.g. Print XYZ |
The string is null terminated and its length is rounded up to a multiple of two bytes. |
$000C | Label, e.g. XYZ: or 190 at the start of a line | |
$0012 | Procedure call reference, e.g. XYZ["hello"] | |
$0018 | Label reference, e.g. Goto XYZ | |
$0026 | String with double quotes, e.g. "XYZ" |
The string should be null terminated and its length is rounded up to a multiple of two bytes. But sometimes, the string isn't null terminated. |
$002E | String with single quotes, e.g. 'XYZ' | |
$001E | Binary integer value, e.g. %100101 |
|
$0036 | Hexidecimal integer value, e.g. $80FAA010 | |
$003E | Decimal integer value, e.g. 1234567890 | |
$0046 | Floating point value, e.g. 3.1452 |
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 |
$2B6A | Double-precision float, e.g. 3.1415926543 |
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 |
$004E | Extension command |
See the list of AMOS extensions for details of extensions |
Specially sized tokens
Token | Type | Interpretation |
---|---|---|
$064A | Rem |
Print the remark string in addition to the remark token.
The remark string is null terminated and its length is rounded up to a multiple of two. |
$0652 | ' | |
$023C | For |
|
$0250 | Repeat | |
$0268 | While | |
$027E | Do | |
$02BE | If | |
$02D0 | Else | |
$0404 | Data | |
$25A4 | Else If | |
$0290 | Exit If |
|
$029E | Exit | |
$0316 | On | |
$0376 | Procedure |
|
$2A40 | Equ |
|
0x2A40 | Lvo | |
0x2A54 | Struc | |
0x2A64 | Struct |
Procedure decryption
If you should find a procedure token with the "is encrypted" bit set, run this C function on the code to decrypt the contents of the procedure. It comes from the ProCode
routine in AMOS's source code
/* 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 = (key & 0xFFFF0000) | ((key + key2) & 0xFFFF);
key2 = (key2 + key3) & 0xFFFF;
key = (key >> 1) | (key << 31); /* rotate right one bit */
}
}
src[10] ^= 0x20; /* toggle "is encrypted" bit */
}
AMOS Memory Bank formats
AMOS memory bank files on disk can be in one of three formats, depending on the 4-byte ASCII identifier they start with:
- AmBs: multiple memory banks
- AmSp or AmIc: a sprite/icon memory bank
- AmBk: a single, regular memory bank
Memory banks saved inside AMOS source code are always in the "multiple memory banks" format.
Multiple memory banks
Multiple memory banks, as found following the tokenized BASIC code in an AMOS source code file, or found on disk (usually with the file extension ".abs") are several individual banks one after the other. They have this format:
Offset | Length | Description |
---|---|---|
0 | 4 bytes | ASCII identifier AmBs |
4 | 2 bytes | Number of banks to follow (0-65535) |
6 | ? bytes | Bank data; each bank is individually sized |
AMOS Sprite and Icon bank formats
Sprite and icon banks define graphic data which can be drawn on-screen. There can only be one sprite bank and one icon bank per program. Even though it's possible to save multiple banks (e.g. create sprites, Bank Swap 1,10, create more sprites... leaving Sprites in both banks 1 and 10), loading the program will result in the later sprite banks overwriting the earlier ones.
Sprite and Icon banks do not have a "normal" bank header, they have their own format:
Offset | Length | Description | |||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 4 bytes | ASCII identifier AmSp (sprites, load to bank 1) or AmIc (icons, load to bank 2) | |||||||||||||||||||||
4 | 2 bytes | the number of sprites/icons to follow | |||||||||||||||||||||
6 | ? bytes | sprite/icon data. Each sprite/icon is individually sized and has this format:
| |||||||||||||||||||||
6+? | 64 | a 32-entry colour palette.
Each entry has the Amiga COLORx hardware register format, $0RGB |
Regular memory bank format
Regular memory banks, as opposed to the special-case sprite/icon banks or multiple banks, have this format:
Offset | Length | Description |
---|---|---|
0 | 4 bytes | ASCII identifier AmBk |
4 | 2 bytes | bank number (1-15 for AMOS, 1-65535 for AMOS Pro) |
6 | 2 bytes | flags
|
8 | 4 bytes | bank length
|
12 | 8 bytes | bank type: unterminated ASCII string which is padded with spaces |
20 | ? bytes | bank data. What's here depends on the bank type, its length is given in the bank length field |
Each bank can be located in CHIP memory, which is accessible to the Amiga's custom graphics and sound processors, or FAST memory, which is only accessible to the CPU.
Standard AMOS bank formats
The following bank types are standard to AMOS:
Type | Format | Description |
---|---|---|
"Music " | AMOS Music Bank format | This bank has music created with various conversion utilities shipped with AMOS |
"Tracker " | Protracker | This bank has tracker music loaded with the Track Load instruction |
"Amal " | AMOS AMAL Bank format | This bank contains instructions in the AMOS Animation Language format. |
"Menu " | AMOS Menu Bank format | This bank contains pull-down menu definitions |
"Datas " | n/a | This bank is created in AMOS 1.x using the Reserve As Data instruction, and has no specific format. |
"Data " | n/a | This bank is created in AMOS Pro using the Reserve As Data instruction, and has no specific format. |
"Work " | n/a | This bank is created in AMOS using the Reserve As Work instruction, and has no specific format.
As a Work bank, it is not saved as part of the source code, unlike normal data banks. |
"Asm " | 680x0 code | This bank contains Amiga machine code that was loaded into a bank using AMOS 1.x's Pload instruction.
It has no specific format, other than containing Motorola 680x0 binary code. |
"Code " | 680x0 code | This bank contains Amiga machine code that was loaded into a bank using AMOS Pro's Pload instruction.
It has no specific format, other than containing Motorola 680x0 binary code. |
"Pac.Pic." | AMOS Pac.Pic. format | This bank contains an image created with the Compact extension's Pack instruction |
"Resource" | AMOS Resource format | This bank contains control buttons and icons for use with AMOS Pro's Resource instructions |
"Samples " | AMOS Samples Bank format | This bank is created with the Sample Bank Editor shipped with AMOS.
The samples can be played back with the Sam Play instruction |