Locomotive BASIC

Amstrad BASICFile:180px

First appeared| 1984; 42 years ago (1984)
OS| AMSDOS
License| Proprietary
Influenced by

* Mallard BASIC
* BBC BASIC

Locomotive Basic is a proprietary dialect of the BASIC programming language written by Locomotive Software.

It was modified (many custom features to support the platform) for use on the Amstrad CPC as "Amstrad BASIC" (where it was built-in on ROM).

Later Locomotive BASIC-2 was produced for the IBM PC compatibles platform as a GEM application on the Amstrad PC1512 and 1640 and was a descendant of Mallard BASIC,[1] the interpreter for CP/M supplied with the Amstrad PCW.

There are two published versions of Amstrad BASIC; 1.0 which only came with the CPC464 (and had a buggy `DEC$` function), and 1.1 which corrected this and shipped with all other CPCs. BASIC 1.1 was also included in the Amstrad CPC Plus series machines, as part of the included game cartridge.

## Contents

* 1 Development
* 2 Features of the CPC platform
* 2.1 Firmware jump blocks
* 2.2 The firmware modules
* 3 BASIC and version differences
* 3.1 BASIC 1.0
* 3.2 BASIC 1.1
* 4 Variables and functions
* 4.1 Two missed opportunities?
* 5 Graphics and colour
* 6 Text handling
* 7 Advanced features
* 8 Machine code support and RSXs
* 9 Memory allocation and management
* 10 Memory bank switching and a notable omission
* 11 Contemporary rivals
* 12 References
* 13 External links

## Development

Development was based on existing work recently undertaken writing Mallard BASIC for Acorn Computers Z80 addon for the BBC Micro. It is reported to have taken around 12 weeks to enhance the existing code, and was "very influenced" by BBC BASIC, though adding additional functions to do things that would have required assembly language on the BBC.[1]

The "ARNOLD" platform (the CPC464 development codename) was designed to be solid enough to attract the "serious" users Amstrad wanted. Locomotive were engaged to produce the firmware and BASIC for the platform. The mix produced a comprehensive result with technical capabilities almost unheard of in any one contemporary platform - the tidy approach to firmware access with fixed jump blocks, the hypothecation of the firmware into modules, the clever hardware allowing expandability, with multiple pages of RAM and ROM all occupying the same address-space, simultaneously accessible, re-locatable display memory etc. many of which appeared only partially, or not at all on rival platforms.

## Features of the CPC platform

A program in Amstrad BASIC which draws a world map in Mode 1 (320x200px and 4 colours) Printing colour bars on the screen in Mode 0 (16 colours) with BASIC Amstrad CPC colour palette with ink numbers

If a programmer is concerned only with writing in a rich BASIC dialect they have an excellent machine on which to ply their skills and there is no reliance or expectation the programmer will ultimately have to resort to machine code or study the function of the hardware to produce good quality software. However, to fully comprehend the ethos behind Amstrad BASIC and push the machine to its limits, it is necessary to understand, at least superficially, the design approach to the machine as a whole.

Fundamentally, the CPC platform consists of clever hardware with a rich firmware to exploit it; compartmentalised into sub-systems with standardised jump tables to access functionality. Amstrad BASIC was written to expose as much of this platform and firmware as possible to the programmer.

### Firmware jump blocks

At a machine level on the CPC platform, application software need not be concerned with code moving about in the actual firmware e.g. for different versions and re-assembly. In many contemporary machines, re-assemblies of the firmware and subsequent moving of routines can cause major headaches. A notable example was the disastrous 1983 Timex modified ZX Spectrum (the ROM modified as T/S 2000 BASIC). Due to a lack of structure, many system calls moved in the subsequent re-assembly. The resultant firmware was incapable of running many extant ZX Spectrum programs - instantly denying access to a huge software library and alienating users. With the Locomotive approach to system calls, so long as programs use the documented addresses, this is never an issue. Consider the firmware call $BB5A TXT_OUTPUT (put a single character on the screen), it is ubiquitous - but note from below the firmware vectors are different in BASIC 1.0 and BASIC 1.1 ($9400 vs $93FE). As long as programs use the published function address (i.e. $BB5A), software will run on all CPC platforms with no issues.

