Author Topic: Genesis8 - C Programming on Amstrad (SDCC, Z88dk and CCZ80)  (Read 4714 times)

0 Members and 1 Guest are viewing this topic.

Offline AMSDOS

  • Supporter
  • 6128 Plus
  • *
  • Posts: 3.623
  • Country: au
    • index.php?action=treasury
    • Programs for Turbo Pascal 3
  • Liked: 890
  • Likes Given: 1540
Re: Genesis8 - C Programming on Amstrad (SDCC, Z88dk and CCZ80)
« Reply #25 on: 11:11, 30 November 15 »
Yes, you can draw circles much faster using Bresneham integer methods and random numbers don't usually have much to do with floats when used in practice (eg. random 0..3 for direction, 10..20 for speed, 0..27 for colours etc). Most times when you use the random functions in BASIC/Pascal/Java etc you do things like x = (int)(Math.random() * 10), and for pure sine/cosine usage I find the most efficient implementation is X * sin(angle), as I've used it in assembler etc. (eg. 65536 * SIN(deg * 256 / 360)) in a table.


This looks like a Good page to look at:


Bresenham Line-Drawing Algorithm


Though it didn't have anything about Circle Generation.


I came across some code from another forum which may help, though the original poster wasn't sure how good it was:


Code: [Select]
void filcircle(int x0,int y0,int R)
 {int dx,dy,curx,cury;
  for(curx=x0-R;curx<=(x0+R);curx++)
  for(cury=y0-R;cury<=(y0+R);cury++)
   {
    dx=curx-x0;
    dy=cury-y0;
    if(dx*dx+dy*dy<=R*R) setpixel(curx,cury);
    }
  }
« Last Edit: 11:25, 30 November 15 by AMSDOS »
* Using some of the hardly used Amstrad compilers :D
* I use Firmware in my Assembly code :P
* Have interpreted some BASIC 1.1 programs for BASIC 1.0. :)

Offline Munchausen

  • 6128 Plus
  • ******
  • Posts: 772
  • Country: gb
  • Liked: 211
  • Likes Given: 215
Re: Genesis8 - C Programming on Amstrad (SDCC, Z88dk and CCZ80)
« Reply #26 on: 12:36, 30 November 15 »
You can look at the Bresenha/Midpoint circle algorithm here: Midpoint circle algorithm - Wikipedia, the free encyclopedia

And tables for trig is also what I would use.

@Alocoholics Anonymous those figures are interesting. It looks as though IAR is indeed hard to find. Is there an implementation of those peephole optimisations available somewhere? It would be interesting to see what you are using

Offline FloppySoftware

  • CPC6128
  • ****
  • Posts: 243
  • Country: es
  • The best team: Amstrad PCW, CP/M, and the Z80 cpu.
    • Floppy Software
  • Liked: 234
  • Likes Given: 171
Re: Genesis8 - C Programming on Amstrad (SDCC, Z88dk and CCZ80)
« Reply #27 on: 21:16, 30 November 15 »
I think it would be nice to have a C compiler that runs on the CPC and can use the RAM expansions.

I think porting MESCC to the CPC should be very easy.
 
In fact, it's a CP/M native compiler, derived from Small-C, and has a nice bunch of libraries.
 
Then, it's posible to run it on the CPC under CP/M 2 or 3, as is.
 
I'm currently working in some MESCC enhancements:
 
- Now, you can declare and assign global variables, on the same line (as in standard C!).
- New peephole optimizer, with an easy system to modify / add / delete rules.
- New libraries: qsort, bsearch.
 
Those enhancements will be included in the next release of MESCC.
 
 
 
floppysoftware.es < NEW URL!!!
cpm-connections.blogspot.com.es

Offline Alcoholics Anonymous

  • CPC664
  • ***
  • Posts: 51
  • Country: ca
  • Liked: 44
  • Likes Given: 0
Re: Genesis8 - C Programming on Amstrad (SDCC, Z88dk and CCZ80)
« Reply #28 on: 21:20, 30 November 15 »
I noticed Phrozen C is a CPC implementation, though it's based on Small-C. Small-C itself operates under CP/M, though you're probably aware it can compile code for a number of operating systems. I guess if Hitech C produces assembly source, that is at least better than having some compiler produce some COM file. 

