Hello User,

By now you may have become quite expert at BASIC programming on the 
Sinclair ZX81. You're probably making good use of one of the Memotech 
MEMOPAKs or another commercial RAM pack. But you'd like to try graphics 
- programming in a new dimension. Graphics can be great fun. Apart from 
space zombies to be zapped without serious risk to your health, there is 
a new world of design, animation, geometry and presentation to try. 
Again, we hope that you like our elegant design. Now let's tell you how 
it works.

How do I set up the Memopak HRG?

Disconnect your ZX81 power supply, and install your HRG pack between the 
ZX81 and your RAM pack. You need a RAM pack because the HRG routines 
operate primarily on the memory,- a screen image is held as a 'video 
page' in about 6.2K of RAM. The more RAM you've got the more video pages 
you can use. We recommend you use the Sinclair 1200 milliamp power supply 
as supplied with the Sinclair printer and recent ZX81's. You will find 
all MEMOPAK units plug in firmly, but for the best connection we suggest 
you cut up and use the velcro tabs provided. Moreover, our HRG pack 
utilises the addresses between 8 and 10K, so if you have a MEMOPAK 
64K you will have to make sure this area is switched out. This means 
you must set your switch either in MODE B (2 ON; 1, 3 and 4 OFF) or 
MODE D (4 ON; 1, 2 and 3 OFF). Remember ON is UP. With a 64K RAM pack 
you will probably want to put your video page above 49152. In this
case you should remove the little square jumper switch next to the back 
connector board. It's best to use a pair of tweezers or pliers 
(but disconnect the power first). To keep the jumper safe, you can 
replace it on just one pin.

Is there a quick test to show my pack is running OK?
Yes. Choose a spare memory area of at least 6.2K and set V to its start 
byte address. Then do our special call. So enter as follows:

LET V= 19000 (with jumper in) or

LET V = 50000 (with jumper out)

RAND USR 8619

What you should get is MEMOTECH appearing in white on a black background. 
If not, check your configuration and your connectors, and try again. 
When it's working, you can test the 'BASIC RE-SET' button which 
is located on the side of your pack. This is for returning you from your 
HRG display to your normal BASIC display.

Where and how are the HRG routines kept?
The MEMOPAK HRG contains a 2K EPROM where our subroutines reside and it's 
full to bursting. We have provided at least 30 functions in the firmware 
to help the user get the most out of the HRG. Our philosophy here has 
been in the Sinclair tradition: help the user to help himself. We have 
increased the scope of your activity; we leave you free to explore the 
new territory.

How does the HRG work?

Simply, the HRG allows you to output in dots rather than characters
 
(1 character=8x8=64 dots) or Sinclair pixels (1 pixel = 4 x 4= 16 dots). 
Since the dot is the smallest graphics item, it offers the maximum 
flexibility. Any shape, character or pattern can be generated by the 
right combination of dots, and the possibility of smoother curves 
increases. 
In everyday life, to fill a page with dots is a laborious process. But 
here the sweat is taken out of it by a number of means:

a) Subroutines which work much faster because they operate directly in 
   machine code.

b) Full use of looping facilities in both BASIC and machine code.

c} The ability to pre-plot special characters or mix in characters 
   from the Sinclair range.

d) Powerful rolling and scrolling facilities.

The range of subroutine calls is listed in a table in the back of the 
booklet. They span many functions, and are particularly powerful in 
their ability to make the most of your memory. They also span a number 
of different levels - dot, line, character, block and page.

How is the screen related to the memory?

As far as our pack is concerned, your screen is made up of 192 x 248 dots 
or HRG pixels (the equivalent area of 24 x 31 BASIC screen character 
positions). The leftmost column of the screen is ignored by the HRG 
- for subtle software reasons. All screen activity takes place in a 
'video page' of memory which you can show on the screen at the same time.
You can also manipulate the 'video page' without showing it on the screen;
or you can be looking at another video page while doing so!