$BB5A call on basic 1.0

The firmware jumps have changed between versions but the address for TXT_OUTPUT remains $BB5A.

$BB5A call on basic 1.1

### The firmware modules

Kernel
Key Manager
Text VDU
Graphics VDU
Screen Pack
Cassette / AMSDOS (AMStrad Disc Operating System)
Sound Manager
Machine Pack
Maths Pack

Amstrad BASIC leveraged and exposed the platform being written to take full advantage of the machine, bundling up BASIC code into the requisite calls into the firmware,[2] providing specific commands for functionality rather than reliance on generic *FX or PEEK & POKE statements required to access features on competitor platforms.

## BASIC and version differences

Internal version numbers of the BASIC ROM differ from the accepted, published versions discussed here.

Although not unique, the platform was unusual among contemporaries in that it used the ASCII character set rather than its own idiosyncratic form - an arguable strength as it instantly made the CPC platform a more serious offering, somewhat underpinning Amstrad's marketing claims of it being capable of professional business use.

In common with many other dialects, multiple program statements are separated on a single line using the colon `:`.

`WHILE/WEND` is the only loop construct other than `FOR/NEXT`.

Reserved words (functions, commands, statements etc.) are capitalized in a program by virtue of being tokenized. This reduces program size and accelerates execution. Listing a program then decodes the token to its reserved word which are all in upper case in the token table (it was this method which revealed the presence of DEC$ in BASIC 1.0 - see below). When saving a basic program, the fully tokenized form is saved in a binary format. Alternatively, saving with option "A" creates a fully text compatible ascii file e.g. `SAVE "MYPROG",A`

### BASIC 1.0

dec$ tokenization and error betrays reserved word origins

Supplied with the Amstrad CPC464, it was a good release with only a single notable bug, being the `DEC$()` function (it provides `PRINT USING` style output but as a string rather than screen output). No time was available to fix this before the firmware had to go for ROM chip production. Consequently, the function was simply left un-documented and pre-fixed to force a syntax error when encountered. The curious programmer found the word `dec$` capitalised in their code indicating it was a recognised reserved word - inexplicable at the time, until the history of the bug and disassemblies of the BASIC ROM became available.

Exploration of the BASIC 1.0 ROM can find the remnants of the function and its crippled token table entry.

### BASIC 1.1

Supplied with the CPC664/6128, besides fixing DEC$, it introduced (among others) the following additional keywords:

COPYCHR$, CURSOR, FILL, FRAME, GRAPHICS PAPER, GRAPHICS PEN and MASK - continuing in the vein of BASIC exploiting the firmware and any advancements therein.

It also introduced a clumsy but adequate method of trapping disc errors with the `DERR` function. Errors still had to be trapped in the usual way with `ON ERROR GOTO ...` but the single "Broken In" error 32 could now be expanded to provide more detail. Examining DERR gives up to ten further indicators. Values returned are the AMSDOS error number plus 128, e.g. 14 is reported as a DERR value of 142 (14+128). Possible errors included the usual file not found, disk full etc. as well as the more specific "142 - The stream is not in a suitable state" and "149 - Disc changed while files were open". DERR is a function of BASIC 1.1 and so was not available on the FDI1 expanded CPC464, with its combination of AMSDOS and BASIC 1.0. Disc errors on the CPC464 were obtainable but relied on `PEEK`ing into the AMSDOS system area, such program being incompatible with CPC664/6128 due to the AMSDOS variable addresses having moved.

## Variables and functions

Variable names must begin with a letter and can be up to 40 characters long; made up of `A-Z`, the digits `0-9` and the `.` symbol. Names are case-insensitive, but case-as-typed is maintained in program listings.

Three data-types are supported signified by an identifier suffix on the variable name and can be selectively presumed by use of the `DEFINT, DEFREAL` and `DEFSTR` directives:

