#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int z, d;
int prim;
int grenze;
printf("Primzahlen bis 1000:\n");
grenze = 1000;
printf(" 2 ");
for (z = 3; z < grenze; z += 2) {
prim = 1;
for (d = 3; d < z / 2; d += 2) {
if (z % d == 0) {
prim = 0;
break;
}
}
if (prim) {
if (z < 10) printf(" ");
if (z < 100) printf(" ");
printf("%d ", z);
}
}
return 0;
}
It compiled, and I got a binary file which I renamed to Prim.com, but I did not yet succeed to run it on my NC100. I tried a BASIC loader to run the program:
10 REM Prim - ROM OS loader
20 IF LOMEM>=&5400 THEN PRINT "Error - need 19k of lower memory free!":END
30 *LOAD PRIM.COM 8C00
40 VDU 4:CLS
50 CALL &8C00
60 VDU 5:CLS
Any hints on how to run a z88dk compiled C source on an Amstrad NC100?
It can be executed on the ROM OS through the BASIC loader program (which is what I used as a template for my prime number program above) or directly on ZCN (a CP/M clone for the NC100). I don't see any special requirements like an ASCII string "NC100PRG", a special origin or a necessary jump to a fixed location. I tested this program, and it runs fine on my NC100.
So maybe we just need to tell the compiler to use the origin we want, maybe using the -zorg compiler option? (Does it need its input as hex or decimal? There's no information about the format.) I guess we'd need -startup=3, too. What else? -make-app? -create-app?
Apparently the z88dk creates code at the SRAM Card location $C200, which is appropriate if you want to create a program card. I use my SRAM Card in a regular manner, i.e. to save files from the word processor, spreadsheet, BASIC, etc. Using the BASIC loader, I need to load the program to a chosen memory location (e.g. $8C00) and run it from there.
So I modified the nc100_crt0.asm file and deleted the lines between the org statement and the start label. I changed the origin to $8C00, which is appropriate for my BASIC loader (I'd prefer to be able to set it dynamically, though, maybe using -zorg?).
I'm not sure what the start and the cleanup code does, but I could at least run the prime number program. I marvelled at the correct prime number output, and then gnashed my teeth when I saw that the NC100 crashed on return...
There must be something wrong with the cleanup code, I guess (help is appreciated).
As soon as I deleted the whole cleanup code except for the ret statement, I succeeded in running the program and returning safely to the BASIC prompt. I guess I compromised something in the file i/o area, so I'm afraid I need a deeper insight...
Here's my current nc100_crt0.asm file (didn't find a way to upload a file here):
; Kludgey startup for nc100
;
; djm 17/4/2000
;
; I've never used one of these brutes so I dunno if it's
; correct at all, this is all taken from the file nciospec.doc
; on nvg.unit.no, I assume that the PCMCIA RAM card is an
; actual fact addressable RAM and we can overwrite variables
; etc NB. Values of static variables are not reinitialised on
; future entry.
;
; $Id: nc100_crt0.asm,v 1.8 2009/06/22 21:20:05 dom Exp $
;
MODULE nc100_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 heaplast ;Near malloc heap variables
XDEF heapblocks
XDEF __sgoioblk ;stdio info block
XDEF base_graphics ;Graphical variables
XDEF coords
org $8C00
start:
call _main ;Call user code
cleanup:
ret
l_dcal: jp (hl)
; Now, define some values for stdin, stdout, stderr
__sgoioblk:
IF DEFINED_ANSIstdio
INCLUDE "stdio_fp.asm"
ENDIF
;-------
; Now, which of the vfprintf routines do we need?
;-------
_vfprintf:
IF DEFINFED_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
;-------
; Some variables
;-------
_std_seed: defw 0 ;Integer rand() seed
;Atexit routine
exitsp: defw 0 ;atexit() stack address
exitcount: defb 0 ;Number of atexit() routines
heaplast: defw 0 ;heap variables
heapblocks: defw 0
base_graphics: defw 0 ;Graphics variables
coords: defw 0
defm "Small C+ nc100"
defb 0
;-------
; Floating point
;-------
IF NEED_floatpack
INCLUDE "float.asm"
fp_seed: defb $80,$80,0,0,0,0 ;FP seed (unused ATM)
extra: defs 6 ;FP spare register
fa: defs 6 ;FP accumulator
fasign: defb 0 ;FP variable
ENDIF
All the cleanup code does is to close all the open files (since there's no file support for nc100 this shouldn't do anything) and restore the stack to what it was on entry.
It's also got some dodgy code to do with restoring hl' which looks like it was a hanger on from the ZX port. Perhaps it's this that's causing the problem.
While inserting the support for the automatic malloc() heap definition I took the opportunity to insert also the '-startup=2' option.
It will hopefully do what bbock was asking for: different location for ORG and card header removed.
If anybody is still onto the nc100, just tell.. if the program is invoked by the CP/M or another OS we can easily add support parameter parsing (argv, argc..) and more.
The Amstrad set up is a bit strange. Firstly the NC100 is a persistent system, it doesn't get rebooted unless something goes horribly wrong (and that means 'I hope your files were backed up on PCMCIA card')
Programs run from basic you really need to make space by playing with the BASIC mem ptrs and keep any heap in that area (automalloc is definitely wrong)
When you run from PCMCICA NC100PRG card ("program card") you are paged in at 0xC000, with the system in the low banks. You have a stack of about 1-2K (I forget exactly) as provided by the system. The heap memory you have available is A000-A3FF which is shared with other apps (so if you yellow button away and then get re-entered it's gone). If you don't use the file selector OS call you've also got A800-AFFF. For any other memory you need to use heapalloc, heaplock, heapaddr, heapfree. These are also persistent, so you either need to keep the handles safe to always have a clean up method, or free them.
The executable mindset is very very different though. The normal behaviour is that you switch between apps
and they keep their state, so running a program doesn't mean "starting it".
The OS itself expects 0000-BFFF to be mapped, C000-FFFF is the usual ROM/PCMCIA window which means bank switching is exciting and you either need a trampoline in Axxx somewhere or to pull the stunt where you
do an out to set the bank and then fetch the next instruction from the new bank, next IP. If you do want to map into other banks you also need to update the system variables and you need to write the variable before you do the out instruction (because NMI is used for power management)
Screen is also at 0xC000 just to be irritating.
For any kind of "normal" apps though you can just build for CP/M instead and run the CP/M clone for the box.
Summary though: the automalloc looks very wrong and will probably eat your computer.
I think you are stuck with a static block and/or A000-A3FF (if running from a card). To go beyond that you have to use the OS heap*() functions and clean them up on exit.
The system does have a real file system and memory allocators. I'll have a fiddle at some point. Need to put the PCI/PCMCIA card reader back into a PC first but I do have a real NC100..
A bit stuck at the moment. While waiting for a chance to play with the memory card I added full stdio support to the nc100, or at least that was the plan.. but if I use say printf() I get
cp /tmp/tmpXX2xiqa7.opt /tmp/tmpXX2xiqa7.asm
zcpp -I. -DZ80 -DNC100 -D__NC100__ -DSCCZ80 -DSMALL_C -I/usr/local/lib/z88dk//include test.c /tmp/tmpXXyNJSdV.i
sccz80 -asm=z80asm /tmp/tmpXXyNJSdV.i
copt /usr/local/lib/z88dk//lib/z80rules.2 < /tmp/tmpXXyNJSdV.asm > /tmp/tmpXXyNJSdV.op1
copt /usr/local/lib/z88dk//lib/z80rules.1 < /tmp/tmpXXyNJSdV.op1 > /tmp/tmpXXyNJSdV.opt
z80asm -eopt -ns -Mo -I/usr/local/lib/z88dk//lib /tmp/tmpXXyNJSdV.opt
z80asm -a -m -Mo -L/usr/local/lib/z88dk//lib/clibs -I/usr/local/lib/z88dk//lib -oa.bin -inc100_clib -iz80_crt0 /tmp/tmpXX2xiqa7.opt /tmp/tmpXXyNJSdV.o
Error at file '/tmp/tmpXX91EreK.opt' line 71: symbol not defined
1 errors occurred during assembly
Key to filenames:
/tmp/tmpXXyNJSdV.o = test.c
Error at file '/tmp/tmpXX91EreK.opt' line 71: symbol not defined
Segmentation fault (core dumped)
Linking with -lndos works *but* as far as I can tell (and strings seems to be about the only tool to dump z88dk libraries ?) printf is in nc100_clib.lib
Bulding the same file with the uzi tree I get the rather more expected
Errors in source file test.c:
Error at file '/tmp/tmpXX4w7nDV.opt' line 57: symbol not defined
^ ---- call creat
Error at file '/tmp/tmpXX4w7nDV.opt' line 99: symbol not defined
^ ---- call close
and close and creat are in the uzi C lib as far as I can tell, but it *does* find printf, and blows up politely a step earlier
Tested on a real NC100, I need to fix some library problems but the corrected startup code seems to work fine. In answer to the question where to put the initial malloc heap - the answer is in the startup code where it says "Waste 509 bytes" !
Unlike Axxx ranges that range is persistent so if you yellow button out and then return it is still present
Incidentally the yellow button code in the stdio code is a bit dubious - you don't want to leap randomly out of the library code but to do a controlled departure. I'll have a look at fixing that and tidying it all up a bit when I get some time next week
I'm printing your hints for malloc() to read them quietly (the CPC stuff can wait a little more ).
The printf() stuff, is linked in any core library but all the file stuff is kept aside, so a programmer can potentially choose between different fcntl flavours, where ndos.lib is just a do-nothing termination (see fcntl/dummy).
'close' is most probably required everytime you use printf (called on exit), but I'm not sure on 'creat': could it be inside your 'open' implementation ? Which library did you base your library on ?
I just updated the nc100 CRT0 file with a new optional 'AMALLOC' implementation.
It uses that fixed 500 bytes area and I did not test it at all.. sorry but to get a program into an emulator was taking too long and I was risking to loose the current work, so here it is.
I've been debugging the enabling bits for a full file implementation for the NC100 (the ROM methods include file I/O, rename etc). Once it's a bit more stable I'll submit it for comment.
No it wasnt !
By the way things were not so bad as I thought, most of the problem went away when I included the fcntl portions written in C in the compilation loop.
I had only to exclude "opendir.c" (probably the culript is a missing declaration for 'DIR') and to replace "puts_cons" with its generic equivalent.
Looking forward the nightly build ..