!0.......^.........^.........^..
!B
\H11\H07      \H10\H04movin' \H10\H02& \H10\H04a'groovin'       

!2.......^.........^.........^.........^.........^.........^....
 Lights, action, music ... Our own top of the pops programmer,
  Andy Pennell, has brought to light a spectacular all-action
  program that'll knock your eyeballs for six. All you have to
                      supply is the music!
!1.......^.........^.........^.........^........

One million pounds - that's how much your  Spec-
trum  and  this  program  can  save you! No,  we
haven't   caught  Bingo  fever,  so  I'd  better
explain.  Have  you  ever  watched  the  graphic
effects on telly programmes like Top of the Pops
and wished you and your Speccy could match them?
Well,  now  you  can - well, almost - thanks  to
these  routines.  OK,  so they won't quite  turn
your  Spectrum  into a \H601,000,000 Quantel,  like
the  Beeb uses, but they'll certainly make  your
programs go with a swing.
  So, what's on offer that'll turn your programs
into chart-toppers? Well, all these routines put
on  picture  onto  the screen over another in  a
variety  of  spectacular ways. You can now  pan,
fade, zoom in, zoom out, corner zoom, horizontal
flip  and vertical flip. And if this all  sounds
like a sort of on-screen breakdance, right on!

!0.......^.........^.........^..
!B
!P\H11\H05\H10\H00\H13\H00
STAR TURNS                      
!1.......^.........^.........^.........^........
!P\H11\H05\H10\H00\H13\H00
Now  we've got to admit that these screen  shots
do  lack a certain something - movement  mostly!
So,  you'll  just have to take our word for  the
stunning visual effects that you can conjure  up
with these routines.

To  the  left  -  quick scroll. The new  picture
scrolls  in  from  the right to replace the  old
one. It's pantastic!

!Sscrollh

!1.......^.........^.........^.........^........
!P\H11\H05\H10\H00\H13\H00
Swoon  as  one picture fades away into  another.
You  can experiment with all different sorts  of
fades till you have the one that suits you.

!Sfade

!1.......^.........^.........^.........^........
!P\H11\H05\H10\H00\H13\H00
There are two zooms but only one picture, as you
wouldn't be able to tell the difference  between
them. Zoom Out zooms the new pic from the middle
of the old one and Zoom In reverses the process.

!Szoom

!1.......^.........^.........^.........^........
!P\H11\H05\H10\H00\H13\H00
Here the zoom service moves the new picture from
the top left corner over the old one.

!Szoomc

!1.......^.........^.........^.........^........
!P\H11\H05\H10\H00\H13\H00
And now you've finally flipped (vertically) and
turned the screen image on its head.

!Sflipv

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

!B
\H11\H07\H10\H00THE BASIC LOADER                
!2.......^.........^.........^.........^.........^.........^....
!P\H11\H07\H10\H00
For the brave, here is the Basic loader that POKEs the code into
place  and saves it onto Microdrive - change the syntax in  line
50 if you're using tape. For the not so brave, remember the com-
plete program is on this month's Dig'T'ape!
!3.......^.........^.........^.........^..

   1 CLEAR 59999
   5 RESTORE : LET z=0
  10 FOR i=60000 TO 60880
  20 READ a: LET z=z+a
  30 POKE i,a
  40 NEXT i
  45 IF z<>95823 THEN  PRINT "Data error":
 STOP
  50 SAVE *"m";1;"TP"CODE 60000,900
