Jump to content
Sign in to follow this  
Pset

[AQUARIUS] z88dk Aquarius Development

Recommended Posts

Following are vital Z88 Development Kit files used for compiling C to Aquarius cassette files (.CAQ)

We should discuss and update these to make them more useful for our particular workflow,

 

C:\Program Files (x86)\z88dk\lib\config\aquansi.lnx

#
# Config file for zcc (front end for Small C+ compiler)
#
 
#
# Names of the various programs, if they're in your path you won't need to
# alter these settings - except for COPYCMD, on unix set it to: cp
#
 
Z80EXE   z80asm
MPMEXE      mpm
CPP zcpp
LINKER z80asm
COMPILER sccz80
COPTEXE copt
COPYCMD cp
APPMAKER appmake
 
#
# Flag to stimulate alternate handling of math constants, this flag is
# supplied to the compiler when you supply -lmz to the frontend
# you'll probably want to change this if you're retargetting
#
# No handling for the Spectrum, so leave as per z88
 
Z88MATHFLG -math-z88
 
#
# Style of the C Preprocessor
#
# 1 = outimplied - cpp creates .i file
# 2 = outspecified - output specified by zcc
# 3 = filter - input piped into cpp by zcc and out to a file by zcc
#
# zcpp, gnu cpp, vbcc cpp are all outspecified
#
 
STYLECPP 2
 
#
# Where the include files are kept (-I is preprocessor flag to tell it where
# to find header files)
#
# Include the full path, eg DESTDIR/include
#
 
INCPATH -IDESTDIR/include
 
#
# Any extra command line options for the assembler
#
# (Leave alone!)
 
ASMOPTS -Mo -IDESTDIR/lib
 
#
# Options for the optimizer
#
# COPTRULES3 contains optimizations which call in other library
# routines..boosting code size, but..may save in the end if they
# are used often
#
# COPTRULES2 is the extended rule set for indexing within arrays and
# optimizing operations on unsigned chars
#
# COPTRULES1 is the standard rule set (been hanging around for ages!
#
# Supply the full path before the filenames, eg DESTDIR/lib/z80rules.1
#
 
COPTRULES1 DESTDIR/lib/z80rules.1
COPTRULES2 DESTDIR/lib/z80rules.2
COPTRULES3 DESTDIR/lib/z80rules.0
 
#
# Asm file which contains the startup code (omit suffix for Z80asm sake)
#
# CRT0   = Full path and name of the startup code file (omit suffix!)
#
 
CRT0 DESTDIR/lib/aquarius_crt0
 
 
#
# Linker Options
#
# 
# Keep the -i before the path in 
# libraries)
#
# LINKOPTS  = Options required when linking (leave alone!) -LDESTDIR/lib
#
 
 
 
LINKOPTS -a -m -Mo -LDESTDIR/lib/clibs -IDESTDIR/lib
 
#
# Names of the libraries
# Z88MATHLIB = name of library linked if -lmz supplied
# STARTUPLIB = library that is always linked in (contains all lib functions)
# GENMATHLIB = generic maths library
#
# (Leave alone!)
#
 
Z88MATHLIB z88_math
STARTUPLIB z80_crt0
GENMATHLIB gen_math
 
#
# Any default options you want - these are options to zcc which are fed
# through to compiler, assembler etc as necessary
#
# -I. needed for some strange reason for GNU cpp, I dunno why..
#
# The ones here, set verbose flag (echo commands) and switch on optimization
#
# (Leave alone!) [Recommended settings..]
#
# spec_clib required here because we've split up machine functions from
# generic z80 startup functions
#
 
OPTIONS -v -O2 -I. -laquansi_clib -lndos -DZ80 -DSMALL_C -DAQUARIUS -D__AQUARIUS__ -M -DSCCZ80 -Cz+aquarius
 
 
# Additional config options for the alternate assemblers
# these override ASMOPTS and LINKOPTS defined above which take
# effect for z80asm/mpm
#
# The choice of assembler can be specified using -asm=XXX by default
# z88dk uses z80asm but this may change in the future
 
# First of all for vasm/vlink
VASMOPTS -quiet -Fvobj -IDESTDIR/lib
VLINKOPTS -LDESTDIR/lib/vlink/
 
# The toolchain can also output for the asxx suite 
ASZ80OPTS
ASLINKOPTS
 



Edited  by Pset

  • Like 1

Share this post


Link to post
Share on other sites

Very subtle differences betwee aquansi.lnx and aquansi.cfg

 

C:\Program Files (x86)\z88dk\lib\config\aquansi.cfg

 

 

#
# Config file for zcc (front end for Small C+ compiler)
#
 
#
# Names of the various programs, if they're in your path you won't need to
# alter these settings - except for COPYCMD copy
#
 
Z80EXE   z80asm
MPMEXE      mpm
CPP  zcpp
LINKER  z80asm
COMPILER sccz80
COPTEXE copt
COPYCMD copy
APPMAKER appmake
 
#
# Flag to stimulate alternate handling of math constants, this flag is
# supplied to the compiler when you supply -lmz to the frontend
# you'll probably want to change this if you're retargetting
#
# No handling for the Spectrum, so leave as per z88
 
Z88MATHFLG -math-z88
 
#
# Style of the C Preprocessor
#
# 1 = outimplied - cpp creates .i file
# 2 = outspecified - output specified by zcc
# 3 = filter - input piped into cpp by zcc and out to a file by zcc
#
# zcpp, gnu cpp, vbcc cpp are all outspecified
#
 
STYLECPP 2
 
#
# Where the include files are kept (-I is preprocessor flag to tell it where
# to find header files)
#
# Include the full path, eg C:\PROGRA~2\Z88DK\include
#
 
INCPATH -IC:\PROGRA~2\Z88DK\include
 
#
# Any extra command line options for the assembler
#
# (Leave alone!)
 
ASMOPTS -Mo -IC:\PROGRA~2\Z88DK\lib
 
#
# Options for the optimizer
#
# COPTRULES3 contains optimizations which call in other library
# routines..boosting code size, but..may save in the end if they
# are used often
#
# COPTRULES2 is the extended rule set for indexing within arrays and
# optimizing operations on unsigned chars
#
# COPTRULES1 is the standard rule set (been hanging around for ages!
#
# Supply the full path before the filenames, eg C:\PROGRA~2\Z88DK\lib\z80rules.1
#
 
