.........1.........2.........3.........4.........5.........6.........7.........8

Mastering Machine Code on Your Spectrum
part 6 of 8 - from ZX Computing Aug/Sep'83

Toni Baker, author of "Mastering Machine Code on Your ZX81",
takes you through the beginnings of a great racing car
program.


In this article I would like to concentrate on the very
basic question of how to write a program. That is, given an
idea, how do we change that idea into byte by byte reality?
There's no real algorithm for it - it's an intuitive
process. If there was an algorithm for it then we could
write a computer program to do it for us. Imagine how great
that would be. We could feed in the information "CHESS:
Board Game, 8x8; starting position; rules" and the program
would output a chess program for us! No such luck in real
life. Writing programs is an abstract, not a logical process
- lateral rather than linear.

Lateral thinking is a skill which all of us, as human
beings, possess. Lateral thinking is different from linear
thinking. In linear thinking, one idea leads to another,
which leads to another, which leads to another, until
eventually you reach a conclusion. Computer programs can be
written to follow this kind of thinking, and those which do
may be defined as 'intelligent'; however, nobody yet has
devised a program which uses lateral logic - this is when
you abandon one train of thought and decide to try a
different approach. This new train of thought comes into
your head spontaneously and you cannot pinpoint exactly
where the idea came from. Artists and songwriters create
their works in their heads almost entirely by lateral
thinking (well, the best of them anyway) and this process
they will describe as 'inspiration' or 'intuition'.
Intuition then, is the basic ingredient in the writing of a
successful computer program from scratch.


Thanks for the memory

