User Tools

Site Tools


FLOS: A "Freezer-Like" Operating System for OSCA on the V6Z80P by Phil Ruston

Last updated 21st November 2013, for FLOS v613


FLOS is a simple Z80 command line operating system for the OSCA architecture, it works in a similar manner to the memory monitor / freezer cartridges of the home computer era. In some ways it also behaves like a more modern DOS, allowing disk-based programs to be executed by entering their filenames etc.

Installation and OS file details

FLOS is normally loaded as a file from the root directory of a FAT16 formatted SD card – the bootcode will load the first *.OSF file it finds to address $1000 and begin execution at $1010. The OS can also be installed on the V6Z80P's EEPROM (by using the application “EEPROM.EXE”). The bootloader looks for the OS on the SD card first, if it is not found it checks the EEPROM. If an OS is not found on either then the user is prompted to download an .OSF file via the serial link. (The .OSF file is just a Z80 code binary file with a 16-byte header, the format of which is given at the end of this document. FLOS occupies System RAM space $1000-$4FFF and uses $0000-$0FFF for variables etc).

Using FLOS

Launching Commands

FLOS commands are either internal (basic debugging and disk navigation) or external (more complicated features). Internal commands are contained within FLOS so do not use any system memory above address $04FFF, whereas external commands need to be loaded in from SD card to the top of system memory (usually $7f000) for execution. This high location is used purely to avoid overwriting user programs which will usually load low in memory ($05000). In all cases, a command (or program) is run simply by entering its name (and any parameters it requires) and pressing Enter.

To find external commands, FLOS looks in the current active volume / directory and then scans the “command paths”. A file extension for the command is not needed but can be specified if desired. If no extension is given then a file on disk with the command name plus extension “.flx” or “.exe” is deemed to be an appropriate program file for the command.

EG: Upon entering “MYPROG”, FLOS will look for a file called MYPROG.FLX or MYPROG.EXE (.FLX is the prefered file extension for FLOS-Executable files). If “MYPROG.ZAP” is entered, FLOS will look for a file called MYPROG.ZAP only.

The aforementioned command paths are set using system environment variables %EX0: to %EX9: - these can be set up with the command ASSIGN. FLOS automatically sets %EX0: to “VOL0:/COMMANDS” on boot, so it will always look in the current dir and VOL0:/COMMANDS.


  • External “commands” are merely FLOS standard Z80 programs with a header which forces FLOS to load them high in memory.
  • It is possible to run a progam with a path prefix, EG: “V0L0:/MYFILES/STUFF/MYPROG”

When a command is supplied with a filename argument which does not have any path data (EG: TYPE myfile.txt) FLOS will look for the associated data file in the currently active volume / directory only. However, most commands allow path information in filenames (see individual command documentation).

FLOS volume and directory handling

When FLOS starts, it looks for FAT16 partitions on the SD Card (if inserted), these are labeled VOL0:, VOL1: etc. (Note that FLOS cannot automatically detect card swaps, so the drives must be remounted with the command MOUNT if this occurs.) Each volume has its own directory pointer, so it it possible to switch volumes (with the VOLx: command) and immediately arrive at the directory that was last active in that volune. The active directory is set with the CD command (which itself does not switch volumes).

Path parsing syntax

  • / or \ (Forward or backslash) Directory seperator, also signifies the ROOT dir when placed at the start of a dir path
  • .. (Dot dot) Refers to the parent directory
  • VOLx: Refers to a volume, IE: Partition on the SD card
  • %abc: Refers to an 'assigned path' (as above, extra path info can follow)

Examples of legal FLOS path strings used with TYPE command:

 TYPE myfile.txt                   - Shows file from currently active volume/directory. 
 TYPE ../myfile.txt                - Shows file from the parent dir of currently active volume/directory.
 TYPE /myfile.txt                  - Shows file from root of currently active volume/directory.
 TYPE somedir/another/myfile.txt   - Shows file from subdir of currently active volume/directory.
 TYPE VOL1:myfile.txt              - Shows file from current dir of VOL1:
 TYPE VOL1:/myfile.txt             - Shows file from root of V0L1:      
 TYPE %FOO/subdir/myfile.txt       - Shows file from subdir of assigned volume/dir %F00


  • Path/filename strings cannot contain spaces.
  • Filename/path strings are limited in length to whatever will fit on a single line of text (40 characters including command name etc).
  • Filenames are not case sensitive in FLOS.

UI Navigation (Keyboard controls)

The UI is a full screen editor, so the cursor can be moved back to any previous command and Enter pressed again to re-execute it if desired. The other keys active in the UI are:

HomePuts cursor at left side.
EndPuts cursor right of last non-space character on a line.
Page UpPuts cursor at top, left.
Page DownPuts cursor at bottom, left on new line.
InsertSwitches between overwrite and insert mode.
AltUse alt_keymap character.

The default keymap is that of the UK, but this can be changed with the command KEYMAP. To assist with such settings, FLOS will run a batch file called “BOOT_RUN.SCR” at start-up if it is present in the root directory of the SD card. (This script - along with any others launched from the EXEC command - can be aborted by pressing CTRL+C).

Programmable Function Keys

FLOS allows the function keys F1 to F9 to be assigned command strings. To use this feature simply put text files (containing the desired command string) called “F1.CMD” (to “F9.CMD”) in a directory of your choice and set the environment variable “%KEY” to point to that directory. (Note: the default BOOT_RUN.SCR script sets %KEY to VOL0:KEYMAPS by default so it is probably best to locate Fx.CMD files there). Alternatively, just place the Fx.CMD file in the current working folder - the most local version has priority at the time when a function key is pressed. The command strings can be a maximum of 40 characters long but can be an EXEC command if desired.


All numeric data is entered and displayed in hexadecimal format without any prefix or suffix (the only exception being the free disk space reported by the DIR command, which is shown in decimal).


