Filling the screen with colour

Okay, so we now know how to set colours, so lets fill the screen with them.

We could try expanding our original program to do this like so:

org 32768 

ld a, 32 
ld (22528), a
ld a, 33
ld (22529), a
ld a, 34
ld (22530), a
...
...
...and so on...

But that could take some time to type to fill all 768 blocks of colour on the screen, and take quite a lot of memory too, so we’ll find a better way by learning some more Z80.

Thinking it through, we’ve got 768 block to fill, starting from address 22528, so really we just want to fill each one in turn with the next number – so we start with colour value 0 in 22528, 1 in 22529, 2 in 22530, and so on, using all 256 colour values three times over to fill all 768 blocks on the screen.

Try the following code:

org 32768

ld hl, 22528
ld bc, 768
ld d, 0
LOOP:
ld (hl), d
inc d
inc hl
dec bc
ld a, b
or c
jp nz, LOOP
ret

END 32768

That’s a lot of new stuff – I said things would start moving faster – but it’s pretty straightforward really, honest!

Lets split it up…

ld hl, 22528
ld bc, 768
ld d, 0

I mentioned before that we had a few 8-bit registers – named A, B, C, D, E, H & L – which we could use to store values between 0 and 255?  Well, some of those registers – B & C, D & E, and H & L – can be combined to work as 16-bit registers – BC, DE, & HL – which can be used to store values in the range 0 to 65535. So what we have above is 22528 in HL, 768 in BC, and 0 in D.  So HL holds the address of the top-left of the screen’s colours, BC the number of blocks of colour on the screen, and D will hold the colour value.

LOOP:
ld (hl), d
inc d
inc hl
dec bc

LOOP: is a label – it’s a named point on the program we can refer back to later on.  The next line puts D into the address held in HL – so we put 0 into 22528 – just like the original program did with. 32.  After that we increase the value of D, making it 1 (the next colour value), increase the value of HL, making it 22529 (the next address), and decreases the value of BC, to 767 (one less address to fill)

ld a, b
or c
jp nz, LOOP

Here we put whatever is in register B into A.  This is because the A register, or ‘Accumulator’ as it’s called, is really good for doing calculations on, where the other registers aren’t. We then combine A with register C, using a logical OR, which also does something special as a by-product – it calculates if result is zero or not.  We then use that final instruction, a Jump, to go back to our LOOP label if it isn’t zero (‘nz’ = not zero), which will keep setting the colours until all 768 are filled.  The OR operation is very handy for checking if a 16-bit number is zero, as only if both A & C are zero will the result be zero,

And when you run it, you should get something like, with extra flashing stuff as well!

temp

Phew!  That’s a lot of new stuff, but I’m getting the feeling that you all might just understand it?  Please let me know in the comments if you don’t.  You probably need to have a companion guide to Z80 to go with this, so you can read up on new stuff and understand what’s going on.  Hope I’ve not frightened off anybody!

Advertisements

19 thoughts on “Filling the screen with colour

  1. Hi Bob, When I first looked at this post I felt a little uneasy until the program was broken down and explained. From this I have learnt a few things.
    The LD instructions before the loop do not need to be in the same order. I have substituted the register d with e with the same results so I would imagine HL, BC or DE could also be substituted as long as the 8 bit registers don’t clash with them. Also by starting register d with 255 and using dec d instead of inc d reverses the picture.

    I have learnt more by following you with hands on than with my head in a book. This is awesome and thank you.

    Liked by 1 person

    1. Correct on all counts! 🙂

      Certain combinations of registers wouldn’t work, for example, you couldn’t entirely swap HL for BC, as Z80 only allows for certain instructions – that’s why we had to use the accumulator to do the maths at the end, we couldn’t do that with any other register, it just wouldn’t compile. Those are quirks you’ll soon get the hang of.

      Playing with the code is a good thing though, you’ll learn a lot from it. If it’s wrong it will either not compile, or do something unexpected in the emulator, but there’ll be no lasting damage.

      Like

      1. Hi again Bob, I swapped the A register (Accumulator) with E and it did compile. It also ran in an emulator but it did crash. I am using Pasmo on Linux so maybe there is limited error checking on this version ?.

        Like

      2. It will compile, the commands are all valid, but the crash is because it will never end the loop, and so just keeps filling memory until it overwrites something important – such as the program itself! :O

        Liked by 1 person

    1. Spoiler, sort of. I mentioned earlier that I wasn’t going to use any ROM routines, which that is. We’ll come to the graphics shortly, as yes, it does look a little messy right now, but I want to explain how it works, as you’ll get more knowledge from it that way – like learning to driver rather than ordering a taxi 🙂

      Liked by 1 person

  2. Thanks for this step-wise introduction, it’s made it quite easy to understand what’s going on!

    I also did the same task filling the screen with the same colours using basic and well, it takes as long for the Spectrum to execute the basic program as it takes to write the assembler code for the same task, which of course executes instantly (or so it appears 🙂 )

    So assembly will be quite important if I’m going to make anything that’s not just teaching my kids how programming works (which is better to do with basic).

    Liked by 1 person

  3. Bob, you loaded a 16 bit number into BC using ld bc, 768, however when loading the value back into the accumulator you used ld a, b. Is using ld a,b a shortcut for ld a,bc as bc should be holding the full 16 bit value. Or, are you just reading an 8bit portion of the 16bits?

    Like

    1. BC is made up of B and C, and so you can’t put it all in A. So you put one half into A, and then combined it with the other half using the OR command, and it’s that result which is tested to see if we’ve finished filling the screen.

      Like

  4. Couple more questions:

    1. You stick the current colour into d starting at zero, and then increment D within the loop 768 iterations. Since the D register is a byte does it just loop back around to zero automatically when the number gets to being a 16 bit number i.e. when it gets to 256?

    2. Very noob question, can the LD command ever do a memory to memory copy, or do you always have to take the results back to a register first?

    Like

    1. 1) Yes, as D is an 8-bit number, it loops around to zero when it tries to go above 255 (likewise it would 255 if you tried decreasing it from zero)

      2) No, not with LD. LDI & LDIR can copy memory (see later post), but that’s it.

      Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s