COPTRULES1 C:\PROGRA~2\Z88DK\lib\z80rules.1
COPTRULES2 C:\PROGRA~2\Z88DK\lib\z80rules.2
COPTRULES3 C:\PROGRA~2\Z88DK\lib\z80rules.0
 
#
# Asm file which contains the startup code (omit suffix for Z80asm sake)
#
# CRT0    = Full path and name of the startup code file (omit suffix!)
#
 
CRT0 C:\PROGRA~2\Z88DK\lib\aquarius_crt0
 
 
#
# Linker Options
#
# 
# Keep the -i before the path in 
# libraries)
#
# LINKOPTS  = Options required when linking (leave alone!) -LC:\PROGRA~2\Z88DK\lib
#
 
 
 
LINKOPTS -a -m -Mo -LC:\PROGRA~2\Z88DK\lib\clibs -IC:\PROGRA~2\Z88DK\lib
 
#
# Names of the libraries
# Z88MATHLIB = name of library linked if -lmz supplied
# STARTUPLIB = library that is always linked in (contains all lib functions)
# GENMATHLIB = generic maths library
#
# (Leave alone!)
#
 
Z88MATHLIB  z88_math
STARTUPLIB  z80_crt0
GENMATHLIB gen_math
 
#
# Any default options you want - these are options to zcc which are fed
# through to compiler, assembler etc as necessary
#
# -I. needed for some strange reason for GNU cpp, I dunno why..
#
# The ones here, set verbose flag (echo commands) and switch on optimization
#
# (Leave alone!) [Recommended settings..]
#
# spec_clib required here because we've split up machine functions from
# generic z80 startup functions
#
 
OPTIONS  -v -O2 -I. -laquansi_clib -lndos -DZ80 -DSMALL_C -DAQUARIUS -D__AQUARIUS__ -M -DSCCZ80 -Cz+aquarius
 
 
# Additional config options for the alternate assemblers
# these override ASMOPTS and LINKOPTS defined above which take
# effect for z80asm\mpm
#
# The choice of assembler can be specified using -asm=XXX by default
# z88dk uses z80asm but this may change in the future
 
# First of all for vasm\vlink
VASMOPTS -quiet -Fvobj -IC:\PROGRA~2\Z88DK\lib
VLINKOPTS -LC:\PROGRA~2\Z88DK\lib\vlink\
 
# The toolchain can also output for the asxx suite 
ASZ80OPTS
ASLINKOPTS
 

 

 

 

Share this post


Link to post
Share on other sites

C:\Program Files (x86)\z88dk\src\appmake\aquarius.c

 

 

/*
 *   Mattel Aquarius
 *   This tool creates a BASIC loader file
 *   and a binary file stored in "variable array" format
 *
 *   The machine code starts at 14712.
 *   The original Mattel loader (now commented out) permitted
 *   little changes in the BASIC loader, but we don't need it.
 *
 *   Stefano Bodrato - December 2001: first release
 *
 *   $Id: aquarius.c,v 1.2 2009/06/13 19:16:42 dom Exp $
 */
 
#include "appmake.h"
 