Environment Variables

Environment variables (“cookies”) are a simple way for programs to use common, global settings stored within FLOS itself. Each variable has a name of 1 to 4 ASCII characters (no spaces) and an associated value 4 bytes long. The FLOS commands SET, INPUTSTR and INPUTNUM can set an environment variable at the command line (and kernal calls are provided to manipulate them within programs). FLOS itself sets the environment variable “ERR” with the error code returned in A whenever a program returns control to it. At present there is space for 16 environment variables - they are all deleted whenever FLOS restarts.

The environment variables can also hold shortcuts to long directory paths, these are set up using the ASSIGN command. When an environment variable is used in this way, its name can only be 3 characters long and is automatically prefixed with “%”. Note that because of the limited space, an entire path string cannot be stored for assignments, instead a hook to the ultimate target folder is used (the volume number and directory cluster). To help prevent problems when assigned directories are deleted, associated environment variables are automatically removed when a directory is deleted. Also, all assigned environment variables apart from %EX0 are deleted when a MOUNT command is performed.


Simple scripts (batch files) with limited flow control can be used in FLOS. These are standard text files launched with “EXEC script_name”. Note that FLOS scripts cannot run other scripts. Basic flow control is achieved with in-script labels (up to 4 characters) and the following commands:

IFJump on condition
GOTOUnconditional jump to label
INPUTNUMGet a hex number from user (up to 32 bit)
INPUTSTRGet string (up to 4 chars) from user
FILEINFOGet file size in envar “FSIZ”
SETManage environment variables

As these are external commands they load to the top of system RAM to avoid corrupting any user program/data. See the command list at the end of this document for full parameter possibilities of the above commands (or use HELP within FLOS).

An example script:



  • Lines must be left aligned.
  • A line can be commented out with a semicolon, but it must be the first character of the line.
  • Labels are 4 chars max and must be in square brackets when defining their locations. No other text can be on the same line as a label location.
  • The termination point is the end of the script file, so if a script is to break before that point then a GOTO is required as in the above example.
  • Script control is achieved internally using the environment variables. Mainly, an environment variable called GOTO is set by the IF command (and of course “GOTO”, which is essentially the same as “SET GOTO = label”


Development tools

Any preferred Z80 assembler can be used on a PC / other system (it is also possible to develop entirely on the V6Z80P using the FLOS commands EDIT.EXE and ASM.EXE - note that the existing sources will need slight modifictions however, due to 8.3 filenames, path issues etc).

The project's source code was developed on the PC using a text editor and assembled with the freeware command line assembler 'Pasmo' by Juliain Albo. Note that Pasmo has case sensitive labels, use all lower case labels if in doubt (See the “readme.txt” and “pasmo documentation.html” in the Pasmo folder for full details about the assembler). Also, avoid using spaces in filenames.

The freeware apps Programmers Notepad or are recommended for writing Z80 assembly source. Both these apps can highlight Z80 'keywords' within the source for clarity and pass the source file direct to Pasmo for assembly (and also call external applications to - for example - send the assembled file to the V6Z80P via serial port). There's set-up info for Programmer's Notepad here and PSpad here.

FLOS Programs and Banked memory

In FLOS, the 512KB System RAM is paged into Z80 address space as follows: The first 32KB is unpaged (IE: System RAM $00000-$07fff always appears at Z80: $0000-$7FFF), the second 32KB of Z80 space can contain any 32KB bank of system memory apart from the first 32KB. The upper page is set with the command B and can be specified locally wherever a command allows it.

FLOS-friendly programs - by default - load and run from $5000. If the program file extends into the paged memory area ($8000-$FFFF), its data will always follow on immediately into the first bank (bank 0), and then (if large enough) the subsequent banks, looping around to $8000 whenever the address overflows from $FFFF. When the program runs, bank 0 will be selected by FLOS and when control is returned to FLOS the bank setting is restored to whatever bank was active before the program ran.

It is possible to force programs to load and run from any address (above $5000) by adding a special header to the start of the code (see details below). The header specifies which bank to use if the required location is within the paged memory area. If the program extends beyond address $FFFF, the subsequent banks are used with the address counter looping around to $8000 each overflow. When the program runs, the bank specified by the header is selected and the original bank is restored by FLOS on exit.


When FLOS runs a program, the following registers are pre-set:

HL = contains the address of the first non-space character after the entered command name (if no arguments were supplied, HL will be pointing at a zero byte). Apps can scan from the address in HL for parameters if required – when zero is encountered, the search should be terminated.
A = The volume number from which the program loaded.
DE = The directory cluster from which the program loaded.

The above values allow a program to know the folder / volume it loaded from. This may be useful because programs can be started indirectly via the exectuable path envars (%EX0 etc) in which case the “current” folder and drive may not be the same as the source of the program.

IY = The location of a 32bit longword (little endian) that is the file length. Also, the 16bit word at IY+8 is the first cluster of the file - these values may be useful for advanced loaders etc.


Programs returning control to FLOS should set the zero flag if no return message is to be displayed (see the list at end of this document). EG: end in XOR A, RET. If the zero flag is not set, a message associated with the value in A is displayed. If the zero flag is not set and A = 0, then a driver error code is assumed to be being passed back in B. A program’s return code returned in A is also placed in the lowest byte of an environment variable called “ERR” (the value from B is copied to the ERR Envar bits [15:8] when A is 0 and the Zero Flag is not set.)

In all cases, if upon return A = $FF then FLOS will restart. If A = $FE a new command will be launched (Set HL to point to the required zero-terminated command string). It is also possible to make FLOS always run a command upon return - this can be set up with the kernal call “kjt_set_commander” (the commander persists even if FLOS is restarted with return code $ff, however it can be cancelled by holding CTRL at restart).

In general, programs can hit the hardware as desired but bear in mind that if critical settings used by FLOS have been altered by the user program, certain Kernal calls may not work and it may not be possible to return to FLOS. If a program has made changes to the display registers, normally you will want to restart FLOS completely with the (A=$FF return code). However, it is possible to restore the hardware registers and return to FLOS normally (A=0) by calling the Kernal routine “KJT_FLOS_DISPLAY” prior to program exit. (Note: This is only useful if the video RAM area $10000-$1ffff has not been overwritten. If it has, then it is necessary to use the full restart code).

By default, FLOS logs the Z80 register set when programs return control to it (as displayed with the R command). If for some reason this is not required the program can call the KJT routine “kjt_dont_store_registers”.

Calling Kernal Routines

The Kernal Jump Table is a simple way of allowing user programs to call routines within the operating system. The location of the jump table and the order of its entries should never change, so calls to FLOS routines can be made indirectly via the KJT_* entries.

The KJT equates file (from the “equates” folder) should be included into the user program’s source, allowing the routines to be called by name. In general, you should PUSH and POP any important registers around KJT routines unless it is specifically stated in the documentation which registers are preserved.

For full details about each kernal routine, see the document Kernal_Call_Descriptions.html in the “documentation/manuals/” folder.

Note: Generally speaking, kernal routines should not be called when video memory is paged into $2000-$3FFF or when sprite RAM is paged in at $1000-$1FFF. The call kjt_page_out_video is guaranteed to work, however).