* Strings with type marker $, e.g.`MyString$`, up to 255 bytes in length
* 2-byte signed integers with type marker %, e.g.`My.Integer%`, in the range -32768 to +32767
* 5-byte real (floating point) with type marker !, e.g.`My99Real!`, in the approximate range +/-10E+38 to +/-4E-39 with nine significant digits. Type real is the default for un-typed variable names. All Floating point mathematics is the result of Amstrad BASIC exposing the MATHS_PACK of the firmware (very complete and entirely usable from machine code).

Unlike some dialects, variable names are unique down to type, e.g. `S%` and `S!` are separate variables.

Dimensioned variables (arrays) have 0 as their lowest element number(s), and can use square brackets around their elements which helps distinguish them from other parentheses in complex expressions in program code. e.g. `A(3)` can be written as `A[3]`.

Named single-line functions are supported and follow the type and name convention of variables but pre-fixed with `FN`. e.g. `FNMy.Func!`

The address of a variable in memory can be determined with the @ directive, e.g. `PRINT @A$`. This replaces the VARPTR() function found in other dialects of BASIC and is mostly used to pass a variable pointer to machine code routines allowing bi-directional data transfer.

Integer and Real variable values are stored in the variable table (see memory map below). String variable contents are stored on the heap. This allows the aggregation of fragmented memory via Garbage Collection. Consequently, for strings, the variable table holds a three byte descriptor made up of the length of the variable and the address in the heap where the actual contents are to be found.

### Two missed opportunities?

BBC Basic uses a clever method for handling some integer variables, which despite claims of its heavy influence on Locomotive BASIC (and by extension Amstrad BASIC), was not replicated in the latter. BBC BASIC has a 54-byte table reserved for the values of the 27 single letter integers `@%, A%, B% ... Z%` so they do not occupy nor require lookup in the variable table - a simple left-shift and addition is all that is required to determine the value of a given variable. This makes access to the subject variables very fast and considering their ubiquitous nature, it is perhaps, surprising this mechanism was not used in Amstrad BASIC.

For strings, the descriptor is three bytes in the variable table, made up of a length descriptor and a further (little-endian) address of the actual payload. Had the value returned by @ been the two byte address in the heap (and the length prefix moved to the heap also) this would have substantially reduced access time by replacing the two address lookups with just one.

Variable table structure for strings.

## Graphics and colour

Handling of graphics and colour was straightforward with commands such as `DRAW, PLOT, INK, PAPER, BORDER` etc.

With Amstrad BASIC V1.1 (CPC664 onwards), the `FILL` command permitted painting complex-shaped, bounded areas of the screen and an eight bit mask could be applied DRAW enabling dotted lines etc.

A table giving the numeric codes for the 27 system colors was printed on the casing of the built-in 3" disk drive on the 664 and later machines.

## Text handling

Text moves through the system using a concept of "streams" numbered 0–9, appropriate commands use the hash `#` symbol to pre-fix the stream number.

Streams 0-7 are text windows. The TEXT_VDU firmware pack allows for the creation of multiple text windows each with their own cursor, dimensions, content, colours etc. An individual window is addressed using its stream number, e.g. `PRINT#3,"Hello World!"`. Omitting the stream number defaults to stream 0 - `PRINT"Hello World!"` being equivalent to `PRINT#0,"Hello World!"`. Text windows are simple screen areas and can overlap but there is no built in provision to preserve the contents of windows "under" others, thus careful attention is required to avoid corruption. Later, machine code routines became available to intercept the firmware calls (by patching the jump block) and preserve the content of a window just before another was drawn over it, restoring it when the new window closed. This gave the much more useful "Windows" look to which we have grown accustomed - being mindful of the times; "pop-ups" were a novel concept in 1984. When using the text windows, screen scrolling relies on software (as only part of the screen content is moved) rather than using the hardware to scroll the entire screen by adjusting the screen-base address in the CRT controller. Two SCREEN_PACK firmware calls are provided for the two forms; $BC4D SCR_HW_ROLL (scrolls the entire screen up or down by eight pixel rows i.e. one character line) - being hardware reliant, the scroll is very fast. $BC50 SCR_SW_ROLL (Scrolls part of the screen up or down by eight pixel lines). The latter can result in a pronounced on-screen "ripple" when scrolling large areas.

