!0.......^.........^.........^..

!B

\H11\H01\H10\H07            GRAPHIC             

\H11\H07\H10\H00          DEFINITIONS           



!2.......^.........^.........^.........^.........^.........^....

  Defining graphics on paper can be an arduous task especially

when the finished item on-screen looks nothing like you imagined

it. Toni Baker's got a much better idea ... and she's backed it

                 up with machine code to boot!



!1.......^.........^.........^.........^........

User-defined  graphics  are  those things  which

appear on your screen when you press a letter of

the  alphabet  while  the  cursor  says 'G'.  By

suitable POKEing you can make any graphics  look

more   or  less  like  anything  you  want;  for

instance,  graphic  A  could be a Peace  symbol,

graphic B could be a flower, and so on.

  But  after  a  while  you  find that all  this

messing  around  with BIN and scraps of  squared

papers gets bit tedious, and you start to  think

how nice it would be to have a simple, foolproof

way  of  defining  any graphics character.  That

means  having  a  powerful  editing tool with  a

moveable  cursor that will allow you to set  and

reset any pixel and see the results immediately,

both  magnified  (so you can see the eight-  by-

eight  layout  explicitly), and 'life-size'  (so

you can see it as it really is).

  So,  rather  than pay ludicrous sums of  money

for someone else's graphics designing program, I

decided to write my own. (As usual, I'm going to

give it away to all you lucky people ... there's

a  lesson to be learnt there somewhere, but  I'd

rather not look for it!)



!0.......^.........^.........^..

!B

QUICK ON THE DRAW

!1.......^.........^.........^.........^........

This is what happens when you run my program. In

the top left-hand corner of the screen you get a

larger  than  life  picture  of  what  the  said

graphic  will  look  like.  This image is  eight

squares  across and eight squares tall with,  of

course,   one  square  for  each  pixel  of  the

finished  graphic.  Each square is either  PAPER

coloured  (with  an INK coloured border) or  INK

coloured  (with  a  PAPER  coloured border).  In

addition, you get a little dot in the middle  of

one  of the squares, representing a cursor.  You

can move this cursor all over the place with the

aid  of  the  cursor controls, so if you make  a

mistake it's dead easy to go back and change it.

  In the middle of the screen you get a  message

saying  'GRAPHIC  TO DEFINE A ="A"'. The  letter

won't  always be 'A', of course - it depends  on

which graphic you're defining. The symbol in the

quotes  is the finished graphic, and is  updated

continuously  as  the graphic is changed.  Below

that   you   get  a  complete  set  of  all  the

user-defined  graphics,  to let you see  exactly

what's what.



!0.......^.........^.........^..

!B

BEFORE ...

!SYR06_59s1



!2.......^.........^.........^.........^.........^.........^....

Once you've got the code up and running, you'll be presented

with a screen like that shown above. To begin defining your own

graphics, simply press the key of the letter you wish to define;

in the first illustration above, the 'C' key is undergoing

transformation. Using the cursor keys, you can move the flashing

dot (see the top left-hand pixel of the character square) and

set and reset the individual cells to form the shape you

require. Once you've designed your graphics alphabet, this will

be displayed at the bottom of the screen so that you can

identify them easily.

!0.......^.........^.........^..



... AND AFTER

!SYR06_59s2



!1.......^.........^.........^.........^........

!B

  Once the program is running there are a number

of things you can do.



1. Press  a letter key (without Shift);  for

   example, if you want to define graphic J then

   press  the  'J'  key,  if you want to  define

   graphic Q then press the 'Q' key, and so on.

2. Press  a  cursor  key. This will move  the

   cursor  left,  right,  up  or  down as  you'd

   expect.  If you press Caps Shift at the  same

   time  then  the pixel at the cursor  position

   will  be 'set', if you press Symbol Shift  at

   the  same  time  then the said pixel will  be

   'reset'. Without Shift, of course, everything

   stays unchanged.

3. Press  any  other  number  key, Space,  or

   Enter  (without  Shift).  This  will have  no

   effect  whatsoever  and  will  be a  complete

   waste of time.

4. Press  Symbol Shift and the '1' key.  This

   will    completely    blank   the  character,

   resetting every pixel.

5. Press  Caps  Shift  and the '1' key.  This

   will   completely   fill  in  the  character,

   setting every pixel.

6. Stop for a bit and put the kettle on.

7. Press  either  Shift key and the '4'  key.

   This will invert the character, so that every

   pixel  which was set becomes reset, and  vice

   versa.

