Автор: Andrew Pennell
Год: 1985
Издатели: Your Spectrum
Языки:
Английский
Формат:
TAP лента
Требования:
ZX Spectrum 48K
Ссылки:
Страница на ZXArt
Страница на World Of Spectrum
Страница на Spectrum Computing
Скриншоты:
Описание:
"Screen Effects" — это графическая утилита, разработанная Эндрю Пеннеллом для ZX Spectrum 48K, опубликованная в 1985 году журналом Your Spectrum. Эта программа позволяет пользователям создавать различные визуальные эффекты на Spectrum, напоминающие те, что можно увидеть в телевизионных шоу, таких как 'Top of the Pops'.
Программа предоставляет рутинные процедуры для панорамирования, затухания, увеличения и уменьшения, зумов из углов, а также горизонтальных и вертикальных переворотов. Эти эффекты можно использовать для улучшения визуальной привлекательности пользовательских программ, предлагая разнообразие переходов и трансформаций для экранных изображений.
Хотя она не превращает Spectrum в высококлассную графическую машину, как системы Quantel, используемые вещателями, она предлагает экономичный способ достижения впечатляющих результатов. Пользователи могут экспериментировать с различными эффектами, чтобы найти то, что лучше всего соответствует их потребностям.
Программа включает загрузчик Basic, который позволяет пользователям сохранять и загружать изображения экрана, что облегчает использование. Она служит мощным инструментом для тех, кто хочет добавить динамичные визуальные эффекты в свои проекты на Spectrum.
Год: 1985
Издатели: Your Spectrum
Языки:
Формат:
Требования:
Ссылки:
Скриншоты:
Описание:
"Screen Effects" — это графическая утилита, разработанная Эндрю Пеннеллом для ZX Spectrum 48K, опубликованная в 1985 году журналом Your Spectrum. Эта программа позволяет пользователям создавать различные визуальные эффекты на Spectrum, напоминающие те, что можно увидеть в телевизионных шоу, таких как 'Top of the Pops'.
Программа предоставляет рутинные процедуры для панорамирования, затухания, увеличения и уменьшения, зумов из углов, а также горизонтальных и вертикальных переворотов. Эти эффекты можно использовать для улучшения визуальной привлекательности пользовательских программ, предлагая разнообразие переходов и трансформаций для экранных изображений.
Хотя она не превращает Spectrum в высококлассную графическую машину, как системы Quantel, используемые вещателями, она предлагает экономичный способ достижения впечатляющих результатов. Пользователи могут экспериментировать с различными эффектами, чтобы найти то, что лучше всего соответствует их потребностям.
Программа включает загрузчик Basic, который позволяет пользователям сохранять и загружать изображения экрана, что облегчает использование. Она служит мощным инструментом для тех, кто хочет добавить динамичные визуальные эффекты в свои проекты на Spectrum.
!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)
--
!$
!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)
--
!$