CPCWiki forum

General Category => Programming => Topic started by: cpcitor on 22:01, 08 October 13

Title: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: cpcitor on 22:01, 08 October 13
Following Benefits of high profile programming: C coding for CPC with decoupling in mind (http://www.cpcwiki.eu/forum/programming/benefits-of-high-profile-programming-c-coding-for-cpc-with-decoupling-in-mind)I started this thread dedicated to a subtopic.

I've created a set of scripts to ease the installation and use of C/ASM compilation tools targetting the CPC.

You can read a description on cpcitor/cpc-dev-tool-chain · GitHub (https://github.com/cpcitor/cpc-dev-tool-chain)
There you have a "download zip" link.

Excerpt from there

What is this ?

This is a portable toolchain for C/ASM development targetting the Amstrad CPC platform.

What does it do ?


Why would I want to use that ?

Why would I not want to use that ?


EDIT: better markup and update following cpcitor/cpc-dev-tool-chain · GitHub (https://github.com/cpcitor/cpc-dev-tool-chain/)
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: cpcitor on 22:04, 08 October 13
Updated "hello world" example.

The "hello world" example is much more sophisticated now. It shows how to:
* have a project with several C files
* implement C functions in assembly
* access firmware routines like km_wait_key and txt_output
* use the latter to set mode, paper, pen, border color, show normal and control characters

Screenshots

Everybody loves screenshots.

For these screenshots I've used an experimental build of Kevin's arnoldemu, where the screen handling is broken.

 [ You are not allowed to view attachments ]  [ You are not allowed to view attachments ]  [ You are not allowed to view attachments ]  [ You are not allowed to view attachments ]  [ You are not allowed to view attachments ]  [ You are not allowed to view attachments ] [attach=7
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: andycadley on 09:42, 09 October 13
I think you missed my point in the last thread, try and imagine how likely you'd be to change your dev environment if the spec started off with:

"You'll need a Windows-like environment (Linux users will want to install Wine)"

I mean, it's not even as if you've evaluated all the options and gone for the best tools, you've just plumped immediately for the GNU toolchain because it just happens to be convenient for you. It's very hard to argue the GNU make is easier to work with than the XML based MSBuild for example, it's certainly much harder to build any kind of IDE or automated process on top of.

And I'll re-iterate, installing Cygwin on Windows is a very, very bad idea. I've seen it hose or utterly compromise the security of far too many systems due to it's utterly broken attempts to use non-canonical ACLs to fudge Unix's limited permissions model over Windows ACLs. You absolutely should not ever recommend anyone installs it at all.
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: Sykobee (Briggsy) on 10:41, 09 October 13

Short of writing a CPC development environment plugin for Eclipse, I think we'll have to cope with two development routes - Unix/Linux and Windows.


Just because it doesn't work for your personal Windows environment, doesn't mean that it isn't useful to make a start somewhere.


Possibly a different build tool can be implemented in the future to remove dependencies on particular platforms. MSBuild sounds horrendously platform specific, so that's out of the question. Maybe with a little work Ant or Maven could be used.
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: jsa on 20:34, 09 October 13
What about scons or waf ? :)



Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: andycadley on 22:04, 09 October 13
Possibly a different build tool can be implemented in the future to remove dependencies on particular platforms. MSBuild sounds horrendously platform specific, so that's out of the question. Maybe with a little work Ant or Maven could be used.
There's a mono port of msbuild (xbuild IIRC) so it's not platform specific, but the point wasn't "You should use X not Y" but rather that trying to start something like this by dictating "You must use X because that happens to be super convenient for me" is a complete non-starter.
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: cpcitor on 22:21, 09 October 13
Thanks everyone for your feedback.

While we talk about build systems, there's a nifty tool that helps a lot in practice when supporting multiple platforms. It's called CMake and runs on Unix, Windows and Mac OS X.

From the very same portable CMake project files, it can generate buildable projects for many build environments, including msbuild mentioned by @andycadley through its frontend Visual Studio, but also eclipse, kdevelop, code::blocks, makefile (for Unix, minGW, MSYS, NMake, Borland, Watcom), Ninja, XCode and Sublime Text 2. For details about generators see CMake Generator Specific Information - KitwarePublic (http://www.cmake.org/Wiki/CMake_Generator_Specific_Information) and CMake - Cross Platform Make (http://www.cmake.org/cmake/help/v2.8.11/cmake.html#section_Generators)

The net result is that, in theory, users of all these environment should be covered relatively easily. A few coworkers and I actually used CMake for a cross-platform project this year. After a fair bit of tuning, Windows and Linux users have worked on projects based on the same set of rule files.

For even more interest, CMake even has some documented setup for SDCC : CmakeSdcc - KitwarePublic (http://www.cmake.org/Wiki/CmakeSdcc) .
I have CMake 2.8 on my machine and a Generic-SDCC-C.cmake is indeed installed. Notice that it doesn't cover installation of sdcc, only use.

With the information available so far, would you consider it a good deal to add CMake as a dependency for a CPC development toolchain as a lever to support many IDEs ?
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: jrodriguezv on 18:09, 14 October 13
Hi!
 
First of all, thanks for your good job  :)
 
Im testing this project in my laptop with Ubuntu 13.4. You need to add libboost-graph-dev as dependency in order to compile SDCC.
 
Can you consider add support to cpcrslib (cpcrslib - CPC libraries for z88dk and SDCC - Google Project Hosting (http://code.google.com/p/cpcrslib/)) in your project.
 
Thanks
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: cpcitor on 19:31, 14 October 13
Hi!

First of all, thanks for your good job  :)

Hi @jrodriguezv ! Thanks for the support.  :)

Im testing this project in my laptop with Ubuntu 13.4. You need to add libboost-graph-dev as dependency in order to compile SDCC.
 

Interesting. It's definitely not needed in 12.10. If you remember what was the symptom it may be interesting for me to understand.

Can you consider add support to cpcrslib (cpcrslib - CPC libraries for z88dk and SDCC - Google Project Hosting (http://code.google.com/p/cpcrslib/)) in your project.

Good idea! Lots of features. Even when not using specialized ones like sprites, out-of-the-box features of general use like UnExo or music player are nice.

I see a tutorial on How to use cpcrslib in SDCC (http://code.google.com/p/cpcrslib/wiki/cpcrslibSDCC) and a release on cpcrslib SDCC 11.03.2012.rar - Google Project Hosting (http://code.google.com/p/cpcrslib/downloads/detail?name=cpcrslib%20SDCC%2011.03.2012.rar&can=2&q=). It seems clear enough and appropriate.

Cannot do this very soon, but here's how I'd do it:

Summary : previous steps would automatically fetch and build cpcrslib from source like it does already for sdcc, z88dk, idsk and hex2bin.

Bonus/sanity check (not needed) a make target (or even a patch) that copies some Makefiles into cpcrslib example directories to build them.

Provide a simple example using it. For a start, modifying hello_world_using_sdcc to follow the tutorial would be enough. A "top" solution would adjust main make target that grep sources to check if there's a #include <cpcrslib.h> and auto-build and link cpcrslib only in this case !

Net result : to enable cpcrslib in any project, just write a C file with #include <cpcrslib.h> and use it, it would just work!

Cheers,
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: cpcitor on 22:21, 15 October 13
Hello all,

Following jrodriguezv's suggestion, I started to work on support for cpcrslib and pushed to cpcitor/cpc-dev-tool-chain · GitHub (https://github.com/cpcitor/cpc-dev-tool-chain/) an updated version.
It now also fetches cpcrslib from google code and compiles it.
cpcrslib is distributed in rar format which makes one more dependency.

Next I'm planning for multi-project. That is, you'll be able to designate any directory as being, for example, a "sdcc project" and it will be, in the sense that the cpc-dev-tool-chain will be able to compile your project without hassle. The first projects to benefit will be the cpcrslib examples themselves. Building cpcsrlib will build them and make a sample dsk, that will make a compile-time sanity check.

Cheers,
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: jrodriguezv on 23:07, 15 October 13
Thanks!! You have done it very soon  ;)

I will test it as soon as possible.

Thanks again
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: cpcitor on 00:37, 16 October 13
Hello,

I updated it again.

Now when you get the project and type "make" it offers a new target : cpcrslib.

Code: [Select]
make

Choose target:
make displayhelp
make hello_world_using_z88dk
make hello_world_using_sdcc
make cpcrslib

This target fetches and builds cpcrslib and tells you that you can enter any example directory. Type "make" there and you get a target.dsk ready to run.

It succeeds in creating an actually runnable disk of cpcrslib example 1 :  "001 - 8x8 Chars & Small Scroll"

Here's a screenshot under arnold :

[attachimg=1]

Other examples do compile but don't work on my emulator.

Maybe the emulator is buggy (this already happened recently).

Any feedback (good or bad results) are interesting.

Visit cpcitor/cpc-dev-tool-chain · GitHub (https://github.com/cpcitor/cpc-dev-tool-chain/) for updated dependencies, verified on Debian 7, Ubuntu 12.10, 13.04
and 13.10 (mainly unrar is new, need "universe" repository enabled).

Regards.
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: cpcitor on 20:17, 16 October 13
Hello,

I updated it again, fixing some missing dependency declaration like "building cpcrslib needs sdcc".

So far example 001 works out-of-the-box.

The others require crt0_cpc and I only had e.g. 006 unexo work by adjusting "load" and "run" addresses by hand at idsk step.

It looks like when asking the compiler to link at e.g. 0x6038 and add crt0_cpc as first argument, the file actually starts at 6000. That's not written in the toolchain yet.

Regards,
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: Bruce Abbott on 08:26, 19 October 13
I installed cpc-dev into cygwin on my Windows XP PC. This is my first experience with command-line linux development, and I had a few false starts trying to get all the components installed. The main problem was that sdcc wouldn't build, and I couldn't figure out why the makefile was insisting that the tools directories didn't exist. So I removed cpc-dev and downloaded the latest version, and then it all just worked!   

Your "Hello World" compiled fine with sdcc and ran successfully on WinAPE. Of the cpcrslib demos, "004 - Music, SFX & Keyboard" wouldn't compile, while "007 - Uncrunch" compiled but just reset the emulator. The other examples compiled and ran fine.
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: cpcitor on 10:52, 19 October 13
I installed cpc-dev into cygwin on my Windows XP PC.

Thanks for trying and reporting !

This is my first experience with command-line linux development, and I had a few false starts trying to get all the components installed. The main problem was that sdcc wouldn't build, and I couldn't figure out why the makefile was insisting that the tools directories didn't exist.

You probably fetched a version before my latest commits. I tried to keep the thing independent of the directory it's in, but did not succeed at first try. It seems okay now.  :)

So I removed cpc-dev and downloaded the latest version, and then it all just worked!   

Great ! That's how it's intended to work. 8)

Your "Hello World" compiled fine with sdcc and ran successfully on WinAPE. Of the cpcrslib demos, "004 - Music, SFX & Keyboard" wouldn't compile, while "007 - Uncrunch" compiled but just reset the emulator. The other examples compiled and ran fine.

Regarding music example, the makefile checks if C source includes cpcrslib.h but not cpcwyzlib.h . It's a matter of including that in the top-level sdcc-project.Makefile. It can be done even without understanding the whole thing. The strange fact is : it worked better for you than for me.

What puzzles me is that other samples worked for you not for me. Can you go again to a sample directory, e.g. 003 and type:

Code: [Select]
make >make003.log 2>&1

Then check if the generated DSK still works, and whatever the result PM the file make003.log to me. Comparing that output with what I get will probably be useful to figure out how to have the thing work smoothly.

Same for sample 007 would be great for more comparisons.

I'll be on holiday with family for the next few weeks so may not answer quickly.  ::) I will finally answer anyway.  :)
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: cpcitor on 10:59, 19 October 13
Screenshots

Thanks to screenshot 10 I see you run the examples with load at explicit address and call.
That may explain.
I Intended to run them just with
Code: [Select]
run"filename.bin"So, if the load and/or run addresses are wrong for whatever reason (and I think they are when using a crt0 at the moment) it will crash.

Thanks again for the informative feedback !

Difficulties like this can hit any newcomer. When they are written for good in a tool, the tool takes care so that the user doesn't have to.
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: cpcitor on 23:55, 20 October 13
Thank you Bruce. Your logs confirm that there's no difference in what happens on Windows and Linux. You succeeded one more samples because you had manually overridden the wrong address calculated by my code.  ::)

Current scripts assume that load address and run address are the same as the code-loc argument given to sdcc, which is not true in general and especially with a crt0.

First, load address should be taken from hex2bin output. It should be the correct value in virtually all cases.

Regarding run address, I'm not sure it can be figured out automatically always.

Regards,
Title: SDCC-compiled hello world : success on a real CPC.
Post by: cpcitor on 23:59, 20 October 13
I've experimented 2cdt and playtzx today (from ralferoo's github, thanks ralferoo ! ), using them to transfer the sdcc hello to tape then to a real CPC 464. And it worked !
I should post a photograph.  :)

Ideally I would integrate 2cdt and playtzx as done for the others tools.
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: cpcitor on 18:03, 21 October 13
Here's the screenshot. Please pardon the mess around the machine. It's straight from the attic. The monitor is the very one I got for my birthday at the time, but I don't remember where that CPC464 comes from (it bears sign of bad use) or where my CPC464 is. But the program is tested and that's what counts.  :D

 [ You are not allowed to view attachments ]

Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: arnoldemu on 19:37, 21 October 13
First, load address should be taken from hex2bin output. It should be the correct value in virtually all cases.

Regarding run address, I'm not sure it can be figured out automatically always.
try this tool:

http://www.cpctech.org.uk/download/fileattr.zip (http://www.cpctech.org.uk/download/fileattr.zip)
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: cpcitor on 23:31, 21 October 13
Hello,
Glad that you liked the photograph of the real CPC running SDCC-compiled stuff.

try this tool:

http://www.cpctech.org.uk/download/fileattr.zip (http://www.cpctech.org.uk/download/fileattr.zip)

Thanks. Let's try that. I see a tool that takes a file as input. If the file has a valid AMSDOS header, the tool can extract start, length, end or execution address and display that as "defw &address". If the file has no header, answer is "defw &0000".

Currently I don't handle files with amsdos headers as I have no tool to create one and no real need.

Instead, I use the options of iDsk and 2cdt to create the correct header on the fly.

Also, the header for disk and for tape are different. fileattr is for disk header only, right ?
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: arnoldemu on 11:33, 22 October 13
Also, the header for disk and for tape are different. fileattr is for disk header only, right ?
Correct. I always use amsdos header. Many tools I use add one.

e.g.

pasmo --amsdos file.asm file.bin

For sdcc, I use "addhead" tool here.

http://www.cpctech.org.uk/download/addhead.zip (http://www.cpctech.org.uk/download/addhead.zip)

All my tools work with it. The header stores start, length and execution address.
The tool makes "defw" because I often do this:

fileattr -x > game_x.asm

then in my loader i put:

Code: [Select]
defb &c3
include "game_x.asm"

2cdt can also use a file with amsdos header and create the correct file.

So I think it's the best.

I think tape headers are not normally important.
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: arnoldemu on 11:34, 22 October 13
Glad that you liked the photograph of the real CPC running SDCC-compiled stuff.
Yes I liked the poor CPC464 still working hard although it has some problems :)
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: arnoldemu on 11:35, 22 October 13
A file i use on windows:

Code: [Select]
set PATH=%PATH%;c:\tools
cd lib\mylib
call make.bat
cd ..\..
cd lib\arkostrackerlib
call make.bat
cd ..\..
REM cd gfx
REM call process-gfx.bat
REM cd ..
sdasz80 -plosgff mygame_crt0.s

sdcc -c --verbose -V --nostdlib --opt-code-speed --nostdinc --no-std-crt0 -mz80 -DDISC=1 -I lib/mylib -l lib/mylib/mylib.lib -I lib/arkostrackerlib -l lib/arkostrackerlib/arkostrackerlib.lib mygame.c
if %ERRORLEVEL% NEQ 0 goto :error
sdldz80 -f custom.lk
hex2bin mygame.ihx

REM zorg only works if you use zcc to build and link
del temp\game_x.asm
del temp\game_l.asm
del temp\game_s.asm

addhead -s 0x08100 -x 0x08100 mygame.bin mygame.bin

fileattr -x mygame.bin >mygame_x.asm
fileattr -l mygame.bin  >mygame_l.asm
fileattr -s mygame.bin  >mygame_s.asm


addhead -r mygame.bin mygame.bin

pasmo --amsdos reloc.asm bin\reloc.bin

fileattr -x bin\reloc.bin >temp\game_x.asm
fileattr -l bin\reloc.bin  >temp\game_l.asm
fileattr -s bin\reloc.bin  >temp\game_s.asm

pasmo --amsdos discload_alt_new.asm bin\discload_alt_new.bin
if %ERRORLEVEL% NEQ 0 goto :error
REM disc version
addhead -r gfx\bin\loadscr.bin gfx\bin\loadscr.bin
addhead -a -t "binary" -s 49152 gfx\bin\loadscr.bin gfx\bin\loadscr.bin

cpcxfs -f -nD virus.dsk
cpcxfs virus.dsk -f -b -p bin\discload_alt_new.bin virus.bin
cpcxfs virus.dsk -f -b -p gfx\bin\loadscr.bin virus.bi1
cpcxfs virus.dsk -f -b -p bin\reloc.bin virus.bi2

pasmo --amsdos tapeload_alt.asm bin\tapeload_alt.bin
if %ERRORLEVEL% NEQ 0 goto :error

addhead -r gfx\bin\loadscr.bin gfx\bin\loadscr.bin
addhead -r mygame.bin mygame.bin

REM 2cdt -n bin\tapeload.bin -r BANGEL69 bin\cdt\bangel69_A.cdt
2cdt -n bin\tapeload_alt.bin -r "! VIRUS !" virus.cdt
2cdt -m 2 gfx\bin\loadscr.bin virus.cdt
2cdt -m 2 bin\reloc.bin virus.cdt

:error

This may help you?

On linux I often use makefiles or shell scripts.
Title: Request for comments from C developers' hints.
Post by: cpcitor on 02:02, 24 October 13
I have figured out why some samples failed, based on looking at the generated binary and symbol map.

Sample 001 works without crt0 because there's no global variable. Things are simple. Data segment has zero size. Thus main symbol happens to be at beginning of generated binary, which fits code-loc argument given to SDCC.

Other samples, e.g. 003 do have global variables.
It can still work without a crt0 by figuring out load address from output of hex2bin and run address from address of main symbol.
The Makefile can do that. I'll do it for the load address anyway.

Regarding the run address it's more complicated to do things right...

Since a crt0 introduces a fixed address in memory, it violates the DRY principle ( see http://en.wikipedia.org/wiki/Don%27t_repeat_yourself (http://en.wikipedia.org/wiki/Don%27t_repeat_yourself) ) because when user wants code in a different memory address, (s)he will have to change it in two places : SDCC argument --code-loc and crt0.

There are probably many ways to try to have things "just work" for projects using the toolchain.
* dry: compute --code-loc argument from (possibly user-provided) crt0
* dry: generated standard crt0 from (possibly user-provided) code address in project conf
* full lazy, not dry: just leave a mess and force the user to choose a memory layout and addresses
* full luxury, more dry that dry (when you say nothing you can't repeat yourself at all) : after compilation proper (but not linking) automatically compute locations to leave room below (for a possible basic loader) and above (for possible extension ROM data) with overridable defaults, generate crt0. (Can it be done without recompiling ?)
* in case of upper 16k ROM output, use a dedicated parameter set...
* Any other cases ? Cassette or Disk doesn't change the deal.

Anyone has hints ? Feedback welcome.
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: cpcitor on 02:05, 24 October 13
This may help you?

On linux I often use makefiles or shell scripts.

It already helped a little. I'm considering naming something.bin a naked binary, and something.amsdos.bin a binary with amsdos header. Not only to have make automatically figure out what to do, but also to help know at all times what a file contains.

In french we say "appeler un chat un chat", which would translate to "naming/calling 'cat' a cat".
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: Munchausen on 15:19, 24 October 13
There's a mono port of msbuild (xbuild IIRC) so it's not platform specific, but the point wasn't "You should use X not Y" but rather that trying to start something like this by dictating "You must use X because that happens to be super convenient for me" is a complete non-starter.


I didn't see anyone saying you must use anything.


It's great to have something that doesn't need msbuild/windows/mono/wine or anything like that. I use haiku, which does not have mono or wine, and most UNIX/BSD users also prefer to have something native. For these users its great, for windows there are other things available.


Or did I miss something?
Title: Look ma, no crt0! And all cpcrslib samples work.
Post by: cpcitor on 13:28, 25 October 13
Hello all,

I have pushed another update of the cpc-dev-tool-chain kit on cpcitor/cpc-dev-tool-chain · GitHub (https://github.com/cpcitor/cpc-dev-tool-chain/) .

Summary of changes:


RAM programs built using a script don't need crt0

During that work I tried to simplify crt0, to the point I suppressed it completely and things became actually easier.

This confirmed that a plain "RAM Program"[nb]"RAM/ROM program" explained in Amstrad CPC Firmware guide chapter 10 at Soft968: CPC 464/664/6128 Firmware - CPCWiki (http://cpcwiki.eu/index.php/Soft968:_CPC_464/664/6128_Firmware) .[/nb] does not actually need a crt0.

The crt0 seen in CPC context.

The crt0 everyone (H. Hansen (http://cpcrulez.fr/coding_initiation_SDCC_and_CPC.htm), Stephbb75 (http://cpcrulez.fr/coding-crossdev_sdcc-02-utilisation_de_SDCC.htm), cpcmania (http://www.cpcmania.com/Docs/Programming/Introduction_to_programming_in_SDCC_Compiling_and_testing_a_Hello_World.htm), norecess (http://www.norecess.net/sdcc-part-2---compiling-our-first-c-program.html), cpcrslib (http://code.google.com/p/cpcrslib/wiki/cpcrslibSDCC)[nb]Octoate's crt0.s for "ROM program" (https://github.com/Octoate/cpc-sdcc-rom/blob/master/src/crt0.s) is a little cleaner.[/nb]) uses in the CPC world is a simplified ("broken") version of a generic one intended for a Z80-based device that starts without OS and needs a specific memory layout at address 0 (often a ROM).

For a RAM program on the CPC, the firmware takes care already. The effect of the crt0 everyone uses is to add constraints and force the programmer to manually adjust it to be consistent with sdcc's --code-loc argument. Removing the crt0 removes the constraint.

crt0 is useful in special cases, where the programmer needs particular memory layout.

Do I need a crt0 ?

I know three cases where a crt0 is useful :


Do I need to care ?

The aim of cpc-dev-tool-chain is to take care so that you don't have to and forget all this.

Next step

I should soon reach a point when I can document how to use the toolchain for a personal project.

Expect something like :

I see some interesting future extensions like :


All feedback welcome.

Your feedback may drive the directions of development, as the suggestion to support cpcrslib did already.
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: cpcitor on 03:49, 26 October 13
Hello,

Another update pushed.

Change summary

New features:


Bugs fixed:


Cheers, :)
Title: Now with custom project tutorial.
Post by: cpcitor on 07:20, 26 October 13
Hello again,

I've updated the documentation. It now explains how to create a project on your own from scratch, then give hints at how easy it is to use cpcrslib instead of bloated stdio.

Homepage cpcitor/cpc-dev-tool-chain · GitHub (https://github.com/cpcitor/cpc-dev-tool-chain/)
Custom project tutorial https://github.com/cpcitor/cpc-dev-tool-chain/blob/master/CDTC_with_custom_project.md (https://github.com/cpcitor/cpc-dev-tool-chain/blob/master/CDTC_with_custom_project.md)

(https://github.com/cpcitor/cpc-dev-tool-chain/raw/master/cdtc_hello_works.png)

Cheers,
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: jrodriguezv on 09:23, 26 October 13
Wow! Wonderful!

I really love this project. Thanks for your job.

What do you think about adding an emulator as another tool? A great candidate could be cap32 (http://sourceforge.net/projects/caprice32/)
Title: Re: Look ma, no crt0! And all cpcrslib samples work.
Post by: ralferoo on 11:45, 26 October 13
Do I need a crt0 ?

I know three cases where a crt0 is useful :

  • As one of several ways to force the run address to a particular address. It can be done with a much shorter crt0 than the one used anyway. Without crt0 the build environment can extract address of main from symbol map (cpc-dev-tool-chain supports both).
  • You code a ROM program. crt0 is a good place to put the ROM header, as Octoate did (https://github.com/Octoate/cpc-sdcc-rom/blob/master/src/crt0.s).
  • You have lot of code, target CPC6128 and want put different part of C or ASM code in different RAM banks. You define the memory layout in crt0, assign different C/ASM source files to different memory areas.[/l][/l][/l][/l][/l][/l]
Actually, the clue to what crt0 is for is in the name - it's there to initialise the C runtime. This means to pass the correct parameters to main (probably 0,NULL for CPC), initialise the memory allocator and standard IO streams. It's often used to also clear all BSS memory to 0 and to run any _atexit hooks after main finishes.

Given that the CPC doesn't have a memory allocator in the firmware, you'd almost certainly want to provide an implementation of malloc and free and crt0 is the only safe place to do such initialisation.

Also, in a traditional C system, crt0 generally wouldn't be used to force the run address - that's usually decided at link or load time. crt0 is unique only in that the linker knows to include it by default and so it specifies the entry point and is often also placed first.
[/list]
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: jrodriguezv on 14:37, 26 October 13
I've got an error compiling last version:

+ sdcc -mz80 --no-std-crt0 -Wl-u hello.rel fillscreen.rel km_wait_key.rel --code-loc 0x4000 --data-loc 0 ..//tool/cdtc_stdio/putchar_cpc.rel -o hellosdc.ihx
?ASlink-Error-<cannot open> : "..//tool/cdtc_stdio/putchar_cpc.rel"
make: *** [hellosdc.ihx] Error 1

Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: cpcitor on 15:24, 26 October 13
Thanks for the report.

Can you manually go to the cdtc_studio directory, do "make" there and see if it then works ?
This will help me figure out what's wrong and how to fix.

Regards.
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: jrodriguezv on 16:12, 26 October 13
Yes, it works!

[jose@carallan cdtc_stdio]$ make
BINS = cdtc_stdio.bin
CDTC_ENV_FOR_2CDT = ../..//tool/2cdt/build_config.inc
CDTC_ENV_FOR_CPC_PUTCHAR = ../..//tool/cdtc_stdio/cdtc_stdio.lib
CDTC_ENV_FOR_HEX2BIN = ../..//tool/hex2bin/build_config.inc
CDTC_ENV_FOR_IDSK = ../..//tool/idsk/build_config.inc
CDTC_ENV_FOR_PLAYTZX = ../..//tool/playtzx/build_config.inc
CDTC_ENV_FOR_SDCC = ../..//tool/sdcc/build_config.inc
CDTNAME = cdtc_stdio.cdt
CODELOC = 0x4000
DSKNAME = cdtc_stdio.dsk
GENHRDS =
HDRS =
IHXS = cdtc_stdio.ihx
LDFLAGS =
RELS =  putchar_cpc.rel
SRCS =
SRSS = putchar_cpc.s
TARGETS = cdtc_stdio.dsk cdtc_stdio.bin
VOCNAME = cdtc_stdio.voc
( . ../..//tool/sdcc/build_config.inc ; set -xv ; sdasz80 -l -o -s putchar_cpc.rel putchar_cpc.s ; )
+ sdasz80 -l -o -s putchar_cpc.rel putchar_cpc.s
( . ../..//tool/sdcc/build_config.inc ; set -euxv ; sdar rc "cdtc_stdio.lib" putchar_cpc.rel ; )
+ sdar rc cdtc_stdio.lib putchar_cpc.rel

After this I've been able to compile the example.  :)
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: cpcitor on 16:30, 26 October 13
Ok, thanks. It's a missing dependency. You'll need to do the same with cpcrslib directory. I'll fix that and the tests soon.
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: jrodriguezv on 16:31, 26 October 13
OK, but I can't compile cpcrslib directory, I have errors on make all related to make examples:

../cpcrslib_SDCC/SDCC/TileMap.s:1248: Error: undefined symbol encountered during assembly
removing TileMap.rel
mak
e[1]: *** [TileMap.rel] Error 2
make[1]: Leaving directory `/home/jose/code/cpc/cpc-dev-tool-chain-master/tool/cpcrslib/cpcrslib_SDCC.buildtree'
make: *** [cpcrslib_SDCC.buildtree/.built] Error 1

Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: cpcitor on 17:36, 26 October 13
Thanks for the report.
I'll have to check what is at line 1248 of tilemap.s .
Can you post the complete make log of this part ?
E.g. in cpcrslib

make clean ; make 2>&1 | tee make.log

And post make.log content.

In future cases it can be useful to try make clean ; make then see if it fixes.
In any case it's interesting to know about it.

Regards.

Thanks.
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: jrodriguezv on 18:05, 26 October 13
Here you have the log....
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: cpcitor on 18:16, 26 October 13
Here you have the log....

Thanks. I'm trying to reproduce the problem.

I just reproduced this:

Quote
?ASlink-Error-<cannot open> : "..//tool/cdtc_stdio/putchar_cpc.rel"
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: cpcitor on 18:35, 26 October 13
?ASlink-Error-<cannot open> : "..//tool/cdtc_stdio/putchar_cpc.rel"

Just pushed an fix, this should not happen again.

../cpcrslib_SDCC/SDCC/TileMap.s:1248: Error: u undefined symbol encountered during assembly

Trying to reproduce that one...
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: cpcitor on 18:49, 26 October 13
Here you have the log....

I have fixed the dependency on cpcrslib and did not encounter that problem.

Here's the part of my build log:

Code: [Select]
+ sdasz80 -o GphStrStd.rel ../cpcrslib_SDCC/SDCC/GphStrStd.s
( . "/mypath/cpc-dev-tool-chain"/tool/sdcc/build_config.inc ; set -xv ; sdasz80 -o TileMap.rel ../cpcrslib_SDCC/SDCC/TileMap.s ; )
+ sdasz80 -o TileMap.rel ../cpcrslib_SDCC/SDCC/TileMap.s
( . "/mypath/cpc-dev-tool-chain"/tool/sdcc/build_config.inc ; set -xv ; sdar rc cpcrslib.lib cpcrslib.rel GphStr.rel Sprites.rel Keyboard.rel UnExoOpt.rel Uncrunch.rel GphStrStd.rel TileMap.rel ; )
+ sdar rc cpcrslib.lib cpcrslib.rel GphStr.rel Sprites.rel Keyboard.rel UnExoOpt.rel Uncrunch.rel GphStrStd.rel TileMap.rel

Can you download a new fresh copy of the toolchain and build the hello project again ? To see if if happens again.

Please keep the old one in case, it may be interesting for a comparison.

I generated the hello.c with these commands :

Code: [Select]
{ echo "#include <stdio.h>" ; echo "int main() { printf(\"Hello World, hello $USER.\\n\"); while (1) {} ; return 0; }" ; } >hello.c
make

{ echo "#include <cpcrslib.h>" ; echo "int main() { cpc_PrintStr(\"Hello World, hello $USER.\\n\"); while (1) {} ; return 0; }" ; } >hello.c
make

Regards,

EDIT: adjusted capitalization. It's cpc_PrintStr not cpc_printStr.
Title: Re: Look ma, no crt0! And all cpcrslib samples work.
Post by: cpcitor on 01:02, 27 October 13
Actually, the clue to what crt0 is for is in the name - it's there to initialise the C runtime. This means to pass the correct parameters to main (probably 0,NULL for CPC), initialise the memory allocator and standard IO streams. It's often used to also clear all BSS memory to 0 and to run any _atexit hooks after main finishes.

Given that the CPC doesn't have a memory allocator in the firmware, you'd almost certainly want to provide an implementation of malloc and free and crt0 is the only safe place to do such initialisation.

Also, in a traditional C system, crt0 generally wouldn't be used to force the run address - that's usually decided at link or load time. crt0 is unique only in that the linker knows to include it by default and so it specifies the entry point and is often also placed first.
[/list]

You're right in many aspects. I had to be short and specific to SDCC and the CPC.

One important thing is also to ensure global variables are initialized.

Looks like no one on the C CPC scene (even Octoate in his crt0 targeting ROM) has taken care of initialized non-const static/global variables.
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: cpcitor on 01:03, 27 October 13
New update

A new test project showing:


See result below. All initialized values should be 42 always. Without gsinit some are zero.

Without GSINIT, line 3 and 4 have value 0.

[attachimg=1]

With GSINIT, line 3 and 4 have expected value 42.

[attachimg=2]

To have them initialized I have written a short but heavily commented crt0.s .
I post a copy below, for didactic value, of c_features_test.c and crt0.s.

I'll make it a default crt0 for RAM programs. In the meantine, if you need global initialized variables just copy it in your project.

You can find the content on cpcitor/cpc-dev-tool-chain · GitHub (https://github.com/cpcitor/cpc-dev-tool-chain/) as usual.

Code: [Select]
#include <stdio.h>

// This file is used to test and clarifies what variables become.

// ## Symbols ?

// ## Symbols and global/static variables
// As expected, sdcc create a global symbol for global variables, not for static variable.
// .globl _int_initialized
// .globl _int_uninitialized
// .globl _const_int_initialized

// ## Symbols and local variables
// Local variables are allocated on the stack.
// No symbol (even a local one) is generated for a local variable.

// sdcc puts a (global or static) int uninitialized to DATA area
static int static_int_uninitialized;
int int_uninitialized;
// becomes :
// ;--------------------------------------------------------
// ; ram data
// ;--------------------------------------------------------
// .area _DATA
// _static_int_uninitialized:
// .ds 2
// _int_uninitialized::
// .ds 2

// sdcc puts a (global or static) int initialized to INITIALIZED area
static int static_int_initialized = 42;
int int_initialized = 42;
// becomes :
// ;--------------------------------------------------------
// ; ram data
// ;--------------------------------------------------------
// .area _INITIALIZED
// _static_int_initialized:
// .ds 2
// _int_initialized::
// .ds 2

// .area _CODE
// .area _INITIALIZER
// __xinit__static_int_initialized:
// .dw #0x002A
// __xinit__int_initialized:
// .dw #0x002A
// .area _CABS (ABS)

// So, for global variables to be correctly initialized, crt0 has to copy _INITIALIZER section to _INITIALIZED.



// sdcc puts a (global or static) int initialized to INITIALIZED area
static const int static_const_int_initialized = 42;
const int const_int_initialized = 42;

// _static_const_int_initialized:
// .dw #0x002A
// _const_int_initialized:
// .dw #0x002A


// SDCC refuses to compile uninitialized const int. It does not make great sense but gcc accepts.
//static const int static_const_int_uninitialized;
//const int const_int_uninitialized;





int main() {

int local_int_uninitialized;
int local_int_initialized = 42;

const int const_local_int_uninitialized;
const int const_local_int_initialized = 42;

#define PRINT_VAR(x) printf( "%d\t= " #x "\r\n", x);
#define PRINT_PTR(x) printf( "%p\t<- " #x "\r\n", &x);

#define PRINT_BOTH(x) PRINT_VAR(x); PRINT_PTR(x);

PRINT_VAR(static_int_uninitialized);
PRINT_VAR(int_uninitialized);

PRINT_VAR(static_int_initialized);
PRINT_VAR(int_initialized);

PRINT_VAR(static_const_int_initialized);
PRINT_VAR(const_int_initialized);

//PRINT_VAR(static_const_int_uninitialized);
//PRINT_VAR(const_int_uninitialized);

PRINT_VAR(local_int_uninitialized);
PRINT_VAR(local_int_initialized);
PRINT_VAR(const_local_int_uninitialized);
PRINT_VAR(const_local_int_initialized);



PRINT_PTR(static_int_uninitialized);
PRINT_PTR(int_uninitialized);

PRINT_PTR(static_int_initialized);
PRINT_PTR(int_initialized);

PRINT_PTR(static_const_int_initialized);
PRINT_PTR(const_int_initialized);

//PRINT_PTR(static_const_int_uninitialized);
//PRINT_PTR(const_int_uninitialized);

PRINT_PTR(local_int_uninitialized);
PRINT_PTR(local_int_initialized);
PRINT_PTR(const_local_int_uninitialized);
PRINT_PTR(const_local_int_initialized);

return 0;
}

Code: [Select]
;; crt0.s - A crt0 in Z80 assembler language targeting Amstrad CPC

;; Copyright (C) 2013 Stéphane Gourichon / cpcitor

;  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.
;--------------------------------------------------------------------------

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Since this will be used by CPC coders, which are usually
;; not savvy of C compiling/linking/init internals, this file
;; is abundantly commented.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; The module name appears in many compiler/linker log files,
;; so it's important to define it.

.module crt0


;; We will reference the C-level symbol "main".
;; The line below is equivalent to C-level "extern void main();"

.globl _main



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Do we need an absolutely positioned HEADER area ?
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; Short answer: no for a RAM program.

;; Most z80 crt0 start with dedicating 0x38 bytes to interrupt
        ;; vectors. This makes sense only when making an image that
        ;; starts at address 0, which is not the case for a CPC RAM
        ;; program or upper ROM program.
;; This crt0 targets a RAM program. So nothing to do at this step.


;; Creating absolutely positioned linker areas would just put
;; constraints and yield more maintenance work.

;; We can avoid that and just let the linker pack areas one
;; after the other.  So, no ".org 0x" here. The simplest thing
;; to do with SDCC's Z80 target is to set location at only one
;; place : the --code-loc option of sdcc.

;; Hence, we start with the CODE area to ensure we start at
;; the requested location.

.area _CODE

cpc_run_address::
init:
        ;; Initialise global variables, see below.
        call    gsinit
jp _main

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Do we need an _exit symbol ?
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; Short answer: not confirmed, so not done.

;; SDCC's default crt0 defines a _init symbol that does "ld a,#0 ; rst 0x08".
;; This is supposed to allow the C-level exit() function to do what people expect.
;; This won't work on the CPC.

;; We have three choices :

;; - just don't implement exit()

;; - implement it with a "ret". This would enable calling
;; "exit(value);" form main(). It has limited interest because
;; "return value;" already works (FIXME check which register
;; holds return value). Unfortunately, from another C function
;; it would just return from the current function, not exit
;; the program. So, not really useful.

;; - implement it with "rst 0x00". This should reset the CPC.

;; - record stack pointer before calling _main, put it back on
;; _exit, set the return value in register and "ret". That
;; would work if the C code has not killed the firmware RAM
;; area.

;; That last option would be useful especially when using
;; cpc-dev-tool-chain to implement some RSX extensions that
;; need to call exit().

;; Until the need is confirmed we do nothing.



;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Initialize global variables.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; Why must we care ? Else global variables are not
        ;; initialized.

;; How this happens ?

;; Compiler does not assume that compiled output can be a RAM.

;; Indeed, if all compiled data lands in a ROM so is
  ;; initialization values. Then we must copy them to RAM.

;; What SDCC does: run-time access to initialized global
;; variables is through area named _INITIALIZED (should be
;; somewhere in RAM).

;; Initial values of initialized global variables are provided
;; in another region named _INITIALIZER.


;; * "ROM program" case

;; This makes total sense if linker output lands in a ROM. The
;; only option is to copy _INITIALIZER to _INITIALIZED (modulo
;; some possible compression tricks).


;; * "RAM program" case

;; If linker output already lands in RAM, as in a CPC "RAM
        ;; program", this works also but wastes an amount of RAM equal
        ;; to the amount of initialized data.

;; We may write an external script to trick the linker to
;; allocate both area in an absolute fashion to the same
;; address. No wasted bytes, no copy.

;; Note that using unitialized global variable and
        ;; initializing them in a function does not solve: the same
        ;; amount of memory is wasted anyway, it has to be maintained
        ;; manually.

;; Using function-local variables is worse: they are accessed
        ;; through the stack which is slower (FIXME unless some SDCC
        ;; compilation tricks are used ?).

;; Conclusion

;; So far we do simple and waste some bytes, that's ok.

;; If/when need is confirmed, the trick to absolutely position
;; both area at same position may be used.  Or tell the
;; compiled that code is in RAM ? FIXME Write that to
;; sdcc-devel mailing-list.

.area   _GSINIT

.globl l__INITIALIZER
.globl s__INITIALIZED
.globl s__INITIALIZER

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
Title: C ease of use without bloat.
Post by: cpcitor on 23:41, 28 October 13
Hello,

Some news. Another update to github cpcitor/cpc-dev-tool-chain · GitHub (https://github.com/cpcitor/cpc-dev-tool-chain/) .

Can we write C without fear of bloat ?

Isn't it a bit frightening to have a 3kb executable for a hello world ? Well, that's because we used the default SDCC printf_large. Lean is good. Can we stay lean ?

Can we get this from a 203-byte binary from a simple C source ?
[attachimg=1]

Answer: yes !

Auto cherry-pick firmware routines.

It's handy to call the firmware for some simple services, at the beginning/end of a program, of when performance does not matter that much.

You wouldn't like if using a single function from C would suddenly bloat your executable, right ?

I was looking for a C to firmware interface and found Kevin's adaptation for contiki. It covers mostly text functions, and 5 graphic functions. It worked but using one function pulled the whole amsgraph or conio to the final program. I want the dev toolchain to be lean.

The trick is simple : define symbols in independent source file (unless they are obviously needed together as a chole). Define a different .module for each sourced file.

The linker will automagically pick the necessary modules but not the unneeded ones. Nice.  8)

So I packaged a few common firmware routines and adjusted the makefiles.

Code: [Select]
find .
./Makefile
./src
./src/fw_gra_line_absolute.s
./src/fw_gra_set_pen.s
./src/fw_km_wait_key.s
./src/cfwi_txt_str0_output.s
./src/fw_gra_move_absolute.s
./src/fw_scr_set_mode.s
./src/fw_km_read_char.s
./src/fw_gra_get_pen.s
./src/fw_gra_plot_absolute.s
./cdtc_project.conf
./include
./include/cfwi
./include/cfwi/cfwi.h
./include/cfwi/fw_km.h
./include/cfwi/fw_scr.h
./include/cfwi/fw_gra.h
./include/cfwi/cfwi_txt.h

It's easy to use : just #include <cfwi/cfwi.h> and you can use the functions appearing in the .h files.

For an example, the following screen

[attachimg=1]

is produced by a 203-byte executable  :) from this simple source :

Code: [Select]
#include "cfwi/cfwi.h"

void
main ()
{
{
static unsigned int x, y;

for (x = 0; x < 255; x++)
{

for (y = 0; y < 255; y++)
{
if ((x ^ y) > x)
{
fw_gra_plot_absolute(2 * x + 1, 2 * y + 1);
}
}

}
}

cfwi_txt_str0_output("Press any key to exit.");
fw_km_wait_key();
}

It could be instantaneous with optimized routines, but that's not the point, which is ease of use without bloat.
Instead it runs in seconds, because it calls GRA_PLOT_ABSOLUTE thousands of times.
It's definitely much faster than BASIC and probably leaner anyway.
QED.
Title: Re: C ease of use without bloat.
Post by: cpcitor on 23:58, 28 October 13
The linker will automagically pick the necessary modules but not the unneeded ones. Nice.  8)

This can be checked by looking at the .map file of the executable after compilation.
It lists all the symbols that are actually present in the final binary.

By the way, CFWI means C-firmware-interface.

There are other news with this update:

Compiler flags

You can set project-wide compiler flags like this in cdtc-project.conf:

Code: [Select]
CDTC_ROOT=(automatically set by new-sdcc-project.sh)
CFLAGS=--fomit-frame-pointer
PROJNAME=004Music
CODELOC=0x4000

I could probably support per-file compiler flags if requested.

Omit frame pointer ?

By default SDCC maintains IX synchronized with SP. It's a little more work but allows to fetch and store local variables more easily.

With --fomit-frame-pointer, SDCC uses directly SP when appropriate, or sets up IY temporarily.

Code can be shorter or longer depending on its complexity (local compitation or passing many args to functions).

I don't use it so far.

Malloc works

I have seed that by default, sdcc provides a working malloc implementation with a 1k heap. So, malloc is already working... for small needs. For bigger needs, one should copy sdcc's _heap.c and for example add to CFLAGS:  "-D HEAP_SIZE=2048"

Local dependencies not fully done

Inter-file dependencies are so far not computed.
In practice it means that changing cfwi does not trigger a recompute of a project that depends on it.
In practice you can force a recompile by touching or doing a trivial change to any .c or .s file in the project directory.

I'll probably follow Advanced Auto-Dependency Generation (http://make.paulandlesley.org/autodep.html) so that you don't have to.

As always, feedback welcome.

Regards,
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: Bruce Abbott on 04:03, 29 October 13
Quote
With --fomit-frame-pointer, SDCC uses directly SP when appropriate, or sets up IY temporarily.
You can also use --fno-omit-frame-pointer to force using the IX register exclusively.

I examined the results of both options with a small test function:-
Code: [Select]
unsigned char test(unsigned char x){
    unsigned char y;
    y = x + 1;
    x = y - 1;
    return x;
}

With --fomit-frame-pointer it used both IY and HL to access variables on the stack...
Code: [Select]
_test: ; --fomit-frame-pointer
;code.c:99: y = x + 1;
    ld    iy,#2
    add    iy,sp
    ld    a,0 (iy)
    inc    a
;code.c:100: x = y - 1;
    ld    hl,#2
    add    hl,sp
    add    a,#0xFF
    ld    (hl),a
;code.c:101: return x;
    ld    l,0 (iy)
    ret

With --fno-omit-frame-pointer it used IX...
Code: [Select]
_test: ; --fno-omit-frame-pointer
    push    ix
    ld    ix,#0
    add    ix,sp
;code.c:99: y = x + 1;
    ld    a,4 (ix)
    inc    a
;code.c:100: x = y - 1;
    add    a,#0xFF
;code.c:101: return x;
    ld    4 (ix), a
    ld    l, a
    pop    ix
    ret

I have been trying to get demo 004 (004 - Music, SFX & Keyboard) to work properly. It would play the music and sound effects OK, but the ball sprite just flickered. Pressing an arrow key to change the music either didn't work or crashed.

Compilation was very slow (up to 5 minutes) making debugging a pain, apparently related to the external references in calls to cpc_WyzInitPlayer(). I fixed that by reducing --max-allocs-per-node to 100.

I found out that SDCC normally uses the IX register to access variables on the stack, so it must be preserved across function calls. However, several functions in cpcrslib.lib and cpcwyzlib.lib (eg. _cpc_PrintStr, _cpc_WyzInitPlayer) modify the IX register without saving and restoring it, resulting in the main program losing track of its variables!

ETA:  --fomit-frame-pointer is the answer, as it forces the compiler to avoid the IX register. Music demo is now working 100%!
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: cpcitor on 17:19, 29 October 13
You can also use --fno-omit-frame-pointer to force using the IX register exclusively.

I have been trying to get demo 004 (004 - Music, SFX & Keyboard) to work properly. It would play the music and sound effects OK, but the ball sprite just flickered. Pressing an arrow key to change the music either didn't work or crashed.

I saw this, too. Also sample 3 has last line of bottom sprite shifted to the right when compiled without omit-frame-pointer.

Compilation was very slow (up to 5 minutes) making debugging a pain, apparently related to the external references in calls to cpc_WyzInitPlayer(). I fixed that by reducing --max-allocs-per-node to 100.

I noticed that this sample only takes eons to compile and suspected a bug in SDCC.
How did you figure out that it's related to external references ?

It's that part that takes a long time to compile:

Code: [Select]
sdcc -mz80 -I/mypath/cpc-dev-tool-chain/cpclib/cpcrslib/cpcrslib_SDCC.installtree/include --fomit-frame-pointer -c code.c

I found out that SDCC normally uses the IX register to access variables on the stack, so it must be preserved across function calls. However, several functions in cpcrslib.lib and cpcwyzlib.lib (eg. _cpc_PrintStr, _cpc_WyzInitPlayer) modify the IX register without saving and restoring it, resulting in the main program losing track of its variables!

ETA:  --fomit-frame-pointer is the answer, as it forces the compiler to avoid the IX register. Music demo is now working 100%!

Congratulations for finding this.

Actually, --fomit-frame-pointer is now default (since yesterday 14:27 UTC) for samples 3 and 4. It did fix sample 3 but not 4 for me.  :-[

This shows that several contracts are possible between C and ASM code and they should not be mixed without care.


How did you figure out that slow compilation is related to external references ?

Cheers,  :)
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: Bruce Abbott on 00:23, 30 October 13
How did you figure out that slow compilation is related to external references ?
Actually it's a red herring. The 'slow' lines all included functions taking externally defined variables which just 'happened' to be arrays. I did some more investigation  and found out this was not a coincidence. Bringing the array definitions into the main code made no difference, but changing them from arrays to plain ints/chars cut compilation time from 167 seconds to 45 seconds. 

In this case 'optimization' of arrays seems to be a complete waste of time, because the code generated was identical. However I don't think kludging the source code is the answer. IMO the best solution is to simply apply --max-allocs-per-node with a small value.     
Title: cpc-dev-tool-chain updated
Post by: cpcitor on 23:40, 29 December 14
Hello,

Summary: cpc-dev-tool-chain updated

I'm working again on a CPC project.
During that project I've hit bugs in iDSK and changed the workflow accordingly.
Since everything is scripted in cpc-dev-tool-chain, I updated it so that all users can benefit.

Here's a summary of recent changes:

* now using SDCC 3.4.0 instead of 3.3.0
* don't use iDSK by default but use Arnoldemu's addhead (to add a AMSDOS header to plain files) and cpcxfs (to put files into a DSK image). iDSK still available with make PREFER_IDSK_OVER_CPCXFS=1
* various fixes (make clean infinite loop, missing dependencies causing some files to not be rebuilt)
* works on Ubuntu 14.04

Work in progress (not really visible yet):
* work in progress on some more flexibility, allowing projects to refer to source tree in other locations. The benefit will be to compile and run from the same C source trees some cpc project and some test/debug code that calls the same routines. Allows to have full benefit of modern development environment, run test suite, etc.
* work in progress on some more flexibility, allowing to generate one DSK containing files from several targets

Happy new year !  :)
Title: Re: cpc-dev-tool-chain updated
Post by: cpcitor on 13:43, 08 January 15
Hello,

Summary: cpc-dev-tool-chain updated

Updated again. Mostly some new C function to call firmware.  :)
It looks like the ASM wrappers to call firmware function from C can be generated from a decorated C-level prototype.  I might later make some wrapper generator.  The benefit would be to cover all firmware calls, that would be a problem solved once and for all.

Anyway, quick changelog:

cfwi.lib wasn't remade as needed. Quick fix. I should rework all this.
Added more firmware calls: fw_scr_set_border fw_scr_set_ink
Added more firmware calls: fw_gra_set_paper fw_gra_get_paper fw_gra_wr_char fw_gra_win_width fw_gra_win_height
Add more keyboard handling routines: fw_km_read_char, fw_km_read_key, fw_km_wait_char, fw_km_wait_key
Add access to firmware routine KL TIME PLEASE.


Github repository: cpcitor/cpc-dev-tool-chain · GitHub (https://github.com/cpcitor/cpc-dev-tool-chain)

As an example, here's a slightly simplified source of the function cf_platform_init(), first function called by main(). As you can see, I favor source readability/maintainability and make sure other aspects (fast code, short code, etc) are good enough, and they are so far.

Code: [Select]
#include "platform.h"
#include "stdlib.h"

#include <cfwi/cfwi.h>

enum { ink_count = 16 };
const uint8_t const inks[ink_count] = { 0, 26, 6, 24, 18, 20, 2, 8, 15, 13, 3, 12, 9, 10, 1, 4 };

void cf_platform_init()
{
        fw_scr_initialise();
        fw_scr_set_mode( 0 );

        {
                uint8_t i;

                for ( i = 0; i < ink_count; i++ )
                {
                        uint8_t color = inks[i];
                        fw_scr_set_ink( i, color, color );
                }

                fw_scr_set_border( 0, 0 );
        }

        {
                long unsigned int cpctime = fw_kl_time_please();
                srand( cpctime );
        }

}
Title: Re: cpc-dev-tool-chain updated
Post by: cpcitor on 21:21, 07 December 17
Updated again. Mostly some new C function to call firmware.  :)

TL;DR: cpc-dev-tool-chain (https://github.com/cpcitor/cpc-dev-tool-chain) is updated again, covering each time more of the CPC firmware, offering a  :) lean, clean, readable, C-based API to program for the CPC, while leaving you free for all asm-level hacks and whatever you want.  ;)

Thanks

Thanks to Kevin Thacker for the scanned+OCRed firmware book!

What's this?

cpc-dev-tool-chain (https://github.com/cpcitor/cpc-dev-tool-chain) is a development environment targeting the Amstrad CPC platform. The pitch: it works on a modern machine and automates all the step to build for the CPC: fetching compilers and other tools, building your projects, right to the DSK or CDT file.

If you know CPC BASIC and modern C, you'll feel right at home!

cpc-dev-tool-chain (https://github.com/cpcitor/cpc-dev-tool-chain) was key inspiration in the creation of the nice cpctelera (https://github.com/lronaldo/cpctelera) which has put lots of efforts on optimized routines for 2D games, especially platform games.

Update

Most updates were driven by the development of color-flood-for-amstrad-cpc (https://github.com/cpcitor/color-flood-for-amstrad-cpc) game.  The focus was to exercise a rich part of C. In that context, the simplest way to have something fun enough was to call firmware for IO.  I confirm SDCC is a solid C compiler.

Summarising a number of updates since then:

* Slightly better Cygwin compatibility (but not tested recently, might be broken now?)
* Updated third-party tools: cpcrslib, 2cdt, SDCC, z88dk
* More firmware calls available from C!
* Install documentation
* Improved SDCC compile parameters
* Sort module names (which match C source file names) to allow developer to choose symbol order. In practice, if the C source file containing main() is called e.g. 00_main.c, then main() will in most cases be the first symbol in the binary, and thus the entry point (but if you use initialised global variables, you have to use a crt0, which will be selected as entry point and put first).
* Updated test/variable_storage_class_test which is also about when you need a crt0.
* Rework project configuration: no more need to store machine-dependent absolute path names in version-controlled files!
* Rework project configuration: use cdtc-project-setup, it will also update existing project to match new behaviour.
* Generated Makefile are better documented and explain how you can customise build parameters.
* Setup time: don't compile useless parts of SDCC
* Fix buggy wrapper to TXT SET CURSOR.
* Refined types, use meaningful types, e.g. unsigned char when it is really a character, vs uint8_t when it's really an integer.
* Verbose download of SDCC (since it's a bit long).
* Ability to resume SDCC download if interrupted (since it's a bit long).
* Various fixes and improvements of user-project Makefile logic.
* Add make au to generate audio files in .au format.
* Possibility to edit text files locally without regards to line feed, and have them converted to CPC-compliant ASCII files.

Next

* Cover more firmware calls.
* Better project management (e.g. some way to express which source files contribute to which generated file, which go to DSK, to tape in which order etc)?
* Just ask what you think?

Stats

Here's a count of firmware calls, grouped by pack/prefix, that are new or were adjusted somehow:


      2 fw_byte
      5 fw_gra
     20 fw_km
     10 fw_txt


which bring the total count of all firmware calls, grouped by pack/prefix, listed in cfwi:


      4 fw_cas
     19 fw_gra
      1 fw_jre
      4 fw_kl
     40 fw_km
      7 fw_lkjb
      2 fw_mc
      7 fw_scr
      2 fw_sound
     47 fw_txt



Here's a list of firmware calls that are new or were adjusted somehow:

Code: [Select]
fw_gra_line_relative(int x, int y);
fw_gra_move_relative(int x, int y);
fw_gra_plot_relative(int x, int y);
fw_gra_test_absolute(int x, int y);
fw_gra_test_relative(int x, int y);
fw_km_char_return (unsigned char c) __z88dk_fastcall;
fw_km_exp_buffer(unsigned char *buffer, uint16_t buffer_bytecount);
fw_km_get_control(uint8_t key_number) __z88dk_fastcall;
fw_km_get_delay();
fw_km_get_expand(uint8_t token, uint8_t char_number);
fw_km_get_joystick(void);
fw_km_get_shift(uint8_t key_number) __z88dk_fastcall;
fw_km_get_state(void);
fw_km_get_translate(uint8_t key_number) __z88dk_fastcall;
fw_km_read_char (void);
fw_km_read_key (void);
fw_km_set_control(uint8_t key_number, uint8_t new_translation) __z88dk_fastcall;
fw_km_set_delay(uint8_t startup_delay, uint8_t repeat_speed);
fw_km_set_expand(uint8_t token, uint8_t string_length, unsigned char* string);
fw_km_set_repeat(uint8_t key_number, enum fw_byte_all_or_nothing repeat_allowed) __z88dk_fastcall;
fw_km_set_shift(uint8_t key_number, uint8_t new_translation) __z88dk_fastcall;
fw_km_set_translate(uint8_t key_number, uint8_t new_translation) __z88dk_fastcall;
fw_km_test_key(uint8_t key_number) __z88dk_fastcall;
fw_km_wait_char (void);
fw_km_wait_key (void);
fw_txt_clear_window();
fw_txt_output(unsigned char c);
fw_txt_set_column(int8_t column);
fw_txt_set_cursor(int8_t row, int8_t column);
fw_txt_set_m_table(void *buffer, bool disable, uint8_t lowest_affected_character);
fw_txt_set_paper(uint8_t p);
fw_txt_set_pen(uint8_t p);
fw_txt_set_row(int8_t row);
fw_txt_win_enable(unsigned char left, unsigned char right, unsigned char top, unsigned char bottom);
fw_txt_wr_char(unsigned char c);
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: Takis Kalatzis on 16:43, 08 December 17
Regarding Cygwin, I have tried doing a clean install today and unfortunately all 3 make commands described in the documentation fail.


hello_world_using_zk88d : says that Modern::Perl is a prerequisite


hello_world_using_sdcc, cpcrslib : WARNING: `makeinfo' is missing on your system.  You should only need it if
         you modified a `.texi' or `.texinfo' file, or any other file
         indirectly affecting the aspect of the manual.  The spurious
         call might also be the consequence of using a buggy `make' (AIX,
         DU, IRIX).  You might want to install the `Texinfo' package or
         the `GNU make' package.  Grab either from any GNU archive site.


Any advice?
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: cpcitor on 17:29, 08 December 17
Thank you Takis for trying and reporting.

What's your operating system? What version of cygwin?

Thanks.
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: cpcitor on 20:25, 08 December 17
Regarding Cygwin, I have tried doing a clean install today and unfortunately all 3 make commands described in the documentation fail.


hello_world_using_zk88d : says that Modern::Perl is a prerequisite


hello_world_using_sdcc, cpcrslib : WARNING: `makeinfo' is missing on your system.  You should only need it if
         you modified a `.texi' or `.texinfo' file, or any other file
         indirectly affecting the aspect of the manual.  The spurious
         call might also be the consequence of using a buggy `make' (AIX,
         DU, IRIX).  You might want to install the `Texinfo' package or
         the `GNU make' package.  Grab either from any GNU archive site.


Any advice?

Reproduced both problems.

Regarding z88dk

It looks like cygwin's perl is just plain too old. That may be tough to fix.

Furthermore, z88dk is not a priority target at the moment.

Z88DK is mostly a target in itself, to provide a common ground for portable code between hardware platforms. With z88dk one typically doesn't target CPC with all its benefits, one writes for z88dk with the common features. That's the spirit of z88dk.

Besides, z88dk now uses SDCC internally, actually a SDCC version which is tuned for the Z80 and uses both register sets. The expected benefit: is shorter and/or faster code in some conditions. The trouble is: this is incompatible with CPC firmware unless you disable firmware and run without it. They are also working on a "firmware interposer" which saves alternate register set on each firmware call, on interrupts, by patching the jump block in first bytes of RAM. But even that is difficult. All in all, meeting cygwin's old perl and z88dk in a state of flux doesn't fit well.

Regarding makeinfo

Looks like makeinfo isn't needed to run the software, only to rebuild documentation in some cases. Actually only the documentation of the bfd tools which isn't currently used.

Try to add -k to your make commands. It should at least build the rest of what it cans.

Looking for a fix.
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: cpcitor on 22:09, 08 December 17
hello_world_using_zk88dk

hello_world_using_sdcc, cpcrslib

Any advice?

Yes, we have a fix!

The fix is in cygwin to add package texinfo.

For maximum reproducibility, you may want to start over with a fresh clone of the git repository.

If the download and/or build steps are too long, you can fix with your current copy, but you have to remove the file tool/sdcc/sdcc_srctree.ref to trigger a full recompile of SDCC. It will reused the cached tar.bz2 archive and thus won't need to redownload the whole thing.

I have updated the documentation. Now it tells:

Quote
make hello_world_using_sdcc-all builds hello_world_using_sdcc/hellosdc.dsk

make cpcrslib-all builds a number of DSK files in cpclib/cpcrslib/cpcrslib-master/examples/*/*.dsk

See https://github.com/cpcitor/cpc-dev-tool-chain/blob/master/documentation/how_to_install.md

Please tell me the option you choose (starting from scratch or only rebuilding sdcc) and if it works well. It worked here.

Title: One more thing...
Post by: cpcitor on 00:04, 09 December 17
I forgot to add:

* Wrappers will now use Z88DK fastcall convention when applicable (new ones do already, not reviewed all existing wrappers yet). This makes shorter and faster wrapper code (though the difference in speed will be small since firmware call imply context switching logic which is longer than the wrapper anyway).
* Fixed cygwin compatibility (thanks Takis for reporting).

Pushed new version with somehow improved messages. Consider:

Code: [Select]
git rebase
and perhaps

Code: [Select]
git reset --hard
if you have some unwanted local changes, to clear them.
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: cpcitor on 13:20, 14 December 17
Hello.

Just pushed another update.  Now covering about half the firmware calls.  Nearly all KM (keyboard, including key repeat, redefine, shortcuts like Ctrl-Return) and TXT (write text, text windows, copy, cursor) now available to C programs!

Some are not tested, yet the most important ones are successfully used in https://github.com/cpcitor/color-flood-for-amstrad-cpc .

Now some statistics:

[attachimg=1]

Added those calls:

Code: [Select]
uint16_t fw_km_read_char (void);
enum fw_byte_all_or_nothing fw_km_exp_buffer(unsigned char *buffer, uint16_t buffer_bytecount);
enum fw_byte_all_or_nothing fw_km_get_repeat(uint8_t key_number) __z88dk_fastcall;
uint16_t fw_km_get_delay(void);
void fw_txt_output(unsigned char c) __z88dk_fastcall;
void fw_txt_wr_char(unsigned char c) __z88dk_fastcall;
uint16_t fw_txt_rd_char(void);
void fw_txt_set_graphic(bool enable) __z88dk_fastcall;
void fw_txt_win_enable(uint8_t left, uint8_t right, uint8_t top, uint8_t bottom);
uint32_t fw_txt_get_window(void);
void fw_txt_clear_window(void);
void fw_txt_set_column(int8_t column) __z88dk_fastcall;
void fw_txt_set_row(int8_t row) __z88dk_fastcall;
void fw_txt_set_cursor(int8_t row, int8_t column);
void fw_txt_set_cursor__fastcall(int16_t colum8h_row8l) __z88dk_fastcall;
uint32_t fw_txt_get_cursor();
uint32_t fw_txt_validate(void);
void fw_txt_set_pen(uint8_t p) __z88dk_fastcall;
uint8_t fw_txt_get_pen(void);
void fw_txt_set_paper(uint8_t p) __z88dk_fastcall;
uint8_t fw_txt_get_paper(void);
void fw_txt_inverse(void);
void fw_txt_set_back(uint8_t is_transparent) __z88dk_fastcall;
uint8_t fw_txt_get_back(void);
typedef uint8_t fw_txt_character_matrix_t[8];
enum fw_byte_all_or_nothing fw_txt_set_matrix(uint8_t character, fw_txt_character_matrix_t *matrix);
uint32_t fw_txt_set_m_table(fw_txt_character_matrix_t *buffer, bool disable, uint8_t lowest_affected_character);
uint32_t fw_txt_get_m_table();
typedef struct fw_txt_control_code_entry_t fw_txt_control_code_table_t[fw_txt_control_code_count];
uint8_t fw_txt_str_select();
void fw_txt_swap_streams(uint8_t stream1, uint8_t stream2);
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: Takis Kalatzis on 16:35, 14 December 17
Hi, tried again with Cygwin for Windows 7. Cygwin version is the latest. Added texinfo package, performed a git rebase and deleted [size=0px]tool/sdcc/sdcc_srctree.ref[/size]


Both targets now fail on cpcxfs compilation :



make[4]: Entering directory '/home/Takis/cpc-dev-tool-chain/tool/cpcxfs/cpcxfs/src'
gcc -Wall -O3 -DLINUX=1 -DDOS=0 match.o tools.o fs.o ui.o cpcfs.o readdef.o unix.o -o cpcxfs  -lncurses
match.o: file not recognized: File format not recognized
collect2: error: ld returned 1 exit status
make[4]: *** [makefile.lnx:59: cpcxfs] Error 1
make[4]: Leaving directory '/home/Takis/cpc-dev-tool-chain/tool/cpcxfs/cpcxfs/src'



Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: cpcitor on 17:29, 14 December 17
Hi, tried again with Cygwin for Windows 7. Cygwin version is the latest. Added texinfo package, performed a git rebase and deleted [size=0px]tool/sdcc/sdcc_srctree.ref[/size]


Both targets now fail on cpcxfs compilation :



make[4]: Entering directory '/home/Takis/cpc-dev-tool-chain/tool/cpcxfs/cpcxfs/src'
gcc -Wall -O3 -DLINUX=1 -DDOS=0 match.o tools.o fs.o ui.o cpcfs.o readdef.o unix.o -o cpcxfs  -lncurses
match.o: file not recognized: File format not recognized
collect2: error: ld returned 1 exit status
make[4]: *** [makefile.lnx:59: cpcxfs] Error 1
make[4]: Leaving directory '/home/Takis/cpc-dev-tool-chain/tool/cpcxfs/cpcxfs/src'

I had a strange experience with cpcxfs while testing on Win10 recently.
At first, cpcfxs did not compile. Then it compiled fine.
But the message was different.

Code includes provision to use iDSK instead of cpcxfs.
Can you try this?

Code: [Select]
cd hello_world_using_sdcc ; make PREFER_IDSK_OVER_CPCXFS=1 dsk

Cool, You wrote at 16:35 and I reply to you at 16:30.
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: Takis Kalatzis on 11:58, 15 December 17
The last command you suggested failed with :



+ iDSK hellosdc.dsk.tmp -n -i hellosdc.bin -e 4000 -c 4000 -t 1
[size=78%]/bin/bash: line 13: /home/Takis/cpc-dev-tool-chain/tool/idsk/iDSK.0.13/iDSK/src/iDSK: cannot execute binary file: Exec format error[/size]make: *** [..//sdcc-project.Makefile:209: hellosdc.dsk] Error 126
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: cpcitor on 20:32, 17 December 17
This is strange.  Both your last error messages imply corrupted files.
Is the underlying system clean?

I have to query for a few informations.

* Version of the Operating System. 32 or 64bits?
* Version of cygwin? 32 or 64bits?
* Can you PM the corrupted files in a ZIP to me, like below?

Code: [Select]
cd /home/Takis/cpc-dev-tool-chain/
tar zcvf corruptedfiles.tar.gz tool/idsk/iDSK.0.13/iDSK/src/iDSK tool/cpcxfs/cpcxfs/src/match.o
explorer . &

... then send corruptedfiles.tar.gz?

I'll try to see what's wrong with them.

Then, what happens if you delete the files then run make again?

Code: [Select]
cd /home/Takis/cpc-dev-tool-chain/
rm -v tool/idsk/iDSK.0.13/iDSK/src/iDSK tool/cpcxfs/cpcxfs/src/match.o
make hello_world_using_sdcc-all

Thanks!
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: cpcitor on 23:00, 20 December 17
Another update. Now fully covering GRA firmware pack jump block!

* A number of functions were changed to __z88dk_fastcall (and wrapper adjusted).
* A number of wrappers were shortened/simplified.

For coverage statistics and details have a look at: https://rawgit.com/cpcitor/cpc-dev-tool-chain/master/cpclib/cfwi/coverage.html

Here's a list of affected functions (generated from git log output):

Code: [Select]
void fw_gra_move_absolute(int16_t x, int16_t y);
void fw_gra_move_absolute__fastcall(uint32_t fw_gra_x_y_coordinates_t_asint) __z88dk_fastcall;
void fw_gra_move_relative(int16_t x, int16_t y);
void fw_gra_move_relative__fastcall(uint32_t fw_gra_x_y_coordinates_t_asint) __z88dk_fastcall;
uint32_t fw_gra_ask_cursor(void);
void fw_gra_set_origin(int16_t x, int16_t y);
void fw_gra_set_origin__fastcall(uint32_t fw_gra_x_y_coordinates_t_asint) __z88dk_fastcall;
uint32_t fw_gra_get_origin(void);
void fw_gra_win_width(int16_t x1, int16_t x2);
void fw_gra_win_width__fastcall(int32_t fw_gra_x_x_coordinates_t_asint) __z88dk_fastcall;
void fw_gra_win_height(int16_t y1, int16_t y2);
void fw_gra_win_height__fastcall(int32_t fw_gra_y_y_coordinates_t_asint) __z88dk_fastcall;
uint32_t fw_gra_get_w_width();
uint32_t fw_gra_get_w_height();
void fw_gra_set_pen(uint8_t pencolor) __z88dk_fastcall;
uint8_t fw_gra_get_pen(void);
void fw_gra_set_paper(uint8_t papercolor) __z88dk_fastcall;
uint8_t fw_gra_get_paper(void);
void fw_gra_plot_absolute(int16_t x, int16_t y);
void fw_gra_plot_absolute__fastcall(uint32_t fw_gra_x_y_coordinates_t_asint) __z88dk_fastcall;
void fw_gra_plot_relative(int16_t x, int16_t y);
void fw_gra_plot_relative__fastcall(uint32_t fw_gra_x_y_coordinates_t_asint) __z88dk_fastcall;
void fw_gra_test_absolute(int16_t x, int16_t y);
void fw_gra_test_absolute__fastcall(uint32_t fw_gra_x_y_coordinates_t_asint) __z88dk_fastcall;
void fw_gra_test_relative(int16_t x, int16_t y);
void fw_gra_test_relative__fastcall(uint32_t fw_gra_x_y_coordinates_t_asint) __z88dk_fastcall;
void fw_gra_line_absolute(int16_t x, int16_t y);
void fw_gra_line_absolute__fastcall(uint32_t fw_gra_x_y_coordinates_t_asint) __z88dk_fastcall;
void fw_gra_line_relative(int16_t x, int16_t y);
void fw_gra_line_relative__fastcall(uint32_t fw_gra_x_y_coordinates_t_asint) __z88dk_fastcall;
void fw_gra_wr_char(char character) __z88dk_fastcall;
void fw_gra_default(void);
long int fw_kl_time_please(void);
unsigned char fw_km_wait_char(void);
uint16_t fw_km_read_char(void);
void fw_km_char_return(unsigned char c) __z88dk_fastcall;
unsigned char fw_km_wait_key(void);
uint16_t fw_km_read_key(void);
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: cpcitor on 12:47, 26 December 17
The last command you suggested failed with :
cannot execute binary file: Exec format error

Cf my previous answer, is that reproducible, can you send me files so that I check if they are indeed corrupted?

CPCTelera mentions in its troubleshooting section specific things that happens with Windows, and workarounds:
Quote
    Antivirus and scanning software.  This kind of software is causing random issues that cause Cygwin and CPCtelera not to operate properly.  Common problems include failing to compile and/or execute programs, privilege problems on executing programs and random crashes of Cygwin.  If you experience this problems, try disabling your antivirus or scanning software.  Once being sure that this is the reason for your problems, you may want to configure your software not to interfere with Cygwin.
    Windows 8/10 privilege problems.  Under some unclarified circumstances, some users have privilege problems executing Cygwin sofware, and that affects CPCtelera.  In this cases, the most common workaround is launching Cygwin terminal with administrator privileges.
    Windows 8/10 executable conflicts.  Some users experience compilation or execution problems due to other Windows being using other software installed outside cygwin.  This usually happens with MinWG (gcc, g++), SDCC and git, but may happen with other software aswell.  On some installations, Windows PATH variable gives priority to previously installed software.  So, when compiling with gcc, sdcc or using git, problems happen due to Windows version of the software being executed.  In this cases, please check Windows PATH variable and adjust it accordingly.

CPCtelera Reference Manual - Troubleshooting (http://file:///org/gourichon/localdata/SG/projects/retrocomputing/code/cpctelera/cpctelera/docs/files/readme-txt.html#Troubleshooting)

It works here, so I can't guess what's wrong.
I'm willing to help but your feedback is needed. Thanks!
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: cpcitor on 18:44, 26 December 17
Another update. Now fully covering GRA firmware pack jump block!

Another update with double focus:

1. Steps towards making it easier to make and publish projects using cpc-dev-tool-chain.
    * Simplified bootstrap of 3rd party projects. For example, color-flood-for-amstrad-cpc (https://github.com/cpcitor/color-flood-for-amstrad-cpc) can be compiled with just git clone ; configure ; make (https://github.com/cpcitor/color-flood-for-amstrad-cpc)
    * More planned on https://github.com/cpcitor/cpc-dev-tool-chain/blob/master/documentation-for-maintainers/third_party_projects_usig_cdtc.md

2. For the record, the benefit of the firmware interface is to easily get firmware benefits with comfort of C, type safety, short C source code, short generated ASM code.
* cfwi now cover MC pack.
    * MC SCREEN OFFSET for firmware-assisted hardware scrolling.
    * MC CLEAR INKS Set all inks to background like BASIC does during e.g. MODE.
    * MC SET INKS Set all inks from a table. Both shorter C and ASM code!
    * MC SEND PRINTER Can be very useful for CPC code in emulator to send detailed debug log to host OS (or for real CPC to send to real printer, if that still exists ;-). I'm considering using this for unit tests.

3. (Yes, 3 for the price of 2 ;-). C header files include official documentation from Amstrad books.  When C-level wrapper needs any explanation, these are given with C-level example code.

List of affected C-level functions:

Code: [Select]
void fw_mc_boot_program(void *loader) __z88dk_fastcall;
void fw_mc_start_program(uint8_t rom_selection, void *entry);
void fw_mc_set_mode(uint8_t mode) __z88dk_fastcall;
void fw_mc_screen_offset(uint8_t screen_base, uint16_t screen_offset);
void fw_mc_clear_inks16(ink_vector16 *ink_vector) __z88dk_fastcall;
void fw_mc_clear_inks4(ink_vector4 *ink_vector) __z88dk_fastcall;
void fw_mc_clear_inks2(ink_vector2 *ink_vector) __z88dk_fastcall;
void fw_mc_clear_inks1(ink_vector1 *ink_vector) __z88dk_fastcall;
void fw_mc_set_inks(ink_vector16 *ink_vector) __z88dk_fastcall;
void fw_mc_print_char(unsigned char char_to_send_7bits) __z88dk_fastcall;
uint8_t fw_mc_busy_printer(void);
void fw_mc_send_printer(unsigned char char_to_send_7bits) __z88dk_fastcall;
void fw_mc_sound_register(uint8_t register_number, uint8_t data);
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: cpcitor on 22:29, 27 December 17
cpc-dev-tool-chain updated again.

* To allow SDCC to better optimize register allocation and avoid unnecessary register PUSH/POP, I've started to add __preserves_regs type annotation on C prototypes in cpc-dev-tool-chain/cpclib/cfwi/include/cfwi at master · cpcitor/cpc-dev-tool-chain (https://github.com/cpcitor/cpc-dev-tool-chain/tree/master/cpclib/cfwi/include/cfwi).
* Improved generation of HTML documentation. Now generated both from official documentation (OCR'ed by @Arnoldemu) and .h files and ASM source. Reports all firmware calls from Soft968 section 15, shows which are implemented or not, the variants. Nice HTML tables with a bit of CSS styling.
* The script that generated documentation also performs more detailed sanity checks, which spotted some inconsistencies.
* Fixed some inconsistencies detected by the documentation script.
* Some actual documentation fixes.

Coverage up to 57% !  8)
Nice coverage report: Firmware coverage in cpc-dev-tool-chain's CFWI (C-firmware interface) (https://cdn.rawgit.com/cpcitor/cpc-dev-tool-chain/master/cpclib/cfwi/coverage.html)

Regarding __preserves_regs:

I did only a quick test (without a high max-alloc-per-node).
Not a big deal but it did reduce code size somehow, while things still work.  Peeking at ASM code, I saw indeed at least an instance where useless PUSH/POP pair disappeared.
When several firmware calls are chained, the optimization can be defeated by one specific firmware call that needs the PUSH/POP pair again, which shows that SDCC still does its job.
It also looks like it causes no-overall-effect changes in where SDCC stores some registers via IX.
All in all, only good points.
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: cpcitor on 00:16, 13 February 20
Heya all!

TL;DR: work-in-progress on improvements in cpcitor/cpc-dev-tool-chain (https://github.com/cpcitor/cpc-dev-tool-chain) to reduce code repetition, program CRTC easily from C, initial support for 2D sprites etc.

I'm working on yet another production for the CPC.

cpcitor/cpc-dev-tool-chain (https://github.com/cpcitor/cpc-dev-tool-chain) did support cpcrslib before cpctelera was forked from it, but 2D sprites was not my focus.

Another production is on its way. This one uses non-standard CPC definition (256x256 like Arkanoid) and features 2D sprites with a routine compatible with this mode.

Some work in progress include:

* generic facility to export ASM-defined values to C (#define for integer values, and when value represents data in memory, a macro to use C pointers with proper C type to get the compiler help you). Allows to apply the DRY principle: don't repeat information in many places. Make code shorter, cleaner, more resilient to changes, reduces development complexity and time.
* Short generic routines to set CRTC to any definition (width<=504 pixels, height<=280). Callable from C or ASM. Compile-time sanity check: abort compilation if values are incompatible with 16k screen. It use the feature above, so C or ASM code can use variables representing CRTC registers. More DRY principle!
* a program to convert PNG images to sprite data of any dimensions (width has to be integral number of bytes, rectangular shape, no transparency so far). Supports mode 0, 1, 2. Many convenient command-line options. For example, reads the palette from file or command line, sensible defaults, sanity checks to ensure generated data makes sense and helps you get the job done even if the program that generates the PNGs is sloppy about the palette (unused entries, duplicates, etc) or even if you know the palette but the PNG is encoded without one. Also command-line option to flip generated data vertically (my routine draws sprites from the bottom, for a reason). The output is generated assembly with generated ASM-level constants (global symbols available to C, too, DRY principle again) representing the sprite dimensions, palette count and all palette values. You can thus set palette from one the sprites without repetition at all. (This is what I do.)
* Integration of the program with the tool chain. Edit your PNG, save it, do make run and the generated DSK,CDT,VOC/WAV and all have the new image updated inside. No need to keep any generated file. DRY, lean and clean.
* Macros to access all known undocumented Z80 instructions. Based on z80 Instruction Set (https://borilla.co.uk/z80.html) and turned into a source ASM with macros by a bash script.
* Now patches the sdasz80 assembler that have it report Z80 timings on the CPC, instead of generic timings! Based on https://borilla.co.uk/z80.html which is based in turn on data measured by Arnoldemu and the Executioner. In the example below, numbers between brackets are CPC timings. Based on same data as above.

I know about RASM, it does undocumented instructions and probably timing reports. Not sure yet if it does everything I need. I'm pretty obsessed with having a build in only one manual step: "trigger the build, get the finished file ready to run". Even the graphics! Perhaps I will give RASM a try some day.

Below is example assembler output showing timings. This is a number of snippets extracted from real code:

Code: [Select]
---------------------->VV<- Z80 CPC Timings
   4006 21 A1 5E      [ 3]   27         ld hl, #sprite_jg9_tile_06_png_data ;3
   4009 01 00 70      [ 3]   28         ld bc, #0x7000
   400C CD 69 40      [ 5]   29         call drawsprite

   407D 4F            [ 1]   46         ld c,a                                            ;1 - store dest LSB
   407E 14            [ 1]   47         inc d                                             ;1 - H table
   407F 1A            [ 2]   48         ld a,(de)                                         ;2 - a=line start MSB
   4080 57            [ 1]   49         ld d,a                                            ;1 - HL=dest
   4081 59            [ 1]   50         ld e,c                                            ;1

   4082 ED A0         [ 5]   72         LDI                     ;5

   43B7 3E 01         [ 2]   71 ld a, #0x01
   43B9 F5            [ 4]   72 push af
   43BA 33            [ 2]   73 inc sp
   43BB CD D4 45      [ 5]   74 call _fw_scr_set_mode
   43BE 33            [ 2]   75 inc sp

   43C2 21 AF 43      [ 3]   79 ld hl, #_game_palette
   43C5 CD DD 45      [ 5]   80 call _fw_mc_set_inks__4

   40A1                      38 _screen_address_processing__configure_crtc::
   40A1 01 01 BC      [ 3]   39         ld bc, #0xbc01
   40A4 ED 49         [ 4]   40         out (c), c
   40A6 01 20 BD      [ 3]   41         ld bc, #0xbd00 + _crtc_r1_disp_width_chars
   40A9 ED 49         [ 4]   42         out (c), c
                             43
                             44         ;; horizontal centering
   40AB 01 02 BC      [ 3]   45         ld bc, #0xbc02
   40AE ED 49         [ 4]   46         out (c), c
   40B0 01 2A BD      [ 3]   47         ld bc, #0xbd00 + 46 + ((_crtc_r1_disp_width_chars-40)/2)
   40B3 ED 49         [ 4]   48         out (c), c
                             49
   40B5 01 06 BC      [ 3]   50         ld bc, #0xbc06
   40B8 ED 49         [ 4]   51         out (c), c
   40BA 01 20 BD      [ 3]   52         ld bc, #0xbd00 + _crtc_r6_disp_height_chars
   40BD ED 49         [ 4]   53         out (c), c
                             54
                             55         ;; vertical centering
   40BF 01 07 BC      [ 3]   56         ld bc, #0xbc07
   40C2 ED 49         [ 4]   57         out (c), c
   40C4 01 22 BD      [ 3]   58         ld bc, #0xbd00 + 30 + ((_crtc_r6_disp_height_chars-24)/2)
   40C7 ED 49         [ 4]   59         out (c), c

   40FA 3E 08         [ 2]  111 ld a, #8
   40FC 84            [ 1]  112 add a, h
   40FD 67            [ 1]  113 ld h, a
   40FE 10 EE         [ 4]  114         djnz next_scan_line_in_char
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: zhulien on 03:05, 13 February 20
i found a lot of sprites libraries and sprite functions are very difficult to use, i guess there needs to be a balance on the CPC given the lower horsepower between ease of use and performance - but I wonder if my JS sprite library would be fast enough on CPC if re-written in C?


http://8bitology.net/poc/framework/js/ (http://8bitology.net/poc/framework/js/)  look at jsprites.js for the sprite library, and game-spritedemo.js for an example how to use them.


Briefly, they work by having an array of images and an array of sprites (basically metadata that can use the images).  the images can be used in multiple sprites and may contain multiple frames of multiple sprites - kind of like tiles - or sprites sheets that you can easily find on Google.


You setup the metadata with a couple of properties, such as animation sequences, as many as you like and you can control from which animation point to start at from the sprite library.  You can automatically loop, or with logic change to different sequences such as death, jump, walk right, walk left etc... whatever suits the situation. 


The sprite library allows you to create easily, custom arrays from the main sprites array - for example, you might have all sprites in the main array, but want to build a custom level1 sprite array for level 1 of a game, so this can be done easily to optimise the array that will be iterated through for updating animation sequences, movements etc.


With JS, like C you can have a function in place of some properties - pointers in C, but in-line functions in JS.  This means updating a coordinate for example doesn't have to be so simple as adding 1, but can be for example a function that looks up the next position within a circle circumference if you want gyrus style movement.


In the provided example, there are a couple of asynchronous callbacks, onRenderCanvas which paints the canvas (or screen if you like), and onIterationGameLoop which does the game processing.  In CPC World think of the game loop being an interrupt and the render  function being a separate interrupt - this allows for different speed systems to play a game at the same speed but with different automatic frame-skips.  On CPC they can be 1 interrupt I guess.   Within onRenderCanvas there is the paintSprites function that automatically paints the sprites on the screen at whatever coordinate they should be painted at and whatever frame should be painted.  In the game loop, we can call the animateSprites which changes them to the next animation sequence, moveSprites which changes their position to their next position and showSprites which decides which ones to show (we can have hidden ones too).


Anyway, the code is very very simple to follow too even though it is in JS and you are coding in C - so... I hope you might find it useful?
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: roudoudou on 08:14, 13 February 20
I know about RASM, it does undocumented instructions and probably timing reports. Not sure yet if it does everything I need. I'm pretty obsessed with having a build in only one manual step: "trigger the build, get the finished file ready to run". Even the graphics! Perhaps I will give RASM a try some day.
RASM does internal timing in order to produce synchronized code but if you want timing report, people have done Visual Studio plugin: https://marketplace.visualstudio.com/items?itemName=mborik.z80-macroasm
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: reidrac on 09:01, 13 February 20
RASM does internal timing in order to produce synchronized code but if you want timing report, people have done Visual Studio plugin: https://marketplace.visualstudio.com/items?itemName=mborik.z80-macroasm

In case this helps: https://github.com/reidrac/z80count

It counts Z80 cycles; not CPC specific. It adds (and updates) comments to the code.
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: roudoudou on 09:06, 13 February 20
It counts Z80 cycles; not CPC specific.
Nops are useless to spectrum/MSX users as regular ticks are useless for CPC users   ;D
Rasm will do both in the future  8)
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: roudoudou on 10:37, 13 February 20
oups, someone told me i put the wrong plugin :D
 z80-asm-meter-vscode, is the cycle measurement plugin
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: norecess on 15:15, 13 February 20
I use both plugins as referenced by @roudoudou (https://www.cpcwiki.eu/forum/index.php?action=profile;u=1714) above and I have to say it's awesome!
ps. it's for VSCode, not VisualStudio
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: roudoudou on 15:22, 13 February 20
I use both plugins as referenced by @roudoudou (https://www.cpcwiki.eu/forum/index.php?action=profile;u=1714) above and I have to say it's awesome!
ps. it's for VSCode, not VisualStudio
Visual Studio Code indeed...
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: cpcitor on 19:18, 13 February 20
I use both plugins as referenced by @roudoudou (https://www.cpcwiki.eu/forum/index.php?action=profile;u=1714) above and I have to say it's awesome!
ps. it's for VSCode, not VisualStudio

Ah, so it exists outside of Windows. That's good news.

Just tried https://marketplace.visualstudio.com/items?itemName=mborik.z80-macroasm but did not figure at once how to tell it where to look for definitions.

I found https://github.com/theNestruo/z80-asm-meter-vscode but just seeing numbers in status bar is not whet I expected.

Nops are useless to spectrum/MSX users as regular ticks are useless for CPC users   ;D
Rasm will do both in the future  8)

But it is open-source, so it can be adjusted to CPC timings. (So is RASM.)

Hey, Reidrac, your games seem impressive! Not played them, but the graphics are great and the video of "The dawn of kernel" from https://www.usebox.net/jjm/ suggests a very nice experience.
Title: Re: cpc-dev-tool-chain: a portable toolchain for C/ASM development targetting CPC.
Post by: reidrac on 20:50, 13 February 20
Hey, Reidrac, your games seem impressive! Not played them, but the graphics are great and the video of "The dawn of kernel" from https://www.usebox.net/jjm/ suggests a very nice experience.

Well, play them!  :D