How is a video page organised?

A variable is reserved by the HRG system to hold the memory address of 
the start byte of the video page. So always remember to set variable V 
to the start of the particular video page you want to reach. 
Roughly speaking, one screen dot (or HRG pixel) is stored in one bit of 
memory. However when placed in memory each horizontal 'line' of 248 
graphics bits is preceded by 2 bytes of control data. In addition, there 
is a single byte of screen control data terminating the whole video page.
So the arithmetic looks like this:

Bit Summary

		Line	Screen	    HRG
		Control	Graphics    Memory
		
        Line	16	+ 248	   = 264
	Page	3072	+ 47616    = 50688

1 video page= 50688+8 page control bits= 50696 bits.

Byte Summary

		Line     Screen      HRG
		Control  Graphics    Memory
        Line	2      + 31        = 33
        Page    384    + 5952      = 6336

1 video page = 6336 + 1 page control byte=6337 bytes.

Whereabouts in memory can I put a video page?

You must choose an area which is not otherwise occupied by the system 
variables, the instructions, the display file or your other arrays. 
The simplest thing is to set a low RAMTOP leaving you enough space 
(6337 bytes per video page) between that and your real limit of memory. 
Clever users may find other ways.

How do I use the HRG subroutines?

A subroutine is called by using the Sinclair USR function. We recommend 
the use of an instruction such as RAND, as this has few side effects, 
but other instructions may do. All the subroutines can be called 
initially from one address (8192), so that the same call can be used for 
any function:

RAND USR 8192

If however you want to reserve RAND to set the seed for the randomizer, 
then use, say, LET A = USR 8192. To nominate a particular subroutine 
however you must first specify its name in a reserved variable Z$. So to 
call for example the simple PLOT function (which sets a bit in the video 
page) you must first enter the instruction:

LET Z$= "PLOT"

"PLOT" in turn uses the X and Y variables to find out the co-ordinates 
to be plotted. So the whole step goes like this:

LET X = 64
LET Y = 100
LET Z$= "PLOT"
RAND USR 8192

This little routine, provided the right initialisation steps have been 
taken, will set one bit in the video page specified.
 
How do I use the MEMOPAK HRG with a BASIC program?

The MEMOPAK HRG has been designed so that you can use it in ordinary 
BASIC. There are also routines which allow you to switch the screen from 
conventional BASIC display to the HRG display and back again. 
While you are developing your program, you can use the manual 'BASIC 
RETURN' button on the side of the pack which puts you back into BASIC 
display mode, without in any way endangering your graphics data. 
When you return back to the BASIC display mode, you may be upset to find 
a blank screen. This is blank simply because although your BASIC program 
is running, it has not been requested to output anything to the 
screen. You'll probably want to look at your program listing at this 
point, so you need to use the Sinclair BREAK and LIST functions.

What about FAST mode?

These routines work rapidly in FAST mode, at least as rapidly as graphics 
on the Sinclair Spectrum and with more pixels. However, in FAST mode you 
lose the screen and the gratifying experience of seeing the graphics 
at work for you. Moreover in FAST mode the 'BASIC RETURN' button cannot 
work, so if you want to get back to BASIC display manually, you have to 
break in and enter"SLOW" even though there will be no screen response 
until you've done it. Now you can use the 'BASIC RETURN' button.

How do I initiate an HRG routine in my BASIC program? (Page functions}

The first thing is to set the start byte of your video page in the 
reserved variable V. Then you must cite an activate the "START" function.
Functions must always be cited in reserved variable Z$ prior to the call.
"START" does two things: initiates the HRG system and assigns the video 
page area (start address cited in V) to it. (Later in the program the 
"PAGE" function could be used to assign another video page without 
reinitiating the system.) (Note: the groups of instructions which follow 
are typical enoughl but when all put together they may form a pretty 
absurd program. For 'real' program examples see the back of this booklet). 
Your routine so far could well look like this:

