Retargetting the Compiler For Other Z80 Based Machines
------------------------------------------------------

[Document under construction]

The compiler part of the Z88DK produces perfectly standard Z80 assembler,
to this end it could easily be retargetted to other Z80 based machines with
the minimum of effort.

In order to port for other Z80 machines a new startup file has to be
supplied along with slightly rewritten library functions.

The startup file for the Z88 is located in the {zcc}/lib directory and
is called z88_crt0.asm, it just provides a simple way to interface
machine code programs to BASIC - in it is contained a short BASIC program
which calls the startup code.

In the case of the Z88 the startup code allocates memory for the atexit()
stack and installs a simple error handler which exits to BASIC when escape
is pressed.

The file also includes the floating point routines if required by any
module in a project. Also defined in this file are LIBrary references
to the various runtime routines used by generated code - such as routines
to divide and multiply etc.

Unlike the earlier versions of Small C runtime routines are only linked in
if they are used, for example if your programs doesn't do any
multiplication or division then these routines will not be included in
the generated executable, hence resulting in much smaller executables.

This is a very fine idea, however potential problems may arise if you
have retargetted the compiler to another Z80 system eg the ZX Spectrum and
wish to generate executables which access far code.

The Z88 has a very flexible method of memory paging - (virtually) any
bank can be placed in any 16k segment of the Z80 physical address space,
and hence it is irrelevant where the code to access far data is located. 
However in the case of the Spectrum 128 memory can only be paged in the
top 16k of address space and, well, I think you see the problem - the code
to access far data is in danger of being paged out.

To circumvent this, place the routines which access far data (the lp_*
routines in the libsrc/crt0 directory) in with the startup code - this
will slightly increase the executable size but will almost guarantee no
embarrassing paging out mistakes (assuming of course that your startup
code is located in low memory).

A short startup for the ZX Spectrum is now in lib/spec_crt0.asm file,
a few Spectrum specific functions have been written so that many of the
examples for the z88 now compile and work on the Spectrum as well.

Floating Point Routines
-----------------------

A set of floating point routines is supplied which will work on any Z80
(it does use undocumented opcodes, but...), however should you wish to
write your own to utilise the fp calculator in your machines ROM, take
a look at the mathz88.asm file in the lib directory for a template, the
chances are you'll need to change the constant for 0.1 in the const.c file,
but let me know and I'll add another flag to the compiler!

Stdio Library Routines
----------------------

The "new" stdio library is now almost completely machine independent however
obviously some low level routines are needed in order for the generic routines
to work, here I shall list the required routines:

int fgetc_cons(void)
		Should read a key from the keyboard returning the ASCII
		key value in hl. This routine should return 0 if no key
		is pressed, however unless an error occurs it should wait
		for a keypress.

void fputc_cons(char code)
		Should print code to the screen

int fgets_cons(char *buf, int maxlen)
		Should read a string from the keyboard. Done this way because
		some computers (i.e. z88) have an OS call to do this which
		offers editing facilities

void puts_cons(char *str)	[optional]
		Writes a NULL terminated string to the console, this call
		is provided to conserve memory usage should no other stdio
		routines be required

int getk(void)			[optional]
		Should read the current state of the keyboard, returning
		NULL if no key is pressed

Should you require file handling you will need the following standard routines
from fcntl.h (or unistd.h as it is sometimes known), should you not want
file-handling for your machine then these functions should be NULL functions
(chances are they won't be called!):

int open(far char *name, int flags, mode_t mode);
int creat(far char *name, mode_t mode);
int close(int fd);
size_t read(int fd, void *ptr, size_t len);
size_t write(int fd, void *ptr, size_t len);
long lseek(int fd,long posn, int whence);

int open_z88(far char *name, int flags, mode_t mode, char *explicit, size_t len)
		This is a non-standard routine and on most machines will
		probably just call open() however this provides the facility
		to return the explicit file name (which is placed in explicit,
		up to a maximum length len)

extern int __FASTCALL__ readbyte(int fd);
		This function reads a byte from filehandle fd (which is 
		supplied in the register pair hl), if an error occurred it
		should return EOF (-1) and return with carry set. Otherwise
		it should return with carry reset and hl holding the byte
		just read

extern int writebyte(int fd, int c);
		This function writes byte c to filehandle fd, once more if
		an error occurs it should return EOF and carry set, otherwise
		hl holds the byte just written and carry is reset

void fabandon(FILE *fp)
		Abandon file with the handle fd - this is called by the system
		on program exit should it not be able to close a file. This
		function is a dummy function on the z88 but for example on the
		Spectrum +3 this function would be of use.

Once you have supplied the above functions the entire z88dk stdio library
is available to you (including printf etc) in addition to all the ctype,
string, assert, setjmp, near malloc, some stdlib and the generic math
routines - just a little work yields over 100 usable functions!

dom, 9/4/2000
