Code - chunk effect: Magnets stretching

Info Guide #11
Magnets stretching
Alone Coder 

   I'll tell you about the effect in the demo grits
The Board II, whose main title 
I couldn’t find it anywhere, whether it’s “stretch” or
"magnets". Let there be "magnets".



   His idea is this: there are two flying ones─
glasses with their own polar coordinate systems─
nat:U1, V1 and U2, V2 (maybe U3, V3,
if there are not two points, but three); for each eq─
early pixel(x,y) we find the coordinates in
each of the polar coordinate systems, corresponding─
we add the corresponding coordinates(U1+U2,
V1+V2), we read the pixel from the texture from them
and display it on the screen.



   It would seem simple, but usually on Speccy
this effect was very slow, even in
low resolution. And I decided to do it
chunks 2x2.

   The demo was written under ATM Turbo 2+, but
Since the car at that party was a ZX Evo
with baseconf firmware (main firmware
this computer-designer implements 
ATM Turbo 2+ at14 MHz,along with three - 
then one - other known models 
Spectrum and one virtual one called─ 
I eat "ATMZ", which is now being bred by Zorel), 
there was an incentive to even try to do this
effectframe on a computer, with a regular
automatic adjustment of the demo to the speed of the car.
I already had data on execution speed─
opinions of the teams there: the main idea is that
the machine cycle with reading is rounded to what─
long clock cycle if the cell is not read in advance
into a 16-bit buffer; the buffer is always read from
even memory address. But since long─
the strength of commands in such “turbo strokes”
unusual and non-standard, I will write at─
measures with ordinary beats and assume that in
there are approximately 220,000 of them in the frame (approximately 100,000
on ATM Turbo 2/2+ @ 7 MHz). Of course it is
the number depends on the code, but in any case,
if the calculations didn’t add up, there would always be
the ability to reduce the window. And you should always
remember that we are writing for a retro car, and not
for some kind of computer firmware─
torus or some other emulator with “new carts─
possibilities" (which really cannot be under─
connect to Spectrum). Because what's the point of an ear─
from Spectrum to fake "new possibilities"
features based on the Spectrum", if all around─
full of real platforms with decent people─
mi? Meaning only for those who are too lazy to write
like real retro, but wants to unwind─
xia (they even unite to praise
each other and bullying those who don’t like fakes
and other show of dust).

   Let me remind you what screen modes we have
available on ATM Turbo 2/2+ and its modern ones
implementations:
 -6912;
 -"EGA" 320x200, 16 colors per point.B
Each byte has 2 pixels that are encoded 
like attributes on 6912. Screen in memory times─ 
divided into 4 layers of 8000 bytes, which 
are reduced every 2 pixels horizontally─ 
ntali. Inside the layer, the address grows linearly. 
Layers lie in different pages and halves 
pages; 
 -multicolor 640x200, hires.Pixels
lie on one page, attributes on another. 
Moreover, both pixels and attributes of the section─ 
linen into 2 alternating layers each; 
 -textmod 80x25.
 Timex Sinclair 2068 modes are not supported─
us.

   The first idea, of course, was using─
tion of chunks and the c2p procedure. But it’s easy to see─
pretend that the result is not achieved even
close: c2p via pop hl:ldd:ld a,(hl):
ld (bc), and, say, in a window320x96, will take 
40*160*48 = 307200 clock cycles - not counting sa─
of my effect, which will obviously not be successful─
me teams.
   Moreover, why do we need c2p, if you can─
write only every second line (about─
give away the interstitial linesunder the inscriptions) -
that is, in essence, to drive whole bytes from the tech─
directly into the screen?

   After these considerations, the effect was seen
like this (on the EGA screen):

   Stage 1: add the coordinates by two
tables of polar coordinates: 

ld a,(de):inc e ;U1
add a,(hl):inc l ;U2
push af
:33 t/chunk per coordinate

ld a,(de):inc e ;V1
add a,(hl):inc l ;V2
ld c,N:ld (bc),a
:36 t/chunk to second coordinate