static char             *binname      = NULL;
static char             *outfile      = NULL;
static char              help         = 0;
 
 
/* Options that are available for this module */
option_t aquarius_options[] = {
    { 'h', "help",     "Display this help",          OPT_BOOL,  &help},
    { 'b', "binfile",  "Linked binary file",         OPT_STR,   &binname },
    { 'o', "output",   "Name of output file",        OPT_STR,   &outfile },
    {  0,  NULL,       NULL,                         OPT_NONE,  NULL }
};
 
 
 
 
int aquarius_exec(char *target)
{
    char    filename[FILENAME_MAX+1];
    char    ldr_name[FILENAME_MAX+1];
char mybuf[20];
FILE *fpin, *fpout;
int c;
int i;
int len;
int dlen;
 
    strcpy(ldr_name,"_");
 
 
    if ( help || binname == NULL )
        return -1;
 
    if ( outfile == NULL ) {
        strcpy(filename,binname);
        suffix_change(filename,".caq");
    } else {
        strcpy(filename,outfile);
    }
 
 
if ( (fpin=fopen(binname,"rb") ) == NULL ) {
printf("Can't open input file\n");
exit(1);
}
 
 
/*
 * Now we try to determine the size of the file
 * to be converted
 */
 
if (fseek(fpin,0,SEEK_END)) {
printf("Couldn't determine size of file\n");
fclose(fpin);
exit(1);
}
 
len=ftell(fpin);
dlen=(len)/4;
 
fseek(fpin,0L,SEEK_SET);
 
/****************/
/* BASIC loader */
/****************/
 
strcat(ldr_name,filename);
 
if ( (fpout=fopen(ldr_name,"wb") ) == NULL ) {
printf("Can't create the loader file\n");
exit(1);
}
 
/* Write out the header  */
for (i=1;i<=12;i++)
writebyte(255,fpout);
writebyte(0,fpout);
writestring("LOADR",fpout);
writebyte(0,fpout);
for (i=1;i<=12;i++)
writebyte(255,fpout);
 
writebyte(0,fpout);
writeword(14601,fpout); /* points to line 10 */
 
writeword(5,fpout); /*  5 U=0 */
writebyte('U',fpout);
writebyte(0xB0,fpout);
writebyte('0',fpout);
 
writebyte(0,fpout);
writeword(14609,fpout); /* points to line 20 */
 
writeword(10,fpout); /*  10 X=0 */
writebyte('X',fpout);
writebyte(0xB0,fpout);
writebyte('0',fpout);
 
writebyte(0,fpout);
writeword(14621+2,fpout); /* points to line 30 */
 
writeword(20,fpout); /*  20 DIMA(xxxxx) */
writebyte(0x85,fpout);
writebyte('A',fpout);
writebyte('(',fpout);
sprintf(mybuf,"%i",dlen);
for (i=1;i<=(5-strlen(mybuf));i++)
writebyte('0',fpout);
writestring(mybuf,fpout);
writebyte(')',fpout);
 
writebyte(0,fpout);
writeword(14629+2,fpout); /* points to line 40 */
 
writeword(30,fpout); /*  30 CLOAD*A */
writebyte(0x9A,fpout);
writebyte(0xAA,fpout);
writebyte('A',fpout);
 
writebyte(0,fpout);
writeword(14651+2,fpout); /* points to line 50 */
 
writeword(40,fpout); /*  40 POKE14340,PEEK(14552)+7 */
writebyte(0x94,fpout);
writestring("14340,",fpout);
writebyte(0xC1,fpout);
writestring("(14552)",fpout);
writebyte(0xA8,fpout);
writebyte('7',fpout);
 
writebyte(0,fpout);
writeword(14671+2,fpout); /* points to line 60 */
 
writeword(50,fpout); /*  50 POKE14341,PEEK(14553) */
writebyte(0x94,fpout);
writestring("14341,",fpout);
writebyte(0xC1,fpout);
writestring("(14553)",fpout);
 
writebyte(0,fpout);
writeword(14682+2,fpout); /* points to end of program */
 
writeword(60,fpout); /*  60 X=USR(0) */
writebyte('X',fpout);
writebyte(0xB0,fpout);
writebyte(0xB5,fpout);
writestring("(0)",fpout);
 
for (i=1;i<=25;i++)
writebyte(0,fpout);
 
fclose(fpout);
 
 
/*********************/
/* Binary array file */
/*********************/
 
/* Write out the header  */
 
if ( (fpout=fopen(filename,"wb") ) == NULL ) {
printf("Can't create the data file\n");
exit(1);
}
 
 
/* Write out the header  */
for (i=1;i<=12;i++)
writebyte(255,fpout);
 
writebyte(0,fpout);
 
 
/* Write out the "file name" */
for (i=1;i<=6;i++)
writebyte('#',fpout);
 
/* for (i=1;i<=6;i++)
writebyte(0,fpout);*/
 
 
/* Mattel games loader relocator */
/*
writebyte(0x2A,fpout); // ld hl,(14552)
writeword(14552,fpout);
writebyte(0x23,fpout); // inc hl 
writebyte(0x23,fpout); // inc hl 
writebyte(0x4e,fpout); // ld c,(hl) 
writebyte(0x23,fpout); // inc hl 
writebyte(0x46,fpout); // ld b,(hl) 
writebyte(0x11,fpout); // le de,67 
writeword(67,fpout);
writebyte(0x19,fpout); // add hl,de 
writebyte(0xe5,fpout); // push hl 
writebyte(0xc5,fpout); // push bc 
writebyte(0xe1,fpout); // pop hl 
writebyte(0xb7,fpout); // or a 
writebyte(0xed,fpout); // sbc hl,de 
writebyte(0x52,fpout);
writebyte(0xe5,fpout); // push hl 
writebyte(0xc1,fpout); // pop bc 
writebyte(0xe1,fpout); // pop hl 
writebyte(0x23,fpout); // inc hl 
writebyte(0x7e,fpout); // ld a,(hl) 
writebyte(0xb7,fpout); // or a 
writebyte(0x28,fpout); // jr z,-4 
writebyte(0xfb,fpout);
writebyte(0x11,fpout); // ld de,14768 
writeword(14768,fpout);
writebyte(0xed,fpout); // ldir 
writebyte(0xb0,fpout);
 
for (i=1;i<=41;i++)
writebyte(0,fpout);
*/
 
 
/* We append the binary file */
 
for (i=0; i<len;i++) {
c=getc(fpin);
writebyte(c,fpout);
}
 
/* Now let's append zeroes and close */
 
for (i=1;i<=(len%4);i++)
writebyte(0,fpout);
 
for (i=1;i<=38;i++)
writebyte(0,fpout);
 
fclose(fpin);
fclose(fpout);
 
    return 0;
}
 
 
Edited by Pset

Share this post


Link to post
Share on other sites

I've created a batch for compiling with z88dk it looks like this

CALL z88dkenv.bat
zcc +aquansi -lm -create-app -o OutputName C_InputFile.c


I've not tried the other command line options in the zcc documenation:

The Frontend
The frontend of z88dk is called zcc, it is this that you should call if you want to do any compilations. To invoke the frontend use the command:

        zcc [flags]  [files to be compiled/linked]
The files can be either C files (.c) , preprocessed C files(.i), compiled C files (.asm), optimised compiled file (.opt) or assembled files (.obj), any combination of them can be mixed together and the relevant processed done on them.
Processing of a file list is done on each file in turn (i.e. preprocess, compile, optimise, assemble) at the end all files may be linked into a single executable if desired.
Options to control the action of the frontend:

     +[file]       Name of alternate config file      		   (must be the first argument)     -a            Produce .asm (or .opt) file only     -c            Do not link object files     -E            Preprocess files only, leave output in .i file     -o [file]     Specify output file for binary (default is a.bas for BASIC                   programs and a.bin for application binaries)     -On           Optimize compiler output (to .opt file)                   n can be either 0 (none) 1,2,3, level 2 is recommended.		   Level 3 is suitable for large programs (includes certain		   lib functions to reduce size of code(!))     -v            Verbose - echo commands as they are executed     -vn           Don't be verbose
Options to control library usage:
     -l[name]      Link in a library - supply just the name (after placing them                   in the correct directory)     -lm           Link in the generic Z80 maths library     -lmz          Link in and generate code for OZ's maths routines     -lmalloc      Link in the near malloc routines     -lgfx         Link in the graphics routines (for BASIC progams)     -lgfxapp      Link in the graphics routines (for applications)     -lz88         Link in some Z88 application routines (eg mailboxing)     -lnet	   Link the the socket routines for ZSock     -m            Generate .map files when assembling/linking
Options to control the type code produced:
     -unsigned     Implicitly define everything as unsigned unless explicitly                   told otherwise.     -create-app   Create an application image (i.e. bank 63,62 etc)     -make-app     (App) Notify the compiler that you're trying to make an                   application     -reqpag=      (App) Number of 256 byte pages required for bad                   application     -zorg=        (App) Origin for a Z88 application     -safedata=    (App) Amount of safedata required by your code     -defvars=     (App) Where static variables should be dropped (only                   valid for single file compilations, but see later)     -expandz88    (App) Expanded z88 required     -no-expandz88 (App) Expanded z88 not required (these two flags toggle                   some startup code to check for an expanded machine)     -startup=3    Produce standalone code that can be run from a set                   address from BASIC. Use -zorg= to change the address     -R            (Use with above) produces relocatable code that can be                   loaded into a DIM'd BASIC array.     -smartpf      Intelligent printf routine handling     -no-smartpf   Turn off the intelligent printf handling     -make-lib     Shortcut to generate .o files from library .c files     -stackoffset  Sets the stack offset for shared libs (see package.txt		   for details)                   