1000 DATA 1,176,234,24,40,1,166,234
1010 DATA 24,35,1,221,234,24,30,1
1020 DATA 26,235,24,25,1,244,235,24
1030 DATA 20,1,17,236,24,15,1,46
1040 DATA 236,24,10,195,23,237,0,0
1050 DATA 195,115,237,0,0,243,33,164
1060 DATA 234,229,197,42,11,92,35,126
1070 DATA 254,14,194,138,28,35,35,35
1080 DATA 94,35,86,201,251,201,235,17
1090 DATA 0,64,1,0,27,237,176,201
1100 DATA 33,0,64,24,245,14,31,33
1110 DATA 1,64,17,33,0,229,6,192
1120 DATA 126,43,119,25,16,250,225,229
1130 DATA 17,0,24,25,17,33,0,6
1140 DATA 32,126,43,119,25,16,250,225
1150 DATA 35,13,32,225,201,6,32,213
1160 DATA 221,225,197,205,181,234,221,229
1170 DATA 6,192,33,31,64,17,32,0
1180 DATA 221,126,0,119,25,221,25,16
1190 DATA 247,221,225,221,229,17,0,24
1200 DATA 221,25,33,31,88,17,32,0
1210 DATA 67,221,126,0,119,25,221,25
1220 DATA 16,247,221,225,221,35,193,16
1230 DATA 201,201,213,221,225,221,229,33
1240 DATA 0,64,1,0,24,17,7,0
1250 DATA 221,126,0,119,25,221,25,124
1260 DATA 254,88,56,8,38,64,221,124
1270 DATA 214,24,221,103,11,120,177,32
1280 DATA 231,225,17,0,24,25,17,0
1290 DATA 88,1,0,3,237,176,201,221
1300 DATA 94,0,221,86,1,221,70,4
1310 DATA 213,205,130,235,209,221,70,5
1320 DATA 205,164,235,221,94,2,221,86
1330 DATA 3,221,70,4,205,130,235,221
1340 DATA 126,0,221,86,1,221,134,4
1350 DATA 214,1,95,221,70,5,205,164
1360 DATA 235,201,14,8,213,197,213,42
1370 DATA 21,237,25,126,18,19,16,247
1380 DATA 209,193,20,13,32,239,209,205
1390 DATA 234,235,42,21,237,25,72,6
1400 DATA 0,237,176,201,72,120,167,40
1410 DATA 47,213,42,21,237,25,126,18
1420 DATA 205,217,235,16,245,209,221,229
1430 DATA 121,203,63,203,63,203,63,71
1440 DATA 205,234,235,42,21,237,25,213
1450 DATA 221,225,17,32,0,126,221,119
1460 DATA 0,25,221,25,16,247,221,225
1470 DATA 201,20,122,230,7,32,10,123
1480 DATA 198,32,95,63,159,230,248,130
1490 DATA 87,201,122,15,15,15,230,3
1500 DATA 246,88,87,201,235,17,0,64
1510 DATA 167,237,82,34,21,237,221,33
1520 DATA 181,236,6,16,197,205,79,235
1530 DATA 193,17,6,0,221,25,16,244
1540 DATA 201,235,17,0,64,167,237,82
1550 DATA 34,21,237,221,33,15,237,6
1560 DATA 16,197,205,79,235,193,17,250
1570 DATA 255,221,25,16,244,201,235,17
1580 DATA 0,64,167,237,82,34,21,237
1590 DATA 221,33,187,236,6,1,62,192
1600 DATA 221,150,5,203,63,198,8,79
1610 DATA 120,254,16,56,7,121,214,8
1620 DATA 221,134,5,79,197,17,0,64
1630 DATA 205,130,235,17,0,64,193,197
1640 DATA 65,205,164,235,193,197,120,254
1650 DATA 16,56,8,221,86,3,221,126
1660 DATA 2,24,6,221,86,1,221,126
1670 DATA 0,230,224,95,205,130,235,193
1680 DATA 197,221,126,0,230,31,95,120
1690 DATA 254,16,56,4,123,238,31,95
1700 DATA 22,64,65,205,164,235,193,17
1710 DATA 6,0,120,254,16,56,3,17
1720 DATA 250,255,221,25,4,120,254,32
1730 DATA 40,10,254,16,32,144,221,33
1740 DATA 15,237,24,138,201,0,64,224
1750 DATA 80,32,192,33,64,193,80,30
1760 DATA 176,66,64,162,80,28,160,67
1770 DATA 64,163,80,26,160,100,64,132
1780 DATA 80,24,144,133,64,101,80,22
1790 DATA 128,134,64,102,80,20,128,167
1800 DATA 64,71,80,18,112,200,64,40
1810 DATA 80,16,96,233,64,9,80,14
1820 DATA 80,10,72,234,72,12,64,11
1830 DATA 72,235,72,10,64,44,72,204
1840 DATA 72,8,48,77,72,173,72,6
1850 DATA 32,110,72,142,72,4,16,111
1860 DATA 72,143,72,2,16,0,0,33
1870 DATA 15,64,221,33,16,64,14,16
1880 DATA 229,221,229,17,32,0,6,192
1890 DATA 197,126,8,221,126,0,14,128
1900 DATA 23,203,25,48,251,113,8,14
1910 DATA 128,23,203,25,48,251,221,113
1920 DATA 0,25,221,25,16,227,193,221
1930 DATA 225,225,229,221,229,197,17,0
1940 DATA 24,25,221,25,17,32,0,6
1950 DATA 24,126,8,221,126,0,119,8
1960 DATA 221,119,0,25,221,25,16,241
1970 DATA 193,221,225,225,221,35,43,13
1980 DATA 32,174,201,221,33,128,72,33
1990 DATA 96,79,6,12,197,221,229,229
2000 DATA 14,8,221,229,229,6,32,126
2010 DATA 8,221,126,0,119,8,221,119
2020 DATA 0,35,221,35,16,241,225,221
2030 DATA 225,37,221,36,13,32,227,209
2040 DATA 193,197,213,205,234,235,98,107
2050 DATA 80,89,205,234,235,6,32,26
2060 DATA 8,126,18,8,119,35,19,16
2070 DATA 246,225,221,225,193,17,32,0
2080 DATA 221,125,254,224,32,3,17,32
2090 DATA 7,167,237,82,221,25,16,172
2100 DATA 201