Stream 8 is the centronics parallel port. To send a line of text to the printer one could use the command `PRINT#8,"Hello World!"`. Creating a printed listing was simply a matter of LISTing the program to stream 8, e.g. `LIST#8`. This flexible method dispenses with the legacy BASIC commands `LPRINT` and `LLIST`. When later, serial interfaces became available and opened up access to a greater range of printers and other devices, #8 could be diverted by patching $BD2B MC_PRINT_CHAR in the MACHINE_PACK jumpblock.

Stream 9 is the currently open file (either cassette or disc, input or output) and relevant commands are context sensitive; e.g. it is possible to have both input and output files open simultaneously with `PRINT#9` and `INPUT#9` routing text accordingly.

## Advanced features

A stand-out feature among almost every other BASIC of the time is a timer-based software interrupt mechanism at 50 ticks per second using the `EVERY`, `AFTER` and `REMAIN` commands (leveraging the KERNEL for its software interrupts). Four timers were available; 0–3, with associated reducing priority - a BASIC imposition not a platform limitation and allows the programmer to run sections of their BASIC program, asynchronously, after a given delay, repeating if required, e.g. `EVERY 50,0 GOSUB <line>` produces a repeating one-second call with no further work. When answering an EVERY or AFTER, there is an implicit disabling (see DI below) of all lower-priority interrupts which is automatically cleared by the corresponding `RETURN`. As with all Interrupt Service Routines (ISR), such GOSUBs should be kept as short as possible, rather setting a flag for further processing of large chunks of program than trying to complete it inside the ISR.

The interrupt ability requires some method to limit its impact when unwanted. Two commands; `DI` and `EI` Disable and Enable BASIC interrupts respectively. DI should be used sparingly as it will interfere with all BASIC interrupt driven functionality: timers, colour flashing, keyboard scanning, sound output etc., thus program enclosed by DI and EI should be considered to have the same requirements as ISRs to avoid stunted program flow.

Amstrad BASIC granted a relatively high level of control over the sound chip, an AY-3-8912 with 3 tone channels and 1 noise channel and interrupt driven sound generation with comprehensive co-ordination of the three audio channels and associated BASIC commands: `SQ()` (Sound Queue), `ON SQ <channel> GOSUB <line>` etc. The same chip was also used on late-model ZX Spectrums, as well as the Atari ST and MSX computers, but none of those had such a complete built-in `SOUND` command. Many things, from selecting a particular channel or a combination of channels, setting envelopes, volume, pitch, noise, and so on could be done with a single `SOUND` command, with up to 7 parameters. Granted, especially complex and/or low-level techniques could not be done with BASIC due to their requiring more precise or direct access to the hardware, e.g. especially complex music from trackers (including simulated chords using arpeggios, etc.), the playback of digitally sampled sounds as in the game RoboCop for example, and so on.

All disc, tape and file management managed by BASIC is through the firmware and are adequate for simple file management with commands such as `SAVE, LOAD, MERGE, RUN", CAT` etc. During this time, it was common for desktop computers to be "boot to BASIC" and that supplied with most low-cost home computers also acted as a simple operating system, managing files and moving program code and data between the machine and storage medium.

Loading a picture from floppy disk in Amstrad BASIC

Also available is a parametric `LOAD` command, allowing, for example, to load a file containing "raw" picture data into video memory, causing it to be displayed, with a couple of BASIC instructions. Adding a memory address as parameter to the commands `LOAD` or `SAVE` allows easy loading of raw uncompressed 16 KB screen pictures.

## Machine code support and RSXs

