Monday 2 January 2012

Starting with C

What starts with C and works on the Sinclair ZX Spectrum? Well, thanks to z88dk - available from z88dk.org - it's C.

I've been playing around with this and, I have to say, the Wiki is useful but not very helpful, and I can't find many clear examples that'd be good for beginners to get their teeth into. This, in my opinion, is due to lack of good commenting in the source code examples, and also it being written by many technically minded people who forget that sometimes things need to be explained in English, which is a language that I'm quite fond of as it can be very clear and concise if used well. So, I intend to write a beginners guide to C programming for the ZX Spectrum in the near future.

Anyway, after scratching my head for a few hours, I wrote a simple 'Hello World!' type program. This isn't a challenge, of course, but I wanted to change the colours of the text and bypass the 64-column mode which is what the z88dk compiler defaults to when you use it. I also got it to drop down to assembly for a short routine which sets up the default colours for the whole screen. Anyway, more importantly, I've commented it quite well so even if you're a complete novice at programming and would struggle with something simple, it should be straight forward enough. Note that there is a much simpler way to do the same thing, but simple doesn't always tell you everything that you need to know. Oh, and it also uses a look-up table, something that I always find myself building even if it's not always strictly necessary.

Here's the code:

/**
 * This does something similar
 * to the classic "Hello World!"
 * code that's a popular starting
 * point for learning programming.
 */
#include <stdio.h>

// Here are our default colour
// attributes
#define INK     7
#define PAP     2
#define FLA     0
#define BRI     1
#define INV     0
#define BOR     5

// This is used in the setup function,
// which drops into machine code -
// see my blog for more information:
#define COL     128*FLA+64*BRI+8*PAP+INK

// Forward declarations of functions:
static void main(void);
static void setup(void);
static void hello(void);
static void magazine(void);

// Global variables:
static int i=0;

// Here is an array which will set up
// the default colour attributes for
// printing our message to the screen,
// 255 is used as a 'terminator' to
// say "we've finished here"
static int screensetup[]=
{
     1, 32, 16, 48+INK, 17, 48+PAP,
     18, 48+FLA, 19, BRI, 20, 48+INV,
     12, 255
};

/**
 * This is the 'entry point' of our program:
 */
void main(void)
{
     // This will call a routine to
     // set the default colour
     // arrtibutes for the whole screen
     // as defined above:
     setup();
     // This does the same for outputting
     // out character see
     // http://www.z88dk.org/wiki/doku.php?id=platform:zx
     // for more information under the
     // heading "The standard ZX Spectrum
     // console driver" - hopefully, these
     // numbers will now make more sense!
     while(screensetup[i] != 255)
     {
          // The %c means 'print character code'
          // or something similar
          printf("%c",screensetup[i]);
          // Increase i to read the next element
          // of the array:
          i = i + 1;
     }
     // Calls our functions, firstly hello:
     hello();
     // and now magazine:
     magazine();
}

/**
 * This function sets up the default colours
 * for our screen as defined above:
 */
void setup(void)
{
     #asm
     // Sets default ink and paper colour,
     // then clears screen
     ld a,COL
     ld (23693),a
     call 3503
     // Sets border colour
     ld a,BOR
     call 8859
     #endasm
}

void hello(void)
{
     // Here is where the magic happens,
     // can you tell what it does?
     printf("Hello ");
}

void magazine(void)
{
     // And what about this bad boy then?
     printf("Magazine!\n");
}
  

Call the source code "HelloMagazine.c" (obviously without the quotation marks) and place it in the same directory as the z88dk 'bin' folder, go to your command line prompt and compile it with:

zcc +zx -lndos -create-app -o hello HelloMagazine.c

it should create a file called "hello.tap", simply load this into your emulator and watch with amazement as the magic actually happens!

PS, I'm certainly not endorsing any printed-matter publication which has all of the latest celeb goss or whatever - it's a joke as I've read too many times about "Hello World!" being the default starting point, so I always try to avoid it.

3 comments:

  1. I enjoyed your page in MM 1193.

    The z88dk can work for the Jupiter Ace see below.

    // Jupiter Ace example of using C and asm Z80
    // with z88dk.
    // save this file in the bin folder of z88dk
    // compile in DOS with
    // zcc +aceansi -o s:/ace_c/first.bin s:/ace_c/first.c
    // a file called first.bin will be created
    // to load the file in 81 use the import memory block
    // at address 16384. then in forth '16384 CALL'
    //


    #include

    // Function prototypes:
    static void main(void);
    static void yourname(void);
    static void isace(void);

    void main()
    {
    #asm
    // clear Ace screen
    call 2596 //call JA Forth code for CLS
    SET 4,(IX+62) // turn off OK message
    #endasm

    // Calls our functions:
    yourname();
    isace();

    return;
    }

    // functions
    void yourname()
    {
    printf("Your Name ");
    }

    void isace()
    {
    printf("is ace!\n");
    }

    //
    // end

    ReplyDelete
  2. Thanks Steve. Yeah, you're right that C is very portable, which makes anything written [in C] useful. That's why I've written a couple of ZX81 games recently; if you want to port them over to the Jupiter Ace then let me know :-)

    Regards,

    Shaun.

    ReplyDelete
    Replies
    1. sure we would love to have ported to the Ace, and have them in the Ace archive. Just point me to the C!

      Delete