!0.......^.........^.........^..
!B
!P\H11\H07\H10\H00
TOP OF THE POPS                 
!2.......^.........^.........^.........^.........^.........^....
!P\H11\H07\H10\H00
Here  then are the routines that'll hype your Spectrum into  the
hippest hardware around. Let's begin by looking at how the Basic
functions  interact with the machine code. When a function  gets
called,  the  values of any parameters are stored in the DEF  FN
statement,  though you never actually see them in your  listing.
The following routines utilise this fact, along with the  system
variable  DEFADD  which points to the DEF FN statement, to  read
the integer parameter. But beware, it makes no checks to see  if
it's actually an integer, so if you pass it a string or a float-
ing point number it won't notice and may crash.
  After  the entry points, come the Load and Save routines  that
save  the  screen  image in memory and then load it from  memory
onto  the screen. They're really quite trivial, consisting of  a
quick LDIR to move the bytes.

!3.......^.........^.........^.........^..
;entry points
       LD   BC,SAVESC
       JR   START
       LD   BC,LOADSC
       JR   START
       LD   BC,ACROSS
       JR   START
       LD   BC,FADE
       JR   START
       LD   BC,ZOOMIN
       JR   START
       LD   BC,ZOOMOT
       JR   START
       LD   BC,TOPLZM
       JR   START
       JP   FLIPHO
       DEFB 0,0
       JP   FLIPVE
       DEFB 0,0
;general entry point
START  DI ;for speed
       LD   HL,ENDING
       PUSH HL
       PUSH BC ;the routine
;now get the parameter
       LD   HL,(23563) ;DEFADD
       INC  HL
       LD   A,(HL)
       CP   14 ;check +p marker
       JP   NZ,#1C8A
       INC  HL
       INC  HL
       INC  HL
       LD   E,(HL) ;read the integer
       INC  HL
       LD   D,(HL)
       RET
ENDING EI
       RET
;LOAD SCREEN from location DE
LOADSC EX   DE,HL
       LD   DE,#4000
MOVESC LD   BC,6912
       LDIR ;copy it all
       RET
;SAVE SCREEN to location DE
SAVESC LD   HL,#4000
       JR   MOVESC

!0.......^.........^.........^..
!B
!P\H11\H07\H10\H00
THE PAN                         
!2.......^.........^.........^.........^.........^.........^....
!P\H11\H07\H10\H00
This  is a left to right horizontal scroll - SCRHOR scrolls  the
screen  one character square to the left as neatly as  possible.
Notice  that  I didn't say as fast as possible - for that  you'd
have to use LDIR but the disadvantage there is that the bit  map
moves  long before the attributes. They get visibly left  behind
during  the scroll and create one hell of an untidy mess on  the
screen.
  This  scroll  (and  all  the  other routines here) only  moves
sections  of  the  bit  map  at a time, closely followed by  the
attributes  'under'  the  section  of the bit map. That way  any
annoying  flicker is kept to the bare minimum. SCRHOR moves  the
screen column by column and so avoids the 'diagonal' effect  you
get  by  doing  it line by line. ACROSS is the main pan  routine
that  scrolls the screen 32 times - after each time, it draws  a
little bit more of the new screen on the right-hand column.

!3.......^.........^.........^.........^..
;horizontal scroll routine
SCRHOR LD   C,#1F ;columns
       LD   HL,#4001
       LD   DE,33
HORIZ  PUSH HL ;save top address
       LD   B,192
HORIZL LD   A,(HL)
       DEC  HL
       LD   (HL),A ;scroll it
       ADD  HL,DE ;next line
       DJNZ HORIZL
;now do the attrs
       POP  HL
       PUSH HL
       LD   DE,#1800
       ADD  HL,DE
       LD   DE,33
       LD   B,32
HATTR  LD   A,(HL)
       DEC  HL
       LD   (HL),A
       ADD  HL,DE
       DJNZ HATTR ;move a column
       POP  HL
       INC  HL ;next column
       DEC  C
       JR   NZ,HORIZ ;do all columns
       RET

