C-ONE BOOT - technical details



Please remember that all this is subject to change. More details will be added later on.

Debug Output

The boot ROM prints debug output to RS-232, if you have a Silver Surfer plugged into clock port 1. Set your terminal program to 38400 baud, 8N1, and hardware flow control.

CPC Boot Environment

The Drive CPU

The CPC core in the 1K30 is referred to as the drive CPU. When the main system is up and running, the CPC core works as a coprocessor. Currently the RISC CPU core is running at 9 MHz, and the 6502 emulation runs at roughly 1.5 MHz. At the time of writing, the 6502 emulation differs from a genuine 6502 in the following ways:

RISC CPU Memory Map

$00000..$3ffff Miscellaneous use:
  • temporary memory for XModem transfers
  • disk images for CPC mode
  • temporary space during flash procedure
$40000..$7ffff DK'tronics memory expansion for Amstrad computer mode (256KBytes)
$80000..$8ffff CPU emulation code (Z80 and 6502)
$90000..$93fff Amstrad OS (lowrom)
$94000..$9bfff memory for shadowed Z80 (Amstrad floppy emulation)
$9c000..$9ffff rom routines for floppy emulation
$a0000..$abfff 6502 memory. This memory is the 'standard' memory for the 6502 processor. There are special commands that can access any other memory address for easy signalling between the CPUs and to give BigBoot the ability to load ROMs.
$ac000..$affff 6502 boot code.
$b0000..$bbfff 48K memory for Z80 emulation. This memory is CPC memory (by nature). There are special Z80 commands that give access to any other memory address for easy signalling between CPUs and to give access to ROM clones and the DK'tronics memory expansion.
$bc000..$bffff 16K memory shared between Z80 and the Amstrad video controller.
$c0000..$fffff CPC rom expansion box (available as highrom in the upper 16K area). There are 16 slots for ROM modules. The real CPC expansion used 27128 eprom sockets that could be filled by the user. The slots are arranged linearly in this area, so the 16K area starting at $c0000 is slot 0.

Flash ROM contents

$00000..$0ffff Reserved for future use (probably romfs with default 1k100 config and bootrom backup).
$40000..$4ffff Z80 and 6502 emulation code, copied to $80000 at power on.
$50000..$5ffff Amstrad ROMs, copied to $90000 at power on.
$60000..$6ffff 1k30 core.
$70000..$7ffff 6502 boot code.

I/O Port Addresses

These are accessed with IN/OUT (Z80) and ZIN/ZOUT (6502).
$7f Gate array and memory management.
$bc..$bd 6845 CRTC. Available registers are: R1, R4, R5, R6, R7, R9, R12, and R13.
$df ROM select.
$ef Printer port (currently not working).
$f4..f7 PPI.


These are accessed with SCA and IST/ILD (6502).
$0000..$efff Reserved for future use.
$f000..$f0ff Cartridge port ROML.
$f100..$f1ff Cartridge port I/O2.
$f200..$f2ff Clock port 1 (Silver Surfer).
$f300..$f3ff SID socket 1 (left channel).
$f400..$f4ff Cartridge port ROMH.
$f500..$f5ff Cartridge port I/O1.
$f600..$f6ff Clock port 2.
$f700..$f7ff SID socket 2 (right channel).
$f800..$f8ff Enable status register buffer.
$f900..$f9ff Printer port data output register latch.
$fa00..$faff Printer port DDR register latch.
$fb00..$fbff Serial port registers.
$fc00..$fcff PCI GRNT RESET.
$fd00..$fdff PCI0 GRNT SET.
$fe00..$feff PCI1 GRNT SET.
$ff00..$ffff Release chip selects. Read from $ffff after accessing I/O.

6502 Memory Map

There are two free memory ranges in the address space, $0080-$00bf, and $2000-$3eff. If you call any provided routines from your code, these are the only areas that are guaranteed not to be overwritten. The cluster buffer ($4000-$bfff) is free to be used, but some routines overwrite it (notably the vol_* routines).

system zp		0000-007f	; reserved for system use
application zp		0080-00bf	; free for application use
(reserved)    	    	00c0-00df
sectorptr		00e0-00e1	; where dev_read_sector stores data
(reserved)		00e2-00ef
dirptr			00f0-00f1	; pointer to current dir entry
clusterptr		00f2-00f3	; where vol_read_clust stores data
(reserved)		00f4-00ff

system stack		0100-01ff	; CPU stack

system variable storage	0200-1eff	; reserved for system use
romaddr			1f00-1f05	; ascii address set by vol_isrom
stat_length		1f06-1f09	; length, set by vol_stat
stat_cluster		1f0a-1f0d	; first cluster, set by vol_stat
vol_fstype		1f0e		; file system type, one of:
					;   $12 = FAT12
					;   $16 = FAT16
					;   $32 = FAT32
					;   $96 = ISO9660
vol_secperclus		1f0f		; # of 512 byte sectors in one cluster
cluster			1f10		; set before calling vol_read_clust
					; or vol_next_clust