Small-C itself doesn't implement FILEs or have a concept of file descriptors.  The latter is not necessary but it's kind of expected in C because file descriptors are in the POSIX standard, which defines what makes Unix Unix.  So it's easy to target another system because there's nearly nothing in it interfacing with an underlying system.   Furthermore, both the small C compiler and the few asm language subroutines in the library all target an 8080 subset which means, for example, in the CPC's case you don't have to think about what is going on with the exx set or index registers when trying to make it compatible with the firmware.  It makes for an easy compiler to re-target.

However I am not sure why people using small C are going all the way back to the original version by Ron Cain.  Small C has a lineage and the next few versions make it ANSI-C compatible (as far as function declarations, etc), and add things like structs and floats.  Phrozen C and it looks like Mess-C are both using the original Small C lacking these features.  The most developed version of small C (afaik) is inside z88dk and is known as sccz80.  This fills in almost all the missing C functionality with the notable exception of multi-dimensional arrays.

Hitech C for cp/m has got the file i/o goodies but it's all tied to cp/m BDOS.  Not surprising since to implement FILE i/o without an underlying operating system to support it requires a lot more work (see fuzix or z88dk).  So wedging anything else in there is going to require someone with the time to separate that portion out.  Hitech C can in fact generate asm output and I think it can also target plain z80s without the extra cp/m goodies.  The asm output expects an assembler with an understanding of areas/sections.  The one supplied by Hitech is ZAS.  I'm not familiar with cp/m in general so I don't know how sophisticated its native assemblers are.  I did run into trouble with Hitech on cp/m when compiling large C programs (read > ~24k binaries) with the assembler running out of symbol space.  But these programs were written on 16 or 32-bit machines in giant source files.  Programs for Hitech C would be split up into multiple source files so that the compiler could deal with large programs in small portions.

Quote
(float) I seem to be using it a bit then in Random Number Generators & Calculating the Cosine & Sine for Drawing/Plotting a circle, do you have an integer based approach for those problems?

As mentioned, graphics primitives are usually implemented in fixed point.  The Bresenham line drawing algorithm, eg, effectively uses fixed point by carrying a fraction that gets the slope added in each iteration that must exceed one before changing pixel coordinate.

There are fixed point implementations of sin, cos and other common functions.  The trig functions are usually done by table look-up.  Fixed point is just a fancy name for integer with an implied binary point so multiplication, division, addition and subtraction use the usual integer subroutines but multiply and divide might get special subroutines to preserve the max number of bits defined in the integer and fraction part of the fixed point number.

Quote
(32-bit floats and financial calculations)
It's not something I've considered, even though I've got books on the topic.

When you start doing time-value of money calculations that involve exponentiation and logarithms the error starts to be measured in cents and can creep into dollars if the float package is weak.  But even before that you can't represent decimal fractions exactly in binary.  So trying to enter 10 cents as 0.1 dollars you end up with a binary fraction that extends indefinitely.  If you don't have enough mantissa bits, rounding can lead to errors in the cents even with simple math operations.  I'm not an expert but at least before the arrival of modern float processors, I think all financial data was stored as integers (dollars plus cents) and they may have done computations in BCD.

Incidentally, in z88dk there are two float packages and both are 48-bit (40 bit mantissa).  It happens to be the max size the z80 can keep in registers.  The first is called genmath which I think comes from Jimi Hendrix's small C derivative but it's been changed somewhat.  The second is called math48 and it's in the development portion of z88dk that we've interfaced to both sdcc and sccz80.  You may be interested to know that math48 is (I believe) the float package used in Turbo Pascal.  We've added things to it but I quite like it -- it's very easy to program in assembly language.

Before harward floating point was commonplace there was a program in the 80s called "paranoia.c" that would test the quality of the floating point implementation.  It's hard to compile with most compilers on the z80 but I managed to compile it on the sdcc/z88dk combination using math48.  It did identify some weaknesses which eventually I will address but for math48 (and TP's float implementation) it seems some transcendental functions are not as accurate as the 40-bit mantissa allows.  Probably not enough terms in the series used.

Quote
So the original C was used to write Unix wasn't it? Or was it BCPL? I just would of thought that C would of been standardised for such a large scale project.

Well C was developed to implement Unix and the result at the end was called K&R C as K&R wrote a book to document it.  That was the standard and described the one and only version of C at the time.  But it continued to evolve and as it was ported to other platforms, non-portable functions were added by vendors to accommodate special features of the hardware.  C was losing its portability so that's why an ANSI committee was put together to brand a de-facto ANSI-C.  Most of it was probably implemented by most C vendors prior to publication of the standard but that first standard is known as C89 or C90.  After that there's C95, C99, C11 but most of what people understand as C is C89/C90.

