Pset Posted January 4, 2014 Share Posted January 4, 2014 (edited) 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 January 4, 2014 by Pset 1 Quote Link to comment Share on other sites More sharing options...
Pset Posted January 4, 2014 Author Share Posted January 4, 2014 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 Quote Link to comment Share on other sites More sharing options...
Pset Posted January 4, 2014 Author Share Posted January 4, 2014 (edited) 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 January 4, 2014 by Pset Quote Link to comment Share on other sites More sharing options...
Pset Posted January 4, 2014 Author Share Posted January 4, 2014 (edited) 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 FrontendThe 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 filesIn 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.cfgZCCCFG/[name].cfg eg +z88ZCCFILEZCCCFG/zcc.cfg Edited January 4, 2014 by Pset Quote Link to comment Share on other sites More sharing options...
Pset Posted January 4, 2014 Author Share Posted January 4, 2014 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 Quote Link to comment Share on other sites More sharing options...
Pset Posted January 4, 2014 Author Share Posted January 4, 2014 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 Quote Link to comment Share on other sites More sharing options...
Pset Posted January 4, 2014 Author Share Posted January 4, 2014 (edited) I can't figure out how to change the CAQ loader in Aquarius.c I change the file, adding lines and even just change thenumbering 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 January 4, 2014 by Pset Quote Link to comment Share on other sites More sharing options...
Pset Posted January 6, 2014 Author Share Posted January 6, 2014 (edited) 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 January 6, 2014 by Pset Quote Link to comment Share on other sites More sharing options...
+Gemintronic Posted January 6, 2014 Share Posted January 6, 2014 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. Quote Link to comment Share on other sites More sharing options...
Pset Posted January 6, 2014 Author Share Posted January 6, 2014 (edited) 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 January 6, 2014 by Pset Quote Link to comment Share on other sites More sharing options...
Pset Posted January 8, 2014 Author Share Posted January 8, 2014 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. z88dkCompilerUI.zip Quote Link to comment Share on other sites More sharing options...
Pset Posted January 8, 2014 Author Share Posted January 8, 2014 (edited) 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 January 8, 2014 by Pset Quote Link to comment Share on other sites More sharing options...
JamesD Posted January 9, 2014 Share Posted January 9, 2014 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. 1 Quote Link to comment Share on other sites More sharing options...
Pset Posted January 9, 2014 Author Share Posted January 9, 2014 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 Quote Link to comment Share on other sites More sharing options...
JamesD Posted January 10, 2014 Share Posted January 10, 2014 (edited) 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 January 10, 2014 by JamesD 1 Quote Link to comment Share on other sites More sharing options...
Pset Posted January 13, 2014 Author Share Posted January 13, 2014 (edited) 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 /* * 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 January 13, 2014 by Pset Quote Link to comment Share on other sites More sharing options...
Pset Posted January 14, 2014 Author Share Posted January 14, 2014 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 Quote Link to comment Share on other sites More sharing options...
JamesD Posted January 15, 2014 Share Posted January 15, 2014 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. Quote Link to comment Share on other sites More sharing options...
Pset Posted January 16, 2014 Author Share Posted January 16, 2014 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 Quote Link to comment Share on other sites More sharing options...
Pset Posted January 16, 2014 Author Share Posted January 16, 2014 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. Quote Link to comment Share on other sites More sharing options...
Pset Posted January 16, 2014 Author Share Posted January 16, 2014 Have to kill that sleep(0); line in the code above and likely in the download. I really wish I could edit posts. 1 Quote Link to comment Share on other sites More sharing options...
Pset Posted January 17, 2014 Author Share Posted January 17, 2014 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 Quote Link to comment Share on other sites More sharing options...
JamesD Posted January 17, 2014 Share Posted January 17, 2014 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. Quote Link to comment Share on other sites More sharing options...
JamesD Posted January 17, 2014 Share Posted January 17, 2014 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. Quote Link to comment Share on other sites More sharing options...
Pset Posted January 17, 2014 Author Share Posted January 17, 2014 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 header created at http://www.vdsteenoven.com/aquarius/romcheck.html '- rom starts at $E000, and compiled at $E010 '- from http://atariage.com/forums/topic/176858-aquarius-using-the-supercart-i-cartridge-board/?do=findComment&comment=2205677 '- 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 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.