10 LET V = 40000
20 LET Z$ = " START"
30 RAND USR 8192

You may now want to clear the video page area initially (or else you may 
pick up what you left there before remember an area above RAMTOP is not 
cleared by Sinclair).

40 LET Z$="CLEAR"

50 RAND USR 8192

Note the same USR address is used whatever the function. "CLEAR" also 
uses variable V to find out where the page to be cleared is located. 
Since we are talking about the same page that was assigned with the 
"START" function, there is no need to re-set V. All the activity so far 
has gone on in the memory video page and we haven't seen a thing. To keep 
your eye on what's going on, let's do an "HRG" call. This will do an HRG 
display of the memory page rather than display anything your BASIC 
program may have output. Don't worry, your BASIC outputs are still 
accessible (they're still in the Display or D-FILE), but they are now 
invisible.

60 LET Z$="HRG"
70 RAND USR 8192

Note that as we are still talking about the same video page, we still 
have not re-set V. The screen is now locked into our video page and 
anything that happens there, we can watch. "HRGINV" will also show what 
is in the page, but in reverse, and without changing the bits in the 
memory. So in just seven lines we are ready to start depicting something.
If seven lines is too much for you, we have kindly provided you with a 
macro (multiple) function: "STARCH". "STARCH" sounds like a new concept 
in programming for laundry control but really it simply means 
"START"+ "CLEAR" + "HRG" and the above program can now be shortened to 
3 instructions:

10 LET V = 40000
20 LET Z$="STARCH"
30 RAND USR 8192

To summarise: the HRG system is initialised; a video page is assigned 
from 40000 onwards; the page is cleared and the contents (blanks or 
unset HRG pixels) displayed. We can just mention 3 other page level 
functions: 
"PRINT" will transfer any video page to the Sinclair printer. 
"STRING" will let you pass a video page into a long string which can 
then be SAVEd on cassette by the ZX81. 
"UNSTRING't will unpack a string into a video page for you on re-LOADing.
The video string is always S$. You can use "STRING" simply to clear 
space for yourself above RAMTOP. But don't try to "UNSTRING" something 
which you did not "STRING" first, unless you are sure you have got the 
control characters right. When re-loading a video page with "UNSTRING" 
that has been stored and SAVED within the "STRING" function) it is 
necessary to:

a) make sure you do not use RUN for the re-load section but GOTO, in 
   order to prevent S$ from being cleared.

b) make sure you do not redimension S$ on re-entering as this will also 
   lose the array

c) remember to re-set V and call the "STARCH", "UNSTRING" and "HRG" 
   subroutines to see the video page again.

Sample re-load subroutine. Enter program with GOTO 1000.

 990 STOP
1000 LET V = 50000
1010 LFT Z$= "STARCH"
1020 RAND USR 8192
1030 LET Z$ = "UNSTRING"
1040 RAND USR 8192
1050 LET Z$= ~'HRG"
1060 RAND USR 8192
1070 GOTO....

Incidentally, if you don't like the idea of repeating the subroutine 
call - e.g . RAND USR 8192 - all the time, you may like to place it in 
a little subroutine. For some repeated calls, you might also like to set 
the parameters from within the routine as well.

What can I do now?

You are now free to experiment with the other subroutine functions (and their 
parameters) listed at the back.
 
They are broken down into five kinds: page functions, block functions, 
character functions, line functions and dot (or HRG pixel) functions. The page 
functions have already been described above. As for the rest, let's 
start small.

HRG pixel (or dot) routines 
The simplest function is "PLOT" which requires X and Y co-ordinate parameters 
in addition to V:

 80 LET X = 50
 90 LET Y = 60
100 LETZ$="PLOT"
110 RAND USR 8192

This will place a dot on your screen. Remember that the co-ordinates in X 
and Y work like this:

	Axis Range Direction 