Memory (human memory, not computer memory) is another basic
ingredient. This is known in the trade as 'experience'.
Experience, however, is not paramount (for if it was then
the first ever program wouldn't have been written).
Experience can be replaced by immediate access to knowledge
in other forms. An experienced programmer may know
instinctively that the Hex 09 means ADD HL,BC and that to
LPRINT a character all you have to do is set bit one of
FLAGS and then use RST 10, whereas everyone else will need
to look these things up. I must stress that this is not a
handicap as long as you do have the information (usually in
book form) immediately to hand. Experienced people may write
better (and by that I mean more sophisticated) programs than
beginners, but this is only because they have immediate
access to more sophisticated blocks of knowledge - "Oh yes,
I know the best way to scroll the screen sideways two
squares with a double somersault in between because I did it
last Thursday for the program to make toasted cheese
sandwiches out of five unknown variables". I wouldn't worry
too much about it. That routine may be to hand now, but even
the experienced had to write it for the first time once, and
believe me it took them a very long time (not to mention
hours of lost sleep) to get it working.

The sophistication of the program then, is what is
determined by experience. The beginner should not attempt to
write a chess program. The experienced programmer would
laugh at the idea of writing anything as trivial as a
program to turn the screen blue. You must compromise the
kind of program you want to write with what you know you can
achieve. Every program you write should fall somewhere
between the limits 'simple' and 'very hard'. These words
obviously mean different things to different people, so
judge by the following convention: a 'simple' program is one
that takes you less than two days to complete, and a 'very
hard' program is one that takes you over a month. Programs
which you think are going to take you much much longer than
even that fall into the category 'impossible' and should not
be attempted, as they usually result merely in the breaking
of a few items of furniture.


On display

The 'format' of the screen display is something else which
improves with experience. The intricacy of the picture - the
'flowerification' as someone I know would say. A beginner
would use screen displays constructed out of characters from
the Spectrum character set, then as you advance you will
find yourself using user-defined graphics (up to 21) and
then even more user-defined graphics (any unlimited number),
and finally dispense with the graphics altogether and just
POKE into the memory to obtain the ultimate in high
resoluteness.

Let's program then. First the idea, then the solution. The
idea is a racing car program. It's not an original idea - I
stole it from a video game I once saw. (It's not illegal to
steal the idea for a video game as long as you write the
actual program yourself from scratch.) The game plays as
follows: given a steering wheel (or in this case two
buttons) and an accelerator to control your speed, you must
perform one lap of a specific race track faster than your
opponent (the computer). Your opponent is a perfect driver
and will never crash, however, this is only because they
maintain a constant and fairly medium speed. You on the
other hand must compromise between travelling slowly but
safely (and losing the race) or going for speed in order to
win (whilst trying not to crash).

Now here's where the intuition / experience bit comes in. I,
as an experienced so and so, happen to know offhand that
there is a subroutine in the ROM which will scroll part of
the screen upwards, but that there is not a subroutine in
the ROM which will scroll part of the screen downwards.
Because I can't be bothered to write one I conclude that it
would be easier to have the car at the top of the screen
with the road scrolling upwards toward the car.


Answers, answers

The solution is that we can resort to an algorithm-type
approach just a little here. The first step in almost any
video game is called initialisation, and this usually
consists of two parts: (i) initialising any variables
needed; and (ii) initialising the image on the screen. We
can't really think about variables just yet because we don't
know what we're going to need - so to the screen.

Here we rely on intuition and artistic ability. We have
total control over what we want the image to look like,
remember, and so we need imagination to decide on how we
want it. My suggested process, written first in BASIC, is
shown in Fig.1.

- Fig.1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
  10 PRINT PAPER 6;"Time    Distance    Distance            to go (H)   to go (C)   ",,"================================"
  20 FOR i=1 TO 17
  30 PRINT TAB 7;"graphic shift 8";TAB 24;"graphic shift 8"
  40 NEXT i
  50 PRINT AT 5,10; INK 1; "graphic shift 1 graphic shift 2 inverse C graphic shift 1 graphic shift 2 two spaces"; INK 2;"graphic shift 1 graphic shift 2 inverse H graphic shift 1 graphic shift 2"
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

If you feed in this program you should see a yellow
information window (yes, that's what it's called!) above the
start of a racetrack on which are drawn a blue human's car
and a red computer's car.

To turn this part into machine code is very simple. We need
two strings as data: one for the string in line 10, and one
for the string in line 50. So in other words, one way to
start the program could be:

11065468 STR_1 DEFM PAPER yellow
16050A8E STR_2 DEFM AT 5,10d graphic shift 1

Notice the special bytes in the strings. Byte 11 means
'PAPER', and so the two bytes 1106 together means PAPER 6.
Similarly the byte 16 means 'AT', and so the bytes 16050A
together mean AT 5,10. Comma separators may be replaced by
the byte 06, and apostrophe separators by 0D. All of these
are listed in Appendix A of the Spectrum manual. A third
string is also needed for the FOR ... NEXT loop. See if you
can work out what it translates to in Hex. (Warning: TAB x
translates to 17xx00, not to 17xx as you'd expect!) The text
needed is as in line 30.

In the machine code version, the first string should end in
PAPER white, which was not necessary in the BASIC version.


Last stage

And so to business. To print one of these strings the
procedure is as follows: load BC with the length of the
string, and DE with the address of the first byte, and then
CALL 103C. Thus, the BASIC may be replaced entirely by the
code in Fig.2.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
01????          LD BC,length of string one
11????          LD DE,address of string one
CD3C20          CALL PR_STRING
0611            LD B,17d
C5        LOOP  PUSH BC
01????          LD BC,length of string three
11????          LD DE,address of string three
CD3C20          CALL PR_STRING
C1              POP BC
10F3            DJNZ LOOP
01????          LD BC,length of string two
11????          LD DE,address of string two
CD3C20          CALL PR_STRING
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 

The initialisation of the screen complete, the next stage is
to look closely at the rest of the game. This is actually
easier than it sounds. Given that there is a subroutine in
the ROM which will scroll all but the top five inches of
screen upwards, see if you can figure out for yourself how
the rest of the program will work. This is where I
effectively test your intuition and lateral thinking
ability. I'm not simply going to leave it at that, of
course, but I am going to wait until the next article before
I carry on. In the meantime I would like you to stretch your
brains a bit trying to decide for yourself more or less what
answer I'm eventually going to come up with. (Good game
this, isn't it?) I will complete this program next issue.
Till then, keep up the good work.


--
Another Fine Product transcribed by:
Jim Grimwood (jimg@globalnet.co.uk), Weardale, England
--