Small C was originally written in 1979/1980 so it's based on K&R C but is not fully compliant with K&R C.  Finding a native ANSI-C implementation for the z80 is a taller order since the ANSI standard was not adopted until 1989 which puts this toward the twilight of the z80's existence.  Hitech-C for cp/m is a fortunate find.  For other examples you have to look at the commercial vendors who sold z80 C for embedded systems and those are Hitech (again), IAR, Avocet, SoftTools and a few others, and the current open source projects (sdcc, z88dk).
« Last Edit: 21:29, 30 November 15 by Alcoholics Anonymous »

Offline FloppySoftware

  • CPC6128
  • ****
  • Posts: 243
  • Country: es
  • The best team: Amstrad PCW, CP/M, and the Z80 cpu.
    • Floppy Software
  • Liked: 234
  • Likes Given: 171
Re: Genesis8 - C Programming on Amstrad (SDCC, Z88dk and CCZ80)
« Reply #29 on: 21:20, 30 November 15 »
I seem to be using it a bit then in Random Number Generators & Calculating the Cosine & Sine for Drawing/Plotting a circle, do you have an integer based approach for those problems?

Have a look (from my XPCW graphic functions for the PCW):
 
Code: [Select]
/* Draw a circle in the current draw mode
   --------------------------------------
*/
DrawCircle(x0, y0, radius)
int x0, y0, radius;
{
 int x, xh;
 int y, yh;
 int decision;
 x = radius;
 y = 0;
 decision = 1 - x;
 while(x >= y) {
  /* The PCW pixels are double in high */
  xh = x >> 1;  /* xh = x / 2 */
  yh = y >> 1;  /* yh = y / 2 */

  /**
  DrawPixel( x + x0,  y + y0);
  DrawPixel( y + x0,  x + y0);
  DrawPixel(-x + x0,  y + y0);
  DrawPixel(-y + x0,  x + y0);
  DrawPixel(-x + x0, -y + y0);
  DrawPixel(-y + x0, -x + y0);
  DrawPixel( x + x0, -y + y0);
  DrawPixel( y + x0, -x + y0);
  **/
  DrawPixel( x + x0,  yh + y0);
  DrawPixel( y + x0,  xh + y0);
  DrawPixel(-x + x0,  yh + y0);
  DrawPixel(-y + x0,  xh + y0);
  DrawPixel(-x + x0, -yh + y0);
  DrawPixel(-y + x0, -xh + y0);
  DrawPixel( x + x0, -yh + y0);
  DrawPixel( y + x0, -xh + y0);
  y++;
  if(decision <= 0) {
   decision += 2 * y + 1;
  }
  else {
   x--;
   decision += 2 * (y - x) + 1;
  }
 }
}
floppysoftware.es < NEW URL!!!
cpm-connections.blogspot.com.es

Offline Alcoholics Anonymous

  • CPC664
  • ***
  • Posts: 51
  • Country: ca
  • Liked: 44
  • Likes Given: 0
Re: Genesis8 - C Programming on Amstrad (SDCC, Z88dk and CCZ80)
« Reply #30 on: 21:53, 30 November 15 »
@Alocoholics Anonymous those figures are interesting. It looks as though IAR is indeed hard to find.

Hitech's z80 compilers are gone too.  What happened with them is they were bought by Microchip who promptly discontinued Hitech compilers that did not target Microchip processors.

With IAR it looks like they've just dropped the z80 from their lineup and there doesn't seem to be a way to get hold of IAR C for the z80 anymore.

I think Zilog's own C compiler only targets later generations (the ez80 and z380, etc).


Quote
Is there an implementation of those peephole optimisations available somewhere? It would be interesting to see what you are using

Yes you can try it yourself:

http://z88dk.cvs.sourceforge.net/viewvc/z88dk/z88dk/libsrc/_DEVELOPMENT/sdcc_peeph.3

There are about 400 new rules there.  This is still a work in progress, keep in mind.  It started with a little messing around before I knew how things worked and contains some experimentation in the middle.  So there are many examples of how not to write peephole rules mixed in with the good.

I use it through z88dk but I think you can use it with sdcc directly like this:

sdcc -mz80 [-S --no-c-code-in-asm] --reserve-regs-iy --max-allocs-per-node200000 test.c --no-peep --peep-file sdcc_peeph.3

The options in square brackets are for generating an asm file only.  "reserve-regs-iy" stops sdcc from using the iy register which gives the peephole rules more opportunites to improve the code.  The rules were written with high max-allocs-per-node active and without that some rules may not be possible to apply.
« Last Edit: 22:51, 30 November 15 by Alcoholics Anonymous »