8. Press  either  Shift key and the '0'  key.

   This will break out of the program and return

   you to normal Basic.

9. Press  Symbol  Shift  and  any number  key

   other than a cursor key (or Space or  Enter).

   This will reset one pixel without moving  the

   cursor.

10.If the kettle has boiled, make the tea.

11.Press Caps Shift and any number key  other

   than  a cursor key (or Space or Enter).  This

   will set one pixel without moving the cursor.

12.Press  either  of the Shift keys  together

   with any letter key. This will re-define  the

   said graphic as an exact copy of the graphics

   character  for  the  letter  key you've  just

   pressed (which is slightly useful).

13.Drink the tea. (I don't mind if I do. Ed.)



As  you  can see, it does quite a good job,  and

tries  its humble best to make life really  easy

for  the  budding  graphic designer. I've  found

that  one  of the most useful ways of using  the

machine  code  is  to  SAVE  it under some  name

("GrMC", say), and then to have a Basic  program

like this:



!0.......^.........^.........^..

10 LOAD "GrMC" CODE

20 RANDOMIZE USR 32854

30 INPUT "Name of program"; A$

40 LOAD A$



!1.......^.........^.........^.........^........

You  can  always  SAVE  the  Basic  bit  with  a

sensible  name like 'Graphics', of course.  This

way,  if  you use SAVE "Graphics" LINE 10,  then

whenever  you LOAD it you'll have your  graphics

designing set-up on the screen waiting for  you.

What's more, when you break out (using Shift and

the  '0' key) you'll be asked to name the  Basic

program with which you want to use the  graphics

you've  just invented. (If you want to invent  a

new  program at this point, then just break  out

using  EDIT/  STOP/  Enter.)  All  this will  of

course   be   just   as  true  for  people  with

Microdrives,  except  that  instead of LOAD  you

