├── .github ├── FUNDING.yml └── workflows │ └── docs.yml ├── .gitignore ├── README.md ├── docs ├── BBC-BASIC-for-Agon.md ├── External-Documentation.md ├── FAQ.md ├── GPIO.md ├── MOS.md ├── Projects.md ├── Theory-of-operation.md ├── Third-Party-Projects.md ├── Updating-Firmware.md ├── VDP.md ├── assets │ ├── favicon.png │ └── logo.png ├── images │ ├── agon_gpio_pinouts.png │ ├── hexload.png │ ├── io_origins.png │ ├── io_uext.png │ ├── iopinsAL1.png │ ├── iopinsAL2.png │ ├── iopinsC8.png │ └── jumpers.webp ├── index.md ├── mos │ ├── API.md │ ├── Argument-Substitution.md │ ├── C-Functions.md │ ├── Executables.md │ ├── Modules.md │ ├── Star-Commands.md │ └── System-Variables.md ├── stylesheets │ └── extra.css └── vdp │ ├── Bitmaps-API.md │ ├── Buffered-Commands-API.md │ ├── Context-Management-API.md │ ├── Copper-API.md │ ├── Enhanced-Audio-API.md │ ├── Font-API.md │ ├── PLOT-Commands.md │ ├── Screen-Modes.md │ ├── System-Commands.md │ ├── VDP-Variables.md │ └── VDU-Commands.md └── mkdocs.yml /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: stevesims 4 | patreon: SteveSims 5 | ko_fi: breakintoprogram 6 | -------------------------------------------------------------------------------- /.github/workflows/docs.yml: -------------------------------------------------------------------------------- 1 | name: docs 2 | on: 3 | push: 4 | branches: 5 | - main 6 | permissions: 7 | contents: write 8 | jobs: 9 | deploy: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v3 13 | - uses: actions/setup-python@v4 14 | with: 15 | python-version: 3.x 16 | - uses: actions/cache@v4 17 | with: 18 | key: ${{ github.ref }} 19 | path: .cache 20 | - run: pip install mkdocs-material 21 | - run: mkdocs gh-deploy --strict --force 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | venv 2 | site 3 | .DS_Store 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Welcome to the community Agon Platform documentation 2 | 3 | This is the community-driven documentation for the Agon Platform, covering the Agon Light, Olimex Agon Light 2, and the Agon Console8 hobbyist computers. It is intended to be a comprehensive guide to the Agon Platform, including Agon MOS and VDP firmware, and the hardware and software that it supports. It is intended to provide a guide to all of the features of the Agon platform with guidance on how to program for it, with information on the various features provided by different versions of the firmware. 4 | 5 | This site is intended to supercede the original "official Quark documentation", and to provide a more comprehensive and up-to-date guide to the Agon Platform. It is intended to be a living document, and to be updated as new features are added to the platform. 6 | 7 | The original documentation for Quark firmware can be found [here](https://github.com/breakintoprogram/agon-docs/wiki). This community documentation was started because GitHub's wiki system does not allow easy contributions by users, and the original documentation contains some errors and omissions. We don't use the wiki here, but just markdown files which are also automatically generated into a [website](https://agonplatform.github.io/agon-docs/). 8 | -------------------------------------------------------------------------------- /docs/BBC-BASIC-for-Agon.md: -------------------------------------------------------------------------------- 1 | # What is BBC BASIC for Agon? 2 | 3 | The original version of BBC BASIC was written by Sophie Wilson at Acorn in 1981 for the BBC Micro range of computers, and was designed to support the UK Computer Literacy Project. R.T.Russell was involved in the specification of BBC Basic, and wrote his own Z80 version that was subsequently ported to a number of Z80 based machines. [I highly recommend reading his account of this on his website for more details](http://www.bbcbasic.co.uk/bbcbasic/history.html). 4 | 5 | As an aside, R.T.Russell still supports BBC Basic, and has ported it for a number of modern platforms, including Android, Windows, and SDL, which are [available from his website here](https://www.bbcbasic.co.uk/index.html). 6 | 7 | BBC BASIC for Agon is a port of his BBC BASIC for Z80, which is now open source, with a number of modifications to make it run on Agon. 8 | 9 | Please note that the information in this file is currently out of date. The original version of BASIC described here is based on Dean Belfield's Agon port of R.T.Russell's original Z80 BBC BASIC. This version is broadly the same as Acorn's BBC BASIC version 4 for the BBC Master series of computers, but includes an inbuilt Z80 Assembler instead of 6502. Since that time, Dean Belfield made a new version based on that work which makes use of the Agon's eZ80 processor, allowing access to all 512KB of RAM, compared to the 64KB of the original Z80 version, and extending the Assembler to support the new eZ80 opcodes. Richard Russell also revisited his original Z80 version of BASIC and extended it to support most features of Acorn's BBC BASIC V, and Dean Belfield has since ported this to the Agon as well. The BASIC V for Agon currently only supports Z80 mode. 10 | 11 | # Implementation on the Agon Light 12 | 13 | BBC BASIC for Z80 runs in Z80 mode, that is within a 64K segment. The interpreter takes around 16K of RAM, leaving around 48K available for user programs and data. 14 | 15 | If you are not familiar with the BASIC programming language, or need a refresher on BBC BASIC, please refer to the [official BBC BASIC for Agon documentation here](https://oldpatientsea.github.io/agon-bbc-basic-manual/0.1/index.html). 16 | 17 | (Please note that this documentation is also slightly outdated and contains some inaccuracies. For example it has incorrect information about PLOT commands. At some point we may merge the Agon BBC BASIC documentation in with the community documentation site.) 18 | 19 | To run, load into memory and run as follows from the MOS command prompt: 20 | 21 | ``` 22 | LOAD bbcbasic.bin 23 | RUN 24 | ``` 25 | 26 | It is possible to automatically `CHAIN` (load and run) a BBC BASIC program by passing the filename as a parameter: 27 | ``` 28 | LOAD bbcbasic.bin 29 | RUN . /path/to/file.bas 30 | ``` 31 | 32 | Note that passing a . as the first parameter of RUN is informing MOS to use the default value there (&40000) 33 | 34 | BBC BASIC needs a full 64K segment, so cannot be run from the MOS folder as a star command. 35 | 36 | 37 | If you are running MOS 2.2.0 you can load and run BBC BASIC from the MOS command prompt using: 38 | 39 | ``` 40 | bbcbasic 41 | ``` 42 | 43 | This assumes that your copy of BASIC is called `bbcbasic.bin` and is either in the root of the SD card, or in the `bin` folder. 44 | 45 | Automatically "chaining" a BBC BASIC program can be done by passing the filename as a parameter: 46 | 47 | ``` 48 | bbcbasic /path/to/file.bas 49 | ``` 50 | 51 | 52 | # Summary of Agon Light Specific Changes 53 | 54 | ## Star Commands 55 | 56 | The following * commands are supported 57 | 58 | ### BYE 59 | 60 | Syntax: `*BYE` 61 | 62 | Exit BASIC and return to MOS. 63 | 64 | ### EDIT 65 | 66 | Syntax: `*EDIT linenum` 67 | 68 | Pull a line into the editor for editing. 69 | 70 | ### FX 71 | 72 | Syntax: `*FX osbyte, params` 73 | 74 | Execute an OSBYTE command. 75 | 76 | The only OSBYTE commands supported at the moment are: 77 | 78 | - 19: Wait for vertical blank retrace 79 | 80 | And from MOS 1.03 or above 81 | 82 | - 11: Set keyboard repeat delay in ms (250, 500, 750 or 1000) 83 | - 12: Set keyboard repeat rate ins ms (between 33 and 500ms) 84 | - 118: Set keyboard LED (Bit 0: Scroll Lock, Bit 1: Caps Lock, Bit 2: Num Lock) - does not currently change status, just the LED 85 | 86 | ### VERSION 87 | 88 | Syntax: `*VERSION` 89 | 90 | Display the current version of BBC BASIC 91 | 92 | ### MOS commands 93 | 94 | In addition, any of the MOS commands can be called by prefixing them with a * 95 | 96 | See the MOS documentation for more details 97 | 98 | ## BASIC 99 | 100 | The following statements are not currently implemented: 101 | 102 | - ENVELOPE 103 | - ADVAL 104 | 105 | The following statements differ from the BBC Basic standard: 106 | 107 | ### REM 108 | 109 | REM does not tokenise any statements within comments. This is to bring it inline with string literals for internationalisation. 110 | 111 | ### LOAD 112 | ### SAVE 113 | 114 | The following file extensions are supported: 115 | 116 | - `.BBC`: LOAD and SAVE in BBC BASIC for Z80 tokenised format 117 | - `.BAS`: LOAD and SAVE in plain text format (also `.TXT` and `.ASC`) 118 | 119 | If a file extension is omitted, ".BBC" is assumed. 120 | 121 | ### MODE 122 | 123 | The modes differ from those on the BBC series of microcomputers. The full list can be found [here](vdp/Screen-Modes.md) in the VDP documentation. 124 | 125 | ### COLOUR 126 | 127 | Syntax: `COLOUR c` 128 | 129 | Change the the current text output colour 130 | 131 | - If c is between 0 and 63, the foreground text colour will be set 132 | - If c is between 128 and 191, the background text colour will be set 133 | 134 | Syntax: `COLOUR l,p` 135 | 136 | Set the logical colour l to the physical colour p 137 | 138 | Syntax: `COLOUR l,r,g,b` 139 | 140 | ### GCOL 141 | 142 | Syntax: `GCOL mode,c` 143 | 144 | Set the graphics colour `c`, and the "mode" of graphics paint operations. 145 | 146 | Colour values are interpreted as per the COLOUR command, i.e. values below 128 will set the foreground colour, and values above 128 set the background colour. 147 | 148 | Versions of the VDP earlier than 1.04 only supported mode 0, with all painting operations just setting on-screen pixels. 149 | 150 | VDP 1.04 introduced _partial_ support for mode 4, which inverts the pixel. Mode 4 would only apply to straight line drawing operations. The mode would affect all applicable plot operations. 151 | 152 | As of Console8 VDP 2.6.0, all 8 of the basic modes are supported for all currently supported plot operations. Separate plot modes are now tracked for foreground and background colours, and the mode is applied to the graphics operation. 153 | 154 | The full array of available modes is as follows: 155 | 156 | | Mode | Effect | 157 | | ---- | ------ | 158 | | 0 | Set on-screen pixel to target colour value | 159 | | 1 | OR value with the on-screen pixel | 160 | | 2 | AND value with the on-screen pixel | 161 | | 3 | EOR value with the on-screen pixel | 162 | | 4 | Invert the on-screen pixel | 163 | | 5 | No operation | 164 | | 6 | AND the inverse of the specified colour with the on-screen pixel | 165 | | 7 | OR the inverse of the specified colour with the on-screen pixel 166 | 167 | ### POINT 168 | 169 | Syntax: `POINT(x,y)` 170 | 171 | This returns the physical colour index of the colour at pixel position (x, y) 172 | 173 | ### PLOT 174 | 175 | Syntax: `PLOT mode,x,y` 176 | 177 | For information on the various PLOT modes, please see the [VDP PLOT command documentation](vdp/PLOT-Commands.md) 178 | 179 | ### GET$ 180 | 181 | Syntax: `GET$(x,y)` 182 | 183 | Returns the ASCII character at position x,y 184 | 185 | ### GET 186 | 187 | Syntax: `GET(x,y)` (from BBC BASIC 1.05) 188 | 189 | As GET$, but returns the ASCII code of the character at position x, y 190 | 191 | Syntax: `GET(p)` 192 | 193 | Read and return the value of Z80 port p 194 | 195 | ### SOUND 196 | 197 | Syntax: `SOUND channel,volume,pitch,duration` 198 | 199 | Play a sound through the Agon Light buzzer and audio output jack 200 | 201 | - `Channel`: 0 to 2 202 | - `Volume`: 0 (off) to -15 (full volume) 203 | - `Pitch`: 0 to 255 204 | - `Duration`: -1 to 254 (duration in 20ths of a second, -1 = play forever) 205 | 206 | ### TIME$ 207 | 208 | Access the ESP32 RTC data 209 | 210 | Example: 211 | 212 | ``` 213 | 10 REM CLOCK 214 | 20 : 215 | 30 CLS 216 | 40 PRINT TAB(2,2); TIME$ 217 | 50 GOTO 40 218 | ``` 219 | 220 | NB: This is a virtual string variable; at the moment only getting the time works. Setting is not yet implemented. 221 | 222 | ### VDU 223 | 224 | The VDU commands on the Agon Light will be familiar to those who have coded on Acorn machines. Please read the [[VDP]] documentation for details on what VDU commands are supported. 225 | 226 | ## Inline Assembler 227 | 228 | BBC BASIC for Z80, like its 6502 counterpart, includes an inline assembler. For instructions on usage, please refer to the [original documentation](https://www.bbcbasic.co.uk/bbcbasic/mancpm/bbc3.html#introduction). 229 | 230 | In addition to the standard set of Z80 instructions, the following eZ80 instructions have been added 231 | 232 | - `MLT` 233 | 234 | The assembler will only compile 8-bit Z80 code and there are currently no plans for extending the instruction set much further in this version. 235 | 236 | ## Integration with MOS 237 | 238 | For the most part, the MOS is transparent to BASIC; most of the operations via the MOS and VDP are accessed via normal BBC BASIC statements, with the following exceptions: 239 | 240 | ### Accessing the MOS SysVars 241 | 242 | MOS has a small area of memory for system state variables (sysvars) which lives in an area of RAM outside of the 64K segment in which BBC BASIC runs. To access these, you will need to do an OSBYTE call 243 | 244 | Example: Print the least significant byte of the internal clock counter 245 | ``` 246 | 10 L%=&00 : REM The sysvar to fetch 247 | 20 A%=&A0 : REM The OSBYTE number 248 | 30 PRINT USR(&FFF4) 249 | ``` 250 | 251 | Documentation for the full list of sysvars can be found in the [MOS API documentation](mos/API.md#sysvars). 252 | 253 | ### Running star commands with variables 254 | 255 | The star command parser does not use the same evaluator as BBC BASIC, so whilst commands can be run in BASIC, variable names are treated as literals. 256 | 257 | Example: This will not work 258 | ``` 259 | 10 INPUT "Filename";f$ 260 | 20 INPUT "Load Address";addr% 261 | 30 *LOAD f$ addr% 262 | ``` 263 | 264 | To do this correctly, you must call the star command indirectly using the OSCLI command 265 | 266 | Example: This will work 267 | ``` 268 | 30 OSCLI("LOAD " + f$ + " " + STR$(addr%)) 269 | ``` -------------------------------------------------------------------------------- /docs/External-Documentation.md: -------------------------------------------------------------------------------- 1 | # Agon 2 | - [Byte Attic: The Agon Light](https://www.thebyteattic.com/p/agon.html) 3 | - [Break Into Program: Agon](http://www.breakintoprogram.co.uk/hardware/computers/agon) 4 | 5 | # BBC BASIC 6 | - [BBC BASIC for Agon Manual](https://oldpatientsea.github.io/agon-bbc-basic-manual/0.1/index.html) 7 | 8 | # Libraries 9 | - [FabGL](http://www.fabglib.org/index.html) 10 | - [FatFS](http://elm-chan.org/fsw/ff/00index_e.html) 11 | 12 | # [Zilog](https://www.zilog.com) 13 | - eZ80F92 Documentation 14 | - [eZ80 CPU](http://www.zilog.com/docs/um0077.pdf) 15 | - [Specification](https://www.zilog.com/docs/ez80/ps0130.pdf) 16 | - [Calling C Functions from Assembly and Vice Versa](https://www.zilog.com/docs/appnotes/an0333.pdf) 17 | - [ZDSII User Manual](http://www.zilog.com/docs/devtools/um0144.pdf) 18 | -------------------------------------------------------------------------------- /docs/FAQ.md: -------------------------------------------------------------------------------- 1 | --- 2 | hide: 3 | # Hide the TOC on the right hand side as we are overriding it on this page only 4 | - toc 5 | --- 6 | # Agon Frequently Asked Questions 7 | 8 | The following questions (and answers) on using the Agon platform are below: 9 | 10 | [TOC] 11 | 12 | ## Are these community documents available offline or in a different format? 13 | 14 | No, and there are no immediate plans on doing this to reduce the amount of time spent doing documentation. 15 | 16 | This documentation however is all [open source](https://github.com/AgonPlatform/agon-docs), and written in [Markdown](https://www.markdownguide.org) format. Pull requests suggesting changes to the documentation are always welcome. 17 | 18 | ## Is the Agon open source? 19 | 20 | Yes. All of the firmware for the Agon platform is open source, for both [MOS](https://github.com/AgonPlatform/agon-mos) and the [VDP](https://github.com/AgonPlatform/agon-mos), and also including the various versions of BBC BASIC for the Agon ([BASIC 4 for Z80](https://github.com/breakintoprogram/agon-bbc-basic), [BASIC 4 for eZ80](https://github.com/breakintoprogram/agon-bbc-basic-adl) and [BASIC V for Z80](https://github.com/breakintoprogram/agon-bbc-basic-v)). 21 | 22 | [Bernado Kastrup](https://www.thebyteattic.com), the original hardware designer of the Agon Light, released the full schematics for the [Agon light](https://github.com/TheByteAttic/AgonLight) and the [Agon light ORIGINS edition](https://github.com/TheByteAttic/AgonORIGINS) as open source. He also designed Heber Ltd.'s [Agon Console8](https://heber.co.uk/agon-console8/), available from the Heber and Retro Collective [shop](https://shop.heber.co.uk/agon-console8/). 23 | 24 | The [Olimex AgonLight2](https://www.olimex.com/Products/Retro-Computers/AgonLight2/open-source-hardware) is based on the original Agon Light design, which is also an open source design. 25 | 26 | ## What else do I need to buy? 27 | 28 | Okay, so you've ordered your Agon Light, and are wondering what else you will need to purchase. 29 | 30 | As a minimum, you also need the following extra hardware: 31 | 32 | - A PS/2 compatible keyboard 33 | - A micro USB card 34 | 35 | !!! note 36 | 37 | - The original Agon Light requires a PS/2 keyboard, or a USB keyboard that supports the PS/2 protocol with a USB to PS/2 adaptor. 38 | - The Agon Light 2 and Agon Console8 require a USB keyboard that supports the PS/2 protocol, or a PS/2 keyboard with a PS/2 to USB adaptor. 39 | 40 | ## Does Agon support CP/M? 41 | 42 | Officially it is not designed to run CP/M out of the box. There are however third-party developers who have ported CP/M to the platform, and the official build supports this. 43 | 44 | There is also available a [CP/M compatibility layer](https://github.com/nihirash/zinc), allowing some CP/M software to run directly from the MOS command line. 45 | 46 | ## Is there a template available for the SD card, to get me started quickly? 47 | 48 | Check out the Popup [MOS repository](https://github.com/tomm/popup-mos); click the green 'Code' icon and select 'Download ZIP' from the dropdown menu. Unzip the file and copy over everything from the 'popup-os-main' folder to an empty SD card. The card should have folders like demos/docs/games/mos/utils in the root of the card 49 | 50 | Another great distribution is [Agon Mite](https://www.agonmite.com) which aims to have a monthly release cycle. 51 | 52 | These repositories are a volunteer effort, periodically collecting the latest versions of software out there. If you need a more recent version of any package, because sometimes development goes pretty fast; please download it individually to your SD card. 53 | 54 | ## What kind of SD card should I use? 55 | 56 | Any class-10 micro SD card of a decent quality will do fine 57 | 58 | ## What size SD card should I buy? 59 | 60 | You should aim for a maximum card size of 32GB. Larger cards are supported (using FAT32), but you may run into issues partitioning and formatting them. 61 | 62 | ## How should I format the SD card initially? 63 | 64 | Format the card using a FAT32 layout 65 | 66 | ## Will my Agon boot directly into BBC BASIC or will I have to download the language onto an SD card? 67 | 68 | Most distributions contain both the BBC BASIC binary (bbcbasic.bin), and an autoexec.txt file at top level of SD card. The latter contains commands for auto loading BBC Basic. If you'd like to disable auto loading BBC BASIC; remove it, or change the content to suit your own requirements. 69 | 70 | ## How should I power the Agon? 71 | 72 | All Agon platforms can be powered using a USB cable to your PC, or a USB wall-charger. The load is relatively light, usually below 200mA with a connected keyboard. Which USB cable you need, depends on the variant of Agon you buy. For example, the Olimex AgonLight2 is powered from a USB-C interface, while the Agon Console8 can be powered using a USB-B interface. The latter can also be powered with 5v DC jack connector. 73 | 74 | ## How can I update the Agon? 75 | 76 | It really depends on the current firmware versions on your Agon. The Agon contains firmware for both the OS (MOS) and graphics unit (VDP). 77 | 78 | Full guidance on updating your Agon can be found in [this detailed guide](./Updating-Firmware.md). 79 | 80 | ## Where can I find the latest Agon firmware(s) to download? 81 | 82 | The latest Agon platform firmware releases for MOS and the VDP can be found here: 83 | 84 | - [MOS firmware](https://github.com/AgonPlatform/agon-mos/releases/latest) 85 | - [VDP firmware](https://github.com/AgonPlatform/agon-vdp/releases/latest) 86 | 87 | ## Quark, Console8, or Agon Platform firmware?? 88 | 89 | The original "official" firmware for the Agon Light was primarily written by [Dean Belfield](http://www.breakintoprogram.co.uk), with help from several other contributors, and was given the name "Quark". 90 | 91 | At the time of writing, the latest Quark firmware releases are Quark MOS 1.04 and Quark VDP 1.04, which were released in November 2023. Dean is a busy man with a full-time job, and a family to look after, so his available time to work on the Agon is limited. Since those firmware releases, he has concentrated his Agon efforts since then in developing and maintaining versions of BBC BASIC for the Agon. 92 | 93 | The Agon Console8 firmware started as a fork of the Quark firmware, made by [Steve Sims](https://www.patreon.com/c/SteveSims). An AgonConsole8 organisation was set up on GitHub, and hard forks made of the Quark firmware. There are many reasons why this fork was made which won't be explored here. The two most important reasons however were to allow for a more rapid release schedule, and to have a wider organisation in place for looking after the firmware, to avoid the "hit by a bus" risk of a single owner. Initially all changes made to the Console8 firmware were raised as pull requests to be merged back into the Quark firmware, and broadly speaking the Quark 1.04 and Console8 2.0.0 releases were nearly identical. 94 | 95 | Owing to the pace of development, it stopped being practical to contribute changes made to the Console8 firmware (as it was then known) back to the Quark firmware early in 2024. 96 | 97 | Despite it's name, the Console8 firmware has always been able to be used on all Agon platforms, including the Agon Light, Agon Light 2, and Agon Origins Edition. Whilst this has always been the case, the "Console8" name has lead to some confusion... 98 | 99 | "Agon Platform" is the new name for the Console8 firmware, and also the new name for the organisation. This rename happened in April 2025. 100 | 101 | ## Which firmware do you currently recommend using on my Agon? 102 | 103 | We recommend using the Agon Platform firmware, as most development currently takes place there while staying compatible with previously released software. It's important to mention that the latest, most interesting games, make use of features that are only available in the Agon Platform (VDP) firmware, so make sure to use that. 104 | 105 | ## Can I switch between the Quark firmware, Console8, and Agon Platform firmware? 106 | 107 | Yes, either way. 108 | 109 | ## What is the function of Agon's jumpers and what is their recommended position? 110 | 111 | ### The ESP jumper 112 | 113 | All Agon variants have a jumper location on the PCB marked 'ESP-PROG' or 'ESP-PROG1'. For programming the VDP over the USB interface, this needs to be **CLOSED**, i.e. both pins should be connected using the removable jumper. It is present on the PCB, to provide the option to *prohibit* the ESP32 to go into programming mode on reset, likely due to the way the USB serial driver behaves on your PC. If this happens to you occasionally and it looks like the Agon doesn't boot on a reset, it may be just waiting for an external programming session that never happens, spewing messages over the USB serial; in that case remove the jumper or leave it open, but remember to close it again before programming it externally over USB. The position of this jumper is ignored when programming the VDP using the flash tool from the MOS prompt. 114 | I recommend to leave this jumper in the **CLOSED** position, unless you experience problems resetting your Agon. 115 | 116 | ### The UART jumper 117 | 118 | All Agon variants have a jumper to either enable, or prohibit the UART between the eZ80 and ESP32. During normal operation of the Agon, both ICs should be able to 'talk' to each other; this jumper was provided in case communication between them would somehow cause issues during programming either IC. AFAIK there haven't been cases to date where this proved necessary, but the option is at least there. If your Agon doesn't do anything after you have received it from your vendor, you may check this jumper's position. Cases have been reported of boards not working due to an incorrect factory jumper setting. 119 | 120 | - The AgonLight/AgonLight2/AgonLight Origins edition have this jumper labeled as 'UART-DIS' or 'UART-DIS1', which should be left **OPEN** to not disable communications and have a working Agon 121 | - The Agon Console8 has this jumper labeled as 'UART-EN1', which should be **CLOSED** to enable communications and have a working Agon. 122 | 123 | ### The Buzzer jumper 124 | 125 | All Agon variants have a jumper to enable/disable the onboard buzzer, labeled 'BUZ-EN', 'BUZ_EN1' or 'BUZZER'. Leaving the jumper open disables the buzzer, while closing it enables it, whichever is your preference. 126 | 127 | ## Do I need to buy the Zilog SMART cable to update my Agon? 128 | 129 | No, not unless you will be developing your own Agon MOS firmware AND need to be comfortably sure you can recover it under ALL circumstances. And even then you may very well get by using one of the community-provided options. People in the community owning SMART cables are seldomly using them nowadays. 130 | 131 | As an example of this, most of the development of the Agon Platform MOS firmware has been done without the use of the Zilog SMART cable. 132 | 133 | Again, for regular update purposes, the Zilog SMART cable is unnecessary and a waste of money. If it's bricking you're worried about; there is a [simple solution](https://github.com/envenomator/agon-recovery) requiring just a few dupont cables and a clear step-by-step plan to recover your Agon. In any case, you can at least buy a new Agon for the price of the Zilog SMART cable. Ease your worries. 134 | 135 | ## I still would like to buy a Zilog SMART cable. Which one should I get? 136 | 137 | The Agon-compatible Zilog product numbers are: 138 | 139 | - ZUS**BSC**00100ZACG (discontinued) 140 | - ZUS**BAS**C0200ZACG (current; requires v5.3.5 or later of Zilog’s ZDS -II IDE) 141 | 142 | !!! danger "Attention" 143 | 144 | The cable with product number ZUS**BES**C0200ZACG is **NOT** suitable for Agon! 145 | 146 | ## Can I go back to an earlier firmware version / downgrade? 147 | 148 | Absolutely (and this has been tested), but because literally ANY version can be flashed, please be mindful going back to older versions. The Pleistocene may not have a wall-outlet to charge your time travel device. 149 | 150 | Do yourselves a big favor, and stay away from anything below Quark 1.03, or that Zilog ZDS cable I mentioned you shouldn't buy, might suddenly start get interesting again. 151 | 152 | ## I don't have a Console8, can I still use the Console8 firmware? 153 | 154 | Yes, the Console8 firmware can be used on any existing Agon platform computer. This includes the original Agon Light, the Olimex Agon Light 2, the Agon Origins Edition, as well as the Agon Console8. 155 | 156 | There are no features in the firmware that are exclusive to the Agon Console8. It is possible to add a PS/2 mouse port and two joystick ports to Agon Light machines in a manner that is completely compatible with the Console8 firmware. 157 | 158 | To help reduce this confusion, the "Console8" name has been dropped for firmware releases in favour of "Agon Platform" in April 2025. The Console8 firmware is now known as the Agon Platform firmware. 159 | 160 | ## How should I connect the Agon to my PC for programming the VDP? 161 | 162 | To program an older VDP (1.03 or earlier) to a newer version, you need to connect the Agon using a USB (data) cable. Some very cheap USB cables may only have wires for powering/charging a USB device, without any wired data lines. Fortunately these are becoming scarce nowadays, but if all else fails, you might be using the wrong cable (or have the incorrect jumper setting; see above) 163 | 164 | The Agon will present a virtual serial port (COM) on your PC, that communicates directly with the ESP32 graphics chip (VDP). 165 | 166 | ## How can I find out the COM port on my PC, to connect to the Agon? 167 | 168 | It depends on the OS you have. In Linux, when you insert your USB cable and type 'dmesg | grep tty', it should show. 169 | 170 | In Windows, it should show up in device manager, or in powershell type '[System.IO.Ports.SerialPort]::getportnames()'. 171 | 172 | In Mac OS, you can type 'ls /dev/tty.*' in Terminal to list all com ports currently attached. 173 | 174 | ## Why is Agon model XXX delivered with out-of-date firmware? 175 | 176 | A legitimate question that you need to ask the respective vendor of your Agon. 177 | 178 | ## What keyboard do I need for my Agon? 179 | 180 | You need a keyboard that supports the PS/2 protocol, regardless of the physical connection that it has. Some Agon variants have a PS/2 interface, so any keyboard with a PS/2 connector should be fine. 181 | However, a number of Agon variants use a USB connector for their keyboard interface; for these you either need a USB keyboard that still supports the PS/2 protocol in backward compatibility mode (and it is usually hard to find out if it does), or a regular PS/2 keyboard with a PASSIVE PS/2-to-USB connector. An example for the latter, which is known to work well [is this one](https://www.amazon.com/Female-Adapter-Converter-Connector-Mouse/dp/B0BHRPVJZD/ref=sr_1_30?crid=3SG167E0EZITQ&keywords=Passive%20ps2%20adapter&qid=1687116944&sprefix=passive%20ps2%20adapter%2Caps%2C169&sr=8-30&fbclid=IwAR14ReD4S5cFHeTfE6eF03ec5_bbYQ7_NgplqCEzzluxCJY_9oq0uiOHcIQ). This is a pass-through connector, that just rewires the PS/2 signals to the USB connector. Perfect for the Agon. 182 | 183 | A PS/2-to-USB connector cannot make use of active logic and/or microcontrollers inside the connector. If the connector is dirt-cheap, it's usually passive, but even active converters can be offered relatively cheap. 184 | 185 | If a PS/2->USB converter has both a PS/2 keyboard and PS/2 mouse cable, a thick USB connector and/or a 'bulge' in the middle of the cable AND it doesn't specifically mention the term **PASSIVE**, it's a dead giveaway to be an active (non-supported) converter. Don't buy these: they scan/convert the PS/2 signals to a USB HID protocol that the Agon doesn't support. Examples to avoid [1](https://www.amazon.com/UCEC-Mouse-Keyboard-Converter-Cable/dp/B00X9QX9MS/ref=sr_1_9?crid=114AET38YBVMF&dib=eyJ2IjoiMSJ9.sD5kOGVjIYYaePDdcac3Zkqa5L5aKdNpzLx-i6lyOI0v9eQEk79fF3DXXJqAwJ0T4H1QiNsePhvnsBHdOqgM4fWvGCJTsZ5bv953oMiQ95lCEOP6zjSqoVS4mshWQjgRNzlGqrHnCJBeCzSqMAiWf3sBl5z_9TXHB1PmOUv4TPAySoDDtXWxcdSOlIsIve9OhejtVS5y2WX4uJJXoE1ZxDW7udIoZ8f1kTpeDt0I5qg.t5T8a8o73hLFRS0P3D_EW0e5KcDVaS7hnT1WdQ6irb4&dib_tag=se&keywords=ps2+to+usb&qid=1710795179&sprefix=ps2+to+us%2Caps%2C178&sr=8-9) and [2](https://www.amazon.com/LEIHONG-Active-Adapter-Keyboard-Converter/dp/B088LPKRLD/ref=sr_1_15?crid=114AET38YBVMF&dib=eyJ2IjoiMSJ9.sD5kOGVjIYYaePDdcac3Zkqa5L5aKdNpzLx-i6lyOI0v9eQEk79fF3DXXJqAwJ0T4H1QiNsePhvnsBHdOqgM4fWvGCJTsZ5bv953oMiQ95lCEOP6zjSqoVS4mshWQjgRNzlGqrHnCJBeCzSqMAiWf3sBl5z_9TXHB1PmOUv4TPAySoDDtXWxcdSOlIsIve9OhejtVS5y2WX4uJJXoE1ZxDW7udIoZ8f1kTpeDt0I5qg.t5T8a8o73hLFRS0P3D_EW0e5KcDVaS7hnT1WdQ6irb4&dib_tag=se&keywords=ps2%2Bto%2Busb&qid=1710795253&sprefix=ps2%2Bto%2Bus%2Caps%2C178&sr=8-15&th=1) 186 | 187 | ## Can you recommend a PS/2 keyboard? 188 | 189 | Sure, there's a crowd-sourced spreadsheet [here](https://docs.google.com/spreadsheets/d/1-6_sz6l-vJW5rFg3M0Y6bwC0hmFS7U6PPNjIZ9plrM8/edit?fbclid=IwAR0SBuM-oCywGE7Km6PupIWpiKnQNXIHQ2hD7iSDo5T7b_LTHXX0JNEe3Fw#gid=0) with a list of known working keyboards. 190 | 191 | If you have one, and it's not on the list, then please feel free to add an entry. 192 | 193 | ## How do I configure a different keyboard layout? 194 | 195 | You can use the following command from the MOS command line, from BBC BASIC (using the *), or loaded on boot/reset using a line in the autoexec.txt file on your SD card: 196 | 197 | *SET KEYBOARD n 198 | 199 | The keyboard layout for UK = 0, US = 1 200 | 201 | The keyboard layouts your Agon can support depends on the firmware versions you are using; at the time of writing 17 different layouts are supported. More information about available layouts is [documented here](mos/Star-Commands.md#keyboard-layout) 202 | 203 | ## How do I exit to the MOS command line, from within BBC Basic? 204 | 205 | Use the following command: 206 | 207 | *BYE 208 | 209 | ## Where can I find the user/hardware manual for my Agon edition? 210 | 211 | Check out these links for your particular Agon edition: 212 | 213 | - [Byte Attic AgonLight R1.0](https://github.com/TheByteAttic/AgonLight/blob/main/Agon%20light%20R1.0%20Manual.pdf) 214 | - [Byte Attic Agon Origins edition](https://github.com/TheByteAttic/AgonORIGINS/blob/main/Agon%20light%20ORIGINS%20Manual.pdf) 215 | - [Olimex AgonLight2](https://github.com/OLIMEX/AgonLight2/blob/main/DOCUMENTATION/AgonLight2-user-manual.pdf) 216 | - [Agon Console8](https://heber.co.uk/agon-cosole8/) 217 | 218 | ## Is there a community list of Agon software? 219 | 220 | We're listing a few here, though there will certainly be others: 221 | 222 | - [Sabotrax/agon-software](https://github.com/sabotrax/agon-software) 223 | - [The Byte Attic - Agon overview](https://www.thebyteattic.com/p/agon.html) 224 | 225 | ## Is there an Emulator available? 226 | 227 | Indeed there is, the [Fab Agon Emulator](https://github.com/tomm/fab-agon-emulator). It is available for Windows, Linux and Mac (or you can [compile](https://github.com/tomm/fab-agon-emulator/blob/main/docs/compiling.md) your own). 228 | 229 | ## What is the difference between the Agon Light and the Olimex Agon Light 2? 230 | 231 | The main differences are: 232 | 233 | - The keyboard connector is USB, yet still requires a keyboard that supports the PS/2 protocol 234 | - LIPO battery charging circuit 235 | - UEXT connector 236 | - USB C power connector 237 | - Plastic boxed 34-pin GPIO connector 238 | 239 | And there are some minor revisions to discrete components on the board. Other than that, it is functionally identical to the original Agon Light design. 240 | 241 | ## I'm having issues with some video modes 242 | 243 | Historically, this has been a problem when the VDP firmware was built using the Arduino IDE. You are strongly advised to use PlatformIO to build the VDP firmware, and to update to the latest versions; in doing so you should no longer have any issues with screen modes. PlatformIO takes care of all the dependencies and settings and thus is much easier to use than the Arduino IDE. The Agon Console8 VDP firmware (now known as the Agon Platform VDP firmware) no longer supports being built using the Arduino IDE and instead is built using PlatformIO to avoid these kind of issues. 244 | 245 | If you wish to still use the Arduino IDE and are building the Quark variant of the VDP firmware, you will need to make sure you have PSRAM enabled in the [Arduino IDE settings](https://github.com/breakintoprogram/agon-vdp#arduino-ide-settings) when you compile and transfer the VDP code. 246 | 247 | Finally there are a few screen modes that the Agon supports that a limited number of screens might not support. If you are having issues with a particular screen mode, try using a different screen mode to see if that resolves the issue. Remember that you can always press the reset button. 248 | 249 | ## I'd like to start programming BBC Basic - where might I start? 250 | 251 | Have a look at [this](https://oldpatientsea.github.io/agon-bbc-basic-manual/0.1/bbc1.html) excellent guide. 252 | We also provide some [documentation](./BBC-BASIC-for-Agon.md) at our community site. 253 | 254 | ## Are there any simple BBC BASIC examples? 255 | 256 | Your AGON may have a 'tests' folder with some BBC BASIC examples; if it doesn't, they can be [found here](https://github.com/breakintoprogram/agon-bbc-basic/tree/main/tests). 257 | 258 | ## Is BASIC the only programming language available? 259 | 260 | The AGON comes pre-shipped with BASIC as it is a good language to start coding with, but you are not limited to it. The following languages are supported: 261 | 262 | - Forth 263 | - Assembly Language (either via BBC Basic inline assembler or external assembler) 264 | - C (Cross-compiled from a PC, via ZDS tools, Agondev, or AgDev) 265 | - C++ (Cross-compiled from a PC or Mac, via Agondev or AgDev) 266 | 267 | ## I'd like to start assembly programming for the Agon platform - where might I start? 268 | 269 | We would recommend watching and learning these [excellent tutorials](https://www.youtube.com/playlist?list=PL-WZxPxo1iaDnvHoGHXeCdKddYqwPaSUk) 270 | 271 | Download the latest version of the [onboard assembler](https://github.com/envenomator/agon-ez80asm/releases). Don't dally using the one that came with your uSD card package, things move quickly in this space - use the latest. 272 | 273 | ## I'd like to start C/C++ programming for the Agon platform - where might I start? 274 | 275 | Assuming you already know some C/C++, we recommend downloading and using [agondev](https://github.com/AgonPlatform/agondev) as it is the best cross-development toolchain available for the Agon platform. This is a comparatively new toolchain and is still in active development. 276 | 277 | Another option is the [AgDev](https://github.com/pcawte/AgDev), which is an extension of the CEDev toolchain originally written to allow programs to be written for the TI-85 Plus CE and TI-83 Premium CE calculators, which use the same eZ80 processor as the Agon. There are a number of example programs available in the AgDev repository. 278 | 279 | Agondev has a decent degree of compatibility with AgDev, but tends to be slightly more compliant with modern C and C++ standards. 280 | 281 | ## I'd like to start Forth programming for the Agon platform - where might I start? 282 | 283 | There is an excellent Forth implementation available [here](https://github.com/lennart-benschop/agon-forth) 284 | 285 | ## Is there some in-depth API documentation available for me to look at? 286 | 287 | The community is building out [at set of markdown documents](https://github.com/AgonPlatform/agon-docs) to detail several aspects. These are extremely useful to a programmer. 288 | 289 | ## Is there a documented memory map available to me as a programmer? 290 | 291 | A memory map can be found [here](https://github.com/envenomator/Agon/blob/master/Memory%20map.png) 292 | 293 | ## I'd like to read all details about Agon's ez80 microcontroller 294 | 295 | Buckle up! 296 | 297 | - [eZ80F92 datasheet](https://www.zilog.com/docs/ez80acclaim/ps0153.pdf) :fontawesome-solid-file-pdf: - details regarding the eZ80F92 microcontroller peripherals like I2C, SPI, Flash memory, debug interface, timers 298 | - [eZ80 CPU datasheet](https://www.zilog.com/docs/um0077.pdf) :fontawesome-solid-file-pdf: - details regarding the ez80 CPU itself, cpu architecture, registers, memory mode, interrupts and instruction set 299 | - [Application note AN033301-0711](https://www.zilog.com/docs/appnotes/an0333.pdf) :fontawesome-solid-file-pdf: - details of the ZDS Application Binary Interface (ABI), how to call C functions from Assembly and vice versa. Also applicable to the AgDev environment which is compliant to the ABI. 300 | 301 | ## Can you code feature {x}? 302 | 303 | All suggestions are welcome, though the developers will be concentrating on key features. If we think your idea has legs, we'll add it to the pile. 304 | 305 | ## Why is feature {x} not documented anywhere? 306 | 307 | You might have found an opportunity to make a valuable contribution to the Agon community. Take a look at the community [documentation](https://github.com/AgonPlatform/agon-docs) and create a pull request. 308 | 309 | ## I'd like to discuss my project or ideas with like-minded people 310 | 311 | Perhaps you have some cool ideas and you want to run them past people, or you want to watch some of the developers talk, or you've followed all the instructions here and broke something and now you'd like to ask around to see if someone else has had the same experience? There is a [Discord server](https://discord.gg/sN3vXru26s) available for Agon & Console 8 community discussions. 312 | -------------------------------------------------------------------------------- /docs/GPIO.md: -------------------------------------------------------------------------------- 1 | # User GPIO pins 2 | 3 | GPIO, or General Purpose Input and Output, is an interface on a computer that is not dedicated to a single task. On the Agon this is exposed as a series of pins for the user to interface to. This might be for input controls, such as a joystick or buttons, motion sensors, or outputs to control your Christmas tree lights, send data to other displays, microprocessors, or even connect to the internet. 4 | 5 | Whilst sharing many similar pins, there are some variations across the range of Agon machines. 6 | 7 | The first generation Agon Light has a double row of 32 pins, whereas the Agon Light 2 has a double row of 34 pins. The additional pair of pins have been added for a battery power supply connection. 8 | 9 | The Agon Console 8 adds a few extra rows for additional connectivity to other parts of the ESP processor. 10 | 11 | More information about using these features can be found in the [MOS API documentation](mos/API.md). 12 | 13 | 14 | ## GPIO Pinouts - Original Agon Light by Bernardo Kastrup 15 | 16 | Viewed from the back, component side up, with the connector to the right of the board. 17 | 18 | ![](./images/iopinsAL1.png) 19 | 20 | 21 | ## GPIO Pinouts - Agon Light Origins Edition by Bernardo Kastrup 22 | 23 | Viewed from the back, component side up, with the connector to the right of the board. A slight change with an additional pair of pins to the right hand side. The pin numbering is the same as the Agon Light 2 by Olimex. 24 | 25 | ![](./images/io_origins.png) 26 | 27 | ## GPIO Pinouts - Agon Light 2 manufactured by Olimex 28 | 29 | The general layout is the same as the Origins Edition, apart from pins 1 & 2. 30 | 31 | ![](./images/iopinsAL2.png) 32 | 33 | Olimex's proprietary UEXT connector is mounted next to the main IO bus. 34 | 35 | Note that although there are duplicate pins exposed on the UEXT connector as the main IO bus, they are connected to the same pins on the ez80 chip. They are there for convenience, but do not provide any additional hardware ports. 36 | 37 | It is sometimes useful to have the duplicate pins for different purposes. For example, connecting a Nintendo Nunchuck controller on the UEXT using Olimex's adapter board, and a joystick on the main IO bus. 38 | 39 | ![](./images/io_uext.png) 40 | 41 | ## GPIO Pinouts - Console 8 manufactured by Heber 42 | 43 | Viewed from the top front, component side up. 44 | 45 | The Console 8's pin numbering is different and although they look similar at first, some of the pins do not align with those of the Agon Light, so do not plug an Agon Light peripheral into the io bus of a Console 8. 46 | Pins marked * go via a transputer. 47 | 48 | ![](./images/iopinsC8.png) 49 | -------------------------------------------------------------------------------- /docs/MOS.md: -------------------------------------------------------------------------------- 1 | # What is the MOS 2 | 3 | The MOS is a command line Machine Operating System, similar to CP/M or DOS, that provides a human interface to the Agon file system. 4 | 5 | It also provides the [MOS API](mos/API.md) for programmers to use that provides some basic facilities for file I/O and other common operations for BBC BASIC and other third-party applications. 6 | 7 | This documentation explains the general features of MOS, as well as commands it offers and how to use them. It covers the Quark 1.04 version of MOS, the later Console8 MOS releases, and the Agon Platform MOS up to and including MOS 3.0. Versions of MOS prior to Quark 1.04 may be missing some features described below. 8 | 9 | Please note that if you are running Quark 1.04 or earlier, the capabilities of MOS are very limited, and quite a few features described in this documentation will not be available to you. You are strongly advised to upgrade to a later version of MOS. MOS 2.x and MOS 3.x releases are fully compatible with software written for Quark 1.04, and will run all Quark 1.04 software without modification. 10 | 11 | ## System Requirements 12 | 13 | To get the most out of MOS, you will need the following: 14 | 15 | * A micro-SD card formatted as FAT32 16 | 17 | Technically MOS will work without an SD card, but you won't be able to do much with it. 18 | 19 | ## Using an SD card 20 | 21 | MOS supports the use of an SD card to store files and [programs](./mos/Executables.md). The SD card must be formatted as FAT32. This documentation previously advised that the card should be 32GB or less in size, however several users report successfully using 64GB cards. MOS supports automatically [running a script file on boot](#boot-script) and a way of adding new commands. 22 | 23 | ### Moslets 24 | 25 | "Moslets" are a special type of program that are intended to extend the functionality of MOS by adding in new commands. 26 | 27 | By convention, moslets are stored in a special folder named `mos` at the top level of the SD card. When you attempt to use a command that is not built into MOS, the system will look in the `mos` folder for a file with the same name as the command with a `.bin` extension. If it finds one, it will execute that file as if it were a built-in command. 28 | 29 | Moslets have a special requirement in that they must be built to run from memory address `0x0B0000` onwards. The use of this address is intended to allow moslets to run without affecting the main user program space. The idea being that this will let you use a moslets from within BASIC (or from within other programs) without having to worry about it overwriting your program. 30 | 31 | From MOS 3.0 onwards it is possible to specify a different directory, or multiple directories, for the location of moslets on your system. This is done by setting the `Moslet$Path` [system variable](mos/System-Variables.md#system-path-variables). By default this variable is set to `/mos/` for compatibility with previous versions of MOS. 32 | 33 | ### The "run path" 34 | 35 | MOS 2.2.0 effectively added the concept of a "run path" to MOS, which would be used by the CLI to either search for commands not built into MOS, or to run programs. In MOS 2.2.0 to MOS 2.3.2 the order of directories searched would be fixed, with the `mos` folder being searched first for moslets, followed by the current directory, and then the `bin` folder. In MOS 2.x the order could not be changed. MOS 3.0 provides a way to change this. 36 | 37 | Programs located outside of the moslet folder are expected to be full standalone programs that will be run and executed at the default memory address of `0x040000`, and thus will overwrite existing programs. 38 | 39 | NB there is currently no way to control the memory address that a program is automatically loaded into, so if you have a program that needs to be loaded at a specific address, you will need to use the `Load` command to load it manually and then use the `Run` command to start the program. 40 | 41 | It should be noted that MOS will always run the first program it finds with the same name as the command you have entered. This means for example that if you have a moslet with the same name as a program in the `bin` folder, the moslet will be run instead of the program. 42 | 43 | From MOS 3.0 onwards the order of directories searched is controlled by the `Run$Path` [system variable](mos/System-Variables.md#system-path-variables). By default this is a macro variable set to `, ./, /bin/` to be compatible with previous versions of MOS. This variable can be changed to search in any order you like, and can include multiple directories. By changing this variable you can, for example, make it so that the `bin` folder is searched before the `mos` folder, or add additional directories to search in. 44 | 45 | ### Automatically running a script on boot {#boot-script} 46 | 47 | MOS has the ability to automatically run a script file on boot (power on, or a system reset). Quite what this script does is up to you, but it could be used to set up your Agon in a particular way, or to run a program automatically. 48 | 49 | The exact file that will be run, and the manner in which the file is run varies depending on which version of MOS you are using. 50 | 51 | As of MOS 3, the system will first look for a boot file named `!boot.obey`, and use that as it's preferred boot script, running it using the [`obey` command](mos/Star-Commands.md#obey). If that file is not present, it will look for a file named `autoexec.obey` and run that. If neither of these are present it will fall back to working in a similar manner to Quark MOS 1.04 and MOS 2.x. If you are running MOS 3, and have a suitably up-to-date version of the VDP firmware installed, you can prevent the boot script from being run by holding down the left "Shift" key on your keyboard during power up or reset. 52 | 53 | Quark 1.04, and Console8 MOS 2.x releases will all, at boot-up time, look for a file named `autoexec.txt` in the root folder of the SD card. The manner in which this file is executed differs slightly between Quark 1.04 and the later Console8 releases. Quark will blindly execute the commands and silently carry on it encounters an error, and any such errors will not be reported. The Console8 MOS 2.x releases execute the `autoexec.txt` file using the [`Exec` command](mos/Star-Commands.md#exec) and will stop execution if there is an error in the file, reporting the error as well as which line the error occurred on. 54 | 55 | If no matching script file is found, the system will simply boot to the command prompt. 56 | 57 | An example script, compatible with Quark 1.04 and all later versions of MOS, follows. This script will to set keyboard to US, load BBC BASIC from the root folder, change to the test folder, then run BASIC. 58 | 59 | ``` 60 | SET KEYBOARD 1 61 | LOAD bbcbasic.bin 62 | CD test 63 | RUN 64 | ``` 65 | 66 | If you are running MOS 2.2.0 or later, and `bbcbasic.bin` is in your run path (most likely in a `/bin` directory), this script could be simplified to: 67 | 68 | ``` 69 | SET KEYBOARD 1 70 | cd test 71 | bbcbasic 72 | ``` 73 | 74 | MOS 3.0 allows for a great deal of customisation of your MOS environment, including the ability to set up custom command aliases, set "run types" to allow all sorts of files to be directly run from the command line, a custom command prompt, adjust the "run path" that will be searched for commands and executables, and many other features. Many of these features are controlled through the use of [system variables](mos/System-Variables.md). It is common to have a `!boot.obey` that will set up system variables to customise your MOS environment. 75 | 76 | MOS 3.0's preferred use of `!boot.obey` means that if you have more than one Agon computer running different versions of MOS then you can use the same SD card in all of them. This would allow your MOS 3 system to use commands in its `!boot.obey` file that are not available in Quark MOS 1.04 or MOS 2, and those systems will still run the separate `autoexec.txt` file. Your `!boot.obey` file could include commands specific to MOS 3, and finish with the command `exec autoexec.txt` to run the boot file used by earlier versions of MOS. 77 | 78 | ## Soft Boot 79 | 80 | Pressing `CTRL+ALT+DEL` will reboot MOS on the eZ80. (`CTRL+SHIFT+ESC` for MOS 1.02 or earlier) 81 | 82 | NB: This assumes that MOS is still talking to the VDP, as it is the VDP that is responsible for detecting keypresses. Sometimes a soft reboot key combination will therefore not work, and you may need to instead press the reset button on your Agon. 83 | 84 | If you are using a MOS version earlier than 2.2.0, then a soft reset will not try to run the boot script. To make sure the boot script runs you would need to do a "hard boot" by powering cycling your Agon (turn it off, then on again), or pressing the reset button. 85 | 86 | ## The MOS Command Line Interface 87 | 88 | MOS provides a command line interface (CLI) that allows you to interact with the Agon file system and perform some basic control over your Agon computer. 89 | 90 | The MOS CLI is loosely inspired by the Acorn MOS present in the BBC Micro and later Acorn computer systems like the Archimedes. The features and facilities supported by the MOS command line have evolved over time, with MOS 3.0 supporting many more commands than earlier versions of MOS. 91 | 92 | MOS works alongside the Agon's VDP, using the facilities of the VDP to display text on the screen and accept input from the keyboard. The VDP provides some useful facilities, such as a "paged mode" that will stop the screen from scrolling until you press the `SHIFT` key to continue, or `ESCAPE` to exit. Paged mode can be toggled on and off by pressing `CTRL+N` and `CTRL+O` respectively. 93 | 94 | In MOS 3 (when used with VDP 2.14.0 or later) the MOS CLI can also [automatically use paged mode](mos/System-Variables.md#autopaged) with commands that produce a lot of output. 95 | 96 | ### The MOS line editor 97 | 98 | MOS provides a simple line editor that allows you to edit the current command line before submitting it to the system. This same line editor is available for third-party applications like BBC BASIC to use. 99 | 100 | The line editor allows you to move the cursor around the current line of text, insert and delete characters, and submit the line to the system. Whilst much of the functionality on Agon is inspired by the BBC Micro, the line editor differs - there is no "copy" cursor system on the Agon. This line editor is similar to those that you will find on modern operating systems like MacOS, Linux or Windows. 101 | 102 | The MOS CLI line editor will also provide some basic command history, keeping track of the last 16 commands the user has entered. Pressing the `UP` arrow key when at the beginning of a line will replace the current line with the last entered command. Similarly pressing the `DOWN` arrow key at the end of a line will cycle through the command history in the opposite direction. The `HOME` and `END` keys will move the cursor to the start and end of the current line respectively. 103 | 104 | The Console8 MOS 2.2.0 release also adds support for pressing the `PAGE UP` and `PAGE DOWN` keys to quickly step through the command history. 105 | 106 | Also added to the 2.2.0 release is "tab completion". If you start typing a command and then press the `TAB` key, MOS will attempt to complete the command for you. This includes both built-in commands, moslets found in the `mos` folder, programs found in the current directory, and programs found in the `bin` folder, or file names within the current directory. In MOS 3.0 onwards, the tab completion uses the `Run$Path` variable to determine where to look for commands. 107 | 108 | There is also support for programmable function keys in the 2.2.0 release. For more information on that see the [`Hotkey` command](mos/Star-Commands.md#hotkey). 109 | 110 | ### The MOS command prompt 111 | 112 | On versions of MOS prior to the 2.2.0 release, the MOS command prompt is a simple `*` character. This is the point at which you can enter commands to the system. 113 | 114 | From the Console8 MOS 2.2.0 release onwards the prompt has been extended to include the current directory. This is to help you keep track of where you are in the file system. The prompt will look something like this: 115 | 116 | ``` 117 | /programs * 118 | ``` 119 | 120 | MOS 3.0 allows you to customise the prompt using the [`CLI$Prompt` system variable](mos/System-Variables.md#cli). By default this is set to a macro to display a prompt identical to that introduced in MOS 2.2.0. If this variable is unset, then the prompt will revert to the simple `*` character. 121 | 122 | ## MOS Commands 123 | 124 | MOS offsets a number of inbuilt commands that allow you to interact with the Agon file system and control your computer. 125 | 126 | The various commands available in MOS are described in the [MOS Command Reference](mos/Star-Commands.md). The exact array of built-in commands available has changed over time with new commands being added, and new features added to existing commands. 127 | 128 | As of MOS 3.0 the command interpreter has become fairly sophisticated. It will support user-defined [commands aliases](mos/System-Variables.md#command-aliases), and the use of [system variables](mos/System-Variables.md). As well as the ability to run [moslets](#moslets) and program files directly (as [described above](#the-run-path)) it can now also directly run any file that has a ["run type"](mos/System-Variables.md#file-type-variables) set up for it by simply typing the name of the file. 129 | 130 | ## MOS System Variables 131 | 132 | From MOS 3.0 onwards, MOS supports the concept of [system variables](mos/System-Variables.md). These can be used for user programs, as well as providing ways to gain information about the system and control the behaviour of MOS. 133 | 134 | ## Script files 135 | 136 | All Agon Platform and Console8 MOS releases support the concept of a script file. This is a file that contains a series of MOS commands that can be executed in sequence. This is useful for automating tasks, or for setting up your Agon in a particular way. When a script file is run, if an error is encountered the system will stop executing the script and report the error, as well as which line the error occurred on. 137 | 138 | The first type of script file is an "Exec" file, which is a simple text file containing a series of MOS commands, one per line. You can run an Exec file using the [`Exec` command](mos/Star-Commands.md#exec). 139 | 140 | MOS 3.0 has added a second type of script file, which is an "Obey" file, which are run using the [`Obey` command](mos/Star-Commands.md#obey). This is very similar to an Exec file, but when running an Obey file the system will set a [system variable](mos/System-Variables.md#obey-files) to indicate the directory inside which the Obey file is located, and it will also support [argument substitution](mos/Argument-Substitution.md). 141 | 142 | Quark MOS 1.04 only supports a single script file, `autoexec.txt` that will be run at boot, and offers no command to run a script file. 143 | 144 | ## Programs and Modules 145 | 146 | Executable program files on MOS need to be in a specific format. This is described in the [Executable file format](mos/Executables.md) documentation. 147 | 148 | A future version of MOS is also likely to support the concept of ["modules"](mos/Modules.md). This will be a way to extend the functionality of MOS to add in new features, whether they are commands, APIs or something else. The exact details of the module system are still in development. 149 | 150 | ## Memory map 151 | 152 | Addresses are 24-bit, unless otherwise specified 153 | 154 | - `&000000 - &01FFFF`: MOS (Flash ROM) 155 | - `&040000 - &0AFFFF`: User RAM * 156 | - `&0B0000 - &0B7FFF`: [Moslet](#moslets)/[Module](mos/Modules.md) memory space 157 | - `&0B8000 - &0BBFFF`: Reserved for MOS 158 | - `&0BC000 - 0BFFFFF`: Global (MOS) heap and stack 159 | - ... 160 | - `&B7E000 - &B7FFFF`: The eZ80's 8kb of internal (fast) RAM 161 | 162 | \* Technically, user programs can actually use the whole RAM space from `&040000` to `&0BBFFF`, but programs that use memory above `&0AFFFF` may have limitations. A program that uses the moslet/module memory space for instance will not be able to use moslet-based commands, and when modules are introduced will have limitations on access to functionality provided by modules. Programs should need to indicate in their [header](mos/Executables.md#advanced-header) whether they are "module safe" or "module compatible". Guidance on how to make your program "module safe" will be provided in the [MOS Modules](mos/Modules.md) documentation. 163 | 164 | ## The Stack 165 | 166 | Up to and including the MOS 3.0 release, MOS sets up a stack pointer for its own use. As MOS is written to run in the eZ80's "ADL" mode, this means the `SPL` register, the version of `SP` visible to ADL-mode code, is what is set up. Programs that are run in ADL-mode will see this stack pointer when they start up. Care should therefore be taken to ensure that the stack pointer is not corrupted by the program, as this will affect the operation of MOS and any other programs that are run after it. 167 | 168 | The architecture of the eZ80 means that programs running in Z80 mode see a different version of the stack pointer `SP` register, known as `SPS`. This value is _not_ set up by MOS, and is left to the user program to set up. The value of `SP` in Z80 mode should be treated by programs as undefined on startup. 169 | 170 | Future versions of MOS may change the behaviour of the stack pointer for ADL-mode code in order to provide better protection for the MOS stack. For compatibility with existing software, a stack pointer will still be set up for programs that use ADL-mode, but this may be allocated within the MOS heap space. 171 | -------------------------------------------------------------------------------- /docs/Projects.md: -------------------------------------------------------------------------------- 1 | In the [Agon Projects Git](https://github.com/breakintoprogram/agon-projects), there are a handful of useful templates and projects. 2 | 3 | # The Templates 4 | 5 | There are three template projects that can be used as a basis for your projects: 6 | 7 | - A 16-bit mode Hello World app in assembler that demonstrates calling the MOS from a 64K segment in Z80 mode 8 | - A 24-bit mode Hello World app in assembler 9 | - A 24-bit mode Hello World app in C 10 | 11 | All three apps act as MOS extensions; the resultant binary can be copied into the `mos` folder on the SD card, can be executed as a star command, and will display any passed parameters. 12 | 13 | # The Applications 14 | 15 | - A memory dump application written as a 16-bit mode assembly language app. 16 | - An eZ80 disassembler written as a C application. 17 | 18 | Both can be run as star commands from MOS. -------------------------------------------------------------------------------- /docs/Theory-of-operation.md: -------------------------------------------------------------------------------- 1 | # Understanding the Agon Light computer platform 2 | 3 | The Agon Light, and its variants, is a retro-style computer platform that is designed to be inexpensive and easy to manufacture, using commonly available parts. 4 | 5 | The platform is designed to be easy to understand, and easy to program. It is designed to be a platform that is suitable for learning about computers, and learning about programming. 6 | 7 | Please note this is a preliminary guide to the Agon Light platform, and is subject to change. The Agon Light platform is still under development, and this guide is still being written. 8 | 9 | 10 | ## The Agon Light hardware 11 | 12 | ### The main processor 13 | 14 | The primary processor on which you run programs is an eZ80. This is a microcontroller based on the Zilog Z80 processor, which was used in many computers and arcade machines in the 1970s and 1980s. The eZ80 is a modern version of the Z80, with a few enhancements. It has attached to it 512KB of RAM, which is considerably more than the 64KB that was common in the 1980s. Also attached to the eZ80 chip is an SD card interface, allowing an SD card to be used for storage. 15 | 16 | The eZ80 was chosen as the main processor of the Agon Light because of its historic ubiquity, and because it is still manufactured today. It is a relatively simple processor, and is easy to understand and program. 17 | 18 | The eZ80 runs an operating system called [MOS](MOS.md). This is a relatively simple operating system designed to provide basic facilities to programs. Alternative operating systems such as CP/M can be used on the Agon Light, but MOS is the default operating system. 19 | 20 | ### The video display processor, or VDP 21 | 22 | Whilst the eZ80 is manufactured today, none of the video chips that were used in computers of the 1970s and 1980s are still manufactured, so for video output a different solution is needed. To solve this problem the Agon Light uses a separate video processor, which we call the VDP, the Video Display Processor. This chip is responsible for sound and video output, and also keyboard and mouse input. Technically, this is an ESP32-Pico-D4 chip, which has attached to it an 8MB RAM chip which is used for storing bitmaps, sound samples, fonts, and other data. 23 | 24 | The exact technical details of the VDP however for most programmers is not important - in the Agon platform, from a software perspective, the VDP is designed to be used via a [simple API](VDP.md), with the details of how it works abstracted away. Indeed, when using an emulator of the Agon Light, the VDP chip is not emulated at all; the emulator instead runs a compiled version of the VDP firmware using the host computer's video and audio hardware. 25 | 26 | 27 | Effectively, the design of the Agon Light is that of two computers in one. The eZ80 is the computer that is used to run programs, and the VDP is a smart terminal computer that draws the screen, plays sound, and handles the keyboard and mouse[^1] interfaces. The eZ80 and the VDP communicate with each other using a high speed serial interface. 28 | 29 | 30 | Some other retro-inspired computers take a different approach to solving the video output problem. Often this involves making use of an FPGA chip, which is a chip that can be programmed to behave like any other chip. This is a very flexible solution, but it is also very expensive. The Agon Light takes a different approach, using a separate video processor chip, which is much cheaper than an FPGA. 31 | 32 | 33 | The use of what is effectively a separate computer for the VDP in the Agon platform creates a significant architectural difference to many classic home computers of the 8-bit, 16-bit and early 32-bit era. Those classic computers would usually use a shared area of memory that the main processor and the video processor would both have access to. This shared memory would be used to store the screen memory, and the main processor would write to this memory to update the screen. This is not the case with the Agon platform. The eZ80 and the VDP have no shared memory, and the VDP has no access to the eZ80's RAM. This means that the VDP cannot read the screen memory directly, and the eZ80 cannot write directly to the screen memory. Instead, the VDP has to be sent commands to draw things to the screen, and the eZ80 has to be sent commands to read things from the screen. This is a significant difference to many classic computers, and is something that programmers need to be aware of when writing programs for the Agon platform. 34 | 35 | 36 | ## The Agon software platform 37 | 38 | From a software perspective, a significant inspiration for the Agon Light was the BBC Micro, a popular computer in the UK from the 1980s designed and built by Acorn Computers Ltd.. (Acorn went on to design the ARM processor, which is now the most commonly used processor design in the world.) The BBC Micro was part of the BBC's Computer Literacy Project, which was a project to introduce computers to the UK population with an emphasis on education. The BBC Micro was designed to be easy to use, and to be used in schools by children. 39 | 40 | There are several significant differences between the Agon Light and the BBC Micro, but the two most important ones are the main processor, and the video system. A BBC Micro was based on the 6502 CPU, which was a competitor to the Z80. The 6502 was a simpler processor than the Z80, and was cheaper to manufacture, and given the relative simplicity often significantly faster than the Z80. The 6502 was used in many popular computers and games consoles of the 1970s and 1980s, including the Apple II, the Commodore 64, and the Atari 2600. The Z80 was used in many other popular computers of the 1970s and 1980s, including the Sinclair ZX80, the Sinclair ZX81, the Sinclair Spectrum, the Amstrad CPC, and the MSX. The BBC Micro however was designed from the ground up to be a computer capable of having multiple processors, and the first second processor option available for the computer was the Z80. A version of BBC BASIC was produced for Acorn's Z80 second processor, and this is the version of BBC BASIC that the Agon Light is directly based on. 41 | 42 | 43 | ### BBC BASIC 44 | 45 | An important part of the BBC Micro was BBC BASIC, a well respected version of the BASIC programming language. Compared to other versions of BASIC, BBC BASIC was very powerful since it included many advanced features, such as procedures, functions, and recursion. It also included many commands for graphics and sound, which made it easy to write games and other programs that used graphics and sound. 46 | 47 | The original version of BBC BASIC for the BBC Micro's 6502 processor was written by Sophie Wilson of Acorn. The version of BBC BASIC for the Z80 was written by Richard T. Russell, and was based on the original version by Sophie Wilson. Specifically it is effectively equivalent to BBC BASIC 4 that was used on the BBC Master series of computers. The version of BBC BASIC for the Agon Light is directly based on R.T.Russell's version, and is largely compatible with the BBC Micro version. 48 | 49 | BBC BASIC has an inbuilt assembler, which allows for machine code to be embedded within BASIC programs. This is a very powerful feature, and allows for programs to be written that make use of the full power of the processor. Machine code can run very many times faster than interpreted BASIC. It should be noted that the Z80 version of BASIC as used on the Agon platform has an assembler for the Z80 built in, whereas the original 6502 version of BASIC for the BBC Micro included an assembler for the 6502 processor. Programs written for the BBC Micro that include assembler code will therefore not run on the Agon Light without rewriting those assembler routines. 50 | 51 | #### BBC BASIC ADL version 52 | 53 | There is now a newer version of BBC BASIC for the Agon platform known as the "ADL version". The original Z80 version of BBC BASIC was restricted to work within 64KB of RAM. This limitation was due to the fact that the Z80 processor only has 16 address lines (also referred to as a 16-bit address bus), so technically it can only address 64KB of RAM. 54 | 55 | The newer eZ80 CPU used in the Agon Light has a 24-bit address bus, which means that it can potentially address up to 16MB of RAM. Agon Light machines come with 512KB of RAM attached to the eZ80 CPU. 56 | 57 | To allow programs to make use of this extra RAM, and some other new facilities, the eZ80 has extensions known as "ADL mode". This mode extends most processor registers to 24 bits, and allows for the use of the extra RAM. The ADL version of BBC BASIC is designed to make use of this extra RAM, and to allow for programs to be written that make use of more than 64KB of RAM. 58 | 59 | The ADL version of BBC BASIC also includes modifications to the assembler to allow for the use of newer ADL machine code instructions. This means that programs written for the ADL version of BBC BASIC may not run on the original Z80 version of BBC BASIC. 60 | 61 | 62 | ### VDU commands, screen modes, and the VDP 63 | 64 | The other significant difference between the Agon Light and the BBC Micro is the video system. As video output is handled by a separate processor, and there is no shared memory between the two processors within an Agon Light, the design of the Agon system does not allow for the video system to work in the same kind of manner as a BBC Micro. From a software perspective, however, the Agon Light is designed to be as similar as possible to the BBC Micro, and the video system is designed to be as similar as possible to the BBC Micro video system. This means that many programs written for the BBC Micro can be ported to the Agon Light with minimal changes. 65 | 66 | Using BASIC on a BBC Micro, the primary way to draw things to the screen was via simple keywords such as `PRINT`, `MOVE`, `DRAW`, `PLOT`, `COLOUR` (etc.) and most importantly `VDU`. It is the `VDU` keyword that sent commands to the video system. Effectively _all_ of the other keywords that drew onto the screen (or changed drawing settings) are just shorthand for `VDU` commands. 67 | 68 | The same is true on the Agon Light. The Agon's VDP processor has been written to understand the same `VDU` commands as the BBC Micro, and so the same keywords that draw things to the screen on a BBC Micro will also draw things to the screen on an Agon Light. This means that many programs written in BBC BASIC for the BBC Micro can be ported to the Agon Light with minimal changes. 69 | 70 | The Agon Light also includes a number of additional `VDU` commands that are not present on the BBC Micro, which allow for more advanced graphics and sound effects. These commands are documented in the [VDP](VDP.md) section of this documentation. 71 | 72 | #### Screen modes 73 | 74 | Another important difference to be aware of is that the available [screen modes](vdp/Screen-Modes.md) on the Agon Light are different to those on the BBC Micro. The single exception to this is mode 7, the teletext mode, which is supported on both platforms. A BBC Micro was highly limited in terms of its video output, supporting only 8 different screen modes, using only 4 different pixel resolutions, and a maximum of 8 colours. Agon machines offer a much wider variety of screen modes, with many more resolutions to choose from, and up to 64 colours on screen at once. 75 | 76 | Whilst the screen modes available on the Agon differ, the Agon graphics system by default uses the same 1280x1024 coordinate space as the BBC Micro[^2], where the origin is at the bottom left of the screen. As this is the same coordinate space as the BBC Micro, programs that use this coordinate space on the BBC Micro will work on the Agon Light without modification. As the screen ratios are different on the Agon you may see some inaccuracies when comparing output directly to a BBC Micro, but the differences are generally minor. 77 | 78 | The purpose of having a uniform coordinate space is to make it easier to allow you to change a program initially written to run in one screen mode (at one particular resolution) to run in a different screen mode at a different resolution without having to change the coordinates used in the program. 79 | 80 | This style of coordinate space may be alien to you, and also has some limitations if you wish for pixel perfect accuracy when positioning things on-screen[^3]. A command is available to switch the coordinate system to use the native pixel resolution of the screen mode with the origin at the top left of the screen. 81 | 82 | Whilst the BBC Micro could only display 8 colours on screen at once, it did have a "16 colour" screen mode where half of the colours were flashing. The Agon does not provide any screen modes with direct support for flashing colours, but it is possible to simulate these modes on later versions of the Agon VDP firmware. 83 | 84 | #### Limitations 85 | 86 | The nature of the MOS/VDP split on the Agon platform carries with it some limitations that you should be aware of. 87 | 88 | The VDP is, essentially, a stream processor. It accepts a stream of data from the eZ80, and interprets that as a series of commands and data. In regular use, there is no command to indicate the beginning of a command stream, and no command to indicate the end of a command stream. The VDU commands that the VDP interprets are of a variable length, ranging from a single byte to potentially over 64kb. A single `VDU` statement in BASIC could be a complete command from the perspective of the VDP, or it could be the first part of a command that is continued in the next `VDU` statement. For commands that are intended to send across a large amount of data, such as a bitmap or a sound sample, the data is typically sent using a series of `VDU` statements, each of which is a part of the same command. 89 | 90 | Care must therefore be taken to ensure that the VDP is sent complete commands, and that commands are not interleaved. For instance, it may be tempting when transferring over a sound sample to use `PRINT` or `DRAW` statements to show progress. This will not work, because the VDP will interpret the `PRINT` or `DRAW` statements (which will have been translated into a raw VDU byte command stream) as part of the sound sample data. 91 | 92 | To solve this issue, the VDP provides a [Buffered Commands API](vdp/Buffered-Commands-API.md). This allows for data to be sent to the VDP in discrete chunks, sent to one of over 65000 buffers. Once all of the data has been sent, a command can be sent to the VDP to make use of the data in the buffer, whether that is to use the buffer as a sound sample, a bitmap, or a sequence of VDU commands. So to print a progress bar whilst sending a sound sample, you would send the sound sample data to a buffer a chunk at a time using the Buffered Commands API "add block" command, and after each chunk use drawing commands to update the progress bar. Once all of the sound sample data has been sent, you would then send a command to the VDP to identify that data as a sound sample, and/or use other commands to play that sample. 93 | 94 | 95 | 96 | [^1]: As of the time of writing, the only model of Agon that comes with an inbuilt PS/2 mouse port is the Agon Console8. All other models of Agon can add one using a simple circuit attached to some GPIO pins. 97 | 98 | [^2]: Technically the BBC Micro's coordinate system was not actually 1280x1024; that was just the coordinate space of all the graphical screen modes that most models of the BBC Micro supported. The actual OS coordinates on a BBC Micro are based on the pixel resolution of the screen with a conversion factor applied for the X and Y dimensions. A BBC Micro built for the UK market was made to work with PAL TVs, and all of its screen modes had a vertical pixel resolution of 256 lines, with a conversion factor for the Y dimension of 4. A BBC Micro built for the US market (which were very rare) had the same conversion factor of 4, but a vertical pixel resolution of 200 lines as they were built to work with NTSC TVs. Later Acorn computers such as the Archimedes used the same system of conversion factors, but as they offered a wider variety of pixel resolutions some screen modes would use different coordinate spaces. 99 | 100 | [^3]: Using a strict 1280x1024 OS coordinate space has meant that in all screen modes on the Agon the vertical conversion factor for the Y dimensions is _never_ a round number, and will always includes a fraction. 101 | -------------------------------------------------------------------------------- /docs/Third-Party-Projects.md: -------------------------------------------------------------------------------- 1 | # Third Party Projects 2 | 3 | Please note that this list is _far_ from exhaustive. If you have a project that you would like to add to this list, please submit a pull request. 4 | 5 | 6 | ## Popup MOS 7 | 8 | [https://github.com/tomm/popup-mos](https://github.com/tomm/popup-mos) 9 | 10 | A batteries-included SDCard template for Agon Light / Agon Light 2 / Console8 11 | 12 | ## Flash Updater 13 | 14 | [https://github.com/envenomator/agon-flash](https://github.com/envenomator/agon-flash) 15 | 16 | A utility to flash a MOS image to the eZ80F92 Flash without a ZDS USB cable, and to update the VDP firmware. 17 | 18 | ## Hex Loader 19 | 20 | [https://github.com/envenomator/agon-hexload](https://github.com/envenomator/agon-hexload) 21 | 22 | Playing microSD jockey during assemble/compile/transfer/test/debug cycles is no fun at all. This utility shortens this cycle significantly by removing the need to physically bring over new binaries to the Agon. 23 | 24 | With the hexload command you are able to transmit Intel I32 hex files to one of the Agon serial ports and run your code immediately from memory. 25 | 26 | ## eZ80 Assembler 27 | 28 | [https://github.com/envenomator/agon-ez80asm](https://github.com/envenomator/agon-ez80asm) 29 | 30 | A fully-featured eZ80 assembler that runs on the Agon. 31 | 32 | ## Forth Interpreter 33 | 34 | [https://github.com/lennart-benschop/agon-forth](https://github.com/lennart-benschop/agon-forth) 35 | 36 | ## Agon Utilities 37 | 38 | [https://github.com/lennart-benschop/agon-utilities](https://github.com/lennart-benschop/agon-utilities) 39 | 40 | A selection of handy utilities including copy, compare, more, memfill, font, and a full-screen editor with nano-style key bindings. 41 | 42 | ## Sokoban 43 | 44 | [https://github.com/envenomator/agon-sokoban](https://github.com/envenomator/agon-sokoban) 45 | 46 | Sokoban game for AGON 47 | 48 | -------------------------------------------------------------------------------- /docs/Updating-Firmware.md: -------------------------------------------------------------------------------- 1 | # Updating the Agon Firmware 2 | 3 | When new versions of the Agon firmware are released, you will need to update your Agon machine to take advantage of the new features and bug fixes. All models of Agon machines to date can run the latest versions of the Agon platform firmware. This includes the original Agon Light, the Olimex Agon Light 2, the Agon Console8, and the Agon Light Origins Edition. 4 | 5 | The Agon firmware is made up of two components: 6 | 7 | - The Agon MOS (the operating system, which runs on the eZ80 CPU) 8 | - The VDP (the graphics chip, which runs on the ESP32) 9 | 10 | These two components are updated separately. The exact steps to update your Agon will depend on the versions of the firmware your Agon is currently running. 11 | 12 | !!! danger "Attention" 13 | 14 | Before you continue, please note that if your Agon is running a version of MOS before 1.03, or a version of the VDP before 1.04RC3, then the upgrade process is a little different. It is important that you follow the guidance that can be found [below](#update-old). Failing to do so may result in your Agon becoming unusable. [Recovery tools](#recovery) are available to restore your Agon to a working state, but it is best to avoid needing them in the first place. 15 | 16 | The primary tool to update the firmware on your Agon is the [Agon firmware update utility](https://github.com/AgonPlatform/agon-flash), otherwise known as "agon-flash". This tool runs on your Agon, and can be used to update both MOS and the VDP so long as they are already running compatible versions. The latest version of the this tool can be [downloaded here](https://github.com/AgonPlatform/agon-flash/releases/latest). 17 | 18 | Updating the VDP firmware can also be done using the online [Agon VDP installer](#vdp-installer). Many users find this to be the easiest way to update the VDP firmware. 19 | 20 | ## How to use the Agon firmware update utility 21 | 22 | The Agon firmware update utility is run on your Agon, and needs to be installed onto the SD card you use with your Agon. That SD card must be formatted as FAT32. 23 | 24 | 1. Make sure to create a **mos** directory on the microSD card, if it's not already present. 25 | 2. Place the [flash.bin](https://github.com/AgonPlatform/agon-flash/releases/latest/download/flash.bin) in the **mos** directory 26 | 3. Place the firmware files in the **root** directory of the microSD card: 27 | - MOS firmware - default filename 'MOS.bin' (download [latest](https://github.com/AgonPlatform/agon-mos/releases/latest/download/MOS.bin) version) 28 | - VDP firmware - default filename 'firmware.bin' (download [latest](https://github.com/AgonPlatform/agon-vdp/releases/latest/download/firmware.bin) version) 29 | 30 | Once you have installed the Agon firmware update utility, and ensured that you have the latest firmware files on your SD card, it can be used to update the firmware on your Agon. 31 | 32 | As noted above, to update MOS using this tool, your Agon must be running at least MOS 1.03. If you are running an older version of MOS, you will need to use the older method of updating MOS. See [below](#update-old) for more details. 33 | 34 | To upgrade MOS, you can use the following command from the MOS command line: 35 | 36 | ``` 37 | *flash mos MOS.bin 38 | ``` 39 | 40 | Updating the VDP using this tool requires a version of the VDP firmware that supports the update process. This is VDP 1.04RC3 or later. If you are running an older version of the VDP, you will need to use the older method of updating the VDP. See [below](#update-old) for more details. 41 | 42 | To upgrade the VDP, you can use the following command from the MOS command line: 43 | 44 | ``` 45 | *flash vdp firmware.bin 46 | ``` 47 | 48 | The update process will take a few seconds, and you will be asked to confirm that you wish to flash a new version of your firmare. Once you press "Y" to confirm the update process will begin, and the Agon will reboot automatically once it is complete. 49 | 50 | On rare occasions the Agon may not reboot automatically - you may see the countdown, but then be left on the update screen. If this happens, just press the "reset" button on the Agon to reboot it, or switch your Agon off and back on. 51 | 52 | When asking for confirmation, the tool will display a CRC checksum for the file you are about to install; we no longer publish the checksums for firmware files, as in general we found that most people did not find this useful. (Older versions of the flash tool would require you to manually enter the CRC number as part of the flash command which users found frustrating as it was easy to make mistakes when typing in the checksum.) Should you wish to verify the checksum of the firmware you are about to install you can generate a CRC32 checksum for the firmware file on your desktop computer using a tool such as `crc32`. 53 | 54 | ### Issues with updating from some Agon VDP firmware releases using the Agon firmware update utility 55 | 56 | There have been three releases of the Agon VDP firmware that unfortunately contained a bug that prevented the Agon firmware update utility from working correctly. These releases are: 57 | 58 | * VDP 2.8.0 59 | * VDP 2.12.0 60 | * VDP 2.13.0 61 | 62 | 63 | 64 | ## How to use the online Agon VDP installer {#vdp-installer} 65 | 66 | The online [Agon VDP installer](https://envenomator.github.io/) is a web-based tool that allows you to update the VDP firmware on your Agon without needing to download and install the Agon firmware update utility. 67 | 68 | The online Agon VDP installer will work with any Agon machine, running any firmware version. Please note though that you should not use this tool unless you are running at least MOS 1.03 - if you are running an older version of MOS then it is very important to [update that first](#update-old). 69 | 70 | There are two pre-requisits to using this tool. 71 | 72 | 1. You must be using a web browser that includes "Web Serial" support, which includes Google Chome/Chromium, Microsoft Edge, and Opera 73 | 2. Your Agon must be connected to your PC (or Mac) using a USB data cable. The type of USB cable may differ according to the Agon platform you're using: 74 | - the original Agon Light has a USB-A type connector * 75 | - the Olimex Agon Light 2 has a USB-C type connector 76 | - the Agon Console8 has a USB-B type connector 77 | - the Agon Origins edition has a USB-B type connector 78 | 79 | \* The original Agon Light's use of a USB-A connector can cause some problems, as a USB-A to USB-A cable is not a standard cable. If your PC has a USB-C connector you may be able to use a USB-A to USB-C cable. 80 | 81 | Many people power their Agon via the Agon's USB connector. If you do so by plugging your Agon in to one of your PC's USB ports, so long as your cable is a data cable and not a power-only cable, you should already be able to use the Agon VDP installer. If you are using a power-only cable, you will need to use a different cable. 82 | 83 | Using the online installer is very simple. Just visit the installer, select the latest version of the VDP firmware, and click on the update button. Once the update is complete, the Agon will reboot automatically. 84 | 85 | ## Upgrading from older firmware versions {#update-old} 86 | 87 | If your Agon is running older versions of the firmware then you will need to follow a different process to update your Agon. This is because versions of MOS before 1.03 and the VDP before 1.04RC3 do not support the current Agon firmware update utility. 88 | 89 | In general, the simplest way to update your Agon is to follow these two steps: 90 | 91 | 1. Update MOS to the latest version using the [Agon legacy firmware update utility](https://github.com/AgonPlatform/agon-flashlegacy) 92 | 2. Update your VDP firmware to the latest version using the online [Agon VDP installer](https://envenomator.github.io/) 93 | 94 | It is very important that you update MOS first, as there was a change in how MOS and the VDP communicated in early firmware versions. If you try to update the VDP first then you will not be able to run the Agon legacy firmware update utility, and you will not be able to update MOS. 95 | 96 | After updating MOS you may find that your Agon appears to not be working properly. It may fail to start up completely, it might only show the VDP version line, or it may appear to boot but not respond to keyboard input. This is normal, and is expected behaviour. Once you have updated the VDP firmware, your Agon will work properly again. 97 | 98 | ## Other options for updating your VDP firmware 99 | 100 | If for some reason you are unable to use the online Agon VDP installer, and you are unable to use the Agon firmware update utility, then there are two remaining options for updating your VDP firmware. Please note that neither of these options are recommended, and you should only use them as a last resort. 101 | 102 | Both of these options require that your Agon is connected to your PC using a USB data cable. 103 | 104 | ### Using PlatformIO 105 | 106 | The Agon VDP firmware can be built from its [source code](https://github.com/AgonPlatform/agon-vdp) using the [PlatformIO IDE](https://platformio.org) extension to [Microsoft Visual Studio Code](https://code.visualstudio.com). This approach is how the firmware is developed, and built for release. 107 | 108 | You will need to download the source code, either by cloning the repository using `git`, or by downloading the source code as a ZIP file and extracting it. When you open up the source code in Visual Studio Code then from the PlatformIO extension under "Project Tasks > esp32dev > General" you can select "Upload" to build and upload the firmware to your Agon. 109 | 110 | If you are not comfortable with using developer tools this is probably not the best option for you. 111 | 112 | ### Using other tools 113 | 114 | Guidance on using other tools can be [found here](https://github.com/envenomator/envenomator.github.io). 115 | 116 | In general these tools are not recommended for use by end users, as they are not very user friendly. 117 | 118 | ## Recovery 119 | 120 | Usually updating your Agon firmware will go smoothly, and you will not have any problems. 121 | 122 | The process of updating the VDP firmware is designed to be as simple and robust as possible, and is designed to be able to recover from all problems. The VDP actually keeps two copies of its firmware installed, and so in the rare event that something does go wrong when updating the VDP firmware the VDP simply won't switch to the new firmware. This means that you can safely update your Agon without worrying. In the incredibly rare event that this does not work then the [online Agon VDP installer](https://envenomator.github.io/) can be used to install the latest VDP firmware. 123 | 124 | It is not possible to make the upgrade process for MOS quite as robust, as it cannot keep two copies of the firmware installed. There is however an [Agon recovery utility](https://github.com/AgonPlatform/agon-recovery) available. 125 | 126 | Full guidance on using the recovery utility is [found here](https://github.com/AgonPlatform/agon-recovery#readme). 127 | 128 | The guidance will let you know that if you have an Agon Light, Agon Light 2, or Agon Light Origins Edition, then as well as connecting your Agon to your PC via a USB data cable you will also need two dupont female-to-female cables to make some connections between the ports on your Agon. The whole process including which connections to make are clearly described. 129 | 130 | If you have an Agon Console8 then recovery is a little more complex. You will need an external ESP32 to perform the recovery. Most ESP32 devkits will do fine for this purpose (there are lots of options, are widely available, and can be bought for less than $5 on AliExpress), or if you have another Agon Light system available that can also be used as a programmer for the Agon Console8. The recovery process is a little more complex, but is still well documented. 131 | 132 | ## Getting help 133 | 134 | If you have any problems with updating your Agon firmware, or if you have any questions, please feel free to ask for help in the [Agon & Console8 Community Discord server](https://discord.gg/sN3vXru26s). 135 | -------------------------------------------------------------------------------- /docs/VDP.md: -------------------------------------------------------------------------------- 1 | # What is the VDP 2 | 3 | The VDP is the Agon's Visual Display Processor. It is responsible for: 4 | 5 | * Video output via the VGA connector 6 | * Audio output via the built-in buzzer and audio jack 7 | * Keyboard input via a PS/2 connector 8 | * Mouse input via a PS/2 connector (on the Agon Console8, or with an adapter on the Agon Light) 9 | 10 | It runs on the ESP32-Pico-D4 co-processor and uses a fork of the FabGL library (known as vdp-gl) to support those functions. 11 | 12 | At a higher level, its input is a byte stream from the eZ80F92 main CPU over an internal high-speed UART connection @ 1,152,000 baud (384,000 baud for versions of MOS/VDP prior to 1.03). This stream contains a mixture of text and control characters. These control characters are mapped to the BBC BASIC VDU control characters, a choice made as BBC BASIC for Agon is the pre-installed programming language of Agon. As a result, we refer to the commands that the VDP understands as VDU commands. 13 | 14 | The ESP32 also outputs data back to the eZ80F92, for example keyboard data and screen information via a custom serial protocol. 15 | 16 | ## Executing a VDU sequence 17 | 18 | ### From BBC BASIC 19 | 20 | The `VDU` statement in BBC BASIC essentially just means "send this data to the VDP". It will accept any number of integer arguments between 0 and 255, separated by commas. If a value is immediately followed by a semicolon `;` instead of a comma then the value is a little-endian word from 0 to 65535. 21 | 22 | Example: 23 | 24 | `VDU 25, 69, 640; 512;`: Plot a dot in the center of the screen 25 | 26 | `VDU 65`: Print the letter "A", without a newline 27 | 28 | A single `VDU` statement in BASIC can potentially contain multiple commands for the VDP to interpret, or a VDU command could instead be split across multiple `VDU` statements. Other BASIC keywords that generate screen output are effectively just wrappers for VDU command sequences. 29 | 30 | For example, the following code snippets are all directly equivalent, and result in an identical command stream being sent to the VDP: 31 | 32 | ``` 33 | PLOT 69, 640, 512 34 | PRINT "A"; 35 | ``` 36 | ``` 37 | VDU 25, 69, 640; 512; 65 38 | ``` 39 | ``` 40 | VDU 25 41 | VDU 69 42 | VDU 640; 512; 43 | VDU ASC("A") 44 | ``` 45 | ``` 46 | VDU 25, 69, 128, 2, 0, 2, 65 47 | ``` 48 | 49 | ### From MOS command line (Version 1.03 or greater) 50 | 51 | MOS also supports a VDU command which can be used to send VDU commands to the VDP. This is useful for testing the VDP without having to write a BASIC program. Its command is simpler than the BASIC equivalent, accepting only 8-bit integer values between 0 and 255, separated by spaces. 52 | 53 | Example: 54 | 55 | `VDU 17 15`: Set the text foreground colour to 15 56 | 57 | As of MOS 2.2.0, the `VDU` command is now more sophisticated and can support sending 16-bit values as well as 8-bit values. More information can be found in the [MOS documentation](MOS.md). 58 | 59 | ### From Assembly code on MOS 60 | 61 | MOS offers two ways to send VDU commands from assembly code. The first is to use the `RST 10h` call, which will send the byte in the A register to the VDP. The second is to use a `RST 18h` call which is used to send multiple bytes to the VDP at once. (Neither of these calls require the string `VDU` to be included in the data sent to the VDP, and both require raw binary values to be sent, rather than an ASCII string.) 62 | 63 | More information about these can be found in the [MOS API documentation](mos/API.md#rst). 64 | 65 | 66 | ## VDU Character Sequences 67 | 68 | The aim is that the Agon's VDP should be as compatible as practical with the BBC Micro's VDU command, as well as the VDU commands supported by later versions of Acorn and R.T.Russell's BBC BASICs. Where necessary, some extensions have been added to help facilitate the Agon's unique features and architecture. 69 | 70 | For a more detailed description of VDU commands supported by the Agon's VDP, see [VDU Commands](vdp/VDU-Commands.md). 71 | 72 | The following is a high-level list of the VDU sequences that are supported: 73 | 74 | - `VDU 0`: Null (no operation) 75 | - `VDU 1`: Send next character to "printer" (if "printer" is enabled) §§ 76 | - `VDU 2`: Enable "printer" §§ 77 | - `VDU 3`: Disable "printer" §§ 78 | - `VDU 4`: Write text at text cursor 79 | - `VDU 5`: Write text at graphics cursor 80 | - `VDU 6`: Enable screen (opposite of `VDU 21`) §§ 81 | - `VDU 7`: Make a short beep (BEL) 82 | - `VDU 8`: Move cursor back one character 83 | - `VDU 9`: Move cursor forward one character 84 | - `VDU 10`: Move cursor down one line 85 | - `VDU 11`: Move cursor up one line 86 | - `VDU 12`: Clear text area (`CLS`) 87 | - `VDU 13`: Carriage return 88 | - `VDU 14`: Page mode On * 89 | - `VDU 15`: Page mode Off * 90 | - `VDU 16`: Clear graphics area (`CLG`) 91 | - `VDU 17, colour`: Define text colour (`COLOUR`) 92 | - `VDU 18, mode, colour`: Define graphics colour (`GCOL mode, colour`) 93 | - `VDU 19, l, p, r, g, b`: Define logical colour (`COLOUR l, p` / `COLOUR l, r, g, b`) 94 | - `VDU 20`: Reset palette and text/graphics colours and drawing modes §§ 95 | - `VDU 21`: Disable screen (turns of VDU command processing, except for `VDU 1` and `VDU 6`) §§ 96 | - `VDU 22, n`: [Select screen mode](vdp/Screen-Modes.md) (`MODE n`) 97 | - `VDU 23, n`: Re-program display character / System Commands 98 | - `VDU 24, left; bottom; right; top;`: Set graphics viewport ** 99 | - `VDU 25, mode, x; y;`: [PLOT command](vdp/PLOT-Commands.md) 100 | - `VDU 26`: Reset graphics and text viewports ** 101 | - `VDU 27, char`: Output character to screen § 102 | - `VDU 28, left, bottom, right, top`: Set text viewport ** 103 | - `VDU 29, x; y;`: Set graphics origin 104 | - `VDU 30`: Home cursor 105 | - `VDU 31, x, y`: Move text cursor to x, y text position (`TAB(x, y)`) 106 | - `VDU 127`: Backspace 107 | 108 | All other characters, i.e. those in the range of 32 to 126 and 128 to 255, are sent to the screen as ASCII, unaltered. 109 | 110 | Any VDU command that is the VDP does not recognise (such as `VDU 2` when running on Quark 1.04) will be ignored. 111 | 112 | \* Requires VDP 1.03 or above
113 | \** Requires VDP 1.04 or above
114 | § Requires Console8 VDP 2.3.0 or above
115 | §§ Requires Console8 VDP 2.5.0 or above
116 | 117 | 118 | ## VDU 23 commands 119 | 120 | `VDU 23` essentially has a split purpose. The first is to redefine the system font display characters, and the second is to send commands to the VDP to control and access more sophisticated behaviour. 121 | 122 | For more information on these commands and a full list, please consult the `VDU 23` section of the [VDU Commands](vdp/VDU-Commands.md) document. This includes the [Bitmap and Sprite API](vdp/Bitmaps-API.md). 123 | 124 | Amongst this you will also find [system commands](vdp/System-Commands.md), which start with `VDU 23, 0`, most of which are unique to the Agon platform. Within the system commands set you will find the [Audio API](vdp/Enhanced-Audio-API.md), [Buffered Commands API](vdp/Buffered-Commands-API.md), [Font API](vdp/Font-API.md), and [Context Management API](vdp/Context-Management-API.md). 125 | 126 | 127 | -------------------------------------------------------------------------------- /docs/assets/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AgonPlatform/agon-docs/1bfd21a87191442627f7168a251648bba16a8f17/docs/assets/favicon.png -------------------------------------------------------------------------------- /docs/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AgonPlatform/agon-docs/1bfd21a87191442627f7168a251648bba16a8f17/docs/assets/logo.png -------------------------------------------------------------------------------- /docs/images/agon_gpio_pinouts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AgonPlatform/agon-docs/1bfd21a87191442627f7168a251648bba16a8f17/docs/images/agon_gpio_pinouts.png -------------------------------------------------------------------------------- /docs/images/hexload.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AgonPlatform/agon-docs/1bfd21a87191442627f7168a251648bba16a8f17/docs/images/hexload.png -------------------------------------------------------------------------------- /docs/images/io_origins.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AgonPlatform/agon-docs/1bfd21a87191442627f7168a251648bba16a8f17/docs/images/io_origins.png -------------------------------------------------------------------------------- /docs/images/io_uext.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AgonPlatform/agon-docs/1bfd21a87191442627f7168a251648bba16a8f17/docs/images/io_uext.png -------------------------------------------------------------------------------- /docs/images/iopinsAL1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AgonPlatform/agon-docs/1bfd21a87191442627f7168a251648bba16a8f17/docs/images/iopinsAL1.png -------------------------------------------------------------------------------- /docs/images/iopinsAL2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AgonPlatform/agon-docs/1bfd21a87191442627f7168a251648bba16a8f17/docs/images/iopinsAL2.png -------------------------------------------------------------------------------- /docs/images/iopinsC8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AgonPlatform/agon-docs/1bfd21a87191442627f7168a251648bba16a8f17/docs/images/iopinsC8.png -------------------------------------------------------------------------------- /docs/images/jumpers.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AgonPlatform/agon-docs/1bfd21a87191442627f7168a251648bba16a8f17/docs/images/jumpers.webp -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | # Welcome to the community Agon Platform documentation 2 | 3 | This is the community-driven documentation for the Agon Platform, covering the Agon Light, Olimex Agon Light 2, and the Agon Console8 hobbyist computers. It is intended to be a comprehensive guide to the Agon Platform, including Agon MOS and VDP firmware, and the hardware and software that it supports. It is intended to provide a guide to all of the features of the Agon platform with guidance on how to program for it, with information on the various features provided by different versions of the firmware. 4 | 5 | This site is intended to supercede the official documentation, and to provide a more comprehensive and up-to-date guide to the Agon Platform. It is intended to be a living document, and to be updated as new features are added to the platform. 6 | 7 | The original documentation for Quark firmware can be found [here](https://github.com/breakintoprogram/agon-docs/wiki). This community documentation was started because GitHub's wiki system does not allow easy contributions by users, and the original documentation contains some errors and omissions. We don't use the wiki here, but just markdown files which are also automatically generated into a [website](https://agonplatform.github.io/agon-docs/). 8 | 9 | ## Want to contribute? 10 | 11 | Great, please go to the [github repository](https://github.com/AgonPlatform/agon-docs) and create a Pull Request with your changes. 12 | 13 | ## What is the Agon Light, and what is the Agon Console8 14 | 15 | The Agon Light is a modern, fully open-source, 8-bit microcomputer and microcontroller in one small, low-cost board, designed by Bernado Kastrup aka The Byte Attic. As a computer, it is a standalone device that requires no host PC: it puts out its own video (VGA), audio (2 identical mono channels), accepts a PS/2 keyboard and has its own mass-storage in the form of a µSD card. The Olimex Agon Light 2 and the Agon Light Origins edition are variations on the original Agon Light design. 16 | 17 | The Agon Console8 is a version of the Agon Light that also includes two Atari-compatible joystick ports, and a PS/2 mouse port, and a stylish case. It was also designed by Bernado Kastrup aka The Byte Attic, and is manufactured by Heber Ltd. 18 | 19 | The Agon Light, Olimex Agon Light 2, and the Agon Console8 are all fully compatible with each other. Software written for one will run on the other, and the same firmware can be used on both. In this documentation, generally, the term "Agon Light" is used to refer to all variations. 20 | 21 | The main CPU is an eZ80F92, a modern Zilog Z80 microcontroller that is fully backwards compatible with the Z80. As well as running in a traditional 8-bit mode with a 64K address space, it can run in 24-bit mode with a 16MB address space, and is also capable of running in a hybrid mode with a mixture of 24-bit and 8-bit code. 22 | 23 | The eZ80F92 integrates a number of standard peripherals, including a UART, and hardware timers. 24 | 25 | There is a second CPU dedicated to handling video, sound, and keyboard, an ESP32-Pico-D4. This co-processor is linked to the eZ80F92 via a UART (a high speed serial communications link), and acts as a graphics terminal. 26 | 27 | ## What is the Agon Platform Firmware 28 | 29 | The Agon Platform firmware is the software that runs on the Agon Light, Olimex Agon Light 2, and the Agon Console8. It is responsible for managing the hardware, providing a programming environment, and running applications. It consists of three main components: 30 | 31 | * [MOS](MOS.md): Machine Operating System 32 | * [VDP](VDP.md): Visual Display Processor 33 | * [BBC BASIC for Agon](BBC-BASIC-for-Agon.md): A specially adapted port of R.T.Russell's excellent BASIC interpreter 34 | 35 | ### What is Agon Quark? 36 | 37 | Agon Quark is the name of the original firmware for the Agon Light, and is now deprecated. The Agon Platform firmware versions are the latest available for your Agon platform computer. 38 | 39 | ## How can I find out more? 40 | 41 | The following documents provide some more information 42 | 43 | * [Agon Platform theory of operation](Theory-of-operation.md) 44 | * [External documentation](External-Documentation.md) 45 | * [Using GPIO](GPIO.md) 46 | * [The Agon Projects github](Projects.md) 47 | * [Third party projects](Third-Party-Projects.md) 48 | * [FAQ](FAQ.md) 49 | 50 | ## Where can I buy one? 51 | 52 | - [Mouser](https://www.mouser.com/ProductDetail/Olimex-Ltd/AgonLight2?qs=9vOqFld9vZWAIti5ng59Vw%3D%3D) 53 | - [The Pi Hut](https://thepihut.com/products/agonlight2-z80-bbc-basic-retro-single-board-computer) 54 | - [Olimex Ltd](https://www.olimex.com/Products/Retro-Computers/AgonLight2/open-source-hardware) 55 | - [DigiKey](https://www.digikey.com/en/products/detail/olimex-ltd/AGONLIGHT2/19204345) 56 | - [PCBWay](https://www.pcbway.com/project/gifts_detail/Agon_light_3f7ffaa8.html) 57 | - [Agon Light Australia](https://agonlight.au) 58 | - [Agon Light Store (UK)](http://agon-light.store) 59 | - [Agon Console8 from Heber (UK)](https://shop.heber.co.uk/agon-console8/) 60 | -------------------------------------------------------------------------------- /docs/mos/Argument-Substitution.md: -------------------------------------------------------------------------------- 1 | # Argument substitution 2 | 3 | Several features in MOS have support for "argument substitution". This includes how the system handles [aliases](System-Variables.md#command-aliases), [hotkeys](System-Variables.md#hotkeys), [loading/running files with given file extensions](System-Variables.md#file-type-variables), and [running Obey files](Star-Commands.md#obey). 4 | 5 | Argument substitution is used by MOS as a way to insert arguments into a new command. Essentially, a source string is defined which includes placeholder tokens for arguments to be inserted into. When the command is executed, the system will replace these tokens with the actual arguments that were passed to the command. 6 | 7 | Before MOS 3 the only command that supported argument substitution was the [`Hotkey` command](Star-Commands.md#hotkey). It would only support a single form of substitution token in the given command string in the form of `%s`, which would insert the whole of the current input line at that point. This has changed in MOS 3 where the system now supports a more flexible form of argument substitution. 8 | 9 | From MOS 3 onwards, arguments substitution is done by using the `%` character followed by a number from 0-9 to specify which argument to insert. These are arguments are taken from the original command. For instance, `%0` will be replaced by the first argument to the command, `%1` will be replaced by the second argument, and so on. If you want to include a literal `%` character in the command, you can escape it by using `%%`. You can also use `%*` to insert all arguments starting from a particular numbered argument into the command. For example, `%*2` will insert all arguments from the second argument onwards. For backwards compatibility, `%s` is still supported, and is equivalent to `%*0`. 10 | 11 | Arguments can be wrapped with double-quote characters `"` to allow for arguments that contain spaces. 12 | 13 | Arguments may also be used multiple times in the command string. For example, the command `*set Alias$DoubleEcho echo %0 %0` will create a command alias called `DoubleEcho` that will echo the first argument twice, so performing the command `*DoubleEcho hello` would produce the output `hello hello`. 14 | 15 | Command aliases, including file load/run types, will automatically append any arguments beyond the last used argument to the end of the resultant command. 16 | 17 | Creating a command alias with the name of an existing command allows you to override that command, changing how it works. The original command can still be used by prefixing the command with a `%` character, as prefixing a command with `%` causes alias-resolution to be skipped. An example of where you might wish to do this is to set the `Dir` command to display the directory by default in long format, rather than short form. This can be achieved with `*set Alias$Dir %dir -l %0`. If you omit the `%` character here before the `dir` command, the system will attempt to recursively call the alias, and you will get a `Too deep` error. 18 | 19 | Prefixing aliases with the `%` character to skip alias resolution can be useful in script files to help ensure that you are definitely using the original command, rather than an alias that another script may have set up. 20 | 21 | The argument substitution system in MOS 3 is available for use by programs through the [`mos_substituteargs` API call](./API.md#0x35-mos_substituteargs). Whilst this is commonly used to construct commands, it can be used for other purposes too. At its core, argument substitution is a simple text replacement system, and can be used for any purpose where you need to insert text into a string. It takes a template string, a separate string for the arguments, and a buffer to write the resultant string to where placeholders in the template string have been replaced with sub-strings taken from the arguments. 22 | -------------------------------------------------------------------------------- /docs/mos/C-Functions.md: -------------------------------------------------------------------------------- 1 | # Using MOS C functions 2 | 3 | MOS 3.0 added a new API, [mos_getfunction](./API.md#0x50-mos_getfunction), which allows programs to get the address of various C functions. These functions comply with the Zilog eZ80 C calling conventions. 4 | 5 | As MOS already provides an extensive API, the range of C functions this API provides is limited. There are essentially three potential reasons why a function has been made available via this API: 6 | 7 | 1. The function cannot be made available via a traditional MOS API 8 | 2. The equivalent MOS API is difficult to use from programs written in C (in general because it uses the `IX(U)` register) 9 | 3. Direct access to the function may be useful for efficiency reasons 10 | 11 | It is important to note that these functions are only accessible to programs written to run in the eZ80's ADL mode. Z80 mode programs cannot use the `mos_getfunction` API, and would not be able to use these functions even if they could, as the calling convention is not compatible with Z80 mode code. 12 | 13 | The complete list of functions available from the `mos_getfunction` API is provided in the [MOS C functions](#functions) section below. 14 | 15 | ## The C function calling convention 16 | 17 | Zilog's documentation for their C function calling convention is described in a document with the very catchy name [ZDS II for eZ80Acclaim!: Calling C Functions from Assembly and Vice Versa](https://www.zilog.com/docs/appnotes/an0333.pdf). This document is essentially an edited except from the "ZiLOG Developer Studio II eZ80Acclaim!® User Manual" with some additional examples. 18 | 19 | When considering function pointers returned by the `mos_getfunction` API the notes around function naming conventions in Zilog's documentation are not really important. 20 | 21 | If you are using these functions from a C program, assuming your compiler understands the Zilog eZ80 C calling convention (which is currently true for all C compilers for the Agon platform) you will need to let your compiler know the function prototype. 22 | 23 | The underlying details of how the C function calling convention works should not be important to you if you are only using these functions from C. You can skip ahead to the descriptions of the [functions available](#functions) from the `mos_getfunction` API. 24 | 25 | However if you are using these functions from assembly then you will need to understand how the calling convention works. 26 | 27 | ### Passing parameters to functions 28 | 29 | Function parameters are passed on the stack in reverse order, i.e. the rightmost parameter is pushed first, and the leftmost parameter is pushed last. The leftmost argument is therefore at the top of the stack when the function is called. 30 | 31 | After a function call, the caller is responsible for cleaning up the stack. This means that the caller must remove the arguments from the stack after the function has returned. 32 | 33 | Arguments of different types are always a multiple of 3 bytes in size, essentially because the eZ80's registers are 3 bytes wide in ADL mode. As most variable types are not a multiple of 3 bytes in size, some bytes pushed to the stack will be ignored by functions that take arguments of those types. C compilers that support the eZ80 C calling convention will automatically understand this and ignore any extra padding bytes on the stack when handling function arguments. For example, a `char` type is 1 byte in size, and will be padded to 3 bytes when passed to a function. The compiler will automatically ignore the extra 2 bytes. 34 | 35 | The following table provides a guid the types of arguments that can be passed to functions, their size, and how they are arranged in memory on the stack. As type names can vary, the table may show various common names used for the same underlying type, and is not exhaustive. For example the table does not list `int8_t`, `unsigned char` or `BYTE`, as they are essentially equivalent to `char` and `uint8_t`. The "memory" column shows how the values are arranged from the least significant byte to the most significant byte. It is always a multiple of 3 bytes, with each individual value byte shown as `xx`; bytes that will be ignored by the function are shown as `??`. 36 | 37 | | Type | Native Size | Size on stack | Memory (Low to high) | 38 | |------|-------------|---------------|----------------------| 39 | | `char`/`uint8_t` | 1 byte | 3 bytes | `xx ?? ??` | 40 | | `short`/`uint16_t` | 2 bytes | 3 bytes | `xx xx ??` | 41 | | `int`/`uint24_t` | 3 bytes | 3 bytes | `xx xx xx` | 42 | | `long`/`uint32_t` | 4 bytes | 6 bytes | `xx xx xx xx ?? ??` | 43 | | `long long`/`uint64_t` | 8 bytes | 9 bytes | `xx xx xx xx xx xx xx xx ??` | 44 | | `float` | 4 bytes | 6 bytes | `xx xx xx xx ?? ??` | 45 | | `double` | 4 bytes | 6 bytes | `xx xx xx xx ?? ??` | 46 | | `void *` (any pointer) | 3 bytes | 3 bytes | `xx xx xx` | 47 | 48 | * as noted above, the types in this table are not exhaustive, and similar types of the same length/size will be treated the same way 49 | * `uint24_t` is not part of the C standard, but may be supported by some compilers that support the eZ80. As the eZ80 includes several 24-bit registers when in ADL mode, this is also the default integer `int` type used by these compilers. 50 | * the Zilog C compiler does not support the `long long`/`uint64_t` type, and this is not part of their C calling convention standard, but it is a common extension that other compilers for the eZ80 supports. This type is not currently used by any of the functions available from the `mos_getfunction` API, but is included for completeness. 51 | * owing to constraints of the eZ80 architecture, both `float` and `double` are IEEE-754 single precision 32-bit floating point values by compilers that target the eZ80. 52 | 53 | ### Calling C functions from assembly 54 | 55 | As values are passed to functions using the stack, the process of calling a C function from assembly is generally to push arguments in reverse order. As noted above, all arguments must be a multiple of 3 bytes in size; the nature of the eZ80 when running in ADL mode is that as you can only push wide registers to the stack you will always push 3-bytes to the stack. This means that if you have an 8-bit value in an 8-bit register for an 8-bit argument (e.g. a `BYTE` or a `char`), you just need to ensure the value is in the least signficant register of a 3-byte register, and then push that register to the stack. The other two bytes will be ignored by the function. 56 | 57 | The `mos_getfunction` API returns a pointer to the requested function in the `HLU` register. In principle your program needs to "call" this function, but the eZ80 does not have a version of the `CALL` instruction that can use a register as the address to call. There is, however, a `JP (HL)` instruction. There is more than one way to use this instruction to "call" a function, but the simplest is probably the following: 58 | 59 | ```Z80 60 | ; Call a function pointer in HL 61 | ; use `CALL call_HL` to call the function, ensuring return address is pushed 62 | .call_HL JP (HL) 63 | ``` 64 | 65 | With this in place, to call a function provided from the `mos_getfunction` API from eZ80 assembler code, you would do the following: 66 | 67 | 1. Push the arguments to the stack in reverse order 68 | 2. Ensure that the `HLU` register contains the address of the function to call 69 | 3. Perform a `CALL call_HL` instruction to push the return address onto the stack 70 | 4. Execution continues after that call, with the return value set as per the calling convention 71 | 5. Pop arguments off the stack 72 | 73 | Step 2 here could be a call to `mos_getfunction` at that point in the process, or that could be done earlier in your program. Please note however that there may in future be some [issues with caching function pointers](#modules) when [MOS Modules](./Modules.md) so please read the guidance below. 74 | 75 | ### Return values 76 | 77 | The return value from a function will be placed in one or more of the eZ80's registers. 78 | 79 | Exactly which registers are used depends on the type of the value returned. The following table shows how different types of return values are returned. As with the table above for arguments, the types in this table are not exhaustive, and similar types of the same length/size will be treated the same way. Some types are returned across multiple registers; the table below illustrates register contents from the most significant byte to the least significant byte. 80 | 81 | | Type | Return registers | Register contents | 82 | |------|------------------|------------------- 83 | | `char`/`uint8_t` | `A` | `xx` | 84 | | `short`/`uint16_t` | `HLU` | `?? xx xx` | 85 | | `int`/`uint24_t` | `HLU` | `xx xx xx` | 86 | | `long`/`uint32_t` | `E:HLU` | `xx: xx xx xx` | 87 | | `long long`/`uint64_t` | `BC:DEU:HLU` | `?? xx xx: xx xx xx: xx xx xx` | 88 | | `float` | `E:HLU` | `xx: xx xx xx` | 89 | | `double` | `E:HLU` | `xx: xx xx xx` | 90 | | `void *` (any pointer) | `HLU` | `xx xx xx` | 91 | 92 | * as noted above, the types in this table are not exhaustive, and similar types of the same length/size will be treated the same way 93 | * as with the argument table, `uint24_t` is not part of the C standard, and the `int` type is a 24-bit value 94 | * as with the argument table, `long long`/`uint64_t` is not part of the Zilog C calling convention standard, but is a common extension that other compilers for the eZ80 supports. This type is not currently used by any of the functions available from the `mos_getfunction` API, but is included for completeness. 95 | 96 | ## Functions available from the `mos_getfunction` API {#functions} 97 | 98 | The following functions are available from the [`mos_getfunction`](./API.md#0x50-mos_getfunction) API. 99 | 100 | It should be noted that that whilst MOS APIs will return `FRESULT` or "status" values in the 8-bit `A` register, most of the underlying functions return an `FRESULT` or an `int` for their status, which are actually 24-bit values. The calling convention means they will be returned in `HL(U)`. 101 | 102 | This list is complete as of the MOS 3.0 release, but may change in future releases of MOS to include additional functions. 103 | 104 | ### 0x00 - `BYTE SD_init();` 105 | 106 | Initialises the low-level SD card handling system 107 | 108 | ### 0x01 - `BYTE SD_readBlocks(DWORD sector, BYTE *buf, WORD count);` 109 | 110 | Read raw sector data from SD card. 111 | 112 | `DWORD` is a 32-bit value, `WORD` is a 16-bit value, and `BYTE` is an 8-bit value. The `buf` pointer is a pointer to a buffer of data that will be filled with the data read from the SD card. The `count` parameter indicates how many bytes to read from the SD card. 113 | 114 | ### 0x02 - `BYTE SD_writeBlocks(DWORD sector, BYTE *buf, WORD count);` 115 | 116 | Write raw sector data to SD card. 117 | 118 | This function works in a similar way to the `SD_readBlocks` function. The `buf` pointer here is a pointer to the buffer of data used to write to the SD card. 119 | 120 | ### 0x03 - n/a 121 | 122 | Calling `mos_getfunction` asking for this function number will succeed, but return a `NULL` pointer. 123 | 124 | Reserved for potential future `SD_status` function 125 | 126 | ### 0x04 - n/a 127 | 128 | Calling `mos_getfunction` asking for this function number will succeed, but return a `NULL` pointer. 129 | 130 | Reserved for potential future `SD_ioctl` function 131 | 132 | ### 0x05 - `int f_printf (FIL* fp, const TCHAR* str, ...);` 133 | 134 | The FatFS `f_printf` function. This function is documented in the [FatFS documentation](http://elm-chan.org/fsw/ff/doc/printf.html). 135 | 136 | ### 0x06 - `FRESULT f_findfirst (DIR* dp, FILINFO* fno, const TCHAR* path, const TCHAR* pattern);` 137 | 138 | The FatFS `f_findfirst` function, equivalent to the [`ffs_dfindfirst`](./API.md#0x94-ffs_dfindfirst) API call. This function is documemented in the [FatFS documentation](http://elm-chan.org/fsw/ff/doc/findfirst.html). 139 | 140 | Please note that for C functions, an `FRESULT` is an `int` type, and therefore will be returned in the `HLU` register. This differs from the MOS APIs for FatFS which returns an 8-bit `FRESULT` value. The return values however are otherwise identical. 141 | 142 | ### 0x07 - `FRESULT f_findnext (DIR* dp, FILINFO* fno);` 143 | 144 | The FatFS `f_findnext` function, equivalent to the [`ffd_dfindnext`](./API.md#0x95-ffs_dfindnext) API call. This function is documemented in the [FatFS documentation](http://elm-chan.org/fsw/ff/doc/findnext.html). 145 | 146 | As with the `f_findfirst` function, an `FRESULT` is an `int` type, and will be returned in the `HLU` register. 147 | 148 | ### 0x08 - `BYTE open_UART1(UART * pUART);` 149 | 150 | Equivalent to the [`mos_uopen`](./API.md#0x15-mos_uopen) API call. Please refer to the API documentation for details of the `UART` structure. 151 | 152 | ### 0x09 - `int setVarVal(char * name, void * value, char ** actualName, BYTE * type);` 153 | 154 | The underlying function the [`mos_setvarval`](./API.md#0x30-mos_setvarval) API call uses. Please see the API documentation for information about variable names and types. 155 | 156 | Please note that the way this function works differs slightly from the API; the API handles creating pointers for some arguments, and getting the values from them to return in registers. 157 | 158 | The parameters are as follows: 159 | - `name` is the name of the variable to set. As with the API, if this name is a pattern the first matched name will be set, unless an `actualName` pointer has been provided. 160 | - `value` is a pointer to the value to be set, or if setting a number type variable this will be the actual number to set. 161 | - `actualName` is a pointer to a pointer to a string. Providing this pointer is optional, but if it is set then on first call the pointer it points to should be set to `NULL`. After the function has been called, the pointer will be set to the actual name string of the variable that has been set. Please note that it is important to not adjust that string in any way. If you have used a pattern in the `name` parameter, and have provided an `actualName` pointer, then subsequent calls to this function will set the next variable that matches the pattern, and the `actualName` pointer will be updated accordingly. 162 | - `type` is a pointer to a `BYTE` for the variable type to be set. This is required. This value will be updated after the function has been called to reflect the actual type of the variable that has been set; please note that varible types 3 and 4 ("expanded" and "literal string") will be replaced with either "string" or "number" as appropriate. 163 | 164 | The return value is a [MOS status code](./API.md#status-codes), which will be in the `HLU` register. 165 | 166 | ### 0x0A - `int readVarVal(char * namePattern, void * value, char ** actualName, int * length, BYTE * typeFlag);` 167 | 168 | The underlying function the [`mos_readvarval`](./API.md#0x31-mos_readvarval) API call uses. 169 | 170 | This function is very similar to the `setVarVal` function, and it's arguments work in a very similar way. These are the differences: 171 | 172 | - `value` can be `null` to measure the length of a variable, but otherwise must always point to a buffer into which the variable value will be read/copied. This is in contrast to the `setVarVal` function which will accept a raw number as the value to be set for "number" type variables. 173 | - a pointer to a 24-bit `length` value is required. On entry, this indicates the length of the `value` buffer, if one has been provided. If a matching variable is found, this value will always be updated to reflect the full length of the variable that has been read, or will be `0` if no variable was found. 174 | - the `typeFlag` pointer is required. On entry, if the value this points to is `3` then the variable being read will be "expanded" before it is returned. This means that if the variable being read is a "macro" type, the returned string will be the expanded string with variables referenced in the macro replaced with their values. If the variable being read is a "number", then it will be converted into a string. On return, this value will be set to the underlying type of the variable that has been read, if a variable was found. 175 | 176 | The return value from this function is a [MOS status code](./API.md#status-codes), which will be in the `HLU` register. If a `value` buffer was provided, and the variable was found, then the value will be copied into that buffer. If the buffer was not large enough to hold the variable then as much of the variable as will fit will be copied into the buffer, the `length` will reflect the total length of the variable (which will be more than was copied) and the function will return an "out of memory" status code. 177 | 178 | ### 0x0B - `int gsTrans(char * source, char * dest, int destLen, int * read, BYTE flags);` 179 | 180 | The underlying function the [`mos_gstrans`](./API.md#0x34-mos_gstrans) API call uses. 181 | 182 | The "GSTrans" functionality in MOS is used to translate a source string that may include references to [system variables](./System-Variables.md) into a new string with those variables expanded. It can also convert other special character sequences into non-printable characters. Guidance on this can be found in the documentation for the [`echo`](./Star-Commands.md#echo) star command. 183 | 184 | The arguments to this function are as follows: 185 | 186 | - `source` is a pointer to the source "template" string to be translated 187 | - `dest` is a pointer to the destination buffer where the translated string will be written. If this is set to `NULL` then the function will not write to the buffer, but will still calculate the length of the translated string. 188 | - `destLen` is the size of the destination buffer, if one is provided 189 | - `read` is a pointer to an integer to store the number of translated characters read from source 190 | - `flags` is a set of flags that control how the translation is performed. These flags are described in the [`mos_gsinit`](./API.md#0x32-mos_gsinit) API documentation. 191 | 192 | The `source` and `read` pointers are both always required. The `dest` pointer is optional, but if provided it cannot be the same as the `source` pointer. 193 | 194 | The GSTrans process essentially performs a call to the [`mos_gsinit`](./API.md#0x32-mos_gsinit) API and then calls [`mos_gsread`](./API.md#0x33-mos_gsread) until it reaches the end of the source string. 195 | 196 | This function returns a [MOS status code](./API.md#status-codes), which will be in the `HLU` register. Various return values are possible, and may indicate that the source string was not valid, or various other errors. 197 | 198 | ### 0x0C - `int substituteArgs(char * template, char * args, char * dest, int length, BYTE flags);` 199 | 200 | The underlying function the [`mos_substituteargs`](./API.md#0x35-mos_substituteargs) API call uses to perform [argument substitution](./Argument-Substitution.md). 201 | 202 | This function works in a very similar manner to its corresponding API call. For information on the arguments to this function, please see the API documentation. 203 | 204 | The return value from this function is the total length of the substituted string. If a destination buffer was provided that was not large enough to hold the entire substituted string then the function will fill the buffer with as much of the substituted string as will fit. 205 | 206 | ### 0x0D - `int resolvePath(char * filepath, char * resolvedPath, int * length, BYTE * index, DIR * dir, BYTE flags);` 207 | 208 | The underlying function the [`mos_resolvepath`](./API.md#0x38-mos_resolvepath) API call uses. 209 | 210 | The `resolvePath` function resolves a file path. The primary use for this function is to take a MOS-style file path that may include a [path prefix](./System-Variables.md#path-variables) or use other [system variables](./System-Variables.md) and to resolve it into a full path that can be used by the underlying file system, i.e. the [FatFS APIs](./API.md#fatfs-commands). It can also be used to find files within a directory that match a given pattern. 211 | 212 | The arguments to this function are as follows: 213 | 214 | - `filepath` is a pointer to the file path string that is to be resolved 215 | - `resolvedPath` is a pointer to the buffer where the resolved path will be written. If this is set to `NULL` then the function will calculate the length of the resolved path. 216 | - `length` is a pointer to an integer that on entry indicates the size of the `resolvedPath` buffer. On exit, this will be set to the length of the resolved path. 217 | - `index` is a pointer to a `BYTE` that is used to keep track of which version of a path prefix is being used. This is used when resolving paths that use a prefix where the corresponding system variable contains multiple values. If the `index` pointer is set to `NULL` then only the first matching path will be returned. You can use this to manually iterate through the available prefixes. 218 | - `dir` is a pointer to a `DIR` object. This is optional, but if it is not provided then the function can only return the first matching path. If a `DIR` object is provided, then repeated calls to this function can be used to find all matching paths. This is useful for finding files that match a given pattern. 219 | - `flags` is a set of flags that control how the path is resolved. These flags are described in the [`mos_resolvepath`](./API.md#0x38-mos_resolvepath) API documentation. 220 | 221 | This function will return a [MOS status code](./API.md#status-codes), in the `HLU` register. For more guidance on possible return values, please see the API documentation for the [`mos_resolvepath`](./API.md#0x38-mos_resolvepath) API call. 222 | 223 | ### 0x0E - `int getDirectoryForPath(char * srcPath, char * dir, int * length, BYTE index);` 224 | 225 | The underlying function the [`mos_getdirforpath`](./API.md#0x39-mos_getdirforpath) API call uses. 226 | 227 | This function will return the directory for a given file path, omitting the leaf name. 228 | 229 | The arguments to this function are as follows: 230 | 231 | - `srcPath` is a pointer to the file path string that is to be resolved 232 | - `dir` is a pointer to the buffer where the resolved path will be written. If this is set to `NULL` then the function will calculate the length of the resolved path. 233 | - `length` is a pointer to an integer that on entry indicates the size of the `dir` buffer. On exit, this will be set to the length of the resolved path. 234 | - `index` is used to determine which version of a path prefix is used 235 | 236 | This function is purely a string manupulation function. It does not perform any filing system operations, 237 | 238 | This function returns a [MOS status code](./API.md#status-codes), in the `HLU` register. If the path contains a prefix that is not recognised, or if the prefix was recognised but the `index` value is out of range, then the function will return a "no path" status code. 239 | 240 | ### 0x0F - `int resolveRelativePath(char * path, char * resolved, int * length);` 241 | 242 | This is the underlying function that [`mos_api_getabsolutepath`](./API.md#0x3c-mos_getabsolutepath) uses. 243 | 244 | This function will take a relative path, i.e. one that may contain `.` or `..` path components, and resolve it into an absolute path. Please note that this function does not perform a file path resolution, i.e. it will not resolve any path prefixes or system variables. This function does however verify that the path provided is valid (at least in terms of does the containing directory exist), and will return an error if it is not. 245 | 246 | At the time of writing, this function requires both the source `path` argument and a destination `resolved` pointer to be provided. To come into line with other functions this may change in the future to allow for the `resolved` pointer to be `NULL` in order to calculate the length of the resolved path. As with the other functions above, the `length` pointer is used to indicate the size of the destination buffer, and will be updated to reflect the length of the resolved path. 247 | 248 | Returns a [MOS status code](./API.md#status-codes), in the `HLU` register. 249 | 250 | ### 0x10 - `void * getsysvars()` 251 | 252 | Returns a pointer to the system variables area. Directly equivalent to the [`mos_sysvars`](./API.md#0x08-mos_sysvars) API call. 253 | 254 | The sysvars pointer will be returned in the `HLU` register. 255 | 256 | ### 0x11 - `void * getkbmap()` 257 | 258 | Returns a pointer to the keyboard map. Directly equivalent to the [`mos_getkbmap`](./API.md#0x1e-mos_getkbmap) API call. 259 | 260 | The keyboard map pointer will be returned in the `HLU` register. 261 | 262 | 263 | ## A note for the future: MOS modules {#modules} 264 | 265 | It is highly likely that a future version of MOS will introduce a [module system](./Modules.md) that will allow some parts of MOS to be loaded and unloaded at run-time. 266 | 267 | What this means is that the address of a function returned by the `mos_getfunction` API might not be valid if the module that provides it has been unloaded. 268 | 269 | Functions provided by "Core MOS" will always be present. At this time the exact details of what will be included in "Core MOS" have yet to be finalised, but it is likely that all of the APIs and star commands present in MOS 2.3 will be included. Whilst some new features added in MOS 3.0 are also likely to be included in "Core MOS" are also likely to be included, not all of them will be. 270 | 271 | For now, the safest way to use the `mos_getfunction` API would be to call it each time you need to use a function, immediately before you call the function it returns. This should guarantee that the module containing the function has been loaded and is present in memory. 272 | 273 | -------------------------------------------------------------------------------- /docs/mos/Executables.md: -------------------------------------------------------------------------------- 1 | # MOS Executables 2 | 3 | Executable programs for the Agon platform have, to date, conventionally used a `.bin` file extension. In principle however any file can be used as an executable. 4 | 5 | Essentially the process for running any executable is the same. The following three steps will be performed: 6 | 7 | 1. The program file will be opened and read into memory 8 | 2. It will then will be checked to see if it is a valid executable 9 | 3. If it is valid, then the program will be run 10 | 11 | The exact details of these steps may differ and vary slightly depending on the version of MOS you are using, but essentially these steps broadly remain the same. 12 | 13 | MOS essentially supports two different types of programs; ["moslets"](../MOS.md#moslets) and regular programs. 14 | 15 | Moslets are always built to be loaded and run at address `0x0B0000`, the start of the "moslet" memory space in the Agon platform's [memory map](../MOS.md#memory-map), and should be smaller than 32 kilobytes in size to fit into that space. 16 | 17 | Regular programs are usually built to be loaded and run at address `0x040000`, the start of the "user RAM" area of memory. This is the address that MOS will automatically use when loading and running a program. 18 | 19 | MOS 2.3 and later will additionally check to ensure that a program cannot be loaded into memory that will overlap the MOS system area of memory. 20 | 21 | ## Parameters passed to executables {#parameters} 22 | 23 | When a program is run, whether that is through the use of the [`Run` command](Star-Commands.md#run) or via a different mechanism, MOS will set up the following processor registers before the program is entered: 24 | 25 | - `A` will be set to the current memory bank value `MB` 26 | - `DE(U)` the execution address 27 | - `HL(U)` pointer to any additional command line parameters 28 | 29 | Notes about the processor stack can be [found here](../MOS.md#the-stack). 30 | 31 | ## The MOS Executable File Format 32 | 33 | To facilitate checking for valid executables, MOS uses a simple executable file format. 34 | 35 | The basic format requires a header to be present at an offset of 64 bytes into the file, as follows: 36 | 37 | | Offset | Size | Contents | 38 | |--------|------|----------| 39 | | 0x40 | 3 bytes | the word `MOS` in ASCII bytes | 40 | | 0x43 | 1 byte | header version | 41 | | 0x44 | 1 byte | executable type: `0` = Z80, `1` = ADL | 42 | 43 | You will note that this header format is very simple and essentially includes only one piece of information, whether the executable code should be run in Z80 or ADL mode on the eZ80 processor. There is no information here about where the program should be loaded into memory, so it is not possible to tell from the header whether a program is a moslet, a regular program, or some other type of program file. 44 | 45 | The header version byte should be set to `0` for all programs that were written for MOS 1 and MOS 2. Up to and including MOS 3.0 the version byte is not actually checked. 46 | 47 | ### The "advanced" header format {#advanced-header} 48 | 49 | As of the MOS 3.0 release an advanced header format is being introduced which allows for the inclusion of additional information in the header. 50 | 51 | Please note that this header format is backwards compatible with the original header format, and programs that use this new header format will still be able to run on earlier versions of MOS. 52 | 53 | The main reason for this new format is is to prepare for [MOS Modules](./Modules.md). When the MOS modules system is introduced, executables with a header version of `0` will not be considered to be "module safe", and API calls, commands, and functions provided by modules will not be available to them. 54 | 55 | Some APIs, commands, and functions introduced in MOS 3.0 may be moved to modules in the future. To guarantee that a program using these features will continue to work in the future you should ensure that your program is "module safe" and has an appropriate header. 56 | 57 | As previous versions of MOS do not actually check the header version, it is possible to use the new header format in existing programs that can run on all versions of MOS. As a result you should be aware that any additional information or or settings included in the header will be ignored by previous versions of MOS. You should not assume that including such information is a guarantee that it will be understood when your program is run. 58 | 59 | The new header format is as follows: 60 | 61 | | Offset | Size | Contents | 62 | |--------|------|----------| 63 | | 0x40 | 3 bytes | the word `MOS` in ASCII bytes | 64 | | 0x43 | 1 byte | header version (this should be `1` for "advanced") | 65 | | 0x44 | 1 byte | executable type: `0` = Z80, `1` = ADL | 66 | | 0x45 | 1 byte | flags | 67 | | 0x46 | 1 byte | bit-inverted copy of the flags byte at offset `0x45` | 68 | | 0x47 | 3 bytes | optional load/execution address (little-endian) - only use this if the corresponding flag is set | 69 | 70 | The flags byte is a bit field. As the original header version byte was not well documented, and is not actively checked inside earlier versions of MOS, it is possible that some programs may exist that have the header version byte set to `1`. To avoid any potential false-positives, an inverted copy of the flags byte is included to allow the flags byte to be verified. 71 | 72 | The following bits are defined: 73 | 74 | | Bit | Meaning | Description | 75 | |-----|---------|-------------| 76 | | 0 | Module safe | The program is "module safe", as it does not use the "moslet" area of memory (where modules are loaded) | 77 | | 1 | Module compatible | The program uses the moslet area of memory, but modules can be loaded into that area of memory. When this bit is set when a module needs to be loaded MOS will save the moslet area of memory to disk before loading a module and executing the command or API that required it. On returning from the module, MOS will restore the moslet area of memory from disk. Programs with this bit set must ensure that any API calls they make will not use the moslet area for data buffers the API calls require. | 78 | | 2 | Strip trailing spaces from arguments | When this bit is set, any trailing spaces in the arguments string passed to the program will be stripped. Please note that this is the default behaviour for executables with a header version of `0`, but the default behaviour for executables with a header version of `1` is to not strip trailing spaces. This bit is provided for backwards compatibility with earlier versions of MOS. | 79 | | 3 | Header includes load/execution address | The default address to load and execute this executable is set at offset 0x47-49. For Z80 executables the most significant byte (at 0x49) will be ignored | 80 | | 4-7 | Reserved | These bit is reserved for future use, and must be set to zero | 81 | 82 | More advice on the meanings of "module safe" and "module compatible" can be found in the [MOS Modules](./Modules.md) documentation. 83 | 84 | Future versions of this header version may include support for more bits in the flags byte to indicate that further information is provided. When support for new flags is added unless there is a good reason to do so the header version will not be changed and remain `1`. 85 | 86 | It should also be noted that whilst this new header format has been introduced with the release of MOS 3.0, the MOS 3.0 release does not understand the new header extensions, and will ignore them. They are included and documented here to allow developers to start using them in their programs in preparation for future versions of MOS. 87 | 88 | It is likely that the next release of MOS will understand this new header format and at least provide support for bits 2 and 3 in the flags byte. When MOS Modules are introduced, bits 0 and bit 1 will be supported. 89 | -------------------------------------------------------------------------------- /docs/mos/Modules.md: -------------------------------------------------------------------------------- 1 | # MOS Modules 2 | 3 | As of MOS 3.0, MOS does not have a module system. However it is highly likely that one will be introduced in the future, most likely in either in MOS 3.1 or MOS 3.2. 4 | 5 | As we add new features to MOS, its size is growing, and we are fast running out of space in the flash memory of the eZ80 CPU where MOS is stored. We therefore have a choice: stop adding new features, or find a way to allow those new features without taking up more space in the flash memory. 6 | 7 | "Stop adding new features" wouldn't be a popular option as we have lots of ideas for new features we'd like to add to MOS. One possibility is to work really hard to make MOS smaller, but that would have its limits too. 8 | 9 | A better solution is to allow some parts of MOS to be loaded and unloaded from the SD card at run-time. A module system. 10 | 11 | !!! note 12 | 13 | It is possible that some of the new commands and APIs added in MOS 3.0 may be moved into modules in the future. To guarantee that a program using these features will work in the future, you will need to ensure that your program is "module safe", and ensure your program has an [appropriate header](./Executables.md#advanced-header). 14 | 15 | The MOS module system is still being designed and developed, and so the exact details of how it will work have not yet been finalised. The following things howver are likely to be true. 16 | 17 | ## "Core MOS" 18 | 19 | "Core MOS" will be the part of MOS that is always present, and which cannot be unloaded. The exact details of what will be included in "Core MOS" are still being worked out, but for compatibility with existing programs written for MOS 1 and MOS 2, all of the star commands and APIs present up to and including MOS 2.3 will be included in "Core MOS". 20 | 21 | Some new features added in MOS 3.0 will also be included in "Core MOS", but not all of them. For example, the underlying functionality that supports [System Variables](./System-Variables.md) will need to be present in "Core MOS", however it may not be necessary to include all of the star commands and APIs used to manage them. It is possible that some of these may be moved into a module. 22 | 23 | As we add new features to MOS we will need to carefully consider which features need to be a part of "Core MOS" and therefore always present, and which can be implemented in modules. 24 | 25 | ## What MOS modules may contain 26 | 27 | It is highly likely that MOS modules will be able to include implementations of API calls, star commands, as well as C functions. The module design is likely to use an extensible format to allow for future expansion, allowing us to add new types of functionality to modules in the future. 28 | 29 | ## How modules are likely to work 30 | 31 | MOS modules will almost certainly be loaded into the ["moslet" area of memory](../MOS.md#memory-map). This area of memory is defined as the RAM from address `0xB0000` to `0xB7FFF`, which is 32 kilobytes in size, which will therefore be the module size limit. 32 | 33 | When attempting to use a star command or API call that is implemented in a module, MOS will take care of loading the module into memory as required. (This will be fairly sophisticated behaviour so as to support calling features in one module present in another module, and so on.) 34 | 35 | The reality of the Agon platform however is that access to RAM from the eZ80 CPU is not, and cannot be, restricted. A program can therefore potentially use the moslet area of memory should it choose to do so. 36 | 37 | Existing programs may therefore be using the moslet area of memory. There could therefore be problems if a module is loaded there, as the program's code or data could be overwritten, causing it to crash or behave unexpectedly. 38 | 39 | The solution to this will be for programs to be "module safe". 40 | 41 | A new [advanced executable header](./Executables.md#advanced-header) format has been introduced with MOS 3.0 to allow for programs to indicate to MOS whether they are "module safe" or "module compatible". 42 | 43 | ## "Module safe" programs 44 | 45 | A program is "module safe" if it does not use the moslet area of memory. 46 | 47 | This means that the program can safely use any and all of the features provided by modules, and will not be affected by a module being loaded into RAM. 48 | 49 | ## "Module compatible" programs 50 | 51 | A "module compatible" program is one that uses the moslet area of memory, but does so in a way that is compatible with modules. 52 | 53 | When MOS detects a program that is marked as "module compatible", and the program attempts to use a feature that is implemented in a module, it will save the contents of the moslet area of memory to disk before loading the module. When the module has finished executing, MOS will restore the contents of the moslet area of memory from disk. 54 | 55 | A "module compatible" program must ensure that any API calls it makes will not use the moslet area of memory for data buffers. Ideally API calls implemented in modules will detect when they are being given a buffer that overlaps the moslet area and return an error, but this cannot be guaranteed. 56 | 57 | It will be safe for a "module compatible" program to use "Core MOS" APIs to be passed buffers that overlap the moslet area of memory. 58 | 59 | ## Using modules from moslets 60 | 61 | As moslets are designed to be loaded into the same area of memory as modules, it is not possible to use features provided by modules from moslets, and unlikely that this will be possible in the future. 62 | 63 | It should be noted however that the purpose of moslets was essentially to provide a way to add new star commands to MOS. As modules provide a different way to add new star commands to MOS, arguably we do not need to add support for using modules from moslets. 64 | 65 | Unfortunately this means that if you write a moslet today that uses a MOS 3.0 API that is later moved into a module, it will not be able to run in future versions of MOS. Calls to that API will fail with an error indicating that the API is not available. You will likely need to rewrite your moslet to be a module instead that provides a star command. 66 | 67 | ## The future of modules 68 | 69 | The exact details of the module system will likely change and evolve as the system is developed. 70 | 71 | Some possibilities for the future include: 72 | 73 | * "Driver" modules 74 | * One of the oldest ideas we had for a MOS module was for a "joystick module". The concept was to define a standard set of Joystick APIs, but to load a joystick driver module specific for the joystick interface being used that implemented those APIs. Whilst the Agon community has _mostly_ settled on the joystick interface system used by the Agon Console8, other interfaces do exist. 75 | * Other types of "driver" modules could be considered 76 | * I/O modules 77 | * A concept being considered for a future version of MOS is "unified I/O", which would allow lots of different types of I/O to be performed in a consistent way 78 | * An I/O module could contain data that identifies which "stream" identifier it implements connections for, and implement a set of functions to support that stream 79 | * User-defined/provided modules 80 | * In principle, users should be able to create their own modules to extend MOS 81 | * These could add new star commands, APIs, or C functions, or whatever other functionality is supported by the module system 82 | * In the case of APIs, we may need to have a registration system to ensure that the same API number does not get multiple different and incompatible/conflicting implementations 83 | * Non-code modules 84 | * If modules are implemented in an extensible format, this may allow for modules to be used to store other things, such as data files, bitmaps, or other resources 85 | * User-space modules 86 | * It may be possible to allow the module system to be used by programs to load and unload modules into their own address space, rather than the moslet area of memory 87 | * By using user-space modules, a program could potentially load/unload multiple modules simultaneously, and use them to extend the program's functionality 88 | * The use of non-code modules could be useful here; for example a game could use modules for level data, or other resources 89 | 90 | ## More information 91 | 92 | At the time of writing the full details of the MOS module system are still being worked out. If you wish to learn more and see how these ideas develop you can check the corresponding [issue on GitHub](https://github.com/AgonPlatform/agon-mos/issues/2). 93 | 94 | -------------------------------------------------------------------------------- /docs/mos/System-Variables.md: -------------------------------------------------------------------------------- 1 | # System Variables 2 | 3 | System variables are global variables that store various settings relating to different parts of the current operating system environment. MOS support a few different types of system variables, and they are used by the system in several different ways. 4 | 5 | Applications/programs are welcome to use system variables for their own needs. MOS provides two API calls to allow for variables to be read and written by application code, and the command line also has several commands that will make use of system variables. 6 | 7 | System variables are a new feature added to MOS 3.0. 8 | 9 | 10 | ## Type of System Variables 11 | 12 | There are a few different data types that system variables can be. The following are the types of system variables that are supported by MOS: 13 | 14 | | Type | Description | How to set | How to remove | 15 | |------|-------------|------------|--------------| 16 | | String | A string of characters | [`*Set`](./Star-Commands.md#set) | [`*Unset`](./Star-Commands.md#unset) | 17 | | Integer | Three-byte integers | [`*SetEval`](./Star-Commands.md#seteval) | [`*Unset`](./Star-Commands.md#unset) | 18 | | Macros | Macros are strings that can be expanded, passed through the GSTrans mechanism, when they are read | [`*SetMacro`](./Star-Commands.md#setmacro) | [`*Unset`](./Star-Commands.md#unset) | 19 | | Code | A machine code routine will be called when the variable is read or set. This allows the OS to provide some more sophisticated behaviour, such as access to real-time clock data | n/a | n/a | 20 | 21 | The GSTrans mechanism is used by the command line in various ways. For instance, when setting a system variable using the [`*Set`](./Star-Commands.md#set) command, the string value in the command line will first be passed through the GSTrans mechanism, allowing for variables to be expanded in the string before the variable is set. The [`*Echo`](./Star-Commands.md#echo) command also uses the GSTrans mechanism, allowing for variables to be expanded in the string that is echoed to the screen. 22 | 23 | 24 | ## Naming of system variables 25 | 26 | Users are free to name their system variables as they wish, but there are some limitations to bear in mind. 27 | 28 | - Using wholly numeric names is not recommended, as this can cause difficulties with GSTrans operations when looking up a variable. For instance, GSTrans will always interpret `<123>` to mean the ASCII character with the value 123, rather than looking up the name as a variable. 29 | - When setting a variable, the case of a name is preserved, however variable lookup is not case-sensitive. This means that `MyVar` and `myvar` are considered to be the same variable. 30 | - Names can contain essentially any non-space, or non-control character 31 | - When looking up variables, wildcard characters `#` and `*` can be used. `#` will match any single character, and `*` will match any number of characters. 32 | 33 | By default, MOS's system variables follow a naming convention where the variable is named loosely in the format `Class$VariableName`. You do not have to follow this convention, but following it can help to keep your variables organised. 34 | 35 | 36 | ## Path variables 37 | 38 | Variables that are named in the format `Name$Path` are considered to be path variables. When loading or running a file, MOS will supports prefixing filenames with a path and a colon. Let's say we have a variable named `Foo$Path`, which is set to `/home/foo/`. If you try to load a file named `Foo:Bar`, the system will look for the file `/home/foo/Bar`. 39 | 40 | Path variables can contain multiple paths to search, separated by commas. For instance, if `Foo$Path` is set to `/home/foo/,/home/bar/`, the system will look for `Foo:Bar` in `/home/foo/Bar` and `/home/bar/Bar`, opening the first it finds. If the file is not found in any of the paths and the file was opened for creation/update, the system will create the file in the first path in the list. 41 | 42 | It is important to note that directories used in path variables should end with a `/` character. If this is omitted then the system will not be able to find files in that directory. For example, if `Foo$Path` is set to `/home/foo`, then the system will look for `Foo:Bar` in `/home/fooBar`, which is unlikely to be correct. 43 | 44 | ### System Path variables: `Run$Path` and `Moslet$Path` {#system-path-variables} 45 | 46 | The MOS system makes use of two path variables, which it will set to default values on startup. These are `Run$Path` and `Moslet$Path`. 47 | 48 | The `Moslet$Path` variable is used to identify the directory where "moslet" programs are located. By default this will be set to `/mos/`. Moslets differ from normal programs in that they are written to be loaded and run from a different memory location, which should usually allow them to be used whilst a different program is running. Their purpose is essentially to allow for new star commands to be added to MOS. When you run a program, the system will use this variable to check to see whether the program you are trying to run is a moslet, and if it is, it will load the moslet and run it in the moslet memory space. 49 | 50 | The `Run$Path` variable used to identify directories in which the command line should search when trying to run a program. By default it is a macro variable set to `, ./, /bin/`, which provides the same default search path for running programs as MOS 2. 51 | 52 | These variables can be redefined to allow you to change where the system looks for moslets and programs to run. 53 | 54 | 55 | ## Application variables 56 | 57 | By convention, application variables are named in the format `App$VariableName` where `App` is the name of the application that the variable is associated with. This helps prevent clashes between variables that serve similar purposes for different applications. 58 | 59 | If an application is started up using an `obey` file, then often the obey file will set a variable named in the format `App$Dir` or `App$Path` to represent the directory the program is located in, which may be used by the program to locate its resources. Typically this is achieved with a command such as `set App$Dir `. 60 | 61 | 62 | ## Command aliases 63 | 64 | If you set up a system variable in the format `Alias$Name` then this will set up a new command alias that can be used from the command line with the given name. For example, one could add a new `Mode` command using `*set Alias$Mode vdu 22 %0`. This would allow you to run the command `mode 1` to change the screen mode to mode 1. The command will be expanded to `vdu 22 1` when the command is run. 65 | 66 | When attempting to interpret a command, the MOS command interpreter checks for aliases first. As with regular commands the matching of the command name is not case-sensitive, and the command can be abbreviated with a `.` character. So if you have defined the `Mode` command alias above, and no other aliases beginning with `m`, then `*m. 1` will be interpreted as `*mode 1`. Only if no matching alias is found will the system look for a matching in-built command. 67 | 68 | Alias resolution can be disabled by prefixing a command with the [`%`](./Star-Commands.md#skip-aliases) character. So `*%m.` will skip alias resolution and run the first in-built command that matches `m.`, which in MOS 3.0 would be the [`Mem`](./Star-Commands.md#mem) command. Disabling alias resolution can be useful in script files to ensure you're running the command you expect, and not an alias that may have been defined by the user. 69 | 70 | Aliases support [argument substitution](Argument-Substitution.md). Any unused arguments (beyond the last used argument) will be automatically appended to the end of the resultant command. 71 | 72 | An alias can include multiple commands, separated by carriage return characters (`|M`). If one command in an alias sequence fails, the rest of the commands will not be executed, and the error reported. 73 | 74 | As an alias will append any unused arguments to the end of the command, the example above for a `mode` command is actually flawed. Whilst `mode 1` would result in a `vdu 22 1` command, `mode 1 2 3 4` would result in the command `vdu 22 1 2 3 4` which is still technically a valid VDU command, but would send 3 extra bytes to the VDP, performing a `VDU 2`, `VDU 3` and `VDU 4` commands (enable printer, disable printer, and "write text at text cursor"), and is unlikely to be the intended behaviour. Therefore a better version of the command would be `*set Alias$Mode vdu 22 %0|M#`. This splits the alias into two separate commands, the first being a `vdu 22` passing in the first argument, and the second command will be a `#` with all other arguments following it. The command interpreter considers commands beginning with a `#` to be a comment, and will ignore it. 75 | 76 | ### File load/run type aliases {#file-type-variables} 77 | 78 | System variables are used to define how certain files should be loaded or run when using either the `LoadFile` or `RunFile` commands. Additionally the MOS 3 CLI will use run type aliases to determine how to run a file if the user enters a filename without a preceding command. 79 | 80 | Load and run type variables are a special type of [command alias](#command-aliases) named in the format `Alias$@LoadType_extension` or `Alias$@RunType_extension`, where the `extension` matches the filing system extension for that file type. As with command aliases, these support [argument substitution](Argument-Substitution.md). The system defines a few such aliases by default. 81 | 82 | Attempting to load or run a file with an extension that does not have a corresponding alias (using `LoadFile` or `RunFile`) will result in an `Invalid command` error. 83 | 84 | The system will set a variable named either `LastFile$Run` or `LastFile$Load` to the alias expansion that was used to run or load the file. This can be useful for debugging purposes, as it allows you to see exactly what command (or sequence of commands) was executed when the file was loaded or run. 85 | 86 | As load and run aliases are essentially a special type of command alias, they work in the same way as other aliases. They can therefore also contain mutiple commands, separated by carriage return characters (`|M`), and will automatically append any unused arguments to the end of the expanded command string. 87 | 88 | MOS 3.0 contains a few built in file load and run-types. These are: 89 | 90 | | Type variable | File extension | Definition | Description | 91 | |---------------|----------------|------------|-------------| 92 | | `Alias$@LoadType_bin` | `.bin` | `Load %*0` | Load a binary file | 93 | | `Alias$@LoadType_obey` | `.obey` | `Type %*0` | Prints the contents of an obey file to the screen | 94 | | `Alias$@RunType_bas` | `.bas` | `BBCBasic %*0` | Run a text-format BBC BASIC program * | 95 | | `Alias$@RunType_bbc` | `.bbc` | `BBCBasic %*0` | Run a BBC BASIC program * | 96 | | `Alias$@RunType_bin` | `.bin` | `RunBin %*0` | Run a binary file | 97 | | `Alias$@RunType_exec` | `.exec` | `Exec %*0` | Run a script using the `*exec` command | 98 | | `Alias$@RunType_obey` | `.obey` | `Obey %*0` | Run a script using the `*obey` command | 99 | 100 | \* The aliases to run BBC BASIC assume that a `BBCBasic.bin` executable is present in your current [run path](#system-path-variables). Often this is the plain Z80 version of BASIC. If you wish to use the eZ80 version of BASIC, or BASIC V, then you can either rename their executable to `BBCBasic.bin` or redefine the `Alias$@RunType_bas` and `Alias$@RunType_bbc` variables to point to the correct executable. For example, if you have a copy of BBC BASIC V in your current run path, with an executable named `BBCBasicV.bin`, you could use the following commands to redefine the aliases: 101 | 102 | ``` 103 | *set Alias$@RunType_bas BBCBasicV %*0 104 | *set Alias$@RunType_bbc BBCBasicV %*0 105 | ``` 106 | 107 | It is common for [boot-up scripts](../MOS.md#boot-script) to set up load and run type variables to add support for other file types, or change the in-built behaviour. 108 | 109 | 110 | ## CLI 111 | 112 | ### `CLI$Prompt` 113 | 114 | The command prompt that the MOS CLI displays is defined using the variable named `CLI$Prompt`. By default this is a macro set to ` *` to match the default prompt from MOS 2.2 onwards. The prompt can be changed to anything you like, and if it is set as a macro it can include variables that will be expanded when the prompt is displayed. 115 | 116 | If you unset the `CLI$Prompt` variable, the system will revert to displaying the default prompt which is `*`. 117 | 118 | ### `CLI$AutoPaged` {#autopaged} 119 | 120 | Setting a variable `CLI$AutoPaged` to any value will enable the auto-paging feature of the CLI, if you are using VDP 2.14.0 or later by [temporarily enabling paged mode](../vdp/System-Commands.md#vdu-23-0-9a). By default this variable is not set. 121 | 122 | When this variable is set then commands that can produce a lot of output will automatically use the VDP's "paged mode" for output. This means that output will pause after a page of text has been displayed, and output will continue when the user presses the "shift" key. This behaviour specifically applies to [`*Dir`](./Star-Commands.md#dir) (and its various aliases), [`*Help`](./Star-Commands.md#help), [`*Show`](./Star-Commands.md#show) and [`*Type`](./Star-Commands.md#type). Other commands that could produce a lot of output such as running a program or a script explicitly do not use this feature so as to allow the user to control the output. 123 | 124 | Auto-paging applies whether you are using the MOS command line, or executing MOS commands via some other means, such as using the [`mos_oscli`](./API.md#0x10-mos_oscli) API, or using the command from a BBC BASIC program. 125 | 126 | Support for this variable was added in MOS 3.0.1. In MOS 3.0.0 the system would always use auto-paging, and the feature could not be disabled. 127 | 128 | To automatically enable paged mode for the CLI, you can add the following line to your [boot script](../MOS.md#boot-script): 129 | 130 | ``` 131 | *set CLI$AutoPaged 1 132 | ``` 133 | 134 | 135 | ## Obey files: `Obey$Dir` {#obey-files} 136 | 137 | When an obey file is run with the `obey` command, the system will set the variable `Obey$Dir` to the directory that the obey file is located in. This can be used by the obey file to locate resources that it needs to run. 138 | 139 | It should be noted that the `Obey$Dir` variable will not include a trailing `/` character, so if you are using it to build a path to a file, you will need to add the `/` character yourself. For example, if you have an obey file located in `/home/foo/`, and wished from that obey file to run a program called `foo.bin` located in the same directory, your script should use the command `*RunBin /foo.bin`. 140 | 141 | ## Time and date: `Sys$Date`, `Sys$Time` and `Sys$Year` {#time-and-date} 142 | 143 | MOS provides three system variables that expose the current real-time clock information. These are `Sys$Date`, `Sys$Time` and `Sys$Year`. The date variable is in the format of `Day, n Mon`. It is possible to set these variables, and the real-time clock should update accordingly. The exception to that is setting `Sys$Date` if the value cannot be interpreted as a valid date. 144 | 145 | The real-time clock information can also be displayed and updated using the [`*Time`](./Star-Commands.md#time) command 146 | 147 | 148 | ## Hotkeys: `Hotkey$` {#hotkeys} 149 | 150 | Hotkey definitions are stored as system variables in the format `Hotkey$n` where `n` is a number from 1-12 equating to the F1-F12 keys on your keyboard. Hotkeys can also be defined using the [`*Hotkey`](./Star-Commands.md#hotkey) command. 151 | 152 | Hotkey definitions support [argument substitution](Argument-Substitution.md). Any unused arguments are discarded. 153 | 154 | If a hotkey definition is set as a macro variable (using [`SetMacro`](./Star-Commands.md#setmacro)), then the system will expand the macro when the hotkey is pressed. 155 | 156 | A hotkey definition that ends with a carriage return character (`|M`) will automatically press return when the hotkey is pressed. When used in a CLI this means the command will execute immediately. Hotkeys set using the [`*Hotkey`](./Star-Commands.md#hotkey) will automatically append a carriage return to the end of the command. 157 | 158 | In MOS 3.0, whilst a hotkey variable can technically contain multiple lines, split by `|M`, the system will only use the first line of the variable, and the rest will be discarded. This limitation is due to how the MOS line editor works. 159 | 160 | If you wish to create a hotkey that can run a sequence of commands then there are two options. Firstly you could create an obey file, and define a hotkey to run the obey file passing in all the arguments. Alternatively you could define a command alias that can run a sequence of commands, and define a hotkey to use that alias. Please note that both of these options are only suitable for running multiple MOS commands, and cannot be used for multi-line input in other environments such as the BBC BASIC command line. 161 | 162 | Support for multiple commands in a hotkey may be added in a future version of MOS. 163 | 164 | 165 | ## System 166 | 167 | As noted above, there are several "system" variables that MOS provides to give access to system information and control how MOS behaves. 168 | 169 | Another two system variables are the `Console` variable and `Keyboard`. These are two special write-only variables that will turn on or disable "console mode", and set the current keyboard layout respectively. These variables are named to be compatible with earlier versions of MOS. 170 | 171 | 172 | ## Return codes 173 | 174 | When a command or program finishes running MOS will set a numeric variable `Sys$ReturnCode` to indicate the success or failure of the program. This variable is set to 0 if the program ran successfully, and to a non-zero value if the program reported an error. 175 | 176 | The `Try` command can also be used to run a command and set a system variable `Try$ReturnCode` to the return code of that command. If an error occurred then a variable `Try$Error` will also be set to the error message. This can be useful in script files to check for errors and take appropriate action. Running commands without using the `Try` command inside a script file (executed using either `exec` or `obey`) that fail will cause the script to stop running. You can then use the `if` command to check the return code and take appropriate action. 177 | 178 | 179 | -------------------------------------------------------------------------------- /docs/stylesheets/extra.css: -------------------------------------------------------------------------------- 1 | /* 2 | the default font sizes look small and encourage zooming, 3 | which loses the navigation side panels 4 | */ 5 | p { font-size: 16px; } 6 | td { font-size: 16px; } 7 | 8 | /* 9 | todo: try to make the nav pane section labels larger 10 | 11 | for now, this at least adds space between sections 12 | so that section starts are easier to see 13 | */ 14 | .md-nav__item { font-size: 20pt; } 15 | .md-nav__link { font-size: medium; } 16 | -------------------------------------------------------------------------------- /docs/vdp/Context-Management-API.md: -------------------------------------------------------------------------------- 1 | # VDU 23, 0, &C8: Context Management API 2 | 3 | As of Console8 VDP 2.8.0 the VDP now has the ability to create and manage different graphical contexts. This allows you to easily switch between different settings for drawing text and graphics on the VDP, and to save and restore these settings as needed. 4 | 5 | Almost all settings related to the text and graphics system are stored in the context. These include things like the currently selected fonts for the text and graphics cursors, text cursor behaviour, position and display settings, the active cursor (whether the context is in `VDU 4` or `VDU 5` mode), the selected graphics coordinate system and last graphics cursor positions, the currently selected font, viewports, GCOL painting mode, the selected bitmap, and so on. 6 | 7 | The only graphical things that do _not_ change with the context are things that should be considered "global" in nature. That includes the contents of buffers and graphical items that make use of buffers, such as bitmaps and font definitions. Sprites are also "global" in nature. Additionally data related to the current screen mode and the system palette are global across all contexts. 8 | 9 | Changing the screen mode will reset the graphics system. All saved contexts will be lost, and the current context stack cleared. 10 | 11 | ## Context concepts 12 | 13 | There are two important concepts to understand when working with contexts, specifically the idea of a "context stack", and the idea of selecting a different context stack. 14 | 15 | ### Context Stacks 16 | 17 | At any time you can choose to save the current graphics system state (context) to the context stack, or restore the last saved context from the stack. 18 | 19 | This allows for a simple way to save the current graphics system state, make temporary changes, and then step back to that previous state. 20 | 21 | This is a common concept in graphics programming APIs. For example, in the HTML5 web canvas API, you can save the current state of the canvas, make changes, and then restore the previous state. Similarly Apple's Core Graphics API has the same concept concept. 22 | 23 | You will always have an active context, and a context stack. 24 | 25 | ### Selecting a Different Context Stack 26 | 27 | The context management API also provides a way to select completely different context stacks. 28 | 29 | This can be useful if you want to have completely different sets of settings for different areas of your program, or applying to drawing different parts of the screen. 30 | 31 | As of VDP 2.12.0, the default context stack is context ID 0. Changing screen mode will reset the currently selected context stack ID to 0. In previous versions there was no default stack, which proved to be confusing. 32 | 33 | ## The API 34 | 35 | The API to manage contexts is relatively simple, and consists of the following commands: 36 | 37 | ### `VDU 23, 0, &C8, 0, contextId`: Select context stack 38 | 39 | This command will select a different context stack to use. 40 | 41 | If there is no context stack with the given `contextId`, a copy of the current context stack will be created and saved to the ID, and the new context stack will be selected. 42 | 43 | If you wish for your new context ID to have an empty stack, then you should subsequently clear the stack with the "clear stack" command. 44 | 45 | Once you have selected a context stack by ID, all subsequent changes to your context stack will be saved against that ID. 46 | 47 | ### `VDU 23, 0, &C8, 1, contextId`: Delete context stack 48 | 49 | This command will delete the context stack with the given `contextId`. 50 | 51 | Please note that deleting a stack from the store will not affect the current context stack, and will not affect the current context. 52 | 53 | As of VDP 2.12.0 you cannot delete your currently selected context stack. Attempting to do so will have no effect. This ensures that there will always be at least one context stack available. 54 | 55 | ### `VDU 23, 0, &C8, 2, flags`: Reset 56 | 57 | This command will reset the current context. It accepts a bitfield of flags to indicate what aspects of the settings should be reset. Sending a flags value of `0` will perform the same type of context reset that happens on a screen mode change. 58 | 59 | The following flags are supported: 60 | 61 | | Bit | Description | 62 | | --- | ----------- | 63 | | 0 | Reset graphics painting options | 64 | | 1 | Reset graphics positioning settings, including graphics viewport and coordinate system | 65 | | 2 | Reset text painting options | 66 | | 3 | Reset text cursor visual settings, including text viewport | 67 | | 4 | Reset text cursor behaviour | 68 | | 5 | Reset currently selected fonts | 69 | | 6 | Reset character to bitmap mappings | 70 | | 7 | Reserved for future use | 71 | 72 | These are broad reset options, resetting all settings in the given category to their default values. More fine-grained control to reset individual settings are available via other VDU commands. 73 | 74 | When all flags are set to `0`, this command performs a reset equivalent to changing the screen mode. The text cursor behaviour and character to bitmap mappings will be left unchanged, as will the selected positioning system. 75 | 76 | ### `VDU 23, 0, &C8, 3`: Save context 77 | 78 | This command will save a copy of the current graphics style state to the context stack so you can later revert any changes you make to it using a "restore". 79 | 80 | ### `VDU 23, 0, &C8, 4`: Restore context 81 | 82 | This command will restore the last saved context from the context stack. 83 | 84 | If there are no saved contexts on the stack, this command will do nothing. 85 | 86 | ### `VDU 23, 0, &C8, 5, contextId`: Save and select a copy of a context 87 | 88 | Saves the current context to the context stack. If there is a context stack saved with the given `contextId` then a copy of the most recent context at that `contextId` will be made and activated, replacing the current context. 89 | 90 | If there is no context stack with the given `contextId`, then a copy of the current context will be saved to the stack, and you will be left with the current context. 91 | 92 | This means that in both cases the context before you called this command is saved to the stack, and to revert to it you should call the "restore context" command. 93 | 94 | Please note that this does _not_ change the current active context stack, so the active context ID will remain the same. 95 | 96 | ### `VDU 23, 0, &C8, 6`: Restore all 97 | 98 | This command is equivalent to calling "restore" repeatedly until there are no more saved contexts on the stack. It reverts back to the first context saved on the current stack. 99 | 100 | ### `VDU 23, 0, &C8, 7`: Clear stack 101 | 102 | This command will clear all saved contexts from the current context stack. You will be left with the current context still active, but no history to "restore" to. 103 | 104 | -------------------------------------------------------------------------------- /docs/vdp/Copper-API.md: -------------------------------------------------------------------------------- 1 | # The "Copper" API 2 | 3 | As of VDP 2.12.0 the VDP supports a set of functionality inspired by "Copper" effects on the Commodore Amiga. The feature requires that a feature flag be set to enable the Copper API, which can be done using `VDU 23, 0, &F8, &310; 0;` 4 | 5 | These effects work on screen modes that use a palette for generating their video output, i.e. 2, 4 and 16 color modes. They are not supported in 64 color modes, as those modes have a fixed output palette. 6 | 7 | Through the use of this API, it is possible to potentially show all 64 colours that the Agon is capable of outputting on a single screen when in a 2, 4 or 16 colour mode. 8 | 9 | At the simplest level, this API allows for different areas of the screen to be shown in different colours. This technique can allow for higher resolution screen modes that would otherwise be limited to showing only a few colours to show a wider range of colours. A version of this technique was first used on machines like the BBC Micro in games such as Revs and Elite. Revs, for instance, used this to allow the dashboard of the racing car to use a different selection of colours to the road, and the road to use a different selection of colours to the sky. In total Revs shows 7 different colours on the screen at once, despite the screen mode it used only supporting 4 colours. 10 | 11 | When combined with the newly introduced VSYNC callback mechanism, it is possible to automatically change the signal list on a per-frame basis, allowing for a wide range of effects to be achieved. This can be done completely on the VDP without your main program needing to send any additional commands once it has set things up. For example, this can be used to add support for flashing colours (similar to the BBC Micro's mode 2), or animated palette effects that were popular on the Amiga. 12 | 13 | ## How it works 14 | 15 | On palette-based screen modes, the screen framebuffer is converted on the fly whilst the VGA scanout is in progress, one row at a time, into the VGA output signal. Up to and including VDP 2.11.0 only a single palette would be used for the signal output. As of VDP 2.12.0, the Copper API allows for multiple palettes to be defined, and a "signal list" set to define which palettes should be used for scanout for different rows of the screen. 16 | 17 | Essentially, all drawing operations in palette-based screen modes are performed using the primary palette, palette ID 0. The existing palette changing operations will only affect the primary palette. 18 | 19 | The Copper API supports 16-bit palette IDs, so in principle up to 65536 palettes could be defined. However in practice you should never define that many. These palettes are allocated in internal memory on the VDP, so there are practical limits to how many palettes can be defined. 20 | 21 | On changing screen mode, the signal list is reset and all palettes are cleared, leaving only the default palette. 22 | 23 | ## Copper API Commands 24 | 25 | ### Command 0: Create a palette 26 | 27 | `VDU 23, 0, &C4, 0, ;` 28 | 29 | This command creates a new palette with the specified ID. The palette will initially be a copy of palette 0. 30 | 31 | NB this command may fail if the VDP runs out of internal memory. 32 | 33 | ### Command 1: Delete a palette 34 | 35 | `VDU 23, 0, &C4, 1, ;` 36 | 37 | Removes the palette with the specified ID. If the palette is currently in use in the signal list, it will be removed from the signal list, with its entries replaced with palette 0. 38 | 39 | Calling this command with palette ID 0 will have no effect. 40 | 41 | If you call this command with palette ID 65535 then all palettes will be deleted. 42 | 43 | ### Command 2: Set a palette entry 44 | 45 | `VDU 23, 0, &C4, 2, ; , , , ` 46 | 47 | Changes the palette entry in the specified palette to the specified RGB value. 48 | 49 | The index value is the index of the palette entry to change. This will wrap around if it is greater than the number of entries in the palette. A 16 colour screen mode has entries numbered 0-15, a 4 colour screen mode has entries numbered 0-3, and a 2 colour screen mode has entries numbered 0-1. Attempting to set a palette entry at index 17 will set the entry at index 1, and so on. 50 | 51 | The colour values for this command are 8-bit values, with 0 being the darkest and 255 being the brightest, i.e. in RGB888 format, consistent with VDU 19. 52 | 53 | If this command is used with a palette ID that does not yet exist then it will attempt to create a new palette with the specified ID. 54 | 55 | ### Command 3: Set/Update the signal list 56 | 57 | `VDU 23, 0, &C4, 3, ;` 58 | 59 | This command is used to set the signal list. The source list must be stored in a buffer, and the buffer ID is passed as an argument to this command. Only the first block in a buffer is used. 60 | 61 | A signal list can be updated at any time, and the new signal list will take effect immediately. 62 | 63 | The [buffered commands API](Buffered-Commands-API.md) can be used to create a buffer and fill it with a signal list. 64 | 65 | A source signal list is a set of pairs of 16-bit values stored in a buffer, where the first value is a count of rows, and the second value is the palette ID to use for those rows. A single entry is therefore 4 bytes long. The 16-byte values must be stored in the buffer in little-endian format. 66 | 67 | A source signal list can be of any length, entries are read sequentially from the source buffer. If the total number of rows in the signal list is less than the number of rows in the screen, then the last palette in the signal list will be used for the remaining rows. If the list has more entries than there are rows on the screen then the extra items in the signal list will be ignored. 68 | 69 | The output signal list will remain in effect until it is replaced by a new signal list, or until it is reset. You are therefore free to do whatever you like with the buffer after the signal list has been set. 70 | 71 | By setting a signal list, and then adjusting the source buffer to contain different values, and then re-setting the signal list you can achieve a wide range of effects. When coupled with the VSYNC callback mechanism these effects can be run completely within the VDP without needing to involve your main program. 72 | 73 | ### Command 4: Reset the signal list 74 | 75 | `VDU 23, 0, &C4, 4` 76 | 77 | This command resets the signal list to the default state, where the default palette is used for all rows. 78 | 79 | ## Using copper to show all 64 colours 80 | 81 | As noted above, the Copper API allows for multiple palettes to be defined, and a signal list set to define which palettes should be used for scanout for different rows of the screen. This therefore allows access to all 64 colours in screen modes that otherwise would only show 2, 4 or 16 colours. 82 | 83 | All drawing operations to the framebuffer are performed as normal, using only the primary palette for colour lookups. 84 | 85 | If you wish to show a bitmap image in a 16 colour screen mode in a manner similar to the Amiga's "Hold and Modify" mode, you can use the Copper API to set up a signal list that will show all 64 colours on the screen. The bitmap data however will be drawn as if the primary palette is the only palette in use. You would therefore need to prepare your bitmap using pixel values that correspond to the primary palette entries, and then prepare palettes and a signal list to change the colours during scan-out. 86 | 87 | ## Interactions with sprites 88 | 89 | Software sprites are drawn into the framebuffer using the primary palette, and so their appearance on-screen will be affected by the signal list. 90 | 91 | Hardware sprites on the other hand are not drawn into the framebuffer, and so are not affected by the signal list. They are shown in their natural colours using the Agon's available 64 colours. 92 | -------------------------------------------------------------------------------- /docs/vdp/Font-API.md: -------------------------------------------------------------------------------- 1 | # VDU 23, 0, &95: Font management 2 | 3 | From Console8 VDP 2.8.0 onwards, the VDP now has an API to allow for different fonts to be uploaded to the VDP and used on your Agon. At this time the VDP supports mono-spaced fonts only, each only at a single size. Future versions of this API may introduce support for variable width fonts, and displaying text at different sizes. 4 | 5 | As with other APIs, the data for fonts is stored in buffers which are sent to the VDP using the [Buffered Commands API](Buffered-Commands-API.md). 6 | 7 | Generally when selecting a font to use, you will need to upload the font data to a buffer on the VDP, and then indicate that buffer contains a font. Once this has been done the font can be selected and used to draw text on the screen. The system font will always be available, and can be used by selecting font -1 (65535). 8 | 9 | You can define as many different fonts on the VDP as you have buffers available, and can switch between them as needed. Your font selection is tied to your currently selected cursor, so you can select different fonts for use with your graphics cursor and your text cursor. 10 | 11 | The commands for the font API are as follows: 12 | 13 | ### `VDU 23, 0, &95, 0, bufferId; flags`: Select font 14 | 15 | Select a font to use for drawing text. 16 | 17 | The `bufferId` here must refer to a buffer that has been uploaded to the VDP, and marked as a font using `VDU 23, 0, &95, 1, `, as described below, or -1 (65535) for the system font. 18 | 19 | The `flags` parameter is a bitfield which can be used to specify options for the font. The following flags are supported: 20 | 21 | | Bit | Description | 22 | | --- | ----------- | 23 | | 0 | Adjust cursor position to ensure text baseline is aligned | 24 | | 1-7 | Reserved for future use | 25 | 26 | If you wish to change the font within a line of text, you should use a flags setting of `1`. This will use data within the font to ensure that the cursor position is moved to keep the text baseline aligned. 27 | 28 | When changing the font at the start of a new line, you should use a flags setting of `0`, as otherwise the text may overlap the previous line. 29 | 30 | ### `VDU 23, 0, &95, 1, bufferId; width, height, ascent, flags`: Create font from buffer 31 | 32 | This command is used to mark a buffer as containing font data. The `bufferId` must refer to a buffer that has been uploaded to the VDP, and contains font data. The `width` and `height` parameters indicate the width and height of each character in the font in pixels, and `ascent` is the distance in pixels from the top of the character to the baseline. 33 | 34 | The `flags` parameter is reserved for future use, and should be set to 0. In the future it will be used for indicating variable width fonts, and other font properties. 35 | 36 | Font data is assumed to be a contiguous block of data, one character at a time, with a full 256 character definitions, from character 0 to 255. The buffer passed to this command should contain a single block of data of an appropriate size for the font. If the data has been uploaded in multiple parts, it should be concatenated into a single block before calling this command using the appropriate commands in the buffered commands API. 37 | 38 | Fonts are monochrome, and the data is assumed to be one character at a time. Each character is stored in a byte-aligned format, where each row of a character is stored in a number of bytes equal to `(width + 7) / 8`, with their pixels organised most significant bit first, with as many rows as indicated by the `height`. "Most significant bit first" means that the leftmost pixel of the character is stored in the most significant bit of the first byte, so a font that is 6 pixels wide would be stored in bits 7-2, with bits 1 and 0 ignored when rendering the font. 39 | 40 | ### `VDU 23, 0, &95, 2, bufferId; field, value;`: Set or adjust font property 41 | 42 | Allows you to set or adjust properties of a font that has been created using `VDU 23, 0, &95, 1, `. The `bufferId` must refer to a buffer that has been marked as containing font data. 43 | 44 | The `field` parameter indicates the property to set, and the `value` parameter is the value to set it to. Whilst the `value` must be sent as a 16-bit value, most of the fields will only use the least significant 8-bits of the sent value. The following fields are supported: 45 | 46 | | Field | Description | 47 | | ----- | ----------- | 48 | | 0 | width | 49 | | 1 | height | 50 | | 2 | ascent | 51 | | 3 | flags | 52 | | 4 | buffer for character pointers (for variable width fonts) * | 53 | | 5 | point size (defaults to 0) * | 54 | | 6 | inleading (defaults to 0) * | 55 | | 7 | exleading (defaults to 0) * | 56 | | 8 | weight (defaults to 400) * | 57 | | 9 | character set (defaults to 255) * | 58 | | 10 | code page (defaults to 1252) * | 59 | 60 | Fields 0-4 directly equate to the parameters passed to `VDU 23, 0, &95, 1, `. 61 | 62 | \* Please note that as of VDP 2.8.0, whilst data can be set for these fields, setting them will not affect the rendering of the font. They are reserved for future use. 63 | 64 | ### `VDU 23, 0, &95, 3, bufferId; []`: Reserved 65 | 66 | This function is reserved for future use, and should not be used at this time. 67 | 68 | (The intent is that this will be used to set the name of the font.) 69 | 70 | ### `VDU 23, 0, &95, 4, bufferId;`: Clear/Delete font 71 | 72 | Deletes a font that has been created using `VDU 23, 0, &95, 1, `. The `bufferId` must refer to a buffer that has been marked as containing font data. 73 | 74 | NB: This does not delete the buffer itself, only the font definition. The data remains intact in the buffer, and can be re-used to create a new font if desired. 75 | 76 | ### `VDU 23, 0, &95, 5, bufferId;`: Copy system font to buffer 77 | 78 | Copies the system font data into a buffer and makes a new font definition for it. 79 | 80 | The buffer at the `bufferId` will be cleared first and then the system font data will be copied into it. The buffer will then be marked as containing font data, and can be used as a font in the same way as any other font. 81 | 82 | This command will let you make multiple copies of the system font which can then be modified independently of each other using the buffered commands API. 83 | 84 | -------------------------------------------------------------------------------- /docs/vdp/PLOT-Commands.md: -------------------------------------------------------------------------------- 1 | # VDU 25: PLOT commands 2 | 3 | `VDU 25, code, x; y;` 4 | 5 | The Agon VDP system supports a number of `PLOT` commands via `VDU 25`, which are used to draw lines, circles, and other shapes on the screen. The command set is inherited from Acorn's BBC Micro, plus Acorn's Graphics eXtension ROM (GXR). 6 | 7 | PLOT commands sent to the VDP all require a command byte, followed by two 16-bit values for X and Y coordinates. The command byte is used to specify the drawing operation, and the mode in which the drawing operation is performed. 8 | 9 | Most PLOT commands require additional coordinates than the single pair provided with the command. The graphics system works using a concept of a "graphics cursor", and will keep track of the last few positions of the graphics cursor. Every PLOT command "pushes" a copy of the current graphics cursor position onto a stack, and then moves the graphics cursor to the new position. Commands that require additional coordinates will look at the last few positions on the stack to determine the additional coordinates. 10 | 11 | Support for PLOT commands has grown over time, but is still only a subset of those available on a BBC Micro with a GXR ROM. 12 | 13 | PLOT commands are essentially split into a drawing operation, and a mode that controls how the drawing operation is performed. There are 8 different modes for each operation. The command byte is effectively split into two parts where the lower 3 bits define the mode, and the upper 5 bits define the drawing operation. 14 | 15 | The complete set of PLOT codes supported by the Agon VDP follows. For completeness, all commands from Acorn's command set are shown, including those that are not yet supported. 16 | 17 | | PLOT code | (Decimal) | Effect | 18 | | --------- | --------- | ------ | 19 | | &00-&07 | 0-7 | Solid line, includes both ends | 20 | | &08-&0F | 8-15 | Solid line, final point omitted | 21 | | &10-&17 | 16-23 | Dot-dash line, includes both ends, pattern restarted §§§§ | 22 | | &18-&1F | 24-31 | Dot-dash line, final point omitted, pattern restarted §§§§ | 23 | | &20-&27 | 32-39 | Solid line, first point omitted | 24 | | &28-&2F | 40-47 | Solid line, both points omitted | 25 | | &30-&37 | 48-55 | Dot-dash line, first point omitted, pattern continued §§§§ | 26 | | &38-&3F | 56-63 | Dot-dash line, both points omitted, pattern continued §§§§ | 27 | | &40-&47 | 64-71 | Point plot | 28 | | &48-&4F | 72-79 | Line fill left and right to non-background §§ | 29 | | &50-&57 | 80-87 | Triangle fill | 30 | | &58-&5F | 88-95 | Line fill right to background §§ | 31 | | &60-&67 | 96-103 | Rectangle fill | 32 | | &68-&6F | 104-111 | Line fill left and right to foreground §§ | 33 | | &70-&77 | 112-119 | Parallelogram fill | 34 | | &78-&7F | 120-127 | Line fill right to non-foreground §§ | 35 | | &80-&87 | 128-135 | Not supported (Flood until non-background) | 36 | | &88-&8F | 136-143 | Not supported (Flood until foreground) | 37 | | &90-&97 | 144-151 | Circle outline | 38 | | &98-&9F | 152-159 | Circle fill | 39 | | &A0-&A7 | 160-167 | Circular arc §§§§ | 40 | | &A8-&AF | 168-175 | Circular segment §§§§ | 41 | | &B0-&B7 | 176-183 | Circular sector §§§§ | 42 | | &B8-&BF | 184-191 | Rectangle copy/move | 43 | | &C0-&C7 | 192-199 | Not supported (Ellipse outline) | 44 | | &C8-&CF | 200-207 | Not supported (Ellipse fill) | 45 | | &D0-&D7 | 208-215 | Not defined | 46 | | &D8-&DF | 216-223 | Fill path (Experimental - Not defined on Acorn systems) §§§§ | 47 | | &E0-&E7 | 224-231 | Not defined | 48 | | &E8-&EF | 232-239 | Bitmap plot § | 49 | | &F0-&F7 | 240-247 | Not defined | 50 | | &F8-&FF | 248-255 | Not defined | 51 | 52 | Within each group of eight plot codes, the effects are as follows: 53 | 54 | | Plot code | Effect | 55 | | --------- | ------ | 56 | | 0 (8) | Move relative | 57 | | 1 (9) | Plot relative in current foreground colour | 58 | | 2 (A) | Plot relative in logical inverse colour §§§ | 59 | | 3 (B) | Plot relative in current background colour | 60 | | 4 (C) | Move absolute | 61 | | 5 (D) | Plot absolute in current foreground colour | 62 | | 6 (E) | Plot absolute in logical inverse colour §§§ | 63 | | 7 (F) | Plot absolute in current background colour | 64 | 65 | Codes 0-3 use the position data provided as part of the command as a relative position, adding the position given to the current graphical cursor position. Codes 4-7 use the position data provided as part of the command as an absolute position, setting the current graphical cursor position to the position given. 66 | 67 | The various "Line fill" plot commands have an additional effect, which is to adjust the graphics cursor position to the right-hand edge of the filled line, if one was drawn. 68 | 69 | § Support added in Agon Console8 VDP 2.1.0
70 | §§ Support added in Agon Console8 VDP 2.2.0
71 | §§§ Support added in Agon Console8 VDP 2.6.0
72 | §§§§ Support added in Agon Console8 VDP 2.7.0
73 | 74 | 75 | ## Interaction with GCOL paint modes 76 | 77 | The GCOL command (`VDU 18, mode, colour`) is used to set the paint mode for the PLOT command. The paint mode is used to control how the PLOT command interacts with the existing pixels on the screen. 78 | 79 | Up until Console8 VDP 2.6.0 the only fully supported GCOL paint mode was mode 0, which sets the pixel to the target colour value. This is the default mode, and is used if no GCOL command has been issued. There was limited support for mode 4, which inverts the pixel, but this was only supported for straight line drawing operations. 80 | 81 | As of Console8 VDP 2.6.0, the following modes are now available for all currently supported plot operations: 82 | 83 | | Mode | Effect | 84 | | ---- | ------ | 85 | | 0 | Set on-screen pixel to target colour value | 86 | | 1 | OR value with the on-screen pixel | 87 | | 2 | AND value with the on-screen pixel | 88 | | 3 | EOR value with the on-screen pixel | 89 | | 4 | Invert the on-screen pixel | 90 | | 5 | No operation | 91 | | 6 | AND the inverse of the specified colour with the on-screen pixel | 92 | | 7 | OR the inverse of the specified colour with the on-screen pixel 93 | 94 | PLOT commands using an "inverse" plot code are essentially identical to setting a GCOL paint mode of 4, and will temporarily override the current GCOL paint mode if a different GCOL paint mode is set. 95 | 96 | 97 | ## Line drawing (PLOT codes &00-&3F) 98 | 99 | For all of the line drawing plot codes, the position given with the PLOT command is the end point of the line. The start point of the line is the last position on the graphics cursor stack. 100 | 101 | Support for plotting dotted lines was added in Agon Console8 VDP 2.7.0. The default pattern is 1 pixel on, 1 pixel off, but this can be changed using the `VDU 23, 6, n1-n8` command which takes 8 bytes of data. The length of pattern can be set using `VDU 23, 0, 242, n` where n is the number of pixels in the pattern. Setting a length of zero will reset to the default pattern with a length of 8. When drawing a line, the pattern is repeated as many times as necessary to draw the line and will be used from the top-most bit of the pattern data, repeating as necessary to draw the whole line. 102 | 103 | 104 | ## Line fill codes (PLOT codes &48-&4F, &58-5F, &68-6F, &78-&7F) 105 | 106 | These various PLOT codes will fill horizontal lines on the screen. When executing "drawing" plot codes, the graphics system will scan the line to find appropriate start and end positions, depending on the PLOT code used and the screen contents. The final calculated end position will be pushed to the graphics cursor stack. 107 | 108 | 109 | ## Filled triangles (PLOT codes &50-&57) 110 | 111 | Filled triangles are drawn using the last two positions on the graphics cursor stack and the position given with the PLOT command. 112 | 113 | The behaviour of the triangle fill command has changed slightly in Agon Console8 VDP 2.6.0, and you may observe some slight differences in the exact pixels drawn when using this command. Unfortunately the old behaviour was not compatible with the new GCOL paint modes, and so the behaviour had to be changed. The behaviour is consistent with general "best practice" for triangle fill algorithms, and so should be more predictable and reliable. As an example, with the revised triangle plotting it is possible to draw a fan of triangles using an EOR paint mode and you will not see the edges of the triangles "cancel each other out" as you would have done with the old behaviour. 114 | 115 | This new behaviour is not entirely consistent with the BBC Micro or GXR ROM, but it is more consistent with modern graphics systems and should be more predictable and reliable. In practice, the differences are minimal and should not affect most programs. 116 | 117 | 118 | ## Filled rectangles (PLOT codes &60-&67) 119 | 120 | Filled rectangles are drawn using the last position on the graphics cursor stack and the position given with the PLOT command to define two corners of a rectangle. 121 | 122 | 123 | ## Filled parallelograms (PLOT codes &70-&77) 124 | 125 | Parallelograms require three points to be defined. They will therefore use the last two points pushed to the graphics cursor stack, coupled with the position given with the PLOT command. 126 | 127 | The three given points represent any three corners of the parallelogram. The first and last (third) points are used to define opposing corners of the parallelogram. The graphics system will calculate the fourth corner of the parallelogram as a point opposite to the second corner, and then fill the shape. 128 | 129 | 130 | ## Circle drawing (PLOT codes &90-&9F) 131 | 132 | Circle drawing requires two points to be defined. They will therefore use the last point pushed to the graphics cursor stack, coupled with the position given with the PLOT command. The first point is the centre of the circle, and the second point is a point on the circumference of the circle. 133 | 134 | 135 | ## Arcs, segments, and sectors (PLOT codes &A0-&B7) §§§§ 136 | 137 | Arcs, segments, and sectors require three points to be defined. They will therefore use the last two points pushed to the graphics cursor stack, coupled with the position given with the PLOT command. 138 | 139 | Arcs, segments, and sectors are all drawn anticlockwise from a start point to an end. 140 | 141 | The first point defines the start of the arc, segment, or sector, which is a point on the circumference of the circle. The second point defines the centre of the circle that the arc, segment, or sector is part of. The distance from the first point to the second point defines the radius of the circle. The final point (provided with the PLOT command) defines the end of the arc, segment, or sector. This point does not have to be on the circumference of the circle, and the graphics system will calculate the point on the circumference that the arc, segment, or sector ends at. Instead the final point is effectively used to define the angle of the arc. 142 | 143 | 144 | ## Rectangle copy/move (PLOT codes &B8-&BF) 145 | 146 | These PLOT codes are interpreted slightly differently from others. The purpose of these commands is to copy or move a rectangle of pixels from one location to another. The rectangle is defined by the last two positions on the graphics cursor stack, and the position provided with the PLOT command is the destination to copy the rectangle to. 147 | 148 | A "move" operation will copy the rectangle to the new location, and then clear the original rectangle using the currently defined background colour. (NB the background GCOL paint mode is _not_ used when filling the original rectangle - the pixels will be set with the background colour). A "copy" operation will copy the rectangle to the new location, but leave the original rectangle in place. 149 | 150 | | PLOT code | Effect | 151 | | --------- | ------ | 152 | | &B8 | Move cursor relative to last position | 153 | | &B9 | Relative rectangle move | 154 | | &BA | Relative rectangle copy | 155 | | &BB | Relative rectangle copy | 156 | | &BC | Move cursor to absolute position | 157 | | &BD | Absolute rectangle move | 158 | | &BE | Absolute rectangle copy | 159 | | &BF | Absolute rectangle copy | 160 | 161 | 162 | ## Fill path - Experimental (PLOT codes &D8-&DF) §§§§ 163 | 164 | The ability to draw a filled path was added in the Agon Console8 VDP 2.7.0 release. This command was not part of Acorn's original PLOT command set, either on the BBC Micro, in their Graphics Extension ROM, or in the later Acorn Archimedes operating systems. For now, it should therefore be considered to be experimental. Whilst at the time of writing this documentation it is thought that this command is not likely to change, it _is_ possible that the command may be removed or altered in future releases. 165 | 166 | This command will fill a path defined by an arbitrary number of points. The path must be at least three points long. 167 | 168 | As the path is is of an arbitrary length the nature of this commands operation differs from other PLOT commands. 169 | 170 | All new paths will be started with the last two points pushed to the graphics cursor stack, plus the position given with the PLOT command. The path thus starts with three points and therefore, if no subsequent commands are received to extend the path, a triangle will be drawn. 171 | 172 | If the next VDU command received immediately after a fill path plotting command is also a matching "Fill path" PLOT command then the path will be extended with the new position given with the PLOT command. If the next VDU command is not a matching "Fill path" PLOT command then the path will be considered to be complete, i.e. the path will be closed by connecting the last point to the first one and the graphics system will then fill the area defined by the path. 173 | 174 | Please note that any "move" PLOT command will be interpreted as closing the current path. Whilst absolute and relative positioning PLOT commands can be combined when building up a path, changing between different codes (such as from "foreground" to "background" PLOTs) will be interpreted as closing the current path and starting a new path. 175 | 176 | If any other VDU commands are received after a "Fill path" PLOT command, then the path will be considered to be complete and the graphics system will fill the area defined by the path. Similarly if there is a significant delay between the VDP receiving "fill path" PLOT commands, even if the next command uses a matching PLOT code, then the path will be considered to be complete and the graphics system will fill the area defined by the path. 177 | 178 | As a result of this mode of operation, it is not possible to interactively enter multiple "fill path" PLOT commands one after another at the BASIC command prompt using separate commands over multiple lines, as the system will interpret the character output for command entry as closing the current path. Instead filled paths must be defined in a single command sequence, uninterrupted by other VDU commands, usually as part of a program. 179 | 180 | 181 | ## Bitmap plots (PLOT codes &E8-&EF) 182 | 183 | Bitmap plots will draw the currently selected bitmap to the screen. 184 | 185 | Before a bitmap plot can be used a valid bitmap must be selected using either `VDU 23, 27, 0, id` or `VDU 23, 27, &20, bufferId;`. 186 | 187 | Bitmap plots will only draw non-transparent pixels to the screen. When using "foreground" PLOTs, the bitmap is drawn to screen using the current foreground GCOL painting mode using the colour from the bitmap. When using "background" PLOTs, the bitmap is drawn to screen using the current background GCOL painting mode using the currently selected background colour. Inverse plot modes invert on-screen pixels that correspond to non-transparent pixels in the bitmap. 188 | 189 | As of Console8 VDP version 2.9.0 it is possible to set an affine transform matrix to be applied to bitmap plots. This allows for bitmaps to be scaled, rotated, sheared, and translated when being drawn onto the screen. The transform matrix is set using `VDU 23, 0, &96, 1, bufferId;` which is documented in the [System Commands](System-Commands.md) documentation. The buffered commands API provides commands to set and manipulate the transform matrix, and is documented in the [Buffered Commands](Buffered-Commands-API.md) documentation. 190 | 191 | 192 | ## PLOT support prior to VDP 1.04 193 | 194 | Prior to VDP 1.04 the PLOT command support was very limited, did not support relative positioning, and had buggy and incorrect interpretations of some of the PLOT codes. As of VDP 1.04 the PLOT command support has been greatly improved, and is now much more compatible with the BBC Micro and GXR ROM. 195 | 196 | The most significant bug was the mis-interpretation of several "move" commands to instead be "draw". As a result, some programs written for earlier versions of the VDP firmware may no longer work correctly. Fixing these programs however is usually very straightforward and usually just involves changing the PLOT code used. 197 | 198 | 199 | ## Compatibility 200 | 201 | If the VDP does not recognise a plot operation, it will be ignored. This can allow you to write programs that "feature detect" whether the VDP supports a particular plot operation, and then use it if it does, or fall back to an alternative if it does not. 202 | -------------------------------------------------------------------------------- /docs/vdp/Screen-Modes.md: -------------------------------------------------------------------------------- 1 | # Screen Modes 2 | 3 | The Agon VDP supports a number of different screen modes, which are listed below. 4 | 5 | Screen modes are selected using `VDU 22, mode`, or in BASIC using `MODE mode`. 6 | 7 | The list of screen modes available for use got revised and greatly expanded in VDP version 1.04. The revision was mostly to make the screen modes more compatible with the VGA standards, and thus more compatible with modern monitors. The original screen modes are still available, but are now considered legacy modes. 8 | 9 | It should be noted that whilst the Agon VDU command system is designed to be compatible with the BBC Micro, the screen modes are not. The BBC Micro has a different set of screen modes, and the Agon VDP does not support them. 10 | 11 | By default, the Agon VDU system uses and adopts the BBC Micro's "logical" coordinate system for graphics, which means that each screen mode appears to be 1280x1024 to software with the graphics origin 0,0 point at the bottom left of the screen. As a result programs written the BBC Micro can usually be fairly easily adapted. 12 | 13 | This logical coordinate system differs from the BBC Micro and later Acorn systems in that Acorn systems all used round numbers for the multiplier between the logical and physical coordinate systems. (This meant that on later Acorn systems some screen modes used logical resolutions other than 1024x1280, depending on the physical resolution of the mode.) On Agon systems, the multiplier for the vertical resolution is, essentially never a round number. 14 | 15 | To work around the limitations of the logical coordinate system, it is possible to change the graphics system to use physical coordinates instead of logical coordinates. 16 | 17 | There are two VDU commands that will affect the screen modes that are available, and how the drawing system works. 18 | 19 | ## VDU Commands 20 | 21 | ### `VDU 22, mode` 22 | 23 | This command selects a screen mode, where the screen mode is a single byte value and must be a mode from the list below. 24 | 25 | Screen modes numbered above 128 are double-buffered, meaning that the screen is drawn to an off-screen buffer, and then the buffer is copied to the screen. This prevents flickering when drawing to the screen. Double-buffered mode numbers are equivalent to a regular mode with 128 added. Please note that owing to memory limitations not all screen modes can be double-buffered. 26 | 27 | As drawing operations, when in a double-buffered mode, are only performed in the off-screen buffer this means that the screen will not be updated until the active buffer is swapped. This means, for instance, that if you enter a double-buffered screen mode in BASIC by using `MODE 129` then commands that you type will not be visible, as your input is being written to the off-screen buffer. Commands will still be processed, but you will only see their effect when the buffer is swapped. Buffers are swapped using `VDU 23, 0, &C3` 28 | 29 | It may sometimes not be possible to change into a screen mode, for instance because the VDP no longer has enough memory to support the mode. In this case the system will fall back to the current mode, and if that fails to the default mode, which is mode 1. All modes should always be available after a reset. 30 | 31 | ### `VDU 23, 0, &C0, n` 32 | 33 | Turn logical screen scaling on and off, where 1=on and 0=off. 34 | 35 | When logical scaling is turned off, the graphics system will no longer use the 1280x1024 logical coordinate system and instead use pixel coordinates. The screen origin point at 0,0 will change to be the top left of the screen, and the Y axis will go down the screen instead of up. 36 | 37 | Support for this was added in VDP 1.03. 38 | 39 | 40 | ### `VDU 23, 0, &C1, n` 41 | 42 | Switch legacy modes on or off. 43 | 44 | By default, the original screen modes 0-4 are not available and are instead replaced by new modes that are more compatible with modern monitors. For compatibility with older software, written for Agon systems running earlier versions of the VDP firmware, this command can be used to switch back to those original, legacy, screen modes. 45 | 46 | Support for this was added in VDP 1.04 47 | 48 | 49 | ### `VDU 23, 0, &C3` 50 | 51 | Swap the screen buffer (double-buffered modes only) or wait for VSYNC (all modes). 52 | 53 | This command will swap the screen buffer, if the current screen mode is double-buffered, doing so at the next VSYNC. If the current screen mode is not double-buffered then this command will wait for the next VSYNC signal before returning. This can be used to synchronise the screen with the vertical refresh rate of the monitor. 54 | 55 | Waiting for VSYNC can be useful for ensuring smooth graphical animation, as it will prevent tearing of the screen. 56 | 57 | (In BASIC performing a `*FX 19` command will also wait for VSYNC, but will not swap the screen buffer.) 58 | 59 | Support for this was added in VDP 1.04 60 | 61 | 62 | ## Screen modes 63 | 64 | Modes over 128 are double-buffered 65 | 66 | ### From Version 1.04 or greater 67 | 68 | | Mode | Horz | Vert | Cols | Refresh | 69 | |-----:|-----:|-----:|-----:|--------:| 70 | |*** 0 | 640 | 480 | 16 | 60hz | 71 | | * 1 | 640 | 480 | 4 | 60hz | 72 | | 2 | 640 | 480 | 2 | 60hz | 73 | | 3 | 640 | 240 | 64 | 60hz | 74 | | 4 | 640 | 240 | 16 | 60hz | 75 | | 5 | 640 | 240 | 4 | 60hz | 76 | | 6 | 640 | 240 | 2 | 60hz | 77 | | ** 7 | n/a | n/a | 16 | 60hz | 78 | | 8 | 320 | 240 | 64 | 60hz | 79 | | 9 | 320 | 240 | 16 | 60hz | 80 | | 10 | 320 | 240 | 4 | 60hz | 81 | | 11 | 320 | 240 | 2 | 60hz | 82 | | 12 | 320 | 200 | 64 | 70hz | 83 | | 13 | 320 | 200 | 16 | 70hz | 84 | | 14 | 320 | 200 | 4 | 70hz | 85 | | 15 | 320 | 200 | 2 | 70hz | 86 | | 16 | 800 | 600 | 4 | 60hz | 87 | | 17 | 800 | 600 | 2 | 60hz | 88 | | 18 | 1024 | 768 | 2 | 60hz | 89 | | § 19 | 1024 | 768 | 4 | 60hz | 90 | | § 20 | 512 | 384 | 64 | 60hz | 91 | | § 21 | 512 | 384 | 16 | 60hz | 92 | | § 22 | 512 | 384 | 4 | 60hz | 93 | | § 23 | 512 | 384 | 2 | 60hz | 94 | | §§ 24 | 640 | 512 | 16 | 60hz | 95 | | §§ 25 | 640 | 512 | 4 | 60hz | 96 | | §§ 26 | 640 | 512 | 2 | 60hz | 97 | | §§ 27 | 640 | 256 | 64 | 60hz | 98 | | §§ 28 | 640 | 256 | 16 | 60hz | 99 | | §§ 29 | 640 | 256 | 4 | 60hz | 100 | | §§ 30 | 640 | 256 | 2 | 60hz | 101 | | 129 | 640 | 480 | 4 | 60hz | 102 | | 130 | 640 | 480 | 2 | 60hz | 103 | | 132 | 640 | 240 | 16 | 60hz | 104 | | 133 | 640 | 240 | 4 | 60hz | 105 | | 134 | 640 | 240 | 2 | 60hz | 106 | | 136 | 320 | 240 | 64 | 60hz | 107 | | 137 | 320 | 240 | 16 | 60hz | 108 | | 138 | 320 | 240 | 4 | 60hz | 109 | | 139 | 320 | 240 | 2 | 60hz | 110 | | 140 | 320 | 200 | 64 | 70hz | 111 | | 141 | 320 | 200 | 16 | 70hz | 112 | | 142 | 320 | 200 | 4 | 70hz | 113 | | 143 | 320 | 200 | 2 | 70hz | 114 | | § 145 | 800 | 600 | 2 | 60hz | 115 | | § 146 | 1024 | 768 | 2 | 60hz | 116 | | § 149 | 512 | 384 | 16 | 60hz | 117 | | § 150 | 512 | 384 | 4 | 60hz | 118 | | § 151 | 512 | 384 | 2 | 60hz | 119 | | §§ 153 | 640 | 512 | 4 | 60hz | 120 | | §§ 154 | 640 | 512 | 2 | 60hz | 121 | | §§ 156 | 640 | 256 | 16 | 60hz | 122 | | §§ 157 | 640 | 256 | 4 | 60hz | 123 | | §§ 158 | 640 | 256 | 2 | 60hz | 124 | 125 | \* Mode 1 is the "default" mode, and is the mode that the system will use on startup. It is also the mode that the system will fall back to use if it was not possible to change to the requested mode. 126 | 127 | \** Mode 7 is the "Teletext" mode, and essentially works in a very similar manner to the BBC Micro's Teletext mode, which was also mode 7. 128 | 129 | \*** As of Console8 VDP 2.8.0, mode 0 is now the mode that the VDP will use on startup. The fallback mode when a requested mode is not available remains mode 1. 130 | 131 | § Support for screen modes 19-23, 145-146 and 149-151 was added in Console8 VDP 2.10.0 132 | 133 | §§ Support for screen modes 24-30, and 153-158 was added in Console8 VDP 2.13.0 134 | 135 | ### Legacy modes (prior to 1.04) 136 | 137 | | Mode | Horz | Vert | Cols | Refresh | 138 | |-----:|-----:|-----:|-----:|--------:| 139 | | 0 | 1024 | 768 | 2 | 60hz | 140 | | 1 | 512 | 384 | 16 | 60hz | 141 | | 2 | 320 | 200 | 64 | 75hz | 142 | | 3 | 640 | 480 | 16 | 60hz | 143 | -------------------------------------------------------------------------------- /docs/vdp/VDP-Variables.md: -------------------------------------------------------------------------------- 1 | # VDP Variables 2 | 3 | VDP variables provide a way to both read and change the state of the VDP. They can be used to enable an experimental feature, read the current state of the VDP, or change the state of the VDP. 4 | 5 | VDU variables contain 16-bit values. Some variables may only use the lower 8 bits. 6 | 7 | Variables are currently split into three general categories: test flags, system settings, and VDU variables. In the future we will add more variables to expose the state of the audio system. These categorites are given some broad ranges of variable IDs to allow for future expansion, and to allow for easy identification of the type of variable. 8 | 9 | Test flags are used to enable a feature that may either be experimental, not yet fully implemented, have an API that might change, or not fully tested. 10 | 11 | System settings variables provide access to VDP system information, such as memory usage, real-time clock data, and keyboard settings. 12 | 13 | VDU variables provide access to the graphics system state, including context-specific information that may change when switching [context](Context-Management-API.md). 14 | 15 | The VDP variables system was added in Console8 VDP 2.9.0, and was initially used only for test flags. 16 | 17 | The Console8 VDP 2.12.0 release has added many new variables that expose the state of the VDP, and allow for changes to be made to that state. It is also now possible to use VDP variables in buffered commands. This allows for conditional commands to be used to check against a variable, and the contents of a variable to be read into a buffer. 18 | 19 | 20 | ## Variable APIs 21 | 22 | There are just two API calls to directly work with VDP variables, one to set a variable, and another to clear it. As of VDP 2.12.0 the buffered command API also allows for the reading of variables into a buffer, and for conditional commands to be used to perform their checks against a variable. 23 | 24 | The commands to set and clear variables are documented in the [system commands](System-Commands.md) documentation. Briefly they are: 25 | 26 | * `VDU 23, 0, &F8, variableId; value;`: Set a VDP Variable 27 | * `VDU 23, 0, &F9, variableId;`: Clear a VDP Variable 28 | 29 | The buffered command API is documented in the [buffered commands](Buffered-Commands-API.md) documentation. The "conditional" commands there are now extended to allow for the use of variables, and an additional command to read the value of a variable and store it into a buffer has been added. 30 | 31 | 32 | ## Variable ID ranges 33 | 34 | All variables listed are available from VDP 2.12.0 onwards. Variables that were introduced in 2.9.0 and 2.11.0 are marked as such. 35 | 36 | The broad ranges of variable IDs are as follows: 37 | 38 | | Variable ID range | Description | 39 | | ----------- | ----------- | 40 | | &1-&FF | Test flags | 41 | | &100-&FFF | System settings | 42 | | &1000-&1FFF | VDU variables (graphics/text system) | 43 | | &2000-&2FFF | Reserved for audio system variables | 44 | | &3000-&3FFF | Reserved for future use | 45 | | &4000-&FFFF | Available for general use | 46 | 47 | The system will not prevent you from using variables in reserved ranges, although inside the "VDU variables" range values that the system does not directly support will not be stored, and cannot be read. 48 | 49 | 50 | ## Test Flags 51 | 52 | As of Console8 VDP 2.9.0 the following test flags are supported: 53 | 54 | | Variable ID | Value | Description | 55 | | ------- | ----- | ----------- | 56 | | 1 | 0 (any) | Enable the Affine Transforms feature (available from 2.9.0) | 57 | | 2 | 0 (any) | Enable hardware sprites | 58 | 59 | If a flag is set that is not recognised then it will have no effect. This means that if a feature graduates from being a test feature and no longer requires a flag to be set for use then, so long as the API for the feature remains the same, software that sets the flag to enable the feature will still work. 60 | 61 | For the current test flags that the VDP supports, any value can be set to enable the feature. Future flags may require specific values to be set to control how the feature works. 62 | 63 | 64 | ## System Variables 65 | 66 | Broadly speaking, system variables are used to read and change the state and configuration of the VDP that are not _directly_ related to the current graphics context state or screen mode. Within the system variables block there are sub-blocks for different types of system information. 67 | 68 | The sub-ranges within system variables are broadly as follows: 69 | 70 | | Block | Description | 71 | | ----------- | ----------- | 72 | | &100-&1FF | Communications system settings | 73 | | &200-&208 | Real-time clock data | 74 | | &209-&20F | Reserved for future use | 75 | | &210-&21F | VDP memory information | 76 | | &220-&22F | Keyboard settings | 77 | | &230-&23F | Context management | 78 | | &240-&2FF | Reserved for future use | 79 | | &300-&3FF | Graphical system enhancement settings/flags | 80 | | &400-&4FF | Bitmap/Sprite system control settings | 81 | | &500-&FFF | Reserved for future use | 82 | 83 | Many system variables can be set and adjusted by other VDU commands 84 | 85 | As of Console8 VDP 2.12.0 the following system variables are supported: 86 | 87 | | Variable ID | Value | Read-only | Clearable | Description | 88 | | ------- | ----- | --- | --- | ----------- | 89 | | &0101 | 0/1 | | X | Full duplex UART hardware flow control flag. This is intended for internal use by MOS. NB setting this flag will break communications with MOS unless a suitable version of MOS that supports full duplex flow control. The first version of MOS to support this is MOS 3.0 alpha 3 | 90 | | &0102 | n/a | | X | Reserved for future use (Buffer size on MOS for VDP protocol packets) | 91 | | &0110 | 0/1 | | X | Reserved for future use (Echo back received data, for redirect/spool, with a suitable version of MOS that supports this feature) | 92 | | &0200 | 0-999 | | | Real-time clock year | 93 | | &0201 | 1-12 | | | Real-time clock month | 94 | | &0202 | 1-31 | | | Real-time clock day | 95 | | &0203 | 0-23 | | | Real-time clock hour | 96 | | &0204 | 0-59 | | | Real-time clock minute | 97 | | &0205 | 0-59 | | | Real-time clock second | 98 | | &0206 | 0-999 | X | | Real-time clock millisecond | 99 | | &0207 | 0-6 | X | | Real-time clock weekday | 100 | | &0208 | 0-366 | X | | Real-time clock day of year | 101 | | &0210 | | X | | Free PSRAM low bytes | 102 | | &0211 | | X | | Free PSRAM high bytes | 103 | | &0212 | | X | | Number of buffers used | 104 | | &0220 | 0-17 | | | Keyboard layout (setting to an invalid number will set to zero) | 105 | | &0221 | 0/1 | | | Control keys on/off (setting to any non-zero value sets to 1) | 106 | | &0230 | 0-255 | | | Current active context ID | 107 | | &0300 | 0 (any) | | X | Tile engine flag (enables layers commands, available from VDP 2.11.0) | 108 | | &0310 | 0 (any) | | X | Enables copper features flag | 109 | | &0400 | 0 (any) | | X | Prefer hardware sprites flag. When set, all sprites will be set to be hardware sprites after calling the "Reset sprites" API, if the "Enable hardware sprites" test flag has also been set | 110 | 111 | 112 | ## VDU Variables 113 | 114 | VDU variables are numbered in the range &1000-&1FFF and are used to expose information on the current graphics system state. This includes both information about the current screen mode, and the current context state. 115 | 116 | The set of variables are loosely based on the VDU variables available in Acorn's RISC OS operating system, and where appropriate they are numbered the same. The Agon VDP includes many extensions to include additional information that is specific to the Agon platform. 117 | 118 | All variables within this range are reserved for use by the VDU system. Any values that are not recognised will not be stored, and cannot be read. 119 | 120 | Flag variables use values 0 to indicate disabled, and 1 to indicate enabled. Setting a flag to any non-zero value is counted as if setting to 1. 121 | 122 | Some variables provide coordinates. For those variables that are marked as "screen coordinates", the origin is at the top-left of the screen, and the location is measured in pixels. For those variables that are marked as "character coordinates", the origin is at the top-left of the screen, and the location is measured in characters. Variables shown as "OS coordinates" will reflect the currently selected coordinate system, as defined in variable &1057. When the default coordinate system is selected, the origin is at the bottom-left of the screen, and the location is measured in OS units, where the screen is defined as 0-1279 for X and 0-1023 for Y. 123 | 124 | | Variable ID | Value | Read-only | Clearable | Description | 125 | | ------- | ----- | --- | --- | ----------- | 126 | | 0x1001 | | X | | Text columns - (characters) | 127 | | 0x1002 | | X | | Text rows - (characters) | 128 | | 0x1003 | 1/3/15/63 | X | | Max logical colour number for current screen mode | 129 | | 0x100B | | X | | Screen width in pixels - 1 | 130 | | 0x100C | | X | | Screen height in pixels - 1 | 131 | | 0x100D | 1/2 | X | | Number of screen banks (1 for single-buffered modes, 2 for double-buffered) | 132 | | 0x1017 | 0-255 | | | Current line thickness (pixels) | 133 | | 0x1018 | | | | Text cursor, absolute X position (chars) | 134 | | 0x1019 | | | | Text cursor, absolute Y position (chars) | 135 | | 0x1020 | | | | Frame counter low word (the frame counter is a 32-bit value) | 136 | | 0x1021 | | | | Frame counter high word | 137 | | 0x1022 | | | | Number of frames to pause on newline when the "Ctrl" key is held * | 138 | | 0x1023 | | | | Current number of frames being waited for * | 139 | | 0x1055 | | X | | Current screen mode number | 140 | | 0x1056 | 0/1 | | | Legacy modes flag | 141 | | 0x1057 | 0/1 | | | Coordinate system (0 = screen/pixel coordinates, 1 = logical/OS (default)) | 142 | | 0x1058 | 0/1/2*/3* | | | Paged mode flag (0 = disabled, 1 = enabled, 2 = disabled, but temporary paged mode is on *, 3 = enabled, and temporary paged mode is on *) | 143 | | 0x1059 | | | | Paged mode context row count * | 144 | | 0x1066 | 0-255 | | | Cursor behaviour flags byte, as set via VDU 23,16,x,y | 145 | | 0x1067 | 0/1 | | | Text cursor visibility | 146 | | 0x1068 | | | | Text cursor block horizontal start column | 147 | | 0x1069 | | | | Text cursor block horizontal end column | 148 | | 0x106A | 0-31 | | | Text cursor block vertical start row | 149 | | 0x106B | | | | Text cursor block vertical end row | 150 | | 0x106C | 0-3 | | | Text cursor appearance, write only (0 = steady, 1 = off, 2 = fast blink, 3 = slow blink) | 151 | | 0x1070 | | X | | Active cursor type (0 = Text cursor, 1 = Graphics cursor) | 152 | | 0x1080 | | | | Graphics window, LH column, screen coordinates | 153 | | 0x1081 | | | | Graphics window, Bottom row, screen coordinates | 154 | | 0x1082 | | | | Graphics window, RH column, screen coordinates | 155 | | 0x1083 | | | | Graphics window, Top row, screen coordinates | 156 | | 0x1084 | | | | Text window, LH column, character coordinates | 157 | | 0x1085 | | | | Text window, Bottom row, character coordinates | 158 | | 0x1086 | | | | Text window, RH column, character coordinates | 159 | | 0x1087 | | | | Text window, Top row, character coordinates | 160 | | 0x1088 | | | | Graphics origin, X, OS coordinates | 161 | | 0x1089 | | | | Graphics origin, Y, OS coordinates | 162 | | 0x108A | | | | Graphics cursor, X, OS coordinates | 163 | | 0x108B | | | | Graphics cursor, Y, OS coordinates | 164 | | 0x108C | | | | Oldest Graphics cursor, X, screen coordinates | 165 | | 0x108D | | | | Oldest Graphics cursor, Y, screen coordinates | 166 | | 0x108E | | | | Previous Graphics cursor, X, screen coordinates | 167 | | 0x108F | | | | Previous Graphics cursor, Y, screen coordinates | 168 | | 0x1090 | | | | Graphics cursor, X, screen coordinates | 169 | | 0x1091 | | | | Graphics cursor, Y, screen coordinates | 170 | | 0x1097 | 0-7 | | | GCOL action for foreground colour | 171 | | 0x1098 | 0-7 | | | GCOL action for background colour | 172 | | 0x1099 | 0-63 | | | Graphics foreground (logical) colour | 173 | | 0x109A | 0-63 | | | Graphics background (logical) colour | 174 | | 0x109B | 0-63 | | | Text foreground (logical) colour | 175 | | 0x109C | 0-63 | | | Text background (logical) colour | 176 | | 0x10A1 | | X | | Max mode number (not double-buffered) | 177 | | 0x10A2 | | X | | X font size, graphics cursor | 178 | | 0x10A3 | | X | | Y font size, graphics cursor | 179 | | 0x10A4 | | X | | X font spacing, graphics cursor | 180 | | 0x10A5 | | X | | Y font spacing, graphics cursor | 181 | | 0x10A7 | | X | | X font size, text cursor | 182 | | 0x10A8 | | X | | Y font size, text cursor | 183 | | 0x10A9 | | X | | X font spacing, text cursor | 184 | | 0x10AA | | X | | Y font spacing, text cursor | 185 | | 0x10F2 | | | | Dotted line pattern length | 186 | | 0x10F3 | | | | Line pattern, bytes 0-1 | 187 | | 0x10F4 | | | | Line pattern, bytes 2-3 | 188 | | 0x10F5 | | | | Line pattern, bytes 4-5 | 189 | | 0x10F6 | | | | Line pattern, bytes 6-7 | 190 | | 0x1100 | | | | Width of text window in chars | 191 | | 0x1101 | | | | Height of text window in chars | 192 | | 0x1118 | | | | X position of text cursor within text window | 193 | | 0x1119 | | | | Y position of text cursor within text window | 194 | | 0x111A | | | | X position of text cursor in screen coordinates | 195 | | 0x111B | | | | Y position of text cursor in screen coordinates | 196 | | 0x1200-0x123F | 0-63 | | | Palette entries. Maps logical colours to physical screen colours. The entries used will depend on the number of colours in the current screen mode | 197 | | 0x1300-0x13FF | | | | Character to bitmap mapping. Value is a 16-bit bitmap ID, or 65535 if character is not mapped. See `VDU 23, 0, &92, char, bitmapId;` | 198 | | 0x1400 | | | | Currently selected bitmap ID (16-bit bitmap ID) | 199 | | 0x1401 | | X | | Count of bitmaps used | 200 | | 0x1402 | | | | Current bitmap transform ID. Must be set to a buffer ID containing a valid affine transform. The affine transforms flag must be set to change this value | 201 | | 0x1410 | 0-255 | | | Current sprite ID | 202 | | 0x1411 | | X | | Number of sprites active (not necessarily visible) | 203 | | 0x1420 | | | | Mouse cursor ID | 204 | | 0x1441 | 0/1 | | | Mouse cursor enabled. Mouse data can only be read if the mouse is enabled | 205 | | 0x1442 | | | | Mouse cursor X position in screen coordinates | 206 | | 0x1443 | | | | Mouse cursor Y position in screen coordinates | 207 | | 0x1444 | 0-7 | X | | Mouse cursor button status. Bit 0 indicates left button pressed, bit 1 the right button, and bit 2 the middle button | 208 | | 0x1445 | | X | | Mouse wheel delta | 209 | | 0x1446 | | | | Mouse sample rate | 210 | | 0x1447 | | | | Mouse resolution | 211 | | 0x1448 | | | | Mouse scaling | 212 | | 0x1449 | | | | Mouse acceleration | 213 | | 0x144A | | | | Mouse wheel acceleration | 214 | 215 | \* Support for these variables was added in VDP 2.14.0 216 | -------------------------------------------------------------------------------- /mkdocs.yml: -------------------------------------------------------------------------------- 1 | # To view the documentation locally on your machine, use the following steps 2 | # 3 | # Clone the GitHub agon-docs repo locally, then on the command line: 4 | # 5 | # cd /github/agon-docs 6 | # python -m venv venv 7 | # source venv/bin/activate 8 | # pip install mkdocs-material 9 | # mkdocs new . 10 | # mkdocs serve 11 | # 12 | # The last command should eventually print something like 13 | # Serving on http://127.0.0.1:8000/ 14 | # and you can open that URL in a local brower. If you are locally editing 15 | # the documentation, leave the server process running and the browser 16 | # pages will auto-reload as you save edits. 17 | # 18 | 19 | site_name: "Community Agon Platform documentation" 20 | repo_url: https://github.com/AgonPlatform/agon-docs 21 | repo_name: contribute 22 | edit_uri: edit/main/docs/ 23 | theme: 24 | favicon: assets/favicon.png 25 | logo: assets/logo.png 26 | name: material 27 | features: 28 | - navigation.sections 29 | - navigation.expand 30 | - navigation.instant 31 | - navigation.top 32 | - search.suggest 33 | - search.highlight 34 | - content.tabs.link 35 | - content.code.annotate 36 | - content.code.copy 37 | - content.footnote.tooltips 38 | - content.action.edit 39 | language: en 40 | palette: 41 | - media: "(prefers-color-scheme)" 42 | toggle: 43 | icon: material/brightness-auto 44 | name: Switch to light mode 45 | - media: "(prefers-color-scheme: light)" 46 | scheme: default 47 | toggle: 48 | icon: material/toggle-switch-off-outline 49 | name: Switch to dark mode 50 | primary: deep purple 51 | accent: purple 52 | - media: "(prefers-color-scheme: dark)" 53 | scheme: slate 54 | toggle: 55 | icon: material/toggle-switch 56 | name: Switch to your system preference 57 | primary: deep purple 58 | accent: lime 59 | 60 | extra_css: 61 | - stylesheets/extra.css 62 | 63 | nav: 64 | - 'Welcome & getting started': 65 | - 'Start here': index.md 66 | - 'FAQ': FAQ.md 67 | - 'Theory of operation': Theory-of-operation.md 68 | - 'MOS': 69 | - 'Overview': MOS.md 70 | - 'Command line': mos/Star-Commands.md 71 | - 'API': mos/API.md 72 | - 'C functions': mos/C-Functions.md 73 | - 'Executable format': mos/Executables.md 74 | - 'Modules': mos/Modules.md 75 | - 'System Variables': mos/System-Variables.md 76 | - 'Argument Substitution': mos/Argument-Substitution.md 77 | - 'VDP': 78 | - 'Overview': VDP.md 79 | - 'Main Commands': vdp/VDU-Commands.md 80 | - 'Screen Modes': vdp/Screen-Modes.md 81 | - 'PLOT Commands': vdp/PLOT-Commands.md 82 | - 'System Commands': vdp/System-Commands.md 83 | - 'Audio API': vdp/Enhanced-Audio-API.md 84 | - 'Bitmaps and Sprites API': vdp/Bitmaps-API.md 85 | - 'Buffered Commands API': vdp/Buffered-Commands-API.md 86 | - 'Context Management API': vdp/Context-Management-API.md 87 | - 'Font Management API': vdp/Font-API.md 88 | - 'VDP Variables': vdp/VDP-Variables.md 89 | - 'Copper Effects API': vdp/Copper-API.md 90 | 91 | - 'BBC Basic': BBC-BASIC-for-Agon.md 92 | - 'GPIO': GPIO.md 93 | - 'Guides': 94 | - 'Updating Firmware': Updating-Firmware.md 95 | - 'Additional resources': 96 | - 'External documentation': External-Documentation.md 97 | - 'Third party projects': Third-Party-Projects.md 98 | 99 | 100 | markdown_extensions: 101 | - pymdownx.highlight: 102 | anchor_linenums: true 103 | - pymdownx.inlinehilite 104 | - pymdownx.snippets 105 | - admonition 106 | - pymdownx.arithmatex: 107 | generic: true 108 | - footnotes 109 | - pymdownx.details 110 | - pymdownx.superfences: 111 | custom_fences: 112 | - name: mermaid 113 | class: mermaid 114 | format: !!python/name:pymdownx.superfences.fence_code_format 115 | - pymdownx.mark 116 | - attr_list 117 | - toc: 118 | toc_depth: "2-5" 119 | - md_in_html 120 | - pymdownx.emoji: 121 | emoji_index: !!python/name:material.extensions.emoji.twemoji 122 | emoji_generator: !!python/name:material.extensions.emoji.to_svg 123 | --------------------------------------------------------------------------------