Machine code is well supported (but not to the impressive heights of the BBC Micro's, in-line assembler). There is an easy method of allocating "safe" memory (see below) and once loaded either from disc or cassette or `POKE`d in, Z80 machine code can be executed with `CALL <addr>`. CALL supports a method to pass parameters to the machine code using BASIC variables (including strings) using the form `CALL <addr>,Q,@X$`. Integer variables and integer immediates can be passed directly as their value (ByVAL). All variables, but specifically strings can be passed using the `@` directive, which points to the address of the variable descriptor (ByREF). Thus, transfer of data in both directions between a BASIC program and machine code is trivial.

Another method, leveraging the firmware, allows for named sections of machine code using a feature known as Resident System eXtensions (RSX). Although not a purely BASIC feature, Amstrad BASIC embraces this mechanism of RSXs and the names can be used in the BASIC program as if they were reserved keywords - each being prefixed with the bar `|` symbol, the remaining syntax being identical to CALL. e.g. `|MYRSX,Q,@X$` (note a comma is required between the RSX name and any arguments). The code for the RSXs has a very specific header structure - the RSX names, their entry points and 4 bytes of scratchpad RAM for the firmware to link in and out of the list. A call is made using the KERNEL routine $BCD1 KL_LOG_EXT to initialise the names and they are then available to use throughout the system (by finding each named section using $BCD4 KL_FIND_COMMAND - BASIC does this for | commands). A major advantage of RSXs is not needing to know the address of a piece of machine code, in whatever bank (CALL can only access the main 64KB address map, however configured) - the KERNEL returns the parameters necessary to execute the code in question no matter where it resides, in the entire memory map and in all ROM/RAM banks (see "bank switching" below). Code can simply call sideways by searching for the RSX name and from the link structure, the firmware immediately knows the required ROM/RAM bank configuration. `KL_SIDE_CALL`, `KL_SIDE_PCHL` etc. is used to run the machine code. Thus all memory is usable for machine code program. Use of RSXs ensures that machine code in sideways ROMs is fully integrated with BASIC and the disc commands `|DIR, |A, |TAPEIN, |ERA` etc. all reside in ROM and are used throughout BASIC program code. On the CPC464, disc commands were only added when the FDI1 (floppy disc interface, with its sideways ROM) is plugged in the rear expansion port.

In UK CPC circles at that time, it was popular to pun words that began with "bar" and name RSXs accordingly, e.g. |BQ, |BARASTREISAND, |STARD etc.

## Memory allocation and management

Generally speaking, BASIC programmers do not have to concern themselves too much with the inner workings of their chosen platform to get decent results. Should a programmer wish to ignore them and stick only to BASIC, they are well catered-for with a speedy, rich dialect. For those who want to go beyond and want more control, they are likewise accommodated.

In many contemporary systems, allocating a block of memory seems an after-thought with no "proper" method of achieving it. Innovative methods were adopted by programmers which resulted in some, often, highly cryptic and fiddly methods, such as creating REM statements with the required length and then POKEing the data into known addresses in the BASIC program line - the command `LET L=USR 16514` was famous in ZX81 circles, 16514 being the address of the first byte after the first token on the first program line (usually a REM statement on line 1) the only area of memory guaranteed not to move around or be corrupted with added program lines, garbage collect etc.

Amstrad BASIC program space occupies RAM from $170 extending to somewhere around $A6F0 (varies with BASIC version and other considerations), just under the BASIC system area, AMSDOS area and the high jump blocks - a little over 41KB. Numeric variables and functions etc. are located immediately above the program with the remaining, free memory in between termed "the heap". The contents of string variables are stored in the heap near the very top, with just the string descriptors being stored in similar fashion to numerics in the variable table - just above the program (see Variables and functions above). BASIC program code grew up and strings grew down towards each other in RAM, gradually consuming the heap in between. Amstrad BASIC has a garbage collector which de-fragments the heap to maximise usable memory - as with most computer languages, as strings are created then sliced/deleted, chunks of un-used memory occur between used parts and the heap can become "porous". Notably the BBC Micro did not have garbage collect and manipulation of strings could result in "out of memory" errors simply because a requested block did not exist in one chunk. In common with other dialects, Amstrad BASIC provides the `FRE()` function to return the amount of free heap. The function has two forms: `FRE(numeric)`, e.g. `PRINT FRE(0)`, returns the size, in bytes, of the largest single block in the heap. The second form, `FRE("")`, forces a garbage collect and so, returns a true count of free heap. Used areas (mainly strings and temporary structures) are aggregated at the top of the heap with no gaps - data is moved and pointers updated, leaving available heap as a single chunk of memory extending down towards the program and variables. This latter form can take some time to run on badly fragmented systems. Should an "Out of memory" error be imminent due to no free heap, Amstrad BASIC performs a garbage collection immediately prior to stopping the program in an attempt to rescue the situation. Subsequently, it was not necessary for the programmer to concern themselves overly with heap management and FRE() is more informational than essential.

Amstrad BASIC provides the function, HIMEM, which returns the last address used by BASIC i.e. the very last address before the system areas. The MEMORY command can be used to adjust this address and through a combination of the two, space can be reserved easily and controllably - a primitive form of `malloc()`. For example, suppose a block of 1KB was required, space could be reserved (with full consent/awareness of BASIC) using `MEMORY HIMEM-1024` \- adjusting down the maximum extent of BASIC memory use. Machine code, say, could then be safely loaded into and called at `HIMEM+1` (or elsewhere in that 1K), safe from other processes and accidental relocation/corruption.

The simplified default CPC memory map as it appears to BASIC.

The CPC range makes provision, through the SCREEN_PACK, for User Defined Graphics (UDG) whereby the 8 × 8 pixel matrix for a character can be redefined allowing for the creation of special characters. By default, the top 16 characters (128 bytes) are "soft" and if that is sufficient, no further adjustment is required. Following on the ethos of exposing the platform capabilities in BASIC, it passes forward this functionality and the memory for UDG is allocated from the heap (i.e. the more characters, the lower HIMEM). More characters (and thus more RAM) can be allocated with the `SYMBOL AFTER <char>` command - where char represents the character code from which UDG is available. e.g. `SYMBOL AFTER 32` allows the entire printable ASCII character set to be redefined, with the corresponding reduction in available program space (1784 bytes). The firmware copies the default character matrices from ROM into the newly allocated space, thus defining the character matrix was not essential for clarity. If UDG are not required, memory can be returned to BASIC (resulting in fixed character matrices) with the command `SYMBOL AFTER 256`.

## Memory bank switching and a notable omission

Although as a BASIC implementation, Amstrad BASIC is fairly complete and goes to great pains to support the CPC platform, one notable omission in all versions is native access to the memory bank switching mechanism used to expand the Z80 memory space; re-using address ranges by overlaying sections of physical ROM or RAM.

Through an arrangement of the custom circuitry, switching pages into one of the four 16KB pages in the Z80 memory map ($0xxx, $4xxx, $8xxx, $Cxxx) is possible. For instance, the top page ($C000) is (usually) occupied by both the video RAM, the BASIC ROM and (on disc equipped machines) the AMSDOS ROM with the hardware and firmware providing the necessary control of access. The firmware ROM is bank-switched to the lower 16KB, extra RAM (that beyond the Z80 64KB e.g. the additional 64KB of the CPC6128) and sideways ROMs (containing user machine code or 3rd party software) are mapped to the top page ($C000) - RAM can actually be mapped to any bank as evidenced by the 61KB TPA (Transient Program Area - free program memory when running CP/M+.). Clearly the OS requirements are more than 3KB.

CP/M+ sign-on banner showing 61K available to programs

The CRT controller generally maps to the 16KB video RAM at $C000 in the main Z80 address space with the hardware ensuring the video picture is not interrupted when other banks were switched into the same page. As an aside; To facilitate clean CPU and CRTC access to the same memory, the hardware is required to match bus access time to a constant number of clock cycles and any instruction will be "stretched" (utilising the WAIT signal on the Z80 control bus) to the next 4th cycle, so; any instruction running on the Z80 will always be a multiple of 4 T-states, i.e 4, 8, 12 etc. despite published timings for the Z80. This resulted in very slightly slower code performance than the fastest contemporary - the BBC Micro. All CPC models supported this fairly advanced (for the time) bank-switching to increase the potential memory storage - even an un-expanded CPC464 uses fully 96KB of ROM and RAM mapped into the Z80 64KB address space.

Memory writes are always applied only to RAM in the main 64KB address space, regardless of switched state, e.g. if the lower ROM ($0-$3FFF) is switched into the memory map, `POKE &800,0` will write into RAM regardless. Several configurations of where the switched banks occur in the memory map are supported by the KERNEL.

The CPC464/664 hardware can address up to 256KB including up to eight 16KB sideways ROMs, controlled by the large custom chip. One position is used by the BASIC ROM and both the CPC664 and CPC464 expanded with the FDI1, use a further slot for the AMSDOS ROM - leaving six slots. The CPC6128 hardware permits bank switching up to 4MB with increased space for 16 (32 with a PCB hack) 16KB sideways ROMs. Again, two positions are occupied with BASIC and AMSDOS leaving 14 available for user or 3rd parties. The KERNEL provides several methods of accessing banked memory; some involve a pseudo 24bit address via a vector or extending the HL register pair using the C register. For ROMs only the high or low ROM switching is controlled by the top two bits of a 16-bit address. Still others can retrieve data from a bank as if it were in the mainstream Z80 address map or directly from the main 64KB of RAM regardless of the state of the banks. Kernel routines to access banked memory include KL_FAR_CALL, KL_FAR_JMP, KL_RAM_LAM among others.

Prior to "calling sideways", i.e. switching in a bank and jumping to execute machine code at an address there, the kernel assembles structures on the Z80 stack to ensure the safe capture of inbound `RET`urns from code in banked memory - restoring the state of the banks and ensuring code execution continues without issue. It is quite normal to have calls between banked ROMs, indeed this happens seamlessly every time BASIC uses AMSDOS (disc commands) as both ROMs occupy the same physical address space. Due to the heavily interrupt driven nature of the CPC range, it is wise to leave the Z80 Stack Pointer (SP) register alone as local use can result in crashes should it be diverted and an interrupt occur (it is quite common to set the stack to a local block so it can simply be abandoned after a routine has run). Such interrupts are likely to rely on the Kernel's structures on the stack.

Despite BASIC not providing support for this kernel functionality, use of banked memory in a BASIC program was certainly possible but required the use of machine code routines to do the switch and take advantage of the result. Banked memory could not be used for BASIC program code.

On the bundled CP/M 2.2 and CP/M+ (CPC6128) discs was a two-part program to add primitive-but-adequate bank-switching commands to BASIC. When run, BANKMAN.BAS reserves 1317 bytes of RAM into which; it loads BANKMAN.BIN, makes a call to that binary and then deletes itself. The latter file contains machine code to initialise a set of RSXs to enable RAM bank switching from BASIC programs. Functionality includes saving and loading screens from banks, copying between banks etc. It was not generally considered practical though as it is necessary to include both BANKMAN files with your own software products and run them at the command prompt before your own program can take advantage of bank switching RAM. To add further hindrance, although not copyrighted, BANKMAN.BAS is saved in protected mode (`SAVE"<my_prog>",p`) and so is not listable - meaning that you cannot easily determine the method to load the RSXs and so use them in your own programs - to eliminate the two-stage start up.

Besides using banked memory to store screen images and rapidly switch between them, some applications implement "RAM Discs" but these are not supported under the cassette/AMSDOS firmware, being quite proprietary.

## Contemporary rivals

This section possibly contains original research. Please improve it by verifying the claims made and adding inline citations. Statements consisting only of original research should be removed. (July 2019) (Learn how and when to remove this template message)

|

Unlike the Commodore 64's built in BASIC (Commodore BASIC), which had no dedicated commands for graphics or sound, Amstrad BASIC allowed doing pretty much anything that was within the standard capabilities of the machine. This was not unimportant, as some other machines of the era required programmers to use assembler in order to access the full sound and graphics capabilities of their system. MSX, Sinclair Spectrum and some others offered a similar, more or less complete command set for their sound and graphics capabilities. The only things going clearly beyond BASIC capabilities were the overscan modes used in games and demos, 27-color graphics modes, digital sound playback, and smooth scrolling.

Unlike Sinclair BASIC or Commodore 64 BASIC, which had various keyboard command shortcuts or specialized keys for choosing symbols or colors, Amstrad BASIC keywords were typed in full and the interpreter parsed, recognized and tokenised them. However, there were abbreviations like "`?`" for "`PRINT`" and a few shortcuts. Programs could be saved onto Compact Cassette or floppy disk and retrieved as binary or ASCII files.

## References

1. ↑ Smith, Tony (12 February 2014). "You're NOT fired: The story of Amstrad's amazing CPC 464". The Register. https://www.theregister.co.uk/2014/02/12/archaeologic_amstrad_cpc_464/.
2. ↑ "You're NOT fired: The story of Amstrad's amazing CPC 464 • the Register". https://www.theregister.com/Print/2014/02/12/archaeologic_amstrad_cpc_464/.

## External links

* Locomotive BASIC reference
* Command reference with code examples
* Command reference (incomplete)
* Additional code examples at Rosetta Code

* v
* t
* e

Dialects of the BASIC programming language (list)

Classic|

* Altair BASIC
* Applesoft BASIC
* Atari BASIC
* Atari 2600 BASIC
* Atari Microsoft BASIC
* Atari ST BASIC
* BASIC-PLUS
* BASICA
* BASIC A+
* BASIC XE
* BASIC XL
* Casio BASIC
* CBASIC
* Chipmunk Basic
* Color BASIC
* Commodore BASIC
* Extended Color BASIC
* Dartmouth BASIC
* Disk Extended Color BASIC
* Family BASIC
* GFA BASIC
* GW-BASIC
* HP BASIC for OpenVMS
* HP Time-Shared BASIC
* IBM BASIC
* Integer BASIC
* Locomotive BASIC
* Mallard BASIC
* Microsoft BASIC
* MSX BASIC
* Pure Basic
* Rocky Mountain BASIC
* S'-BASIC (Tandy, Casio, Sharp Pocket Computers)
* SCELBAL
* ScriptBasic
* Sinclair BASIC
* Southampton BASIC System
* STOS BASIC
* TI BASIC (TI 99/4A)
* TI-BASIC (calculators)
* TI Extended BASIC (aka XBasic)
* Tiny BASIC
* Turbo-Basic XL
* Tymshare SUPER BASIC
* UBASIC
* Vilnius BASIC
* XBasic

Procedure-oriented|

* AmigaBASIC
* AMOS BASIC
* ASIC
* BBC BASIC
* Beta BASIC
* DarkBASIC
* FreeBASIC
* FutureBASIC
* GFA BASIC
* GLBasic
* Liberty BASIC
* Microsoft Small Basic
* PowerBASIC
* PureBasic
* QBasic
* QB64
* QuickBASIC
* SmallBASIC
* SuperBASIC
* ThinBasic
* True BASIC
* Turbo Basic
* XBasic
* Xblite
* Basic4ppc
* Visual Test
* B4J

With object extensions|

* AutoIt
* Basic For Qt (KBasic)
* BlitzMax
* Chipmunk Basic
* FreeBASIC
* Gambas
* GLBasic
* HBasic
* OpenOffice Basic
* PowerBASIC
* ProvideX
* RapidQ
* REALbasic
* Run BASIC
* Visual Basic
* Visual Basic .NET
* Xojo

For mobile devices|

* B4X
* Basic4android (B4A)
* Basic4ppc
* GLBasic
* NS Basic
* Basic4ios (B4i)

Microsoft|

* Microsoft BASIC
* MBASIC
* IBM BASIC/BASICA
* GW-BASIC
* QuickBASIC
* QBasic
* VBScript
* Visual Basic
* VBA
* Visual Basic .NET
* Embedded Visual Basic
* VB 5 for Microsoft Excel 5.0
* VSTO
* VSTA
* WordBASIC
* TRS-80 Basics (Level I, Level II, Level III)
* Microsoft Small Basic

Third-party VB-like|

* B4X
* Basic For Qt
* Gambas
* HBasic
* Hummingbird Basic
* LotusScript
* WinWrapBasic
* Xojo

0.00

(0 votes)

Original source: https://en.wikipedia.org/wiki/Locomotive BASIC. Read more

|

Retrieved from "https://handwiki.org/wiki/index.php?title=Locomotive_BASIC&oldid=4347339"
*[v]: View this template
*[t]: Discuss this template
*[e]: Edit this template