X Horizontal 0-247 Left to right 
Y Vertical   0-191 Bottom to top

"UNPLOT" works in exactly the same way, so:

120 LET Z$ = "UNPLOT"
130 RAND USR 8192

will take the dot away again. If you want to find out whether an HRG pixel is 
set use "TEST", this time calling the routine with the Basic LET instruction 
for the reply:

140 LET Z$="TEST"
150 LET K=USR 8192
160 IF K=0 THEN .........
170 IF K= 1 THEN .........

Any variable may be used; if the routine returns 0 then the pixel is unset, if 
1 then set; and you can take action accordingly. In this case, since the 
routine is still testing the old X,Y locations, which we UNPLOTted, then the 
reply will be zero. With "HRG" called, your screen displays an image of the 
video page. However you can use the "LOCATE" function to find the absolute 
memory address of a pair of co-ordinates, and so manipulate the video page 
directly. Remember however, that the video page is not exactiy the same as a 
screen; there are two control bytes preceding each line (the first one is a 
Sinclair newline byte (118) and the second one is zero) and one more byte 
after the last line in the page (also 118). So if you want to interfere with 
a video page directly, take these into account. To find out where in 
memory our pixel location is, enter:

180 LET Z$="LOCATE"
190 LET K= USR 8192

and K will receive the address.

Can I run two or more video pages together?

Yes, they can be located next to each other in memory and will effectively 
be joined vertically. In this case the first line control byte of the later 
video page should be the same as the last page control byte of the first 
video page. It is now possible to look at any 'intermediate' page made up of 
later lines of the earlier page and earlier lines of the later page. To call 
such a page make sure that your start byte value placed in V is displaced 
from the start bytes of the 'real' video page by a multiple of 33.

What about Geometry?

At this point we can introduce our simple geometric functions. We could have 
provided more but we think it is an excellent chance for users to brush up on 
their skills. The only functions we provide are "LINE", "UNLINE", "BLINE" and 
"WLINE"; any other shape can be effected by combinations of these or the 
"PLOT" call, and the Sinclair maths functions. 
You'll need to work on your algebraic geometry, or dust off a text-book to 
get algorithms for curves, sine waves and so on. Try this natural log curve:

200 LET Z$ = "PLOT"
210 FOR X= 1 to 245
220 LET Y= 33 * LN X
230 RAND USR 8192
240 NEXT X

Line routines 
"LlNE" will join the points specified in the pairs of co-ordinates P, Q and 
X, Y and you should be able to do straight-edge geometry yourself. "UNLINE" 
will wipe out a line in the same way. "BLINE" (black line) and "WLINE" 
(white line) are used only for vertical plotting and will draw a line upwards 
from X, Y until a bit of the same setting is encountered. The vertical 
coordinate of the setting is returned in Y. Used in conjunction with the 
"LAUNCH" routine, some sophisticated shading routines are possible. See our 
example at the back. Lastly, for the zappers, there is our "LAUNCH" routine. 
This will fire a laser beam vertically up the screen and detect a 'hit' 
(i.e. if any of the bits in its path were set). If there is a hit, it passes 
back the vertical co-ordinate and vanishes. Otherwise, it disappears off the 
top of the screen. "LAUNCH" need not be used so aggressively; it can also 
serve as a 'radar' function to detect the presence of the first bit set in a 
vertical column rising from the X, Y position cited. This can be used for 
shading or blocking in.

Character routines

There are two kinds of character you can plot - those you've designed yourself 
and those Sinclair provides. To design a simple horizontal line of bit 
settings, simply set up a string of O's and 1's in C$, with a colon as 
terminator:

250 LET C$="10101:"

Instead of 0, you can use * to avoid disturbing the initial status of a bit. 
To design a 2-dimensional character you can simply use N, S, E or W (or a 
combination) to re-set the start location of the next series of bit settings, 
and continue. So we could plan a cross on the screen instead:

Type in

250 LET C$="1***1NE1*1NE1NW1*1NW1***1 :"
260 LET X = 30
270 LET Y = 40
280 LET Z$="SKETCH'
290 RAND USR 8192

and the cross will appear with the bottom left-hand point located at 30,40. 
In this example, we built the character upwards using N, but we could have 
dropped it downwards using S, or missed out a line altogether using SS.

"UNSKETCH" has the effect of unsetting the bits set in the string. 
"INVSKETCH" is like "SKETCH" except that it reverses the bit settings, 
placing a reverse image of your character in the video page itself. "SINCH" 
does the same thing as "SKETCH" except that you need to cite a Sinclair 
character. For reverse images, you can use Sinclair's own inverse functions. 
A whole string of Sinclair characters can be displayed anywhere in the page, 
starting at the X, Y point which represents the bottom left-hand corner of 
the first character. To wipe out a "SINCH" display, use the Sinclair space 
character.

Block handling routines 
For block handling routines, to save on tedious co-ordinates we have hit on 
the concept of north, south, east and west. For this reason, variables 
N S, E and W are called. We have two dynamic routines which can be useful 
for animated displaysroll and scroll. The "roll" functions take a block and 
shift the constituent lines up or down, taking the line that has dropped off 
the block at one end and adding it on at the other. This is done according 
the following 2-character command strings -"RU" (roll up) and "RD" (roll down), 
and these will use the N, S, E and W parameters. A similar set of commands 
exist for the scroll functions. "Scroll" differs from "roll" in that the line 
that drops off will completely disappear and a blank line will step in at the 
other end. Scrolling can be done horizontally as well as vertically. So these 
are the last four command strings you've got: "SU", "SD", "SR" and "SL". 
Note that when moving horizontally, E must be greater than W; when going 
vertically, N must be greater than S. 
Scrolling and rolling is most effective when set in a loop.

Subroutine Calls

Command
string (Z$)    Function                                       Parameter

Page routines
START          Initiates HRG system and assigns memory        V
	       video page

PAGE           assigns memory video page                      V
CLEAR          Clears a page                                  V
HRG            Displays a page                                V 
HRGINV         Displays a page inversly                       V
STARCH         Macro = Start + Clear + HRG                    V
PRINT          Prints a video page                            V
PRINT1         Prints top line of video page                  V
BASIC          Displays current BASIV page                    none
STRING         Copies page into BASIC string                  V, S$
UNSTRING       Copies string into video page                  V, S$
               (requires DIM S$(6337) or more) 
Block routines 
RU             Roll Block up                                  V,N,S,E,W
RD             Roll Block down                                V,N,S,E,W
SU             Scroll Block up                                V,N,S,E,W
SD             Scroll Block down                              V,N,S,E,W
SR             Scroll Block right                             V,N,S,E,W
SL             Scroll block left                              V,N,S,E,W

Character routines 
SKETCH         Plots user-defined character                   V,X,Y,C$
UNSKETCH       Unplots userdefined character                  V,X,Y,C$
INVSKETCH      Reverses user defined character in
               page and screen                                V,X,Y,C$
SINCH          Plots ZX81-defined character                   V,X,Y,C$

Line routines
LINE	       Draws a line	                              V,X,Y,P,Q	
UNLINE         Wipes out a line	                              V,X,Y,P,Q	
*BLINE         Draws black line 'UP' until set BIT            V,X,Y
*WLINE         Draws white line 'UP' until set BIT            V,X,Y
*LAUNCH        Draws momentary line 'UP' until set BIT        V,X,Y

Dot routines 
PLOT           Sets one BIT/HRG pixel                         V,X,Y
UNPLOT         unsets one BIT/HRG pixel                       V,X,Y
*TEST          Gets a setting of a BIT                        V,X,Y
*LOCATE        Gets a memory location of a BIT                V,X,Y
	