have  to  put LOAD *"m"; 1; (awkward isn't  it?)

and likewise for SAVE.

  The program is designed to sit at address 8000

Hex, which means that anyone who's only got  the

16K  Speccy  will have to mess around trying  to

stick it somewhere else. The best way to do this

is  to change every address beginning '80' to  a

similar  address with a different low byte,  and

every  address beginning'81' to something  else.

For SAVEing purposes, you may like to know  that

the  program  takes up 361 (decimal) bytes,  and

that 8000 (Hex) is 32768 (decimal).



!0.......^.........^.........^..

!B

WHO'S A CHEAT?

!1.......^.........^.........^.........^........

An  interesting bit of program to watch out  for

is  the  stuff  just  above  the label  'CHEAT';

that's where the program works out which machine

code  instruction  it wants to execute and  then

POKEs  it into the program before executing  it.

Thus,  the program is self-modifying. There  are

two  schools  of thought regarding this sort  of

practice - the majority, who think it's cheating

and thus shouldn't be allowed, and a minority of

programmers   who   think  it's  actually  quite

clever.  As  you  will have gathered I  (without

shame) subscribe to the second viewpoint; anyone

now   reaching   for   a   pen   to  write  that

"encouraging  bad  programming practice"  letter

should note that I've seen it all before.

  Well,  that's  it,  barring  the code  itself.

Remember, to run it you must call the code  from

address 8056 Hex.



!2.......^.........^.........^.........^.........^.........^....

!B

DEFB 16 0C 00 47 52 41 50 48 49 43 20 54 4F 20 44 45

DEFB 46 49 4E 45 20 41 3D 22 90 22 0D 0D 41 42 43 44

DEFB 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53 54

DEFB 55 0D 90 91 92 93 94 95 96 97 98 99 9A 9B 9C 9D

DEFB 9E 9F A0 A1 A2 A3 A4



This block of Hex is similar to Basic's Data statements; it

holds information necessary for displaying information on the

screen. The code should be organised at 8000h.



!B

Machine code       Assembler          Comments

---------.---------.------------------.-------------------------

3A1580   FIND_UDG  LD   A,(UDGLETTER) A:=the character code of

                                      an upper case letter name

                                      of a graphics character.

---------.---------.------------------.-------------------------

3D       FIND_UDG2 DEC  A

87                 ADD  A,A

87                 ADD  A,A

87                 ADD  A,A           Multiply by eight

5F                 LD   E,A

1600               LD   D,#00

2A7B5C             LD   HL,(UDG)      Point HL to graphic A

19                 ADD  HL,DE         Point HL to required graphic

C9                 RET



Above: This is a subroutine used by the main machine code

program - when you get there you should be at 8047h. Below: This

is the start of the machine code proper. To run the program, you

need to call address 8056h.



!B

Machine code       Assembler          Comments

---------.---------.------------------.-------------------------

210000   START     LD   HL,#0000

FD7402             LD   (TVFLAG),H    Print to the lower part of

                                      the screen

22B05C             LD   (XY_COORDS),HLReset the graphics cursor

---------.---------.------------------.-------------------------

CD4780   RESTART   CALL FIND_UDG      HL:=address of graphics

                                      character

E5                 PUSH HL            Stack:=address of graphics

                                      character

210040             LD   HL,D_FILE     HL:=points to AT 0,0 position

0E08               LD   C,#08

---------.---------.------------------.-------------------------

E3       LOOP_I    EX   (SP),HL

7E                 LD   A,(HL)        A:=the next pixel row

23                 INC  HL            Point to next pixel row

E3                 EX   (SP),HL

0608               LD   B,#08

---------.---------.------------------.-------------------------

17       LOOP_J    RLA

F5                 PUSH AF            Stack pixel information

9F                 SBC  A,A           A:=00 if pixel reset, 

                                      FF is set

2F                 CPL                A:=FF if pixel reset,

                                      00 if set

77                 LD   (HL),A        Print onto the screen

24                 INC  H             Point to next row on screen

EE7E               XOR  #7E           A:=81 if pixel set,

                                      7E if reset

1606               LD   D,#06

---------.---------.------------------.-------------------------

77       LOOP_K    LD   (HL),A        Print onto the screen

24                 INC  H             Point to next row on screen

15                 DEC  D

20FB               JR   NZ,LOOP_K     Fill in body of character

EE7E               XOR  #7E           A:=FF if pixel set,

                                      00 is reset

77                 LD   (HL),A        Print onto the screen

F1                 POP  AF            A:=pixel information

1101F9             LD   DE,#F901

19                 ADD  HL,DE         Point to next char square

10E7               DJNZ LOOP_J        Repeat for eight pixels

111800             LD   DE,#0018

19                 ADD  HL,DE         Point to next line of squares

0D                 DEC  C

20DA               JR   NZ,LOOP_I     Repeat for each row of pixels

E1                 POP  HL            Balance the stack

3AB05C             LD   A,(Y_COORD)   A:=Y coord of the graphics

                                      cursor

0F                 RRCA

0F                 RRCA

0F                 RRCA

FDB677             OR   (X_COORD)     A:=8*Y+X coordinates

6F                 LD   L,A

2643               LD   H,#43         Point HL to appropriate

                                      point on the screen

7E                 LD   A,(HL)        A:=18 or 7E accordingly

EE18               XOR  #18           A:=99 or 66 to mark cursor

77                 LD   (HL),A        Mark cursor on screen

24                 INC  H             Point to next row on screen

77                 LD   (HL),A        Mark cursor on screen

014700             LD   BC,#0047      BC:=length of message

110080             LD   DE,#8000      DE:=start of message

CD3C20             CALL #203C         Print message on screen

---------.---------.------------------.-------------------------

FDCB016E WAIT      BIT  5,(FLAGS)

28FA               JR   Z,WAIT        Wait until key is pressed

FDCB01AE           RES  5,(FLAGS)     Signal ready for next key

CD8E02             CALL KEY_SCAN      A:=character code of digit

                                      or capital letter on key

                                      pressed (or 0D, 0E or 20

                                      for Enter, both Shift keys

                                      or Space, respectively)

3A045C             LD   A,(KSTAT_4)   D:=the Shift key status

FE40               CP   #40

14                 INC  D

381D               JR   C,NOTLETTER   Jump unless letter pressed

2810               JR   Z,CHANGEUDG   Jump if no Shift pressed

CD4A80             CALL FIND_UDG2     HL:=address of UDG for key

                                      pressed

E5                 PUSH HL

CD4780             CALL FIND_UDG      HL:=the address of the UDG

                                      specified

D1                 POP  DE            DE:=the address of the UDG

                                      for the key pressed

EB                 EX   DE,HL

010800             LD   BC,#0008

EDB0               LDIR               Copy the UDG

1808               JR   EXIT_1        Jump to exit

---------.---------.------------------.-------------------------

321580   CHANGEUDG LD   (UDGLETTER),A Change current UDG name

C64F               ADD  A,#4F         A:=the UDG character

321880             LD   (UDG_CHAR),A  Insert into the message ...

---------.---------.------------------.-------------------------

C35680   EXIT_1    JP   START         And start all over again

---------.---------.------------------.-------------------------

284C     NOTLETTER JR   Z,NO_SHIFT    Jump only if no Shift keys

                                      were pressed

FE30               CP   "0"

C8                 RET  Z             Exit the program if Shift

                                      and "0" were pressed

FE31               CP   "1"

2016               JR   NZ,TEST_4     Jump unless Shift and "1"

                                      were pressed

7A                 LD   A,D

FE19               CP   #19

2804               JR   Z,RESET_UDG   Jump if Symbol Shift and

                                      "1" were pressed

---------.---------.------------------.-------------------------

0EFF     SET_UDG   LD   C,#FF         Set all the pixels of C

1802               JR   BLANK_UDG

---------.---------.------------------.-------------------------

0E00     RESET_UDG LD   C,#00         Reset all the pixels of C

---------.---------.------------------.-------------------------

CD4780   BLANK_UDG CALL FIND_UDG      HL:=address of UDG specified

0608               LD   B,#08

---------.---------.------------------.-------------------------

71       BL_LOOP   LD   (HL),C

23                 INC  HL

10FC               DJNZ BL_LOOP       Blank the entire UDG

186B               JR   EXIT_2        Jump to exit

---------.---------.------------------.-------------------------

FE34     TEST_4    CP   "4"

200D               JR   NZ,NEW_PIX    Jump unless Shift and "4"

                                      pressed

CD4780             CALL FIND_UDG      HL:=address of UDG specified

0608               LD   B,#08

---------.---------.------------------.-------------------------

7E       INV_LOOP  LD   A,(HL)        A:=next row of pixels

2F                 CPL                Change to inverse video

77                 LD   (HL),A        Invert the row

23                 INC  HL            Point to the next row

10FA               DJNZ INV_LOOP      Invert the whole character

185A               JR   EXIT_2        Jump to exit

---------.---------.------------------.-------------------------

F5       NEW_PIX   PUSH AF            Push the character code

7A                 LD   A,D

FE20               CP   #20

9F                 SBC  A,A           A:=00 if Caps Shift

                                      pressed, FF otherwise

E608               AND  #08           A:=00 or 08

EEDF               XOR  #DF           A:=DF or D7

FDAE77             XOR  (X_COORD)

07                 RLCA

07                 RLCA

07                 RLCA

322881             LD   (CHEAT),A     Specify the appropriate

                                      set or reset instruction

CD4780             CALL FIND_UDG      HL:=address of UDG specified

FD4E76             LD   C,(Y_COORD)

0600               LD   B,#00

09                 ADD  HL,BC         Point HL to row containing

                                      pixel at cursor position

CB00               DEFB CB 00

---------.---------.------------------.-------------------------

         CHEAT     $-1

F1                 POP  AF            A:=code of key pressed

---------.---------.------------------.-------------------------

FE35     NO_SHIFT  CP   "5"

2818               JR   Z,LEFT        Jump if "cursor left"

FE36               CP   "6"

282A               JR   Z,DOWN        Jump if "cursor down"

FE37               CP   "7"

281B               JR   Z,UP          Jump if "cursor up"

FE38               CP   "8"

202C               JR   NZ,EXIT_2     Exit unless "cursor right"

---------.---------.------------------.-------------------------

3AB15C   RIGHT     LD   A,(X_COORD)

FE07               CP   #07

2825               JR   Z,EXIT_2

FD3477             INC  (X_COORD)     Move cursor right

1820               JR   EXIT_2

---------.---------.------------------.-------------------------

3AB15C   LEFT      LD   A,(X_COORD)

A7                 AND  A

281A               JR   Z,EXIT_2

FD3577             DEC  (X_COORD)     Move cursor left

1815               JR   EXIT_2

---------.---------.------------------.-------------------------

3AB05C   UP        LD   A,(Y_COORD)

A7                 AND  A

280F               JR   Z,EXIT_2

FD3576             DEC  (Y_COORD)     Move cursor up

180A               JR   EXIT_2

---------.---------.------------------.-------------------------

3AB05C   DOWN      LD   A,(Y_COORD)

FE07               CP   #07

2803               JR   Z,EXIT_2

FD3476             INC  (Y_COORD)     Move cursor down

---------.---------.------------------.-------------------------

C35F80   EXIT_2    JP   #805F

!1.......^.........^.........^.........^........

!B



--

from Your Spectrum 6 (Aug.1984)

--

!$

