Introduction
Hello! My name is HellMood, and this article is about a small MS DOS program called Memories. This program has a size of 256 bytes, it won in the category of «PC 256 byte» competition demoscene «Revision» in 2020, and also received the Audience Award. You can watch the video of the programâs output here , and the video with the reaction of the online audience and moderators here . Download the release and leave comments here. This article will present an in-depth analysis of the program, talk about historical references and development stages. The article is posted in the sizecoding wiki. It will not only allow you to understand the internal structure of Memories, but will also help you create something similar. Explore it! If you are new to sizecoding (writing programs within the desired size) or in x86 assembler, it is recommended that you start with the basics of this wiki . The principles are easy to understand, but itâs not so easy to figure out implementation details.Short review
In this article we will talk about the version sent to the contest for DosBox (256 bytes). The archive also contains versions for FreeDos and Windows XP DOS, which at the time of writing the post did not work on all computers. These alternative versions were included in the archive as proof of concept to show that the program not only works in the emulator. In the âPC 256 bytesâ category of the âRevisionâ competition of 2020, it was possible to indicate âFreeDosâ or âDosBoxâ as the platform (the latter in a specific configuration). As alternative versions prove, in fact, you can modify the version for DosBox so that it works in FreeDos, MS DOS, WinXP and Win98, but the article will not be about that.Be that as it may, reliable versions for all platforms and computers are under development. As for possible further optimizations, I will only talk about the version sent to the contest, although I have already found several places where the code can be optimized. Since this is a demonstration of the history of small effects, almost none of the code is perfect, and it can be further reduced. In order not to get confused in different versions, I will talk only about the competition.History of small effects
Dimension categories at http://www.pouet.netWe, sizcoders, reason in size categories. For MS DOS, these categories are 256b, 128b, 64b, and 32b. These are the standards of one of the largest archives of the demo scene www.pouet.net. There is no 16b category, however many small effects can be implemented in 16 bytes. Almost all the effects from âMemoriesâ were written and optimized by me earlier, and basically their implementation was an attempt to reduce the existing size of the effect, or to create something similar, but smaller. By size reduction here is meant its reduction to one of the following smaller categories 2 ^ N. For example, if the effect was implemented in 33-64 bytes, then it is reduced to 32 bytes or less. Almost every time I managed to âlowerâ the effect to a lower category, I sent the resulting tiny program to an event dedicated to the demoscene, in which remote participants were allowed to participate in category 256b, and / or published the result on www.pouet.net. In this section, I will introduce you to the effects, as well as talk about their origin and authors.Array of chessboards
kasparov, 16 bytes. Thesource of this effect was my own âKasparov 16bâ of 2018 ( link ). It seems (quote from the release notes), I "just made this board, fit it into 17 bytes, but it was not very beautiful until I came up with a trick ...". Previously, there was already a similar effect implemented in 32 bytes: 2003 ew from the developer headcrash. ( link ) In this case, I tried to implement ârealâ chessboards with an 8x8 square and recognizable black and white squares, as well as the correct orientation of individual chessboards, that is, the lower right corner (h1) should have been white. In order for this effect to work with the global framework, in âMemoriesâ it had to be re-implemented using another technique: recording on the screen; In addition, the direction of scrolling has been changed so that it differs from the âscrolling tilted planeâ effect.Zooming circles
Scalable circles (zooming circles) were supposed to participate in demopati as an intro of 32 bytes, but I never did. This effect does not have a 64 byte predecessor, because in the 64b category much more complex effects are possible. Zooming circles were the result of my desperate attempt to get into category 32b with the effect of a round âtunnelâ, for which my personal record was still 52 bytes (âNeontubeâ - 2016) ( link ), which, in turn, became an optimization of the classic 64 -byte effect "constant evolution" developers ryg / Farbrausch (2003) ( link ). In the zooming circles procedure, the distance and angle are eliminated / ignored, due to which it was possible to fall into category 32b.Scrolling tilted plane
Floorcast, a 32-byte version, a variation of theScrolling tilted plane, is one of my own releases, the 2018 floorcast 32b. The effect of âflooringâ has its own history in sizecoding and has gradually decreased from 256 bytes to 32 bytes. Different versions differ in the number of planes, in some two planes are displayed, in others - only one. In the âfloorcast 32bâ release, I specifically decided to abandon the âXORâ texture, and in âMemoriesâ I used it again, masking it with the final touch in the form of âANDâ.- 2008 rain_storm version - 256 bytes - link
- 2008 version of org_100h - 128 bytes - link
- 2013 Baudsurfer version - 86 bytes - link
- 2014 Baudsurfer version - 64 bytes - link
- 2018 HellMood Version - 32 bytes - Link
Parallax checkerboards
Projektbeschreibung, 32 bytesI released parallax chessboards in 2018 as a 32-byte Projektbeschreibung effect. In it, I tried to reduce the size of âFollow the lightâ ( link ) from âDigimindâ (2006) or my own âLucyâ (2014) ( link ) to 32 bytes. Very useful sources of inspiration were Paralaxa by Rrrolas (32 bytes, 2007, link ) and Byteropolis by Sensenstahl (2013) ( link) The Rrrolas rendering technique was very close to my final decision, the code was changed to correct the location of the planes, replace the triangles with chessboards, and improve the colors. Memories used the color scheme of the Digimind version. In addition, the effect was maximally modified to reduce deformations.Sierpinski rotozoomer
colpinski, 16 bytesrotastic, 32 bytesIt consists of two effects: rotozoomer and Sierpinski effect as a texture. The Sierpinski effect is based on my own 2013 Colpinski 16b effect ( link ), where I managed to get the maximum possible with the frag function fsqrt. This effect has no predecessor, because it can be implemented directly by combining X and Y, rather than using an Iterated Function System or cellular automata. âRotation and scalingâ (rotozoomer) was released by me in 2017 as the 32b intro ârotasticâ ( link ), it is based on the ideas of ârygâ by the developer Farbrausch (51 bytes, 2002, link ) and âGargajâ of the group âConspiracyâ "(49 bytes, 2002, link ).Raycast bent tunnel
Into a new era, 64-bit version Theraycast bent tunnel has become a modified version of my own 64-byte release, âInto a new eraâ (2018, link ). The original colors were replaced with the colors of the standard palette, the geometry and the corresponding calculations were slightly changed so that the depth effect was not used to calculate texture values. A separate version of this effect is 50 bytes in size. The main sources of inspiration for creating the 64-byte version were two 128-byte intros: âSpongyâ from âTBCâ (2009, link ) and âWolf128â by Baudsurfer (2014, link ), and I developed the algorithm myself.Ocean night to day
Ocean, version 64bThe ocean effect is based on my own 64-byte release of âOceanâ 2016 ( link ). A separate generation of the colors and music of the original was cut out, both generators were not compatible with the main Memories framework without using heaps of extra bytes. The special effect of "dawn" is due to the overall implementation of the framework structure. I will talk about this in the next chapter.Fading effect
The transition between the two effects is in itself an effect that has no predecessors. Rather, it is an idea that has evolved over several years, and perhaps it was similarly implemented by many others. In short, when calculating the frame, the position of each pixel is randomized, and the time that determines which effect should be used is shifted by this randomization value, which was previously reduced. This allows you to use a standard VGA palette (image, source), rather than create your own colors for smooth mixing, which saves space.The framework of my "tiny megademo"
To combine several small effects into one âmegademoâ, they should use the same technique and at most they should not apply assumptions (regarding the contents of memory and registers). They are also required to use the same timing values ââand work in accordance with the total time. It took quite a long time to prepare individual effects suitable for the framework, and at first a lot of extra space. It should be noted that some of the most impressive effects (judging by the reaction of viewers and views on social networks) could not be included in the demo due to the HUGE excessive use of memory. After all the effects had been fixed, I could start thinking about âbracketingâ frequently repeated calculations, which would save a few more bytes.The framework performs the following actions:org 100h
s:
mov al,0x13 ; set AL to mode 320*200 in 256 colors
int 0x10 ; call BIOS to set mode
xchg bp,ax ; set timing value to 0x13
push 0xa000-10 ; write the screen adress to register ES
pop es ; works in conjunction with Rrrola trick
mov ax,0x251c ; parameter for changing timer interrupt
mov dl,timer ; adress of timer routine, assume DH=1
int 0x21 ; install timer routine
top:
mov ax,0xcccd ; load magic Rrrola constant
mul di ; transform screen pointer to X, Y
add al,ah ; use transformation garbage as
xor ah,ah ; pseudorandom value and clear AH
add ax,bp ; add time value to random value
shr ax,9 ; divide by 512 (basically the speed)
and al,15 ; filter effect number
xchg bx,ax ; move effect number to BX
mov bh,1 ; reset BH to align with start of code
mov bl,[byte bx+table] ; read the effect address from the table
call bx ; call the effect
stosb ; write the return value and advance
inc di ; triple interlace trick for after
inc di ; effect and smoothing the animation
jnz top ; repeat until the frame is complete
mov al,tempo ; set AL to divider for timer
out 40h,al ; set timing (dual pass)
in al,0x60 ; read keyboard
dec al ; quit on ESC
jnz top ; otherwise repeat loop
sounds: db 0xc3, 11, 0x93; 0xc3 is MIDI/RET; fx2-s is used as volume
table: db fx2-s,fx1-s,fx0-s,fx3-s,fx4-s,fx5-s,fx6-s,sounds-s,stop-s
Array of chessboards
array of chessboardsThe easiest effect to start with. After shifting the string temporarily, the classic XOR pattern is applied. To create the impression of a chessboard grid, all but two bits are set in color. The real trick is to shift to the âgoodâ place of the palette. The part of the frame that is perceived as black is actually not black, but is the dark part of the standard VGA palette . This shift allows you to give the dark and light cells the feeling of an ancient chessboard. xchg dx,ax ; get XY into AX
sub ax,bp ; subtract time from row
xor al,ah ; XOR pattern (x xor y)
or al,0xDB ; pattern for array of boards
add al,13h ; shift to good palette spot
Zooming circles
zooming circlesThe distance D from the point (X, Y) to the center (0,0) is sqrt (XÂČ + YÂČ). The framework previously makes DL contain the centered coordinate X, and DH = Y needs to be centered in the code. To perform the square root calculation operation in x86, quite a lot of code is required, but in fact it can be omitted. With a careful choice of colors, the feeling of converging circles without a square root seems quite convincing. mov al,dh ; get Y in AL
sub al,100 ; align Y vertically
imul al ; AL = YÂČ
xchg dx,ax ; YÂČ/256 in DH, X in AL
imul al ; AL = XÂČ
add dh,ah ; DH = (XÂČ + YÂČ)/256
mov al,dh ; AL = (XÂČ + YÂČ)/256
add ax,bp ; offset color by time
and al,8+16 ; select special rings
Scrolling tilted plane
scrolling tilted planeThis effect is implemented as follows: first, to simulate the distance, a large constant is divided by line number Y. Then the obtained value is used twice: a) multiplied by the centered value of X and b) as offset by the current time. Then these results are combined using the XOR pattern, from which a special pattern is selected. mov ax,0x1329 ; initialize with constant
add dh,al ; preventing divide overflow
div dh ; reverse divide AL = C/Y'
xchg dx,ax ; DL = C/Y', AL = X
imul dl ; AH = CX/Y'
sub dx,bp ; DL = C/Y'-T
xor ah,dl ; AH = (CX/Y') ^ (C/Y'-T)
mov al,ah ; move to AL
and al,4+8+16 ; select special pattern
Parallax checkerboards
parallax checker boardsThis is a kind of reykasting (emitting rays) with dynamic geometry. Each plane of the objects is divided horizontally due to 16-bit multiplication with a sign and vertically due to the operation of implicit logic with the column number. Additionally, indirect distortion is applied to connect the edges of the resulting mesh (4 âsolidâ areas, 4 âtransparentâ areas alternately). If the beam crosses one of the solid areas, the color becomes the iteration number (+ the palette offset in shades of gray), and if not, the plane moves to the screen pointer, after which the process repeats until the maximum number of iterations is reached. mov cx,bp ; set inital point to time
mov bx,-16 ; limit to 16 iterations
fx3L:
add cx,di ; offset point by screenpointer
mov ax,819 ; magic, related to Rrrola constant
imul cx ; get X',Y' in DX
ror dx,1 ; set carry flag on "hit"
inc bx ; increment iteration count
ja fx3L ; loop until "hit" or "iter=max"
lea ax,[bx+31] ; map value to standard gray scale
Sierpinski rotozoomer
sierpinski rotozoomerGraph 1 / cos (atan (x)), created using www.google.comTo rotate with scaling, trigonometric functions or their good approximate values ââare usually required. Let's take a look at the usual 2D rotation equation and interpret it in a special way to get rid of trigonometry in calculations:x' = x*cos(a) - y*sin(a)
y' = x*sin(a) + y*cos(a)
If we add scaling, it will look like this:x' = z * (x*cos(a) - y*sin(a))
y' = z * (x*sin(a) + y*cos(a))
Now let's say that we do not define z ourselves, and put 1 / cos (a) out of brackets:x' = 1/cos(a) * (x - y*tan(a))
y' = 1/cos(a) * (x*tan(a) + y)
Now we replace tan (a) with a time variable, because the tangent function tends to infinity as it approaches 180 °:x' = 1/cos(atan(T)) * (x - y*T)
y' = 1/cos(atan(T)) * (x*T + y)
If we donât care about the lack of the ability to set the scaling factor and we donât control the angle directly, now we can rotate from -180 ° to + 180 ° without using trigonometric functions. As a result of this, the scaling factor turns out to be tied to time T. The function for the coefficient is shown in the image, due to which scaling occurs from an infinitesimal number to one (the original size) and back to infinitesimal. A fair amount of bytes were spent decorating this effect, fixing time offsets, speeding up animations, increasing the pixels of Sierpinskiâs triangles and creating beautiful colors, but I think it was worth it. lea cx,[bp-2048]; center time to pass zero
sal cx,3 ; speed up by factor 8!
movzx ax,dh ; get X into AL
movsx dx,dl ; get Y int DL
mov bx,ax ; save X in BX
imul bx,cx ; BX = X*T
add bh,dl ; BH = X*T/256+Y
imul dx,cx ; DX = Y*T
sub al,dh ; AL = X-Y*T/256
and al,bh ; AL = (X-Y*T/256)&(X*T/256+Y)
and al,252 ; thicker sierpinski
salc ; set pixel value to black
jnz fx4q ; leave black if not sierpinski
mov al,0x2A ; otherwise: a nice orange
fx4q:
Raycast bent tunnel
raycast bent tunnelThis is a type of tunnel with rakasting from "into a new era" (see above). A detailed description of this effect for a similar Essence program has been published on reddit. I got rid of unique colors, changed the direction of the tilt, and the geometry became more closed to improve performance on older computers and in DosBox. mov cl,-9 ; start with depth 9 (moves backwards)
fx5L:
push dx ; save DX, destroyed inside the loop
mov al,dh ; Get Y into AL
sub al,100 ; Centering Y has to be done "manually".
imul cl ; Multiply AL=Y by the current distance, to get a projection(1)
xchg ax,dx ; Get X into AL, while saving the result in DX (DH)
add al,cl ; add distance to projection, (bend to the right)
imul cl ; Multiply AL=X by the current distance, to get a projection(2)
mov al,dh ; Get projection(1) in AL
xor al,ah ; combine with projection(2)
add al,4 ; center the walls around 0
test al,-8 ; check if the wall is hit
pop dx ; restore DX
loopz fx5L ; repeat until "hit" or "iter=max"
sub cx,bp ; offset depth by time
xor al,cl ; XOR pattern for texture
aam 6 ; irregular pattern with MOD 6
add al,20 ; offset into grayscale palette
Ocean night to day
oceannightoceandayThe Ocean Effect is an excellent example of âflukeâ. If we load the value into the FPU as an integer and store it as a floating point, and then interpret it again as an integer, then we get a great pattern. If you combine this with the inverse division, you get a beautiful wave effect. It works closely with the DX register, which has a sign reversal in the position we need, so we can easily separate the sky from the sea. However, the final touch is the color. In accordance with the structure of the global framework, the value of AL is determined at the input of the function, it contains the address of the effect. By shuffling the code a bit, you can get the sky color "free" without using instructions, just like the color of the "transition to day", which is also the effect address. And this is not a happy coincidence. In other versions than the DosBox version,the color of the sky for this reason may vary. sub dh,120 ; check if pixel is in the sky
js fx6q ; quit if that's the case
mov [bx+si],dx ; move XY to a memory location
fild word [bx+si] ; read memory location as integer
fidivr dword [bx+si]; reverse divide by constant
fstp dword [bx+si-1]; store result as floating point
mov ax,[bx+si] ; get the result into AX
add ax,bp ; modify color by time
and al,128 ; threshold into two bands
dec ax ; beautify colors to blue/black
Fading effect
For convenience, the effect is isolated from the global framework. In fact, it generates a pseudo-random number from the screen pointer, and then performs a time offset by its scaled value, after which it causes the desired effect. mov ax,0xcccd ; load magic Rrrola constant
mul di ; transform screen pointer to X, Y
add al,ah ; use transformation garbage as
xor ah,ah ; pseudorandom value and clear AH
add ax,bp ; add time value to random value
shr ax,9 ; divide by 512 (basically the speed)
and al,15 ; filter effect number
xchg bx,ax ; move effect number to BX
mov bh,1 ; reset BH to align with start of code
mov bl,[byte bx+table] ; read the effect address from the table
MIDI music
This section of code increments the time value and creates a sound. By selecting channel 3, we can reuse the âchange tool channelâ instruction as âRETâ. By shifting the effect code, you can create a suitable value for the volume, which saves another byte. It is worth considering that this part of the code only works if the MIDI device is already in UART mode, otherwise you will need to spend another three bytes. Many of the spectators and organizers told me that the tune is a bit like Mike Oldfield's Incantations , but it was created with a very simple technique. Since Hypnoteye 2015, I experimented with procedural MIDI and eventually released a small MIDI framework (64 bytes). The main principle of his work is to jump with a fixed pitch in the tone space and convert high values ââto lower ones (by division modulo). Simple combinations of stepwidth and modvalue can achieve interesting effects. For example, stepwidth = 3 allows you to get a continuously lasting reduced minor chord, and stepwidth = 4 or stepwidth = 6 - tritonal effects. With a well-chosen modvalue, these patterns can create sequences. I have not carried out a proper theoretical analysis, but simply explored the space of tones and noted interesting sounds.sounds: db 0xc3, 11, 0x93, fx2-s
...
inc bp ; increment timing value
test bp, 7 ; play a note every 8th step
jnz nomuse ; quit if in between
mov dx,0x330 ; port number for MIDI
mov si,sounds ; adress for sound data
outsb ; change instrument of channel 3
outsb ; to vibraphone
outsb ; play a note on channel 3
imul ax,bp,-19*32*4 ; the magic melody constant
shr ax,10 ; scale down and implicit "and 63"
add al,22 ; pitch base is 22
out dx,al ; play THIS note on channel 3
outsb ; play it with THIS volume
Full release code
; "memories" by HellMood/DESiRE
; the tiny megademo, 256 byte msdos intro
; shown in April 2020 @ REVISION
;
; (= WILL BE COMMENTED IN DETAIL LATER =)
;
; create : nasm.exe memories.asm -fbin -o memories.com
; CHOOSE YOUR TARGET PLATFORM (compo version is dosbox)
; be sure to use the dosbox.conf from this archive!
; only ONE of the defines should be active!
%define dosbox ; size : 256 bytes
;%define freedos ; size : 230 bytes
;%define winxpdos ; size : 263 bytes
; DON'T TOUCH THESE UNLESS YOU KNOW WHAT YOU'RE DOING
%ifdef winxpdos
%define music
%define switch_uart
%define safe_dx
%define safe_segment
%endif
%ifdef freedos
%define safe_dx
%endif
%ifdef dosbox
%define music
;%define safe_dx ; sometimes needed
%endif
; GLOBAL PARAMETERS, TUNE WITH CARE!
%define volume 127 ; not used on dosbox (optimization)
%define instrument 11
%define scale_mod -19*32*4;
%define time_mask 7
%define targetFPS 35
%define tempo 1193182/256/targetFPS
%define sierp_color 0x2A
%define tunnel_base_color 20
%define tunnel_pattern 6
%define tilt_plate_pattern 4+8+16
%define circles_pattern 8+16
org 100h
s:
%ifdef freedos
mov fs,ax
mov [fs:0x46c],ax
%endif
mov al,0x13
int 0x10
xchg bp,ax
push 0xa000-10
pop es
%ifndef freedos
mov ax,0x251c
%ifdef safe_dx
mov dx,timer
%else ; assume DH=1, mostly true on DosBox
mov dl,timer
%endif
int 0x21
%endif
top:
%ifdef freedos
mov bp,[fs:0x46c]
%endif
mov ax,0xcccd
mul di
add al,ah
xor ah,ah
add ax,bp
shr ax,9
and al,15
xchg bx,ax
mov bh,1
mov bl,[byte bx+table]
call bx
stosb
inc di
inc di
jnz top
mov al,tempo
out 40h,al
in al,0x60
dec al
jnz top
sounds:
db 0xc3 ; is MIDI/RET
%ifdef music
db instrument,0x93
%ifdef switch_uart
db volume ; without switch, volume is in table
db 0x3f
%endif
%endif
table: ; first index is volume, change order with care!
db fx2-s,fx1-s,fx0-s,fx3-s,fx4-s,fx5-s,fx6-s,sounds-s,stop-s
stop:
pop ax
ret
timer:
%ifndef freedos
%ifdef safe_segment
push cs
pop ds
%endif
inc bp
%ifdef music
test bp, time_mask
jnz nomuse
mov dx,0x330
mov si,sounds
outsb
outsb
outsb
imul ax,bp,scale_mod
shr ax,10
add al,22
out dx,al
outsb
%ifdef switch_uart
inc dx
outsb
%endif
%endif
nomuse:
iret
%endif
fx0: ; tilted plane, scrolling
mov ax,0x1329
add dh,al
div dh
xchg dx,ax
imul dl
sub dx,bp
xor ah,dl
mov al,ah
and al,tilt_plate_pattern
ret
fx2: ; board of chessboards
xchg dx,ax
sub ax,bp
xor al,ah
or al,0xDB
add al,13h
ret
fx1: ; circles, zooming
mov al,dh
sub al,100
imul al
xchg dx,ax
imul al
add dh,ah
mov al,dh
add ax,bp
and al,circles_pattern
ret
fx3: ; parallax checkerboards
mov cx,bp
mov bx,-16
fx3L:
add cx,di
mov ax,819
imul cx
ror dx,1
inc bx
ja fx3L
lea ax,[bx+31]
ret
fx4: ; sierpinski rotozoomer
lea cx,[bp-2048]
sal cx,3
movzx ax,dh
movsx dx,dl
mov bx,ax
imul bx,cx
add bh,dl
imul dx,cx
sub al,dh
and al,bh
and al,0b11111100
salc ; VERY slow on dosbox, but ok
jnz fx4q
mov al,sierp_color
fx4q:
ret
fx5: ; raycast bent tunnel
mov cl,-9
fx5L:
push dx
mov al,dh
sub al,100
imul cl
xchg ax,dx
add al,cl
imul cl
mov al,dh
xor al,ah
add al,4
test al,-8
pop dx
loopz fx5L
sub cx,bp
xor al,cl
aam tunnel_pattern; VERY slow on dosbox, but ok
add al,tunnel_base_color
ret
fx6: ; ocean night / to day sky
sub dh,120
js fx6q
mov [bx+si],dx
fild word [bx+si]
fidivr dword [bx+si]
fstp dword [bx+si-1]
mov ax,[bx+si]
add ax,bp
and al,128
dec ax
fx6q:
ret
Bonus - NFO / ASCII art : hammerfist
â#MW%e _d$Ng,
'B, âb _jM@$QZb,cQ" )@
,edRB$b,l@ Wk,yGR$KM&$b, ,dP" Wl ]bsd%UR8BG6&$@DSyG#ZKM&$b,
,dP "T%L 'MGF "*âR_ Tg "*4Zk,#I YP W" 7P "*âR
4M gd@ ^ â@ d@b dQ$#@Z@R3L_ "*GMj 'W ,gd$ d@b 9Q$#%b
W#, `M Wb `* _4P `Qk *#N8L `H5 @b 'QR7YK `* _4F" Qk
`6@L dML '@ ,BK 'M âB *b, '#L
^QBb,_ _,4&Mââ@=,_ _dGL _gQKM GL @k 'Mg,_ _dG,
"*BN5W$2#MNP" "*G3WRM8&B5P"`Y@QNW3Z5P" â#$W8BRM3XZN87 "*GW38M%EBDW5P"`
p r e s e n t s
4
d@,
_& `Wl
_,aP "#baedM$#@@K JP*"?ML
,ad@$#P" ,d@NEWVB" X,aQPYb,_
V@Mm,_ ,d@MW#BW' EMP" '¶R ,ngBP^fML
¶M@N@y Y#BNW#M" J9" `MQ9" "MgRBq ,QBMg,
VN#P` ,d@@ `WM@^ 7f ¶F` 7kY" ^G _.eQNE1.
]B _G@MWN$, `P ' 4b QP ¶w@F*^ ^Qb
]O@NRM#W@MNB, ; ^` j JP^ Yl
J#NRNWM@#BcT"^ ,A _J _q@ `X
'¶WM#B@WdY`,7 _G#YN#PM _,gG" M,
*BN#WP" dK ,Q@NRMB"]9 , _,M@Q* #A
"U^ V@h, iNBW#NT J' J9 s@QN" _; 'D,
¶RMBv&NMQR@9 .W .K' "9` ,6BA _JL ]l
Y#NE@W#NRP #[ `¶8 _d@MW#B_jW#W BN
"GQ@MR#W QL_ *B _,p#NBW#NQMG@WY 3Q
"Y@F ,XW@M%im,_Yb_ _,g5@#MW@QMNE@E@NRMB ,WM
` _,gP*"#REM#GB@N#MQbnd@N#M@MW#R8QSB^'WQERM@ ;4NB,
,GYKL ¶E#B8R8QSB@M@#BM#W@MNB"`_ , "^` N ,dW@Ql
_Q`'W`*t '¶@GS#MBQ#E@W#NQBW[ 'LvQ_ ,K _dNABGM#N
,F ' `^WAB@QGE9*"9^*@L jP7FY, ¶h,_.jWM#BR#GBM,
J; , _ ' ' "LL YxE#B8R8QSBNW@W;
AP _,Ag6^ _ J ¶A `"Q#M@MW#R8E#P
j@ `"XQW[ 'LvK,_ 'L_,/ @t Y#NE@WNR"
:M/ 9^*@L jP7F" _PYKL _,A; ¶RSNQ"
dKL ' ` ' "L "`'W`*t `"XQb `W^
Q`8t 'L_,/ , _ ' 9^Q
,W _PYKL _,Ag6^ ' W, _ ,#N&
!N _ J "`'W`*t `"XQW[ _ J N!_JG9^RwQ' *t
`W, 'LvK,_ ' _gGB8@L _ 'LvK,_ ,WgB' V 7L
_.,gm&@B&wBZF" j@'` "WL _gML jZd7Yb lN" dBWl
,g&QB*"^` `"*G@g, .gR&k,_ ,N" '@QF ¶k;gMF *QvQ jQ, ,@N@B#,
.eQF*` `Yb@" "*6Qg,gF , 7 XMN" 'MNB, ^¶QWSER@N;
,gP" qy, W' ^Q' &L ,g@W' `QMEL `"WBNWP
g7 ¶9 ,X M? 9" _q8MSK ¶EMt *@K
Vh _,m#L _AH le ,GBDNE9^A, *@F NMg
¶L,qQ@ND _.m@Bl We ,gM@B8#Q' ¶h_ lWE,
W9NHW@` JWM#B@] @e 4WR@NGF^ 'QL dRWl
VMd* "@BE@PM 'N *UP" VW, JRSB;
,@F j `¶WK W, ¶t XNt _A@E#N
_JP ,6& "GLdM XD, _.g8NMA@k,_ _,gG#NMGR;
"Z .JRER 'VMi _jNB#W&_ _,j@E@W#Nl ¶MBGMNQGNQMG@QBW9
¶h ,G@NRMBl `" ,d#R@M$F ¶Mg,_.gp&@@NEWVBWBMG *QMN8R8SBN$E@WF
Vb dW#R8QSRb, *YM@EQ,_ 'MENBW#NQMG#B@R@MW#l "BM@QNENRQG'
*WGS#MBMNEYL `^"*8M@Q@NRM#W@BWSNW@QBF"` `^*@QBF^ [HFT]
^M@MW#Q9 ^Wt `^¶RQ@W8NQGP*`
¶Q#@P Vk lA `"^`
Y" `MA J#,
*R@, ,MQl
Y#Wk, GWM8L
W8RQSt,_ AQ@MR#,
`@M@#SB@Mbm.,_ QNBW#NW
¶QB8R8SBN$WNRM@#GNtwg@NMQR@B'
*MBQ#8R8QS@NE@WNBW#NQMG@NR;
`WGS#MBQ#R8QSB@NE@W#NQBW9
*OMW@QMNE@E@NRMW@QMB@*
`^"YQW@Q#SB#NE@EGP
`^"*8R@GBQF`