* These calls elicit a reply and so should be made with the LET statement:

LET G = USR 8192

will place the reply in G. "LAUNCH", "BLINE" and "WLINE" will get a value 
of the vertical coordinate or zero if none is found. "TEST" will get a 
value of zero for an unset, one for a set bit. "LOCATE" will get the 
absolute memory address of a bit set. Or you can use a logic test:

IF NOT USR 8192 THEN GOTO 1000

HRG Parameters
Z$ = Command string
V  = Start byte of assigned video page
X  = Horizontal co-ordinates (0-247)
Y  = Vertical co-ordinates (0-191 )
P  = Secondary horizontal co-ordinates (0-247)
Q  = Secondary vertical co-ordinates (0-191 )
N  = Uppermost block line (0-191 )
S  = Lowest block line (0-191 )
E  = Rightmost block line (0-247)
W  = Leftmost block line (0-247)
C$ = String for "SKETCH", "SINCH" etc.
S$ = String for storing video page data

HRG error codes
L = Parametervariable not declared
M = HRG command string not known
N = Horizontal parameter too large
O - Vertical parameter too large
P = Invalid element in "SKETCH" string

Here are some examples to try:

A) To draw two waves, and shade in the areas between.

 10 LET V = 40000
 20 LET Z$ = "STARCH"
 30 RAND USR 8192
 40 LET Z$ = "PLOT"
 50 FOR X = 0 TO 247
 60 LET Y = 100+50*SIN(X/20)
 70 RAND USR 8192
 80 LET Y = 100 + SIN (X/30) * COS(X/15) * 50
 90 RAN D USR 8192
100 NEXT X
110 FOR X = 0 TO 247
120 LET Y = 0
130 LET Z$ = "LAUNCH"
140 LET Y=1 + USR 8192
150 LET P = USR 8192
160 IF P = 0 THEN GOTO 190
170 LET Z$ = "BLINE"
180 RAND USR 8192
190 NEXT X

Run it and see. Is it a bird? Is it a Loch Ness Monster? 
A few notes about the program: "LAUNCH" detects the first set bit in a 
vertical pattern. In line 140 we add 1 and use that as the start of "BLINE"
which will draw a black line up until the next set bit. Sometimes, we 
don't want to draw a line up, so we test to make sure that a second bit 
exists as in lines 150-160.

B) To make a beautiful pattern from curves. Is it a bird? is it a seal?

 10 LET V = 40000
 20 LET Z$= "STARCH"
 30 RAND USR 8192
 40 LET Z$ = "PLOT"
 50 FOR A= 10 TO 100 STEP 3
 60 LET D = A * A
 70 LET C = D * 190
 80 FOR X = 0 TO 247
90 LET Y = C/(X * X + D)
100 RAND USR 8192
110 NEXT X
120 NEXT A

C) Here is a program which shows a funny clock. We're sure you could make 
it better- more accurate; with hours as well. Change line 80 to make it 
slow down or speed up. 
 10 LET V = 40000 
 20LET Z$ = "STARCH" 
 30 RAND USR 8192 
 40 LET P= 100 
 50 LET Q= 100 
 60 FOR T=1 TO 60 
 70 GOSUB 130 
 80 FOR Z= 1 TO 20 
 90 NEXT Z 
100 GOSUB 210 
110 NEXT T 
120 STOP 
130 LET X= 100 + 50*SIN (T* PI/30) 
140 LET Y= 100 + 50*COS (T* PI/30)
150 LET Z$ = "SlNCH"
160 LET C$ = STR$ T
170 RAND USR 8192
180 LET Z$ ="LINE"
190 RAND USR 8192
200 RETURN
210 LET X= 100+50*SIN(T* PI/30)
220 LET Y = 100 + 50*COS (T* PI/30)
230 LET Z$ = "UNLINE"
240 RAND USR 8192
250 RETURN

Good Luck from all at MEMOTECH