Using Z88DK - RC2014Z80/RC2014 GitHub Wiki
Z88DK is a complete development toolkit for the 8080, 8085, gbz80, z80, z180 (ez80), z80n and Rabbit processors.
The Z88DK wiki is the source for general install and tool use. This page is RC2014-specific. Also see:
- Platform โ RC2014 (subtypes / clib summary)
-
Platform โ HBIOS (
+hbios/ RomWBW) -
Platform โ CPM (classic
+cpmunder CP/M) - Getting started ยท Compilers
The Z88DK contains three C compilers, an assembler / linker / librarian, data compression tools and a utility for processing the raw binaries into forms needed by specific targets (z88dk-appmake).
It comes with an extensive library of functions written in assembly language that implements the C standard and many extensions supporting specific target hardware. It holds the largest repository of z80 code on the Internet.
Development in assembly language or C is completely integrated; projects can be 100% assembler, 100% C or any mixture of the two. The toolset treats both as first-class languages and is designed to make it very easy to mix them at will with C and asm functions being able to call each other or make use of the hand-optimized library functions.
Tree layout note (2026): RC2014 and HBIOS target sources live under
libsrc/target/rc2014andlibsrc/target/hbios(formerly underlibsrc/_DEVELOPMENT/target/โฆ/libsrc/newlib/target/โฆ). Newlib library products install underlib/clibs/{sccz80,sdcc_ix,sdcc_iy}/(third-party packages underlib/clibs/โฆ/lib/<target>/). Note:sdcc_iycompile mode often still links thesdcc_ixlibrary product path on many targets โ seelib/config/rc2014.cfg. Classic console examples live underexamples/console/. Float packages live underlibsrc/math/float/(math16, math32, math48, am9511, โฆ). General install/recipes: z88dk wiki Examples, Load and run.
The Z88DK Installation page has full instructions on how to install the compilers and environment. Follow that first as it is more likely to be up to date and accurate.
Development pace within Z88DK is fairly rapid, and as such it is best to use a git clone of the z88dk repository and build your own installation where possible.
Where you prefer (for macOS or Windows platforms), the latest nightly build should be installed using the normal macOS or Windows binary installation instructions. The nightly build contains a ready-made z88dk-zsdcc for these platforms, so there is no need to build it following the instructions below.
To clone the current Z88DK GitHub package:
git clone --recursive https://github.com/z88dk/z88dk.git
# or: git clone โฆ && git submodule update --init --recursive
sudo apt-get install expect texinfo libxml2-dev flex bison gputils libboost-dev
This will create a populated z88dk directory in the current working directory.
To succeed in building the z80svg graphics tool you need the libxml2 library to be previously installed, although its absence will not prevent the rest of the kit from building.
Check the installation page for a complete set of dependencies required to be installed before building.
Then to build the z88dk (with z88dk-zsdcc), just type:
cd z88dk
git submodule update --init --recursive
export BUILD_SDCC=1
chmod 777 build.sh
./build.sh
You can run z88dk keeping it in the current location; all you need to do is to set the following environment variables.
Supposing you have bash (most likely it is your system default shell) and you want to keep z88dk in your home directory, you can configure it permanently in this way:
vi ~/.profile
Modify the configuration by adding these lines (with the appropriate paths).
export PATH=${PATH}:${HOME}/z88dk/bin
export ZCCCFG=${HOME}/z88dk/lib/config
A system install is not supported in this release of Z88DK.
To install the sdcc compiled specifically for the Z88DK, also called z88dk-zsdcc, these are the instructions. If you exported BUILD_SDCC=1 in the previous step, then z88dk-zsdcc will have already been built for you and you do not need to do this step.
Check out the current development version of sdcc. If you already have the sdcc/sdcc-code tree available from a previous checkout you can instead perform an update.
svn checkout svn://svn.code.sf.net/p/sdcc/code/trunk@15248 sdcc-code
# or if you're doing this to refresh your sdcc installation...
cd sdcc-code
svn update -r 15248
You will have to apply the patch found in src/zsdcc and build sdcc from source. Copy sdcc-z88dk.patch into the sdcc-code directory.
The supplied configuration options below disable all ports other than the Z80 family ports, and turn off compilation of many unnecessary libraries and tools. This will also prevent potential errors from completing the build process, and results in a smaller compiler binary.
cd sdcc-code/sdcc
patch -p0 < ../sdcc-z88dk.patch
./configure --disable-ds390-port --disable-ds400-port --disable-hc08-port --disable-s08-port --disable-mcs51-port --disable-pic-port --disable-pic14-port --disable-pic16-port --disable-tlcs90-port --disable-xa51-port --disable-stm8-port --disable-pdk13-port --disable-pdk14-port --disable-pdk15-port --disable-pdk16-port --disable-mos6502-port --disable-mos65c02-port --disable-r2k-port --disable-non-free --disable-device-lib --disable-ucsim --disable-packihx --disable-sdcpp --disable-sdcdb --disable-sdbinutil
make all
Copy the patched sdcc executable built in the src directory to {z88dk}/bin and rename it z88dk-zsdcc.
cp src/sdcc ~/z88dk/bin/z88dk-zsdcc
Undo the patch.
patch -Rp0 < ../sdcc-z88dk.patch
You can stop here and verify the install was successful below. Keeping the sdcc source tree in an unpatched state can allow you to update the zsdcc binary by repeating the steps above as sdcc itself is updated. Both z88dk and sdcc are active projects that see frequent updates.
To verify that sdcc is usable from z88dk, try compiling sudoku.c for the rc2014 target using sdcc:
zcc +rc2014 -subtype=sio -v -m -SO3 --max-allocs-per-node200000 --c-code-in-asm --list sudoku.c -o sudoku -create-app
Assuming we have a source file called test.c.
int main(void)
{
return(0);
}We can compile it and produce binary CODE and DATA sections. With -create-app, z88dk-appmake assembles the linked image into forms useful for the RC2014 (typically Intel HEX, and section binaries such as test_CODE.bin / test_DATA.bin depending on subtype and map). For the default basic subtype, programs are ORG'd at 0x9000.
zcc +rc2014 -v -m -SO3 --max-allocs-per-node200000 --c-code-in-asm --list test.c -o test -create-app
The binary code can be checked by installing and then using a disassembler such as z80dasm:
sudo apt install z80dasm
# Prefer the CODE section image when present (basic subtype):
z80dasm --address --labels --origin=0x9000 test_CODE.bin
# Some builds also leave a combined image as test.bin โ use the map file if unsure
Or the z88dk disassembler z88dk-dis can be used.
There are three C compilers available for RC2014 work.
-
z88dk-sccz80โ derived from small-C, with continuous development over many years. Most early small-C limitations have been removed: floating point is supported, ANSI C declarations are supported, 8/16/32-bit integers are supported, and so on. Select it with-clib=new(newlib) or, on classic targets such as+cpm, the classic clib default. -
z88dk-zsdccโ a patched sdcc, an optimizing compiler that implements subsets of C89, C99 and C11. z88dk's patch improves output with Z80-family fixes, optimised intrinsic compiler functions, and a large peephole rule set. Select it with-clib=sdcc_ixor-clib=sdcc_iy. For+rc2014,sdcc_iyis the default: it is the same newlib/zsdcc path assdcc_ix, but with--reserve-regs-iyso the library ownsiyand the compiler keepsixfor its frame pointer (see Libraries). -
z88dk-80ccโ a third frontend integrated into the toolset (-compiler=80cc). It is used alongside the same libraries and targets as the other compilers (for example newlib+rc2014and classic+cpm). It is exercised in the tree's regression suites (including target I/O underz88dk-ticks) and is a valid choice when you want that code generator rather than sccz80 or zsdcc.
Examples:
# sccz80 + newlib
zcc +rc2014 -subtype=basic -clib=new -v -m prog.c -o prog -create-app
# zsdcc + newlib (default clib for +rc2014 is sdcc_iy = reserve-regs-iy model)
zcc +rc2014 -subtype=basic -clib=sdcc_iy -SO3 -v -m prog.c -o prog -create-app
# 80cc + newlib
zcc +rc2014 -subtype=basic -clib=new -compiler=80cc -v -m prog.c -o prog -create-app
# 80cc + classic CP/M (BDOS file I/O)
zcc +cpm -compiler=80cc -v -m prog.c -o prog.com -create-app
A command line for compiling a C file or .lst file containing a simple list of mixed C and asm files can look complicated, but it is pretty straightforward.
zcc +rc2014 -subtype=basic -clib=sdcc_iy -SO3 -v -m --list --c-code-in-asm --fverbose-asm --max-allocs-per-node100000 --math32 -llib/hbios/time -llib/hbios/diskio_hbios -llib/hbios/ff @mytest.lst -o mytest -create-app
-
zccis the frontend driver, and is always used. Calls to the individual compilers, assembler, linker, and packager are not typical. -
+rc2014is the target. Unless you prefer the classic CP/M+cpmor RomWBW HBIOS+hbiostargets, you should use this+rc2014target for RC2014-specific hardware and drivers. -
-subtype=basicis the subtype, as described below. If it is missing, a default subtype will be selected (basicfor currentrc2014.cfg). -
-clib=sdcc_iyis the compiler and library choice (sdcc_iyis the default and can be omitted). Use-clib=newforz88dk-sccz80, or add-compiler=80ccto select 80cc. -
-SO3is the optimisation level used with zsdcc. Unless you are debugging the compiler, use a high optimisation setting for production builds. -
-vis verbose.-vnis silent compilation. -
-mproduces a map file. This is very useful to see where each label and section is located in memory. -
-wproduces a warning ifCODE,DATA, orBSSsections overlap (default). -
--listproduces an assembly listing of the C files and the crt. -
--c-code-in-asmincludes C comments in the assembly listing. This is useful to track specifically what assembly is being generated from your C. Often simple adjustments to your C can substantially improve the generated assembly. Do not use this for your final build, as some peephole optimisations will be affected by comments interspersed within the assembly files. -
--fverbose-asmproduces verbose assembly listings when--listis added. Do not use this for your final build, as some peephole optimisations will be affected by comments interspersed within the assembly files. -
--max-allocs-per-node100000defines how aggressively thez88dk-zsdcccompiler should attempt to optimise the code. Typical values range from 3000 to 400000. Increasing the value produces better code, but the compilation time can become excessive. -
--math32uses the IEEEmath32library. The traditionalmath48library is linked by-lm. The APU Module library is--am9511(or equivalent project flags). -
-llib/target/librarylinks a specific third-party library installed withz88dk-lib(see below). -
@mytest.lstis a file containing a simple list of C and assembly programs to be compiled and linked into one outcome. If you have only one C file, usemyfile.con the command line instead. -
-o testspecifies the root of the output files. Section images such astest_CODE.bin/test_DATA.binand an Intel HEX file are typical after-create-app; consult the map file if a zero-lengthtest.binappears (the useful image is often*_CODE.bin). -
-create-appcallsz88dk-appmaketo produce the final binary and Intel HEX files required to upload to the RC2014.
The classic C library is the C library that has always shipped with z88dk. It has many crts available for it that allow compiling for a lot of target machines out of the box. The level of library support varies by target with the best supported having sprite libraries, sound, graphics, etc. supplementing the standard C library. It is mostly written in machine code and has a small stdio implementation. However, at this time it cannot be used to generate ROM-able code as it mixes variables with code in the output binary.
The new C library is a rewrite from scratch with the intention of meeting a subset of C11 compliance. It is 100% machine code, is written to be compatible with any C compiler, and can generate ROM-able code with separation of ROM and RAM data. The stdio model is object oriented and allows device drivers to be written using code inheritance from the library. Although it is unfinished and ongoing (disk I/O is target- and library-dependent; non-blocking I/O is limited), it is in an advanced state.
The RC2014 is supported by the new C library for its +rc2014 subtypes. The classic C library and the +cpm target can be used with the RC2014 when it is running any implementation of CP/M. The classic C library does not support bare-metal RC2014 ROM subtypes directly; use +rc2014 for those.
The choice of C library is made on the compile line:
| Compile flags | Compiler | Library |
|---|---|---|
-clib=new |
z88dk-sccz80 |
new C library |
-clib=new -compiler=80cc |
z88dk-80cc |
new C library |
-clib=sdcc_ix |
z88dk-zsdcc |
new C library (IX register model) |
-clib=sdcc_iy |
z88dk-zsdcc |
new C library (--reserve-regs-iy model; default for +rc2014) |
other / classic targets such as +cpm defaults |
classic tool chain | classic C library |
+rc2014 -clib=default |
classic tool chain | classic rc2014_clib (limited; prefer newlib for ROM subtypes) |
In order to generate ROM-able code, you must be using the new C library.
z88dk's C libraries are different from many other development environments in that they are written in Z80 (8080, 8085, z180, z80n) assembly language, so they are faster and more compact than C libraries written in C.
When the compiler is z88dk-zsdcc, you select a library register model with -clib=sdcc_ix or -clib=sdcc_iy. These are not two unrelated libraries: sdcc_iy is the reserve-registers form of the same newlib / zsdcc setup used for sdcc_ix.
Under the hood (see lib/config/rc2014.cfg):
- Both use
-compiler=sdccand the newlib target product (-lrc2014fromlib/clibs/sdcc_ix/โฆ). -
sdcc_iyadditionally passes--reserve-regs-iyto zsdcc. That tells the compiler that theiyregister pair is reserved โ the compiler must not allocateiyfor its own code generation. - With
iyreserved for the library, the hand-written newlib can useiyfreely as its preferred index/frame-style register in asm library routines. -
ixis then left entirely to zsdcc for its usual purpose as the C stack frame pointer (locals, parameters, and compiler-managed stack addressing).
-clib=sdcc_ix |
-clib=sdcc_iy (preferred) |
|
|---|---|---|
Compiler (zsdcc) |
Uses ix as frame pointer |
Uses ix as frame pointer |
| Library (newlib asm) | Also relies on ix in many routines |
Uses iy (--reserve-regs-iy keeps the compiler out of iy) |
| Conflict | Compiler and library share ix
|
No shared index register |
| Cost | Library entry/exit (and many callees) must save and restore ix so the frame pointer is not corrupted |
Library need not preserve ix around normal library use of iy
|
| Result | Extra push ix / pop ix (and related) traffic โ larger, slower
|
Smaller, faster object code and library call overhead |
In short: sdcc_iy is the --reserve-regs-iy variant of the sdcc/newlib path. Reserving iy for the library removes the ix ownership fight with zsdcc's frame pointer, so the library does not have to constantly save/restore ix. That is why sdcc_iy is the default for +rc2014 and should be preferred over sdcc_ix unless you have a specific reason to share ix with the library.
Use sdcc_ix only when you must (for example third-party asm that assumes the library uses ix, or debugging register allocation). For ordinary RC2014 applications, sdcc_iy is the correct choice.
The standard I/O library #include <stdio.h> provides console output for either one or two serial interfaces, depending on the hardware configuration. For the ACIA and BASIC subtypes stdin, stdout, and stderr are provided. For SIO subtypes ttyin, ttyout, and ttyerr are added on the second serial terminal where dual UART wiring applies. For RomWBW, use the +hbios target (not a +rc2014 subtype). The CP/M subtype provides stdrdr, stdpun, stdlst to reference the CP/M reader, punch and list devices respectively.
Terminal attributes can be controlled by modifying the rc2014_rules.inc file, according to the instructions here.
For stdin, ttyin, stdrdr:
bits 15..10 reserved (includes some state for driver base class)
bit 9 = 1 to enable printed cursor
bit 8 = 1 to enable crlf conversion (will be filtered to generate lf only)
bit 7 = 1 to echo typed input characters
bit 6 = 1 to enable password mode (input printed as *)
bit 5 = 1 to enable line mode (input is edited before being delivered)
bit 4 = 1 to enable cook mode (input characters are interpreted in some way)
bit 3 = 1 for caps lock
bits 2..0 reserved (device state)
For stdout, ttyout, stdpun, stdlst:
bit 13 = (page mode) 1 = clear on full screen, 0 = wrap on full screen
bit 9 = enable signal bell
bit 8 = enable bell
bit 7 = page mode (1) or scroll mode (0)
bit 6 = enable pause on full screen
bit 5 = cook output chars
bit 4 = enable crlf conversion (C side \n -> \r\n)
bits 3..0 reserved (device state)
z88dk has the standard inp() and outp() functions for compliance, but there is a much faster method described in the SDCC Manual in section 3.5.2, which we use almost exclusively. The compiler recognises the special function register __sfr ports and generates in a,(*) and out (*),a (or the relevant register where the info is to be accessed) directly. This takes 18 cycles to output a byte, typically.
These special function register ports defined for the RC2014 are generated from the configuration file here.
An example of writing 0x01 to the RC2014 ROM toggle port, and then reading the ACIA status register, and using the compiler to do this:
#include <arch.h> // brings in the predefined RC2014 standard ports from the target build.
#include <arch/rc2014.h> // defines __sfr for these ports (special function registers)
uint8_t status;
io_rom_toggle = 1; // writes 0x01 to the port
status = io_acia_status; // reads the ACIA status portGenerates assembly like this:
ld a,$01 ; 7
out (__IO_ROM_TOGGLE),a ; 11
in a,(__IO_ACIA_STATUS_REGISTER)
ld (ix+*),aYou can also do this via the standard C inp() and outp() functions, but it is much slower.
It typically takes more than 145 cycles to achieve the same outcome.
If we take an example of using the outp() callee function:
#include <z80.h>
z80_outp(__IO_ROM_TOGGLE,$01);The resulting assembly looks like this:
; in the C program
ld h,$01 ;7
push hl ;11
inc sp ; 6
ld hl,__IO_ROM_TOGGLE ; 10
push hl ; 11
call _z80_outp_callee ; 17
_z80_outp_callee:
pop af ;10
pop bc ;10
dec sp ;6
pop hl ;10
push af ;11
ld l,h ;4
jp asm_z80_outp ;10
asm_z80_outp:
; enter : bc = port
; l = data
; uses : none
out (c),l ;12
ret ;10For the RC2014, the z88dk new library offers two main floating point libraries. The math48 library is the default (linked using -lm), and has been proven correct over many years. It is usually faster than the default classic library floating point library, genmath.
The computational accuracy provided by math48 with a 40-bit mantissa is unused by z88dk-zsdcc which only supports IEEE-754 single precision floating point with a 24-bit mantissa. The additional accuracy of math48 is only useful with z88dk-sccz80 which supports many 4 byte and 6 byte floating point formats.
The math32 library is a full IEEE-754 single-precision main maths package (not an adjunct). It takes advantage of z180 (ez80) and z80n (SpectrumNext) hardware multiply where available, and provides optimised software multiply for the z80 (linked with --math32). It matches the float layout used by z88dk-zsdcc. Compliance is full for normal use, with only small exceptions (non-normalised / subnormal edge cases and minor rounding). See also the z88dk Math32 wiki page.
On the 8085 hybrid (basic85, acia85, uart85), prefer packages that have been gated on that CPU โ for example mbf32, math32 (math32_8085), and am9511 โ rather than assuming every Z80 newlib float option applies. The in-tree math suite under test/suites/math exercises several of these combinations with z88dk-ticks.
The z88dk classic library provides performance benchmarking of the many floating point math libraries available for z80, including 40-bit BBC BASIC, and 32-bit and 64-bit MS BASIC found in the ROM of classic machines.
In addition, there is an adjunct IEEE-754 half-precision library math16 (link with --math16; 8085 product math16_8085 via -clib=8085 / hybrid subtypes). It is approximately 4 times faster than math32, but limited to about 3.5 significant decimal digits. math16 is not a full main library: for printf / format conversion you must also link a main package such as math32 (--math32 --math16) or math48 (-lm --math16). See z88dk Math16.
With the additional APU Module, it is possible to use the Am9511A Floating Point library, linked with --math-am9511 (alias --am9511 also works). The library masks differences between Am9511A hardware and IEEE 32-bit layout; the API matches math32-style usage.
External libraries are installed using the z88dk-lib tool. The tool installs a library for the desired target. For example, for the ff library on the rc2014 machine:
z88dk-lib +rc2014 ffLibraries are installed under lib/clibs/{sccz80,sdcc_ix,sdcc_iy}/lib/<target>/ (headers under include/_DEVELOPMENT/{proto,common}/lib/<target>/). Rebuild third-party packages against your current z88dk tree after large target/layout updates; prebuilt packages from older layouts can fail to link or run.
Some further examples of z88dk-lib usage.
- libraries list help
z88dk-lib
- list 3rd party libraries already installed for the rc2014 target
z88dk-lib +rc2014
- remove the
libname1libname2... libraries from the rc2014 target,-ffor no nagging about deleting files.
z88dk-lib +rc2014 -r -f libname1 libname2 ...
Once installed, the libraries can be linked on the compile line by adding -llib/target/library and the include file can be found with #include <lib/target/library.h>.
A collection of libraries relevant to the RC2014 can be found here. Specifically the ff, diskio_hbios, and time libraries are worth attention.
The support for the RC2014 within Z88DK is extensive. To differentiate build characteristics across different hardware and software environments Z88DK uses the concept of subtypes. Depending on your interest and hardware, different subtypes can be invoked to best support your needs.
Whilst the default configurations of each subtype are provided here, it is easy to use #pragma defines from within your program or from the command line to change any configuration as needed.
The ACIA, SIO, and UART subtypes are useful to build ROM-able code that includes configuration and driver code for the corresponding serial hardware. There is no dependency on a monitor or other code pre-existing on your RC2014. They require the RC2014 Classic, Mini, or Micro as a minimum starting point, but can be configured to support all the RAM or ROM available on a RC2014 Plus or Pro as required.
The BASIC subtype is useful if you have a RC2014 Classic, Mini, or Micro with a BASIC ROM. As this is the minimum starting point for the RC2014 world, it is expected that quite a few people will be able to use this option, together with the (now obsolete) hexload program, to get started in writing their own C or assembly programs. Recent RC2014 BASIC ROMs now incorporate an integrated hload function which uploads Intel Hex code and adjusts the BASIC Memory top correctly.
The BASIC subtype is also used with the Small Computer Monitor SCM. As the SCM uses RAM slightly differently than BASIC, programs need to provide #pragmas to define the correct origins. More on this below.
The CPM subtype is a useful adjunct to the Z88DK classic CP/M target. It can be used to get direct access to hardware, drivers, and libraries available for the RC2014 that do not exist in the classic target. For example, the IDE drivers and FatFs support available to the RC2014 new library are not found in the classic library CP/M target.
For RomWBW HBIOS, use the separate target +hbios (not a +rc2014 subtype โ see HBIOS target below). Target sources: libsrc/target/hbios. HBIOS covers most RC2014-class hardware, so +hbios is usually preferred over inventing RC2014-specific drivers when you already run RomWBW.
Current +rc2014 subtypes (from lib/config/rc2014.cfg): acia, acia85, sio, uart, uart85, basic, basic85, cpm, none. Defaults in that cfg: -clib=sdcc_iy -subtype=basic.
Additionally, subtypes for the 8085 CPU Module have been developed: basic85 for MS Basic on 8085, acia85 for the ACIA serial module, and uart85 for UART-based serial on 8085. These hybrid builds use classic-style console I/O with the 8085 tool chain; do not expect a full newlib fcntl stack on the hybrid clib.
The zcc +rc2014 -subtype=acia subtype is designed for the RC2014 Classic, Mini, or Micro platforms where RAM is located from 0x8000 and between 8kB and 32kB of ROM is located at 0x0000, and the MC68B50 (ACIA) module is installed.
The ACIA subtype is intended for programs to be burnt to ROM, and provides the full configuration and drivers required to run on bare metal. Use the map file to ensure that your code does not extend beyond the end of available ROM. A warning has been added when your CODE section passes beyond 0x8000 or 32kBytes.
The Z88DK default configuration table is located here.
The zcc +rc2014 -subtype=acia85 subtype is designed for the RC2014 Classic, Mini, or Micro platforms equipped with a 8085 CPU Module, where RAM is located from 0x8000 and between 8kB and 32kB of ROM is located at 0x0000, and the MC68B50 (ACIA) module is installed.
It is otherwise similar to the ACIA subtype (8085 hybrid library).
The zcc +rc2014 -subtype=sio subtype is designed for the RC2014 Classic, Mini, or Micro platforms where RAM is located from 0x8000 and between 8kB and 32kB of ROM is located at 0x0000, and the SIO/2 module is installed.
The SIO subtype is intended for programs to be burnt to ROM, and provides the full configuration and drivers required to run on bare metal. Use the map file to ensure that your code does not extend beyond the end of available ROM. A warning has been added when your CODE section passes beyond 0x8000 or 32kBytes.
The Z88DK default configuration table is located here.
The zcc +rc2014 -subtype=uart and -subtype=uart85 subtypes provide ROM-oriented builds for UART serial hardware on Z80 and 8085 respectively (see lib/config/rc2014.cfg). Configuration details follow the same pattern as ACIA/SIO: consult the map file and crt_config.inc.
The zcc +rc2014 -subtype=basic subtype is designed for the RC2014 Classic, Mini, or Micro platforms and the BASIC ROM is installed. The BASIC subtype is intended to be loaded to RAM.
By default programs are loaded at 0x9000 to allow space between 0x8000 where RAM originates and the data origin for BASIC and to initially load a (now unnecessary) hexload program to support uploading Intel Hex code.
The functionality of uploading Intel Hex has been integrated into several BASIC implementations so a space reservation for the BASIC hexload program is no longer necessary. Therefore it is possible to load Intel Hex at 0x8400, beyond the end of the BASIC system, and the integrated hload function will configure the BASIC Memory Top to suit. To make this change to the default configuration for the BASIC subtype the following lines can be added to your C programs.
#pragma output CRT_ORG_CODE = 0x8400To provide the maximum space for CODE, DATA, BSS, and heap space, CODE is loaded by default from 0x9000, DATA, BSS, and heap follow contiguously using RAM through to 0xFFFF. The stack is configured to start at 0xFFFF and grow downwards.
The Z88DK default configuration table is located here.
For example for sudoku.c:
zcc +rc2014 -subtype=basic -SO3 --max-allocs-per-node200000 sudoku.c -o sudoku -create-app
Or for umchess.c:
zcc +rc2014 -subtype=basic -SO3 --max-allocs-per-node200000 --math32 umchess.c -o umchess --fsigned-char -create-app
This will create an Intel HEX file with the origin at 0x9000, which can be loaded into the RAM of the RC2014 using the 'hexload' BASIC program with the standard RC2014 BASIC ROM, or via integrated hload on newer BASIC ROMs.
The memory model for this implementation has the C data and bss sections following immediately after the C code loaded at 0x9000, and the C stack located at 0xFFFF and growing down.
To ensure there is no conflict with the BASIC hexload program, the initial Memory top? question should be answered with 35071 (0x88FF) or lower when that loader is still in use.
Further information on preparing C programs can be found on the hexload page.
If using a NASCOM BASIC / HexLoadr-style ROM (or the RC2014 hexload materials), the Z80 RST vectors are directed to a jump table starting at 0x8000. This allows the user to redirect the RST instructions to a routine of choice. See also Using Basic.
For example if the user wants to use RST20 for their own program, then the following C can be used.
#include <cpu.h>
#define Z80_VECTOR_BASE 0x8000
// whole RST table for reference
#define RST_00_ADDR Z80_VECTOR_BASE+0x01
#define RST_08_ADDR Z80_VECTOR_BASE+0x05
#define RST_10_ADDR Z80_VECTOR_BASE+0x09
#define RST_18_ADDR Z80_VECTOR_BASE+0x0D
#define RST_20_ADDR Z80_VECTOR_BASE+0x11
#define RST_28_ADDR Z80_VECTOR_BASE+0x15
#define RST_30_ADDR Z80_VECTOR_BASE+0x19
#define RST_38_ADDR Z80_VECTOR_BASE+0x1D
#define INT_INT0_ADDR Z80_VECTOR_BASE+0x1D
#define INT_NMI_ADDR Z80_VECTOR_BASE+0x21
void my_rst_20_function(void);
int main(void)
{
uint16_t volatile * const interrupt_vector = (uint16_t *) RST_20_ADDR;
* interrupt_vector = (uint16_t) my_rst_20_function;
return 0;
}
void my_rst_20_function(void)
{
return;
}To use SCM with the BASIC subtype, the code origin and the stack origin need to be relocated. SCM stores its configuration data from 0xFC00 to 0xFFFF, so our stack origin must be moved down to 0xFC00 to avoid a clash. However SCM does not use RAM at 0x8000, so our code origin can also be moved down to 0x8000 without any issue.
To make these changes to the default configuration for the BASIC subtype the following lines can be added to your C programs.
#pragma output CRT_ORG_CODE = 0x8000
#pragma output REGISTER_SP = 0xFC00Pragmas can also be done from the command line, but it is usually more convenient to do it once in the program file.
The command line then includes...
zcc +rc2014 -subtype=basic -clib=sdcc_iy ... mycode.c -o mycode -create-app
The resulting Intel Hex (mycode.ihx) can be uploaded to the SCM monitor using instructions found in the SCM User Guide, and the program initiated using the g 8000 command.
The zcc +rc2014 -subtype=basic85 subtype is designed for the RC2014 Classic, Mini, or Micro platforms equipped with a 8085 CPU Module, and the BASIC ROM is installed. The subtype is intended to be loaded to RAM (default code origin 0x9000, same class of use as basic).
It selects the 8085 hybrid library (-clib=rc2014-8085): classic console (fgetc_cons / fputc_cons style) with the RC2014 8085 CRT, not a full newlib disk fcntl stack. Console I/O is suitable for printf / scanf under tools such as z88dk-ticks (use -m8085 and load at 0x9000 for BASIC-class images). For IEEE-style float work on 8085, prefer libraries that are actually built and tested for that CPU (see Floating Point above).
Example:
zcc +rc2014 -subtype=basic85 -v -m prog.c -o prog -create-app
The zcc +rc2014 -subtype=cpm subtype is designed for any RC2014 running CP/M.
The CP/M subtype is intended to be run from RAM, and resulting binaries mycode.bin or mycode.com can be transferred to the RC2014 using XMODEM (for example) and stored to disk as MYCODE.COM and then run from the CP/M command line. Alternatively mycode.ihx files can be transferred using PIP, and then converted to .COM on the RC2014 using LOAD, or MLOAD.
As is traditional, programs are loaded at 0x0100 and rely on BDOS calls for all access to hardware. This subtype does not expose a full POSIX-style newlib disk API for CP/M FCB files. To use CP/M file I/O it is necessary to either: use the classic +cpm target (BDOS FCB open/read/write/โฆ), or use the ChaN FatFs library and the RC2014 IDE module for direct access to FAT32 formatted CF or IDE drives.
The Z88DK default configuration table is located here.
To use this subtype for RC2014, this is the relevant command line for the program Test.c.
zcc +rc2014 -subtype=cpm -clib=sdcc_iy -SO3 -v -m --list --max-allocs-per-node100000 --math32 -llib/rc2014/ff Test.c -o Test -create-app
The ChaN FatFs library ff must be installed for the RC2014 target (z88dk-lib +rc2014 ff), and then used as shown.
As noted above, to access the CP/M file system with classic FCB I/O use the z88dk standard CP/M target: zcc +cpm -subtype=default (optionally -clib=8085 on 8085 CP/M systems). That path is covered by in-tree z88dk-ticks tests for serial and disk I/O.
There is no -subtype=hbios on +rc2014. Use the dedicated target:
zcc +hbios -clib=sdcc_iy โฆ
(or -clib=new for sccz80). Config: lib/config/hbios.cfg. CRT default code origin is 0x0100 (libsrc/target/hbios/crt_config.inc). Subtypes: default, none.
Intended load path under RomWBW: enter dbgmon (M), load Intel Hex with L, run with R100 (origin 0x0100). Hardware access goes through the HBIOS API โ see RomWBW documentation (System Guide, Hardware).
BSS / bank notes for FatFs buffers often require BSS above 0x8000 โ check the map and use #pragma output CRT_ORG_BSS = โฆ if sections collide (see example program below).
Install third-party packages for this target, not +rc2014:
z88dk-lib +hbios time
z88dk-lib +hbios diskio_hbios
z88dk-lib +hbios ff
Example:
zcc +hbios -clib=sdcc_iy -SO3 -v -m --list --max-allocs-per-node100000 \
-llib/hbios/time -llib/hbios/diskio_hbios -llib/hbios/ff Test.c -o Test -create-app
See also Platform โ HBIOS.
For automated checks without hardware, z88dk-ticks can run selected RC2014 and CP/M images:
| Image class | Typical load | Notes |
|---|---|---|
+rc2014 -subtype=basic / basic85
|
z88dk-ticks -pc 0x9000 โฆ_CODE.bin (8085: add -m8085) |
Filename should contain rc2014 so ticks installs BASIC RST 08/10/18 console hooks |
classic +cpm
|
z88dk-ticks prog.com (8085: -m8085) |
.com enables BDOS/BIOS traps at 0x100; CP/M FCB file I/O is emulated |
In-tree suite: test/suites/target_io (serial printf/scanf and file create/write/lseek/read/close for RC2014 basic and classic CP/M, including sccz80 and 80cc). Math recipes for RC2014 live under test/suites/math.
Many example programs are located under examples/ (classic console samples in examples/console/). Additional newlib-oriented notes appear under libsrc/_DEVELOPMENT/EXAMPLES/ (for example z80/stdio_target/). External examples: z88dk-ext. Smoke-tested recipes: z88dk wiki Examples.
This is one example which demonstrates a file copy. Use +rc2014 -subtype=cpm with the RC2014 FatFs package and IDE module, or +hbios with HBIOS diskio/FatFs packages for RomWBW disks.
zcc +rc2014 -subtype=cpm -clib=sdcc_iy -SO3 -v -m --list --max-allocs-per-node100000 -llib/rc2014/ff fileCopyTest.c -o fileCopyTest -create-app
zcc +hbios -clib=sdcc_iy -SO3 -v -m --list --max-allocs-per-node100000 -llib/hbios/time -llib/hbios/diskio_hbios -llib/hbios/ff fileCopyTest.c -o fileCopyTest -create-app
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>
#if __RC2014
#include <lib/rc2014/time.h> /* Declaration of system time */
#warning No timer calculation possible.
#else
#error Do you have time?
#endif
//#if __RC2014 /* CPM subtype */
//#include <lib/rc2014/ff.h> /* Declarations of FatFs API */
//#include <arch/rc2014/diskio.h> /* Declarations of diskio & IDE functions */
#if __RC2014 /* HBIOS subtype */
#include <lib/hbios/ff.h> /* Declarations of FatFs API */
#include <lib/hbios/diskio_hbios.h> /* Declarations of diskio functions */
#include <arch/hbios.h> /* Declarations of HBIOS functions */
#else
#warning - no FatFs library available
#endif
// #pragma output CRT_ORG_BSS = 0x9000 // for hbios move bss origin to address 0x9000 (check map to confirm there is no overlap between data and bss sections)
#pragma printf = "%s %c %u %li %lu" // enables %s, %c, %u, %li, %lu only
static FIL FileIn, FileOut; /* File object needed for each open file */
#define BUFFER_SIZE 4096 /* size of working buffer (on heap) */
static BYTE * buffer; /* working buffer */
/* must be in bss (which is above 0x8000) for romwbw hbios buffer */
static FATFS * FatFs; /* FatFs work area needed for each volume */
/* Pointer to the filesystem object (on heap) */
int main (void)
{
UINT bw;
UINT br;
DWORD bwt = 0;
FRESULT res;
struct timespec startTime, endTime, resTime;
buffer = (BYTE *)malloc(sizeof(BYTE)*BUFFER_SIZE); /* Get working buffer space */
FatFs = (FATFS *)malloc(sizeof(FATFS)); /* Get work area for the volume */
startTime.tv_sec = 1577836800 - UNIX_OFFSET;
clock_settime(CLOCK_REALTIME, &startTime); /* Set the time of day, y2k epoch */
if ((res = f_mount(FatFs, "0:", 1)) == FR_OK) { /* Give a work area to the default drive */
printf("\r\n\nFatFs->fs_type %u\nFatFs->fsize %lu\n", FatFs->fs_type, FatFs->fsize);
printf("\r\nOpening 0:random1.txt");
if ((res = f_open(&FileIn, "0:random1.txt", FA_READ)) == FR_OK) {
printf(" - Opened");
if ((res = f_lseek(&FileIn, 0)) == FR_OK) {
printf("\r\nCreating 0:random2.txt");
if ((res = f_open(&FileOut, "0:random2.txt", FA_CREATE_ALWAYS | FA_WRITE)) == FR_OK) {
printf(" - Created\r\n\nCopying...");
clock_gettime(CLOCK_REALTIME,&startTime);
for (;;) {
res = f_read(&FileIn, buffer, sizeof(BYTE)*BUFFER_SIZE, &br); // put_rc(res);
if (res != FR_OK || br == 0) break; // eof or error
res = f_write(&FileOut, buffer, br, &bw); // put_rc(res);
bwt += bw;
if (res != FR_OK || bw != br) break; // error or disk full
}
clock_gettime(CLOCK_REALTIME,&endTime);
f_close(&FileOut);
if ((res = f_unlink("0:random2.txt")) != FR_OK) {
printf("\r\nCouldn't delete 0:random2.txt - f_unlink error #%u\r\n", res);
}
} else {
printf("\r\nCouldn't open 0:random2.txt - f_open error #%u\r\n", res);
}
} else {
printf("\r\nCouldn't seek 0:random1.txt - f_lseek error #%u\r\n", res);
}
f_close(&FileIn);
} else {
printf("\r\nCouldn't open 0:random1.txt - f_open error #%u\r\n", res);
}
timersub(&endTime, &startTime, &resTime);
printf("\r\nCopied %lu bytes", bwt );
printf(", the time taken was %li.%.4lu seconds\n", resTime.tv_sec, resTime.tv_nsec/100000 );
f_mount(0, "0:", 0); /* Free work area */
} else {
printf("\r\nCouldn't mount drive - f_mount error #%u\r\n", res);
}
// Perform any shutdown/cleanup.
free(FatFs);
free(buffer);
return 0;
}Checked against z88dk tree lib/config/rc2014.cfg, lib/config/hbios.cfg, and live tools (2026-07). Prefer zcc +rc2014 -h / zcc +hbios -h if this page and the tree disagree.