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:

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/rc2014 and libsrc/target/hbios (formerly under libsrc/_DEVELOPMENT/target/โ€ฆ / libsrc/newlib/target/โ€ฆ). Newlib library products install under lib/clibs/{sccz80,sdcc_ix,sdcc_iy}/ (third-party packages under lib/clibs/โ€ฆ/lib/<target>/). Note: sdcc_iy compile mode often still links the sdcc_ix library product path on many targets โ€” see lib/config/rc2014.cfg. Classic console examples live under examples/console/. Float packages live under libsrc/math/float/ (math16, math32, math48, am9511, โ€ฆ). General install/recipes: z88dk wiki Examples, Load and run.

Installation

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.

Building sdcc for 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

Using the C compilers

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.

Compiler

There are three C compilers available for RC2014 work.

  1. 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.

  2. 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_ix or -clib=sdcc_iy. For +rc2014, sdcc_iy is the default: it is the same newlib/zsdcc path as sdcc_ix, but with --reserve-regs-iy so the library owns iy and the compiler keeps ix for its frame pointer (see Libraries).

  3. 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 +rc2014 and classic +cpm). It is exercised in the tree's regression suites (including target I/O under z88dk-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

Basic Usage

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
  • zcc is the frontend driver, and is always used. Calls to the individual compilers, assembler, linker, and packager are not typical.
  • +rc2014 is the target. Unless you prefer the classic CP/M +cpm or RomWBW HBIOS +hbios targets, you should use this +rc2014 target for RC2014-specific hardware and drivers.
  • -subtype=basic is the subtype, as described below. If it is missing, a default subtype will be selected (basic for current rc2014.cfg).
  • -clib=sdcc_iy is the compiler and library choice (sdcc_iy is the default and can be omitted). Use -clib=new for z88dk-sccz80, or add -compiler=80cc to select 80cc.
  • -SO3 is the optimisation level used with zsdcc. Unless you are debugging the compiler, use a high optimisation setting for production builds.
  • -v is verbose. -vn is silent compilation.
  • -m produces a map file. This is very useful to see where each label and section is located in memory.
  • -w produces a warning if CODE, DATA, or BSS sections overlap (default).
  • --list produces an assembly listing of the C files and the crt.
  • --c-code-in-asm includes 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-asm produces verbose assembly listings when --list is 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-node100000 defines how aggressively the z88dk-zsdcc compiler 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.
  • --math32 uses the IEEE math32 library. The traditional math48 library is linked by -lm. The APU Module library is --am9511 (or equivalent project flags).
  • -llib/target/library links a specific third-party library installed with z88dk-lib (see below).
  • @mytest.lst is 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, use myfile.c on the command line instead.
  • -o test specifies the root of the output files. Section images such as test_CODE.bin / test_DATA.bin and an Intel HEX file are typical after -create-app; consult the map file if a zero-length test.bin appears (the useful image is often *_CODE.bin).
  • -create-app calls z88dk-appmake to produce the final binary and Intel HEX files required to upload to the RC2014.

Libraries

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.

Choosing classic vs new library

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.

zsdcc library models: sdcc_ix vs sdcc_iy

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=sdcc and the newlib target product (-lrc2014 from lib/clibs/sdcc_ix/โ€ฆ).
  • sdcc_iy additionally passes --reserve-regs-iy to zsdcc. That tells the compiler that the iy register pair is reserved โ€” the compiler must not allocate iy for its own code generation.
  • With iy reserved for the library, the hand-written newlib can use iy freely as its preferred index/frame-style register in asm library routines.
  • ix is then left entirely to zsdcc for its usual purpose as the C stack frame pointer (locals, parameters, and compiler-managed stack addressing).

Why sdcc_iy performs better

-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.

Standard I/O

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)

Hardware I/O

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 port

Generates assembly like this:

ld a,$01  ; 7
out (__IO_ROM_TOGGLE),a  ; 11
in a,(__IO_ACIA_STATUS_REGISTER)
ld (ix+*),a

You 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  ;10

Floating Point

For 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.

3rd Party Libraries

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 ff

Libraries 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 libname1 libname2 ... libraries from the rc2014 target, -f for no nagging about deleting files.
z88dk-lib +rc2014 -r -f libname1 libname2 ...

Library Usage

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.

RC2014 Target

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.

ACIA Subtype

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.

ACIA85 Subtype

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).

SIO Subtype

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.

UART / UART85 Subtypes

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.

BASIC Subtype

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 = 0x8400

To 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;
}

SCM

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 = 0xFC00

Pragmas 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.

BASIC85 Subtype

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

CPM Subtype

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.

HBIOS target (RomWBW)

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.

Host testing with z88dk-ticks

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.

Application Examples

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;
}

Page accuracy

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.

โš ๏ธ **GitHub.com Fallback** โš ๏ธ