An example FLOS program that calls a kernal routine to display a text message:

; Standard header for OSCA and FLOS
include "equates\kernal_jump_table.asm"        ; useful equates
include "equates\osca_hardware_equates.asm"    ; ""    ""
include "equates\system_equates.asm"           ; ""    ""


	org $5000              ; Start of free memory
	ld hl,my_text          ; location of ASCII string
	call kjt_print_string  ; use OS print ascii string routine
	xor a                  ; report no error on return 
	ret                    ; back to FLOS        

my_text db "Hello World!",13,10,0    ; Text followed by <CR+LF> and zero

Program Location header

If necessary, programs (IE: files with .flx or .exe extensions) can be made to load and run from a specific location and also be truncated to 'n' bytes. This is achieved by putting the following header at the start of the code:


my_location equ $f000        

my_bank     equ $00          ; desired bank (used if location is $8000 to $FFFF)

            org my_location  ; desired load address

load_loc    db $ed,$00       ; header ID (Invalid, but safe Z80 instruction)
            jr exec_addr     ; jump over remaining header data 
            dw load_loc      ; Z80 address file should load to 
            db my_bank       ; upper 32KB bank that file should load into
            db xy            ; control byte: 1=truncate using next 3 bytes
            dw abcd          ; Load length 15:0 (if truncate feature required)
            db ef            ; Load length 23:16 (""                "")



Main program execution begins from “exec_addr”. The labels “my_location” and “my_bank” obviously should be set to suit the program. (Note: The header is loaded to “my_location” as a normal part of the file).

The header source above is available as an include in “code library\program header\inc\” - (the version there also checks to make sure the code has indeed been loaded to its correct location).

As mentioned above, when a program uses the header to load to paged memory ($8000-$FFFF), the bank where it is located is selected prior to execution. When it returns control to FLOS, the original FLOS bank is automatically restored. If a program itself wishes to know which bank was orignally selected by FLOS, the kernal call KJT_GET_FLOS_BANK can be used.


FLOS sets the NMI vector to a freeze subroutine so that programs can be stopped and the memory / registers examined. A push switch across the NMI pin to Ground (see pin header diagram in the documentation folder) can be used to stop a program and return to the OS. Note: it is not possible to restart the “frozen” program from the point it was stopped. Also, the OSCA ROM must not be paged out (and lower 32KB page selection bits = zero) at the point the button is pressed.


OSCA is designed to use Interrupt Mode 1. The ROM has the instruction JP $0A00 at $38 (IRQ) and JP $0A03 at $66 (NMI). FLOS places the following code at these locations:

$0A00: JP aabb (where aabb is FLOS's default IRQ handler)
$0A03: JP ccdd (where ccdd is FLOS's default NMI handler)

These locations can be set by external apps if desired. Alternatively, the OSCA ROM can be banked out, allowing direct access to the IRQ locations at $38 and $66. See the OSCA hardware manual for details regarding switching out the ROM.


FLOS's IRQ routine handles keyboard and mouse interrupts only. If an external program wants to use its own interrupt handler (for example to process timer, audio and/or video interrupts) but still use the kernal keyboard and mouse routines, the FLOS IRQ routines can be called via two Kernal Jump Table entries: “kjt_keyboard_irq_code” and “kjt_mouse_irq_code”. The custom interrupt handler should test bit 0 (keyboard) and 1 (mouse) of the port “sys_irq_ps2_flags” and call the appropriate routine if the relevant bit is set. An example follows where a custom timer interrupt handler is used along with the usual FLOS keyboard and mouse irq service code.

         ld hl,(irq_vector)                       ; The label "irq_vector" = $A01 (contained in equates file)
         ld (original_irq_vector),hl              ; Store the original FLOS vecotr for restoration later.
         ld hl,my_custom_irq_handler
         ld (irq_vector),hl
         ld a,%10000111                           ; Enable keyboard, mouse and timer interrupts
         out (sys_enable_irqs),a


         ld hl,(original_irq_vector)
         ld (irq_vector),hl
         ld a,%10000011                            ; Enable keyboard and mouse interrupts only
         out (sys_irq_enable),a


         push af
         in a,(sys_irq_ps2_flags)
         bit 0,a
         call nz,kjt_keyboard_irq_code             ; Kernal keyboard irq handler
         bit 1,a
         call nz,kjt_mouse_irq_code                ; Kernal mouse irq handler
         bit 2,a
         call nz,my_timer_irq_code                 ; User's timer irq handler
         pop af
         ei                                        ; Re-enable Z80 IRQ mask


         push af
         ; (do whatever, push/pop registers!) 

         ld a,%00000100
         out (sys_clear_irq_flags),a              ; Clear the timer IRQ flag
         pop af

original_irq_handler: dw 0


FLOS's NMI routine is used in association with a push switch across the V6Z80P's pin header NMI pins. When an NMI is triggered, the running program stops, control is returned to FLOS and the register set is displayed. (The NMI vector is changed to point to a RETN instruction when FLOS itself is running so no action takes place). Note: some memory paging combinations will cause the NMI handler to fail.

Resources used by FLOS

Default OSCA ROM (Z80 address space) : $0000-$01FF
System RAM (Z80 address space) : $0200-$4FFF

$0200-$037F 1)Keymaps
$0380-$03FF 2)Storage devices info
$0400-$047F 3)Volume mount list
$0500-$0523 4)Colour list
$0524-$07FF 5)Unused at the moment
$0800-$09FFSector buffer
$0A00-$0A05JP xxxx, JP xxxx for IRQs
$0B00-$0BFFStack / Scratchpad
$0C00-$0FE8Character map buffer
$1000-$4FFFMain FLOS code and data