stat_type		1f14		; dir entry type, set by vol_stat
vol_rleflag		1f15		; rle compression flag for vol_isfpgabin
(reserved)		1f16-1f3f
lba			1f40		; set before calling dev_read_sector
devtype			1f44		; current device type
(reserved)		1f45-1fff
flashbuf		2000-3eff	; reserved for flash code or
					; application code


Reserved for future use.


clusterbuf		4000-bfff	; used by vol_*


system code		c000-feff	; reserved for system code
jump table		ff00-ffdf	; system jump table
ver_major		fff0		; major version number
ver_minor		fff1		; minor version number
ver_rev			fff2		; revision number
ver_str			fff3-fff9	; 0 terminated version string
irq vector		fffa-fffb	; CPU IRQ vector (not used)
reset vector		fffc-fffd	; CPU reset vector
nmi vector		fffe-ffff	; CPU NMI vector


vol_set_fs		ff00		; activate filesystem
vol_read_volid		ff03		; read volume info
vol_cdboot		ff06		; change to boot directory
vol_cdroot		ff09		; set cluster to root dir
vol_dir_first		ff0c		; set dirptr to first dir entry
vol_dir_next		ff0f		; advance dirptr to the next entry
vol_next_clust		ff12		; find the next cluster in the chain
vol_read_clust		ff15		; read cluster
vol_endofdir		ff18		; check for end of dir
vol_isfpgabin		ff1b		; check if entry is ?FPGA.BIN
vol_isrom		ff1e		; check if entry is ?R??????.BIN
vol_isflashbin		ff21		; check if entry is FLASH.BIN
vol_isdrivebin		ff24		; check if entry is ?DRIVE.BIN
vol_stat		ff27		; copy cluster and length
vol_firstnamechar	ff2a		; return first char in filename
vol_write_clust		ff2d		; write cluster

dev_init		ff40		; initialize device
dev_read_sector		ff43		; read sector
dev_set			ff46		; activate device
dev_find_volume		ff49		; inspect filesystem
dev_write_sector	ff4c		; write sector

ctl_select		ff50		; activate controller
ctl_select_dev		ff53		; select device

debug_init		ff60		; initialize rs-232 debugging
debug_done		ff63		; disable rs-232 debugging
debug_puts		ff66		; print string
debug_get		ff69		; get character
debug_put		ff6c		; print character
debug_puthex		ff6f		; print hex number
debug_putdigit		ff72		; print digit
debug_crlf		ff75		; print cr+lf

gfx_cls			ff80		; clear the screen
gfx_drawlogo		ff83		; draw C-ONE logo
gfx_gotoxy		ff86		; set cursor position
gfx_puts		ff89		; print string
gfx_putchar		ff8c		; print character
gfx_quickcls		ff8f		; clear text area
gfx_drawicon		ff92		; draw 32x32 icon
gfx_puthex		ff95		; print hex byte

dsk_load		ffa0		; load DSK image
dsk_save		ffa3		; save DSK image

Custom Instructions

Common to all the instructions are that they don't set the processor flags. E.g. you can't use
    lda #ide_status  ; status register
    csa              ; set IDE address
    ild              ; read register
    bmi waitbsy      ; does NOT work
You need to add a cmp #$00, and #$ff, or some other regular 6502 instruction before you check the registers.

CTL, system control

CTL uses the value in the accumulator to control various I/O lines:
  bit 0    CPU DMA control line, active low
  bit 1    strobe 0 to erase FPGA, keep set to 1
  bit 2    CPU RESET control line, active low
  bit 3-7  unused, set to 0

CSA, select address

CSA uses the value in the accumulator to address the IDE vus:
  bit 0-2  IDE interface A0-A2
  bit 3    select IDE channel, 0 = primary, 1 = secondary
  bit 4-7  unused, set to 0

SCA, set control address

SCA is used to address the C-ONE I/O bus. The X register is latched as the MSB and the A register is latched as the LSB.

ILD, load from I/O bus

Loads A and X from the currently selected I/O register. The LSB ends up in A, and if register 0 is read the MSB ends up in X, otherwise X is trashed.

IST, store to I/O bus

Stores A and X to the currently selected I/O register, see ILD.

LAM, load accumulator from memory

Loads A from the 24-bit RISC memory location pointed to by the 16-bit argument. This works like lda (zp), except the location is 24-bit and doesn't have to be stored in zeropage.

SAM, store accumulator to memory

Store A to RISC memory, see LAM for a description of the addressing mode.

SAF, store accumulator to FPGA

SAF sends the current value in A to the config port of the 1K100.

LKA, load keyboard

LKA loads the next byte from the PS/2 keyboard FIFO into A. If there is no valid data the carry is set. The overflow flag is set if it's an extended ($e0) key code. The negative flag is clear if it's a make code, and set if it's a break code.


ZIN reads a byte from the Z80 I/O address space.


ZOUT writes a byte to the Z80 I/O address space.