;the horizontal scroll/mix routine
ACROSS LD   B,32 ;scrolls read
       PUSH DE
       POP  IX ;the other screen
ACLP   PUSH BC
       CALL SCRHOR ;scroll it
       PUSH IX
;now put the next bit of the other
;screen on RHS
       LD   B,192
       LD   HL,#4000+31 ;RHS
       LD   DE,32
HCOPY  LD   A,(IX+#00)
       LD   (HL),A ;copy it
       ADD  HL,DE
       ADD  IX,DE ;inc both
       DJNZ HCOPY ;do whole col
       POP  IX
;now copy attrs
       PUSH IX
       LD   DE,#1800
       ADD  IX,DE ;others attrs
       LD   HL,#5800+31
       LD   DE,32
       LD   B,E ;=32
HCPAT  LD   A,(IX+#00)
       LD   (HL),A
       ADD  HL,DE
       ADD  IX,DE
       DJNZ #EB09
       POP  IX
       INC  IX
       POP  BC
       DJNZ ACLP ;do all pict
       RET

!0.......^.........^.........^..
!B
!P\H11\H07\H10\H00
THE FADE                        
!2.......^.........^.........^.........^.........^.........^....
!P\H11\H07\H10\H00
FADE  puts a piccy onto the screen by copying every seven  bytes
and wrapping around when it gets to the end of the screen. Seven
is the "fade factor" which I came up with after trial and error.
You're welcome to try other fade factors just so long as they're
odd numbers less than 256. That way you can pick your favourite,
but  be  warned,  some  look very boring. If you end up with  7,
don't say I didn't tell you!

!3.......^.........^.........^.........^..
;FADE one screen into another
FADE   PUSH DE
       POP  IX
       PUSH IX
       LD   HL,#4000
       LD   BC,6144
       LD   DE,7 ;fade factor
FADELP LD   A,(IX+#00)
       LD   (HL),A ;copy to screen
       ADD  HL,DE
       ADD  IX,DE ;next one
       LD   A,H
       CP   #58
       JR   C,ONS2
;gone past end of screen so wrap around
       LD   H,#40
       DEFB #DD
       LD   A,H
       SUB  #18
       DEFB #DD
       LD   H,A
ONS2   DEC  BC
       LD   A,B
       OR   C
       JR   NZ,FADELP ;do all the screen
;pic map done so copy attrs onto display
       POP  HL
       LD   DE,#1800
       ADD  HL,DE
       LD   DE,#5800
       LD   BC,768
       LDIR ;copy them
       RET

!0.......^.........^.........^..
!B
!P\H11\H07\H10\H00
THE ZOOMS                       
!2.......^.........^.........^.........^.........^.........^....
!P\H11\H07\H10\H00
Like  all these routines, the zoom is an optical illusion.  ZOOM
takes  the data stored at IX in order to draw a box from one  of
your pictures onto the screen. It's used in both the zoom in and
zoom  out  routines,  where you'll see that the box it makes  is
formed  from a horizontal block for the top and bottom, and  two
vertical  blocks for the left and right. DOHORIZ and DOVERT  are
the  general  subroutines  that  draw  blocks from a picture  in
memory onto the screen. The subroutine DEDOWN alters DE so  that
it  points to the pixel directly below it on the screen.  DEATTR
converts DE from the bit map into the location of the  attribute
'under' it.

!3.......^.........^.........^.........^..
;DRAW BOX IX
ZOOM   LD   E,(IX+#00)
       LD   D,(IX+#01) ;start of top left
       LD   B,(IX+#04) ;width
       PUSH DE
       CALL DOHORI ;do the top
       POP  DE
       LD   B,(IX+#05) ;depth
       CALL DOVERT ;do the left
       LD   E,(IX+#02)
       LD   D,(IX+#03) ;start of bottom left
       LD   B,(IX+#04) ;width
       CALL DOHORI ;do bottom
       LD   A,(IX+#00)
       LD   D,(IX+#01)
       ADD  A,(IX+#04)
       SUB  #01
       LD   E,A ;DE=start address of RHS
       LD   B,(IX+#05)
       CALL DOVERT ;do right
       RET

;do a horizontal box
;with starting address
;in DE, width in B
DOHORI LD   C,#08 ;pixels high
       PUSH DE ;save address
HBOX   PUSH BC
       PUSH DE
HBOXLP LD   HL,(DISP)
       ADD  HL,DE
       LD   A,(HL)
       LD   (DE),A ;copy
       INC  DE ;go along
       DJNZ HBOXLP ;do a line
       POP  DE
       POP  BC
       INC  D ;DE down a line
       DEC  C
       JR   NZ,HBOX ;do 8 lines
;colour
       POP  DE
       CALL DEATTR
       LD   HL,(DISP)
       ADD  HL,DE
       LD   C,B
       LD   B,#00
       LDIR ;copy attrs to screen
       RET
;do a vertical box
;top at DE, B deep
DOVERT LD   C,B ;save for later
       LD   A,B
       AND  A
       JR   Z,NOVERT ;if no box required
       PUSH DE
DOVELP LD   HL,(DISP)
       ADD  HL,DE
       LD   A,(HL)
       LD   (DE),A ;copy to screen
       CALL DEDOWN ;next pixel down
       DJNZ DOVELP ;do the whole depth
;now do the colour
       POP  DE
       PUSH IX ;save it
       LD   A,C
       SRL  A
       SRL  A
       SRL  A
       LD   B,A ;height in chars
       CALL DEATTR
       LD   HL,(DISP)
       ADD  HL,DE
       PUSH DE
       POP  IX
       LD   DE,32
VBATTR LD   A,(HL)
       LD   (IX+#00),A ;copy vertical column
       ADD  HL,DE ;of attrs
       ADD  IX,DE
       DJNZ VBATTR
       POP  IX
NOVERT RET

;alter DE to pixel directly below
DEDOWN INC  D
       LD   A,D
       AND  #07
       JR   NZ,EASY
       LD   A,E ;straddles a 1/3 boundary
       ADD  A,32
       LD   E,A
       CCF
       SBC  A,A
       AND  #F8
       ADD  A,D
       LD   D,A
EASY   RET
;convert DE from bit map into attr file
DEATTR LD   A,D
       RRCA
       RRCA
       RRCA
       AND  #03
       OR   #58
       LD   D,A
       RET

!2.......^.........^.........^.........^.........^.........^....
!B
!P\H11\H07\H10\H00
ZOOMIN  and  ZOOMOT are the main zoom entry points that use  the
box  data  table and the ZOOM subroutine, though obviously in  a
different order to create their opposing effects.

!3.......^.........^.........^.........^..
;ZOOM IN
ZOOMIN EX   DE,HL
       LD   DE,#4000
       AND  A
       SBC  HL,DE
       LD   (DISP),HL ;screen difference
       LD   IX,ZDATA
       LD   B,16 ;no of boxes
ZINLP  PUSH BC
       CALL ZOOM ;do the box
       POP  BC
       LD   DE,6
       ADD  IX,DE
       DJNZ ZINLP
       RET
;ZOOM OUT
ZOOMOT EX   DE,HL
       LD   DE,#4000
       AND  A
       SBC  HL,DE
       LD   (DISP),HL
       LD   IX,ZDATEN
       LD   B,16
ZOUTLP PUSH BC
       CALL ZOOM
       POP  BC
       LD   DE,-6 ;go outwards
       ADD  IX,DE
       DJNZ ZOUTLP
       RET

!2.......^.........^.........^.........^.........^.........^....
!B
!P\H11\H07\H10\H00
TOPLZM  is the routine for a corner zoom from the top left.  I'd
intended to do zooms from the other three corners but found them
much  tougher than I'd bargained for. So, now it's up to you  to
come up with the goods!

!3.......^.........^.........^.........^..
;ZOOM FROM TOP LEFT
TOPLZM EX   DE,HL
       LD   DE,#4000
       AND  A
       SBC  HL,DE
       LD   (DISP),HL
       LD   IX,ZDATA+6
       LD   B,1
TOPLP  LD   A,192
       SUB  (IX+#05)
       SRL  A
       ADD  A,#08
       LD   C,A ;=x coord reflected
       LD   A,B
       CP   16
       JR   C,TOPZM
       LD   A,C
       SUB  #08
       ADD  A,(IX+#05) ;handle lower 1/2
       LD   C,A
TOPZM  PUSH BC
       LD   DE,#4000
       CALL DOHORI ;top box
       LD   DE,#4000
       POP  BC
       PUSH BC
       LD   B,C
       CALL DOVERT ;left box
       POP  BC
       PUSH BC
       LD   A,B
       CP   16
       JR   C,TOPZM2
       LD   D,(IX+#03) ;for lower half
       LD   A,(IX+#02)
       JR   TOPZM3
TOPZM2 LD   D,(IX+#01) ;for upper half
       LD   A,(IX+#00)
TOPZM3 AND  #E0 ;make it the very left
       LD   E,A
       CALL DOHORI ;do the bottom
       POP  BC
       PUSH BC
       LD   A,(IX+#00)
       AND  #1F
       LD   E,A ;x coord only
       LD   A,B
       CP   16
       JR   C,TOPPZM4
       LD   A,E
       XOR  #1F ;reflect lower half x pos
       LD   E,A
TOPZM4 LD   D,#40 ;top line of screen
       LD   B,C
       CALL DOVERT ;right
       POP  BC
       LD   DE,6
       LD   A,B
       CP   16
       JR   C,TOPZM5
       LD   DE,-6
TOPZM5 ADD  IX,DE ;go backwards or forwards
       INC  B
       LD   A,B
       CP   32
       JR   Z,QUITTZ
       CP   16
       JR   NZ,TOPLP
;now do the lower screen
       LD   IX,ZDATEN
       JR   TOPLP
QUITTZ RET

!2.......^.........^.........^.........^.........^.........^....
!B
!P\H11\H07\H10\H00
The ZDATA table is for the series of boxes that make up a  zoom.
I worked it out on squared paper. It's also used, though differ-
ently, in the TOPLZM routine.

!3.......^.........^.........^.........^..
;data for zoom boxes in the form
;top, left, bottom, right,
;width (chars), depth (pixels)
ZDATA  DEFW #4000,#50E0
       DEFB 32,192
       DEFW #4021,#50C1
       DEFB 30,176
       DEFW #4042,#50A2
       DEFB 28,160
       DEFW #4043,#50A3
       DEFB 26,160
       DEFW #4064,#5084
       DEFB 24,144
       DEFW #4085,#5065
       DEFB 22,128
       DEFW #4086,#5066
       DEFB 20,128
       DEFW #40A7,#5047
       DEFB 18,112
       DEFW #40C8,#5028
       DEFB 16,96
       DEFW #40E9,#5009
       DEFB 14,80
       DEFW #480A,#48EA
       DEFB 12,64
       DEFW #480B,#48EB
       DEFB 10,64
       DEFW #482C,#48CC
       DEFB 8,48
       DEFW #484D,#48AD
       DEFB 6,32
       DEFW #486E,#488E
       DEFB 4,16
ZDATEN DEFW #486F,#488F
       DEFB 2,16
DISP   DEFW #0000

!2.......^.........^.........^.........^.........^.........^....
!B
!P\H11\H07\H10\H00
The  horizontal flip is noticeably slower than the vertical  one
because it has to turn all the bits around for each byte.

!3.......^.........^.........^.........^..
;flip screen horizontal
FLIPHO LD   HL,#400F ;LHS
       LD   IX,#4010 ;RHS
       LD   C,16 ;width/2
FLIPH  PUSH HL
       PUSH IX
       LD   DE,32
       LD   B,192
       PUSH BC ;save C
FLIPH2 LD   A,(HL)
       EX   AF,AF'
       LD   A,(IX+#00)
       LD   C,128
SWITCH RLA
       RR   C
       JR   NC,SWITCH ;turn around
       LD   (HL),C
       EX   AF,AF'
       LD   C,128
SWIT2  RLA
       RR   C
       JR   NC,SWIT2 ;turn around
       LD   (IX+#00),C ;swap them over
       ADD  HL,DE
       ADD  IX,DE
       DJNZ FLIPH2 ;swap a column
;now do colour
       POP  BC
       POP  IX
       POP  HL
       PUSH HL
       PUSH IX
       PUSH BC
       LD   DE,#1800
       ADD  HL,DE
       ADD  IX,DE
       LD   DE,32
       LD   B,24
FLATTR LD   A,(HL)
       EX   AF,AF'
       LD   A,(IX+#00)
       LD   (HL),A
       EX   AF,AF'
       LD   (IX+#00),A ;swap attrs
       ADD  HL,DE
       ADD  IX,DE
       DJNZ FLATTR ;do a column
       POP  BC
       POP  IX
       POP  HL
       INC  IX ;more right
       DEC  HL ;move left
       DEC  C
       JR   NZ,FLIPH ;do all the columns
       RET
;FLIP VERTICAL
FLIPVE LD   IX,#4880
       LD   HL,#4F60
       LD   B,12
FVERT  PUSH BC
       PUSH IX
       PUSH HL
       LD   C,#08
;swap two rows
SWVER2 PUSH IX
       PUSH HL
       LD   B,32
SWVERT LD   A,(HL)
       EX   AF,AF'
       LD   A,(IX+#00)
       LD   (HL),A
       EX   AF,AF'
       LD   (IX+#00),A ;swap them
       INC  HL
       INC  IX
       DJNZ SWVERT ;swap a pixel line
       POP  HL
       POP  IX
       DEC  H ;up a pixel
       DEFB #DD
       INC  H ;down a pixel
       DEC  C
       JR   NZ,SWVER2 ;swap two rows
;colour now
       POP  DE ;HL
       POP  BC ;IX
       PUSH BC
       PUSH DE
       CALL DEATTR
       LD   H,D
       LD   L,E ;HL=one line
       LD   D,B
       LD   E,C
       CALL DEATTR ;DE=other
       LD   B,32
SVATTR LD   A,(DE)
       EX   AF,AF'
       LD   A,(HL)
       LD   (DE),A
       EX   AF,AF'
       LD   (HL),A ;swap attrs
       INC  HL
       INC  DE
       DJNZ SVATTR ;do the whole row
       POP  HL
       POP  IX
       POP  BC
;now make HL go up, IX down
       LD   DE,32
       DEFB #DD
       LD   A,L
       CP   #E0
       JR   NZ,EASYUP
       LD   DE,#0720 ;if over a boundary
EASYUP AND  A
       SBC  HL,DE ;up
       ADD  IX,DE ;down
       DJNZ FVERT ;do 12x2 lines
       RET
       END
!0.......^.........^.........^..

!B
\H11\H06\H10\H02SHOWIN' OFF                     
!2.......^.........^.........^.........^.........^.........^....
!P\H11\H06\H10\H00
Just  to get you going, here's a simple demo program. As all  of
the  routines, except the flips, need to be told the address  of
the  picture  to  be put onto the screen, they use User  Defined
functions in an unusual way - there are no POKEs or anything  to
use them. So, you'll have to use the following lines of Basic:
!0.......^.........^.........^..
!P\H11\H06\H10\H00
                                
Save Screen      RAND FN S(x)   
Load Screen      RAND FN L(x)   
Horizontal Pan   RAND FN H(x)   
Fade             RAND FN F(x)   
Zoom In          RAND FN I(x)   
Zoom Out         RAND FN O(x)   
Corner Zoom      RAND FN T(x)   
Flip Horizontal  RAND USR fh    
Flip Vertical    RAND USR fv    
                                
!2.......^.........^.........^.........^.........^.........^....
!P\H11\H06\H10\H00
The  'x'  in  the  lines should be the address in memory of  the
screen  you  want  displayed  -  or in the case of FN L(x),  the
address where you want the screen saved.
  The  demo  program  loads  two pictures called S1 and S2  into
memory - you can change these to suit your favourite screens and
of  course,  remember  to change the syntax if you're not  using
microdrives. First, start the program with RUN 9999. After this,
a  RUN  will  do and after that a GO TO 1010 is all you need  to
warm  start  it. For the sake of simplicity, I've only used  two
screens  in  this  demo.  But just think what you could do  with
Chris Wood's Screen Scrunger from YS 13. That way you'd fit many
more  screens  into  memory  and get a really tremendous  moving
graphic display. A million quid! Who needs it?
!3.......^.........^.........^.........^..

!B
   1 CLEAR 38999
  10 DEF FN s(a)=USR 60000
  20 DEF FN l(a)=USR 60005
  30 DEF FN h(a)=USR 60010
  40 DEF FN f(a)=USR 60015
  50 DEF FN i(a)=USR 60020
  60 DEF FN o(a)=USR 60025
  70 DEF FN t(a)=USR 60030
  80 LET fh=60035
  90 LET fv=60040
!2.......^.........^.........^.........^.........^.........^....
!P\H11\H06\H10\H00
Lines 1-90       This is the basic set-up routine - you'll need
                 to put these lines at the start of all your own
                 programs.
!3.......^.........^.........^.........^..

1000 LET s1=46000: LET s2=53000: LET s3=39
000
1005 LOAD *"m";1;"S1"CODE s1
1006 LOAD *"m";1;"S2"CODE s2
!2.......^.........^.........^.........^.........^.........^....
!P\H11\H06\H10\H00
Lines 1000-1006  These lines initialise the start of the screen
                 addresses and load in the pictures from Micro-
                 drive (if you haven't got drives, replace lines
                 1005-1006 with the normal cassette loading
                 syntax).
!3.......^.........^.........^.........^..

1010 RANDOMIZE FN l(s1)
1020 LET a$="PANNING": GO SUB 8000
1030 RANDOMIZE FN h(s2)
1040 GO SUB 8000: RANDOMIZE FN h(s1)
!2.......^.........^.........^.........^.........^.........^....
!P\H11\H06\H10\H00
Lines 1010-1040  Panning. This routine simply performs a screen
                 trick, panning in this case, and then scrolls a
                 couple of times before moving onto the next
                 example.
!3.......^.........^.........^.........^..

1090 FOR i=1 TO 2
1100 LET a$="ZOOM OUT": GO SUB 8000
1110 RANDOMIZE FN o(s2)
!2.......^.........^.........^.........^.........^.........^....
!P\H11\H06\H10\H00
Lines 1090-1110  Zoom Out.
!3.......^.........^.........^.........^..

1120 LET a$="ZOOM IN": GO SUB 8000
1130 RANDOMIZE FN i(s1)
1140 NEXT i
!2.......^.........^.........^.........^.........^.........^....
!P\H11\H06\H10\H00
Lines 1120-1140  Zoom In.
!3.......^.........^.........^.........^..

1200 LET a$="CORNER ZOOM": GO SUB 8000
1210 RANDOMIZE FN t(s2)
1220 GO SUB 8000
1230 RANDOMIZE FN t(s1)
!2.......^.........^.........^.........^.........^.........^....
!P\H11\H06\H10\H00
Lines 1200-1230  Corner Zoom.
!3.......^.........^.........^.........^..

1300 LET a$="FADING": GO SUB 8000
1310 RANDOMIZE FN f(s2)
1320 GO SUB 8000
1330 RANDOMIZE FN f(s1)
!2.......^.........^.........^.........^.........^.........^....
!P\H11\H06\H10\H00
Lines 1300-1330  Fading.
!3.......^.........^.........^.........^..

1400 LET a$="FLIP HORIZONTAL": GO SUB 8000
1410 RANDOMIZE USR fh
1420 PAUSE 0
1430 RANDOMIZE USR fh
!2.......^.........^.........^.........^.........^.........^....
!P\H11\H06\H10\H00
Lines 1400-1430  Flip Horizontal.
!3.......^.........^.........^.........^..

1500 LET a$="FLIP VERTICAL": GO SUB 8000
1510 RANDOMIZE USR fv
1520 PAUSE 0
1530 RANDOMIZE USR fv
!2.......^.........^.........^.........^.........^.........^....
!P\H11\H06\H10\H00
Lines 1500-1530  Flip Vertical.
!3.......^.........^.........^.........^..

1600 LET a$="AND ALL OF THEM": GO SUB 8000
1610 LET d=25
!2.......^.........^.........^.........^.........^.........^....
!P\H11\H06\H10\H00
Lines 1600-1610  Start of the demonstration loop.
!3.......^.........^.........^.........^..

2000 RANDOMIZE FN o(s1): PAUSE 0: RANDOMIZ
E FN i(s2): PAUSE 0
2010 RANDOMIZE USR fh: RANDOMIZE FN s(s3)
2020 RANDOMIZE USR fv: PAUSE 0: RANDOMIZE 
USR fv: PAUSE 0
2030 RANDOMIZE FN f(s1): PAUSE 0: RANDOMIZ
E FN f(s2): PAUSE 0: RANDOMIZE FN f(s1): P
AUSE 0
2040 RANDOMIZE USR fv: PAUSE 0
2050 RANDOMIZE FN h(s2): PAUSE 0
2060 RANDOMIZE USR fh: RANDOMIZE FN h(s2):
 PAUSE 0
2070 RANDOMIZE FN o(s3): PAUSE 0
2080 RANDOMIZE FN o(s2): PAUSE 0
2090 RANDOMIZE FN o(s3): PAUSE 0
2100 GO TO 2000
!2.......^.........^.........^.........^.........^.........^....
!P\H11\H06\H10\H00
Lines 2000-2100  Demonstration loop.
!3.......^.........^.........^.........^..

8000 PRINT #0;AT 1,(32-LEN a$)/2;" ";a$;" 
";
8010 PAUSE 0: RETURN
!2.......^.........^.........^.........^.........^.........^....
!P\H11\H06\H10\H00
Lines 8000-8010  This is a short subroutine that prints the 
                 title on each screen.
!3.......^.........^.........^.........^..

9999 CLEAR 59999: LOAD *"m";1;"TP"CODE :
RUN
!2.......^.........^.........^.........^.........^.........^....
!P\H11\H06\H10\H00
Line 9999        Clears space in memory and loads in the Top of
                 the Pops routine. Use this line in all your
                 programs.
!1.......^.........^.........^.........^........

!B
--
from Your Spectrum #19 (Oct.1985)
--
!$
