FLOS
FLOS v5.97 docs
Created by: Administrator, Last modification: Fri 13 of Jan, 2012 (14:53 UTC) by phil
Page Contents
A Simple Command Line Operating System for OSCA on the V6Z80P by Phil Ruston.
Description:
FLOS operates in a similar manner to the memory monitor / freezer cartridges of the 8 bit 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 boot-loader will load the first *.OSF file it finds. It can also be installed on the V6Z80P's EEPROM (by using the application “EEPROM.EXE”)
The .OSF file is just a Z80 program binary with a 16 byte header, the format of which is as follows:
$00 - $07 : ASCII Characters: Z80P*OS*
$08 - $0B : Length of file (excluding header)
$0C - $0D : CRC checksum of file
$0E - $0F : Not currently used – set to $0000
(A Windows utility is provided to attach this header onto a raw OS file. See the project folder “PC_based_apps/” - PureBasic source code also supplied.)
Upon start up, the bootloader loads the *.OSF file to Z80 address $1000 and jumps to location $1010 to execute its code (therefore any FLOS replacement should also have an origin of $1010). The bootloader looks for the OS on the SD card first, if it is not found there it checks the EEPROM. If no OS is found on either, then the user is prompted to download an OS file via the serial link.
Using FLOS at command line level:
When the OS 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 if this is done then the drives must be remounted with the command 'MOUNT' (hot-swapping cards is probably best avoided for sake of stability in any case.)
There are a set of internal debugging and disk navigation commands. To run a command type its name (and any parameters it requires) and press Enter.
Internal_Commands
(Click here for more detail)
B - Set the bank of System RAM appearing at at Z80 $8000-$FFFF
C - Copy bytes in memory (from currently selected bank)
CD - Change directory
CLS - Clear OS screen
COLOUR – Change the OS colour scheme
D - Disassemble Z80 code
DEL - Delete a file
DIR - Show directory
EXEC – Execute a script
F - Fill Memory
FORMAT - Format the (entire) SD card as a single FAT16 partition.
G - Goto location (IE: Call Z80 routine)
H - Hunt in memory for hex bytes
LB - Load Binary file to RAM from disk
M - Show memory as hex bytes
MD - Make a new directory
MOUNT – Remount drives
R - Show registers
RD - Remove directory
RX - Receive file (to RAM) from PC via serial link (and optionally, run as code)
SB - Save Binary file from RAM to disk
T - Show memory as ASCII text
TX - Transmit bytes to PC (from RAM) via serial link
VERS - Show OSCA / FLOS version
VOLx: - Switch volume without altering the directory position.
: - Put hex bytes in memory
> - Put text in memory
? - Show internal command list and parameter requirements
< - Put bytes in memory and disassemble
Throughout FLOS, numeric data is in hexadecimal format (apart from the free disk space reported by the DIR command). The default keymap is that of the UK, but this can be changed to other locales with the command ”Keymap”. To assist with such settings, FLOS will auto-run a batch file called “BOOT_RUN.SCR” at start-up if is present in the root directory of the SD card (the execution of the script can be aborted by pressing CTRL+C when FLOS starts up).
FLOS also allows the function keys to be assigned command strings. To use this feature simply put text files called F1.CMD (to F9.CMD) in the current directory (or use the assign envar %key - the most local version has priority). The command strings can be 40 characters long max but can be an EXEC command if desired.
External Commands
If the command entered is not recognized as an internal command name, FLOS will look in the current disk directory, and then look in the "executable path" for a file with an .exe extension that matches the string entered. If found, the file is assumed to be a program, loaded and executed.
The "executable path" is set up with asssigned folders with the envar names %ex0 to $ex9 (FLOS itself sets %ex0 to VOL0:COMMANDS)
The programs supplied in the COMMANDS folder all load high in memory to avoid interference with user data which will normally be at the usual load address $5000 onwards.
More general utilities (and programs written in C that need to load low) are supplied the folder UTILS.
EXTERNAL COMMANDS:
ASSIGN.EXE - Makes a environment variable link to a directory (substitute long paths)
BAUD.EXE - Sets the BAUD rate
BOOT.EXE - Reconfigure the FPGA from a given slot
CHFNT.EXE - Changes the OS font
ECHO.EXE - Displays short messages
FILEINFO.EXE - Retuns info about a file
GOTO.EXE - Script control
IF.EXE - Script control
INPUTNUM.EXE - Wait for a hex number to be entered
INPUTSTR.EXE - Wait for a 4 character string to be entered
HELP.EXE - Show help doc files
KEYMAP.EXE - Change the key map
LCD.EXE - LineCop disassembler
LOADSPR.EXE - Loads a file to Sprite RAM
LOADVID.EXE - Loads a file Video RAM
SERCOPY.EXE - Bulk serial download / copy to
MOUSE.EXE - Activate the mouse driver
MONO.EXE - Sets the audio panning to mono mode
SET.EXE - Set/list environment variables
STEREO.EXE - Sets the audio panning to split stereo mode
TYPE.EXE - Displays text files
VGA50.EXE - Force VGA refresh rate to 50Hz (non standard)
VGA60.EXE - Force VGA refresh rate to 60Hz (default)
In FLOS, type HELP (command) for paramter details etc.
UTILS:
ASM.EXE - Assemble Z80 source code
DDIR.EXE - Alernative DIR command (Decimal listing)
DISKTOOL.EXE - Allows partitioning of SD card.
EDIT.EXE - A simple text editor
EEPROM.EXE - An app to write FPGA configs etc to the onboard EEPROM
FILEMGR.EXE - Simple file manager
FIRMWARE.EXE - Writes blocks of data to the EEPROM 'wholesale'
FS.EXE - File viewer / launcher (by Valen)
GOSPEC.EXE - Lauches Alessandro Dorigatti’s Spectrum Emulator for v1.1+ V6Z80Ps
HEXOR.EXE - File Hex Editor (by Enzo)
MEMCLR.EXE - Clears entire memory (apart from FLOS)
MEMRND.EXE - Fills memory with random data (apart from FLOS)
MODPLAY.EXE - 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.EXE - Plays .wav format sound files
PT3PLAY.EXE - PT3 format music player (by Daniel)
SHOWBMP.EXE - Displays .bmp pictures
ZPACK.EXE - File packer (by Enzo)Scripts
Simple scripts (batch files) with limited flow control can be used within FLOS. These are standard text files launched with “EXEC script_name”. Note that FLOS scripts cannot run other scripts.
Script flow control is achieved with in-script labels (up to 4 characters in square brackets) and the following commands:
IF - Jump on condition
GOTO - Unconditional jump to label
INPUTNUM - Get a number from user (up to 32 bit)
INPUTSTR - Get string (up to 4 chars) from user
FILEINFO - Get file size in enavr “FSIZ”
SET - Manage environment variables
As these are external commands they load to the top 4KB 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:
ECHO CHOOSE AN OPTION
ECHO 1. RED TEXT
ECHO 2. GREEN TEXT
ECHO 3. YELLOW TEXT
INPUTNUM PEN
IF PEN = 1 GOTO RED
IF PEN = 2 GOTO GRN
IF PEN = 3 GOTO YEL
ECHO INVALID CHOICE
GOTO END
RED
COLOUR 3
GOTO DONE
GRN
COLOUR 5
GOTO DONE
YEL
COLOUR 7
DONE
ECHO CHOICE ACCEPTED
END
Notes: Comments are not supported in scripts, lines must be left aligned, labels are 4 chars max, no other text can be on the same line as a label. The termination point is the end of the script file, so if a script is to break before then a GOTO END 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”
Coding apps for FLOS:
FLOS-friendly programs by default load and run from $5000 (as the OS resides at $1000-$4FFF), but it is possible to force FLOS-based programs to load and run from any address above $5000 by adding a program location header to the start of the code. It is also possible to truncate the load length with this header.
Where programs start, 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). Apps can scan from this address for parameters if required – when zero is eventually 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 is 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.
Upon exit, apps returning control to FLOS should set the zero flag to report no error. If the zero flag is not set, a text message associated with the value in A is displayed - see return messages for the list.
If A=0, then a driver error code is being passed in B.
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).
(If a program has only changed the display mode and not overwritten the video RAM used by the OS, then the kernal call “KJT_FLOS_DISPLAY” can be called prior to exit to restore the display, this way FLOS does not have to restart.)
By default, FLOS logs the Z80 register set on return (as displayed with the R command). If this is not required the program can call the KJT routine “kjt_dont_store_registers”.
Assembling:
Any preferred Z80 assembler can be used - code can even be produced entirely on the V6Z80P using EDIT.EXE and ASM.EXE.
The project's source code was developed using a plain text editor and assembled with the freeware assembler 'Pasmo'. In the project's code folders there's normally a batch file called "assemble.bat". This contains the Pasmo commands required to produce the Z80 binary. The .asm file can be dragged to this batch file and it'll produce a binary file with the extension ".asm.bin". (The Windows program "pasmo_rename.exe" takes the .asm.bin and renames it to an 8.3 format filename with .exe extension.) See the "example_source" folder for templates and simple examples.
Resources used by FLOS:
- System RAM : $00200-$04FFF
- Video RAM : $10000-$1FFFF
- Video registers associated with bitmap planar display.
- The timer hardware
- IRQ mode 1 for keyboard (and mouse)
- The Blitter
- The Maths Table (first word, index and mult_write)
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)
Note: As FLOS internally uses the blitter and the first word of the hardware multiply table (index 0) – user programs should take into account that these systems are reset to the values FLOS requires every time control is passed to it (via KJT calls etc) and will not be restored upon return.
Debugging:
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 that it's not possible to restart the "frozen" program from the point it was stopped and also that the ROM must not be paged out (and lower 32KB page selection bits = zero) at the point the button is pressed.
Environment Variables (or "cookies")
Each environment variable has a name of 1 to 4 ASCII characters (case sensitive, no spaces) and an associated binary value 4 bytes long. Variables are handled with the kernal commands kjt_set_envar, kjt_get_envar and kjt_delete_envar. The external command "SET.EXE" can set an environment variable at the command line (or list those already set up if no arguments are supplied). At present there is room for 16 environment variables.
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, it can only be 3 characters long and is automatically prefixed with "%". Note that because of the limited space, the entire path string is not actually 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.
A Note About Interrupts:
The OSCA ROM* has the instruction JP $0A00 at $38 (IRQ) and JP $0A03 at $66 (NMI). OSCA is designed to use Interrupt Mode 1. 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)
FLOS uses the global labels irq_vector and nmi_vector for $0A01 and $0A04 respectively. As indicated above, these are set by default to FLOS's IRQ/NMI routines but can be set by external apps if desired.
FLOS's IRQ routine handles keyboard and mouse interrupts only (for operating the kernal keyboard and mouse routines). 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 user's interrupt handler just needs to test bits 0:1 of the port sys_irq_ps2_flags and call the appropriate routine if the relevant bit is set.)
FLOS's NMI routine is used in association with a push switch across the V6Z80P pin header's 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)
(* The OSCA ROM can be banked out if desired - see OSCA hardware manual.)
Kernal
A Kernal Jump Table is a simple way (indirect jumps) of ensuring that routines within the operating system can be used by external programs, even if the OS code changes. IE: The location of the jump table and the order of its entries should never change, so calls to OS routines can be made via the KJT_* entries.
The KJT equates file should be included into the user program, 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 which registers are preserved.
Bear in mind that FLOS assumes the memory paging settings are in their default state and certain Kernal routines may not work correctly if for example video memory is paged in. See the individual routine descriptions for details.
KJT Disk Routines:
In general, these routines set the zero flag on return if the operation was successful. If the zero flag is not set, then the accumulator contains the file system error code. If the accumulator is zero, then there was a low-level hardware error and register B will contain the hardware level error flags associated with the device (if B is zero, the device timed out.) For full details follow the links.
List of Kernal Disk I.O routines:
kjt_check_volume_format - Checks if current volume is formatted to FAT16.
kjt_change_volume - Selects drives VOL0: to VOL7:
kjt_get_volume_info - Returns data about the volumes mounted
kjt_format_device -Formats entire disk (or card) to FAT16
kjt_make_dir -Creates a new sub directory in current directory
kjt_change_dir - Change to subdirectory
kjt_parent_dir -Move up a directory level
kjt_root_dir -Go to root directory of drive
kjt_delete_dir - Deletes an (empty) directory
kjt_erase_file -Deletes a file
kjt_get_total_sectors -Returns total sectors on current volume
kjt_open_file - Looks for a file on current disk, resets file pointer
kjt_set_file_pointer - Moves the read point from the start of a file
kjt_set_load_length - Forces the read length of the transfer to a certain value
kjt_read_from_file - Forces a file to be loaded to a particular address
kjt_create_file -Makes a file stub for a new file.
kjt_write_to_file - Appends new data to an existing file.
kjt_load_file - Opens and loads an entire file
kjt_save_file - Creates and saves an entire file
kjt_dir_list_first_entry – Find first entry in current directory.
kjt_dir_list_get_entry - Returns data from directory list (see output registers)
kjt_dir_list_next_entry - Moves directory list pointer to the next entry
kjt_get_dir_name - Returns the name of the current directory.
kjt_mount_volumes - Initializes the attached disk list.
kjt_store_dir_position - Internally remembers the current directory position.
kjt_restore_dir_position – Restores directory to that stored by above.
kjt_get_device_info – Returns info about the storage devices.
kjt_get_dir_cluster - Returns the directory location cluster
kjt_set_dir_cluster - Sets the directory location cluster
kjt_rename_file - Rename a file (or directory)
Low-level sector access routines:
kjt_read_sector - Loads 512 byte sector to the sector buffer
kjt_write_sector - Writes 512 byte sector to the current device
kjt_file_sector_list - Retrieves the location of the (next) disk sector that a file occupies.
kjt_get_sector_read_addr - Returns location of a drivers read sector routine, the OS LBA variable and sector location variable. With this info, fast direct sector loading can be performed.
Kernal Serial Comms Routines:
Similar to the disk routines, the Zero flag is set on successful operation. If an error is encountered the zero flag is not set and A contains the error code, a list which is given in the 'KJT full descriptions' document.
High level serial IO routine list:
kjt_serial_receive_header - Waits for a file header from serial port
kjt_serial_receive_file - Receives serial file data
kjt_serial_send_file - Sends a file to serial port (Serial Link App format)
Low level serial IO routine list:
kjt_serial_rx_byte - Wait for a byte from serial port
kjt_serial_tx_byte - Send a byte to serial port
Kernal Keyboard and Mouse Routines:
kjt_wait_key_press - Pauses until a key is pressed
kjt_get_key - Returns value of key, if one has been pressed (does not wait)
kjt_get_key_mod_flags - Returns status of the shift, ctrl, alt etc keys
kjt_enable_mouse - Activates mouse driver / sets window limits.
kjt_get_mouse_position - Returns absolute mouse position and button data
kjt_get_mouse_motion - Returns relative mouse offsets since the last time the routine was called.
kjt_keyboard_irq_code - allows external apps to use kernal IRQ code with a custom IRQ handler
kjt_mouse_irq_code - allows external apps to use kernal IRQ with a custom IRQ handler
kjt_get_key_buffer - allows external apps to monitor the keyboard buffer without removing keystrokes from it.
Kernal Text and display routines
kjt_print_string - Prints ASCII text string at the current cursor position
kjt_clear_screen - Clears OS screen and sets cursor position to top left (0,0)
kjt_plot_char - Prints character at given coords using current pen colours
kjt_set_pen - Changes current pen colour
kjt_get_pen - Returns current pen colour
kjt_draw_cursor - Draws (or removes) the cursor at the current cursor position
kjt_get_input_string - Waits for user to enter a string of characters
kjt_set_cursor_pos - Repositions the text printing (cursor) position
kjt_get_cursor_pos - Returns the current cursor position
kjt_scroll_up - Scrolls the screen (and character map) up a line.
kjt_flos_display - Restores the video registers to the state used by the OS.
kjt_get_display_size -Returns size of OS_window
kjt_get_charmap_addr_xy - Returns the charmap address of coordinates x,y
kjt_wait_vrt - Wait for last scanline of display
kjt_get_colours - Returns location of FLOS colour scheme list
kjt_set_colours - Sets FLOS colour scheme
kjt_patch_font - Change individual characters in the FLOS font / add user defined chars.
Kernal Memory Management Routines:
kjt_force_bank - Switches the upper RAM page to a specific bank
kjt_get_bank - Returns the current bank number in A
kjt_inc_bank - Change to the next bank
kjt_page_in_video - Pages video memory into $2000-$3FFF
kjt_page_out_video - Pages system memory into $2000-$3FFF
kjt_read_sysram_flat - Read memory in a linear, flat mode
kjt_write_sysram_flat - To write to memort in a linear, flat mode
Kernal Misc Routines:
kjt_hex_byte_to_ascii – Make ASCII version of a hex byte
kjt_ascii_to_hex_word - Converts text hex number to real hex word
kjt_dont_store_registers – Stops the OS noting the register values on exit
kjt_get_version - Returns OS and hardware ID numbers
kjt_compare_strings - Compares two ASCII strings
kjt_bchl_memfill - Fill memory with value in accumulator
kjt_timer_wait - Waits n periods of 16 microseconds and returns
kjt_set_commander - Tells FLOS to always run a specific command string when programs exit.
Environment Variable Routines:
kjt_set_envar - Sets an environment variable
kjt_get_var - Retrieves data address for an environment variable
kjt_delete_var - Deletes an environment variable