Offline AMSDOS

  • Supporter
  • 6128 Plus
  • *
  • Posts: 3.623
  • Country: au
    • index.php?action=treasury
    • Programs for Turbo Pascal 3
  • Liked: 890
  • Likes Given: 1540
Re: Genesis8 - C Programming on Amstrad (SDCC, Z88dk and CCZ80)
« Reply #31 on: 12:06, 02 December 15 »

Have a look (from my XPCW graphic functions for the PCW):
 
Code: [Select]
/* Draw a circle in the current draw mode
   --------------------------------------
*/
DrawCircle(x0, y0, radius)
int x0, y0, radius;
{
 int x, xh;
 int y, yh;
 int decision;
 x = radius;
 y = 0;
 decision = 1 - x;
 while(x >= y) {
  /* The PCW pixels are double in high */
  xh = x >> 1;  /* xh = x / 2 */
  yh = y >> 1;  /* yh = y / 2 */

  /**
  DrawPixel( x + x0,  y + y0);
  DrawPixel( y + x0,  x + y0);
  DrawPixel(-x + x0,  y + y0);
  DrawPixel(-y + x0,  x + y0);
  DrawPixel(-x + x0, -y + y0);
  DrawPixel(-y + x0, -x + y0);
  DrawPixel( x + x0, -y + y0);
  DrawPixel( y + x0, -x + y0);
  **/
  DrawPixel( x + x0,  yh + y0);
  DrawPixel( y + x0,  xh + y0);
  DrawPixel(-x + x0,  yh + y0);
  DrawPixel(-y + x0,  xh + y0);
  DrawPixel(-x + x0, -yh + y0);
  DrawPixel(-y + x0, -xh + y0);
  DrawPixel( x + x0, -yh + y0);
  DrawPixel( y + x0, -xh + y0);
  y++;
  if(decision <= 0) {
   decision += 2 * y + 1;
  }
  else {
   x--;
   decision += 2 * (y - x) + 1;
  }
 }
}


Yes, this code looks similar to the one in the Midpoint Circle Algorithm article on Wikipedia that @Munchausen posted, though I'll have a look at this code, at the moment I've written a BASIC & Pascal which I'll post in due course in another thread to stop hijacking this thread.
* Using some of the hardly used Amstrad compilers :D
* I use Firmware in my Assembly code :P
* Have interpreted some BASIC 1.1 programs for BASIC 1.0. :)

Offline AMSDOS

  • Supporter
  • 6128 Plus
  • *
  • Posts: 3.623
  • Country: au
    • index.php?action=treasury
    • Programs for Turbo Pascal 3
  • Liked: 890
  • Likes Given: 1540
Re: Genesis8 - C Programming on Amstrad (SDCC, Z88dk and CCZ80)
« Reply #32 on: 12:51, 05 December 15 »
Yes, you can draw circles much faster using Bresneham integer methods and random numbers don't usually have much to do with floats when used in practice (eg. random 0..3 for direction, 10..20 for speed, 0..27 for colours etc). Most times when you use the random functions in BASIC/Pascal/Java etc you do things like x = (int)(Math.random() * 10), and for pure sine/cosine usage I find the most efficient implementation is X * sin(angle), as I've used it in assembler etc. (eg. 65536 * SIN(deg * 256 / 360)) in a table.


Regarding Random Numbers, I understand the logic behind producing those results, I was referring to producing a Random Number Generator.
I made a Random Number Generator a couple of years back in Hisoft Pascal using Integers, which lead to Skewed Results. Another attempt shortly after was a lot better and using a Real to store a result, though still somewhat frowned at for using 2 Divides. I managed to get that down to one Divide by Dividing Range with 32767 (MAXINT) to get my Real Result and then times Seed with that Result to get a value somewhere in the Range I specified. I've since found another Random Number Generator in Pascal, though it's also using Real for Returning a Random Result. So on one hand it's good I came up with something which produces values within a set range, though to write it had to work with Real Numbers. I should point out that I had to do that because while Hisoft Pascal has a RANDOM(num) function, it's nature is to return a Random Seed (between 0 and 32767), and that only happens when num=0, so a RANDOM(1) for instance doesn't return numbers between 0 & 1, only 1's and seems to be the trend with any number in that spot (except 0).
* Using some of the hardly used Amstrad compilers :D
* I use Firmware in my Assembly code :P
* Have interpreted some BASIC 1.1 programs for BASIC 1.0. :)