Video RAM : $10000-$1FFFF

  • OS display bitplanes: $10000,$12000,$14000,$16000,$18000,$1A000
  • Char colour buffer: $1C000-$1C3E8
  • Window routines: $1C400-$1DFFF (Note: Not actually used by FLOS itself)
  • Font bitplane images: $1E000-$1FFFF

Also used by FLOS: The video registers associated with bitmap planar display, The timer hardware, IRQ mode 1 for keyboard (and mouse) and the Blitter.

If the user program has made radical changes to these systems, then it may be best to restart FLOS on exit (clear the carry flag and set accumulator to $FF).

As FLOS internally uses the blitter user programs should take into account that FLOS sets its hardware registers to the values it requires every time control is passed to it (via KJT calls) and will not be restored upon return to the user program. (FLOS does not use the blitter or timer during IRQ interrupts).

FLOS Commands

Internal Commands

BSet the bank of System RAM appearing in Z80 address space $8000-$FFFF
CCopy bytes in memory (from currently selected bank)
CDChange directory (does not switch the active volume)
CLSClear OS screen
COLOURChange the OS colour scheme
DDisassemble Z80 code
DELDelete a file
DIRShow directory listing
EXECExecute a script
FFill memory
FORMATFormat the (entire) SD card as a single FAT16 partition
GGoto location (IE: Call a Z80 routine) (“G 0” resets the Z80)
HHunt in memory for hex bytes or text
LBLoad Binary file from disk to system RAM
MShow system RAM contents as hex bytes
MDMake a new directory
MOUNTRemount drives
RShow CPU registers
RDRemove directory
RNRename file or directory
RXReceive file (to RAM) from PC via serial link (and optionally, run it)
SBSave Binary file from RAM to disk
TShow system RAM as ASCII text
TXTransmit bytes from system RAM (to PC) via serial link
VOLx:Switch volume (without altering the directory position)
:Put hex bytes in memory
>Put text in memory
<Put bytes in memory and disassemble
?List internal commands


Bank select (ie: select one of 15 32KB banks for Z80 address $8000-$FFFF)

 Use: B [n] (n = 0 to E)

Bank 0 pages in system RAM $08000-$0FFFF to Z80 $8000-$FFFF
Bank 1 pages in system RAM $10000-$17fff to Z80 $8000-$FFFF
and so on…

If [n] is not supplied, the current bank is displayed.

FLOS does not allow system RAM $00000-$07FFF to be paged into Z80 $8000-$FFFF (though the OSCA architecture does allow it) hence FLOS Bank 0 = System RAM $08000-$0FFFF.


Copy bytes in memory (from currently selected bank).

 Use: C start_address end_address destination_address [dest bank]


