Tools for building and running Z80 code under ProDOS on an Apple II with a Z80 Softcard (or clone)
Go to file
Bobbi Webber-Manners 1ddef3001a F_SFIRST/F_SNEXT can now return all file extents 2019-11-03 14:38:02 -05:00
z80as Initial commit of z80as (and hex2bin) source. 2019-10-12 19:16:41 -04:00
z80asm Initial commit of z80asm (without Apple II mods.) 2019-10-12 19:17:55 -04:00
5K_BASIC_(Software#2).pdf Initial commit. 2019-10-12 20:18:59 -04:00
BASIC5.BIN#000000 Initial commit. 2019-10-12 20:18:59 -04:00
BASIC5.S#000000 Initial commit. 2019-10-12 20:18:59 -04:00
BASIC5.S.ORIG#000000 Initial commit. 2019-10-12 20:18:59 -04:00
LICENSE Initial commit 2019-10-12 17:28:50 -04:00 Implemented REN command in CCP 2019-11-02 00:04:54 -04:00
RUNBASIC5#040000 Initial commit. 2019-10-12 20:18:59 -04:00
SOFTCARD65#ff2000 6502 code to switch to 80 column mode on startup 2019-10-26 21:07:56 -04:00
SOFTCARD65.S#040000 6502 code to switch to 80 column mode on startup 2019-10-26 21:07:56 -04:00
SOFTCARD80.ASM#040000 F_SFIRST/F_SNEXT can now return all file extents 2019-11-03 14:38:02 -05:00
SOFTCARD80.BIN#041000 F_SFIRST/F_SNEXT can now return all file extents 2019-11-03 14:38:02 -05:00
zapple2.po F_SFIRST/F_SNEXT can now return all file extents 2019-11-03 14:38:02 -05:00


Tools for building and running Z80 code under ProDOS on an Apple II with a Z80 Softcard (or clone)

  • Z80 cross assemblers running under ProDOS on the Apple II
  • CP/M BDOS emulation to allow CP/M programs to run under ProDOS
  • Simple CP/M Command Console Processor (CCP)
  • Sample program: Processor Technology's SOL-20 BASIC/5

Aztec C v3.2 can be found on this website.

Z80 Cross Assemblers & Tools

I didn't fancy writing a Z80 assembler from scratch, and I wasn't able to find any existing Z80 cross-assemblers for 6502. In order to get something up-and-running quickly, I searched for small Z80 assemblers written in C.


The first suitable candidate I found was Z80Asm, which was developed by Udo Munk back in the 1988 to 1990 timeframe. (Hr. Munk is still active and has repositories here on GitHub.) I am using an older version of Z80Asm (v1.1) which is written in K&R (pre-ANSI) C, so it was easy to get it to compile on Aztec C for the Apple II.

The program is rather large for Aztec C's compiler, and the resulting binary was also too large to run in the available memory. I made a few minor modifications:

  • I split the largest source file z80arfun.c into eight pieces because Aztec C can't handle files larger than around 500 lines.
  • Slimmed down a few buffers to save some RAM.
  • Reduced the number of supported files from 512 to 10.
  • I had to compile the code to Aztec C VM code using cci rather than to native 6502 code using cc. The natively compiled version creates an executable which is too large to run.

The resulting assembler runs but it is quite slow due to the use of the Aztec VM and can't assemble large programs with lots of symbols without running out of memory. However I have been using it successfully to develop the BDOS emulation.

Z80Asm also builds and runs on Linux which allows larger files to be assembled and is much faster than running on 6502 at 1Mhz.


Udo Munk pointed me towards an alternative assembler, Z80as, which was originally developed by the Mark Williams Company and which ran on PDP-11 under Coherent. This assembler has the advantage of small size, and is also written in K&R C.

Z80as compiled 'out-of-the-box' under Aztec C on the Apple II, without any modification.

This assembler generates Intel HEX files rather than BIN files, so I wrote a simple converter called HEX2BIN.

Z80as also builds and runs on Linux which allows larger files to be assembled and is much faster than running on 6502 at 1Mhz.


This is a quick-and-dirty conversion program for converting the HEX files generated by Z80as into BIN files that can be loaded on the Apple II using BLOAD.

HEX files can have 'holes' in them, and HEX2BIN takes care of zero-filling the holes.

CP/M BDOS Emulation

I have started work on a CP/M BDOS emulation layer. The plan is to add support for all the CP/M 2.2 system calls, which should allow a CP/M program to run on the Softcard Z80 CPU and have all the system calls routed to the 6502 and serviced using the Apple II ROM monitor routines and the ProDOS MLI.

I have most of the calls now and most of them have been tested to some degree and aren't totally broken.

The directory calls do not return any size information in the FCB yet. I will fix this in due course. There are doubtless loads of other issues and bugs. See SOFTCARD80.ASM for TODO comments.

  • BDOS call 00h: C_TERMCPM - System reset
  • BDOS call 01h: C_READ - Console input
  • BDOS call 02h: C_WRITE - Console output
  • BDOS call 06h: C_RAWIO - Direct console I/O
  • BDOS call 07h: GET_IOB - Get IOBYTE
  • BDOS call 08h: SET_IOB - Get IOBYTE
  • BDOS call 09h: C_WRITESTR - Console write string
  • BDOS call 0Ah: C_READSTR - Read console string
  • BDOS call 0Bh: C_STAT - Console status
  • BDOS call 0Ch: S_BDOSVER - Return version number
  • BDOS call 0Dh: DRV_ALLRESET - Reset disks
  • BDOS call 0Eh: DRV_SET - Select disk
  • BDOS call 0FH: F_OPEN - Open file
  • BDOS call 10H: F_CLOSE - Close file
  • BDOS call 11H: F_SFIRST - Search for first match in directory
  • BDOS call 12H: F_SNEXT - Search for next match in directory
  • BDOS call 13H: F_DELETE - Delete file
  • BDOS call 14h: F_READ - Read file sequentially
  • BDOS call 15h: F_WRITE - Write file sequentially
  • BDOS call 16H: F_MAKE - Create (and open) file
  • BDOS call 17H: F_RENAME - Rename file
  • BDOS call 18H: DRV_LOGVEC- Return bitmap of logged-in drives
  • BDOS call 19H: DRV_GET - Return current drive
  • BDOS call 1AH: F_DMAOFF - Set DMA address
  • BDOS call 1BH: DRV_ALLOCVEC - Return address of allocation map
  • BDOS call 1CH: DRV_SETRO - Software write-protect current drive
  • BDOS call 1DH: DRV_ROVEC - Return bitmap of read-only drives
  • BDOS call 1FH: DRV_DPB - Get Drive Parameter Block address
  • BDOS call 20H: F_USERNUM - Get/set user number
  • BDOS call 21H: F_READRAND - Random access read record
  • BDOS call 22H: F_WRITERAND - Random access write record
  • BDOS call 23H: F_SIZE - Compute file size
  • BDOS call 24H: F_RANDREC - Update random access pointer
  • BDOS call 25H: DRV_RESET - Selectively reset disk drives
  • BDOS call 28H: F_WRITEZF - Random access write record zero-filled

There are two parts to the BDOS emulation:

  • softcard80.asm - This is the Z80 code to handle BDOS calls and send them to the 6502 to be processed. Written in Z80 assembler. I am currently assembling this using Z80asm under Linux (it got too large to assemble with Z80asm under ProDOS on the Apple II.
  • softcard65.asm - This is the 6502 back end code. Written in Merlin8 v2.58. Loads at $0900 in 6502 space. This is less than 100 bytes of code!

Sample Programs


This is one of the BASIC interpreters from the Processor Technologies SOL-20 system. The source code was provided as an example with z80as.

I assembled this code under Z80as on Linux, since it defines too many symbols to assemble natively on the Apple II in the available memory. I plan to take a look at the Aztec C build configuration to see if it is possible to find more memory for dynamic allocation (ie: malloc()).

It is a 5K BASIC, so it is rather primitive. However it does have a floating point package and trig functions.

BASIC/5 only uses three system calls: C_READ, C_WRITE and C_STATUS.

There is currently no support for loading or saving BASIC programs, but I may add this later.

The manual for BASIC/5 is included in this GitHub repo, in PDF format.

Interestingly, there was a bug in the original BASIC/5 source that caused it to initialize one byte of memory too many, blowing away the first byte of the BDOS implementation at the top of memory. This has been patched by adding a DEC HL instuction at line 47 (shout-out to Qkumba for finding what the issue was!)

BASIC/5 can now be started from the CCP prompt: B:BASIC5

Other CP/M 2.2 Programs that work (to some degree)

  • DDT debugger
  • ZSID v1.4 debugger
  • DUMP hex dump utility
  • PIP (can copy files using PIP DEST.COM=SOURCE.COM)
  • STAT (at least STAT DSK and STAT filename seem to work)
  • NSWEEP file manager

Probably lots of other small, simple programs should also work.

Programs known not to work yet

Most of these are two big for my current TPA (around 32K). I need to rearrange things to make a bigger TPA, and this will probably involve using auxiliary RAM.

  • MBASIC - I think it tries to patch the BIOS.
  • Wordstar - My eventual goal is to get this to work.
  • Turbo Pascal - My eventual goal is to get this to work.

How to Build the Code

You don't really need to build the code unless you want to make changes. Pre-compiled versions of everything are included in this repository.

The 800K ProDOS disk image zapple2.po has all the files you should need.

Building Z80asm using Aztec C

  • Two scripts are provided to do the build: compile and link
  • Run the script compile. This takes a long time!
  • Run the script link. This just takes a couple of minutes.
  • z80asm executable is created.

Note that z80asm can only be run from the Aztec C shell. It should be possible to build it as a normal ProDOS application, but I have not done this yet.

Building Z80as using Aztec C

I didn't provide a script for this. Just build all the C files in Aztec C as follows:

cc as0.c
cc as1.c
cc as2.c
cc as3.c
cc as4.c
cc as5.c
cc as6.c
ln -o z80as as0.o as1.o as2.o as3.0 as4.0 as5.0 as6.0 -lc

Building HEX2BIN using Aztec C

  • You can just run the script makeh2b in Aztec C
  • This just does the following:
cc hex2bin.c
ln hex2bin.o -lc

Building SOFTCARD65 using Merlin8 2.58

  • Start Merlin8 (v2.58)
  • Hit 'D' for disk commands, enter PREFIX /ZAPPLE2
  • Hit 'L' for load, enter SOFTCARD65 and hit return.
  • Hit 'E' for edit.
  • Type ASM to assemble.
  • Type 'Q' to go to the main menu.
  • Hit 'O' to save the object file SOFTCARD65 to disk, and hit return.
  • Hit 'Q' to quit to ProDOS.

Building SOFTCARD80.BIN using Z80asm

  • In the Aztec C shell, enter the following commands:
  • cd /zapple2
  • z80asm softcard80.asm

Update: The code has grown too large to build natively on the Apple II. I have been using z80asm under Linux instead.

How to Run The Code

The code assumes a Z80 Softcard (or clone) in slot 4. This can be changed by modifying the SOFTCARD address in SOFTCARD65.S and SOFTCARD80.ASM if your card is in a different slot.

To run the code, use zapple2.po, which is a ready made 800K disk image. You need to boot ProDOS from some other device, because this image is not bootable (I should fix that!)

Run SOFTCARD65 to start everything. This will relocate itself to high memory and then load the Z80 code SOFTCARD80. The system will then start the CCP and show the familiar A> prompt.

There are three CP/M 'drives' (actually ProDOS subdirectories) on the diskette image: A, B and C.

The following commands are implemented:

  • DIR
  • TYPE
  • ERA
  • REN
  • Changing drives using A:, B:, etc.
  • Launching a .COM file (just type the name and any arguments)

Wildcards using * are not yet supported.

REN, USER and SAVE built-in commands are not supported yet either.

Some things to try

  • DIR - show files on current drive
  • DIR A: - show files on another drive
  • DIR ABC?????.TXT - show matching files using ? wildcards
  • TYPE TEST.TXT - view a text file
  • A:PIP B:MY.TXT=A:TEST.TXT copy TEST.TXT from A: to B:, renaming it as MY.TXT
  • ERA MY.TXT erase file MY.TXT
  • STAT DRV - show info on the virtual drive
  • DDT MYPROG.COM - debug MYPROG.COM using DDT (8800 debugger)
  • ZSID MYPROG.COM - debug MYPROG.COM using ZSID (Z80 debugger)
  • DUMP MYPROG.COM - hex dump of file
  • NSWEEP - simple interactive file manager
  • BASIC5 - Processor Technology SOL-20 BASIC/5