(total 69 t/chunk) 

   Stage 2: read the pixel from the texture and
display it on the screen: 

pop hl ;coordinates in texture
ldi ;write a byte from the texture to the screen
:26 t/chunk

   The procedures are simple, standard, but... simple─
really, isn't it?
   So I wondered if we could go together─
thread calculating coordinates and reading textures.
This can be done if the table is polar─
the coordinates for one of the points will be
driven indirectly into the procedure:

pop bc ;UV1=polar coordinates for point 1
ld hl,NN ;UV2=polar coordinates for point 2
add hl,bc ;address in texture
set 7,h ;you can't occupy everything with a 64K texture!
ldi ;byte from texture
:55 t/chunk

   For each pass we output only one
layer of the screen from 4, that is, constantly re─
jump through 3 chunks (one layer contains─
live pixels0,1,8,9.., second - pixels
2,3,10,11.., third - pixels4,5,12,13.., 
fourth...well, you understand).So cunning
screens on real retro - not for lame─
moat :)

   It is easy to see that an attempt to display
all layers immediately lead to the loss of bars,
even if you write it like this:

ld a,(de):inc e ;U1
add a,(hl):inc l ;U2
ld c,a
ld a,(de):inc e ;V1
add a,(hl):inc l ;V2
ld b,a
ld a,(bc)
ld (NN),a ;alternating layers
:72 t/chunk -
and this is without address restrictions simple─
texture damage!

   Converting the effect to multicolor (2 chunks
in byte) also seems like a loss:

pop bc ;UV1
ld a,(de):inc e ;U2
add a,c
ld l,a ;U
ld a,(de):inc e ;V2
add a,b
ld h,a ;V
ld c/b,(hl) ;byte from texture
1/2*ld a,(bc):ld (NN),a
:65 t/chunk
(no address space limitation
textures)

   And it’s not even clear yet which windows
memory what will lie (table of polar
coordinates, texture, code and two pages of eq─
wound or one for multicolor).

   We sit and feel sad.

   Obviously, a change in the algorithm is needed.Which?
Let's try the texture 16x16 (in one byte
both coordinates -%VVVVUUUU ):

1/2*pop bc ;UV1 (read 2 records at once)
ld a,(de):inc e ;UV2
add a,c/b ;overflow by ml. coordinate!
ld l,a ;coordinates in the texture
ld a,(hl)
ld (NN),a ;alternating layers
:51 t/chunk

   Or for multicolor:

pop bc ;UV1 (read two records at once)
ld a,(de):inc e ;UV2 left
add a,c ;overflow by ml. coordinate!
ld c,a ;coordinates in the texture, left
ld a,(de):inc e ;UV2 right
add a,b ;overflow by ml. coordinate!
ld l,a ;coordinates in the texture, right
ld b,N
ld a,(bc) ;%LOLLLOO00
or (hl) ;%0R0OORRR
ld (NN),a ;alternating layers
:82 t/2 chunks = 41 t/chunk

   The gain is more than 2 times compared
with the original version!  But in the window
320x96 so far315000 clock cycles - it doesn’t fit at all 
to the frame. Is it possible to win more?
   It is possible, and even significant!
   Let the points move in mirror order─
exactly the center of the screen. Then the bottom half
screen - a copy of the top one with a rotation of 180
degrees. This revolution is much faster
than the effect output:

1/2*pop de
ld (hl),d/e:dec l
:16 t/chunk

   Or for multicolor (here you already need that one─
byte flip blitz):

1/2*pop bc ;b,c!=0
ld l,c/b
ldd
:25 t/2 chunks = 12.5 t/chunk
 It turned out that the tablefaster than without
tables :)

   In addition, we can turn over straight─
mo during withdrawal!

1/2*pop bc ;UV1 (read 2 records at once)
ld a,(de):inc e ;UV2
add a,c/b ;overflow by ml. coordinate!
ld l,a ;coordinates in the texture
ld a,(hl)
ld (NN),a ;effect
ld (NN),a ;reflection
:64 t/2 chunks = 32 t/chunk

   Or for multicolor:

pop bc ;UV1 (read 2 records at once)
ld a,(de):inc e ;UV2, left chunk
add a,c ;overflow by ml. coordinate!
ld c,a ;coordinates in the texture, left chunk
ld a,(de):inc e ;UV2, right chunk
add a,b ;overflow by ml. coordinate!
ld l,a ;coordinates in the texture, right chunk
ld b,h
ld a,(bc) ;%LOLLLOO00
inc h
or (hl) ;%0R0OORRR
ld (NN),a ;effect
inc b
ld a,(bc) ;%0L0OOLLL
dec h
or (hl) ;%RORRROO0
ld (NN),a ;reflection
:110 t/4 chunks - 27.5 t/chunk

   Another problem is at the intersection of the effect and
reflections may result in a gap. Firstly
queue due to the fact that it constantly arises
overflow on the lowest coordinate. Its mo─
This can be avoided if the texture is not16x16,
a16x8. Then the bytes will be%VVVVOUUU, and when
addition, the overflow will go to the zero bit, so─
which will not affect anything.
   But there is a better way - draw even
effect lines to the entire height of the screen, and not─
even numbers are reflected. Then the breaks
will not be visible.This allows for multicolor text─
swarm8x8 implement an even more cunning method
- reading two chunks from the texture at once!

pop de
ld a,e
add a,(hl):dec l ;OOvvvuuu + OOvvvuuu
 ; = 0?vvvuuu
ld e,a ;coordinates in the texture, left chunk
ld a,d
add a,(hl):dec l ;OOvvvuuu + OOvvvuuu
 ; = 0?vvvuuu
ld d,a ;coordinates in the texture, right chunk
ld a,(de) ;two colors
exx
ld (bc),a ;effect
ld l,a ;h=tMIRROR/256
ldi ;reflection ;c!=0
exx
:90 t/4 chunks = 22.5 t/chunk

   Of course, this is in theory. In practice it is necessary
fit into memory windows.
   Screen and polar tablecoordinates ne─
switchable (for each screen layer -
its own table). Code and texture - no (in this
there are no addresses in the code, so it no longer requires
stuffing a bunch of pages). But from 32─
Lobyte texture has nowhere to put the code.
   Therefore, the texture will have to be compressed into one
window (for this you need to add and c before
ld d,a, atc=#3f ). Another window will take 
screen (switchable). One more thing - table
polar coordinates (switchable). And os─
The closed window will be filled with code.
   The polar coordinate table will fit into
one window if not aligned to 256
byte, for example, with a card224x144. For this─
godec l will have to be replaced with dec hl. Yes
way to replace only one of them - yep─
give how? That's right, for every parity
X-coordinates - own table of polar coordinates─
Dinat :)

   So the final version of the effect is ta─
coy:

pop de
ld a,e
add a,(hl):dec l ;OOvvvuuu + OOvvvuuu
 ; = 0?vvvuuu
ld e,a ;coordinates in the texture, left chunk
ld a,d
add a,(hl):dec hl ;OvvvOuuu + OvvvOuuu
                  ; = ?nnn?nnn
and c ;#3f
ld d,a ;координаты в текстуре, правый чанк
ld a,(de) ;два цвета
exx
ld (bc),a ;эффект
ld l,a ;h=tMIRROR/256
ldi ;отражение ;c!=0
exx
:96 t/4 чанка = 24 t/чанк

   Обвязка:

DRLOOPO
dup wid/4 ;=40
<эффект>
edup
org $-1
ld hl,-40*4+(wid/4)
add hl,bc
ld b,h
ld c,l
ld hl,+40*4-(wid/4)
add hl,de
ex de,hl
ld h,tMIRROR/256
exx
dec b
jp nz,DRLOOPO

   All that remains is to write a table generator and
textures, add display of titles and scripts─
tion, and the effect is ready!

Share your thoughts about the article