Miscellaneous options:
     -z80-verb     Allow z80asm to be verbose, this tends to generate a lot                   of output to the screen so may not be desired.     -cc           Intersperse C code as comments in the assembler output, warning:                   this *will* clobber some optimizations.     -Wall         Turn on all the compiler warnings     -Wnone        Turn off all compiler warnings     -Wn[num]      Turn off the compiler warning [num]     -W[num]       Turn on the compiler warning [num]     -asxx	   Cause the compiler to emit asxx compatible code     -Cp[option]   Pass an option through to the pre-processor     -Ca[option]   Pass an option through to the assembler
In addition, the flags, -D, -I, -U are passed through to the preprocessor.
Any unrecognised options are passed through to the compiler (to allow for improvements in the future.)
Configuration files
In order for z88dk to work on as many platforms as possible and so that it can be easily tweaked, retargetted and generally mutilated, the frontend (zcc) consults a plain text configuration file which is in the directory pointed to be the ZCCCFG variable.
The default is to use the file ZCCCFG/zcc.cfg which by default is a softlink to the configuration file for the z88. Should you mainly be targetting a different machine then simply change the softlink to the appropriate file.
Should you want to occasionally compile for other machines then as the construct your zcc line thusly:

zcc +[name] [....]
Where name is either z88, zx (Spectrum), or vz (for the VZ200/300 port). If you wish to use a config file located in the current directory or anywhere else on the system then specify the full path and filename - make sure the filename as the suffix .cfg.
Finally, for the sake of backwards compatibility zcc will take the value of the environmental variable ZCCFILE and use that config file.

The order of checking is as follows:


"Local" file (if exists) eg +temp.cfg
ZCCCFG/[name].cfg eg +z88
ZCCFILE
ZCCCFG/zcc.cfg
Edited by Pset

Share this post


Link to post
Share on other sites

Looks like there's a lot more to this than I thought.

"C:\Program Files (x86)\z88dk\lib\clibs\aquansi_clib.lib"

Is full of binary gabrage and I don't think we can edit it.
I assumed its built from something like this .lst file?

 

C:\Program Files (x86)\z88dk\libsrc\aquansi.lst

 


stdio/aquarius/fgetc_cons

stdio/aquarius/getk
stdio/ansi/f_ansi
stdio/ansi/f_ansi_lf
stdio/ansi/f_ansi_putc
stdio/ansi/fputc_cons
stdio/ansi/puts_cons
stdio/ansi/f_ansi_dsr6
stdio/ansi/aquarius/f_ansi_attr
stdio/ansi/aquarius/f_ansi_bel
stdio/ansi/aquarius/f_ansi_char
stdio/ansi/aquarius/f_ansi_cls
stdio/ansi/aquarius/f_ansi_dline
stdio/ansi/aquarius/f_ansi_scrollup
@gfxbasetxt6.lst
graphics/aquarius/textpixl6
games/aquarius/bit_open
games/aquarius/bit_open_di
games/aquarius/bit_close
games/aquarius/bit_close_ei
games/bit_click
games/bit_play
games/bit_fx
games/bit_fx2
games/bit_fx3
games/bit_fx4
games/bit_synth
games/bit_frequency
games/bit_beep
games/beeper
games/joystick
@z80.lst

Share this post


Link to post
Share on other sites

C:\Program Files (x86)\z88dk\lib\aquarius_crt0.asm

 

 

;       CRT0 for the Mattel Aquarius
;
;       Stefano Bodrato Dec. 2000
;
;       If an error occurs eg break we just drop back to BASIC
;
;       $Id: aquarius_crt0.asm,v 1.8 2009/06/22 21:20:05 dom Exp $
;
 
 
 
                MODULE  aquarius_crt0
;--------
; Include zcc_opt.def to find out some info
;--------
        INCLUDE "zcc_opt.def"
 
;--------
; Some scope definitions
;--------
 
        XREF    _main           ;main() is always external to crt0 code
 
        XDEF    cleanup         ;jp'd to by exit()
        XDEF    l_dcal          ;jp(hl)
 
        XDEF    _std_seed        ;Integer rand() seed
 
        XDEF    _vfprintf       ;jp to the printf() core
 
        XDEF    exitsp          ;atexit() variables
        XDEF    exitcount
 
        XDEF    __sgoioblk      ;stdio info block
 
        XDEF heaplast ;Near malloc heap variables
XDEF heapblocks
 
        XDEF    base_graphics   ;Graphical variables
XDEF coords ;Current xy position
 
XDEF snd_tick ;Sound variable
 
 
        ;;org     14768 ; Mattel relocating loader
org 14712 ; Simpler loader
 
start:
        ld      (start1+1),sp ;Save entry stack
        ld      hl,-64
        add     hl,sp
        ld      sp,hl
        ld      (exitsp),sp
 
IF !DEFINED_nostreams
IF DEFINED_ANSIstdio
; Set up the std* stuff so we can be called again
ld hl,__sgoioblk+2
ld (hl),19 ;stdin
ld hl,__sgoioblk+6
ld (hl),21 ;stdout
ld hl,__sgoioblk+10
ld (hl),21 ;stderr
ENDIF
ENDIF
        call    _main ;Call user program
cleanup:
;
;       Deallocate memory which has been allocated here!
;
 
IF !DEFINED_nostreams
IF DEFINED_ANSIstdio
LIB closeall
call closeall
ENDIF
ENDIF
 
start1: ld sp,0 ;Restore stack to entry value
        ret
 
l_dcal: jp (hl) ;Used for function pointer calls
 
 
;-----------
; Define the stdin/out/err area. For the z88 we have two models - the
; classic (kludgey) one and "ANSI" model
;-----------
__sgoioblk:
IF DEFINED_ANSIstdio
INCLUDE "stdio_fp.asm"
ELSE
        defw    -11,-12,-10
ENDIF
 
 
 
