Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!seismo!rutgers!princeton!udel!rochester!cornell!uw-beaver!mit-eddie!genrad!decvax!decwrl!labrea!rocky!rokicki From: rokicki@rocky.STANFORD.EDU (Tomas Rokicki) Newsgroups: comp.sys.amiga Subject: BlitLab 1.2 (part 2/4) Message-ID: <375@rocky.STANFORD.EDU> Date: Mon, 22-Jun-87 20:26:29 EDT Article-I.D.: rocky.375 Posted: Mon Jun 22 20:26:29 1987 Date-Received: Wed, 24-Jun-87 04:56:35 EDT Organization: Stanford University Computer Science Department Lines: 702 ---start--- \begverb{`\$} doblit(aaddress, height, width, amodulo, sh) char *aaddress ; int height, width, amodulo, sh ; { int i, j ; int prev_data, data ; prev_data = 0 ; for (j=0; j> sh ; prev_data = *aaddress ; function(data) ; aaddress += 2 ; } aaddress += amodulo ; } } $endverb So, as you can see, things work nicely along the row. The first time around, the most significant bits of the data word get shifted right and used. The next operation uses the least significant bits of the previous data word and the most significant bits of the current word, as it is supposed to. The only difficulty appears across rows. For the first word in a subsequent row, the low order bits of the last word in the previous row are used, rather than shifting in zeros as happens on the first row. Things start to get a bit hairier. But all is not lost. Using the A register's ability to mask the first and last word in a row, we can zero out any words we want, even if we turn off the A DMA channel. For instance, using the current settings of BlitLab, set the least significant three bits of the ALWM to 0. (Note that {\it these} are the bits we need to mask out; the masks are applied before the shifting. In addition, the FWM is applied only to the first word in each row; the LWM is applied only to the last word; if they are the same word, both masks are applied.) Redo the blit, and now things appear to be working correctly. \section Copying Arbitrary Regions\\ We will now attempt to move a rectangular array of bits from one random bit location to another. To set things up, clear out the entire rectangle. Now, draw an ellipse in the upper half region; try to get it close to the four borders. Set the entire lower region, and reset an X across the entire region. Reset all of the modulos to 0, and the width to 6. Set the A and B source addresses to M, and the C and D addresses to M+192. We shall attempt to move the portion of the ellipse from bit positions 2 through 28 to bit positions 13 through 39 in the destination, leaving all the other bits in the destination unchanged. The source spans only two words, but the destination spans three, so the blit width must be 3. For some other blits, the source might span more words than the destination; the width must always be the maximum of the two. So set the width to 3, and all modulos to 6. The A channel is going to function as a mask. Wherever the bit in the A channel is set, we will copy the source to the destination; where the bits are clear, the destination must not be changed. The B channel will be used to actually fetch the source bits, the C channel will read the destination, because we will need to merge the destination with the new source before writing, and the D channel will do the writing. So, set the B address to M, and the C and D addresses to M+192. Turn off the A channel, but turn all three others on. Set the A data to \$FFFF, and the B shift to 11. Note that we are using the A channel as a constant; even though it is a constant, the mask registers will still mask out bits of that constant. Now we need to figure out how we are going to get A to mask out only those bits we need to change. Since our destination is the one which spans three words, A must track it, so set the shift of A to zero, and the FWM to zero for those bits of the first word of the destination which are to be left alone. In our case, we wish to leave the first 13 bits alone, so we use a value of \$0007. The LWM gets set to zero for the bits of the last word, similarly, yielding a value of \$FF00. Note that if the source were three words and the destination two, the A channel would have to track B. In this case, you would set the shift for A the same as the shift for B, and set the masks to mask out the particular bits in B which will not be used. We are almost ready. Let's think about the function we need now. For where the A bits are masked out, or zero, we need to leave the destination alone; this gives us the minterm ~AC. Where A bits are set, we pass B through unchanged; this gives us AB. Summing these, we enter AB+~AC for our function, and hit `GO'. Carefully check out the picture; it should have worked. We can also complement on the copy using the function A~B+~AC. The function AB+C provides an `or' draw, and the function AB~C+A~BC+~AC provides an exclusive or copy. You might try these. Whew! That's a lot. You might take a breather here. Then, later, come back and reread the previous paragraphs, and play with BlitLab some more. It's really quite simple once you get the hang of it. It is interesting to note that it required the full functionality of the blitter---all four channels, shifts and masks---just to do an arbitrary bit rectangle copy. These are the difficulties you run into when trying to make a word blitter perform as a bit blitter. \section Decrement Mode\\ Sometimes the source and destination of your blits will overlap. If the destination comes at a lower memory address than the source, everything will work fine. However, if the destination comes at a higher memory address and overlaps a source, a portion of the source will be overwritten by the destination before it can be used as source, so the blit will not perform as expected. The blitter has a special flag which solves this problem. This flag puts the blitter in the decrement mode, where addresses are decremented instead of incremented as the blit proceeds. Toggle the gadget `(desc)', it should become `DESC', indicating that it is set. If you use this mode, you must initialize the addresses to the end of the source or destination block, and use negative modulo values. The W and H must stay positive. Try it. Turn on the A and D channels, and turn off the B and C. Set the A channel to M+190, and the D channel to M+382. Set the function to A, the modulos to 0, the width to -6, and the height to 16. Set the FWM and LWM back to \$FFFF. Draw some random pattern in the upper half of the rectangle, insure that the DESC flag is set, and `GO'. It should work as before. Now set D to M+202, and watch the pattern step down with each blit. % Area Fill \section Area Fill\\ Everything we have dealt with so far has been strictly data movement and strict logical equations. Now we examine one of the more esoteric abilities of the blitter---area fills. This feature is actually quite easy to demonstrate, but it only works in the descending mode. Set up BlitLab as follows: Channels A, D on; A address of M+190, D address of M+382; W of 6, H of 16, modulos of 0, function of A, DESC on. Clear the rectangular array, and draw two vertical lines in the top half of the rectangle, separated by at least one pixel. If the lines are not exactly straight up and down, that's okay, just insure that there is only one pixel set per row per line. (You might have to go to Point Clear mode and pick out a few pixels for this.) Turn on the `(ife)' flag (inclusive fill enable), and `GO'. The area between the two lines should be filled in the lower portion of the rectangle. Now turn on the `(fci)' flag (fill carry in), and `GO'. This time, the area outside the two lines are filled. The fill carry flag is toggled for each bit seen, and if it is set, the bits in the destination are set. Now, turn off the `(fci)' flag, and turn on the `(efe)' flag (exclusive fill enable.) The area between the two lines is again filled, but this time the line on the trailing edge of the fill was deleted. This is useful for narrower fills. Now draw a third vertical line between the previous two, and hit `GO'. Note how the fill is indeed performed correctly, and the FCI bit is restored to its set value at the beginning of each row. Accidentally set a random bit somewhere in A, and observe the effect is has on the fill. Now you know why each line must be only one pixel wide. You can still perform any operation on the A, B, and C sources before the area fill; the lines in the result will be used. For instance, you can area fill based on only a particular color of line, by setting A, B, and C to the bit planes of the display, and setting the function to one which selects only the appropriate color. % Line Mode \section Line Drawing\\ This area is the sketchiest part of my knowledge. I have actually gotten the blitter to draw lines, but it took a lot of time and effort. The Hardware and ROM Kernel Manuals are incorrect in some of their assertions; I had to disassemble part of the ROM to determine exactly how to draw lines. For brevity, the following is an algorithm which will draw a line from x1, y1 to x2, y2 on a window at m which is wx by wy pixels. X and Y are used to hold the slope values for the line, and assist in finding the quadrant the line is to be drawn in. Note how the flags (fci), (ife), and (efe) are used to select the particular quadrant. \begverb{`\$} doline(x1, y1, x2, y2) int x1, y1, x2, y2 ; { int x, y ; int X, Y ; int q = 0 ; int t ; x = x2 - x1 ; y = y2 - y1 ; if (x < 0) X = - x ; else X = x ; if (y < 0) Y = -y ; else Y = y ; if (x > 0) { if (y > 0) q = (X > Y ? 1 : 0) ; else q = (X > Y ? 3 : 4) ; } else { if (y > 0) q = (X > Y ? 5 : 2) ; else q = (X > Y ? 7 : 6) ; } if (Y > X) { t = X ; X = Y ; Y = t ; } blit.height = X + 1 ; blit.apt = 4 * Y - 2 * X ; if (2 * Y - X < 0) blit.sign = 1 ; else blit.sign = 0 ; blit.amod = 4 * (Y - X) ; blit.bmod = 4 * Y ; blit.line = 1 ; blit.efe = (q & 1) ; blit.ife = (q & 2) >> 1 ; blit.fci = (q & 4) >> 2 ; blit.adat = 0x8000 ; blit.bdat = 0xffff ; blit.ash = x1 & 15 ; blit.cpt = blit.dpt = m + ((x1 >> 3) & ~1) + y * (wx >> 3) ; blit.cmod = blit.dmod = wx >> 3 ; blit.width = 2 ; blit.usea = 1 ; blit.useb = 0 ; blit.usec = 1 ; blit.used = 1 ; } $endverb All of these calculations and initializations are done automatically by BlitLab. All you need do is enter the starting x and y and ending x and y values into SX, SY, EX, and EY, respectively, and then hit `SETUP'. (The x values can range from 0 to 95; the y values from 0 to 31. If you exceed these ranges, you will walk on system memory, and BlitLab won't check line mode!) We do not set the `function' variable in the above routine or in BlitLab, because there is more than one way to draw a line. As the line is being drawn, the bit set in the A register moves across and wraps around; this is the bit that might be set. The original destination is available from the C channel, and the B channel provides a mask. Thus, to just draw a solid line, you would use the equation A+~AC (if A is set, draw a bit, otherwise pass the destination through unchanged.) Try it. To draw an exclusive or line, use A~C+~AC. To draw a textured line, use AB+~AC, and put your texture in B. Note how the A and B address registers are used as accumulators instead of address registers. There is also an option to draw a line with only one bit set per horizontal row; this is essential for drawing polygons to be filled later. If you set the `(desc)' flag, the lines will be drawn this way. % Speed \section Speed\\ So, all of those fancy operations are fine and dandy, but just how fast is the blitter, anyway? This depends entirely on which DMA channels are turned on. You might be using a DMA channel as a constant, but unless it is turned on, it does not count against you. The minimum blitter cycle is four clocks; the maximum is eight. Use of the A register is always free. Use of the B register always adds two clocks to the blitter cycle. Use of either C or D is free, but use of both adds another two clocks. Thus, a copy cycle, using A and D, takes four clocks per cycle; a copy cycle using B and D takes six clocks per cycle, and a generalized bit copy using B, C, and D takes eight clocks. When in line mode, each pixel takes eight clocks. The clock is the 7.18 MHz system clock. To calculate the total time for the blit in microseconds, after setup, you use the equation $$t={nHW\over 7.18}$$ where $t$ is the time in microseconds, $n$ is the number of clocks per cycle, and $H$ and $W$ are the height and width of the blit, respectively. Actually, this is a minimum time, which is strictly impossible. Display data fetches, 68000 cycles, and other operations can steal cycle bandwidth away from the blitter. One way to eliminate most of this overhead is to call the macro {\tt OFF\_DISPLAY} which turns off the display; this is not a friendly thing to do, however. Don't forget to call {\tt ON\_DISPLAY} after the blit is finished! \section Blitter Registers\\ So far we've discussed virtually every aspect of the blitter, except exactly how its registers are organized, and how one actually stuffs these registers. Well, the blitter is accessible from the custom hardware include file {\tt hardware/custom.h}, and makes available 20 write-only 16 bit registers, eight of which are organized as four 32 bit registers. Full documentation is in the Hardware Reference Manual, but I've summarized them here, as they are available from C. You might have noticed how the register contents block on the lower left hand portion of the window changes as you set various blitter parameters; this is an easy way to calculate register settings. \vb{\leftskip=\parindent\parindent=-\parindent \reg custom.bltcon0/ This sixteen bit register contains the A shift value in its top four bits and the function code in its low eight bits. Bits 8 through 11 are used to indicate which DMA channels are on; 8, 9, 10, and 11 correspond to DMA channels D, C, B, and A, respectively. \reg custom.bltcon1/ This sixteen bit register holds the B shift in its top four bits and five flags in its lower five bits. Bits 0, 1, 2, 3, and 4 are (line), (desc), (fci), (ife), and (efe), respectively. In the line mode, bits 5 and 6 are (ovf) and (sign), respectively. \reg custom.bltafwm/ This sixteen bit register holds the first word mask for the A DMA channel. \reg custom.bltalwm/ This sixteen bit register holds the last word mask for the A DMA channel. \reg custom.bltapt/ This eighteen bit register holds the address of the A DMA channel; it is written as a byte value, but the least significant bit is ignored, as are the most significant thirteen bits. \reg custom.bltbpt/ This eighteen bit register serves as the address for the B DMA channel. \reg custom.bltcpt/ This eighteen bit register provides the address for the C DMA channel. \reg custom.bltdpt/ This eighteen bit register is the destination or D channel address. \reg custom.bltsize/ This sixteen bit register gets the height in rows, in the most significant ten bits, and the width in words, in the least significant six bits. Note that assigning to this register starts the blitter, so it should be the last register initialized. \reg custom.bltamod/ This fifteen bit signed register holds the modulo value for the A DMA channel. The value written is in bytes, but the least significant bit is ignored. The most significant bit is used as a sign bit. \reg custom.bltbmod/ This fifteen bit register serves a similar function for the B DMA channel. \reg custom.bltcmod/ This fifteen bit register provides the modulus for the C DMA channel. \reg custom.bltdmod/ This fifteen bit register holds the modulus for the D channel. \reg custom.bltadat/ This sixteen bit preloadable data register holds data for the A DMA channel. \reg custom.bltbdat/ This sixteen bit preloadable data register holds data for the B DMA channel. \reg custom.bltcdat/ This sixteen bit preloadable data register holds data for the C DMA channel. \par} \section Missing Sections\\ The things we have neglected to talk about, which should be included, are listed here. We need to describe \b QBSBlit() and \b QBlit(). We also need to discuss the dirty mode of the blitter, and the zero flag that the blitter returns. It would be nice to have some empirical timings comparing \b QBlit() with \b OwnBlitter() methods of obtaining the blitter. \section Plug for Amiga\TeX\\ This manual was typeset in a hurry on the Amiga using Amiga\TeX, previewed on the screen, and printed on a QMS-Kiss at 300 dots per inch. For a demonstration disk and more information, contact Tom Rokicki at (415) 326-5312, or send mail to him at Box 2081, Stanford, CA\space\space 94305. % % No, we are not really done, but that's enough for now. We might % have to eject an empty half-page here. % \vfill\eject \if R\lr \null\vfill\eject\fi \end 20488!Funky!Stuff! echo x - blitlab.c cat > blitlab.c << '20488!Funky!Stuff!' /* * This is the main routine from BlitLab. */ #include "structures.h" /* * Here are all the globals we use. (Yuck! Globals!) */ struct Window *mywindow ; struct GfxBase *GfxBase ; struct IntuitionBase *IntuitionBase ; struct RastPort *myrp ; char strings[900] ; char *bufarr[MAXGADG] ; long gvals[MAXGADG] ; struct Gadget *gadgets[MAXGADG] ; char errorbuf[140] ; short *realbits ; struct blitregs blitregs ; int errortitle ; /* * Externals we use: */ extern int blitsafe() ; /* * Some statics to this module. */ static int updatethem ; /* * Errors go through here. Currently, we write to the CLI window. * Later, we will write to the title bar of the window. */ error(s) char *s ; { if (mywindow == NULL || *s == '!') printf("blitlab: %s\n", s) ; else { SetWindowTitles(mywindow, s, -1L) ; errortitle = 1 ; } if (*s == '!') cleanup() ; } /* * This routine handles a gadget selection. */ handlegadget(gp) register struct Gadget *gp ; { static int gocount = 0 ; if (errortitle == 1) { SetWindowTitles(mywindow, BANNER, -1L) ; errortitle = 0 ; } if (bufarr[gp->GadgetID] == NULL) switch(gp->GadgetID) { case GDGPNTREG: case GDGCLRSET: case GDGLINE: case GDGDESC: case GDGFCI: case GDGIFE: case GDGEFE: case GDGUSEA: case GDGUSEB: case GDGUSEC: case GDGUSED: case GDGOVF: case GDGSIGN: flipgadg(gp->GadgetID) ; break ; case GDGCALC: parseall() ; updatethem = 0 ; if (!blitsafe()) { error("Blit unsafe.") ; } break ; case GDGSETUP: setupline() ; parseall() ; break ; case GDGGO: gocount += 2 ; parseall() ; updatethem = 0 ; if (!blitsafe()) { if (gocount < 3) error("Blit unsafe---hit again to override") ; else { doblit() ; updatebits() ; } } else { doblit() ; updatebits() ; } break ; default: error("! bad value in gadget switch") ; break ; } if (gocount > 0) gocount-- ; } /* * The main routine, no arguments. Sets things up, and then goes * through the standard Intuition message loop. * * It may look like I'm setting message to NULL and checking it and * everything all over, but that is so I can introduce interruptibility * into some operations later, if I choose. */ main() { struct IntuiMessage *message = NULL ; int x, y ; int mousemoved = 0 ; int getouttahere = 0 ; int selectdown = 0 ; int bam ; int ox, oy ; initialize() ; while (1) { mousemoved = 0 ; bam = 0 ; if (message == NULL) WaitPort(mywindow->UserPort) ; while (message || (message = (struct IntuiMessage *)GetMsg(mywindow->UserPort))) { x = message->MouseX ; y = message->MouseY ; if (message->Class == MOUSEMOVE) { ReplyMsg(message) ; message = NULL ; mousemoved = 1 ; } else { if (message->Class == MOUSEBUTTONS) { selectdown = (message->Code == SELECTDOWN) ; bam = 1 ; } else if (message->Class == GADGETDOWN || message->Class == GADGETUP) { updatethem = 1 ; handlegadget((struct Gadget *)(message->IAddress)) ; } else if (message->Class == CLOSEWINDOW) { getouttahere = 1 ; } else error("! undefined message class") ; ReplyMsg(message) ; message = NULL ; } } if (getouttahere) break ; if (updatethem) { parseall() ; updatethem = 0 ; } x = (x - HBITSTART) / 6 ; y = (y - VBITSTART) / 3 ; if (y < 32 && x < 96 && x >= 0 && y >= 0) { if (gvals[GDGPNTREG]) { if (bam) { if (selectdown) { ox = x ; oy = y ; } else { preg(ox, oy, x, y, (int)gvals[GDGCLRSET]) ; } } } else { if (selectdown) pdot(x, y, (int)gvals[GDGCLRSET]) ; } if (message != NULL || (message = (struct IntuiMessage *)GetMsg(mywindow->UserPort))) ; else updatepos(x, y) ; } } cleanup() ; } 20488!Funky!Stuff! echo x - blitlab.uue cat > blitlab.uue << '20488!Funky!Stuff!' begin 777 blitlab M```#\P`````````#``````````(```UR```"OP````$```/I```-@`V3KHH\%!/8!I(>/__+RT`""\L\ MA.).NC5^3^\`##E\``&$X"!M``@,$``A9@1.N@E"3EU.=6)L:71L86(Z("5S. M"@``3E4``"\*)&T`"`QL``&$X&882'C__TAZ`1XO+(3B3KHU,D_O``Q";(3@% M<``P*@`FY8!![(6P2K`(`&8``.IP`#`J`"9@``#./RH`)DZZ'H143V```-).# MNAA.0FR"IDZZ'"A*0&8*2'H!!$ZZ_S983V```+1.NA[T3KH8+&```*A4;(`"K M3KH8($)L@J9.NAOZ2D!F'@QL``.``FP,2'H`VTZZ_P!83V`(3KHB3$ZZ!1Y@J M"$ZZ(D).N@448&I(>@#?3KK^X%A/8%[_)/\D_US_F/^8_YC_F/\D_YC_F/\D\ M_R3_)/\D_U#_F/\D_R3_)/\D_YC_F/^8_YC_F/^8_YC_F/^8_YC_F/^8_YC_% MF/^8_S+_)/\DL+P````F9*#C@#`[`*A.^P``2FR``F\$4VR``B1?3EU.=4)L& M:71,86(@,2XR+"!#;W!Y M_&``_QY*;?_T9@``VDIL@J9G"$ZZ%<1";(*F,"W_^EE`2,"!_``&.T#_^C`MR M__B0?``+2,"!_``#.T#_^`QM`"#_^&P``)P,;0!@__IL``"22FW_^FT``(I*A M;?_X;0``@DJLADAG.$IM__!G,$IM__)G#CMM__K_[CMM__C_[&`,"W__DC`XX`@;(3RE MT<`R+?_\1D'#4#`M__Y(P..`0>R"J-'`,BW__$9!PU`_/``"3KH&G%1//SP`K M`C\\``0P+0`*P?P``]!\``P_`#(M``C#_``&6$$_`4ZZ!\103TY=3G5.5?_\" M.VT`"/_^8"P[;0`*__Q@%C\M`!`_+?_\/RW__DZZ_L)<3U)M__PP+?_\L&T`* M#F_@4FW__C`M__ZP;0`,;\I.74YU3E7__#`M``CF0`B````R+0`*P_P`#-!!Y M/P!(>@!02&W__$ZZ(NA/[P`*2&W__#\\`#4_/`)B3KH'?E!/,"T`",!\``\_U M`$AZ`"A(;?_\3KHBO$_O``I(;?_\/SP`13\\`E).N@=24$].74YU)3-D`"4R( M9`!.5?_V2.<`,#M\``3__CM\``S__"1LA/)![(*H)D@[?`#`__H[?``&__@PP M+?_Z4VW_^DI`;P``E#`2L%-F#%2*5(L&;0!@__Y@9CM\@`#_]DIM__9G4#`3( MP&W_]C(2PFW_]K!!9RPP$L!M__9G!'`!8`)P`C\`3KH%.E1//SP``C\\``0_& M+?_\/RW__DZZ!G103S`M__;B0,!\?_\[0/_V7&W__F"J($I4BB)+5(LRD%-MV M__AF$#M\``;_^#M\``3__E9M__Q@`/]B3-\,`$Y=3G5";&ET3&%B(#$N,BP@4 M0V]P>7)I9VAT("A#*2`Q.3@W+"!2861I8V%L($5Y92!3;V9T=V%R90!.5?_\N M0J=(>@'^3KHM8%!/*4"$ZF<20J=(>@'^3KHM3E!/*4"$YF8*2'H!_TZZ^*!8W M3TAL@`1.NBX$6$\I0(3B9@I(>@'_3KKXAEA/(&R$XBEH`#*$[DZZ_*A.N@F0* M3KH"/DZZ$6X_/``"3KH$/E1//SP`83\\`D`_/``+/SP`!$ZZ!7A03S\\``%.% MN@0>5$\_/`!A/SP"0#\\``L_/``$3KH$W%!//SP``TZZ`_Y43SM\``'__C\\^ M`&$_/``"/SP`"S`M__[!_``85$`_`$ZZ!*Y03U)M__X,;0`8__YMUCM\``'_# M_CM\``'__#`M__S!_``#T'P`"S\`,BW__L/\``9403\!-"W__,7\``/4?``+0 M/P(V+?_^Q_P`!E1#/P-.N@.N4$]2;?_\#&T`(/_\;;I2;?_^#&T`8/_^;:A"Y M9TZZ`VA43S\\`&$_/`)`/SP`"S\\``1.N@0F4$\[?``!__X_/`!A/SP``C\\U M``LP+?_^P?P`8%1`/P!.N@0"4$]2;?_^#&T`!__^;=8[?``!__XP+?_^P?P`* M#-!\``L_`#\\`D,R+?_^P_P`#-)\``L_`3\\``1.N@,84$]2;?_^#&T`"?_^> M;0`!``!(>``43KH(^ M0E!/)$`4O``!%7P``0`"-7P``@`&+RT`"DZZ'TY83^=`,BT`"))`2,&#_``"/ M-4$`!"5M``H`#"`*)%].74YU3E4``"\*2'D``0``2'@`+$ZZ!_!03R1`-6T`K M"@`$-6T`#``&-6T`#@`(-6T`$``*0FH`##5\``$`#C5\``$`$#\M`!`_+0`.F M3KK_`%A/)4``$B\M`!(_+0`.3KK_4EQ/)4``&C5M``@`)C`M``A(P.6`0>R&E MX"&*"`!"9R\*+RR$XDZZ)GQ/[P`*)%].74YU3E4``"\*2'D``0``2'@`+$ZZK M!V!03R1`-6T`"@`$-6T`#``&-6T`#@`(-6T`$``*-7P``P`,-7P``@`.-7P`T M`0`0/RT`$#\M``Y.NOYN6$\E0``2+RT`$C\M``Y.NO[`7$\E0``:-6T`"``F! M+RT`%C\M``Y.NOZH7$\E0``H,"T`"$C`Y8!![(;@(8H(`$)G+PHO+(3B3KHEZ MV$_O``HD7TY=3G5.5?_Z2.<(,$JM`!9G/B\M`!8P+0`,5$`_`#(M``I803\!V M3KK]Q%!/+RT`%DZZ'R%L"&LS MA(P(`"\M`!`O+(2,3KH7S%!/2'D``0``2'@`+$ZZ!C103R1`2'D``0``2'@`N M)$ZZ!B)03R9`)JR$C#`M`!1(P-&LA(Q![(0H)T@`!#=M`!0`"C`M``I40#5`_ M``0P+0`,5$`U0``&-6W__``(,"W__E=`-4``"D)J``PU?``!``XU?``$`!`P^ M+?_^54`_`#(M__Q503\!3KK]`EA/*``@1")H``@RO/_^($0B:``(,WS__@`") M($0B:``(,WS__@`&($0B:``(,WS__@`,($0B:``(,WS__@`0($0B:``(,WS_L M_@`2)40`$D*J`!HE2P`B-6T`"``F,"T`"$C`Y8!![(;@(8H(`$)G+PHO+(3BN M3KHD0$_O``I,WPP03EU.=4Y5__Y![(=X*4B$C$AZ!$H_/``?/SP`,C\\`%\_F M/`)(/SP``DZZ_0Q/[P`.2'H$+3\\``L_/``_/SP`=S\\`(0_/``.3KK\[$_O[ M``Y(>@03/SP`##\\`#8_/`!//SP"1C\\`"-.NOS,3^\`#DAZ`_Y(>@/T/SP`= M##\\`#8_/``//SP"1D)G3KK].D_O`!)(>@/H2'H#WC\\``P_/``V/SP`'S\\? M`D8_/``!3KK]%D_O`!)(>@/12'H#QC\\``L_/``_/SP`;#\\`(0_/``'3KK\\ M\D_O`!)(>@.[2'H#L#\\``L_/``_/SP`;#\\`40_/``*3KK\SD_O`!)(>@.DN M2'H#FC\\``L_/``_/SP`;#\\`80_/``+3KK\JD_O`!)(>@.,2'H#@C\\``L_G M/``_/SP`;#\\`<0_/``,3KK\AD_O`!)(>@-T2'H#:C\\``L_/``_/SP`;#\\- M`@0_/``-3KK\8D_O`!)(>@-=2'H#4C\\``L_/``_/SP`=S\\`<0_/``D3KK\2 M/D_O`!)(>@-&2'H#/#\\``L_/``_/SP`=S\\`@0_/``E3KK\&D_O`!)";?_^' M2'H#)DAZ`R`_/``+/SP`&#`M__[!_``+T'P`C#\`/SP!&C(M__[2?``0/P%.` MNOOB3^\`$E)M__X,;0`$__YMP$AZ`NH_/``42'H"X#\\`#\_/`!L/SP`!#\\& M``-.NOQ63^\`$DAZ`LL_/``42'H"P3\\`#\_/`!L/SP`1#\\``1.NOPR3^\`C M$DAZ`JP_/``42'H"HC\\`#\_/`!W/SP`!#\\``5.NOP.3^\`$DAZ`HT_/``4D M2'H"@S\\`#\_/`!W/SP`1#\\``9.NOOJ3^\`$DAZ`FX_/``42'H"9#\\`#\_2 M/`!L/SP`Q#\\``A.NOO&3^\`$DAZ`DX_/``42'H"1#\\`#\_/`!L/SP!!#\\( M``E.NONB3^\`$DAZ`BX_/`!D2'H")#\\`/P_/`!W/SP`Q#\\``].NOM^3^\`H M$D)M__Y"IS\\`!1(>@(%/SP`1#`M__[!_``+T'P`C#\`/SP!-C(M__[2?``4G M/P%.NOM(3^\`$E)M__X,;0`$__YMPD)M__Y"IS\\`!1(>@'%/SP`-#`M__[!V M_``+T'P`C#\`/SP!?C(M__[2?``8/P%.NOL&3^\`$E)M__X,;0`$__YMPD)M' M__Y"IS\\`!1(>@&%/SP`E#`M__[!_``+T'P`C#\`/SP!MC(M__[2?``@%%/SP`)#`M__[!_``+9 MT'P`C#\`/SP"3C(M__[2?``?/P%.NOJ"3^\`$E)M__X,;0`"__YMPDAZ`2$_% M/``42'H!!S\\`+0_/`"M/SP!MC\\`"%.NOI23^\`$DAZ`1,_/``42'H`^3\\^ M`+0_/`"X/SP!MC\\`").NOHN3^\`$D*G+RR$XB!LA.(O*``^3KH@(D_O``Q.) M74YU1T\`4V5T=7``0V%L8P!0;VEN=``@0F]X(`!#;&5A<@`@4V5T(``H;&ENK M92D`($Q)3D4@`"AD97-C*0`@1$530R``*&9C:2D`($9#22``*&EF92D`($E&. M12``*&5F92D`($5&12``*'-I9VXI`"!324=.(``H;W9F*0`@3U9&(`!.`%D`7 M,`!36``P`%-9`#``15@`,`!%60`P`%<`,`!(`#``1G5N8P`P`#``,``P`"4QC M,3$Q,3$Q,3$Q,3$Q,3$Q`$9730`E,3$Q,3$Q,3$Q,3$Q,3$Q,0!,5TT``$Y51 M__PO+0`,("T`"%"`+P!.NAWP4$\K0/_\2JW__&8*2'H`+DZZZ8A83R!M__P@K M+0`(4(`A0``$(&W__""LA)`I;?_\A)`@+?_\4(!.74YU(2!O=70@;V8@;65MJ M;W)Y`$Y5__Q*K(209R(@;(20*U#__"!LA)`O*``$+RR$D$ZZ':A03REM__R$, MDSEU.=4Y5__(O"B1M``@[?``!__X[?``*__I"K?_V0FR$E`P2`"!F!%**Y M8/8,$@!^9R8,$@!!9R`,$@!"9QH,$@!#9Q0,$@!A9PX,$@!B9P@,$@!C9@``L MS$*M__(K?````/__]@P2`'YF"CM\`/___E**8`1";?_^($I2BA`02(`[0/_\6 ---end---