Change Directory (or show path).

 Use: CD (no args)        (show current dir path)
      CD ..               (go to parent dir)
      CD /                (go to root dir)
      CD /dir             (go to a dir in root)
      CD ../../hats       (go up two dir levels and into "hats")
      CD subdir           (change to subdir)
      CD VOLx:/           (change volume x's active directory to root)

Note: CD does not switch the volume (even when used with an assigned path).


Clear OS screen.

 Use: CLS (no args)


Changes the FLOS colour scheme.

 Use: COLOUR pen [paper] [border] [cursor] 

Notes:'pen' = $nm where 'n' is the font character's background colour and 'm' is the foreground colour as per the following table:

0transparent (shows “paper” colour)
9dark grey
amid grey
blight grey
dlight blue
elight green

[Paper], [border] and [cursor] are 12 bit $RGB values.


Disassemble Z80 code.

 Use: D start_address end_address

Note: To aid debugging, it is possible to cursor up to a line of code, edit the hex bytes and press enter to update the disassembly listing. (You cannot edit the mnemonics, however).


Delete File.

 Use: DEL [path/]filename (name must be a file, not a dir)
 EG:  DEL somefile.txt
      DEL ../settings/test.bin
      DEL VOL0:/tests/text/file.txt


Show Directory Listing.

 Use: DIR [dir]
 EG:  DIR            - shows contents of current directory
      DIR somedir    - shows subdirectory listing
      DIR %ASN       - shows listing of assigned volume:/dir
      DIR files/more - shows listing of subdir "more" in subdir "files"


Execute a script.

 Use: EXEC [path/]filename (note: scripts cannot execute further scripts\\
 EG:  EXEC boot_run.scr
      EXEC scripts/test.src


Fill Memory.

 Use: F start_address end_address fill_byte


Formats *entire disk* for FAT16 (Without an MBR, so no partition table is made).

 Use: FORMAT device_name [label] 


Goto location (IE: Call Z80 routine).

 Use: G address


  • “G 0” resets the Z80
  • HL will be equal to the first non-space character after the address.


Hunt in memory for hex bytes or text (not case sensitive).

 Use: H start_address end_address byte1 [byte2 byte3 etc]
      H start_address end_address “string”


Loads bytes to RAM from currently selected drive.

 Use:  LB [path/]filename address [bank]
 EG:   LB myfile.bin 5000
       LB VOL1:../mytest.txt 8000 3
       LB %ex0/echo.exe 5000


  • If no bank is specified, the current FLOS bank is used (only when address is > $7FFF)
  • If no address is specified, the file is loaded to $5000
  • If address is < $8000, any data loading beyond $7FFF will load into bank 0
  • If the load address counter goes beyond address $FFFF, bytes are loaded into the next bank (and the address wraps around to $8000). This does not affect the current bank as selected by the B command.


Show memory as hex bytes.

 Use: M address

Note: You can edit the displayed data and press return to update it in memory as the string is displayed with the : prefix


Make new directory.

 Use: MD [path/]new_dir
 EG:  MD hats          (makes a new subdir called HATS)
      MD settings/test (makes a new dir in subdir SETTINGS called TEST)          
      MD /gubbins      (makes a new dir in root called GUBBINS)


Rescans for connected drives.

 Use: MOUNT (no args)

Note: Deletes all environment variables except %EX0


Show registers.

 Use: R (no args)


  • The register list is updated on return from external programs or via NMI freeze.
  • The PC register reflects the current location only when a program has been stopped via NMI.
  • At all other times it is simply set to the start/execute address when a program is run.


Remove directory.

 Use: RD [path/]dir (name must be a dir, not a file)
 EG:  RD hats          (removes a subdir called HATS)
      RD settings/test (removes dir in SETTINGS called TEST)          
      RD /gubbins      (removes a dir in root called GUBBINS)

Notes: DIR must be empty.


Rename file or Dir.

 Use: RN [path/]filename new_filename
 EG : RN myfile.bin file1.bin
      RN stuff/lettuce.bin veg.bin
      RN textdir mytext


Receive data from serial comms port (place it in RAM) and optionally execute it as code.

 Use: RX filename address [bank]   


  • If filename is “*” whatever file is sent is accepted.
  • If filename is “!”, the file is downloaded and immediately run (no other arguments are used. If the file being downloaded has a FLOS location header, it is loaded to the address and bank specified in the header (any truncation info in the header is ignored) otherwise it is loaded to $5000. HL will be set to the first non-space character after the “!”)
  • If no bank is specified, the current bank is used (only when address is > $7FFF)
  • If address is < $8000, any data loading beyond $7FFF will load into bank 0
  • If the load address counter goes beyond address $FFFF, bytes are loaded into the next bank (and the address wraps around to $8000). This does not affect the current bank as selected by the B command.


Save bytes from RAM to currently selected drive.

 Use: SB [path/]filename address length [bank]  
 EG:  SB myfile.bin 5000 2000
      SB settings/cfg.bin 8000 123 3


  • When address < $8000 any data eventually sourced from the paged memory area will be taken from bank 0 first.
  • If no bank is specified, the current bank is used (but only when address is > $7FFF)
  • When the length + address extends beyond address $FFFF, bytes are fetched from the next bank (ie: the address wraps around to $8000 and the bank number increases. This does not affect the currently selected bank as set with the B command.


Show memory as ASCII text.

 Use: T address

Note: you can edit the displayed data and press return to update it in memory as the string is displayed with the > prefix.


Transmit bytes from RAM to serial comms port (using Serial Link app).

 Use: TX filename address length [bank]


  • When address < $8000 any data eventually sourced from the paged memory area will be taken from bank 0 first.
  • If no bank is specified, the current bank is used (but only when address is > $7FFF)
  • When the length + address extends beyond address $FFFF, bytes are fetched from the next bank (ie: the address wraps around to $8000 and the bank number increases. This does not affect the currently selected bank as set with the B command.


Switches to another volume (goes to the directory that was last active on that volume).

 Use: VOL0:


Put text in memory.

 Use: T address "text"


Put hex bytes in memory.

 Use: address byte1 [byte2 etc]


List internal commands.

 Use: ? (no args)


Put hex bytes in memory and disassemble.

 Use: < address hexbytes

External Commands

(These are located in the COMMANDS directory and load high in memory - usually Bank $0E, address $F000)

ASSIGNAssigns a directory path to a short string of characters
BAUDSets the BAUD rate (57600/115200 supported)
BOOTReconfigure the FPGA from a given slot
CALCSimple command line calculator / number base converter
CHFNTChanges the OS font
CMPCompares two areas of system memory, shows differences
ECHODisplays short messages
FINFOShows info about a file
FCOPYSingle file copy
FCMPCompares two files, shows differences
FMOVESingle file move
FRXReceive a file via Serial Link and put in current dir
FTXSend a file from current dir (to PC) via Serial Link
GOTOScript control (see script section)
HELPDisplays help files
IFScript control (see script section)
INPUTSTRGet input from user, place in environment variable
INPUTNUMGet hex value from user, place in environment variable
KEYMAPChanges the keyboard mapping for non-UK keyboards
LCDLineCop disassembler
LOADSPRLoads a file to Sprite RAM
LOADVRAMLoads a file to Video RAM
MONOSets the stereo panning to “All channels to both sides”
MOUSEActivates the mouse driver
SAVEVRAMSaves data from Video RAM to a file
SETSets an environment variable (or shows those defined)
STEREOSets the stereo panning to Channels 0+2: Left 1+3:right
TYPEDisplays text files
VERSShow OSCA / FLOS version
VGASets VGA refresh rate to 50Hz (non standard) or 60Hz

Documentation for these programs is available by typing “HELP command_name”.


Assigns a directory to an environment variable.

 Use: ASSIGN xyz [path]

'xyz' is the name of the path “proxy” which will have a “%” prefix. If the path is omitted then the current folder is assigned.


Sets the BAUD rate used in FLOS.

 Use: BAUD speed

'Speed' is 115200 or 57600 (default Baud rate is 115200).


Reconfigure the FPGA from the specified slot.

 Use: Boot [slot]

If slot is not supplied, the EEPROM contents are listed.


A very simple calculator / number base converter.

 Use: CALC expression

expression can contain the following operators:

 +  Add
 -  Subtract
 *  Multiply
 /  Divide
 &  Logical AND
 |  Logical OR
 >> Shift right
 << Shift left
 EG: CALC 1F*25
     CALC "A"
     CALC 47<<1
     CALC (#25*#2)/#10

The result is shown in hex, decimal and binary with leading zeroes supressed.

Numbers are interpreted as hex by default (or when “$” prefix is used).
Other number base symbols are:

 # Decimal 
 % Binary
 "Between quotes" - ASCII value

Brackets can be used - parsing will be in a simple left to right fashion.


  • Only integers can be used.
  • Internal registers are 16 bit so any time a value exceeds 65535 an overflow error will occur.
  • Underflows are allowed to occur if the result is no smaller than -32767


Changes the OS font.

 Use: CHFNT [path/]filename [xx]

If filename does not contain a path, CHFNT looks in the current directory and then in the VOL0:fonts directory for the font file.


  • Two types of font files are supported - both use raw bitmap data but are formatted differently. The original (.fnt) files hold 96 character definitions (for ASCII codes 32 to 127) and are stored in a raster-like format: 96 bytes wide * 8 lines high.
  • FLOS 6.02+ supports all 256 ASCII characters, so the font file can be 1 to 256 characters long. The new FLOS font files (.fff) are formatted in the linear “8-bytes-per-character-defintion” grouped style. When an .fff file is specified, the first character image to be overwritten can be set by adding a hex value to the end of the command line. This allows, for example, the extended ASCII char images (128-255) to be patched onto the current font. (If no value is supplied, patching starts at ASCII char $00).


Compares two areas of system RAM and shows differences.

 Use: CMP [#] start_address end_address target_address [bank]

If # is included, the operation is carried out silently (apart from FLOS error messages such as incorrect syntax).

The source bank is always that currently seleced by FLOS, the target bank is the same as the source bank unless specified.


Displays a line of text.

 Use: ECHO some text to display


Shows file length / load address, sets the Envar “FSIZ”.

 Use: FINFO (#) [path/]filename

If # is included, the operation is carried out silently (any FLOS error message is also muted to $80)

A load and bank address is only shown if the file is a program with the location header.


Compares two files and shows any differences.


If # is included, the operation is carried out silently (apart from FLOS error messages such as incorrect syntax).

If the files are not the same size the comparison runs to the end of the shortest file.

If any bytes are different, the “ERR” envar is set to $80.

If the filesizes are different but the bytes up to the end of the shortest are the same, “ERR” is set to $81.


Copies a file from one place to another (or appends data to end of existing file).

 Use: FCOPY source destination

Where source and destination are “[path/]filename”.


  • If no filename is supplied in destination, the source filename is used.
  • Any directories in paths must exist already, they will not be created.
  • This command loads to Bank $0E, address $B000


Move a file from one place to another (or shifts data to end of an existing file).

 Use: FMOVE source destination

Where source and destination are “[path/]filename”.


  • If no filename is supplied in destination, the source filename is used.
  • Any directories in paths must exist already, they will not be created.
  • This command loads to Bank $0E, address $B000


Receives files over Serial Link and saves them to the current dir or specified folder.

 Use: FRX [path]


Sends a file (to PC) over Serial Link.

 Use: FTX [path/]filename


Causes a jump within scripts (IE: sets the GOTO envar).

 Use: GOTO label

Where ‘label’ is a 4 character ASCII label within a script.

This command is essentially the same as: “SET GOTO label”


Shows the help file for a particular command.

 Use: HELP command


Main script control function.

 Use: IF xxxx cond yyyy GOTO zzzz

xxxx is the name of an Envar cond is “=” or “<>” for maths/strings or “<” or “>” for maths only
yyyy = is a hex number, another Envar name if enclosed in brackets or a literal string if enclosed in quotes
zzzz = a 4 character (max) label


(Remember: Envars names/values and labels are 4 characters max).


Get user input (hex number) and apply to an environment variable.

 Use: INPUTNUM envar


Get user input (4 chars max string) and apply to an environment variable.

  Use: INPUTSTR envar


Change the keymap.

 Use: KEYMAP [path/]filename

If filename does not contain a path, Keymap looks in the current directory and then in VOL0:keymaps for the keymap file.

The currently available keymap list is:

 UK.bin - UK (default)
 US.bin - USA
 DE.bin - Germany
 IT.bin - Italy
 PT.bin - Portugal


Keymap files are “PS/2 set 2” scancode-to-ASCII translation tables. They can contain two or three “banks” of the translation table: one for unshifted keys, one for shifted keys and optionally one for Alt-modified keys. Each bank is 98 bytes long, covering scancodes $00-$61.


Disassembles a Linecop program.

 Use: LCD linecop_address

Note: “linecop_address” is in the range 0-FFFE and refers to the LineCop accessible area of system RAM from $70000-$7ffff. (The least significant bit is ignored).


Loads a file to Sprite RAM.

 Use: LOADSPR [path/]filename address

Note: address is flat sprite memory location between 0-1FFFF.


Loads a file to Video RAM.

 Use: LOADVRAM [path/]filename address

Note: address is a flat video memory location between 0-7FFFF.


Direct all 4 sound channels to both left and right speakers.

 Use: MONO (no arguments)


Activate the mouse driver.

 Use: MOUSE (no arguments)


  • The mouse command initializes the mouse driver.
  • If a mouse is detected it calls the kernal routine “kjt_enable_mouse”.


Saves data from Video RAM to a file.

 Use: SAVEVRAM [path/]filename address length

Note: address is flat video memory location between 0-7FFFF.


Sets / deletes / adjusts environment variables.

 Use: SET abcd (=) value

Where: abcd is the 4 character ascii name for the envar. “=” can be omitted if desired.

Value is either:

  • A 32 bit max hex value string EG: 1234AAFF
  • A 4 character (max) string in quotes EG: “BEEP”
  • Another envar name in round brackets. EG: (NAME)
  • + To increment the value of the envar
  • - To decrement the value of the envar
  • # To delete the envar if it exists.

If no arguments are given, the current environment variables are listed.

     SET BEAN = 12345678
     SET BEAN -
     SET BEAN +
     SET HATS #
     SET BLAH = (HATS)


Directs sound channels 0+2 to left speaker, and 1+3 to right speaker.

 Use: STEREO (No arguments)


Shows the contents of a text file.

 Use: TYPE [path/]filename


Reports the FLOS / OSCA version.

 Use: VERS (#)

Note: If # is included, nothing is displayed. Instead, two EnVars called “OSCA” and “FLOS” are created. These are set to the respective version values.


Sets VGA refresh rate.

 Use: VGA rate

Where rate = “50” or “60”.

Note: 50hz is non-standard and may not work on some monitors.

Utilities list

ASM.FLX - Assemble Z80 source code.
BULKFILE.FLX - Makes a new file by joining the all files in dir (index at top).
CHECKSYS.FLX - System diagnostic tool.
DDIR.EXE - Alernative DIR command - Decimal listing (By Stefano).
DISKTOOL.FLX - Allows partitioning of SD cards.
EDIT.FLX - Simple text editor.
EEPROM.FLX - An app to write FPGA configs etc to the onboard EEPROM.
EMU.FLX - Used to launch Alessandro’s cycle-perfect Spectrum Emulators.
FILEMGR.FLX - A simple file manager.
FIRMWARE.EXE - Writes blocks of data to the EEPROM 'wholesale'.
FS.EXE - File viewer / launcher (by Valen).
GREP.EXE - An implementation of the unix GREP command (by Stefano).
HEXOR.EXE - File Hex Editor (by Enzo).
KMAPEDIT.FLX - Keymap editor (to assist making keymaps for non-UK keyboards).
MEMCLR.EXE - Clears entire memory (apart from FLOS) (By Daniel).
MEMRND.EXE - Fills memory with random data (apart from FLOS) (By Daniel).
MODPLAY.FLX - Protracker format music player.
PCXSHOW.EXE - Displays .pcx format graphic files (By Enzo).
PLAYCV6.EXE - Plays .cv6 video files (by Daniel).
PLAYMV6.EXE - Plays .mv6 video files (by Daniel).
PLAYWAV.FLX - Plays .wav format sound files.
PT3PLAY.EXE - PT3 format music player (by Daniel).
SHOWBMP.FLX - Displays .bmp pictures.
SHOWSPR.FLX - Browse sprite memory.
SHOWSND.FLX - Browse system memory for sound sample data.
SHOWVRAM.FLX - Display section of video RAM.
SQ.EXE - File Packer (by Stefano).
UPDATE.EXE - Used to update the firmware of old V6Z80Ps (Bootcode/FLOS/OSCA) in one go.
USQ.EXE - File Unpacker (by Stefano).
ZPACK.EXE - File packer (by Enzo).
ZCALC.FLX - A port of the open source scientific calculator app ZCALC (by Enzo).

Documentation for most of these programs is also available by typing “HELP util_name”, or is provided in their respective folders.

FLOS return messages

When a program returns to FLOS with a value in A other than zero, (and the zero flag is not set) one of the following messages will be displayed:

$01 - Volume Full
$02 - File Not Found
$03 - Dir Full
$04 - Not A Dir
$05 - Dir Is Not Empty
$06 - Not A File
$07 - File Length Is Zero
$08 - Address out of Range
$09 - Filename Already Exists
$0a - Already at root
$0b - Unknown command
$0c - Invalid Hex
$0d - No filename
$0e - Invalid Volume
$0f - Checksum bad
$10 - [Space] Bytes Loaded
$11 - Comms error
$12 - Bad arguments
$13 - Not FAT16
$14 - Serial time out
$15 - Filename too long
$16 - No start address
$17 - No file length
$18 - Save aborted
$19 - Save error at destination
$1a - Value out of range
$1b - Data after EOF request
$1c - No end address
$1d - No destination address
$1e - Bad range
$1f - Missing arguments
$20 - OK
$21 - Invalid bank
$22 - Device not present
$23 - Dir not found
$24 - End of Dir
$25 - Filename mismatch
$26 - OS RAM protected
$27 - “?”
$28 - No Volumes
$29 - None Found
$2a - Receive Aborted
$2b - Envar not found
$2c - Envar file full
$2d - Aborted
$2e - No MBR

$80-$f0 = Silent, unspecified errors (No text is shown by FLOS, but “ERR” envar is set to the value in A).

Note: Please refer to the individual Kernal Call documentation for the exact error codes those routines return.


Format of header for Operating System (.OSF) file:

$00 - $07 : [ASCII] Characters: Z80P*OS*
$08 - $0B : [DWORD] Length of file (excluding header)
$0C - $0D : [WORD] CRC checksum of file
$0E - $0F : [WORD] If <> 0, this is interpreted as an offset from the start of the OS ($1000) to an OS indentification ASCII string

(A Windows utility is provided to insert the correct CRC into an OS file - see the project folder “PC_based_apps/”, PureBasic source code also supplied.

Note: The CRC is not checked when an OS boots via serial link as the serial protocol already contains error checking.)


Volume Mount List

The address of this table is returned in HL by the KJT routine “kjt_get_volume_info”.
Each volume entry is 16 bytes long and contains the following data:

$001 = Volume is present, else zero (note: this does not mean it is a valid FAT16 volume.)
$01Volume's host driver number
$04Volume's total capacity in sectors (3 bytes)
$07Partition number on host drive (0/1/2/3)
$08Offset in sectors from MBR to partition boot sector (2 words, little endian)

Host Device Hardware Info

The address of this table is returned in HL by the KJT routine“kjt_get_device_info”.
Each device entry is 32 bytes long and contains the following data:

$00Device driver number
$01Device's TOTAL capacity in sectors (4 bytes)
$05Zero terminated hardware name (22 ASCII bytes max followed by $00)

(remaining bytes to $1F currently unused)

Driver Table

The address of this table is returned in DE by the KJT routine “kjt_get_device_info”.
Each driver entry is the absolute address of the driver in memory. There are 4 driver slots available, if an entry is zero, the slot is free for use (a user program can place an address there, and remount drives to update the device and volume tables).

$00 - Driver 0 address (normally the SD card driver on V6Z80P)
$02 - Driver 1 address
$04 - Driver 2 address
$06 - Driver 3 address

Each FLOS device driver has the following structure:

$00-$07 : 7 ASCII bytes, name of driver EG: “SD_CARD”
$07 : Zero
$08 : Z80 code: JP read_sector routine
$0B : Z80 code: JP write_sector routine
$0E : “get_id” routine starts here.

The three routines should return with the Zero Flag set if the operation was a success. Otherwise, if an error was encountered a hardware error code can be placed in A.
The “get_id” (initialization) routine should additionally return with BC:DE set to the total capacity of the device in sectors, and HL set to the location of a zero-terminated hardware ID ASCII string (this string is used for reference only).

Driver routines should use these standard labels (used throughout FLOS):

“sector_buffer” - 512 bytes

“sector_lba0” - LBA of desired sector LSB
“sector_lba3” - LBA of desired sector MSB

PSPad Setup

PSPad setup for Z80 / V6Z80P coding:

Settings → Highlighter Settings..

On the Specification tab, untick “x86 assembly” and then tick one of the “<not assigned>” entries, locate and click “Z80” in the user highlighters box and click “Apply”.

Move to the Compiler tab..

 Compiler    : [browse to the Pasmo executable in the project folder Pasmo dir.]
 Parameters  : -d -I [location of project folder]\%Dir%%Name%%Ext% %Dir%%Name%.flx
 Default dir : [browse to Pasmo dir in project folder]
 Tick        : "Capture program output window" to display Pasmo output at foot of display.
 Tick        : "Save all files before compilation" as desired.

Compile with FILE→COMPILE or CTRL+F9

The source code will be assembled to a file called [filename].flx in the source file's dir (Pasmo's output is shown at the bottom of the display).


If it is required to send the freshly assembled code to FLOS for testing via the serial port, this can be achieved by setting up PSpad to call the PC command line program “SerialTX.exe” as an “external application”.

This can be set up as follows:

Settings → Highlighter Settings.. [External applications tab]

 Name        : Send to V6Z80P
 Application : [Browse to \PC_based_apps\SerialTX\serialtx.exe]

Change the default parameters at the end of the command string from %file% to: %Dir%%Name%.flx

Click Add.

Now, whenever you want to send the previously assembled file to FLOS, enter “RX !” in FLOS and on the PC, press F9 or click the “Open active file in external program” button on the right side of the tool bar.

(Daniel Illgen has made a Linux equivalent to the Windows SerialTX - see the Contributions folder.)

Programmer's Notepad Setup

Programmer's Notepad Setup for Z80 / V6Z80P coding:

First, copy the z80.scheme file from the “Pasmo\For Programmer's Notepad\” folder to the schemes folder of the Programmer's Notepad. The next time you start up Programmer's Notepad, you should see “Z80 Assembler” listed as a language for syntax highlighting.

Next, set up the compiler:

Tools → Add Tools..

 Name       : Pasmo
 Command    : [browse to Pasmo.exe in Pasmo dir of project folder]
 Folder     : [browse to Pasmo dir in project folder]
 Parameters : -d -I [location of project folder]\ %d%f %d%n.flx
 Shortcut   : [As desired, F9 suggested]
 Save       : Current file

Compile with TOOLS → Pasmo (or hit your shortcut key). The source code will be assembled to a file called [filename].flx in the source file's dir (Pasmo's output is shown at the bottom of the display).


If it is required to send the freshly assembled code to FLOS for testing via the serial port, Programmers Notepad can be set up to do this by configuring another tool: SerialTX (found in the dir \PC_based_apps\SerialTX\).

Tools → Add Tools..

 Name       : Send to V6Z80P
 Command    : [browse to serialtx.exe in the project folder: PC_based_apps/SerialTX]
 Folder     : [browse to the SerialTX dir]
 Parameters : %d%n.flx
 Shortcut   : [As desired, F10 suggested]
 Save       : None

Click OK.

Now, whenever you want to send the previously assembled file to FLOS, enter “RX !” in FLOS, then on the PC press your shortcut key or click “TOOLS→Send to V6Z80P” in the tool bar.

(Daniel Illgen has made a Linux equivalent to the Windows SerialTX - see the Contributions folder.)


(Kernal is “misspelled” throughout as a nod to the C64:)

1) , 2) , 3) , 4) , 5)
System RAM “underneath” video registers
flos_manual.txt · Last modified: 2017/07/03 19:31 by z00m