;---------------------------------
; Select which printf core we want
;---------------------------------
_vfprintf:
IF DEFINED_floatstdio
LIB vfprintf_fp
jp vfprintf_fp
ELSE
IF DEFINED_complexstdio
LIB vfprintf_comp
jp vfprintf_comp
ELSE
IF DEFINED_ministdio
LIB vfprintf_mini
jp vfprintf_mini
ENDIF
ENDIF
ENDIF
 
;-----------
; Now some variables
;-----------
coords:         defw    0       ; Current graphics xy coordinates
base_graphics:  defw    $3028   ; Address of the Graphics map
; (text area-second line)
 
_std_seed:      defw    0       ; Seed for integer rand() routines
 
exitsp:         defw    0       ; Address of where the atexit() stack is
exitcount:      defb    0       ; How many routines on the atexit() stack
 
 
heaplast:       defw    0       ; Address of last block on heap
heapblocks:     defw    0       ; Number of blocks
 
IF DEFINED_NEED1bitsound
snd_tick:       defb    0       ; Sound variable
ENDIF
 
defm "Small C+ Aquarius" ;Unnecessary file signature
defb 0
 
;-----------------------
; Floating point support
;-----------------------
IF NEED_floatpack
        INCLUDE         "float.asm"
fp_seed:        defb    $80,$80,0,0,0,0 ;FP seed (unused ATM)
extra:          defs    6 ;FP register
fa:             defs    6 ;FP Accumulator
fasign:         defb    0 ;FP register
 
ENDIF

Share this post


Link to post
Share on other sites

I can't figure out how to change the CAQ loader in Aquarius.c

 

I change the file, adding lines and even just change the
numbering of the lines, recompile and I get the same exact CAQ file.

The number 12 here seems important. Why do these loops exist?

Is that 12 the number of BASIC keywords and operators in the BASIC LOADR file?

for (i=1;i<=12;i++)
writebyte(255,fpout);
writebyte(0,fpout);
writestring("LOADR",fpout);
writebyte(0,fpout);
for (i=1;i<=12;i++)
....
Edited by Pset

Share this post


Link to post
Share on other sites

Might take some time to figure out how to change z88dk.

For now let's learn some C programming on the Aquarius

 

Here's a C file that takes key input,returns the key value, the character, and demonstrates custom defintion of keys using #Define.

There are several ways of getting key input. I pulled this one from Barnie's sprite demo.

I've been doing all my C for Aquarius dev directly in the z88dk directory. To try it yourself, copy the attached .c and .bat files to the z88dk directory adn double click the .bat file.

You should get two .caq files as a result.

 

 

 

#include <stdio.h>
/* 
Single Character Input C 
Compiles for AQUARIUS using z88dk
To compile I use a batch file in the z88dk directory that looks like:
 
CALL z88dkenv.bat
zcc +aquansi -lm -create-app -o SingleCharInput SingleCharInput_C.c
 
Where "SingleCharInput_C.c" is the filename to be compiled
and "SingleCharInput" is the output file name
The result is files  "_SingleCharInput.caq"  and "SingleCharInput.caq"
 
Run Virtual Aquarius
In  BASIC type CLOAD and press RETURN key twice
Choose File > Play Cassette File > "_SingleCharInput.caq"
AQUARIUS should return "Found: LOADR"
Type RUN and press RETURN key twice
Choose File > Play Cassette File > "SingleCharInput.caq"
The screen should turn black and you will be asked to enter text.
Do some typing to test the program, try control keys, see multi char output.
 
Press ENTER to drop back to BASIC
*/  
 
// custom names for keys
#define UP       'w'  /* arrow up     */
#define DOWN     's' /* arrow down   */
#define LEFT     'a'  /* arrow left   */
#define RIGHT    'd'  /* arrow right  */
 
main()
{
int flag=1; 
char k;
 //clear screen to black w/ white text
printf ("%c2J",155);
// loop until flat is not 2
  while (flag!=2)
{ 
// put key down number into variable k
k=getk()
 
// handle input conditions
       switch( k ) {
               case UP:
                printf("%d= %c =UP\n",k,k);
                       break;
               case DOWN:
                printf("%d= %c =DOWN\n",k,k);
                       break;
               case RIGHT:
                printf("%d= %c =RIGHT\n",k,k);
                       break;
               case LEFT:
                printf("%d= %c =LEFT\n",k,k);
                       break;
               //quit on return key
               case 13:
                       flag=2;
                       break;
              // print any key pressed 
               default:
                if (k != 0) printf("%d = %c\n",k,k);
       }        
}
}
 

 

 

SingelCharInput.zip

Edited by Pset

Share this post


Link to post
Share on other sites

Just so you know: my lack of comment in this topic is not lack of interest! The next step in my growth as a developer is getting my hands dirty with C. Topics like this help me get into the right mindset.

Share this post


Link to post
Share on other sites

Now lets get a series of key down input using C with z88dk.

This one exits to BASIC with Control + C key combo.

Had hell of a time trying to use escape (aquarius can't see), and Control + Q never worked. *shrug*

 

 

 

#include <stdio.h>
#include <string.h>
/* 
New Line User Input C 
Compiles for AQUARIUS using z88dk
To compile I use a batch file in the z88dk directory that looks like:
 
CALL z88dkenv.bat
zcc +aquansi -lm -create-app -o NewLineInput NewLineInput_C.c
 
Where "NewLineInput_C.c" is the filename to be compiled
and "NewLineInput" is the output file name
The result is files  "_NewLineInput.caq"  and "NewLineInput.caq"
 
Run Virtual Aquarius
In  BASIC type CLOAD and press RETURN key twice
Choose File > Play Cassette File > "_NewLineInput.caq"
AQUARIUS should return "Found: LOADR"
Type RUN and press RETURN key twice
Choose File > Play Cassette File > "NewLineInput.caq"
The screen should turn black and you willbe asked to enter text.
Do some typing to test the program, try control keys, see strange characters.
 
Press Control C to drop back to BASIC
*/  
 
int main()
{
   char text[72]; // max string length for AQUARIUS.
   int cIn;
    //clear screen to black with white text
printf ("%c2J",155);
    
   do {
    fputs("enter some text: ", stdout);
    fflush(stdout);
   
    if ( fgets(text, sizeof(text), stdin) != NULL )
    {
       char *newline = strchr(text, '\n'); /* search for newline character */
       if ( newline != NULL )
        {
          *newline = '\0'; /* overwrite trailing newline */
       }
      printf("text = \"%s\"\n", text);
      
      if (cIn == '@') break; 
    }
    //loop until CONTROL C
   }while((cIn = getchar()) != '\03')
 
   return 0;
}

 

 

NewLineInput.zip

Edited by Pset

Share this post


Link to post
Share on other sites

To make compiling with z88dk easier I've created a program that lets

you peruse your C files and compile them, it then organizes all the various files into one folder.

For instance hello.c produces hello.bat, _hello.caq, hello.caq, and hello and they all get swept into folder "hello_"

 

I had dozens of small C experiments floating around z88dk folder.

This tool allows you to place C files anywhere.

I added the path to z88dk to my user PATH variable, but I'm not sure its needed.

 

Oh this program also launches the virtual aquarius using the command "aquarius", Which I set up with an alias in my PATH variable somewhere?

I did it long ago, forget how that's done. I'll have to test on another PC to see what kind of trouble that might cause. Hopefully not too much.

 

As usual the livecode source is included with the binaries for win/mac/linux.

EtVg0lr.png

 

 

z88dkCompilerUI.zip

Share this post


Link to post
Share on other sites

I've started some discussion with z88dk's developer about getting it to compile cartridge binaries.

He's asking about loading 'snapshots' of memory.

 

Maybe someone besides me should do the talking.

Maybe drop on over at their forum?

Edited by Pset

Share this post


Link to post
Share on other sites

I don't have membership to the Z88dk forum to post so I'll comment here.
This pertains to the last message that mentions carts.

You just have to tell the linker where to put the code and data segments. These are usually referred to as code, data or bss sections

On the SDCC site there is a comment about _CODE and _DATA being passed to the linker and after looking through the SDCC sources, I found them defined in crt0.s.
You'll need to org them to the proper memory locations to create a cart.
There should be docs for the ".area" directive that will help out with this.

  • Like 1

Share this post


Link to post
Share on other sites

Wooosh you say stuff, its all very mysterious to me. What?

 

"C:\Program Files\SDCC\lib\src\z80\crt0.s"

 

;--------------------------------------------------------------------------
;  crt0.s - Generic crt0.s for a Z80
;
;  Copyright (C) 2000, Michael Hope
;
;  This library is free software; you can redistribute it and/or modify it
;  under the terms of the GNU General Public License as published by the
;  Free Software Foundation; either version 2, or (at your option) any
;  later version.
;
;  This library is distributed in the hope that it will be useful,
;  but WITHOUT ANY WARRANTY; without even the implied warranty of
;  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;  GNU General Public License for more details.
;
;  You should have received a copy of the GNU General Public License 
;  along with this library; see the file COPYING. If not, write to the
;  Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
;   MA 02110-1301, USA.
;
;  As a special exception, if you link this library with other files,
;  some of which are compiled with SDCC, to produce an executable,
;  this library does not by itself cause the resulting executable to
;  be covered by the GNU General Public License. This exception does
;  not however invalidate any other reasons why the executable file
;   might be covered by the GNU General Public License.
;--------------------------------------------------------------------------
 
.module crt0
.globl _main
 
.area _HEADER (ABS)
;; Reset vector
.org  0
jp init
 
.org 0x08
reti
.org 0x10
reti
.org 0x18
reti
.org 0x20
reti
.org 0x28
reti
.org 0x30
reti
.org 0x38
reti
 
.org 0x100
init:
;; Stack at the top of memory.
ld sp,#0xffff
 
        ;; Initialise global variables
        call    gsinit
call _main
jp _exit
 
;; Ordering of segments for the linker.
.area _HOME
.area _CODE
.area _INITIALIZER
.area   _GSINIT
.area   _GSFINAL
 
.area _DATA
.area _INITIALIZED
.area _BSEG
.area   _BSS
.area   _HEAP
 
.area   _CODE
__clock::
ld a,#2
rst     0x08
ret
 
_exit::
;; Exit - special code to the emulator
ld a,#0
rst     0x08
1$:
halt
jr 1$
 
.area   _GSINIT
gsinit::
ld bc, #l__INITIALIZER
ld a, b
or a, c
jr Z, gsinit_next
ld de, #s__INITIALIZED
ld hl, #s__INITIALIZER
ldir
gsinit_next:
 
.area   _GSFINAL
ret

Share this post


Link to post
Share on other sites

I'm not completely familiar with SDCC but I'll try to explain it.

*edit*
A compiler does not just mix code and data together like you might in assembly. It normally generates an intermediate object code that is a mix of code and data with embedded data for the linker and those are organized in segments based on what they are for.
*edit*

These are segments the compiler/linker uses to define where things go in memory: In the startup code you posted, the code/data segments are just inserted one after the other. That will need to be changed to specific addresses.

C allocates non-static variables on the stack and passes parameters on the stack. As long as you initialize the stack pointer to some area RAM, most stuff will work. Normally you initialize this to be the top of RAM or a large area of RAM since the stack builds down as you push things onto it. This is not a segment but it's built into the code and as long as the stack pointer is set you don't have to worry much about it. Just remember that things like recursion can build a huge stack and it can run down into memory you use for something else if you aren't careful. You will need to change the org at the start of the startup code to be the first address executed in a cart. Note that some game consoles require all sorts of data to reside in the cart before your code and you'll need developer docs for something like that. I had to look that up for the Colecovision to build the IDE boot image for the Adam.

_CODE is your machine code output by the compiler. All the code is joined together there by the linker.

_DATA *should* point to things like strings that aren't modified... this is partially under programmer control so the better way to put it is don't mess with constants once you've created them and you won't have trouble putting the code in ROM... which is where this segment will go, right after your code.

_BSS goes in RAM. These are variables, data or data buffers that are at a fixed location, are modified by the program but aren't given a value where they are created in the code. This will not go in ROM but the linker normally reserves a block of memory for it. The linker either needs a command to leave it off your you have to chop it off of the binary image generated by the linker. Make sure you initialize all these variables in your C code somewhere at startup or at least clear that block of RAM to zero in your startup code (crt0.s).
This will explain bss a little better:
https://en.wikipedia.org/wiki/.bss

_HEAP is free memory that you would allocate from and usually contains globals you have defined. You need to initialize globals before you use them because RAM will have unknown contents when a cart starts.

If you use malloc you will also need to tell the memory handling routines what RAM to use before you call the main C code. Be sure *not* to include memory you will be using for the stack.

The startup code would need several things moved. The way it's written,it just stuffs in each segment where the last one ends.

These would need moved to RAM, the rest would be ROM (I think):

.area _BSEG
.area   _BSS
.area   _HEAP

I think the INITIALIZE would be dropped but I'm not sure. I'd have to study the docs.

Move these to the end and put an org statement before them with the address of where free RAM starts (avoiding any RAM ROM routines you call will use) that should be what you need. I have done this with other compilers for embedded systems but I make no promises since I haven't done it with this compiler/linker and it's been a few years.

I hope that helps.


Edited by JamesD
  • Like 1

Share this post


Link to post
Share on other sites

I wish that made some sense, but it doesn't. Thanks for trying.

 

For now here's a nice sprite demo in which we demonstrate loading files exterior to our main program.

In this case it is the large 10x17 running man sprites produced in Spedito.

 

The C files defining the sprite get a .h (for header) extension and become accessible with the #include statement.

 

I think Licecap GIF screengrabber caught inbetween frames

 

B6upSpE.gif

 

 

 

 /*
 * Test the ANSI terminal
 *
 * 15/4/2000 Stefano Bodrato
 *
 * Compile with zcc +zxansi ansitest.c
 */
#include "stdio.h"
#include "games.h"
 
#include <stdlib.h>
#include <graphics.h>
#include "10x17manrightx4.h"
#include "10x17manLeftx4.h"
 
#define UP       'w'  /* arrow up     */
#define DOWN     's' /* arrow down   */
#define LEFT     'a'  /* arrow left   */
#define RIGHT    'd'  /* arrow right  */
 
main()
{
int x,y,z;
int flag=1;
int cnt=0;
int face=0;
int vx=0;
int vy=0;
int timer=0;
char *ptr;
/*
        CSI n J
        Clears part of the screen. If n is zero (or missing), clear from cursor to end of screen. 
If n is one, clear from cursor to beginning of the screen. 
If n is two, clear entire screen (and moves cursor to upper left on DOS
*/
 x=35; 
 y=20;
  printf ("%c2J",155);
  
do {
 // get keyboard input , reset timer, set velocity and flag.
       switch( getk() ) {
               case UP:
                timer =0;
vy=-1;
vx=0;
flag=1;
                       break;
               case DOWN: 
timer =0;                
vy=1;
vx=0;
flag=1;
 
 
                       break;
               case RIGHT:
                timer =0;
vx=1;
vy=0;
face=0;
                flag=1;          
                       break;
               case LEFT:
                timer =0;
                vx=-1;
                vy=0;
                face=1;
                flag=1;
                       break;
               case 8:
                printf ("%c2J",155);
break;
case 13:
flag=2;
return 0;
break;
 
default:
// when no key down timer will stop man from running
timer=timer+1;
if(timer>10)
{
flag=0;
timer=0;
} 
break;         
       }
 
if (flag==1){
// update sprite position
 
x=x+vx;
y=y+vy;
if (x>89)x=1;
if (x<-9)x=79;
if (y>79)y=1;
if (y<-10)y=71;
 
 
//animate the sprite images
++cnt;
if (cnt==4) cnt=0;
if (face == 0){
 
if( cnt<=1)
{
putsprite(spr_or,x,y,manright1);
putsprite(spr_mask,x,y,manright1mask); 
} 
else 
{
putsprite(spr_or,x,y,manright2);
putsprite(spr_mask,x,y,manright2mask);
}
}
else{
 
if(cnt<=1)
{
putsprite(spr_or,x,y,manleft1);
putsprite(spr_mask,x,y,manleft1mask); 
}
else 
{
putsprite(spr_or,x,y,manleft2);
putsprite(spr_mask,x,y,manleft2mask); 
}
}
 
}
}while(flag!=2)
 
}
 

 

 

Edited by Pset

Share this post


Link to post
Share on other sites

Sorry this forum cuts off anything I do after using code blocks.

 

Here's the source files for that sprite demo.

 

He actually goes left and right with the A and D keys.

Up and down with W and S.

 

Be sure to check out the H files and see how the hex is put into data,

and the 'image' of the sprite is saved in commented code blocks.

Also how these 10x17 sprites were cut into 8x17 blocks for converting to hex.

Well here's an example of an 8 x16 sprite I couldn't use.

The pixels on the edge leave trails when the sprite moves so I had to go larger to add a mask.

 

char manright2[] = { 8, 16,
  0x00 /* ........ */,
  0x38 /* ..###... */,
  0x3c /* ..####.. */,
  0x00 /* ........ */,
  0x39 /* ..###..# */,
  0x79 /* .####..# */,
  0xdf /* ##.##### */,
  0xdc /* ##.###.. */,
  0x7c /* .#####.. */,
  0x3e /* ..#####. */,
  0x1b /* ...##.## */,
  0x33 /* ..##..## */,
  0xf3 /* ####..## */,
  0xc3 /* ##....## */,
  0x80 /* #....... */,
  0x00 /* ........ */
};
 

 

sprite10x17_.zip

Share this post


Link to post
Share on other sites

The documentation for SDCC is a bit lacking and I'll probably need to look at the source code to be sure any changes I make will be correct.

I worked on a 6809 code generator for SDCC but that was many versions ago and a lot has changed.

Share this post


Link to post
Share on other sites

OK.

Here's a colorful 99 Bottles of Beer program for your Aquarius. Note the for(t=100000) loops to slow it down.

A version in BASIC without coloring is blazing fast to.

Coloring the lines in BASIC and making them scroll is a chore for another time.

Colors don't scroll in BASIC, although I think there was a poke to get the screen to shift?

Maybe that was wishful thinking. Something must exist though because we can do it in C

 

 

// 99 bottles of beer mostly from  http://www.99-bottles-of-beer.net/language-c-844.html
 
#include <stdio.h>
 
int main(void)
{        
        int b;
int c;
        int t;
int color =31;
 
printf ("%c2J",155);
        for (b = 99; b >= 0; b--) {
c = c + 1;
if(c >= 5){
c=0;
//printf("%c2J",155);
}
color =color + 1;
if (color == 39) color=42;
if (color >= 47) color=31; 
sleep(1000);
//slow it down
for(t=100000; t<=0; t--); 
for(t=100000; t<=0; t--); 
for(t=100000; t<=0; t--); 
for(t=100000; t<=0; t--); 
for(t=100000; t<=0; t--); 
 
                switch (b) {
                case 0:
                        printf("No more bottles of beer on the wall, no more bottles of beer.\n");
 
                        printf("Go to the store and buy some more, 99 bottles of beer on the wall.\n");
                        break;
                case 1:
                        printf("1 bottle of beer on the wall\n 1 bottle of beer.\n");
                        printf("Take one down and pass it around, no more bottles of beer on the wall\n");
                        break;
                default:
                        printf("%d bottles of beer on the wall\n %d bottles of beer.\n", b, b);   
//slow it down
for(t=100000; t<=0; t--); 
for(t=100000; t<=0; t--); 
for(t=100000; t<=0; t--); 
for(t=100000; t<=0; t--); 
for(t=100000; t<=0; t--); 
 
                                // you can break long line  by carriage returns before your semi colon finishes the line good to know.
 
                                  printf("%c[%umTake one down and pass it around\n %d %s of beer on the wall.\n\n",27,color
                                ,b - 1 ,((b - 1) > 1)? "bottles" : "bottle");
                        break;
                }
        }       
        
        return 0;
}
 

new99bottles_.zip

Share this post


Link to post
Share on other sites

Also a note about my compiler app. For whatever reason in stand alone mode it only makes the batch file but doesn't actually compile your C program.

Dragging the batch to the command console will get your C program all compiled up.
I guess double clicking works to but I drag and drop then use the arrow up key in the command console to recompile my changes every other minute.

Share this post


Link to post
Share on other sites

Have to kill that sleep(0); line in the code above and likely in the download.

I really wish I could edit posts.

  • Like 1

Share this post


Link to post
Share on other sites

Here is an ASCII chart in C. It stops after filling the screen and waits for a key press so you can get a screenshot, or study the chart.

It loops until you press Control C and then drops into BASIC

 

Typing x=usr(0) and pressing return will run the program again.

Learned this in a CS class last year, knew it would come in handy.

 

Instead of using the CLOAD sequence for the two CAQ files you can use the build bin.

I've renamed one of the build files to asciichart.bin, you can use Virtual Aquarius Util menu "Load Binary File..." and set USR address to $3978

Then type x=usr(0) and pressing return will run the program

 

 

// ascii chart display for the Aauarius  in C
#include <stdio.h>
// prints ascii value list
void main()
{
char cIn;
// ascii value, I force the zero character to print NULL.
int i,x,n, h;
 
// run until command C
do{
i=1;
 
//  column counter
x=0;
 
// variable number of columns
n=5;
   
// half of characters
h = 120
//clear screen to black with white text
printf ("%c2J",155);
printf("0 NULL ");
 
do
{
    //  escape characters 
    if (i>6 && i<14) {
        if (i==7){printf("%d BELL ",i);}
        if (i=={printf("%d BS ",i);}
        if (i==9){printf("%d TAB ",i);}
        if (i==10){printf("%d LF ",i);}
        if (i==11){printf("%d VT ",i);}
        if (i==12){printf("%d LF ",i);}
 
        // after the carriage return start new column and row 
        if (i==13){
        printf("%d CR \n",i); 
        x = 0;
        }
    } 
 
    // print the ascii value and the character 
    else{
    printf("%d %c ",i,i);
    }
// use longer rows after the escape characters are printed.
    if (i > 14){
    n = 6;
    }
    // make a new row every n chars.
    if (x == n) {
    printf("\n");
    x = 0;
    }
if (i == h){
printf("\n");
while((cIn = getchar()) == ''); 
}
    // increment x and i
    x++;
    i++;
}
while(i<=255);
printf("\n");
// press any key to run again
while((cIn = getchar()) == '');
// press contraol C to exit into BASIC
}while(cIn = getchar() != '\03')
return 0;
 
}
 

asciichart_.zip

Share this post


Link to post
Share on other sites

I *think* I found what I was looking for. Ignore the stuff I said needed changed.

Just use the startup module you already posted that was written for the Aquarius and set some linger options discussed on the following page:

http://manpages.ubuntu.com/manpages/hardy/man1/sdcc.1.html

 

I believe the options you want to set to build carts are:

--code-loc

--data-loc

--stack-loc

 

The startup file may need some changes but I'm not familiar with the Aquarius to know without looking things up and I don't have time at the moment.

The code location should be set to the start address of cart ROM.

The data location should be set to the first usable free RAM address.

The stack location should be set to the top of RAM.

Share this post


Link to post
Share on other sites

I *think* I found what I was looking for. Ignore the stuff I said needed changed.

Just use the startup module you already posted that was written for the Aquarius and set some linger options discussed on the following page:

http://manpages.ubuntu.com/manpages/hardy/man1/sdcc.1.html

 

I believe the options you want to set to build carts are:

--code-loc

--data-loc

--stack-loc

 

The startup file may need some changes but I'm not familiar with the Aquarius to know without looking things up and I don't have time at the moment.

The code location should be set to the start address of cart ROM.

The data location should be set to the first usable free RAM address.

The stack location should be set to the top of RAM.

That was supposed to say linker.

Share this post


Link to post
Share on other sites

Ok now which file did you say we insert some changes to? The one in the first post? Well ain't that something.

And then what we need to recompile something somewhere?

 

 

Maybe someone knows for sure what values go in the commands.

I expect it starts with E010 for the 16 bytes of cartridge header?

But that seems out of range, but maybe out of range is expect because its on the cartridge?

I tried to make heads of Martin's boot loader script but there was even more outrageous numbers in there.

I need to look at it more.

Here's what Boriels zx BASIC does at cartridge compile time

 


aquariusromheader:
asm
defb $53,$43,$30,$38,$4B,$9C,$B5,$B0,$A8,$6C,$AC,$64,$CC,$A8,$06,$70
end asm
'- do not forget to scramble your program with 62
'- rom starts at $E000, and compiled at $E010
'- 8K Mode Header: 53 43 30 38 4B 9C B5 B0 A8 6C AC 64 CC A8 06 70
'- 16K Mode Header: 53 43 31 36 4B 9C B5 B0 A8 6C AC 64 CC A8 08 70

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...