p p ` O`! Oo-/3o79;=?ACoIMQ SUY[]_/c@e`gikmoq s@u`wy{}@`/ o O ` @ ` @ ` ǀ ɠ ׀ ٠  @` @`!Aa   !Aa!!#A%a')+-/1!3A5a79;=?A!CAEaGIKMOQ!SAUaWY[]_a!cAeagmoqOuawy{}!oAaAa!Aa!Aaǁɡ!Aaׁ١!Aa!Aa " B b  !"!B!b!!!!!"!""#B"%b"'")"+"-"/#1"#3B#5b#7#9#;#=#?$A"$CB$Eb$G$I$K$M$O%Q"%SB%Ub%W%Y%[%]%_&a"&cB&eb&g&i&k&m&o'q"'sB'ub'w'y'{'}'("(B(b((((()")B)b)))))*"*B*b***+"+B+b+++++,B,` O`! Oo-/3o79;=?ACoIMQ SUY[]_/c@e`gikmoq s@u`wy{}@`/ o O ` @ ` @ ` ǀ ɠ ׀ ٠  @` @`!Aa   !Aa!!#A%a')+-/1!3A5a79;=?A!CAEaGIKMOQ!SAUaWY[]_a!cAeagmoqOuawy{}!oAaAa!Aa!Aaǁɡ!Aaׁ١!Aa!Aa " B b  !"!B!b!!!!!"!""#B"%b"'")"+"-"/#1"#3B#5b#7#9#;#=#?$A"$CB$Eb$G$I$K$M$O%Q"%SB%Ub%W%Y%[%]%_&a"&cB&eb&g&i&k&m&o'q"'sB'ub'w'y'{'}'("(B(b((((()")B)b)))))*"*B*b***+"+B+b+++++,B,ASSEMBLY NAUTO NC NGFA OhMISC )OSTOS 3ODESKTOP INF ICTARI TXT S{NREAD_ME TXT qnV ICTARI 012. N.. STECYCLE NTIMERS NVBL_INFO NSPRITE TUTNCOMPARE N/XFORMAT N4KEY_EQUATESN. N.. NSTECYCLES <`%*************************************************************************** * Hello ICTARI members! Yep, it's me again (Ralph) and this time I've got * a colour cycling routine for you which uses the STE palette but should * work just as well on a standard ST. * If you want it to run in medium resolution, simply remove the trap #14 * instruction below, and change the "move (a0)+,$ffff825e.w" command in the * hbl routine to "move (a0)+,$ffff8246.w", as the text colour is different * for medium resolution. * Likewise, if you want to have the cycle in the background (rasters style) * you can change it to "move (a0)+,$ffff8240.w". This gives you around * 300 colours on screen. * This routine can easily be incorporated into any program; just remember * to reload the palette etc. at the start of your vertical blank routine. * Should the synchronisation required for the horizontal blank cause * problems, I suggest you use timer B instead - the disadvantage is that * this method cannot manipulate every visible scanline! * NOTE: Set your tabs to 10 for everything to make sense. (?!) * And if anyone has ST Internals, please call me on 0367 241940. Thanks! *************************************************************************** clr -(sp) pea -1.w pea -1.w move #5,-(sp) trap #14 Switch to low res (not essential) add.l #12,sp pea start(pc) move #38,-(sp) trap #14 Execute routine in supervisor mode addq.l #6,sp move.w #1,-(sp) pea -1.w pea -1.w move #5,-(sp) trap #14 Switch back to medium res add.l #12,sp clr -(sp) exit trap #1 start move.b #$12,$fffffc02.w disable mouse bclr.b #5,$fffffa09.w disable timer C (prevents flicker) move.l $70.w,oldvbl save the old vbl move.l $68.w,oldhbl save the old hbl clr.w $ffff8240.w Background = black clr.w $ffff825e.w Text = black move.l #text,-(sp) move.w #9,-(sp) trap #1 Print silly text addq.l #6,sp move.l #vbl,$70.w install new vbl move.l #hbl,$68.w install new hbl move #$2100,sr set interrupt level testkey cmp.b #$39,$fffffc02.w check for space bar bne.s testkey move.w #$777,$ffff8240.w Background = white clr.w $ffff825e.w Text = black move.l oldhbl,$68.w load old hbl move.l oldvbl,$70.w load old vbl bset.b #5,$fffffa09.w enable timer C (for keyboard input) move.b #8,$fffffc02.w enable mouse rts user mode *** vbl move.l #pal,offset reload the palette add.l #2,counter move down colour table cmp.l #1276,counter end of table? bne.s continue clr.l counter back to start of table continue move.l counter(pc),d0 add.l d0,offset pointer to colour for 1st scanline rte *** hbl dcb.w 88,$4e71 synchronise (88 NOPs) move.l a0,-(sp) move.l offset(pc),a0 get offset into color palette move (a0)+,$ffff825e.w next color -> next scanline move.l a0,offset store next color move.l (sp)+,a0 rte *************************************************************************** section data text dc.b " The Chromatastic STE Colour Cycle...",13,10 dc.b " Coded by Ralph Lovesy",13,10 dc.b " (aka Axolotl)",13,10 dc.b " in January 1994.",13,10,13,10 dc.b " Some technical information:",13,10 dc.b " The effect is created by using",13,10 dc.b " the Horizontal Blank Auto-Vector",13,10 dc.b " Interrupt at address $68.",13,10,13,10 dc.b " The colours are read off a table of",13,10 dc.b " values and the palette offset is",13,10 dc.b " incremented every vertical blank",13,10 dc.b " after reloading the palette...",13,10,13,10 dc.b " The speed of the colour cycle can be",13,10 dc.b "changed by altering the amount by which",13,10 dc.b ' the value "counter" is incremented',13,10 dc.b " at the start of every vertical blank.",13,10,13,10 dc.b " Although this effect was designed for",13,10 dc.b " STE machines, it works on all STs,",13,10 dc.b " as the extra bits of the STE palette",13,10 dc.b " are ignored by the ST/F/M/FM!",13,10 dc.b " Hope this is useful or inspirational!" dc.b 0 pal dcb.w 24 dc.w $00F,$00F,$00F,$00F,$80F,$00F,$80F,$80F dc.w $80F,$80F,$80F,$10F,$80F,$10F,$10F,$10F dc.w $10F,$10F,$90F,$10F,$90F,$90F,$90F,$90F dc.w $90F,$20F,$90F,$20F,$20F,$20F,$20F,$20F dc.w $A0F,$20F,$A0F,$A0F,$A0F,$A0F,$A0F,$A0F dc.w $30F,$A0F,$30F,$30F,$30F,$30F,$30F,$B0F dc.w $30F,$B0F,$B0F,$B0F,$B0F,$B0F,$40F,$B0F dc.w $40F,$40F,$40F,$40F,$40F,$C0F,$40F,$C0F dc.w $C0F,$C0F,$C0F,$C0F,$50F,$C0F,$50F,$50F dc.w $50F,$50F,$50F,$D0F,$50F,$D0F,$D0F,$D0F dc.w $D0F,$D0F,$60F,$D0F,$60F,$60F,$60F,$60F dc.w $60F,$E0F,$60F,$E0F,$E0F,$E0F,$E0F,$E0F dc.w $70F,$E0F,$70F,$70F,$70F,$70F,$70F,$F0F dc.w $70F,$F0F,$F0F,$F0F,$F0F,$F0F,$F07,$F0F dc.w $F07,$F07,$F07,$F07,$F07,$F0E,$F07,$F0E dc.w $F0E,$F0E,$F0E,$F0E,$F06,$F0E,$F06,$F06 dc.w $F06,$F06,$F06,$F0D,$F06,$F0D,$F0D,$F0D dc.w $F0D,$F0D,$F05,$F0D,$F05,$F05,$F05,$F05 dc.w $F05,$F0C,$F05,$F0C,$F0C,$F0C,$F0C,$F0C dc.w $F04,$F0C,$F04,$F04,$F04,$F04,$F04,$F0B dc.w $F04,$F0B,$F0B,$F0B,$F0B,$F0B,$F03,$F0B dc.w $F03,$F03,$F03,$F03,$F03,$F0A,$F03,$F0A dc.w $F0A,$F0A,$F0A,$F0A,$F02,$F0A,$F02,$F02 dc.w $F02,$F02,$F02,$F09,$F02,$F09,$F09,$F09 dc.w $F09,$F09,$F01,$F09,$F01,$F01,$F01,$F01 dc.w $F01,$F08,$F01,$F08,$F08,$F08,$F08,$F08 dc.w $F00,$F08,$F00,$F00,$F00,$F00,$F00,$F80 dc.w $F00,$F80,$F80,$F80,$F80,$F80,$F10,$F80 dc.w $F10,$F10,$F10,$F10,$F10,$F90,$F10,$F90 dc.w $F90,$F90,$F90,$F90,$F20,$F90,$F20,$F20 dc.w $F20,$F20,$F20,$FA0,$F20,$FA0,$FA0,$FA0 dc.w $FA0,$FA0,$F30,$FA0,$F30,$F30,$F30,$F30 dc.w $F30,$FB0,$F30,$FB0,$FB0,$FB0,$FB0,$FB0 dc.w $F40,$FB0,$F40,$F40,$F40,$F40,$F40,$FC0 dc.w $F40,$FC0,$FC0,$FC0,$FC0,$FC0,$F50,$FC0 dc.w $F50,$F50,$F50,$F50,$F50,$FD0,$F50,$FD0 dc.w $FD0,$FD0,$FD0,$FD0,$F60,$FD0,$F60,$F60 dc.w $F60,$F60,$F60,$FE0,$F60,$FE0,$FE0,$FE0 dc.w $FE0,$FE0,$F70,$FE0,$F70,$F70,$F70,$F70 dc.w $F70,$FF0,$F70,$FF0,$FF0,$FF0,$FF0,$FF0 dc.w $FF0,$FF0,$FF0,$FF0,$FF0,$FF0,$FF0,$FF0 dc.w $7F0,$FF0,$7F0,$7F0,$7F0,$7F0,$7F0,$EF0 dc.w $7F0,$EF0,$EF0,$EF0,$EF0,$EF0,$6F0,$EF0 dc.w $6F0,$6F0,$6F0,$6F0,$6F0,$DF0,$6F0,$DF0 dc.w $DF0,$DF0,$DF0,$DF0,$5F0,$DF0,$5F0,$5F0 dc.w $5F0,$5F0,$5F0,$CF0,$5F0,$CF0,$CF0,$CF0 dc.w $CF0,$CF0,$4F0,$CF0,$4F0,$4F0,$4F0,$4F0 dc.w $4F0,$BF0,$4F0,$BF0,$BF0,$BF0,$BF0,$BF0 dc.w $3F0,$BF0,$3F0,$3F0,$3F0,$3F0,$3F0,$AF0 dc.w $3F0,$AF0,$AF0,$AF0,$AF0,$AF0,$2F0,$AF0 dc.w $2F0,$2F0,$2F0,$2F0,$2F0,$9F0,$2F0,$9F0 dc.w $9F0,$9F0,$9F0,$9F0,$1F0,$9F0,$1F0,$1F0 dc.w $1F0,$1F0,$1F0,$8F0,$1F0,$8F0,$8F0,$8F0 dc.w $8F0,$8F0,$0F0,$8F0,$0F0,$0F0,$0F0,$0F0 dc.w $0F0,$0F8,$0F0,$0F8,$0F8,$0F8,$0F8,$0F8 dc.w $0F1,$0F8,$0F1,$0F1,$0F1,$0F1,$0F1,$0F9 dc.w $0F1,$0F9,$0F9,$0F9,$0F9,$0F9,$0F2,$0F9 dc.w $0F2,$0F2,$0F2,$0F2,$0F2,$0FA,$0F2,$0FA dc.w $0FA,$0FA,$0FA,$0FA,$0F3,$0FA,$0F3,$0F3 dc.w $0F3,$0F3,$0F3,$0FB,$0F3,$0FB,$0FB,$0FB dc.w $0FB,$0FB,$0F4,$0FB,$0F4,$0F4,$0F4,$0F4 dc.w $0F4,$0FC,$0F4,$0FC,$0FC,$0FC,$0FC,$0FC dc.w $0F5,$0FC,$0F5,$0F5,$0F5,$0F5,$0F5,$0FD dc.w $0F5,$0FD,$0FD,$0FD,$0FD,$0FD,$0F6,$0FD dc.w $0F6,$0F6,$0F6,$0F6,$0F6,$0FE,$0F6,$0FE dc.w $0FE,$0FE,$0FE,$0FE,$0F7,$0FE,$0F7,$0F7 dc.w $0F7,$0F7,$0F7,$0FF,$0F7,$0FF,$0FF,$0FF dc.w $0FF,$0FF,$07F,$0FF,$07F,$07F,$07F,$07F dc.w $07F,$0EF,$07F,$0EF,$0EF,$0EF,$0EF,$0EF dc.w $06F,$0EF,$06F,$06F,$06F,$06F,$06F,$0DF dc.w $06F,$0DF,$0DF,$0DF,$0DF,$0DF,$05F,$0DF dc.w $05F,$05F,$05F,$05F,$05F,$0CF,$05F,$0CF dc.w $0CF,$0CF,$0CF,$0CF,$04F,$0CF,$04F,$04F dc.w $04F,$04F,$04F,$0BF,$04F,$0BF,$0BF,$0BF dc.w $0BF,$0BF,$03F,$0BF,$03F,$03F,$03F,$03F dc.w $03F,$0AF,$03F,$0AF,$0AF,$0AF,$0AF,$0AF dc.w $02F,$0AF,$02F,$02F,$02F,$02F,$02F,$09F dc.w $02F,$09F,$09F,$09F,$09F,$09F,$01F,$09F dc.w $01F,$01F,$01F,$01F,$01F,$08F,$01F,$08F dc.w $08F,$08F,$08F,$08F,$00F,$08F,$00F,$00F dc.w $00F,$00F,$80F,$00F,$80F,$80F,$80F,$80F dc.w $80F,$10F,$80F,$10F,$10F,$10F,$10F,$10F dc.w $90F,$10F,$90F,$90F,$90F,$90F,$90F,$20F dc.w $90F,$20F,$20F,$20F,$20F,$20F,$A0F,$20F dc.w $A0F,$A0F,$A0F,$A0F,$A0F,$A0F,$30F,$A0F dc.w $30F,$30F,$30F,$30F,$30F,$B0F,$30F,$B0F dc.w $B0F,$B0F,$B0F,$B0F,$40F,$B0F,$40F,$40F dc.w $40F,$40F,$40F,$C0F,$40F,$C0F,$C0F,$C0F dc.w $C0F,$C0F,$50F,$C0F,$50F,$50F,$50F,$50F dc.w $50F,$D0F,$50F,$D0F,$D0F,$D0F,$D0F,$D0F dc.w $60F,$D0F,$60F,$60F,$60F,$60F,$60F,$E0F dc.w $60F,$E0F,$E0F,$E0F,$E0F,$E0F,$70F,$E0F dc.w $70F,$70F,$70F,$70F,$70F,$F0F,$70F,$F0F dc.w $F0F,$F0F,$F0F,$F0F,$F07,$F0F,$F07,$F07 dc.w $F07,$F07,$F07,$F0E,$F07,$F0E,$F0E,$F0E dc.w $F0E,$F0E,$F06,$F0E,$F06,$F06,$F06,$F06 dc.w $F06,$F0D,$F06,$F0D,$F0D,$F0D,$F0D,$F0D dc.w $F05,$F0D,$F05,$F05,$F05,$F05,$F05,$F0C dc.w $F05,$F0C,$F0C,$F0C,$F0C,$F0C,$F04,$F0C dc.w $F04,$F04,$F04,$F04,$F04,$F0B,$F04,$F0B dc.w $F0B,$F0B,$F0B,$F0B,$F03,$F0B,$F03,$F03 dc.w $F03,$F03,$F03,$F0A,$F03,$F0A,$F0A,$F0A dc.w $F0A,$F0A,$F02,$F0A,$F02,$F02,$F02,$F02 dc.w $F02,$F09,$F02,$F09,$F09,$F09,$F09,$F09 dc.w $F01,$F09,$F01,$F01,$F01,$F01,$F01,$F08 dc.w $F01,$F08,$F08,$F08,$F08,$F08,$F00,$F08 dc.w $F00,$F00,$F00,$F00,$F00,$F80,$F00,$F80 dc.w $F80,$F80,$F80,$F80,$F10,$F80,$F10,$F10 dc.w $F10,$F10,$F10,$F90,$F10,$F90,$F90,$F90 dc.w $F90,$F90,$F20,$F90,$F20,$F20,$F20,$F20 dc.w $F20,$FA0,$F20,$FA0,$FA0,$FA0,$FA0,$FA0 dc.w $F30,$FA0,$F30,$F30,$F30,$F30,$F30,$FB0 dc.w $F30,$FB0,$FB0,$FB0,$FB0,$FB0,$F40,$FB0 dc.w $F40,$F40,$F40,$F40,$F40,$FC0,$F40,$FC0 dc.w $FC0,$FC0,$FC0,$FC0,$F50,$FC0 section bss counter ds.l 1 offset ds.l 1 oldhbl ds.l 1 oldvbl ds.l 1 * Th-th-th-tha-that's all folks!. N.. NHZ_TIMERS y~HZ_TIMERDOC 4oP;Convert Hz value into Control & Data values for Timers ;ENTRY: D0 = Interrupt Frequency (in Hertz) ;EXIT: D0 = Control byte in High word, Data byte in Low word ;USES: Macro Div_l in INTMATH.I ; Registers D0-D1 include INTMATH.I TEXT Hz_to_timer move.l #2457600,d1 ;timer frequency Div_l d0,d1 ;answer in d1, remainder in d0 Hz_tt4 lsr #2,d1 ;divide counter by 4 move.w #1,d0 ;divide by 4 in prescalar cmp.l #128,d1 ;timer count <256 (allowing for tempo changes) ble.s Hz_ttset Hz_tt16 lsr #2,d1 move.w #3,d0 ;divide by 16 in prescalar cmp.l #128,d1 ble.s Hz_ttset Hz_tt64 lsr #2,d1 move.w #5,d0 Hz_ttset swap d0 move.w d1,d0 ;counter value rts SUB-ROUTINE NAME Hz_to_timer BRIEF DESCRIPTION Convert Number in d0.l to Control and Data values for System Timers A to D. FILENAME HZ_TIMER.S OTHER RESOURCES Macro Div_l in INTMATH.I LANGUAGE Assembler (Devpac) AUTHOR Simon.H.Rigby - aka PoshPaws - aka Si(gh) ENTRY PARAMETERS D0 = Interrupt Frequency Required (in Hertz) EXIT PARAMETERS D0 = Control Value in High Byte Data Value in Low Byte DETAILS - Takes the contents of d0 and converts it into Control and Data Values suitable for feeding into the Interrupt Timer Registers. It uses the closest match it can to the frequency required by dividing the master clock (2457600Hz) by 4, 16 or 64 and then working out the number of clock ticks required to give the required interrupt frequency. Destroys previous contents of d0-d1. Example - Library move.l #12000,d0 ;12KHz required bsr Hz_to_timer move.w d0,d2 ;Data value swap d0 move.w d0,d1 ;Control value ... ... Xbtimer #0,d1,d2,#Int_sub ;enable Timer A (0) interrupt ... ;with control and data to call ... ;Int_sub routine rts Int_sub ... ... rte ;return from interrupt . N.. NVBL TXT N q VBL - the V ertical BL ank Interrupt routines. =============================================== By Mike Barnard The VBL is one of the most useful interrupts in the ST TOS. Each time the Video Shifter reaches the end of the currently displayed screen, it generates an interrupt signal (level 4 for the vbl queue) which tells the 68000 that the VBL queue is waiting to be processed. As with all interrupts, the processor runs on until the interrupt mask is able to accept the VBL queue as top priority. When control is transferred to the VBL routine it does the following tasks. 1. It increases the counter 'frclock' ($466) by one. This counts the number of frames displayed, regardless of what happens later in the queue. 2. Tests the variable 'vblsem' ($452) to see if the VBL has been software disabled. If vblsem is 0 or negative then it has and the routine immediately exits and returns control of the processor to the program. 3. All registers are saved to the stack. 4. It increases the counter 'vbclock' ($462) by one. This counts the number of times the VBL routine is executed. 5. It then checks to see if a different monitor has been connected. This is because the refresh rate of 70Hz required by a monochrome monitors could do damage to a colour monitor designed to refresh at 50 or 60Hz. If a change has been made, the video shifter is reprogrammed accordingly. (More detail required, please). 6. A routine to flash the cursor. (Any useful details anyone?). 7. Test 'colorptr' ($45A) for 0. If it's anything other than 0 this is considered the address of a new colour palette and the 16 words from here are loaded into the video shifter as a new palette, colorptr is then cleared again. (This is how the BIOS call changes the palette). 8. Test 'screenpt' ($45E) for 0. If other than zero it's considered to be the base address of the screen. ???? (logical or physical?) (Where is the other address stored?) (More detail...) 9. The floppy disc routines are run. My information is limited to... a. Decide if a disc has been changed within a drive. b. Deselect the drives after the disc controller has turned the drive motor off. 10. Now the VBL queue is processed. This is where we put our routines. 11. The variable 'dmpflg' ($4EE) is examined. If it's zero, a hardcopy of the screen is outputted. The flag is set during the IKBD's interrupt routine if ALT+HELP are pressed together. 12. The register contents are restored. 13. The book 'Atari ST Anatomy' by First Publishing says that 'vblsem' is released'. It doesn't say how. Anyone with more information, please? 14. RTE, return from exception. The original program continues as if nothing had happened. Much! All this happens at the refresh rate of your monitor, 50, 60 or even 70 times a second. The VBL queue is a vector array. That is, a list (queue) of addresses held in protected memory. Each entry may hold either an address or zero (i.e. empty). The variable 'vblqueue' ($456) holds the address of the start of this array. The variable 'nvbls' ($454) holds the size of this array, normally 8 longwords of memory, i.e. 8 entries. (If there is not enough space with 8 entries then you can increase the number in 'nvbls' to however many you need, but you will have to move the queue to an area of memory with enough room to store the extra addresses and change the contents of 'vblqueue' to the address of the new array. Also, don't forget to restore the original values on exiting from your program). The TOS VBL routine tests each of the entries in turn and if the entry is not zero it is considered as the start address of a routine to be run. If it is zero, it is ignored. So, how can we use the VBL queue for ourselves? Firstly write the routine you wish to run. Maybe it increases a counter for something, or looks at joystick input? If it's in the VBL queue it WILL BE PROCESSED AT LEAST 50 TIMES A SECOND! So make it as short and as fast as you possibly can. Don't use the VBL without real need. If your routine takes (for example) 250 cycles to run, then it takes 12,500 cycles a second from the 8,000,000 the processor has. Add that on to the amount of time the rest of the VBL routine takes for itself and any other routines you may also have in the queue and your program may slow down considerably. My books say that your VBL routine can use all the CPU registers as normal EXCEPT the user stack pointer. It must end in RTS. I haven't experimented with this yet, but I ASSUME this to mean the command '- (sp)' and similar stack commands, are a no-go. Again, will someone fill in more detail please? So, now you have a short, fast routine. Label it. Our next job is to add the address of this label to the VBL queue. The area of memory holding the VBL queue and pointers is PROTECTED memory, i.e. an area of RAM that can only be accessed in supervisor mode. This is to stop stray program commands wiping out vital parts of the OS or its data and variables. But we need to access it so we must switch from user mode to supervisor mode. You have two choices. There is a system trap that switches the CPU from user to super and back again, (GEMDOS $20 - SUPER), and another trap that takes the address of a routine and runs that routine in super. (XBIOS 38 - SUPEXEC). Which to choose? That's your choice. Some people use gem20 to set the whole of their program to super mode at or near the start of their source and leave it that way throughout the whole program. Restoring to user mode at the end, I hope! Then you can access protected memory and OS variables at will. Others try to follow the 'rules' (ha!) and give the address of any routines that want to access protected memory to supexec which runs them in super for you, returning in user mode again. You'll have to work out the fine detail of this bit yourself. If you're reading this you're a programmer, of some sort, aren't you? But the outline is: Into super mode, (allows access to protected memory). Search the queue for an empty slot, (value of 0). Save the address of the slot you're about to fill. Put the address of your routine into the slot. Return to user mode. (Maybe). Continue with the program. Your vbl routine is now running each frame. On exiting your program, restore the value of 0 to the slot or it will stay there. CRRRRRRAAAAAASH, BOMMMMB!! Pooooow, zap, pop. I hope this helps any beginners to programming and perhaps any experts could fill in the gaps in my knowledge of interrupt programming. $F04,$F04,$F04,$F04,$F04,$F0B,$F04,$F0B dc.w $F0B,$F0B,$F0B,$F0B,$F03,$F0B,$F03,$F03 dc.w $F03,$F03,$F03,$F0A,$F03,$F0A,$F0A,$F0A dc.w $F0A,$F0A,$F02,$F0A,$F02,$F02,$F02,$F02 dc.w $F02,$F09,$F02,$F09,$F09,$F09,$F09,$F09 dc.w $F01,$F09,$F01,$F01,$F01,$F01,$F01,$F08 dc.w $F01,$F08,$F08,$F08,$F08,$F08,$F00,$F08 dc.w $F00,$F00,$F00,$F00,$F00,$F80,$F00,$F80 dc.w $F80,$F80,$F80,$F80,$F10,$F80,$F10,$F10 dc.w $F10,$F10,$F10,$F90,$F10,$F90,$F90,$F90 dc.w $F90,$F90,$F20,$F90,$F20,$F20,$F20,$F20 dc.w $F20,$FA0,$F20,$FA0,$FA0,$FA0,$FA0,$FA0 dc.w $F30,$FA0,$F30,$F30,$F30,$F30,$F30,$FB0 dc.w $F30,$FB0,$FB0,$FB0,$FB0,$FB0,$F40,$FB0 dc.w $F40,$F40,$F40,$F40,$F40,$FC0,$F40,$FC0 dc.w $FC0,$FC0,$FC0,$FC0,$F50,$FC0 section bss counter ds.l 1 offset ds.l 1 oldhbl ds.l 1 oldvbl ds.l 1 * Th-th-th-tha-that's all folks! . N.. NPAC OBJ PAC_HD OBJ *SPRITE LIB ` DINIT LIB f`#GRAPHICSLIB V`%*INIT LIB u`'kMAIN S `)SPRITE TXT [+O  @?@~|~@?@ @ @  @?@|@?@    @?@@?@  ""@@?    @?@@?@""  X?}(g0g0Bg0ppppXX @@ }?}ss豈ssZнpppp  }?}hNpNphNpNpZнppppj@@j@@@@NEOOBJPACMAN.PI1  1R p   @?@~|~@?@ @ @  @?@|@?@    @?@@?@  ""@@?    @?@@?@""  X?}(g0g0Bg0ppppXX @@ }?}ss豈ssZнpppp  }?}hNpNphNpNpZнppppj@@j@@@@***************************************************** * SPRITE SUBROUTINES * * * * (c) Nick Bates 1994 * * Last modified: 23/03/94 * ***************************************************** ***************************************************** * DRAW_SPRITE_16 * * * * Draws a 16x16 sprite to logical screen * * No clipping, * * * * Parameters: D0 - x cordinates * * D1 - y co-ordinates * * D2 - spite number * * sprite - pointer to sprites file * * log - logical screen * * NOTE: * * PHRASES WITHIN ****/ /***** SHOW WHERE TO * * MODIFY FOR DIFFERENT SPRITE SIZES * ***************************************************** draw_sprite_16 movem.l a0-a1/d0-d7,-(sp) STORE REGISTERS lea sprites,a1 POINTER TO SPRITE FILE move.l log,a0 POINTER TO LOGICAL SCREEN * NEED TO MOVE TO THE REQUIRED SPRITE IN THE SPRITE FILE mulu #128,d2 ****/ SPRITE SIZE : x * y / 2 : 16 * 16 / 2 = 128 /**** add.l d2,a1 ADJUST INTO SPRITE FILE TO REQUIRED SPRITE NUMBER * NEED TO CONVERT X and Y CORDINATES TO VALUES TO ADD INTO SCREEN ADDRESS move.w d1,d7 STORE Y CO-ORDINATE add.w d7,d7 add.w d7,d7 add.w d1,d7 lsl.w #5,d7 ABOVE IN EFFECT MULTIPLIES : * 5 * 32 adda.w d7,a0 GOTO Y CO-ORDINATE IN LOGICAL SCREEN move.w d0,d7 STORE X CO-ORDINATE andi.w #$fff0,d7 ADJUST TO 16 BOUNDARY lsr.w #1,d7 DIVIDE BY 2 adda.w d7,a0 GOTO X CO-ORDINATE IN LOGICAL SCREEN andi.w #$f,d0 D7-D0 - VALUE TO ROTATE BY * DRAW EACH LINE OF SPRITE AT A TIME moveq #15,d2 ****/ SPRITE HEIGHT - 1 ****/ .loop ****/ REPEAT THIS FOR EACH 16 PIXELS IN LENGTH ****/ * LOAD IN THE FOUR PLANES, AND ROTATE THEM moveq #0,d4 ZERO DATA REGISTER move.w (a1)+,d4 PLANE 0 ror.l d0,d4 ROTATE BY REQUIRED VALUE moveq #0,d5 move.w (a1)+,d5 PLANE 1 ror.l d0,d5 moveq #0,d6 move.w (a1)+,d6 PLANE 2 ror.l d0,d6 moveq #0,d7 move.w (a1)+,d7 PLANE 3 ror.l d0,d7 * CREATE A MASK FROM THE FOUR PLANES INTO D3 move.w d4,d3 or.w d5,d3 or.w d6,d3 or.w d7,d3 OR ALL THE VALUES TOGETHER not.w d3 NEGATE THE RESULT * PUT INTO LOGICAL SCREEN - AND THE MASK WITH THE * CURRENT SCREEN DATA, AND OR THE NEW DATA IN and.w d3,(a0) AND MASK or.w d4,(a0)+ OR PLANE 0 - INCREMENT SCREEN and.w d3,(a0) or.w d5,(a0)+ PLANE 1 and.w d3,(a0) or.w d6,(a0)+ PLANE 2 and.w d3,(a0) or.w d7,(a0)+ PLANE 3 * NOW DO THE PART THAT WAS ROTATED TO THE OTHER HIGH WORD swap d4 SWAP HI-LOW VALUES OF REGISTER swap d5 swap d6 swap d7 * CREATE MASK move.w d4,d3 or.w d5,d3 or.w d6,d3 or.w d7,d3 not.w d3 * AND MASK WITH CURRENT SCREEN DATA, OR WITH NEW DATA and.w d3,(a0) or.w d4,(a0)+ and.w d3,(a0) or.w d5,(a0)+ and.w d3,(a0) or.w d6,(a0)+ and.w d3,(a0) or.w d7,(a0)+ * NOW ADD TO THE SCREEN TO GET TO THE NEXT LINE IN THE SCREEN add #144,a0 *****/ VALUE FOR NEXT LINE : 152-(length/2) : 152-(16/2) /***** dbra d2,.loop LOOP FOR ALL LINES movem.l (sp)+,a0-a1/d0-d7 RESTORE REGISTERS rts ***************************************************** * DE-INITIALISE SUBROUTINES * * * * (c) Nick Bates 1994 * * Last modified: 23/03/94 * ***************************************************** ***************************************************** * RESTORE_SCREEN * * * * Restores vbi, resolution, logical and physical * * screens. * * Parameters: old_vbi, old_res, old_scrn * ***************************************************** restore_screen move.l old_vbi,$70 move.w old_res,-(sp) restore resolution move.l old_scrn,-(sp) restore physical move.l old_scrn,-(sp) restore logical move #5,-(sp) XBIOS - SET SCREEN trap #14 lea 12(sp),sp rts ***************************************************** * RESTORE_PALETTE * * * * Restore old palette from: old_pal * ***************************************************** restore_palette movem.l old_pal,d0-d7 movem.l d0-d7,$fff8240 restore pallette rts ***************************************************** * GO_USER * * * * Restore stack from: old_stk * * Goes to User Mode * ***************************************************** go_user move.l old_stk,-(sp) restore stack move.w #$20,-(sp) GEMDOS - USER MODE trap #1 addq.l #6,sp user mode rts ********************************************************* * GRAPHICS SUBROUTINES * * * * Author: Nick Bates (c) 1994 * * Last Modified: 24/03/94 * ******************************************************** ********************************************************* * CLEAR_SCREEN * * * * Clear the logical screen * ********************************************************* clear_screen move.l log,a0 lea 32000(a0),a0 movem.l a0-a6/d0-d7,-(sp) clr.l d1 clr.l d2 clr.l d3 clr.l d4 clr.l d5 clr.l d6 clr.l d7 move.l d1,a1 move.l d1,a2 move.l d1,a3 move.l d1,a4 move.l d1,a5 move.l d1,a6 move.w #614,d0 .loop movem.l d1-d7/a1-a6,-(a0) dbra d0,.loop movem.l d1-d5,-(a0) movem.l (sp)+,a0-a6/d0-d7 rts ********************************************************* * WAIT_VBI * * * * Wait for vbi interupt * ********************************************************* wait_vbi tst.b vbi_done beq.s wait_vbi rts vbi st vbi_done rte ********************************************************* * FLIP_SCREEN * * * * Flips the logical to Physical screens * * Requires: log, phys * ********************************************************* flip_screen movem.l d0-d1,-(sp) move.l log,d0 move.l phys,d1 move.l d1,log move.l d0,phys lsr.w #8,d0 move.l d0,$ffff8200.w sf vbi_done movem.l (sp)+,d0-d1 rts ***************************************************** * INITIALISE SUBROUTINES * * * * (c) Nick Bates 1994 * * Last modified: 23/03/94 * ***************************************************** ***************************************************** * GO_SUPER * * * * Goto supervisor mode, * * - Saves old stack to old_stk * ***************************************************** go_super pea 0 move.w #$20,-(sp) trap #1 addq.l #6,sp move.l d0,old_stk save stack rts ***************************************************** * SAVE_PALETTE * * * * Saves pallete to: old_pal * ***************************************************** save_palette movem.l $fff8240,d0-d7 movem.l d0-d7,old_pal rts ***************************************************** * GET_SCREEN_ADDR * * * * Get logical screen and generates physical * * - Saves to log, phys * ***************************************************** get_screen_addr move.w #2,-(sp) trap #14 addq.l #2,sp move.l d0,phys move.l d0,old_scrn move.l #screen,d0 PHYSICAL SCREEN addi.l #256,d0 256 BYTE BOUNDARY andi.l #$ffffff00,d0 move.l d0,log rts ***************************************************** * SAVE_VBI * * * * Saves vbi to: old_vbi * ***************************************************** save_vbi move.l $70,old_vbi STORE OLD VBI move.l #vbi,$70 NEW VBI rts ***************************************************** * GO_LOW * * * * Saves current resolution to: old_res * * and change to low resolution. * ***************************************************** go_low move.b $ff8260,old_res store resolution move.b #0,$ff8260 low resolution rts ********************************************************* * SPRITE CODE - BEATING THE 16 PIXEL BOUNDARY * * * * (c) Nick Bates 1994 * * Version: 1.0 * * Last modified: 06/06/94 * * * * SET TAB TO 4 * ********************************************************* bra main include graphics.lib include init.lib include dinit.lib include sprite.lib main bsr setup bsr main_loop bsr restore clr.l -(sp) QUIT trap #1 ********* * SETUP * ********* setup bsr go_super SUPERVISOR MODE bsr save_palette STORE PALETTE bsr get_screen_addr GET PHYSICAL AND LOGICAL SCREEN ADDRESS bsr save_vbi SAVE VBI bsr go_low GO TO LOW RESOLUTION rts *********** * RESTORE * *********** restore bsr restore_screen RESTORE OLD SCREEN bsr restore_palette RESTORE OLD PALETTE bsr go_user USER MODE rts ********************* * MAIN PROGRAM LOOP * ********************* main_loop movem.l palette,d0-d7 movem.l d0-d7,$ffff8240.w CHANGE PALETTE .loop bsr wait_vbi WAIT FOR VBI bsr clear_screen CLEAR SCREEN ***************************************************************** * EXPERIMENT WITH THESE VALUES move.w #0,d0 X CO-ORDINATES move.w #0,d1 Y CO-ORDINATES move.w #0,d2 SPRITE NUMBER ****************************************************************** bsr draw_sprite_16 bsr flip_screen FLIP SCREENS cmp.b #$39,$fffffc02 TEST FOR beq .exit bra .loop .exit rts ***************************************************** sprites incbin "b:\assembly\sprite\source\pac.obj" pic dc.l 1 palette dc.w $000,$007,$005,$003,$770,$700,$060,$707 dc.w $000,$440,$500,$744,$373,$047,$505,$777 bss even old_res ds.b 1 old_pal ds.w 16 vbi_done ds.b 1 old_vbi ds.l 1 old_stk ds.l 1 old_scrn ds.l 1 log ds.l 1 phys ds.l 1 screen ds.b 32000+256 ASSEMBLY SPRITE TUTORIAL ======================== PART 2 BEATING THE 16 PIXEL BOUNDARY PRDUCED FOR: ICTARI USER GROUP (C) Nick Bates 1994 Last month, I described the theory behind beating the 16 pixel boundary and this month I have written a subroutine that demonstrates the points I made. I hope you all had your own go at doing this yourselves, as this will help you to learn the principles involved. The source included with this document includes several library files. Most of these are provided to enable the main program to run and therefore present no new items code, or certainly nothing you do not know all ready, else otherwise this tutorial is not for you. The important library is the sprite library, which contains 1 subroutine which is a routine to draw a 16x16 sprite, with masking, but without clipping. The main program calls this subroutine and passes the required values, as you can see from the example, you can pass any required values for x and y co-ordinates and any sprite number value. Remember 0 is sprite 1 and 1 is sprite 2, etc ... The PAC.OBJ file contains about 6 sprites all of which are the same size. This file was produced in much the way I explained last month, however the file does not contain the headers, and therefore cannot be loaded back into Neochrome Master. I have therefore included another file called PAC_HD.OBJ which does contain these headers. The reason I prefer to save without the headers is that in the final version of the program it's best not to include any unnecessary stuff. However I always save the file with the headers in case I need to check or edit the sprites with either Neochrome Master or Peter Hibbs own Sprite Check program (ICTARI #7). The latter is a very nice program to use to display your sprites for the first time and get an impression of what they look like on the screen without having to do any code, it is also useful to check that all sprites are of equal size. With this routine, or preferably your own version, you can now display any 16x16 sprite anywhere on the screen. The sprite will be masked with the current backgroud, try this by loading a Degas picture into the background first. The only problem with this routine is that you will get problems trying to display the sprite near the edges. You need to add some sort of clipping routine that detects for this and display only part of the sprite, i.e the part that is visible. So, your homework for this month is to have a go at loading in a background, with the sprites, try drawing your own sprites - of both the same size and perhaps bigger. Write a version of the subroutine that works for a 32x32 sprite for example. Try and make the subroutine detect if the co-ordinates are on the screen, and clip appropriately, in order to avoid a crash. If you're feeling very adventurous have a go at making the sprite move to responses from either the joystick or the mouse. The code to do this has been included in past issues of Ictari Magazines. Next Month, I shall include some source with some answers to some of the above. Until then, have fun ...... . N/.. NCOMPARE S MH 0COMPARE DOC [1;compare routine ;ENTRY d0.w=value to compare ; in-line data=no of words to test ; =first word ; =first address ; =etc ;EXIT program jumps to new address or ; continues compare movem.l a0/d1,-(sp) move.l 8(sp),a0 move (a0)+,d1 subq #1,d1 compar1 cmp (a0)+,d0 beq compar3 addq.l #4,a0 dbra d1,compar1 compar2 move.l a0,8(sp) movem.l (sp)+,a0/d1 rts compar3 move.l (a0),a0 bra compar2 SUB-ROUTINE NAME compare BRIEF DESCRIPTION Compare value in d0.W with in-line table and jump to new address if match found FILENAME COMPARE.S OTHER RESOURCES None LANGUAGE Assembler (Devpac) AUTHOR Peter Hibbs ENTRY PARAMETERS d0.W holds value to be tested. In-line data follows BSR instruction (see below) EXIT PARAMETERS Program jumps to new address if match found or next instruction if no match found No registers changed. DETAILS - This routine allows a program to jump to one of a number of different addresses in the program if the value in register d0.W matches a similar value in a look-up table. The table of values and addresses follows the BSR instruction as in-line data. For example, suppose the keyboard routine is called and returns with a key value in d0.W. The program then is required to jump to one of three different addresses if the keys A, Q or Z are pressed, i.e. labels 'address_a, address_q and address_z. If no match is found the program continues with the next instruction after the table. The in-line table consists of a 'word' which defines the number of tests to be made, the values to be tested and the addresses to jump to if a match is found. The above example would be coded as follows :- bsr keybrd fetch value into d0.W (or other code) bsr compare call 'compare' S/R dc.w 3 number of tests (3 in this case) dc.w 'A' first value to test dc.l address_a first address dc.w 'Q' second value to test dc.l address_q second address dc.w 'Z' third value to test dc.l address_z third address .. .. next instruction If no match is found the program continues with the next instruction after the end of the in-line data. This system is preferable when the program has to jump to a number of different addresses depending on the value of a register rather than a series of cmp instructions. . N4.. NCLS S 5DIALOG S Y8GEMINC S <LHEX_ASCS B#MOUSE S DHOBJCSTATS ERDR_EVNTS GVDIINC S KWINDOW S nYOW_EVENT S TXFORMATRHRD xKVXFORMATRI xKWXFORMATRPRG eXXFORMATRRSC xK^ZXFORMATRS `a***************************************** * Routine name : CLS * * Function : To clear clear the * * screen inside of a window, or to * * clear a rectangle * * ------------------------------------- * * Programmer : Martyn Armitage * * Generates : P.I.C. * * Written : 12/01/1988 * * Updated : 06/07/1989 * * 12/06/1989 * ***************************************** * clear the current window cls move.w window_handle(a6),d0 move.w #4,d1 bsr get_wind_info get window area add.w d0,d2 get x2 coord add.w d1,d3 get y2 coord lea fill_type(a6),a0 variables move.w #1,(a0)+ solid fill clr.w (a0)+ white move.w #1,(a0) replace * fill a rectangle with white * enter with x,y in d0-d1 and x2,y2 in d2-d3 fill_rect movem.w d0-d3,-(sp) save coords bsr hide_mouse bsr.s set_fill_col set colour bsr.s set_fill_type set type bsr set_char_mode set mode type movem.w (sp)+,d0-d3 get coords subq.w #1,d2 { adjust coords subq.w #1,d3 { by one pixel lea ptsin(a6),a0 ptsin array movem.w d0-d3,(a0) pass coords move.w #2,contrl+2(a6) two points clr.w contrl+4(a6) clr.w contrl+6(a6) clr.w contrl+8(a6) move.w device(a6),contrl+12(a6) vdi VR_RECFL bsr show_mouse rts * set the fill type * enter with fill type in 'FILL_TYPE' set_fill_type clr.w contrl+2(a6) clr.w contrl+4(a6) move.w #1,contrl+6(a6) move.w #1,contrl+8(a6) move.w device(a6),contrl+12(a6) move.w fill_type(a6),intin(a6) vdi VSF_INTERIOR rts * set the fill colour * enter with required colour in 'FILL_COLOUR' set_fill_col clr.w contrl+2(a6) clr.w contrl+4(a6) move.w #1,contrl+6(a6) move.w #1,contrl+8(a6) move.w device(a6),contrl+12(a6) move.w fill_colour(a6),intin(a6) vdi VSF_COLOUR move.w intout(a6),d0 get set colour rts * set the character mode set_char_mode lea contrl+2(a6),a0 clr.l (a0)+ move.l #$00010001,(a0) move.w device(a6),contrl+12(a6) move.w draw_mode(a6),intin(a6) vdi VSWR_MODE move.w intout(a6),d0 get mode set rts fill_type rs.w 1 fill type required fill_colour rs.w 1 fill colour requried draw_mode rs.w 1 drawing mode ***************************************** * Routine name : DIALOG * * Function : Display and control * * dialog boxes on the screen * * ------------------------------------- * * Programmer : Martyn Armitage * * Produces : P.I.C. * * Written : 12/12/1987 * * Updated : 12/06/1989 * ***************************************** * put a dialog box onto the screen and control the input * returns with the exit button in 'UPDATE_INDEX' * pass tree address in a0.l * pass index of editable text in d0.w * if no editable text then d0.w must hold 0 dialog_box bsr.s do_dialog do box bsr.s get_dial_action get input bsr close_dialog close box move.w update_index(a6),d0 exit button rts * put dialog box on screen * pass tree address in a0.l * pass index of editable text in d0.w * if no editable text then d0.w must hold 0 * to put an uncentred box on the screen set up x y coords in * dialog tree and dial_coords, dialog_y and call 'do_dialog1' do_dialog bsr.s dialog_centre do_dialog1 bsr.s dialog_resv move.w start_ob(a6),d0 start object move.w depth(a6),d1 depth to draw bsr.s draw_object rts * center the dialog box dialog_centre move.l a0,d_temp_address(a6) save tree addr move.w d0,edit_text_index(a6) save index move.l a0,addr_in(a6) gem FORM_CENTER movem.l int_out+2(a6),d0-d1 get coords movem.l d0-d1,dial_coords(a6) save them rts *reserve memory for dialog box dialog_resv clr.w int_in(a6) movem.l d0-d1,int_in+2(a6) pass coords movem.l d0-d1,int_in+10(a6) ditto gem FORM_DIAL rts * draw the dialog box * pass start object index in d0.w and depth (no of objects) in d1.w draw_object movem.w d0-d1,int_in(a6) start object and depth movem.l dial_coords(a6),d0-d1 get coords movem.l d0-d1,int_in+4(a6) pass them move.l d_temp_address(a6),addr_in(a6) tree address gem OBJC_DRAW rts * get user action from dialog box get_dial_action move.w edit_text_index(a6),int_in(a6) editable text move.l d_temp_address(a6),addr_in(a6) tree address gem FORM_DO move.w d0,update_index(a6) store exit button/object rts * close the dialog box close_dialog move.w update_index(a6),d0 object to update clr.w d1 normal status move.w d1,d2 no redraw bsr.s update_dialog reset exit button move.w #3,int_in(a6) release dialog memory movem.l dial_coords(a6),d0-d1 get coords movem.l d0-d1,int_in+2(a6) pass them movem.l d0-d1,int_in+10(a6) ditto gem FORM_DIAL move.l #99,start_ob(a6) reset start/depth * redraw the screen to remove dialog boxes, file selector etc * uses event_multi to remove 'redraw' screen message * all registers preserved remove_dial movem.l d0-d7/a0-a6,-(sp) save reg's bsr wait_event wait for an event bsr redraw redraw window(s) movem.l (sp)+,d0-d7/a0-a6 get reg's back remove_dial_2 rts all done * normalise the exit button reset_dial_exit move.w update_index(a6),d0 get index clr.w d1 new status (0=normal) move.w #1,d2 redraw bsr.s update_dialog update it rts * redraw the dialog box redraw_dialog bsr.s reset_dial_exit reset exit button clr.w int_in(a6) move.w #2,int_in+2(a6) movem.l dial_coords(a6),d0-d1 dialog coords movem.l d0-d1,int_in+4(a6) pass them move.l d_temp_address(a6),addr_in(a6) gem OBJC_DRAW rts * update the dialog box * pass object index in d0.w new status in d1.w no redraw/redraw in d2.w update_dialog move.w d0,int_in(a6) index of obj to change clr.w int_in+2(a6) always 0 move.w d1,int_in+12(a6) new status move.w d2,int_in+14(a6) no draw/ redraw movem.l dial_coords(a6),d0-d1 movem.l d0-d1,int_in+4(a6) move.l d_temp_address(a6),addr_in(a6) gem OBJC_CHANGE rts * an include file for inclusion when GEM calls are required * the AES function id codes APPL_INIT equ 10 APPL_READ equ 11 APPL_WRITE equ 12 APPL_FIND equ 13 APPL_TPLAY equ 14 APPL_TRECORD equ 15 APPL_EXIT equ 19 EVNT_KEYBD equ 20 EVNT_BUTTON equ 21 EVNT_MOUSE equ 22 EVNT_MESAG equ 23 EVNT_TIMER equ 24 EVNT_MULTI equ 25 EVNT_DCLICK equ 26 MENU_BAR equ 30 MENU_ICHECK equ 31 MENU_IENABLE equ 32 MENU_TNORMAL equ 33 MENU_TEXT equ 34 MENU_REGISTER equ 35 OBJC_ADD equ 40 OBJC_DELETE equ 41 OBJC_DRAW equ 42 OBJC_FIND equ 43 OBJC_OFFSET equ 44 OBJC_ORDER equ 45 OBJC_EDIT equ 46 OBJC_CHANGE equ 47 FORM_DO equ 50 FORM_DIAL equ 51 FORM_ALERT equ 52 FORM_ERROR equ 53 FORM_CENTER equ 54 GRAF_RUBBERBOX equ 70 GRAF_DRAGBOX equ 71 GRAF_MOVEBOX equ 72 GRAF_GROWBOX equ 73 GRAF_SHRINKBOX equ 74 GRAF_WATCHBOX equ 75 GRAF_SLIDEBOX equ 76 GRAF_HANDLE equ 77 GRAF_MOUSE equ 78 GRAF_MKSTATE equ 79 SCRP_READ equ 80 SCRP_WRITE equ 81 FSEL_INPUT equ 90 WIND_CREATE equ 100 WIND_OPEN equ 101 WIND_CLOSE equ 102 WIND_DELETE equ 103 WIND_GET equ 104 WIND_SET equ 105 WIND_FIND equ 106 WIND_UPDATE equ 107 WIND_CALC equ 108 RSRC_LOAD equ 110 RSRC_FREE equ 111 RSRC_GADDR equ 112 RSRC_SADDR equ 113 RSRC_OBFIX equ 114 SHEL_READ equ 120 SHEL_WRITE equ 121 SHEL_FIND equ 124 SHEL_ENVRN equ 125 * this is the list of Control parameters for the AES calls * contains control(1..3), comment is the function number * (an asterisk indicates it is not defined) gem_list dc.b 0,1,0 10 dc.b 2,1,1 11 dc.b 2,1,1 12 dc.b 0,1,1 13 dc.b 2,1,1 14 dc.b 1,1,1 15 dc.b 0,0,0 16* dc.b 0,0,0 17* dc.b 0,0,0 18* dc.b 0,1,0 19 dc.b 0,1,0 20 dc.b 3,5,0 21 dc.b 5,5,0 22 dc.b 0,1,1 23 dc.b 2,1,0 24 dc.b 16,7,1 25 dc.b 2,1,0 26 dc.b 0,0,0 27* dc.b 0,0,0 28* dc.b 0,0,0 29* dc.b 1,1,1 30 dc.b 2,1,1 31 dc.b 2,1,1 32 dc.b 2,1,1 33 dc.b 1,1,2 34 dc.b 1,1,1 35 dc.b 0,0,0 36* dc.b 0,0,0 37* dc.b 0,0,0 38* dc.b 0,0,0 39* dc.b 2,1,1 40 dc.b 1,1,1 41 dc.b 6,1,1 42 dc.b 4,1,1 43 dc.b 1,3,1 44 dc.b 2,1,1 45 dc.b 4,2,1 46 dc.b 8,1,1 47 dc.b 0,0,0 48* dc.b 0,0,0 49* dc.b 1,1,1 50 dc.b 9,1,0 51 dc.b 1,1,1 52 dc.b 1,1,0 53 dc.b 0,5,1 54 dc.b 0,0,0 55* dc.b 0,0,0 56* dc.b 0,0,0 57* dc.b 0,0,0 58* dc.b 0,0,0 59* dc.b 0,0,0 60* dc.b 0,0,0 61* dc.b 0,0,0 62* dc.b 0,0,0 63* dc.b 0,0,0 64* dc.b 0,0,0 65* dc.b 0,0,0 66* dc.b 0,0,0 67* dc.b 0,0,0 68* dc.b 0,0,0 69* dc.b 4,3,0 70 dc.b 8,3,0 71 dc.b 6,1,0 72 dc.b 8,1,0 73 dc.b 8,1,0 74 dc.b 4,1,1 75 dc.b 3,1,1 76 dc.b 0,5,0 77 dc.b 1,1,1 78 dc.b 0,5,0 79 dc.b 0,1,1 80 dc.b 0,1,1 81 dc.b 0,0,0 82* dc.b 0,0,0 83* dc.b 0,0,0 84* dc.b 0,0,0 85* dc.b 0,0,0 86* dc.b 0,0,0 87* dc.b 0,0,0 88* dc.b 0,0,0 89* dc.b 0,2,2 90 dc.b 0,0,0 91* dc.b 0,0,0 92* dc.b 0,0,0 93* dc.b 0,0,0 94* dc.b 0,0,0 95* dc.b 0,0,0 96* dc.b 0,0,0 97* dc.b 0,0,0 98* dc.b 0,0,0 99* dc.b 5,1,0 100 dc.b 5,1,0 101 dc.b 1,1,0 102 dc.b 1,1,0 103 dc.b 2,5,0 104 dc.b 6,1,0 105 dc.b 2,1,0 106 dc.b 1,1,0 107 dc.b 6,5,0 108 dc.b 0,0,0 109* dc.b 0,1,1 110 dc.b 0,1,0 111 dc.b 2,1,0 112 ** Control(4)=1 ** dc.b 2,1,1 113 dc.b 1,1,1 114 dc.b 0,0,0 115 dc.b 0,0,0 116 dc.b 0,0,0 117 dc.b 0,0,0 118 dc.b 0,0,0 119 dc.b 0,1,2 120 dc.b 3,1,2 121 dc.b 0,0,0 122* dc.b 0,0,0 123* dc.b 0,1,1 124 dc.b 0,1,3 125 ****************************** * GEM routines and constants * ****************************** * a macro to call GEM function given as a parameter gem macro moveq #\1,d0 can be Quick as all are<128 bsr call_gem endm * initialise the GEM parameter array set_gem_p lea gem_params(a6),a0 lea control(a6),a1 move.l a1,(a0)+ lea global_(a6),a1 move.l a1,(a0)+ lea int_in(a6),a1 move.l a1,(a0)+ lea int_out(a6),a1 move.l a1,(a0)+ lea addr_in(a6),a1 move.l a1,(a0)+ lea addr_out(a6),a1 move.l a1,(a0) rts * call GEM function D0.W - all elements in control[1..4] are set call_gem clr.w -(sp) last param = 0 cmp.w #RSRC_GADDR,d0 is it RSRC_GADDR bne.s call_gem1 no addq.w #1,(sp) last param = 1 call_gem1 lea gem_list(pc),a0 address of table lea control(a6),a1 control array move.w d0,(a1)+ store the op code sub.w #10,d0 subtract offset mulu #3,d0 multiply by 3 add.w d0,a0 point to the entry moveq #2,d1 init counter call_gem2 clr.b (a1)+ clear first byte move.b (a0)+,(a1)+ move a byte dbra d1,call_gem2 loop till done move.w (sp)+,(a1) pass last param lea gem_params(a6),a1 address of param array move.l a1,d1 address of param array move.w #200,d0 function number trap #2 go do it move.w int_out(a6),d0 returned value (usually) rts * this is the array of pointers to the rest of the AES arrays gem_params rs.l 1 rs.l 1 rs.l 1 rs.l 1 rs.l 1 rs.l 1 * these are the arrays for AES control rs.w 5 5 words for control array global_ rs.b 30 [ 30 bytes for global int_in rs.b 32 [ 32 bytes for intin int_out rs.w 7 14 bytes for intout addr_in rs.l 2 8 bytes for addrin addr_out rs.l 1 4 bytes for addrout * convert a long hex number to ascii string * the number must be less than 10,000,000 * if it is the number defaults to 9,999,999 lhex_asc movem.l a0-a1,-(sp) cmp.l #9999999,d0 number in range? ble.s num_ok yes move.l #9999999,d0 default num_ok lea num_buffer(a6),a0 buffer for ascii number moveq #0,d4 clear reg move.l #1000000,d1 number to divide by lea div_1(pc),a1 new divider num moveq #0,d2 clear counter num0 cmp.l d1,d0 number < divider? blo.s num1 yes addq.w #1,d2 inc counter sub.l d1,d0 subtract divider bra.s num0 loop back for more num1 tst.w d4 stored first digit? bne.s num2 yes tst.w d2 any result? beq.s num4 no moveq #1,d4 not first digit any more num2 add.b #$30,d2 convert to ascii number num3 move.b d2,(a0)+ number to string num4 jmp (a1) get new divide number div_1 move.l #100000,d1 new divider lea div_2(pc),a1 new divider routine bra.s num div_2 move.l #10000,d1 new divider lea div_3(pc),a1 new divider routine bra.s num div_3 move.l #1000,d1 new divider lea div_4(pc),a1 new routine bra.s num div_4 moveq #100,d1 new divider lea div_5(pc),a1 new routine bra.s num div_5 moveq #10,d1 new divider lea div_6(pc),a1 new routine bra.s num div_6 moveq #1,d1 new divider lea div_7(pc),a1 new routine bra.s num divu #10,d1 get new divider tst.w d1 down to zero? bne.s num no div_7 clr.b (a0) yes, null the string end movem.l (sp)+,a0-a1 rts num_buffer rs.l 3 * code to hide / unhide the mouse * using this is better than the ALINE equivalent * make the mouse an arrow arrow_mouse clr.w int_in(a6) arrow bra.s set_mouse * make the mouse a cursor cursor_mouse move.w #1,int_in(a6) cursor bra.s set_mouse * make the mouse a bee bee_mouse move.w #2,int_in(a6) bee bra.s set_mouse * make the mouse a finger finger_mouse move.w #3,int_in(a6) * set the mouse set_mouse gem GRAF_MOUSE mouse_out rts * hide the mouse hide_mouse move.w #256,int_in(a6) disable bra.s set_mouse show_mouse move.w #257,int_in(a6) enable bra.s set_mouse * test the mouse button test_m_button clr.w contrl+2(a6) move.w #1,contrl+4(a6) clr.w contrl+6(a6) move.w #1,contrl+8(a6) move.w device(a6),contrl+12(a6) vdi VQ_MOUSE move.w intout(a6),d0 get button rts ***************************************** * Routine name : OBJC_STATUS * * Function : To obtain the status * * of objects within the Resource Tree * * ------------------------------------- * * Programmer : Martyn Armitage * * Generates :P.I.C. * * Written : 01/12/1987 * * Updated : 12/06/1989 * ***************************************** * get the status of an object * pass the tree index in D0.w and the object index no in D1.w * - OR - * pass D0.w = 0 and the tree address in A0 * returns with : * the status of the object in D0.w * flags in D1.w * object list address in A0 * and ted_info / string pointer in A1 * if an error occured then D0.w = -1 ($ffff) objc_status movem.l d2-d7/a2-a6,-(sp) save reg's tst.w d0 index passed ? beq.s tree_addr_got no, address is tho find_address clr.w int_in(a6) tree structure move.w d0,int_in+2(a6) index no of tree move.w d1,-(sp) save d1 gem RSRC_GADDR go do it move.w (sp)+,d1 get d1 back tst.w d0 error ? beq.s gaddr_error yes move.l addr_out(a6),a0 get tree address tree_addr_got and.l #$ffff,d1 clear hi word beq.s gaddr_error no 0 index mulu #24,d1 get offset of object add.l d1,a0 address of object table move.w 8(a0),d1 get flags move.w 10(a0),d0 get status move.l 12(a0),a1 ted_info/string address bra.s objc_stat_out return gaddr_error move.w #-1,d0 error objc_stat_out movem.l (sp)+,d2-d7/a2-a6 get reg's back rts update_index rs.w 1 index of exit object start_ob rs.w 1 object to start drawing at depth rs.w 1 depth to draw edit_text_index rs.w 1 index of editable text dial_coords rs.w 4 coords of dialog box d_temp_address rs.l 1 temp storage for tree address * redraw the window * enter with a0 holding address of MESSAGE BUFFER redraw movem.w 6(a0),d0 get window handle cmp.w window_handle(a6),d0 my window ? beq.s re_do1 yes rts re_do1 movem.w 8(a0),d0-d3 get redraw coords movem.w d0-d3,rd_coords(a6) save them bsr hide_mouse move.w #1,int_in(a6) gem WIND_UPDATE move.w #11,int_in+2(a6) get 1st rect next_rect move.w window_handle(a6),int_in(a6) gem WIND_GET movem.w int_out+2(a6),d0-d3 get coords move.w d2,d4 copy height or.w d3,d4 or width onto height beq.s re_done no height or width present re_do2 bsr.s clip clip coords to redraw bmi.s re_do3 not in redraw bsr clipping_on turn clipping on bsr cls clear the rectangle bsr display display the rectangle bsr clipping_off turn clipping off re_do3 move.w #12,int_in+2(a6) get next rect bra.s next_rect get next rectangle * no more rectangles re_done clr.w int_in(a6) gem WIND_UPDATE end update bsr show_mouse rts * clip coords to screen * enter with:- * coords of area in window to redraw in d0-d3.w (from rectangle list) * total redraw coords in rd_coords * returns with fill area in d0-d3.w -=IF=- area is in redraw * else returns with -1 ($ffff) in d0.w * labels used: * wx, wy, wx1, wy1 >w = window * rx, ry, rx1, ry1 >r = rectangle (redraw) wx equr d0 wy equr d1 wx1 equr d2 wy1 equr d3 rx equr d4 ry equr d5 rx1 equr d6 ry1 equr d7 clip add.w d0,d2 get Wx1 coord (window) add.w d1,d3 get Wy1 coord (window) * d0-d3 are now screen coordinates of rectangle list rx, rx1, ry, ry1 movem.w rd_coords(a6),d4-d7 get redraw coords add.w d4,d6 get Rx1 coord (redraw) add.w d5,d7 get Ry1 coord (redraw) * d4-d7 are now screen coordinates of redraw area * right down to business... * using names for the registers... see the equates at the top cmp.w wx,rx rx > wx ? bhs.s clip01 yes cmp.w wx,rx1 rx1 > wx ? ble not_in_redraw no cmp.w wx1,rx1 rx1 > wx1 ? bhs.s clip02 yes move.w wx,xstart(a6) save start x co-ord move.w rx1,xend(a6) save end x co-ord bra.s clip03 clip01 cmp.w wx1,rx rx > wx1 ? bhs not_in_redraw yes cmp.w wx1,rx1 rx1 > wx1 ? bhs.s clip04 yes move.w rx,xstart(a6) save start xcoord move.w rx1,xend(a6) save end x coord bra.s clip03 clip02 move.w wx,xstart(a6) save start x co-ord move.w wx1,xend(a6) save end x co-ord bra.s clip03 clip04 move.w rx,xstart(a6) save start x co-ord move.w wx1,xend(a6) save end x co-ord * now that the x co-ords have been got lets get the y coords clip03 cmp.w wy,ry ry > wy ? bhs.s clip05 yes cmp.w wy,ry1 ry1 > wy ? ble not_in_redraw no cmp.w wy1,ry1 ry1 > wy1 ? bhs.s clip06 yes move.w wy,ystart(a6) save start y coord move.w ry1,yend(a6) save end y coord bra.s coords_got clip05 cmp.w wy1,ry ry > wy1 ? bhs.s not_in_redraw yes cmp.w wy1,ry1 ry1 > wy1 ? bhs.s clip07 yes move.w ry,ystart(a6) save start y coord move.w ry1,yend(a6) save end y coord bra.s coords_got clip06 move.w wy,ystart(a6) save start y coord move.w wy1,yend(a6) save end y coord bra.s coords_got clip07 move.w ry,ystart(a6) save start y coord move.w wy1,yend(a6) save end ycoord coords_got movem.w xstart(a6),d0-d3 get coords for fill rts not_in_redraw move.w #-1,d0 no redraw rts * turn clipping on * enter with coords to clip to in clipping_on move.w #1,intin(a6) bra.s set_clipping * turn clipping off clipping_off clr.w intin(a6) set_clipping move.l #$40000,contrl+2(a6) move.l #$10000,contrl+6(a6) lea ptsin(a6),a0 lea xstart(a6),a1 addr of coords move.l (a1)+,(a0)+ move.l (a1),(a0) vdi VS_CLIP rts clip_x rs.w 1 clip_y rs.w 1 clip_w rs.w 1 clip_h rs.w 1 rd_coords rs.w 4 total redraw coords xstart rs.w 1 x coord to redraw ystart rs.w 1 y coord to redraw xend rs.w 1 end x coord yend rs.w 1 end y coord ********************************* * VDI subroutines and constants * ********************************* * initialise the VDI parameter array set_vdi_p lea vdi_params(a6),a0 lea contrl(a6),a1 move.l a1,(a0)+ lea intin(a6),a1 move.l a1,(a0)+ lea ptsin(a6),a1 move.l a1,(a0)+ lea intout(a6),a1 move.l a1,(a0)+ lea ptsout(a6),a1 move.l a1,(a0) rts * call the vdi, with opcode in d0 * all other parameters must be set by caller call_vdi move.w d0,contrl(a6) store the op-code lea vdi_params(a6),a1 addr of parameter block move.l a1,d1 vdi parameter block move.w #115,d0 the function code trap #2 rts ************************* * VDI WORKSPACE * ************************* vdi_params rs.l 1 rs.l 1 rs.l 1 rs.l 1 rs.l 1 * now the arrays themselves contrl rs.w 20 intin rs.w 30 ptsin rs.w 30 intout rs.w 45 ptsout rs.w 12 * a macro to call a VDI function given as a parameter vdi macro move.w #\1,d0 cant be Quick as some are>127 bsr call_vdi endm * VDI function constants V_OPENWK equ 1 open workstation V_CLSWK equ 2 close workstation V_CLRWK equ 3 clear workstation V_UPDWK equ 4 update workstation V_ESCAPES equ 5 various V_PLINE equ 6 polyline V_PMARKER equ 7 polymarker V_GTEXT equ 8 text V_FILLAREA equ 9 filled area V_CALLARRAY equ 10 call array V_GDP equ 11 bar,arc,pie,circle,ellipse,round rects, etc VST_HEIGHT equ 12 set character height VST_ROTATION equ 13 set character baseline vector VS_COLOR equ 14 set colour representation VS_COLUR equ 14 ditto VSL_TYPE equ 15 set polyline type VSL_WIDTH equ 16 set polyline width VSL_COLOR equ 17 set ployline colour VSL_COLOUR equ 17 ditto VSM_TYPE equ 18 set polymarker type VSM_HEIGHT equ 19 set polymarker height VSM_COLOR equ 20 set ploymarker colour VSM_COLOUR equ 20 ditto VST_FONT equ 21 set text face VST_COLOR equ 22 set text colour VST_COLOUR equ 22 ditto VSF_INTERIOR equ 23 set fill interior style VSF_STYLE equ 24 set fill style index VSF_COLOR equ 25 set fill colour index VSF_COLOUR equ 25 ditto VQ_COLOR equ 26 inquire colour representation VQ_COLOUR equ 26 ditto VQ_CELLARRAY equ 27 inquire cell array VI_LOCATOR equ 28 input locator, request/sample VI_VALUATOR equ 29 input valuator, request/sample VI_CHOICE equ 30 input choice, request/sample VI_STRING equ 31 input string, request/sample VSWR_MODE equ 32 set writing mode VSIN_MODE equ 33 set input mode VQL_ATTRIBUTES equ 35 inquire polyline attributes VQM_ATTRIBUTES equ 36 inquire plymarker attributes VQF_ATTRIBUTES equ 37 inquire fill area attributes VQT_ATTRIBUTES equ 38 inquire graphic text VST_ALIGNMENT equ 39 set text alignment V_OPNVWK equ 100 open virtual workstation V_CLSVWK equ 101 close virtual workstation VQ_EXTND equ 102 extended inquire V_CONTOURFILL equ 103 contour fill VSF_PERIMETER equ 104 set fill perimeter V_GET_PIXEL equ 105 get pixel VST_EFFECTS equ 106 set text effects VST_POINT equ 107 set character cell height VSL_ENDS equ 108 set polyline end markers VRO_CPYFM equ 109 copy rastor VR_TRN_FM equ 110 transform form VSC_FORM equ 111 set mouse form VSF_UDPAT equ 112 set user-defined fill pattern VSL_UDSTY equ 113 user defined line pattern VR_RECFL equ 114 fill rectangle VQIN_MODE equ 115 inquire input mode VQT_EXTENT equ 116 inquire text extent VQT_WIDTH equ 117 inquire char cell width VEX_TIMV equ 118 exchange timer interrupt vector VST_LOAD_FONTS equ 119 load fonts VST_UNLOAD_FONTS equ 120 unload fonts VRT_CPYFM equ 121 copy rastor transparent V_SHOW_C equ 122 show cursor V_HIDE_C equ 123 hide cursor VQ_MOUSE equ 124 sample mouse button VEX_BUTV equ 125 exchange button change vector VEX_MOTV equ 126 exchange movement vector VEX_CURV equ 127 exchange cursor change vector VQ_KEY_S equ 128 sample keyboard state VS_CLIP equ 129 set clipping rectangle VQT_NAME equ 130 inquire face name and index VQT_FONT_INFO equ 131 inquire current face information ********************************************************* * Window creation routine * * ----------------------------------------------------- * * Programmer: Martyn Armitage * * Written : 14/08/87 * * Updated : 14/04/89 * * Previous updates : 06/04/89 * * ----------------------------------------------------- * * Pass Window_type in d0.w * * Pass address of Title in a0 * * Pass total x,y,w,h, in d1-d2.l * * If full window req then pass d1-d2.l = 0 * * Window is created and a Window_handle is returned * * in d0.w * * Window total coords are returned in d1-d2.l * * Window work coords are returned in d3-d4.l * * A call to open_wind with wi_handle in d0.w will * * put the window on the screen * ********************************************************* HSLIDE equ 2048 RTARROW equ 1024 LFARROW equ 512 VSLIDE equ 256 DNARROW equ 128 UPARROW equ 64 SIZE equ 32 INFO equ 16 MOVE equ 8 FULL equ 4 CLOSE equ 2 NAME equ 1 build_window move.l a0,title_address(a6) move.l a1,info_address(a6) move.w d0,window_type(a6) save window type movem.l d1-d2,wind_x_size(a6) save size required moveq #4,d0 d0 = wi_handle/funct id bsr get_wind movem.l d1-d2,scrn_x_coord(a6) save screen size test_w_h tst.l wind_w_size(a6) is size specified? beq.s size_got 0 = no get_size movem.l wind_x_size(a6),d1-d2 get required size size_got move.l #$00010000,d0 move.w window_type(a6),d0 d0 = calc work/wi_type bsr calc_wind movem.l d1-d2,wind_x_coord(a6) save working area moveq #0,d0 move.w window_type(a6),d0 d0 = calc total/wi_type bsr calc_wind movem.l d1-d2,wind_x_total(a6) save total window area move.w window_type(a6),d0 bsr create_wind create window bmi.s no_windows no windows left tst.l title_address(a6) address supplied ? bne.s title_got yes move.l #null_title,title_address(a6) title_got move.w d0,window_handle(a6) swap d0 move.w #2,d0 set title move.l title_address(a6),d1 get title address bsr set_wind move.w window_type(a6),d0 get type btst #4,d0 info specified ? beq.s no_info_bar no move.l info_address(a6),d0 get address bne.s info_mssg address passed move.l #null_title,info_address(a6) info_mssg move.w window_handle(a6),d0 swap d0 move.w #3,d0 set info move.l info_address(a6),d1 get info address bsr.s set_wind no_info_bar move.w window_handle(a6),d0 get window handle movem.l wind_x_total(a6),d1-d2 get window size movem.l wind_x_coord(a6),d3-d4 get work area no_windows rts return get_wind move.l d0,int_in(a6) d0 top = wind_handle gem WIND_GET d0 btm = function id movem.l int_out+2(a6),d1-d2 d1 = x/y d2 = w/h rts get_wind_info move.w d0,int_in(a6) handle move.w d1,int_in+2(a6) function gem WIND_GET movem.w int_out+2(a6),d0-d3 get coords rts calc_wind move.l d0,int_in(a6) d0 = calc_type/window_type movem.l d1-d2,int_in+4(a6) d1 = x/y d2 = w/h gem WIND_CALC movem.l int_out+2(a6),d1-d2 d1 = x/y d2 = w/h rts create_wind move.w d0,int_in(a6) d0 = window_type movem.l d1-d2,int_in+2(a6) d1 = x >,y >largest size gem WIND_CREATE d2 = w >,h >largest size rts d0.w = window_handle set_wind move.l d0,int_in(a6) d0 = wi_handle,function id move.l d1,int_in+4(a6) a0 = addrs not always req move.l d2,int_in+8(a6) d1 = not often used gem WIND_SET rts open_wind move.w d0,int_in(a6) d0 = wi_handle movem.l d1-d2,int_in+2(a6) d1 = x,y coords gem WIND_OPEN d2 = w,h of window rts close_wind move.w d0,int_in(a6) d0 = wi_handle gem WIND_CLOSE rts delete_wind move.w d0,int_in(a6) d0 = wi_handle gem WIND_DELETE rts update_wind move.w d0,int_in(a6) d0 = update type gem WIND_UPDATE rts ******************** * Window variables * ******************** window_handle rs.w 1 window_type rs.w 1 info_address rs.l 1 address of info message title_address rs.l 1 address of window title null_title rs.l 1 no title required scrn_x_coord rs.w 1 co-ords of screen scrn_y_coord rs.w 1 scrn_w_coord rs.w 1 scrn_h_coord rs.w 1 wind_x_size rs.w 1 co-ords of working area of window required wind_y_size rs.w 1 wind_w_size rs.w 1 wind_h_size rs.w 1 wind_x_coord rs.w 1 co-ords of working area of window wind_y_coord rs.w 1 wind_w_coord rs.w 1 wind_h_coord rs.w 1 wind_x_total rs.w 1 co-ords of total window size wind_y_total rs.w 1 wind_w_total rs.w 1 wind_h_total rs.w 1 MU_KEYBD equ 1 MU_BUTTON equ 2 MU_M1 equ 4 MU_M2 equ 8 MU_MESAG equ 16 MU_TIMER equ 32 wait_event lea int_in(a6),a0 int_in array lea event_type(a6),a1 address of param table move.w (a1)+,(a0)+ move.w (a1)+,(a0)+ move.w (a1)+,(a0)+ move.w (a1)+,(a0)+ move.w (a1)+,(a0)+ move.w (a1)+,(a0)+ move.w (a1)+,(a0)+ move.w (a1)+,(a0)+ move.w (a1)+,(a0)+ move.w (a1)+,(a0)+ move.w (a1)+,(a0)+ move.w (a1)+,(a0)+ move.w (a1)+,(a0)+ move.w (a1)+,(a0)+ move.w (a1)+,(a0)+ move.w (a1)+,(a0)+ move.l a1,addr_in(a6) gem EVNT_MULTI lea event_buffer(a6),a0 buffer address evnt_out rts event_type rs.w 1 messsage event mouse_clicks rs.w 1 number of clicks mouse_button rs.w 1 button to wait for m_button_status rs.w 1 button status for exit m_entry_exit1 rs.w 1 entry or exit mouse_x1 rs.w 1 mouse x coord mouse_y1 rs.w 1 mouse y coord m_rect1_width rs.w 1 width of rectangle m_rect1_height rs.w 1 height of rectangle m_entry_exit2 rs.w 1 entry or exit mouse_x2 rs.w 1 mouse x coord mouse_y2 rs.w 1 mouse y coord m_rect2_width rs.w 1 width of rectangle m_rect2_height rs.w 1 height of rectangle timer_lo rs.w 1 timer lo count timer_hi rs.w 1 timer hi count event_buffer rs.b 16 16 byte buffer for mesages Le format_dialLexit_buttonLdiskname_strLformat_buttonLdriveaLdrivebL singleL doubleLeightyLeightyoneLeightytwoLeightythreeLeightyfourLnineLtenLelevenLskew_offLskew_onLimmunise_onL immunise_offL#verify_onL$verify_offL$formatting_dialLfbarLfsliderK) format_dial EQU 0 exit_button EQU 2 diskname_str EQU 3 format_button EQU 4 drivea EQU 7 driveb EQU 8 single EQU 11 double EQU 12 eighty EQU 15 eightyone EQU 16 eightytwo EQU 17 eightythree EQU 18 eightyfour EQU 19 nine EQU 22 ten EQU 23 eleven EQU 24 skew_off EQU 27 skew_on EQU 28 immunise_on EQU 31 immunise_off EQU 32 verify_on EQU 35 verify_off EQU 36 formatting_dial EQU 1 fbar EQU 3 fslider EQU 4 `zB=(`AC( CP C C C" Nu=@(C" 0<sNBNu A:CR C\ Cz C C C NuBg|pfRWAnCR2@ rBQ2C:" 0<NB0.Nu*o,m.N - ЭЭ// Bg?<JNAO JjHzaa`aaPp at=@pMaj=@av?<NNT=@fA 0<a`f?<NNT-@p AP0Q=|dBn*=| .Bn40<dax0.4=@=@ a^0<A(0eBXQ=n40<eaHpaBg?<LNA?<NATNu-_?< NAT/.Nu-H-I=@HpaHJgL <0.aHp0.aH0.akXJf-|=@H@0<".a0.g .f-|0.H@0<".ad0.LLNu-@zphaLNu=@z=A|phaLNu-@zH~plaLNu=@zH|pdaNu-@z-A~-BpiaNu=@zH|peaNu=@zpfaNu=@zpgavNu=@zpkajNu0.2<al@AA0BX0HaVafa:aLSBSCAH=|*Bn,Bn.Bn0=n 40<rara"NuBn*Bn,=|.=|0=n 4=nP0<aDNuBn*Bn,=|.=|0=n 4=nP0<a0.NuA*B =n 4=nP0< a0.NuLngNuLHa|=|zpka\=| |=nzphaJL8Cga*kaaaa=| |`Bnzpkaa0Nu@ALDE@d@ozBd=@=F`&BdfBd=D=F`=@=B`=D=BAdAoJ@gBnz=@|?ppap2J@g ng2(0( "h `0=|aPa~afx=|aaha(fd=n=|aEJRgR=|`@:::><aF:><a:.<8g Sfa~Nu:0g:aaDNu$n~8.n0.<Na<.SF0.BGav0<><al0.><NaL0< BGaD0<><a:0<.a,0.><NaRDncxQ .><NaNuQNuJng0.nW@n0.=@nNurfrf rf2<=ANuJn^gj?.?<NAX zCp$I><g"< g Q`RQ.><W?</ ?<NAXNuA0<aNuEJn\fBRNu=|=|:>.aar:::><az:><an.<8g Sfa`,:0g :aRafRnSnfBRNuNqSnj4`0.H`B/:>.a<<a6 LxBx>JNuBFa"f <Nu=|>.:a<<0..<:af.<aSg8faBFNua|Nu:><az><QaxNuaVK:apf0<aa^Nu0.Rn @|8FNu   Nua1Ɔ`a1dž`a >8`a08@?>< Q>FNu0.`2T@ nR"nV1@3| 3||Pg3|Nu(nV Vl0<2aNuBg0.fT@?/<Hn(?<NNOA(0.fR@`@H@0.@H@|JnZg0`1|Nup><XQ2<4@0?<BgBg?<?.BHn(?< NNOJ@Nu0.R@?Hn?<6NAPA "($( aDAFCH~gSG`| SGbytes QA0<aNup?</?<?./Hn(?<NNOA(0|C"h0|g 246ga$`p?</?<?./Hn(?< NNONuNqNu/<?< NA\J@fB?< NA\-@$Nu/<?< NA\J@g /.$?< NA\Nupoa0."a0."aNu-|c4=|=|=|BnA(-H~A@-HNu[2][This program can not|operate in Low Res!| |Sorry ][ Ok ]EThere is insuffiecient memory for this application. Press any key to quitXFORMATR.RSC Disk Formatter V1.1 (C)1991 Martyn Armitage [2][There seems to be a|problem with the|Resource File.|Cant continue without it!][ Abort ][3][An error has occurred|whilst formatting the|disk!][ Ok ][3][There may be a problem with|the disk just formatted.|It is not possible to write|the diskname you specified.|The disk has not been named.][ Ok ][1][This disk has 9999999 bytes |available to the user.][ Ok ]b6bb6$6bR*ZFORMATEXITDISKNAMEEXTDISK LABEL: ________.___FFFFFFFFFFFFFORMATDRIVE:ABFORMAT:SINGLE SIDEDDOUBLE SIDEDTRACKS:8081828384SECTORS:91011SKEW:OFFONIMMUNISE:ONOFFVERIFY:ONOFFFORMATWORKING...$+,2>W krstvwxz{|      &'(34 "*6-Rdn          2Nj    .  Jf !   "#$ $"1* *F  b***************************************************************** * * * Disk Formatter, allows user to select format * * Also the disk is immunised against virus' * * ============================================================= * * * * Programmer : Martyn Armitage * * Started : 22/07/1989 * * Finished : * * Updated : * * ============================================================= * * Language : Assembler * * Assembler : Hisoft Devpac 2 * * * ***************************************************************** opt o+,p+,w- optimise,posn ind,no warnings stack_len equ 2048 stack length include xformatr.i resource file equates * the first variable, DO NOT REMOVE OR PLACE RS.x's BEFORE IT!!! first_var rs.w 1 ap_id rs.w 1 application id ghandle rs.w 1 graphics handle scr_res rs.w 1 screen resolution scrn_addr rs.l 1 address of screen device rs.w 1 device id ws_handle rs.w 1 workstation handle stack_ptr rs.l 1 temp storage for return address *--------------- program bra the_beginning branch to program start * the GEM & VDI include files include vdiinc.s include geminc.s *--------------- the_beginning move.l 4(a7),a5 get address of BASEPAGE move.l 24(a5),a6 start of BSS section move.l a6,sp copy BSS start to SP add.l 28(a5),sp add BSS len - SP points to end of BSS move.l 12(a5),d0 get length of TEXT area add.l 20(a5),d0 add length of DATA area add.l 28(a5),d0 add length of BSS area add.l #$100,d0 add length of BASE PAGE move.l d0,-(sp) length of memory to keep move.l a5,-(sp) start address of mem to keep clr.w -(sp) filler move.w #$4a,-(sp) MSHRINK trap #1 lea 12(sp),sp tst.l d0 error bpl.s memory_ok1 no pea no_mem_mssg(pc) bsr print_mssg bsr get_key bra terminate_prog quit memory_ok1 bsr set_vdi_p init vdi arrays etc bsr set_gem_p init vdi arrays etc * initialise application gem APPL_INIT get application id move.w d0,ap_id(a6) save it * get graphics handle gem GRAF_HANDLE get graphics handle move.w d0,ghandle(a6) save it bsr hide_mouse hide mouse move.w #4,-(sp) get res trap #14 addq.l #2,sp move.w d0,scr_res(a6) save screen resolution bne.s res_ok not lo res lea res_error(pc),a0 message move.w #1,d0 first button default bsr alert_box bra.s quit_program quit SECTION DATA res_error dc.b '[2][This program can not|' dc.b 'operate in Low Res!|' dc.b ' |Sorry ][ Ok ]',0 SECTION TEXT * get the address of the screen res_ok move.w #2,-(sp) Physbase trap #14 addq.l #2,sp move.l d0,scrn_addr(a6) save address * open a workstation moveq #9,d0 init counter lea intin(a6),a0 addr of array open_wkst move.w #1,(a0)+ dbra d0,open_wkst loop till done move.w #2,intin+20(a6) use raster coords clr.w contrl+2(a6) length of ptsin move.w #11,contrl+6(a6) length of intin clr.w contrl+12(a6) device number vdi V_OPNVWK open virtual workstation move.w contrl+12(a6),d0 get device handle move.w d0,ws_handle(a6) save handle move.w d0,device(a6) save device id * now run the users program bsr user_prog execute the program * now close the workstation move.w #3,d0 init counter lea contrl(a6),a0 array address move.w #101,(a0)+ opcode close_wkst clr.w (a0)+ dbra d0,close_wkst loop till done move.w ws_handle(a6),contrl+12(a6) device id vdi V_CLSVWK close it quit_program gem APPL_EXIT exit * return to the DESKTOP or calling program terminate_prog clr.w -(sp) two byte message move.w #$4c,-(sp) PTERM trap #1 return to caller * get a key press get_key move.w #7,-(sp) trap #1 addq.l #2,sp rts * print a message to screen * put message address on stack before calling print_mssg move.l (sp)+,stack_ptr(a6) save return address move.w #9,-(sp) opcode trap #1 addq.l #2,sp move.l stack_ptr(a6),-(sp) return address rts SECTION DATA no_mem_mssg dc.b 27,'EThere is insuffiecient memory',10,13 dc.b 'for this application.',10,13 dc.b 'Press any key to quit',0 even SECTION TEXT * include the library files include window.s window handling file include cls.s clear screen include rdr_evnt.s redraw code include w_event.s wait events include mouse.s mouse code include dialog.s dialog box code include objcstat.s object status code include lhex_asc.s binary to ascii * display an alert box alert_box move.w d0,int_in(a6) default button move.l a0,addr_in(a6) address of alert string gem FORM_ALERT display it rts DATA resource_name dc.b 'XFORMATR.RSC',0 even program_name dc.b ' Disk Formatter V1.1 (C)1991 Martyn Armitage ',0 even TEXT fbar_addr rs.l 1 address of object fslider_addr rs.l 1 ditto *--------------- user_prog bsr init_variables initialise preset vars * load the resource file lea resource_name(pc),a0 file name move.l a0,addr_in(a6) gem RSRC_LOAD bne.s rsc_loaded no error * error loading rsc file lea rsc_msg(pc),a0 move.w #1,d0 bsr.s alert_box rts DATA rsc_msg dc.b '[2][There seems to be a|' dc.b 'problem with the|' dc.b 'Resource File.|' dc.b 'Cant continue without it!]' dc.b '[ Abort ]',0 format_addr dc.l format_dial formatting_addr dc.l formatting_dial diskname_addr dc.l diskname_str TEXT * get the address' of the menubar and 2 dialog boxes rsc_loaded lea format_addr(pc),a5 table address moveq #1,d7 init count get_address clr.w int_in(a6) tree move.l (a5),d0 get index move.w d0,int_in+2(a6) pass index gem RSRC_GADDR get address move.l addr_out(a6),(a5)+ store address dbra d7,get_address * get the address of the diskname string move.l format_addr(pc),a0 tree address clr.w d0 address passed move.w #diskname_str,d1 index bsr objc_status get status move.l (a1),a1 get string address move.l a1,(a5) save address clr.b (a1) null the name * get the address of the bars in the formatting dialog move.l formatting_addr(pc),a0 tree address move.w #fbar,d1 object index clr.w d0 address passed bsr objc_status get status etc move.l a0,fbar_addr(a6) save address move.l formatting_addr(pc),a0 tree address move.w #fslider,d1 object index clr.w d0 address passed bsr objc_status get status etc move.l a0,fslider_addr(a6) save address move.w #NAME,d0 lea program_name(pc),a0 name of window sub.l a1,a1 no information line moveq #0,d1 full size moveq #0,d2 window please bsr build_window build it move.w d0,window_one(a6) save handle bsr open_wind open window bsr.s wait_redraw bsr arrow_mouse bsr show_mouse program_loop move.l format_addr(pc),a0 tree address move.w #diskname_str,d0 editable index bsr dialog_box do the box cmp.w #exit_button,d0 exit pressed ? beq all_done yes bsr.s get_drive get drive bsr.s get_tracks get number of tracks bsr get_sectors get number of sectors bsr get_sides get number of sides bsr get_immunise get immunise flag bsr get_verify get verify flag bsr get_name get disk name bsr get_skew get the skew flag bsr format_disk do the format bpl.s finish_format formatted ok, continue bsr arrow_mouse back to arrow bsr close_dialog close the box bra.s program_loop to the main loop finish_format bsr track_zero write boot sector etc bsr save_disk_name do the name bsr prepare_fat write the FAT to disk bsr arrow_mouse back to arrow bsr close_dialog close the dialog bsr format_complete formatting done bra.s program_loop back to main dialog * wait for a redraw event wait_redraw bsr wait_event wait for event display bsr cls clear the window rts * get the drive to format get_drive clr.w f_drive(a6) use drive A move.l format_addr(pc),a0 tree address clr.w d0 address passed move.w #drivea,d1 object index bsr objc_status get status btst #0,d0 selected ? bne.s drive_got yes move.w #1,f_drive(a6) use drive B: drive_got rts * get the number of tracks to format get_tracks move.w #80,w_tracks(a6) format 80 tracks move.w #eighty,w_object(a6) object index get_tracks_lp move.l format_addr(pc),a0 tree address clr.w d0 tree address passed move.w w_object(a6),d1 object index bsr objc_status get status btst #0,d0 selected ? bne.s tracks_got yes addq.w #1,w_object(a6) next object index addq.w #1,w_tracks(a6) inc tracks bra.s get_tracks_lp loop till found tracks_got rts * get the number of sectors to format get_sectors move.w #nine,w_object(a6) object index move.w #9,w_sectors(a6) 9 sectors get_sectors_lp move.l format_addr(pc),a0 tree address clr.w d0 tree address passed move.w w_object(a6),d1 object index bsr objc_status get status btst #0,d0 selected ? bne.s sectors_got yes addq.w #1,w_object(a6) next object addq.w #1,w_sectors(a6) inc sectors bra.s get_sectors_lp loop sectors_got move.w w_sectors(a6),d0 get sectors required rts * get the number of sides get_sides clr.w w_sides(a6) one side move.l format_addr(pc),a0 tree address clr.w d0 address passed move.w #single,d1 object index bsr objc_status get status btst #0,d0 selected ? bne.s sides_got yes move.w #1,w_sides(a6) two sides sides_got rts * get immunise get_immunise move.w #1,f_immun(a6) immunise on move.l format_addr(pc),a0 tree address clr.w d0 address passed move.w #immunise_on,d1 object index bsr objc_status get status btst #0,d0 selected ? bne.s immunise_got yes clr.w f_immun(a6) dont immunise immunise_got rts f_immun rs.w 1 immunise flag * get the verify flag get_verify move.w #1,f_verify(a6) verify on move.l format_addr(pc),a0 tree address clr.w d0 address passed move.w #verify_on,d1 object index bsr objc_status get status btst #0,d0 selected ? bne.s verify_got yes clr.w f_verify(a6) no, dont verify verify_got rts f_verify rs.w 1 verify flag * get the skew factor get_skew move.w #1,f_skew(a6) skew on move.w w_sectors(a6),d0 get sec/track addq.w #3,d0 adjust start move.w d0,skew_start(a6) start sector number move.l format_addr(pc),a0 tree address moveq #0,d0 address passed move.w #skew_on,d1 objec index bsr objc_status get status btst #0,d0 selected? bne.s skew_got yes clr.w f_skew(a6) turn off move.w #1,skew_start(a6) start sector # skew_got rts * get the disk name if present get_name clr.w f_disk_name(a6) no name yet move.l diskname_addr(pc),a0 string address tst.b (a0) string present ? beq.s name_got no move.w #1,f_disk_name(a6) name present name_got rts f_disk_name rs.w 1 disk name present w_tracks rs.w 1 w_sectors rs.w 1 number of sectors to format w_inter rs.w 1 w_sides rs.w 1 w_object rs.w 1 start_sector rs.w 1 sector # of first sector format_disk bsr init_f_dialog initialise the dialog move.l formatting_addr(pc),a0 tree address clr.w d0 no edit text bsr do_dialog display the dialog bsr bee_mouse busy bee lea gap1(a6),a0 gap size data block cmp.w #11,w_sectors(a6) eleven sectors ? blo.s format_t_disk no, init params for 9/10 * set parameters for 11 sectors gap 1 size move.w #4,(a0)+ 4 move.w #3,(a0)+ 3 move.w #22,(a0)+ 22 clr.w (a0) 0 bra.s f_params_set all set * standard TOS format 9/10 sectors gap 1 size format_t_disk move.w #60,(a0)+ 60 move.w #12,(a0)+ 12 move.w #22,(a0)+ 22 move.w #40,(a0) 40 f_params_set move.w w_sectors(a6),f_spt(a6) sectors to format moveq #0,d0 start track (1) move.w d0,f_side(a6) format side 1 move.w d0,virgin(a6) virgin data lea sector_list(a6),a0 space for bad sector list move.l a0,sector_list_a(a6) save address *--------------- * the format loop s_next_track tst.w w_sides(a6) double sided? beq.s s_s_virgin no lea new_virgin(pc),a5 return address bra.s virgin_ok for d/sided formatting * first two track of single sided disk formatted to 0's * single sided format returns to here s_s_virgin lea s_s_virgin1(pc),a5 return address s_s_virgin1 cmp.w #2,d0 track 2? blo.s virgin_ok less than, keep virgin data new_virgin move.w #$e5e5,virgin(a6) new virgin data lea virgin_ok(pc),a5 new loop address virgin_ok move.w d0,f_track(a6) track to format bsr super supervisor mode bsr set_skew set up skewing bsr format_track format the track bpl.s side_one_ok formatted ok * deal with error cmp.w #-16,d0 bad sectors ? bne.s s_format_error no bsr.s save_bad_secs save bad sectors side_one_ok move.w w_sides(a6),d0 get number of sides beq.s s_frmt_one_side single sided * format side 2 bsr set_skew set skew for side 2 move.w #1,f_side(a6) format side 2 bsr.s format_track format it bpl.s side_two_ok side 2 formatted ok * deal with error cmp.w #-16,d0 bad sectors ? bne.s s_format_error no bsr.s save_bad_secs yes, save to list side_two_ok clr.w f_side(a6) back to side 1 s_frmt_one_side bsr user user mode bsr update_f_dial update dialog move.w f_track(a6),d0 get track addq.w #1,d0 inc count cmp.w w_tracks(a6),d0 tracks done ? beq.s trks_done yes jmp (a5) no, loop trks_done move.l sector_list_a(a6),a0 list pointer move.w #-1,(a0)+ end of table moveq #0,d0 no error rts s_format_error bsr user bsr reset_drive reset drive light etc bsr arrow_mouse back to arrow bsr close_dialog close the dialog lea format_err(pc),a0 alert string move.w #1,d0 first buton bsr alert_box do box move.w #-1,d0 error rts SECTION DATA format_err dc.b '[3][An error has occurred|' dc.b 'whilst formatting the|' dc.b 'disk!][ Ok ]',0 SECTION TEXT * save the list of bad sectors save_bad_secs move.l sector_list_a(a6),a0 list pointer lea bad_sector_list(a6),a1 list for this track move.w f_side(a6),(a0)+ save side id move.w f_track(a6),(a0)+ save track id next_b_sec move.w (a1)+,(a0)+ get sector number bne.s next_b_sec loop till null found move.l a0,sector_list_a(a6) save pointer rts * FLOPFMT, FORMAT A TRACK format_track MOVEM.L D3-D7/A3-A6,reg_save(a6) save registers LEA $FFFF8606.w,A5 fdc address move.w #-1,disk_error(a6) default error move.w #1,$43E.w disable floppy vbl move.w #2,retry(a6) retry count bsr sel_drive_side select drive and side bsr set_dma set buffer address bsr hseek seek track bne floppy_fail error, not found move.w #-10,disk_error(a6) write error bsr init_buffer initialise the buffer bsr set_dma set dma address bsr.s write_track bne floppy_fail command failed * track formatted ok, so verify it move.w f_spt(a6),v_count(a6) SPT AS COUNT move.w #1,v_sector(a6) START AT SECTOR 1 bsr verify_track verify the track lea bad_sector_list(a6),a2 BAD SECTOR LIST tst.w (a2) BAD SECTOR ? beq floppy_ok NO, FLOPOK move.w #-16,disk_error(a6) BAD SECTORS bra floppy_fail FLOPFAIL ERROR *--------------- * format the track write_track move.w #$190,(a5) { clear move.w #$90,(a5) { dma move.w #$190,(a5) { status move.w #$1F,D7 SECTOR COUNT TO 31 bsr write_d7_fdc WRITE TO 1772 move.w #$180,(a5) SELECT 1772 move.w #$F0,D7 FORMAT TRACK COMMAND bsr write_d7_fdc WRITE TO 1772 MOVE.L #$40000,D7 TIME OUT COUNTER format_wait BTST #5,$FFFFFA01.w 1772 DONE ? BEQ.S read_dma_status YES SUBQ.L #1,D7 DEC TIME OUT BNE.S format_wait SOME TIME LEFT bsr reset_fdc timeout, RESET & TERMINATE format_done MOVEQ #1,D7 CLEAR Z-BIT RTS DONE read_dma_status move.w #$190,(a5) SELECT DMA STATUS move.w (a5),D0 READ STATUS BTST #0,D0 DMA ERROR ? BEQ.S format_done YES move.w #$180,(a5) SELECT 1772 STATUS REG bsr read_d0_fdc READ REGISTER bsr calc_err_num CALC ERROR NUMBER AND.B #$44,D0 TEST WRITE PROTECT, LOST DATA rts *--------------- * initialise the buffer ready for writing to the disk init_buffer move.l dma_buffer(a6),a2 track buffer move.w skew_start(a6),d4 first sector number * initialise the track data move.w gap1(a6),d0 gap length move.b #$4e,d7 value to write bsr write_to_buff to buffer move.w f_spt(a6),d6 get sector count subq.w #1,d6 adjust makt1 move.w gap2(a6),d0 length to write clr.w d7 nulls bsr.s write_to_buff to buffer move.w #3,d0 three sync bytes move.w #$f5,d7 $f5's bsr.s write_to_buff to buffer move.b #$fe,(a2)+ index address mark move.b f_track+1(a6),(a2)+ track number to buffer move.b f_side+1(a6),(a2)+ side number to buffer move.b d4,(a2)+ sector number to buffer move.b #2,(a2)+ sector size (512) move.b #$f7,(a2)+ write CRC move.w gap3(a6),d0 (22) gap size move.w #$4e,d7 value to write bsr.s write_to_buff to buffer move.w #12,d0 gap size clr.w d7 value to write bsr.s write_to_buff to buffer move.w #3,d0 3 sync bytes to write move.w #$f5,d7 value to write bsr.s write_to_buff to buffer move.b #$fb,(a2)+ data mark to buffer move.w #512,d0 count (sector length) move.b virgin(a6),d7 value to write bsr.s write_to_buff to buffer move.b #$f7,(a2)+ CRC to buffer move.w gap4(a6),d0 length of gap 4 move.w #$4e,d7 value to write bsr.s write_to_buff write to buffer * loop till all sectors written addq.w #1,d4 inc sector number cmp.w f_spt(a6),d4 used last sector number? bls.s sector_num_ok not yet moveq #1,d4 reset sector number sector_num_ok dbra d6,makt1 move.l dma_buff_end(a6),d0 calc gap 5 length sub.l a2,d0 get distance to end move.w #$4e,d7 value bsr.s write_to_buff write it rts first_sector rs.w 1 number of first sector to write *--------------- * write the byte in 'D7' to the track buffer 'D0' times write_to_buff1 move.b d7,(a2)+ write_to_buff dbra d0,write_to_buff1 rts *--------------- * set up skewing set_skew tst.w f_skew(a6) skewing? beq.s no_skewing no move.w skew_start(a6),d0 get start sector subq.w #3,d0 adjust bgt.s sec_skew_ok not -ve or 0 move.w f_spt(a6),d0 get # sectors sec_skew_ok move.w d0,skew_start(a6) save sector # no_skewing rts skew_start rs.w 1 start sector # for skewing *--------------- * CALCULATE ERROR NUMBER calc_err_num MOVEQ #-$D,D1 BTST #6,D0 BNE.S save_err_num MOVEQ #-8,D1 BTST #4,D0 BNE.S save_err_num MOVEQ #-4,D1 BTST #3,D0 BNE.S save_err_num move.w #-1,D1 save_err_num move.w D1,disk_error(a6) RTS * write the disk name to disk save_disk_name tst.w f_disk_name(a6) name present ? beq.s no_name no move.w f_drive(a6),-(sp) get drive number move.w #$e,-(sp) set it trap #1 addq.l #4,sp move.l diskname_addr(pc),a0 string address lea name_buff(a6),a1 dest addr move.l a1,a2 copy address move.w #7,d7 loop count cop_name move.b (a0)+,d0 get char beq.s end_fnd end found cmp.b #' ',d0 space ? beq.s spc_fnd1 yes move.b d0,(a1)+ copy char dbra d7,cop_name copy bra.s cop_ext spc_fnd addq.l #1,a0 spc_fnd1 dbra d7,spc_fnd cop_ext move.b #'.',(a1)+ period move.w #2,d7 cop_ext1 move.b (a0)+,(a1)+ dbeq d7,cop_ext1 end_fnd move.w #8,-(sp) disk name move.l a2,-(sp) address of filename move.w #$3c,-(sp) opcode trap #1 addq.l #8,sp tst.w d0 error bmi.s name_error yes move.w d0,-(sp) move.w #$3e,-(sp) trap #1 addq.l #4,sp rts name_buff rs.b 14 name_error lea name_err(pc),a0 move.w #1,d0 bsr alert_box no_name rts DATA name_err dc.b '[3][There may be a problem with|' dc.b 'the disk just formatted.|' dc.b 'It is not possible to write|' dc.b 'the diskname you specified.|' dc.b 'The disk has not been named.]' dc.b '[ Ok ]',0 TEXT * VERIFY DISK SECTORS verify_track lea bad_sector_list(a6),a2 baad sector list tst.w f_verify(a6) verify track ? bne.s do_verify yes clr.w (a2) no error rts do_verify move.w #-11,disk_error(a6) READ ERROR verify_sector move.w #2,retry(a6) RETRY COUNT move.w #$84,(a5) SELECT SECTOR REG move.w v_sector(a6),D7 SECTOR NUMBER bsr write_d7_fdc WRITE TO 1772 retry_s_verify bsr set_dma set dma address move.w #$90,(a5) { CLEAR move.w #$190,(a5) { DMA move.w #$90,(a5) { STATUS move.w #1,D7 SECTOR COUNT TO 1 bsr write_d7_fdc WRITE TO 1772 move.w #$80,(a5) 1772 COMMAND REG move.w #$80,D7 READ SECTOR bsr write_d7_fdc WRITE TO 1772 MOVE.L #$40000,D7 TIMEOUT COUNTER wait_sectr_read BTST #5,$FFFFFA01.w 1772 DONE ? BEQ.S sector_read_ok YES SUBQ.L #1,D7 DEC TIME OUT COUNTER BNE.S wait_sectr_read STILL SOME TIME LEFT bsr reset_fdc RESET 1772, TERMINATE BRA.S v_try_again NEXT TRY sector_read_ok move.w #$90,(a5) DMA STATUS REG move.w (a5),D0 READ IT BTST #0,D0 DMA ERROR ? BEQ.S v_try_again YES, TRY AGAIN move.w #$80,(a5) 1772 STATUS REG bsr read_d0_fdc READ IT bsr calc_err_num CALC ERROR NUMBER AND.B #$1C,D0 TEST RNF, CRC, LOST DATA BNE.S v_try_again ERROR, NEXT TRY verify_n_sect ADDQ.W #1,v_sector(a6) NEXT SECTOR SUBQ.W #1,v_count(a6) DEC SECTOR COUNT BNE.s verify_sector ANOTHER SECTOR ? CLR.W (A2) TERMINATE BAD SECTOR LIST RTS DONE v_try_again nop do_retry SUBQ.W #1,retry(a6) DEC RETRY COUNT BPL.s retry_s_verify ANOTHER TRY move.w v_sector(a6),(A2)+ SECTOR NUMBER TO SECTOR LIST BRA.S verify_n_sect NEXT SECTOR * FLOPFAIL floppy_fail move.w disk_error(a6),D0 get error number EXT.L D0 sign extend BRA.S floppy_ok1 * FLOPOK floppy_ok CLR.L D0 no error floppy_ok1 MOVE.L D0,-(sp) save error number move.w #$86,(a5) select 1772 move.w f_track(a6),D7 get track number bsr write_d7_fdc move.w #$10,D6 seek command bsr.s flop_cmds MOVE.L (sp)+,D0 get error number MOVEM.L reg_save(a6),D3-D7/A3-A6 CLR.W $43E.w release floppy vbl tst.l d0 error ? RTS * FIND TRACK ZERO seek_track_zero CLR.W D6 seek track zero command bsr.s flop_cmds write to fdc BNE.S s_t_z_error error BTST #2,D7 test track 0 bit EORI.B #4,CCR invert z-flag s_t_z_error RTS * HSEEK, FIND TRACK * find the track passed in 'F_TRACK' hseek move.w #-6,disk_error(a6) error number move.w f_track(a6),D7 track number move.w #$86,(a5) data reg bsr write_d7_fdc write d7 to fdc move.w #$10,D6 seek command * FLOPCMDS flop_cmds move.w seek_rate(a6),D0 disk seek rate AND.B #3,D0 keep bits 0-1 OR.B D0,D6 or onto command MOVE.L #$40000,D7 time out value move.w #$80,(a5) select 1772 bsr read_d0_fdc read fdc status BTST #7,D0 motor on ? BNE.S delay_ok yes MOVE.L #$60000,D7 longer delay, for motor delay_ok bsr write_d6_fdc write command cmds_wait SUBQ.L #1,D7 dec time out BEQ.S cmds_error zero reached then error BTST #5,$FFFFFA01.w fdc done ? BNE.S cmds_wait no bsr read_d7_fdc read fdc CLR.W D6 no error RTS cmds_error bsr.s reset_fdc reset fdc MOVEQ #1,D6 error RTS * RESET 1772, RESET FLOPPY CONTROLLER reset_fdc move.w #$80,(a5) move.w #$D0,D7 bsr.s write_d7_fdc move.w #$F,D7 reset_delay DBF D7,reset_delay bsr.s read_d7_fdc RTS * reset the drive and side reset_drive bsr super supervisor mode lea $ffff8606.w,A5 fdc address * wait for the motor to stop wait_motor move.w #$80,(a5) select 1772 bsr.s read_d0_fdc read fdc status BTST #7,D0 motor on ? BNE.S wait_motor yes move.w #7,d0 set bits for active low bsr.s dsel_drive_side deselect bsr user user mode rts done * SELECT DRIVE AND SIDE sel_drive_side move.w f_drive(a6),d0 get drive id ADDQ.B #1,D0 adjust number LSL.B #1,D0 move left OR.W f_side(a6),d0 include side id EORI.B #7,D0 invert bits for act_low AND.B #7,D0 keep bits 0-2 * SET PORT A, SELECT DRIVE AND SIDE dsel_drive_side MOVE SR,-(sp) ORI.W #$700,SR MOVE.B #$E,$FFFF8800.w MOVE.B $FFFF8800.w,D1 AND.B #$F8,D1 OR.B D0,D1 MOVE.B D1,$FFFF8802.w move.w (sp)+,SR RTS * set the buffer address in the dma set_dma MOVE.B dma_buffer+3(a6),$FFFF860D.w MOVE.B dma_buffer+2(a6),$FFFF860B.w MOVE.B dma_buffer+1(a6),$FFFF8609.w RTS * WRITE 'D6' TO FDC write_d6_fdc bsr.s fdc_delay move.w D6,$FFFF8604.w BRA.S fdc_delay * WRITE 'D7' TO FDC write_d7_fdc bsr.s fdc_delay move.w D7,$FFFF8604.w BRA.S fdc_delay * READ FDC TO 'D7' read_d7_fdc bsr.s fdc_delay move.w $FFFF8604.w,D7 BRA.S fdc_delay * READ FDC TO 'D0' read_d0_fdc bsr.s fdc_delay move.w $FFFF8604.w,D0 * DO A DELAY FOR THE FDC fdc_delay MOVE SR,-(sp) move.w D7,-(sp) move.w #$20,D7 fdc_delay1 DBF D7,fdc_delay1 move.w (sp)+,D7 move.w (sp)+,SR RTS * start and end address of the dma buffer (format) dma_buffer rs.l 1 dma_buff_end rs.l 1 * space for the sizes of the gaps gap1 rs.w 1 gap2 rs.w 1 gap3 rs.w 1 gap4 rs.w 1 seek_rate rs.w 1 seek rate virgin rs.w 1 virgin data for format f_drive rs.w 1 drive to format f_track rs.w 1 track to format f_side rs.w 1 side to format f_spt rs.w 1 sectors per track to format f_inter rs.w 1 interleave to use f_skew rs.w 1 skew flag v_sector rs.w 1 sector to verify v_count rs.w 1 number of sectors to verify disk_error rs.w 1 error number retry rs.w 1 retry count sector_list_a rs.l 1 address of disk list bad_sector_list rs.w 20 space for list of bad sectors reg_save rs.l 16 space for saving registers * initialise the formatting dialog init_f_dialog move.w w_tracks(a6),d0 number of tracks move.w d0,d1 copy value mulu #3,d0 three pixels per track addq.w #2,d0 one pixel border move.l fbar_addr(a6),a0 tree address move.l fslider_addr(a6),a1 tree address move.w d0,20(a0) width of bar move.w #1,20(a1) width of slider bset #7,9(a1) hide tree move.w #$11a3,14(a1) green cmp.w #80,d1 80 tracks beq.s colour_set yes move.w #$11a2,14(a1) red colour_set rts * update the formatting dialog box update_f_dial move.l fslider_addr(a6),a4 tree address bclr #7,9(a4) addq.w #3,20(a4) inc width move.w #fslider,d0 object move.w d0,d1 depth bsr draw_object draw the object rts * initialise track 0 * create a boot sector etc track_zero clr.w -(sp) not executable move.w w_sides(a6),d0 get sides formatted addq.w #2,d0 convert to disk type move.w d0,-(sp) pass disk type move.l #$1000000,-(sp) random disk number pea format_buffer(a6) buffer address move.w #18,-(sp) opcode trap #14 lea 14(sp),sp * pass number of sectors to boot sector lea format_buffer(a6),a0 buffer address move.w w_sides(a6),d0 get number of sides addq.w #1,d0 adjust side count mulu w_tracks(a6),d0 get total no. tracks mulu f_spt(a6),d0 calc total sectors move.b d0,19(a0) low byte first lsr.w #8,d0 move a byte right move.b d0,20(a0) high byte * pass number of sectors per track move.w f_spt(a6),d0 get sectors formatted move.b d0,24(a0) low byte lsr.w #8,d0 move.b d0,25(a0) high byte move.b #3,22(a0) 3 sectors per fat * immunise the disk if required tst.w f_immun(a6) immunise the disk ? beq.s dont_immun no move.w #$601c,(a0) bra.s + 30 bytes move.w #$4e75,30(a0) rts * calc magic for executing boot sector moveq #0,d0 clear counter move.w #254,d7 loop counter calc_loop add.w (a0)+,d0 dbra d7,calc_loop move.w #$1234,d1 sub.w d0,d1 move.w d1,(a0) value to add for magic * write the boot sector dont_immun move.w #1,-(sp) one sector clr.w -(sp) side 0 clr.w -(sp) track 0 move.w #1,-(sp) sector 1 move.w f_drive(a6),-(sp) drive clr.l -(sp) pea format_buffer(a6) move.w #9,-(sp) trap #14 lea 20(sp),sp tst.w d0 rts * format done display dialog box etc format_complete move.w f_drive(a6),d0 current drive addq.w #1,d0 move.w d0,-(sp) drive id pea free_buff(a6) buffer address move.w #$36,-(sp) trap #1 addq.l #8,sp lea free_buff(a6),a0 buffer address move.l (a0),d0 get free clusters move.l 8(a0),d1 get bytes per sector move.l 12(a0),d2 get sectors per cluster mulu d1,d2 calc bytes per cluster mulu d2,d0 calc bytes free bsr lhex_asc convert to ascii string lea num_buffer(a6),a0 buffer address lea bytes_free(pc),a1 dest addr moveq #8,d7 14 digits (inc BYTES ) copy_bytes_f move.b (a0)+,(a1)+ beq.s null_cpid end found subq.w #1,d7 dec counter bra.s copy_bytes_f null_cpid move.b #' ',-1(a1) conv to space subq.w #1,d7 dec counter move.b #'b',(a1)+ move.b #'y',(a1)+ move.b #'t',(a1)+ move.b #'e',(a1)+ move.b #'s',(a1)+ copy_spcs move.b #' ',(a1)+ dbra d7,copy_spcs lea disk_space(pc),a0 move.w #1,d0 bsr alert_box rts free_buff rs.b 16 DATA disk_space dc.b '[1][This disk has ' bytes_free dc.b '9999999 bytes |' dc.b 'available to the user.][ Ok ]',0 TEXT * write the FAT to the disk marking any sectors that may be bad * the FAT is always at SIDE 0, TRACK 0, SECTOR 2; ACCORDING TO THE BOOK prepare_fat moveq #0,d0 clea reg move.w #3,-(sp) 3 sectors move.l d0,-(sp) side 0 track 0 move.w #2,-(sp) sector 2 move.w f_drive(a6),-(sp) drive move.l d0,-(sp) filler pea format_buffer(a6) buffer address move.w #8,-(sp) opcode trap #14 read the fat lea 20(sp),sp lea format_buffer(a6),a0 point to buffer move.w #$f7ff,(a0) to buffer } 1st 3 bytes move.b #$ff,2(a0) to buffer } always $7FFFFF lea sector_list(a6),a1 address of bad list next_f_sec move.w (a1)+,d0 get entry cmp.w #-1,d0 last entry ? beq.s write_fat yes, all done move.w (a1)+,d1 get side number move.w (a1)+,d2 get track number get_f_sec move.w (a1)+,d3 get sector number beq.s next_f_sec null, get next entry bsr.s busy_fat_entry make this sector busy bra.s get_f_sec get next faulty sector * now write the fat back to the disk write_fat moveq #0,d0 clea reg move.w #3,-(sp) 3 sectors move.l d0,-(sp) side 0 track 0 move.w #2,-(sp) sector 2 move.w f_drive(a6),-(sp) drive move.l d0,-(sp) filler pea format_buffer(a6) buffer address move.w #9,-(sp) opcode trap #14 write the fat lea 20(sp),sp rts * make the fat entry busy * the details of the faulty sector are in: * D1 = side number (0 or 1) * D2 = track number (0 to ??) * D3 = sector number (1 to ??) * A0 points to the start of the FAT data * A1 points to the faulty sector data * A0 and A1 must be preserved busy_fat_entry nop rts * goto supervisor mode if not already in it super move.l #1,-(sp) get mode move.w #$20,-(sp) trap #1 addq.l #6,sp tst.w d0 supervisor ? bne.s super1 yes clr.l -(sp) set mode move.w #$20,-(sp) trap #1 addq.l #6,sp move.l d0,user_stack(a6) save user stack super1 rts * goto user mode if not already in it user move.l #1,-(sp) get mode move.w #$20,-(sp) trap #1 addq.l #6,sp tst.w d0 in user ? beq.s user1 yes move.l user_stack(a6),-(sp) set usermode move.w #$20,-(sp) trap #1 addq.l #6,sp user1 rts all_done gem RSRC_FREE remove the resource file move.w window_one(a6),d0 handle bsr close_wind close the window move.w window_one(a6),d0 handle bsr delete_wind delete it rts back and quit program window_one rs.w 1 handle of first window * initialise all of the required variables init_variables move.l #99,start_ob(a6) init start/depth move.w #MU_MESAG,event_type(a6) move.w #1,f_inter(a6) interleave move.w #1,seek_rate(a6) seek rate 3ms clr.w f_drive(a6) drive a lea format_buffer(a6),a0 format buffer move.l a0,dma_buffer(a6) save buffer address lea 8000(a0),a0 buffer end address move.l a0,dma_buff_end(a6) save address rts *--------------- user_stack rs.l 1 storage address of user stack format_buffer rs.w 4000 space for format buffer sector_list rs.w 2400 space for bad sector list stack_space rs.b stack_len 2k should do * the very last RS variable DO NOT REMOVE OR PLACE RS.x's AFTER IT!!! vars_end rs.w 1 SECTION BSS reserved_space ds.b vars_end-first_var SECTION TEXT . N.. NKEYTABLES +wKEYTABLEDOC R ;Keyboard definitions for event_multi call routine ;Keys a-z key_a equ $1E61 key_b equ $3062 key_c equ $2E63 key_d equ $2064 key_e equ $1265 key_f equ $2166 key_g equ $2267 key_h equ $2368 key_i equ $1769 key_j equ $246A key_k equ $256B key_l equ $266C key_m equ $326D key_n equ $316E key_o equ $186F key_p equ $1970 key_q equ $1071 key_r equ $1372 key_s equ $1F73 key_t equ $1474 key_u equ $1675 key_v equ $2F76 key_w equ $1177 key_x equ $1D78 key_y equ $1579 key_z equ $2C7A ;SHIFT+keys a-z key_A equ $1E41 key_B equ $3042 key_C equ $2E43 key_D equ $2044 key_E equ $1245 key_F equ $2146 key_G equ $2247 key_H equ $2348 key_I equ $1749 key_J equ $244A key_K equ $254B key_L equ $264C key_M equ $324D key_N equ $314E key_O equ $184F key_P equ $1950 key_Q equ $1051 key_R equ $1352 key_S equ $1F53 key_T equ $1454 key_U equ $1655 key_V equ $2F56 key_W equ $1157 key_X equ $2D58 key_Y equ $1559 key_Z equ $2C5A ;CONTROL+ keys A-Z ctrl_key_A equ $1E01 ctrl_key_B equ $3002 ctrl_key_C equ $2E03 ctrl_key_D equ $2004 ctrl_key_E equ $1205 ctrl_key_F equ $2106 ctrl_key_G equ $2207 ctrl_key_H equ $2308 ctrl_key_I equ $1709 ctrl_key_J equ $240A ctrl_key_K equ $250B ctrl_key_L equ $260C ctrl_key_M equ $320D ctrl_key_N equ $310E ctrl_key_O equ $180F ctrl_key_P equ $1910 ctrl_key_Q equ $1011 ctrl_key_R equ $1312 ctrl_key_S equ $1F13 ctrl_key_T equ $1414 ctrl_key_U equ $1615 ctrl_key_V equ $2F16 ctrl_key_W equ $1117 ctrl_key_X equ $2D18 ctrl_key_Y equ $1519 ctrl_key_Z equ $2C1A ;ALTERNATE+ keys A-Z alt_key_A equ $1E00 alt_key_B equ $3000 alt_key_C equ $2E00 alt_key_D equ $2000 alt_key_E equ $1200 alt_key_F equ $2100 alt_key_G equ $2200 alt_key_H equ $2300 alt_key_I equ $1700 alt_key_J equ $2400 alt_key_K equ $2500 alt_key_L equ $2600 alt_key_M equ $3200 alt_key_N equ $3100 alt_key_O equ $1800 alt_key_P equ $1900 alt_key_Q equ $1000 alt_key_R equ $1300 alt_key_S equ $1F00 alt_key_T equ $1400 alt_key_U equ $1600 alt_key_V equ $2F00 alt_key_W equ $1100 alt_key_X equ $2D00 alt_key_Y equ $1500 alt_key_Z equ $2C00 ;Numeric keys 1-0 (main keyboard only) key_1 equ $0231 key_2 equ $0332 key_3 equ $0433 key_4 equ $0534 key_5 equ $0635 key_6 equ $0736 key_7 equ $0837 key_8 equ $0938 key_9 equ $0a39 key_0 equ $0b30 ;SHIFT+numeric keys 1-0 (main keyboard only) shft_key_1 equ $0221 shft_key_2 equ $0340 shft_key_3 equ $0423 shft_key_4 equ $0524 shft_key_5 equ $0625 shft_key_6 equ $075e shft_key_7 equ $0826 shft_key_8 equ $092a shft_key_9 equ $0a28 shft_key_0 equ $0b29 ;CONTROL+numeric keys 1-0 (main keyboard only) ctrl_key_1 equ $0211 ctrl_key_2 equ $0300 ctrl_key_3 equ $0413 ctrl_key_4 equ $0514 ctrl_key_5 equ $0615 ctrl_key_6 equ $071e ctrl_key_7 equ $0817 ctrl_key_8 equ $0918 ctrl_key_9 equ $0a19 ctrl_key_0 equ $0b10 ;ALTERNATE+numeric keys 1-0 (main keyboard only) alt_key_1 equ $7800 alt_key_2 equ $7900 alt_key_3 equ $7a00 alt_key_4 equ $7b00 alt_key_5 equ $7c00 alt_key_6 equ $7d00 alt_key_7 equ $7e00 alt_key_8 equ $7f00 alt_key_9 equ $8000 alt_key_0 equ $8100 ;Miscellaneous keys key_help equ $6200 key_undo equ $6100 key_ins equ $5200 key_shft_ins equ $5230 key_home equ $4700 key_up equ $4800 key_down equ $5000 key_right equ $4b00 key_left equ $4d00 key_space equ $3920 key_escape equ $011b key_back equ $0e08 key_delete equ $537f key_return equ $1c0d key_tab equ $0f09 shft_home equ $4737 shft_up equ $4838 shft_down equ $5032 shft_left equ $4d36 shft_right equ $4b34 ctrl_home equ $7700 ctrl_right equ $7300 ctrl_left equ $7400 ctrl_space equ $3900 ctrl_delete equ $531f ctrl_return equ $1c0a ;Control pad keys pad_lpar equ $6328 pad_rpar equ $6429 pad_slash equ $652f pad_star equ $662a pad_minus equ $4a2d pad_plus equ $4e2b pad_. equ $712e pad_enter equ $720d pad_0 equ $7030 pad_1 equ $6d31 pad_2 equ $6e32 pad_3 equ $6f33 pad_4 equ $6a34 pad_5 equ $6b35 pad_6 equ $6c36 pad_7 equ $6737 pad_8 equ $6838 pad_9 equ $6939 ctrl_pad_lpar equ $6308 ctrl_pad_rpar equ $6409 ctrl_pad_slash equ $650f ctrl_pad_star equ $660a ctrl_pad_minus equ $4a1f ctrl_pad_plus equ $4e0b ctrl_pad_. equ $710e ctrl_pad_enter equ $720a ctrl_pad_0 equ $7010 ctrl_pad_1 equ $6d11 ctrl_pad_2 equ $6e00 ctrl_pad_3 equ $6f13 ctrl_pad_4 equ $6a14 ctrl_pad_5 equ $6b15 ctrl_pad_6 equ $6c1e ctrl_pad_7 equ $6717 ctrl_pad_8 equ $6818 ctrl_pad_9 equ $6919 ;Function keys f_key_1 equ $3b00 f_key_2 equ $3c00 f_key_3 equ $3d00 f_key_4 equ $3e00 f_key_5 equ $3f00 f_key_6 equ $4000 f_key_7 equ $4100 f_key_8 equ $4200 f_key_9 equ $4300 f_key_10 equ $4400 shft_f_key_1 equ $5400 shft_f_key_2 equ $5500 shft_f_key_3 equ $5600 shft_f_key_4 equ $5700 shft_f_key_5 equ $5800 shft_f_key_6 equ $5900 shft_f_key_7 equ $5a00 shft_f_key_8 equ $5b00 shft_f_key_9 equ $5c00 shft_f_key_10 equ $5d00  Tx l B T9x l   KEYBOARD DEFINITIONS ==================== by Peter Hibbs Usually in GEM type programs (i.e. ones that use the menu bar) there are keyboard equivalents of most of the drop down menu commands. For example ALT L to load a file, ALT Q to quit the program and so on. The normal way to access the keyboard is via the evnt_multi GEM function which will detect a keypress and return with the key value in a variable. This code consists of the key value in the low 8 bits and the scan code in the high 8 bits which gives a unique value for every key on the keyboard, the user program would then check these values and jump to the required code depending on which key was pressed. To make the program easier to understand these key codes should be defined as equates so that symbols represent the key functions, i.e. use the symbol 'key_a' rather than the value $1E61. The following tables show the symbols that I use and correspond to the 'equate' file KEYTABLE.S on this disk. If you don't like the key names I have used, you can of course change them but don't forget to use exactly the same name in both this file and the KEYTABLE.S file. If you do change the names, bear in mind that you will need to use names that you are not likely to use in a program as labels or you will get assembler 'multiple label' errors. To use the codes just 'include' the KEYTABLE.S file in your program and then use the key symbols within the program source code, see example below. Print this document and keep it in your programming reference folder. This file does not include ALL the keys available on the keyboard, the punctuation marks have been omitted as I find they are not often used with evnt_multi so you will need to add those if you need them. Note also that the TOS BIOS calls to the keyboard return a longword value with the key code in the low 8 bits of the low word and the scan code in the low 8 bits of the high word so that if you want to use these definitions for BIOS calls you will need to copy the high word data down to the top half of the low word before calling the 'compare' routine. A typical example could be as follows (using the 'compare' routine elsewhere on this disk :- include KEYTABLE.S program code .. .. code to fetch keypress into d0 bsr compare dc.w 5 dc.w alt_key_L load file dc.l load_file dc.w alt_key_S save file dc.l save_file dc.w alt_key_D delete file dc.l del_file dc.w ctrl_key_N new file dc.l new_file dc.w key_help help option dc.l show_help .. Keyboard definitions for event_multi call function Keys a-z SHIFT+keys A-Z CTRL+keys A-Z ALT+keys A-Z key_a key_A ctrl_key_A alt_key_A key_b key_B ctrl_key_B alt_key_B key_c key_C ctrl_key_C alt_key_C key_d key_D ctrl_key_D alt_key_D key_e key_E ctrl_key_E alt_key_E key_f key_F ctrl_key_F alt_key_F key_g key_G ctrl_key_G alt_key_G key_h key_H ctrl_key_H alt_key_H key_i key_I ctrl_key_I alt_key_I key_j key_J ctrl_key_J alt_key_J key_k key_K ctrl_key_K alt_key_K key_l key_L ctrl_key_L alt_key_L key_m key_M ctrl_key_M alt_key_M key_n key_N ctrl_key_N alt_key_N key_o key_O ctrl_key_O alt_key_O key_p key_P ctrl_key_P alt_key_P key_q key_Q ctrl_key_Q alt_key_Q key_r key_R ctrl_key_R alt_key_R key_s key_S ctrl_key_S alt_key_S key_t key_T ctrl_key_T alt_key_T key_u key_U ctrl_key_U alt_key_U key_v key_V ctrl_key_V alt_key_V key_w key_W ctrl_key_W alt_key_W key_x key_X ctrl_key_X alt_key_X key_y key_Y ctrl_key_Y alt_key_Y key_z key_Z ctrl_key_Z alt_key_Z Numeric keys 1-0 SHIFT+numeric keys 1-0 CONTROL+numeric keys 1-0 (main keyboard only) (main keyboard only) (main keyboard only) key_1 shft_key_1 ctrl_key_1 key_2 shft_key_2 ctrl_key_2 key_3 shft_key_3 ctrl_key_3 key_4 shft_key_4 ctrl_key_4 key_5 shft_key_5 ctrl_key_5 key_6 shft_key_6 ctrl_key_6 key_7 shft_key_7 ctrl_key_7 key_8 shft_key_8 ctrl_key_8 key_9 shft_key_9 ctrl_key_9 key_0 shft_key_0 ctrl_key_0 ALTERNATE+numeric keys 1-0 Miscellaneous keys Function keys (main keyboard only) key_help f_key_1 alt_key_1 key_undo f_key_2 alt_key_2 key_ins f_key_3 alt_key_3 key_shft_ins f_key_4 alt_key_4 key_home f_key_5 alt_key_5 key_up f_key_6 alt_key_6 key_down f_key_7 alt_key_7 key_right f_key_8 alt_key_8 key_left f_key_9 alt_key_9 key_space f_key_10 alt_key_0 key_escape key_back Control pad keys Miscellaneous keys Shift+Function keys pad_lpar key_delete shft_f_key_1 pad_rpar key_return shft_f_key_2 pad_slash key_tab shft_f_key_3 pad_star shft_f_key_4 pad_minus shft_home shft_f_key_5 pad_plus shft_up shft_f_key_6 pad_. shft_down shft_f_key_7 pad_enter shft_left shft_f_key_8 pad_0 shft_right shft_f_key_9 pad_1 shft_f_key_10 pad_2 ctrl_home pad_3 ctrl_right pad_4 ctrl_left pad_5 ctrl_space pad_6 ctrl_delete pad_7 ctrl_return pad_8 pad_9 ctrl_pad_lpar ctrl_pad_rpar ctrl_pad_slash ctrl_pad_star ctrl_pad_minus ctrl_pad_plus ctrl_pad_. ctrl_pad_enter ctrl_pad_0 ctrl_pad_1 ctrl_pad_2 ctrl_pad_3 ctrl_pad_4 ctrl_pad_5 ctrl_pad_6 ctrl_pad_7 ctrl_pad_8 ctrl_pad_9 @ @ @ @ @ @@@0  (< @$ @$ @ @ @( 0 @@@ . N.. STE_FIX PRG 3``:` f`dJxfA`A P=f" hmBCzp f8QP`, P?f J9g##/|vByN"m y #f EgQ`R( yNJDESKTOP.INF&o k  Ј<.@// ?<?<JNAO aBg/<?<1NAJ/ / B@rC02 x$f*`0 _INFf2` _MCHf fpRPH$fJ@f2`p$x )g2`\o _INF!|PHBpЁ!@`: xC!` $HPH&IPI&& f"_INF#|PIB#|(&_$_NuA8NA NZ090g A#NH090D@HA pN0A+N&090gNAp!N#rNu?<NA/?< NA\ONu/ /??<NMPO @$_Nu/ /?<&NN\O$_NuDESKTOP.INF patch installedalready installedthis machine is not an STEthis STE ROM version does not need the patch ERROR: . mytrap1main_StkSizeerrno0Pterm0dmsgCconwsjstartt1savercookie_jvalidate:SetexcvSupexecMADMAClongframjmp_abs_NFopen=opcodeFO_filenFO_modeFread?FR_handlFR_countFR_bufstartupsuptrp gheadplstkchkfnckreadDdeskinftstb4gotopennoreadjreadbufsaveretmungeitvxmunggetbytnxbytgoteresendTpaStartTpaEndTextSegSTextSegS DataSegSDataSegSBssSegStBssSegSiDtaPtr PntPrcPt$Reserved(EnvStrPt,Reserved0CurDrv7Reserved8CmdLineBasePage> h""   < @A    @A  !. N.. GEM_TUT 003ODIALOGS  OGRAFIX O. O.. NFIGURE1 IMG \l FIGURE2 IMG FIGURE3 IMG FIGURE4 IMG  LESSON3 TXT CzReLESN3REFTXT ur 6tt d @)  @x !@ @  @* @ !@A?>0>A?0* @13a 33033a00 !@03q 33033q00* @03y 33033y00 !@03} >303?}>0* @03_ 330>3_00 !@03O 33003O00* @13G 33003G00 !@C 3?03C??* @  @* @  @* @ !@ _  @8  !j UUWUUUUUUUUUUUUUUUUUx j  UUV UUUUUUUUUUUUUUUUUx j  UUV UUUUUUUUUUUUUUUUUx  j UUVUUUUUUUUUUUUUUUUUx !j !UUVUUUUUUUUUUUUUUUUUx !j !UUVUUUUUUUUUUUUUUUUUx !j !UUVUUUUUUUUUUUUUUUUUx !j UUVUUUUUUUUUUUUUUUUUx j UUVUUUUUUUUUUUUUUUUUx j  UUV UUUUUUUUUUUUUUUUUx j UUUUUUUUUUUUUUUUUUUUx j !UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUx !j/Wx?l?Tx l Tx l Tx l  Tx l B T9x l  T x sl  @Tx !l Tx l Tx l Tx l Tx/l?Tl0`TxplpTxplpTxp|lpDTxpGop >UUUUUUUUUUUUUUUUUp"33 332"UT33 338UUUUUUUUUUUUUUUUUp"33 33"UT33 33UUUUUUUUUUUUUUUUUp"33 33&"UT> 3UUUUUUUUUUUUUUUUUp0UT0UUUUUUUUUUUUUUUUUp0UT UUUUUUUUUUUUUUUUUp UWUUUUUUUUUUUUUUUUUpUWUUUUUUUUUUUUUUUUUp""UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUpppp p!@pspppppppppppߜppppppppDEppDEppDEppDEppDEppDEppDEppDEppDEppDEp`p<DEpp<DEp`pDEpߜpDEppDEppDEpppppppsp@!p ppp"UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUp; the system send you one or more messages. The big if-then-else loop is actually just processing messages. Unfortunately, there are an awful lot of possible messages you can get. First of all, there are the messages sent by other applications. We saw those last time. The next group we will look at are window messages.ttd) @ @ @ @ @  @@@ @ @ @ @ @ @ @ @@@  @ @ @ @ @  @@@ @ @ @ @ @ @ @ @@@  @ @ @ @ @  @@@ @ @ @ @ @ @ @ @@@  @ @ @ @ @  @@@ @ @ @ @ @ @ @ @@@  @ @ @ @ @  @@@ @ @ @ @ @ @ @ @@@ ` @ @ @ @ @  @@@  @ @ @ @ @ @ @@@0  (< @$ @$ @ @ @( 0 @@@ @ @ @ @ @  2 of point. There are various messages you might receive, depending on how you have set up the window. I shall detail each one, with what you should do and the part of the window you must have made 'active', (the actual format of evnt_mesag is in the reference for this month) 1) WM_SIZED (sizer box). Use wind_set to actually set the window's new size. Then use wind_get to get the new working size, set the sliders to their new values (a bit later..) and redraw the window. 2) WM_MOVED (title bar). Use wind_set to set the new sizes. 3) WM_FULLED (fuller). If the window is not 'fulled', record the current window size, then set the window to the maximum size allowed and redraw. It the window was previously 'fulled', recall the previous coordinates and set the winttz*    @@    @@     ! @A    @A  !    @@    @@     ! @A    @A  !    @@    @@     ! @A    @A  !    @@    @@     ! @A    @A  !    @@    @@     ! @A    @A  !    @@    @@     ! @A    @A  !    @@    @@     ! @A    @A  !    @@    @@     ! @A    @A  !    @@    @@     ! @A    @A  !     @@    @@  @ x  ! @A x @  @A  !    @@    @@   0ultitask, won't multitask' errrr sorry.) So, if your program allows for DA's (i.e. it has a menu with spaces for them) you have to assume that at some time one of them is going to be opened over your program. So, we shall look at the WM_REDRAW message in detail. All system generated messages are th GEM PROGRAMMING by Jonathan White ARTICLE III WINDOWS. Before we get into the article proper, I will pass on a bit of news I heard today on the Internet. There is a second edition of the Atari Compendium coming out soon. Not only will it fix all the errr typographical undisclosed features (errors) in the first ed. It will also include details on some things left out of the first. Plus it will have a better cover (my first ed is already looking somewhat distressed. The book world has a term for it - badgered. I think mine is more sort of 'rabid enraged polar beared'..). Also, wonder of wonders, it's going to be bound so it will lie flat on the desk. So if you were thinking of buying it, wait a bit to see if the second ed comes available. Also, I have just had a chance to look at the book 'Modern Atari System Software' by Hisoft. If you already have a set of GEM reference manuals - say the Compute! ones.. a) Why are you reading these articles?? b) It's a cheaper way to get new info than the AC. Your references won't be as integrated as the AC, but it'll save you 20 quid.. In the third of the series, we look at how to use windows - how to create them, how to limit graphics to within them, and how to process user changes to them. Thus we shall have our first introduction to GEM events and messages on the way. Before we actually look at windows, a point about using them at startup. If a program starts with no command line, do you display a window or not. Most Macintosh applications, if started without a file being passed to them open a blank window to start a new document into. Some do not. The Atari interface guidelines give you two alternatives. One, do as a Macintosh and open a blank window with the name 'untitled'. Two, start with a dialogue box giving the user the option to load a file (using the file selector) or open a new document. Personally, I prefer this way. There are few things as infuriating as watching an application open a blank window, knowing full well the first thing you are going to do is close it again. 1) Creating Windows. Creating windows is pretty simple in itself, but it does require a bit of preparation. The call to create a window is, unsurprisingly, wind_create(), which takes several parameters, and returns the handle for the window. All functions which affect the window identify it by this handle. It is the window's ID. The parameters passed to the function define the maximum size the window can be set to by the user. Finding these limits if the first bit of preparation we must do. The maximum size the window can be isn't usually the size of the display, as passed back when the initialisation functions were called. It is actually that minus the size of the menu bar. But to save you the effort, there is a useful command called wind_get() which can give you all sorts of information. One of the parameters it can take is a flag, and if that flag has a value of WF_WORKXYWH, when the window you are examining has the number 0 (the desktop has the handle 0), it will return X,Y width and height of the desktop. Therefore, if the four numbers returned are x,y,w and h, the maximum size a window can be is these numbers too. Since they are passed and returned as pointers, all you have to do is use the same variables in both calls. For once GEM helps us along. The other thing you must pass to wind_create is what parts of the window you will display. You can have scrollbars (or not), close boxes (or not). Anything from a full GEM window, to a window which has no identifying objects at all, and is therefore just a frame. As it is, the objects defined also define what messages the program must process. You will never receive a 'window resized' message if the window doesn't have a sizer attached to it. Most GEM compilers define the set of objects in one of the include files. Therefore, to set the object, you logically AND these pre-defined names into a variable passed to the function. For example, a window to display messages in might have a close box (to remove it) and a title bar (to move it), but not a sizer box. So, you define the 'parts' variable to equal NAME | CLOSER. Once you have used wind_create(), and got your window handle, you can actually display it. If you have given the window a title bar or an info line, you have to set the text in these before you open the window. You do this with wind_set(). This function has other uses (such as setting the size and position of the scroll bars) but it can also set these text strings. Once you have done these, you can display the window with wind_open(). This sets the initial size of the window. You can set it to the maximum size if you wish, or to a standard size. The appropriate size depends on the exact function of your program. You can then go on to fill it. Obviously, a window can have ANYTHING in it. To go into all the possibilities here would take too long and would be too much of a digression (like digressing isn't something I do enough. Damn I did it again..). But, all graphic operations (that includes text printing, when done in a GEM window) must be limited to the windows 'working area'. What's the point of having windows if programs splatter their output around willy nilly? The first thing we must do is find out the windows working area. The function to do this is one we have already come across, wind_get(). If you pass that function the WF_WORKXYWH flag with your windows handle, it will return the x,y w and h of the windows work area - the window not including any scroll bars, gadgets and the title / info lines. If you pass the flag as WF_CURRXYWH, it will return the full size of the window. Alternatively, you can use the function wind_calc() to convert between work area and full area. The functions wind_set() and wind_get() are used frequently when dealing with windows, and we shall come across other functions they serve soon. So, you now have the co-ordinates of your work area. The next step is to pass these co-ordinates to the VDI (the GEM output manager) to restrict output to our window - a process known as 'clipping'. Here we come across a small problem. While the AES prefers to define windows in terms of start corner, width and height, the VDI prefers to have them as top left and bottom right corners. Why this is I can't possibly imagine, aside from the usual reason (Atari messed up) but there you go. The VDI rectangle form actually has an official name - it's called a GRECT - and usually has a structure definition somewhere in the include files if you care to use it. Converting from AES to VDI is not a problem (x1=x, y1=y, x2=(x1+w-1), y2=(y1+h-1)), but if you don't remember to do it, your program will fail, and will probably crash. Anyway, the call to clip your graphics output is, logically, called vs_clip(), and takes the VDI-form rectangle as a parameter, along with the VDI handle (NOT the window handle). Then, you can go on to draw your graphics or text. It is, usually, wise to put this re- drawing routine in a procedure or function, and pass the coordinates to re-draw into and the window handle as parameters, as this means you can use the same routine to re-draw parts of the window later on. If fact, the most elegant system I saw presumed all graphics were as a result of a 'please redraw your window' message. The program I saw first displayed it's graphics by sending the application itself a redraw message which is a useful idea I shall detail in a sec. And talking of messages.. 2) Handling Windows (or, messages part 1) The system communicates what is happening to the user via messages. Every time the user performs an action - picking an item from the menu, moving a window etc. etc - its called an event. Each event makes the system send you one or more messages. The big if-then-else loop is actually just processing messages. Unfortunately, there are an awful lot of possible messages you can get. First of all, there are the messages sent by other applications. We saw those last time. The next group we will look at are window messages. You check for messages via one of several calls. The most general one is the infamous evnt_multi(), which basically informs you if ANYTHING happens - keypresses, menu selections, mouse clicks, messages etc etc etc- all in the one call. That's the one you would use for most FULL GEM programs. AS we are only looking at window messages (right now) we can restrict ourselves to the more simple evnt_mesag() function (no, I don't know why its spelt that way..). Before we look at it, I'd just like to talk about multitasking again. In the first part, I spoke about how, under certain circumstances, the system leaves your program and goes off to give other programs a go (cooperative multitasking, as used by the Geneva system). It is the case that evnt_calls are actually when it does this. Until the event you wish to look out for happens, your program sits and waits. Thus if you wish your program to be multi-tasking friendly, you should put an evnt_call in every long processing job, even if you don't actually wish to know what's going on. Pre-emptive multitasking environments (MultiTOS, Mag!x ) don't need this courtesy, but since this method allows all multitasking systems to work, it's best to use it. The standard call to use is evnt_timer, which causes your program to wait a certain number of milliseconds. Seeing as how Atari have never actually guaranteed its accuracy to any degree, the call isn't a lot of use for its stated function. However, if you call an evnt_timer() with a time of 0, it allows multitasking to continue. The evnt_mesag() function waits for messages to come down the 'pipe' to your program. They can be system messages, messages from other apps, or even from your own program - sent using appl_write with your own app_id. Thus, you can send yourself a window redraw message whenever you wish. You could also send yourself any other message, but since the event they are attached to hasn't happened, there isn't a lot of point. There are various messages you might receive, depending on how you have set up the window. I shall detail each one, with what you should do and the part of the window you must have made 'active', (the actual format of evnt_mesag is in the reference for this month) 1) WM_SIZED (sizer box). Use wind_set to actually set the window's new size. Then use wind_get to get the new working size, set the sliders to their new values (a bit later..) and redraw the window. 2) WM_MOVED (title bar). Use wind_set to set the new sizes. 3) WM_FULLED (fuller). If the window is not 'fulled', record the current window size, then set the window to the maximum size allowed and redraw. It the window was previously 'fulled', recall the previous coordinates and set the window to these, then redraw. 4) WM_CLOSED (closer). Use wind_delete() to remove the window from the screen. You could also incorporate a routine to query this if the window contents haven't been saved. 5) WM_ARROWED (scroll bars and arrows). This message can mean several things. Firstly, it can mean the user has clicked on one of the scroll bar arrows. If so, move the 'window contents' one system characters width up, down, left or right (that's actually just a rough rule I use, you can actually use any distance you like) for graphic images or one line up/down or one character left/right for text. If the user has clicked in the free space near the bar, move the screen one screen MINUS ONE LINE (according to the Atari guidelines) in the relevant direction for text images, or (the working area - some small amount) for graphic images. Obviously, a screen redraw is required and you should also set the window scrollbars as appropriate. 6) WM_HSLID (horizontal slider). This passes back a number between 0 and 1000. This number defines how far to the right the scroll bar has been placed IN IT'S MOVEMENT RANGE (which is actually window width -(scroll bar width+arrows width+sizer width). Basically 0=start of document, 1000=end of document and ranges in between are calculated depending upon the form your window is displaying. Then, redraw the screen. 7) WM_VSLID (vertical slider). As previous, except in a different direction. There are also various messages you will only receive if you are dealing with AES 4.0+ systems, i.e. multitasking systems. They basically tell you if something done to some other window belonging to another application has had some effect on your windows. Most of these follow a logical pattern, and they are in fact pretty easy to deal with. Details of these are in both the new reference books. The last, and most important message you can receive when dealing with windows is the WM_REDRAW message. Your application will process this message many times when it is run, so it is vital that it is as bug- free and robust as possible. Please note that it is possible you will need to redraw your window contents even if you have hard coded in that you only will have one window open and you are running under a single tasking OS. Why? Desk Accessories. They can open windows too (Hey, a slogan.. 'Da's are programs too'. 'I am not a DA, I am a proper program', 'Can't multitask, won't multitask' errrr sorry.) So, if your program allows for DA's (i.e. it has a menu with spaces for them) you have to assume that at some time one of them is going to be opened over your program. So, we shall look at the WM_REDRAW message in detail. All system generated messages are the same size, 16 bytes or eight WORDS. evnt_mesag returns a pointer to the message buffer. If you expect to get messages from apps, 16 bytes might not be the right length. That's why I suggested if you are going to use messages for interprocess communication, you keep them to 16 bytes too, to keep things simple. This structure is defined as follows.. message[0]=message type (WM_REDRAW should be defined in one of your include files, you can use that for an 'if') message[1]= the ap_id of the sending application (for above you can ignore this) message[2]= the length of the message over 16 bytes (in this case, 0) message[3]= the window handle which needs to be redrawn message[4]= x co-ordinate of dirtied triangle message[5]= y " " " message[6]= width of " " message[7]= height of " " So, in theory, all you need to do is get the coordinates, and pass those co-ordinates on to your screen redrawing routine. Lovely. Unfortunately ( you knew I was gonna say that didn't you..) things can get a little more complicated than that. It is entirely possible that you will get a redraw message, yet your active window will be partially obscured. How is this? Just to use an example, suppose a DA ("free rights for.. " Oh Shut up!) in a window is moved across the surface of your active window. E,g, If you have a DA being opened across your window like this.. and the user moves it like this... then the part that had been dirtied is this... but you can't just redraw the whole window because some of the space is being used by the desk accessory, like this.. In actual fact, part of the dirtied rectangle might even be under the DA, so you can't really assume anything about the rectangle to redraw. GEM actually gives us the answer. The function wind_get() (said we'd see that one again) has a couple of pre-defined values it can look at. What the GEM system does is divide up your window into visible rectangles, which GEM is sure aren't obscured. Basically, GEM takes the visible section (or sections) of your window and divides it into the minimum number of rectangles that will cover it. Like those puzzles you did when you were a kid, when you got six weird shapes and you had to fit them together to make a square.. What this does is give us a method to systematically check the damaged rectangle against each of the visible rectangles. If you spot the area each visible rectangle overlaps into the dirtied rectangle, and redraw that bit, then by the end of the visible rectangle list, you should have correctly redrawn your window.. Next, we'll present the algorithm to do this in detail. Seriously folks, if you can do this bit, and the bit later on in the series where we look at GEM dialog box trees, you have GEM sussed. So here comes one of the more difficult bits.. 3) Redrawing your Window (in 7 easy steps..) Right, there is a fairly well defined process for redrawing a GEM window, and it goes something like this... 1) Get your damaged rectangle. This is sent to you in the window redraw message. 2) Use wind_get with a flag parameter of WF_FIRSTXYWH. This gives you the size of the first rectangle in your 'visible rectangle' list. 3) If the width and height is 0, you have reached the end of the list and the redraw is complete. 4) If width or height of the list window is not 0, you have to calculate the overlap between the two, and redraw this overlap. The overlap is calculated by the following rules... If the damaged rectangle is x1,y1,w1,h1 and the visible rectangle is x2,y2,w2,h2 and the rectangle to redraw is x3,y3,w3,h3 then :- x3= the bigger of x1 and x2 y3= the bigger of y1 and y2 w3= (the bigger of (x1+w1) and (x2+w2)) - x3 h3= (the bigger of (y1+h1) and (y2+h2)) - y3 Note that, if you have Lattice C, there is a function called rc_intersect which will give you the overlap. It's actually supposed to be used for drawing dialog boxes, but what the hell... 5) If w3 and h3 are both greater than zero, you have a window to redraw. The process for doing this is as follows.. a) call graf_mouse(M_OFF,OxOL) to freeze the mouse b) call wind_update(BEG_UPDATE) to freeze the screen while you redraw. c) call vs_clip to limit your drawing to the damage rectangle d) redraw the rectangle e) call wind_update(END_UPDATE) to release the screen f) call graf_mouse(M_ON, 0x0L) to set the mouse free 6) Get the next visible rectangle, using WF_NEXTXYWH to get the next rectangle in the list 7) Go back to step 3. And so on until you exit on step 3. You can, of course, put most of this in a C function call. I actually use two standard ones. The first one, redraw_wind() gets the window handle and the damaged rectangle passed to it, and it does the overlap checking. If it finds it needs to redraw, it calls a function named draw_rect, again passing the window handle and the rectangle to be redrawn. Thus, I can use this function over and over again just by changing draw_rect to draw the appropriate thing.. That's almost Object-Orientated Programming!! (it's as close as I'll ever get..). Note that, if you are REALLY clever, you might include a check about redoing the scrollbars in here too. And right on cue.. 4) Windows Scrollbars.. One of the best parts of GEM is the fact that it has proportional scrollbars. These show you not only where you are in the document, and also how much of the document you can see. In fact, they are such a good idea that Microsoft (spit!!) has put them in windows 4 / Chicago. Ten years behind as usual. Just as an aside, not only does Windows 3.1 not have these type scrollbars, the little buttons it uses instead are called 'thumbs'. So if you use windows, you actually do spend a lot of your time twiddling your thumbs.. But if you use windows, you spend a lot of your time doing that anyway :-)... Anyway. Having these things is very useful, but it does mean you have to keep an eye on them. Whenever the user puts in some more data, resizes the window or clicks on the scrollbars / arrows etc you have to redraw them. This is done via the getting-to-be-overexposed wind_set call. Figuring out what to tell it is a two step thing. First of all, you have to figure out how big they should be. GEM rates them proportionally to your window,and uses an arbitrary measure that the range is from 0 (nonexistent) to 1000 (the full length / width - the size of the arrows). So you don't have to figure it out for yourself in pixels, just as a percentage. Obviously, if you have less data than the window size, it's the full 1000. If you are showing 50% of the data, it's 500 etc etc. It's actually considered proper to have a minimum of 2-3%, so the user has something to drag.. Actually, there is a simple formula to get the size.. size = 1000 * (amount seen / total amount). Position is a little more tricky. Mainly because the 0-1000 range doesn't define the full width the scroll bar can go (i.e. the size of the window - (the size of the arrows+ any gadgets)). Instead, the 0- 1000 covers the possible movement range of the top of the scrollbar. Since your scrollbar has a finite width, the top line can never get to the bottom. An example will make things easier. Say you have a 100 line document, and you are currently showing 20 lines of it. The scrollbar therefore takes up 20% of space. So, our 0- 1000 range is actually only 0-800. But we give the number still in 0- 1000 units. You see? No? The 0-1000 is the whole bar, but the range of movement is 0-800. therefore, if you want the bar to start at 48% of the way through, your bar is actually placed at.. 1000*48/(100-20) or 600 - 60% of the way down. It also means that, even if you go right to the bottom of the file, your slider edge will only be 80% of the way down the bar. This gives us a general formula for the start of the scrollbar.. position = 1000* Start point / (total length - length shown) Therefore, to redraw the scroll bar you have 4 steps.. 1) Calculate the total size of the file in that direction - pixels, lines, characters.. 2) Calculate the amount of the image shown - in the same units 3) Apply the above formulae to find the parameters 4) Call wind_set to set the scrollbars. 5) Window Cleanups. That's just about all. OK, so I haven't told you how to PUT anything in then yet, but that's coming soon (well, as soon as someone takes my shiny new Jaguar away..). All that's left is how to remove the window, and that's pretty simple, in fact it's two calls, wind_close() and wind_delete(). Wind_close removes the window from the screen (and will probably send you a redraw message if you have other windows) and then you use wind_delete to tell the system you've finished with it, so the handle can be used by another window. That's all for now. Next time we'll go over how to use a GEM menu. That'll be pretty straightforward after this. GEM PROGRAMMING by Jomathan White ARTICLE III REFERENCE 1) Creating Windows WORD wind_create(kind,x,y,w,h) WORD kind,x,y,w,h This function creates (but does not display) a GEM window. x,y,w and h are the maximum size the window can be set to. kind is a set of bit flags which define the 'widgets' (official term folks) that the window possesses, as follows (these can be ANDed by standard name) Bit Name Function 0 NAME Window has a title bar, and a text title 1 CLOSER Window has a close box, and is therefore closeable 2 FULLER Window has a 'full' box, and can be maximised 3 MOVER Window can be moved if it has a title bar 4 INFO Window has a text info line 5 SIZER Window has a sizing dragbox, and is sizable 6 UPARROW Window has an up arrow 7 DNARROW Window has a down arrow 8 VSLIDE Window has a vertical slidebar / scrollbar 9 LFARROW Window has a 'move left' arrow 10 RTARROW Window has a 'move right' arrow 11 HSLIDE Window has a horizontal slidebar / scrollbar Returns the window handle if successful, or -(a number) if no handle was available. TOS V1.0 and 1.01 had a limit of four windows. TOS 1.04 took this up to 7. Later versions are limited only by memory. Word wind_set(handle,mode,par1,par2,par3,par4) WORD handle,mode,par1,par2,par3,par4 Sets various parameters for GEM windows. Handle is the handle of the window you wish to alter. Par1 to par4 depend upon the value of mode, as follows.. (note, for brevity I have not included parameters for versions of TOS not available to the general public) Mode Function WF_NAME Sets the text in the title bar of the window. Par1 contains the high WORD of the pointer to the string, and Par2 contains the low word. WF_INFO Sets the text in the window info-line. Par1 and Par2 contain the pointer to the string as above. WF_CURRXYWH Sets the actual size of the window. Par1 to par4 contain the x,y,w and h of the new setting, e.g size including window widgets. WF_HSLIDE Sets the position of the horizontal slider. Par1 contains the position between 1 and 1000. 1 is leftmost WF_VSLIDE Sets the position of the vertical slider. Par1 contains the position between 1 and 1000. 1 is at the top. WF_HSLSIZE Sets the width of the horizontal slider relative to the whole width of the scrollbar. Par1 contains the value.1000 is the full width. WF_VSLSIZE As above, but for the vertical slide bar. WORD wind_get(handle, mode, par1, par2, par3, par4) WORD handle, mode WORD *par1, *par2, *par3, *par4 NOTE: I am not going to give the FULL definition of wind_get here, as it has a wide range of possible functions. I will list all that I have used, plus the other major ones. The more obscure ones can be found in any good GEM reference. Handle is the handle of the window about which info is required. Par1 to par4 are the variables which contain the information after the call is made. the information returned is defined by mode, as shown below.. Mode Function WF_ WORKXYWH Returns the area of the window minus any windows widgets, i.e. the blank part. Par1 - par4 contain the x,y,w and h of this area. WF_CURRXYWH Returns the actual size of the window, including all window gadgets. WF_PREVXYWH Returns the 'fulled' size of the window prior to the last wind_set call. WF_FULLXYWH Returns the values for the maximum possible size of the window, as set by wind_create(). WF_HSLIDE Returns the current position of the horizontal slidebar, in the usual 1-1000 range, in par1. WF_VSLIDE As above, but for the vertical slidebar. WF_TOP Par1 is filled with the handle of the currently active window. WF_FIRSTXYWH Par1 to par4 contain the x,y,w and h of the first visible rectangle in the windows area. If w and h both = 0, the window is completely covered. WF_NEXTXYWH as above, but each time it is called it is for a subsequent rectangle, When w and h both = 0, the end of the list has been reached. WF_HSLSIZE Returns the size of the horizontal slidebar in par1 (1-1000) WF_VSLSIZE As above for the vertical slider. This function returns 0 if an error occurs. WORD wind_open(handle, x, y, w, h) WORD handle, x, y, w, h Displays the window specified by handle on the screen, with a TOTAL size (i.e. with widgets) defined by x,y,w and h. This will usually also trigger a WM_REDRAW message of the working area of the window. Returns a 0 if an error occurs. WORD wind_calc (form, mode, x1, y1, w1, h1, x2, y2, w2, h2) WORD form. mode, x1, y1, w1, h1, x2 WORD *x2, *y2, *w2, *h2 This function converts between full window coordinates (window including widgets) and working area coordinates (just the bit you want to draw on). You place the set of data you have in x1 to h1, and the other set is returned in x2 to h2. mode is the set of widgets the window has (as wind_create above). If form equals WC_BORDER, the system presumes you are passing whole window coordinates, and passes back the smaller work area coords. If form equals WC_WORK, the opposite is presumed. VOID vs_clip(handle, flag, pxy) WORD handle, flag WORD *pxy Sets the global clipping rectangle for VDI graphics functions. Handle is the workstation handle. Flag = 0 for clipping off, or 1 for clipping on. If on, *pxy should point to a GRECT defining the clipping rectangle. If flag =0, *pxy should be NULL. 2) Handling Windows WORD evnt_mesag(msg) WORD *msg This function waits until a message is passed to your program by the system. Msg points to this message structure of at least 16 bytes where the message should be placed. (All system messages will fit in 16 bytes). msg[0] contains the message type (see below) - usually defined constants msg[1] contains the ap_id of the sending application msg[2] contains the size of the message over 16 bytes (you need to use appl_read to get the rest of the message) Further values of msg[] array parts are defined by the message type.. Type Function MN_SELECTED A menu item has been selected. Msg[3] holds the menu title object number, and msg[4] contains the item object no. WM_REDRAW A portion of the screen needs to be redrawn. msg[4-7] contain the AES rectangle coordinates of the corrupted area. WM_CLOSED The user has clicked on the close box of the window whose handle is in msg[3]. WM_FULLED The user has clicked on the full box for the window whose handle is in msg[3]. If not fulled, the window should be fulled. If it is already fulled, it should be returned to its previous size. WM_ARROWED The user has clicked on one of the window contents movement areas. A row/column change is sent when the arrows are clicked. A page message is sent when the area around the slider bar is clicked. The handle of the window is in msg[3], and the contents of msg[4] define what has been clicked. 0 page up 1 page down 2 line up 3 line down 4 page left 5 page right 6 column left 7 column right WM_HSLID The user has dragged the horizontal slider. the window handle is in msg[3], and the new position (1-1000) is in msg[4]. WM_VSLID The user has dragged the vertical slider. the window handle is in msg[3], and the new position (1-1000) is in msg[4]. WM_SIZED The user has re-sized the window. Msg[3] contains the handle of the window. Msg[4-7]contain the new size of the window. WM_MOVED The user has dragged the window. Msg[3] contains the window handle, and msg[4-7] contains the new window size and location. NOTE: WM_SIZED and WM_MOVED can usually share the same code. There are actually many other messages, some to do with new AES functions not in generally available versions of TOS, or for MiNT processes, etc.. As I am not covering these areas, I have not included these messages. If you are using MiNT / MTOS / AES 4.0+, you can examine the extra messages in the Atari Compendium or the Modern Atari Systems Software book from Hisoft. Evnt_mesag always returns 1, according to Atari. If it returns anything else for you, complain to them, not me. WORD evnt_timer(lotime,Hitime) WORD Lotime, Hitime This stops your program for a specific number of milliseconds. Lotime and Hitime are the upper and lower words (respectively) of a 32-bit integer that defines how long to wait. Note that Atari have never guaranteed that this time is accurate, only that the wait time will be at least that long (fat lot of good that is..). The main use for this function is with both variables set to 0, to allow multitasking to continue by releasing the system. Once one round of other apps has been performed, control is returned to your program. This function also always returns 1. 3) Redrawing Your Window WORD graf_mouse(mode, form) WORD mode VOIDP form This function controls the shape and function of the mouse pointer, as follows.. Mode Function ARROW Change to default arrow TEXT_CSR Change to I-bar BUSY_BEE Change to bee POINT_HAND Change to pointing hand FLAT_HAND Change to open hand THIN_CROSS Change to one pixel width (of lines) cross THICK_CROSS Change to 3 pixel width (of lines) cross OUTLN_CROSS Change to outline of THICK_CROSS USER_DEF Change to user defined form as pointed to by form (see below) M_OFF Remove the mouse cursor from the screen M_ON Put the mouse back on the screen FORM is a structure containing the custom mouse form, and is defined as follows.. (for other MODEs, FORM is null) typedef struct { short mf_xhot; /* x posn of hotspot in 16*16 grid */ short mf_yhot; /* y posn of hotspot in 16*16 grid */ short mf_nplanes; /* no. of col planes (1 only ) */ short mf_fg; /* foreground colour */ short mf_bg; /*background colour */ short mf_mask[16]; /* 16 bytes mask data */ short mf_data[16]; /* 16 bytes form data */ }MFORM; WORD wind_update(flag) WORD flag Locks the screen while you redraw a window. No dialog boxes will pop up and no menu item can be activated. This way, you know that no other area will be corrupted while you are redrawing the screen. The function is defined by the value of flag, Flag Function BEG_UPDATE Notify AES you are beginning a redraw, and freezes the screen END_UPDATE Frees the screen BEG_MCTRL prevents the mouse being accessed by processes other than yours END_MCTRL Gives the mouse back to the system 5) Window Cleanups WORD wind_close(handle) WORD handle This function removes the window associated with the value of handle from the screen. Note all the relevant data structures are not cleared, and wind_set and wind_get will still work, though they will occasionally give odd results.. WORD wind_delete(handle) WORD handle This function actually erases the window associated with handle from the system, and frees the value of handle to be re-used (not necessarily by your application). QA43Ea*HaL L@E`G,y"y`C Nq-0@64 GcGR beNu fraT@(Q`" f ra|T@` rap@ BQeNuIG@,KBGBCBD|BE4Pf"<2tQPQ<<żGg pFvk>CREyeRF Ff$y(yg.t2&4&0&v@xlSDzm(>G5xEQfIG@,KBCBD|BE4Pf"<2tQPQ<<żGg pFvk>CRE E eRF Ff$y(yfNut2&4&0&v@xlSDzm((EQfNuNq-H@-.  O.. NDIALOG TXT I **************************************************************** * J a m e s H T a y l o r 12 West Drive, Cleadon, * * Sunderland, Tyne & Wear, UK, SR6 7SJ Tel: 091 536 2165 * **************************************************************** Below are a few C functions I use a lot which may be of some interest to other members. They are concerned with Dialog box handling and button setting/resetting and tedinfo strings. /*- * myform.h header file */ #define MOUSE_ON graf_mouse(M_ON,NULL) #define MOUSE_OFF graf_mouse(M_OFF,NULL) MFDB sMFDB = {0L,640,400,40,1,1,0,0,0}; MFDB dMFDB = {0L,640,400,40,1,1,0,0,0}; MFDB iMFDB = {0L,640,400,40,1,1,0,0,0}; short v_handle; /* The VDI handle */ int handle_dialog(OBJECT *dlog,int editnum); int doform_noctr(OBJECT *dlog, int editnum); /* Dialog box handler. */ int handle_dialog(OBJECT *dlog,int editnum) { short x,y,w,h; short pxyarray[8]; int but; MOUSE_OFF; form_center(dlog,&x,&y,&w,&h); pxyarray[0] = x;pxyarray[1] = y; pxyarray[2] = x+w;pxyarray[3] = y+h; pxyarray[4] = x;pxyarray[5] = y; pxyarray[6] = x+w;pxyarray[7] = y+h; vro_cpyfm(v_handle,3,pxyarray,&sMFDB,&dMFDB); form_dial(FMD_START,0,0,0,0,x,y,w,h); form_dial(FMD_GROW,x+w/2,y+h/2,0,0,x,y,w,h); objc_draw(dlog,0,10,x,y,w,h); MOUSE_ON; but=form_do(dlog,editnum); MOUSE_OFF; form_dial(FMD_SHRINK,x+w/2,y+h/2,0,0,x,y,w,h); form_dial(FMD_FINISH,0,0,0,0,x,y,w,h); vro_cpyfm(v_handle,3,pxyarray,&dMFDB,&sMFDB); MOUSE_ON; /* De-select exit button */ dlog[but].ob_state&=~SELECTED; return but; } /* Dialog box handler. Does not centre the dialog or draw expanding gizmos. */ int doform_noctr(OBJECT *dlog,int editnum) { short x,y,w,h; short pxyarray[8]; int but; MOUSE_OFF; x = pxyarray[0] = dlog[0].ob_x; y = pxyarray[1] = dlog[0].ob_y; w = dlog[0].ob_width;pxyarray[2] = x+w; h = dlog[0].ob_height;pxyarray[3] = y+h; pxyarray[4] = 0;pxyarray[5] = 0; pxyarray[6] = w;pxyarray[7] = h; /* Save screen area */ vro_cpyfm(v_handle,3,pxyarray,&sMFDB,&iMFDB); /* Draw the dialog box */ objc_draw(dlog,0,10,x,y,w,h); MOUSE_ON; but=form_do(dlog,editnum); MOUSE_OFF; /* Replace screen area */ pxyarray[0] = 0; pxyarray[1] = 0; pxyarray[2] = w; pxyarray[3] = h; pxyarray[4] = x; pxyarray[5] = y; pxyarray[6] = x+w;pxyarray[7] = y+h; vro_cpyfm(v_handle,3,pxyarray,&iMFDB,&sMFDB); MOUSE_ON; /* de-select exit button */ dlog[but].ob_state&=~SELECTED; return but; } /* * copy a string into a TEDINFO structure. */ void set_tedinfo(OBJECT *tree,int obj,char *source) { char *dest; dest=((TEDINFO *)tree[obj].ob_spec)->te_ptext; strcpy(dest,source); } /* * copy the string from a TEDINFO into another string */ void get_tedinfo(OBJECT *tree, int obj, char *dest) { char *source; /* Extract address */ source=((TEDINFO *)tree[obj].ob_spec)->te_ptext; strcpy(dest,source); } /* Set a radio button */ void set_rbut(OBJECT *tree,int parent,int button) { int b; for (b=tree[parent].ob_head; b!=parent; b=tree[b].ob_next) if (b==button) tree[b].ob_state |= SELECTED; else tree[b].ob_state &= ~SELECTED; } /* Set/reset a dialog button */ void set_but(OBJECT *tree,int button,int mode) { tree[button].ob_state=mode; } /* Set/reset a dialog button, Usage: set_obstat(dlog,index,DISABLED,0); (enable object) Notes: SELECTED 0 CROSSED 1 CHECKED 2 DISABLED 3 mode: 0=reset bit, 1=set bit OUTLINED 4 SHADOWED 5 */ void set_obstat(OBJECT *tree, int index, int bit_mask, int mode) { if(mode == 0) tree[index].ob_state &= ~bit_mask; else tree[index].ob_state |= bit_mask; } /* Return the state of an object. index = index of object. bit_mask = mask of bits to be tested (see above Notes.) Usage: ret_obstat(dlog,index,SELECTED); (enable object) */ int ret_obstat(OBJECT *tree, int index, int bit_mask) { return tree[index].ob_state && bit_mask; } /* Return a dialog button state. */ int ret_sb(OBJECT *tree,int button) { return tree[button].ob_state; } /* Return the button set in a group of radio buttons. Note: only one button will be set. parent = index of the parent object. */ int ret_srb(OBJECT *tree,int parent) { int b; b=tree[parent].ob_head; for (; b!=parent && !(tree[b].ob_state&SELECTED); b=tree[b].ob_next) ; return b; } /* Returns set buttons (not radio) in a group, as a bit pattern. Note: The last button must not be the last object in the tree. */ int ret_buts(OBJECT *tree,int parent) { int b, bits; float e; bits = 0; b=tree[parent].ob_head; for (; b<=tree[parent].ob_tail; b=tree[b].ob_next) { if(tree[b].ob_state&SELECTED) { e = b-parent-1; bits |= (int)(pow2(e)); } } return bits; } /* Set buttons (max 32) from an integer bit pattern. NB: last button must not be the last object in the tree. */ void set_buts(OBJECT *tree,int patt,int parent) { int b, bit; float bt; b=tree[parent].ob_head; for (bt=0;b<=tree[parent].ob_tail;b=tree[b].ob_next,bt++) { bit = (int)(pow2(bt)); if(patt & bit) { tree[b].ob_state |= SELECTED; } else { tree[b].ob_state &= ~SELECTED; } } } ------------------------ end of file ------------------------------i'I%ϕd+ɮݵU~J>w[vH8oJէKӢ^t }+jM\5r17ُ̗YkV/}F.#/)`+kCƘi#ܩc3|Ѽ1(Z+UN;OZm8 OArmKLi4s#ohlDX\;g#b宯mKGb[ҳu{ҭQ{Ҧ=?kj+_kϻ&ȭJ͸N?0dǎ5sme@,+4!e]ȼR~?6?(mf%EG$Vh/,.LA$N1Nt4Pr{$] R+'QK8"o݈qBc4_a\BbvH⒖[9DXLMvwF=8o6xNS:'+kʚ)NʚbeͣqCƖkD5AKV`1*|N Z@ZIP!NV/HxHyN YN |" ae zb_ YfHxHyN |``BHyN B."N^NuNVH xGItCzJ1 f |``Cz 1\ ftCzE$$$$$$$$$$$$$$$$$$$$4B3 C/ N UHxPHS?<N J_f,fUHxPHSN J_lB.`RBCzJ1 ft|LN^NuE*Gzz EfaHx;HyN "m0")"m0ҩ+A "m0+i" x"c+|x"Y(m0","ҭ //-"/ Encrypted file not supported Error writing Error while extracting (disk full ?) CRC error Unsupported compression method Press Return. _/HO>N _///O.NHT _" "_x$HBJgSf)f&)f)f f( SSf.LTN _0g HT$_"_S@QLTNPNN NA=@ LN^ _TNNVH``/./. ?.?<@NA-@LN^ _O NNVH``/.?<ANA=@LN^ _PNNVH``/.?<HNA-@ LN^ _XNNVH``?./. ?<NNA=@LN^ _O NNVH``?.?. /. ?<WNALN^ _PNNUNV2J@gA??<LNA o"h ($I!Sf+H0 ( ШШ"h$) Ђ"҈.A//??<JNAO +@,#aBNAN vH~E#*yBG<9F(yQJ9f.raraJ@g. @gh @gp`a B@FL~ _>NJGgRBGt-JTv-KTFCCgp`SBNqSFfaQ`tAp2<Qp 2<oQp2<Qp2<QAp2<Q3 H aL0EG,y"y`Hra@<raR@:ra8VDpABQAClra2QHIG,KBGBCBD|BE4Pf"<2tQPQ<<żGg pFvk>CRE EfRF FfEIt042v@xlSDzm((EQfL MIEA0<BQApBQA43Ea*HaL L@E`G,y"y`C Nq-0@64 GcGR beNu fraT@(Q`" f ra|T@` rap@ BQeNuIG@,KBGBCBD|BE4Pf"<2tQPQ<<żGg pFvk>CREyeRF Ff$y(yg.t2&4&0&v@xlSDzm(>G5xEQfIG@,KBCBD|BE4Pf"<2tQPQ<<żGg pFvk>CRE E eRF Ff$y(yfNut2&4&0&v@xlSDzm((EQfNuNq-H@-06Ѐ01 Gb GcGR`GT @l SFfa` @g @b4B`4@4-0BC3 Cr0 GcGRB43 <@-HA-2 y0 y0A Gb GcGR`GT-H@-0BC3Cr0 Gc GT` GcGRA23v@Fea< LBSBQ`-H@-0AAr GcGRNuH&y, gZ K0S@*9MrAA"6Q#/ /?9?<@NAg LO?pX` 0< L(yQ<9FLO?Nu  #+3;CScs !1Aa  0@`?     NLApBr4Bf `f J Bf R@ @fNPK4w;\hGRAFIX11/BGIDEMO/BGIDEMO.PRG XW.(,( B̗J BhclEPV bMaJq*@0tLdzcialqldf*cv qcrmHY4;z2]/,1&ؼbҼ:ۋ]V3u Kl%6Uj}ʒ_,y3F^iS~&2%iQY\;s7u\t+rS{SP.YY]{1KG)-t9UXCXrSʙYq&3KipثV)Atncnj`RP pnb̉Wf]h9W2S ,hPY,LtyIvxLg_UYqMo:W;7n1ւ-cHo"0f<:f؜[u^mKԱu, p7WXڮ:ec%cu: x6MֱO8E~\(h_g yK 7At&ϳ^c>-At oa ܟ'8ϐF0/aW1uE R'+1]"qyy[K>cuOx3x:NO-xH_;p!rvjB(_c90y"oݧT#D b|P1P<nnn 010MrOzcn4SYe< @2Zz (/Ώ7|W(Xҫav_2&tTQg 0RX1?#58)b #W/n u)p¼U j^>?" Cs <Ёg@*/!O㕎S!g(q#CWQAV3F JtP#(b5u=t"ٮVHPқ˄Kc7'To T#ppxVW `g켳o+\!Ef(!,͹tt ^򯺓oƓcP&srھZ%>YMȔ9q)xL)g5Fj`Ʈ4Ny6H% b/֌N䚅+?A}X۫U8=/:^J !ՙDBK g߃7]!KXuZ:=WLKf{ Va0}I)5'xa2n ,^Az-eKx dȑINx }Sd>#H4cA >p1mڧ% ~пPAԕSρU'2>Q>/V6S1OR,bKa(E)gŴT] SoH \呐Gmd+Cn*FCtȕ5s8\CN!Q-SzG ȥ\Hy@xZ,ڮkpyl'~ ~%>튨" PH 0 қ$P sYv_jrA jK {bx2f-NaaSlMB`Q Y:|B$IR~n!$fSj,V/ɤ&M|^`GmK2s/)$q.L,c xIBDy xCD \c( R+ (/dv㎖y%kma:.9Z.2H-I{)<_paH%OK5xRmBy; GAO#mn(+k1Y>Mt@M1YI&bt3Ϭ I\fQ1OYۑe㰘&1OF 'Je~)뗨2ZI"u岍/Wђv5eqwP?LEV=cEkhcTDǝ}4 E!tNjmYIg1)Wn&C$sgU=5D(d=wg$]D룜j%BtwI"ݠ9Bc͛$"4gr*9)jѨW魯5ȡO9!]N4~NGsw<\RE%=F)1J'SOTƔkؼ99uE:4AX9pg^V-֭59/#"w$9D>-kZ_^|nNK>Ѳr'%z5CЅ.P[D98 k8Zdx$2/=!Az+P8 u)cHӤk6I?4{s14=|L{1Șk_ɰ<5&.^#79L2% JH|V[K>b>G3[c Hp@ `f p@c)((q6@sHc9G;7)|8?uC)"S?robHv<֑8 y~j$QS=IH! 6q:Qz> 4cS_"M٘o&S%t |N$,1i `)@ (Ou&o}XΕ:fȴzGF6nbMX&:LlӨyt }pj;*CDDG,w$aRy =!aZqd3Q;;؆1:eAF.8苾H}iTbBPA_(CWN T@S0d>H3.Pl*q5Ru,}ʼtKQԱ^lѠ؎6qx4zBF=iEQLJZcJ;((\;s>c'7[jϐ(6e#/Fx7 \/zྵ'kd-#We-g3c }`JL 09=C *,3Č6{Dl:٢7<?)tOsQ4W*T*S-*Q^Cύ=1qW4%nMCqmQ+>+ ī0 ipx^E6@va8oc38*z rUvSҕk"D{ԓ{% yX# s& kfHH80@% |Rg/ Kc!*r@ w հ-'XkជsGuR>IY!)05pz /RVb I9Wbt^\@bJs@Eo}h60zg_-DGd*": 9P!( %i0#()qzl/Y.^_c39 @nI8Bͩ&+?گ&̵ߑ8-͙7FxY|TM Y|d-TnK2)tԗ4\`\;ds.BVRXuL}OK/io4=ĶYJs(֣# C(mWmYKuj4R:z?N"[w;fǼ:k;u d;-UC/~W%Ձ%#~nX9X`omQ Q]pأ [?o)Al/ ^ǥ|! UPMQaخIjVmƸ Ybt?[M=I1pė Z=Qyq |EToZ"=2-, ;mͣvpmtǡЯт(oIx&q+>8;U Q^#s{67K4IwUxs$X5vu`l_q?ɑ;lcͿ ;o+Y5BUNDV$xHlF@GHr ̂ngEl fvp{]UcZW~ZEyc15A>f<#j.tAW%pkpmu Rq AqMhgW@[2< P f^EuRTK<:.h]83Wq? ^nְK3xV94eFVDޣF~MQ^_3? &R>6 5C$y^'ɑ3vcXLjR~)<3%N+VlY}|< @돬c[zd`;Z=\[~#A^4,kA|`a"&̞H8WS4eIŊG6zZ9b-sw|7vWH R|.ӠTT\zEHZEp*!onGEMDx5#Aݨh F?"8!Yq|ɥ2hlrC#XD!愷G{4bB""ʥ;soi#b+"NksDָ" Kk6Dmabч$O{ź(Jsqc2F װ!tzkI0Zr?&)\OњP'#P 6x̰Xi1{r^H`u͹{9f Z5 : im={ ƊԟmQlas  +!ϝ>IB[GJ#tP+<'v%5k9ϊX 4 U@^] i0ޠ9>{QV)isR*F̥ '|}e~ƶ<9Bv5(kΒkS&c?J?#ί-`d9%.D)'9Ͼ5hε0]j~IT4"hM+;ֻMNGz`St\o!ۤmN[*"T\ue}H}; . BȆ}IILQ7еL'$K;$hws$iN;[R$f$1H毦؈[+%vg}+V sXN=iTۏ }Nz26MvtcstT'RjI.]^3exBH!ZaA >Q7H^z޾EĜ|6`ɜIj$xp~8 /&NGl8Ʈ)2&EsӡM,s\kr\9QnHq<=ڗXIs$PR #wӷ:h}Zg߷aug+`\#Mvަ9٨ RMb?/F/KT f"x&rJhĉ;W^Ku@=V5V_~Rj2XLjV!SY,a`SkO3.~}觝yXWRY϶-D!_Gķ?.7*18B yeT,6f3aКMh_2`E P]_1l_z)#tjȿx"؊n_?Ý'p4 .xo<\W-x\~ o} G9wS/g֡)pY)p=Np8wPi@qNS#?cHǨJ-*r;P~/_A(ֻoDHږB2"\92|R>j)VA[5]'Yy';zcjw So #fn~}7t$30gT~&gwbj.W)_ ͵EdWf D()]MA?yO+ 7V(8!xVKEi Qb_3X m?:iE.3뱋0Ffh`tFTQE6 o3K47M8Gyx4/6w4ZK _T}Iomk^e6-̰nJ'i'I%ϕd+ɮݵU~J>w[vH8oJէKӢ^t }+jM\5r17ُ̗YkV/}F.#/)`+kCƘi#ܩc3|Ѽ1(Z+UN;OZm8 OArmKLi 8?scrӊ͡Bl2P?T^/eˌyh@/6S6M!B HOXkSv2'(kB(I"kIO\n@ :]RME =hJ:yKeQ51N>W`O΍UT"pojA[k,ZY!Ⱥ F @;^_1bZ VYb[jhuyY`AyוcpG" VG?WTy_7)wF-B4-Kqv"=uF&x̗9LV *.~Ck^58 أJI:-AÌS)Lsifߊ^Qxhs !ZY3t߇FhbJ14 xL#s>*W=|^N3YJ(j \k \h ,.+k5pY>fGGfZr̮f^;V}g:c45Q1Hu֙YOcD=ew*4Wֵ51)NPfBn]v`Y^ 䔌 ߫nArZ,Z ;KdK1|!ڙv?]-Ԋ;)6KF$#x};a4cr6BA2(Q{l]8lr8<zL;ٍq Y9]kX"ڻX-w ֯u|NLrFg>4s#ohlDX\;g#b宯mKGb[ҳu{ҭQ{Ҧ=?kj+_kϻ&ȭJ͸N?0dǎ5sme@,+4!e]ȼR~?6?(mf%EG$Vh/,.LA$N1Nt4Pr{$] R+'QK8"o݈qBc4_a\BbvH⒖[9DXLMvwF=8o6xNS:'+kʚ)NʚbeͣqCƖkD5AKVڜ\El><\]Ewi,YVV_q=~mzV=|~eo@^]|8%mQAp࢜8%ațΎP+(CM;nUuUL֯_t7X"Axx]^fz%w%ǢwXzG;̈́ڪӀ=kȩA":TWfdpC0v@jiʹӫE3"3Rkt>{rGB _~Gx~.j~@h;nϟcI=S#w9Į'x+qF2 .vGl gW$%q˞KCj_~7-[:7I<`b'݉gޒ-ܤ)̲ ɭ|;NnA|`ozU\uW8sIpwKp9"?TuRWDHKuFpbY3ݶN`Ҡ;|B K񛻾:Obenwt[8g&-j>j7Se E'm5eos:OB\669; QKr1Eq}Hp.G(S8qDB#$j.JM *"!?@?Xa.ZbvLFBڹ] y }"'p&B앢_|=2l&F=+kIX4qOAlEsn"fhmVݞ0(?q_snx@=SW#VۻBG/$zOJ -srV}b7_AbUc|>֛Dieg"@-k rR;T'H [3b۠Q v>˝q"/lϣܥ ϮNᆉX vB (ٮrZU5AXOs#EM[ oir٧fBrsqU?8isN1Ysq jl`tE5oxΐ[q {ľq 4?fg:BK;Ѿ,%W.]A8?ʽ^o0zXVFw+Ws;?w[{~3z"z,cMTaӊJ/[W4gU% z}ҫ,"XWxs*F ܪk5ʘ|Ux3p򪟳zSx_ L"E]v#J5`繪bVo^ ޔxtMů] q*MCWYJg%- (sCo V4crVx_!5?Nyk溙fQNMmckPp:"E͝6D4vkϡ?<}-|تp8,G_zsN1BDEX|DLsC;[W'N!l&SgR>Yu _t+Gkt.!U,k lS {ЧgN˅H'a6,orELjW_,#A=d&́1~ Y.tiKVelk.,h$vgSBZnS-V dŢ\lY`rya rzk]a~y(⵺ ig $eήo k@w[D ckUbVBC lJ^{)ۙ[]{29:yлç%[B]P_:m;|WB{Ji|7L"p/`_M8H mPfTͩܤwqyXTviQJsQ q .k rUJ1i7|3cB߈@Jͤ =_i>1$.neg[ӞCAr6?NZQBŮf_آEQ炈7";x^k4T=ՎvXr܋râAOé8әΡj6s$xO_ 꽗ETÍ]A]}s5nq=0w>L.Ӧ,P*'<x|1+0g>״oЈ߭цO]w!u^5y9<N"Js̢1u`:X^ wj$[ |‹[oR$?<ȧeȣ}FM'oW( mOƚaxs=B9vk 4rq|4۩dKE¥>#!MHnuwo7hL#οHiǗAh9jڄ2p8)Up$[ה<<9F .QY iPCkc ^ǰJC T -*ї_6^C]˟ul2ʇ7 ჎2+h5Aj?CкlJ r^`jlmIC`21a:%ٓh3\ ZkklDSMVGp?_&\A*U ^Uc2;ߞ9/׀Ws)W՝56Mm|Bcwgo3m[땮S6)[1V nШZaкB5zhD}b؞O㲂 N Ձc ['L 5ͧ (}Ea# q}ix!/棔;N5t\ U4|%q}-+Qu7|z)y8 ZS=-3~vgelo=3+ܥKP/̣5r{[ag^eלNWA?[:!<EJTjܖ9(eӀ)D) "?}vsQnF1sE@띻)O}LGo S9l V n+|4QZ͊\Dm*WڭEYU%28nAiMR>Gw-K "Nȉ ԱM#? ~~m[3hmTHYaMEAFզ>eQQ10)0V970n/*J( [A2nHa.;o"{eY9;߹ MuY10EM%[P f8a,jlUj/ݪp'R}7JIo?Y]j:Pfm6Vr-z.[s_ő=rSĞwս:QO!ZZ73)]R-ᩪf MvgmvIq+}?{J6hRoJj*r'PQikZFwqqn[NmX[׆Rp2yvǡ iVɯͫ vvգqy piʰ&^qpEd9f"vJucgnX|rnc6W-]2~|-[-Ow~#WO_/?QsN?(J{٩:l埔ŹSle ܄S3S>жر ߴanYi/[M;z/tӭ[21'ѷF~lԦl %!$9zzAeU6=3opL &0,^F}ͥ>k8_5׺aDINFCے> }/K6l5?JOnD'[)S-Ql*q]~oMpC83*џ3bFɪǭ{Q{T}:uK{wֽ/OGm26 R1y:X]t\\O>ZGJ1u8 8ףtkۢ5XK5|=ߺL5_EooNu^0X8n[|3W0_+:f2UC^'b[q+}qý ;T_IG}kѱîZs8삯{/ ֟Hd^xZSL\U &~3ϧL J0DEj|8rI8i24ciS$.EW :s(ry%.ޗLp,za&XKl<y=sHz̠MwD!%lռeH3<o">u sciBI#x=mf*|=Vֈ1g)7 [O 8eVN%TwP;c2/ *tc-.r-]GʡX$OZەhkc;8uP5ц^R!dmWe/;g"{݊Ψotڜ(d,3M yᣯƸ3 8Oq,3X%/b'6KrI Xftp3B,h`dpـI'!'&9P*ؽ$E&& ~pp C'pfG69jQBHṖETi `lby0'|X-,G~؛nߪᧀ0u sL`O=cXH|MGsŚ{X8a Y@txo V[rcWBXU cnꩮPW'#sIb":oG_TZT4dՕqK6օ Izv+$̎5ѣtGj㌮tBqfW(<\81uΊ!=Rfq!RO JL2<5_/&)N1P 2OcX59B+'7 z \}++1i6Nmәffيƺ=^J $Wq֧̐\]Z2%X(}s>Wu[aNyFgIGbA~}Ӟ*P|m`koIBP:s!VV8f{?񤖊%`AUwVvKnV7V\fJwb ?.$?G[ vwF,fI"?Vx7<ɺ5/7x%c=Nu!86<~h*m$_$gDiSuͧP=5yJLj\{.>C6zXrΤ{nUΏ*4d%g^? Mw;p-UAc^N e6qFS$]^К vX-LY8[?SHo;:{m"$`x,v ب@ne|vd1 X VT8>lǒLGtF)ӌgO'(|sړixth~3EIb?a/( Ožw"!%3Mj:*õް-DEԴYgޗ^K`qқ=-|CToĽ[s%_רvo!N >#VhdF(F v|c)pǣz"dsoK*4>`Ź0k(blqfV,"ƇF+s_eU?T7vxMϵyJzdD˂#D SR4ZLQ2 gP{\^E󃘋QK% ~_ -5"2!f !ꃨ7TGuqQ$Q ;qU.v|pSpr_|=S\< Qr|ORk55>yd=gz8|G,cE[(c8P!h+jYMtSbh|ߙbDG, Q]HPi\*`ay 98IvxMp?A$UHQM]Vے쪘+p/ab͟F"K4"+gpLs _ ȕުEx#w؋aZXLC 3}Ď4W 36HE<Ƨ5hpbzx'R?р&M` 2>Yq})3{Af@:` IO#$K2UlPߨAWz jcw=bVϞtkfUoۆo k I&—mZ϶ֶ/W^],If:vQ~a*GFp[m{mI585hVQ7J I(V6܎s;wk$|OH |O3U}'KOAn{j>%^+,Vc{VYcBc:RL Ѫh5P,$zWHsKHr2=Jj0F$"B?"w J'G7dE۽Ld~Eл hǏYD'IғC52mH$|w6e,J#EcCx<ȯ'GLWc1dxSÕr⧜xE*=Z t:1Lg"w]1Hw+猘R/P"nX |*>ˆOQp z)ǧB}$k~8rjx@y 9_c ~֞R 'yQXF=^з›O>c7ĩ<ң0"Ja5SxT@\i%%Ǐ~80ptV +t|6Ԉ㺌R AK~ C*Gzg߯))dKG|e!lǏv֫jJ;V`/rn=Zl^ľD0I"tm- +|m+Pqj ,^pׂI}ё=1L*O;+:1Y&ԗ&2{ixȭ';uw]o\w+( *=Qq%D+I u/6 [mP?S[h6uk#Nq X_\9΋~LjG.:rW!9>00dd̷cl⻮eg79̝fȤPP///L,IC9^6 D L9N[W j@j` TA82 xv0FKo _5Lݜ_s+]{V$:\zm=]}Zk+z28d <ga ~ SΤ7C:H9X9P4)u-OvϢ}C* ZmHkHS\s[-LD{#cKs2/nJsyO{“R-Ʈ ?XǟL:7v2#N~F j>:oQxa zRk,ahZ>sXy"8CUPC;GGUnYϣVAP):i. Qg&ݼRc*UqA#;C &c;hwz6#9%L |p6 <̡q8* 1E i,g6wzd/J+`#C6[p?]33l63cJ8(Z/u@ MT|+4Hu/YTXYukrwX+ط;O߭&`k֝ 3a1֯3 ^)~NK//h]6Lm5Ż*Ə⧕ɯSR–} [s͆:O|kXXo-k׽ۃ=kg;ܫ5;uMZXICSKCJ6Vllֵ#w 3K7[^*[1?UkjDbxɶ>\fkyQ|>eDnu 7F^B[. ѷ0&.߲a-Fۛ붖 `α![~[+<-<]k%o 6yݲ2cozR(Q6ḿE :^˦BeNi] "6/(d?\?/N y1}Z57Qx6>Cד汒M2"l^Cpu~&Q&X6,+7o\'&7u|uk| bH)<,acK?UM 7Fe<)GO(ԯ 4(B/Y[{Jh㺭 ty:}%jٺc|%$|W8vV=|ԵlRZCn{^w;3 $_~}ecҽ@?.+;E@+c?wAa?$Ƈp.&Ta\DX DOe%vGP%XJ =Hr\T5!̣D/=Ga$bǧ/׃ʪҥ]hVáv.ƻb߻p0; ]n w_uppC}z{>.׻gP޽7wuݫpE]}БZpXٍ~nn% ,QX t#OC7&vnߍNr;t8N8ԾrGxRw?lQ/Cߢ>"Qc8.ߜ˦Ly?E}~48!A~8G!.? V_=9jIVjԺBGXKXNII[֧-JK^evdge|>=d2fjY)]V)'=wGi\pZ^T'33ea!%-h0dR2S#M/-ٖ҅e+u«)))@3 zC>=Cn^ ̜MiRQk\dJI4fkEb1daɉ 7Ν[2sffkam/ŭ/\`=ڹBnAJ^͚;dkN׬fS?M}0Vɫ+.UT58SLn4PKk EJIkGRAFIX11/DEMOS/LINES.CXmOIl$C(YխY/pG 6{{jϴq3/mf_Ub(9<`9?[{`>!1\_FVk$ws m@ ?*lN\11so![i`}_$A\\_嵊|r.'`pG?`bo@䟵HKB&x#tb9Ӑ&<|]̅'~a1Z b`Z ˩8US '-2W" Ӏz5Oq[ÛJ"D?).O&(> [MQkfͳ>]w 0 x=zc< ɮ iuq~Z&H/nE.*_z6'3qldr; σ}yY9*U,0XoenZё8=.r ÷q78/.Ͼz6>soo튙gpsӫK21݉xE4qZkvQw&/'7ף#\^&Q}G:Sby{jPxh_3oΙ`Hd/Sh~{s~Kśjb-4䏔MQDRJƗֆS&UB-dZ(tò5ŞkIt.tSnH&.-G}-#8lC)DzZC҈DFK'&q_$eDGKlMAjcRO~&*.)vg{maWb>gcG#sdE>8y' k[c3ڬC_7G8.8"vh8=\NremL)ԃMDBE~x\Y[,j<4dt&&JxpHT7v=c0inɚmERa;G5}a5h6^'d)~\>@zsJXXO,{Z[VӖ 'ah0O[V)Z IFVNJyB˙皦/Qu'O, rpcFc@)r=-& :nn 2.T^B{l;I y3~Y+ReYN~SbpԖWP Jقt@k![Y`Y* yWדwDž8P/ogMqNO-fY{tv9>>;!S`ov>f7pvنg+Yݰ=R"B>tˤ̱%3~Zt.4_0n{$m^@A-B-+řٟZXO I-0h`sB#݁B}T2 ْV njX |$z6>Řf0_zİ.;\sQ@B :gBAF{`\vn%Sc6m:֢%>V)I} ~q``f2熘Am yu؁? -9o ֱn4+Ri}QH}$(cK&(vAiima ts,a+KTZkX+͌xfֱiLz2$t؋D9UvhmBccۼ&§sf(";.1 -o@K} b :w5?G`W<[~)?;L,L5ƅhOB ՏuIi+V!PKkE &+GRAFIX11/DEMOS/SORT.CZms:?hl!!wZ4$fKlB0 j[ԒI{$B`I~ts^$|ʶ&Q=(MOzutXS#Wv2Y'iYw%H1$Pz4xTdw3I?-rvbi{QM.n]ұ۽/2Z4 \P @iG9%cp߷WC; LB7Ktm)CI< ԋ'M[oD b̯XQ%h0Jk  %TA=$Js+~k.U>I$* x,2 ʁ-9d92OT`SlTV%&~I-VPaP,Qd(M \@yIΘtƌ5Er4 tL}6SʌMgU@0&+L`ܺGIjzlP4'Qm.'at]vpKyjFHN';d-$||p7 @!ý$4LJF6mlhT4 ƹG>?! On Yjs4z}@o!᪀+D^K';?9gxM'wGN_&&9VG,pȅHc< -^S!]ƛ4i1]!l` D[F0f6P$ p[ᥝ.+d+g'`;֊2dO6ԭqAq>hwq,.·C.SϞ ?%!f/򤂉'Aw!ryr\\$FVs?xE t-\Χ8s<1!3tvGSז;!G,ot+{j͂xcNJNUЕW*~nlt#N2}R%f <'M1AqLez@Y gzs鬜xD186&,0X_,xT|ek3xǃuȌR_N9Tۂ_ØR`+ j팙L1r'4HVTj/z1,̓HH6W;ǽó~;9UY`U?NűG#ȲVV3E`5j,!@I6We{m_ezme{5wZ-X[o0ZC[bRrSc̢MP5YZj.ZƪݫY<U޲*% dj`zV^Ԓa$Ir6$leGZqEF[U)%7IkkNZ \?uȘ[a6=k`Dn$+[0VopMguR>1-a-vG,we^wuD1.RQ4ErF֥ːǤ+,*EMm|^}p<熇.wQ-Y̘ѧd]8@6NS!ږ(s91،KvμW$=C੫&|B=訷ړ7{II^ 2C)N;)g%2Y ݋KUE*2egzcYKJ({& ICh( Y2`3[ ڋvA'1rbn%SS/:˅Rjtf+j7`n?hn5\d+`-B˒ E%&{{%L=`2kL. xuqr5o#SèT&ܦTIwS.Ocng6 s 7w2/06hg"q-}}϶Ų4什7?jK=0V['ɜK1;LХMdg:|YO:rCHoF.< w@􍈆>{fN4 ʯό^6hB3`* 4u8 y `V pK %%oFU.{ , hO i`0?2dW$e0/}psFIq BܡA r8Uع΀P k!*$ 4BD<Bΰ0(|)e4~ & C}66;=N" R/g@F,7r$&Rtlؘw$)iDheɨP5)iFK]^mo:iLHqQ\nJ86'Ճ{2A٥=W=j ,!e;Fm ԯQX۷],ONJ~@fq6h6T~;((ٝV*LP9u0Qg!f6A_ `d91AFM8ZنeI]OyRg@˓NGF$nk+s{1σDОDܢ>0^7ޅDS#,L4W#X:$n  A )X}X0d`٠f%~"( oP+9>f)`/ RqU!@4\ S)/0R''۽ vǮ!.?'Ȋ!NdTzc5(ж\J)d"eT3#xBk@;o.HUfUtu{lnYX.g[RY t {/"ze]pxWeF ҈RpҞ\L};u@vi40 \7ѝ 6wNDF}ؚ2$_[: CG}TptmZd#PXӋ̺C&Y2oðC܀b v< q:$:UF!B:V!B[Ϭ _l^! x 6$5(-yOW[s U_07. 2{u gd9 +kp@LŘZH2 ޜPaœ̛.J!TQ\%2?%kL ۘ7v0üּҰ}1D}-u  ';ٮHp=Pa1_[p ۿA CM%Wם#{V+]l9lu6L-MZ'6+Y> G=(`F~<'7sQÀ1D*Cr+ЁQDvxU @!=зbjY|az1h-vY}=lyy` ˫z=V}{u_w܌mc8(ӈ͢aO^3!.N)T\eqwb5)ڐD?й%tҗ{m6,9=%; ?,/ReF<% )|nR\Dwʢ;&+S n€ȸ06C".kr`LP)gHf PZF9lm&sI$*D$pzH5_7[c_ecJgS$i,!`LRHI9e 9l^%# Њ. H N>RHFՉ@.1gOKg5 Ii ҧ`h!GP3{ȼH744  ?"I$%PxWY#7c F(:pa\hkt3Np6%4TCmzlH4k͑q K.wH,8k h`IMˣ,+eGxmF#[^Y2ݭ 4 !ȁsөtցD4;c󀰃N2 /ab<td:$J6\UE& ǘ 2!/kvI4c=-8bd߂(+J=6:)A  >44jȬ$NI11u$B<#8SA5c#mTc+cȫ64b)pwwkߓ&F'B*w'Iuo` -v|y&AGE"ET?e#'&J3l~N v0HWΖ  z{Cld7OV鍘RG{V):9ZC%+dDeQ*s}{FbvZ<50p2O̢H3Y)p"xni|(j愡=0D H YpJ[t/9@(̪ DB“P9EN1l89.a}l{[/9Dj 萂f# āKjz^ho}ußaKëvq>%aށ7֤ɿ?osh9f,aV>:4gƻ9iKǣ7 %0!Pl$sb"8 s;v'&CrIiA{R.Hծ>kD;Yh #^r!ՋnMC}b4ӊ:L%lt$\}2%r(pif]ƒM#qqF$!5uͣܰGju=N퀮s1VR(n #ބ|5G"ѽMK*v8#>(:fG>wfѓ 3XySUR)*ƈ{Q~後+,K,_z|+h5Е)ipY ;7Vݿ8Lɉ4nk^}8ʢ3,S.`t ݂JC)R̂MG#?{v 52@9  Nhcdr™~kGj:$z .>'ƙ m~_`}jnstnYYD 41s%31N ?+XZmے〲/O0=hL1>Wl:Ѩc#O3>΄ABPTg_z\TMo8N_p(\3hFb\b^7x>-ϒ `4l!H>P+ FQTܩk}U`ok Ȕ7zkOމ5ʌ) a-Z;Oҋg]u?~Q9hvpyo}i&Qx ãƻ߿_BFow?wCLSMD9zVu2,\B':7d109)m{0 "G[^~u|;3r9e2`Qi;s%sCjlܣ>*N6[9h>sSju@`'.(cT\*V5.yF|Z 5HU#G1P]b,OH<{íP-V16Pn.#jC WTbG0CApQC 7:!$(QO!Gww)<BpƿЁ_`6Q]c=O<㯳ch^EFZQg/+e\r|IcJ#f<G^ڡoJ͍wƺHnelC6t۹aVK Z{ -DWdut"v);$ sIFoD):X9nC!a"W3.ثMY/g.w2&;5n|IvnGh:y YBXo,~,~WCUM{=»eε8]& 8!!uq7h Fڏ>Qs>^guԆBj4QC~kUB~l  r!t~7v2O~8ڼK.K@ퟋs: `N Sp-). AEcPoF6ĵl9sѰ܉, ^1.윔p6PLET*0sj-MԺZNBk+b:BOH ff^9Mʩp†lD@83sXUl\6$&j\M9{32s,^;6@8]:sEZp5X<#9rl:DFŜ[k9 )-k=8eo-VR _q&(^GXb?[Z{b wa(xFI}bKؖw DxE)) C} Z*ѩSF6!sZJV^&m,My,z˨ A;\M:nx¸騈|n]ΩvWE0/@RhRUu"2\h$06 |o[ Sa.w< ad?{P,D҆ŽLP[כm"SAiv^s_խv20{DmjM|qݯo_1,jቨ{n*|mʲK^9@Dl9 tM[2Z$XeW<f׊^rRyq CL7ygs=\wqǂwUP]fMQAg -qR갑X֖S_u粼UseCQY:#sV,S 'c#^/I0j3Ү^b3]>Pɜ 6ރTOav{XXcK,v~K(gdSڱnG\unғ@7}%ǥ=iih3Z6akD_CGRq:q}܂9eKBՕڦz>tL Ij4Q0yU3i$ Љ)jX%I1ںɧ1 m_?w5[t*lSw}_5co~\fm-[ KGA\]ޢP7q*_]Lhםle}Db˄RSlJdc}yԋ75 _P=gU P 0S~_l/B'7+~:HʾwT(pb L]Osj:k>JLŸ>Ūw1ͰjF%W_)wRJYG1jٯ;|`m՛?>?|R?Aȑ$Ϭuq|pEit-_> VO_>;ζP/^{Yv/:CGq[?ԇ~O+yRv0ݾwN~E07cB w9ƇO޾}mO*R^y yfA= %b1xOfu _'$+A]EDPD4>h`ש/O.R&VHt`\6>ųU8۞R@%a# nK~#l"u#9[?#Ƙ1N+5IT\[ θZV0vMhPےaZ*9wWڵ uvOWR5^ZSYLZG׏\wf/ /  >Y?ho- t+s7zR/?OY-2yR8Ρjt:+t55g)FRvOu䮱4QCr2H\3@)HJ9ɴI[cKSUU4 +%YTVxiU'S%ՙXJLӕ>^#]F]) eK_ 4MF΀8ބ9*.l, mkfDD?7Sl'KSUN6'GwlKzzPIW (% {\:j'AoYj}g;zy /8/t_Li#>`6.:[82pa= pB3-"ux953rWʩ%HZ^Xl] VO<s_;xl)1~Z2 TY)V5?yj_+^w3'9LR-C/k~3yOp.OǣЕ"V>C:U8:fYkst d.'5'xg[N\w6zu}PP;+.pEy)_tix]}WbWpNq!>9W8"ΣRo1aWA-/b| cJw.DT'+d8&<' LS\Ӎ$=Su^eQ+lULUU!>vKS@[?URIqT>,oFQ758wC'C *T,qWU:\bom%K $Vb*|% ڐZ+>OKbA6 f[Sg5m3^ɘ2o_T`tSU $3}-DP[ RCs: S,iDI_d^ /,=dkvVȁq/O/NN4Wud,MTKks+Ĉ&ſ?bd6oFQzBj =9*;qkr.k}n]29/Y)պN o! |ׇ Dߎ*@U\[%T . +f5T`*xCʘϦrv"K- U tl>XeUiN[B-9b )Gܽg@,fPԽ")E#Im nl>rm5l \KeeJfj~6;kz/ա-A;ؑҨIV`Nn.`z 8 E08+.^z o/[h\@ =V[bxQM!+: (Vs;5אβQTmi~qۺrZg\H6#_S8Q)%k,az?} bب՚L*51QtgP63^FQ u4lZ]3WtMr  NCŚ8L~ʞ]j6+nf&Y&EasP 흏sDGa/-uVlzEIe@=m5 ٔuɕڒI1ܡ'C.ֺ` Cy&^Z!lh;F#B>NLSRdӭ ɴ[1YV +S)HY*qc_)QIAOnL@jo.dsKz]r%?ݑmwG9_@}$BjsVl6?hO'F\nIsbbiPёx? xkS iw#ޘѤ|pm8pfH*i4pv*54jc>My,8ڦ)ۍ4w~ԍXy*cfGɺ>eCUkl$z5^dfqRr\dkܲyPC  Yͤ`SdSNL*t#yx.lMs%M`פ?GS!BAE.2Z}hC;VY;( V@\6?u)p20ڦ)$ ZZ]Z!h^ƻWY*.*\H4t4>ʛiZ,| cx_{9"$G eN[WnHD6 ]vGʠ݄Wd2cyU;Υd6L~Sg?j\&Li)A9uTL܂6)uBvcZ6' @W0@G(4݈ i[@N9^S;U˃''<7WM)N;z{JA{6*E\} n xY]_ _c,l2 ư奚wj`_{ xVz2o[$MXmŸ  p!:?UxC/>hpyݤ5x1u]:Ƴ{XW?k`Sx&qQM(>GUC#%;~s3{5v}Dm_:at=v5Na5a$hNMkԬݹ/ZFr>$Pё~I-?d C:$'sg(>;;%Ӆ[d?rNt"Nqts:!MiM))%ĨzJna3oD3:yBCr5Ϊ9|/25/8=_ΠQqM gzٸjT М%M_p[:r<&Tka;z7\]7͛wu^H]6Ωh{gc\ڰLpJG4fR IEkDfGo=߉Pk/yT@Ҋꗉʄ~ V]PH΢_q3ԯ̞]xI k\Buf|ͼ7xs2D7jޛKZkTwfJ7XJb|9 so/7B܌T6#AM+TD!SZc۽˹L Q2]!' 9^Hk:A(UNZFAQ&z:.Frs(F?HTG.7$QnI(%ε+*@#7d&衝F4I$kr<}41&欸gHjih/(U[LG_*+6 vH,I@4!p Pt6VTj RӠF |4vNmax`@,?QFQBg yjZjIlsČ M$5.Ϟi-*6DfխzZd0F'v5!"XZRu"**xI"4ZT/S1vUCWsKf 7KZY[`1qNu3- &4\\0mMhma!1C~C$gQ΋g=) {}PL$צ\9Fs Ss%4W+*֊ P Z@|Ui"Y&ko/Ш7zU-;юeyfk!2T6T M D!2T@PxX`T#'or̖mx5>U8Kd oY4$.2Lp5PLa]IBvS35:P0Hm v~'%aȂFQc=;e2q9Sd|#X $p\CSK ק_70?L}M9$9][8>_ɂ_ް<;b 58گ"gh:{j͠0oٷ{~nZx6σnÎ_y ͛Pvk!(5ǐ,MOh^zxׇ Ǽ94 h p+ DL7mQT!jExxk [׃.2I( #a>%bPuGwJ =Q!:;[&gc8Q7V* c*d ;jI#"2߮&Ir j b)fpb'\2 Yj-̪9}=9]lJ|`|\fq{ 2Hg.LzAZ Gߴ!fF`ᐎsS( ^2fPxFn2l"r"&SOȍ] nLd.̵`?!-]Pօ*ALOOB7ٯ^j) g""1t)K},*T{YyKݘ4<gU7:E[%^'R,^#+B&Ov֜;?V?7٩!بidVmcϜ"UuM}\]6Lڼ-|vOZ%L,Gh/'gF,bOf6,,؜ega"y{}P)2ϡ[ YFFݝYi&~(Nϐ5yi!°2`!fSY҆xiAO~,@J$A<[(  q6Z L\!*YS(&Æ.IBG|K&r&mЎE\pbUr;N: +d$$&g./*r|4d3WcRj-Dm&(TMZ<1*+dmA()'k  <=QTry* bvxhD"O!ITXZUpF|( *)>@M~Լ1eo"Pܕq7$@*,KhqYE\Nҭ9LJ,x'w&Z5r;1GX!є^ H,%]`@B|z{N 3{msϔ'g BehP:Ye⤙b%(I@r9ceFaD&rMKv2OX%izGqRr찟C?9 ,Kglt_p>z}PQk^:%Q mByN1nA E.LM<-^ݽaee[e9OaկrZ=z.ݤKx? 2nVc= g<9)l>|@cK:,[.YN"9驕Tz"_tZg~gSu9Ws\;~ U$ \˩ut\8@1jɇCP^Ao`{Ƅ`;T!*>TkQX;=%EcTcP=WWta52>('+6܉ oB+*u>QKfXWZ`s.zh`\{VILpRKh@W3P=5+HA)MɋmWmBh .%E ht"ai8'C&*GRAFIX11/DOCS/GRAPHX11.TXT}{sFw$ug9KѢ<"Ɏ~k[>KIvrP (}׼H٤:"<~e4JI/˨\p}z7IQ{u:Nԡj@ETǡLZWu7d4OWՇ_>߽oe^Mk3~F/_>_k˞yRO/CcTY7_S.:QrGY2PH:!az8( I^'%8.NM'ujX/j8,M`qj"w(/ 4T*$Vu,*U1,0"z$[ C@#Pa roth.)+Q͠O5/*u D-F`$՛d^ɓJ s ތQtH1?Eq]=_EfN;;J(aF:Y KQTLDj\)0I\ OKXͳggɳEעEL/c}~)YL.$ \Kϱ:HJ$@/?IE\xTvǏR$l\ashPu>L͙˖j.k(=~DRY ,lf@yY5 [*DhA@MW?M1ѡ` 5)n`ID .xLWHsU0!&-d38Q kr1} P 5uJ*͖&!+4i?5pgddyfEN11GZ0hG<o`ݦYp)2\)!hoaxf'@a(C$m91XBmU rh=ZW).6$?Sm'T1iF4qǏ.t6ϒYĀW12)/)C"M]i2!E.]eMvQN&jERŐ/.TiI@e2P4kz8ms 2[ w>"&gd=|eQ43$4c[>q$ mP ;0~;Z\] y(Anc5To #]<,wJqFG3 +Bx$w5H'05br =؍u3XŎP3F4e0C`^-2 *=QMk_Z\A}$|<=ɳHIm3rnl$KXoe("ט*`ކ$Ȓh[ڔp/Тb6( IZƐ&}%/:%/m$dcD`^h ,2Z\hq2FhIl9|eZgwγqGJ'$LYa7!m)6 F;G&*SJa*DwUn Z 224y@x2)/zgůJyyE׀L Y);38kp}ԚAVd ` d HU3l̈́8i2!J@!S;nT*\[rNmO':5Xbtr8ɲeNg"N5Nbs `1ddȗȿoNn2AJG=TIO"_3(AjՐuh jxQC#6y' AYJ+I{x%Ag*pAF`R`7f 4CfNI<"kn 3z}Ws.ONQ.DpVϋQ/Ŷ<&*8bvvB|P18Fgr\̰R~lX#̪DS54pb z>W83zŎns=-4=XrhqpӸA2,4oArN:~2ћN1qUC=x~3AZnMzYX$N#WoDA3PD69%0B Ԅ<z:aJzd$GKDlvvqTXCcjFr!Lf}3~z]JatuS)P(T76YNNY@Auv A^[F>c$FDlP H?vI'ʢ)/=3fwgӑyz^+:vTBՐwhY\nA:ف[ c3D{@Gx-^gb[Y7Ǡ62E@٘R퐤Cl%̈́/0Aklrq߁) "B &;XHCK}@\2r4b,Ђ%F/Zk0="ЫNq xqهË 3ļ.1-* q\ #;O&+!Wq6<{B~:b ;3y~ 'Q3`F1UEXzEh8 Jc oXnt[))qV )Ël8ɨK+A,G0ل!F$!Ut.늤D3dl$,D]]H]3վk:P)<.(,Gn%*ɩJC+"9 _wr8 CIeBRPaE"+)}6fOX D p2ÛËMZ9uwҢSktz|B"1l͉mDqtCr!JDyL߮ooxQl`psؓ?ɯE;iϢS6俎1c?zD:F_֙cyXNj4su5Hczcǂe;3 vAQZD(a9 ~IT<>09D.-'Չ ~`^܎}# KHmd0.3. % Iox9:DRV2PHqeɆR9ت l95]0T3}(kboUA@4gNk 8#h qcPz lEN91DžTCL0VU䏊s=,X̩ZCcYcFCJzV^E-}y58br `n6'IsLjA4J`#@d(UE22Z>[߮ureLnLGkyJqXJ ?#_e㈞&$'DlhUq4.u؎SE0zꨁoK4c(JYM#A#F{WW5S9,"M`x$J,M1UrWqupIz ҉:굔%'!Ia9XLnDr _$SX2Ύf? PQ{w;pRuM rc4Cbgxrg9 @U?Ȑ\kIZ,p8sd9fg# [rSӪXx \ %O htGD6A<Չc;<)-嘆g;R6ڑJṟ6s9kX ݷH%BFZ,6c&:1<؂]Hdk؉ (#{K0qLmhB!sO4 %!MN<7ϭ ٬x dD }K2mav4z2)^G`(!1@jH@ @X!=xlmVHmG)e$ (3%=Ut"TLE4B⫿،5ӱLC>3LyY;^<3.SΘ'YDpz{ I^9oD**:kʙI#Fy;ęCǍp=$nYEW~q w u)gjBRzN(@ f6B@dnLTǏʄ,ܾ^a>GetqZ-Ζӹ Մ]ҿW1oK3 E8/9i<w˧D4\I7tLČ 4 ny7$ʼ D>Ghha^ld^,JޤqTWҙ|0hX=2!mqIZB;z\TLEjKZ"f4h24(eA_рm˨t$vc8WtPk%0,._cw\u]̂g)Y>0]X ]9!@ژrk@B„aΪWYӮ-=yO&jK'Q"#m!0Q52lMU078yb Z T+ 2 =U]9P yt/ؔSk[4%=ǟB.s+Z9$(gčw ɣc̙ZGԆOAkDh"+^&[1!Q]€Pv6i9;A0x6SAɿ&ɫ?6%#ܿAUՐcg'Gϟt0j<{; ~up~8z<~ݷA^_ޝ>U'3+ m"mK#fmLJ^AߝnȎzthdiB^e(p/ ޶Zo/w'jptcԱKp:ӣ6Sw:.4dAqWŖ" +$LbljvtG;ĩq3u|Gw BO`|́p\a^u547X& ,xPcaA$bUP`LIp-AHݰ^̺|T&[Nwzy`T8"_ jՌ53P ;q2/GIʲho12z!6k!g,[>3z^S­GzCuȡn{+fpƉ$Ѡ̴;l 6o"τJi!ukNdj'pf#PzdpT"HJs]^7Pghw?7U)PgުdYmq{ o[J逶CkN@~ҵP|؟ƸI*?jؓ7>9=X!1 #B89LWDڞ Tl 'ϑ4d8sB$ ƕAf ~dJL X^OM26P/`)ch2^XoZ{δ`pkW9؄VHU;Q_z^9G'|sFFIu9ܱo̫G_ރBռSG\@FßU7^ALʌIۨONau.^y)^ntqvbwal5~skKr V@Aٳ͗Y2׵](hi_]f_;[xp~胋Jvpڡ/ *@)hɻo~6ˀn)ʍTI#GfR\h[ͩJk\ƇoNϼ#VOtH8x6rmivx'A1"@vm!C2vUzihdS#rnOE,ڢ E[6 j#ylْ]@'||=ӾFC3Y`U;ݎ}9*<s I" q(x:q"qTV 7,ЅLjw%c+fAILvׅWkyvsjz|qڿNՀZw sINTN#4 adln2Z 2b\NbmatO[JjU!7ksC¹c:.GX0j[D~Vw~>,txN;y~PyFY,311t0c#|w{kIjڡW9nRJ by(MM. ̞\Jp*U~&$y% > ;oJGuh C_#% cg!Ǽ&*U iς[J 8IjTaP3i73k;Ucs wyWcӳLfk5ڞ+U:/^oNh5_-VlrՊ-+gZ1_nz\@o.9},^]Orr3Ovh3.7"k;D~z 5ݿM ͦig }.0dŋV^,tBUg%͹L,BfaɄPYw8mwݺFaPҫ 6K: ?kVM&!UZ$uyK&qudp 3f#OH-:GCC'ՒX9Ĭ`Z$oi*j45 p]mkX ~#d׋&\R:`V(7s:6YήFnf?iHɽN3 Fg۠Ndnʽ5O1vnfW #N ="ҝ/`slbw(kDV) \GUcokz[teXpAfb e0)&1Fښ!m3P+JL"8{"* U#Z^8Oelj 7Uݏ4f+-~ݑi8SZ_F5*[ɀjO<Ƅ'  G2㛫M8_c}3+m}EsķWI(A'=Ƅ0pHbG|Wwś"ߒPbq5r/I3.)Tag7NTv}P$K++}҉<0fW^.*D#-ݹB o #Lr!T`wGX'ڼcwdi4N7KkwWE)7rخfcؼ Ϳ}F1ZolTM-*.I@t6*Xco uoӬὑ'zҢ訔Lpu*cJM }n?hl@#x j^P m!49L2QHoP76B=!|>Bq75ZU=Y4dx}-R:uQM24K&PњVt\yMYU'Kp#e=B ^ekX!ZA%y.O7b)w]qwŭ+xUߙj7'׹ nk<5O}H&p2'K+ۙtpNñ[œht!>LOp#;gɈKO%sݮmsHwlbwֺp\W,&i9zT,Ն4+d$#酶7 (Ơ:ь̶Ĉ$F\Df6D {Xw"7ځ!c*90V'4:|?8[#Ƅ(I^H^uunb XH85nqI]>#[@VP&[ : ˍV7KڋXdo; Ζ7Snw9Kolkٺٍ͆ Km1P?[ emV. 9B'<爝ϕ-0!g$@(tt "؀krlum m-s`~2oX@j(kQG[pK 냧M0zs-nTÝxS/Rsqe~e (vuWu"P 2ł _i>{a T{gYw3rRga)v /i$Ҹ;Ż@]WK \eɺm{s6o;ws~_jqEn}7-)Kpsm*H2C-" \#xːxgIT-0?$&p7@51Y=Ӛ+<"Uu;;`67qYq:Б~I^Ͳ FCbηX%;̪@,ԙ5FMM.d3 e~^6!%wcȀl62 AT#NvV;{3 F[Y}V,ykl-K .] F1^@@[Jv|HJgvŦ#s 3tkw}f®/[: gZP؆@W^^}đSX2C {ZZB+fA]*"n“]yjcN!*sF aG.!2wé:^ ։%H)ND^Q%1jnSv"m㹖"!:'O)~g }jiGi"&Q?ńJiK>Uhsbn afE5^.m}1AM9panOpV)G"*nkd7Y`I4R3bK{rt¤x Mg39S)n T Q S9{g 麤|ZMO$É[)HaZ0x~*-Zc9tr$$sCkn-=R7Z};/5 ؙ Rw)%wpvPpUƏzQC/ZƑ=UC][z 0|>P/hd.6qѫ2%KM ~mzccY|efbh"Xgٿ~/yr!iMy>$C4 o]lpnbǕ_3a'Y?= &;Avt kNu!Xm[1I>5ؘVn.J6YH@AU@9 PjjP_iآTseF$o؈إmP0V&C<%w%#y' U7dY\:Gu Va7lB+ 8PڇHRM "&;]7{:qoN-/~ 50o2*Eﭷ1'# rQ*ӻe> :~#hyrR!c9NΏ?zţq>T@>OZ_k!=ɻW`l> EҐP j6(5ώ"V|=>==5 npq鎏]v \zM̓7B7ofSdd:r]I te B)h ntLoPK>W]Uee?(L0kZ0]9c% fy$A0n9NTUyԜ62QtTUntb-FXXs|2$&nliy];xe]IcVz'bĂ!˵ jw0uq3}3BC!'Gvp<8=izBqpcRSHSŶ y86h[XұC%1^GPAD/LvTP/HjPALۗ\'-k(c-6+C;w%#s'E!.[h %-.wYal:h}R|dlr:ά,sx6Ɓ qo[,Hju^kk o@lj~v}AE^R2tb]ȯ񲆒|@g?UMzVn AOdIz0v:m tyq;#*AyV JQ{<D?g@H>+;14|Y.Ɨf8T?@^qkӼ_yݭ$JU@.u|&`&BY ˒:ahU] 0iZSoBjmG}S(W;۟F ,f$,]m/x5GQ@YCbu>0#Bʂ*z|V\&l6"Q;IŞAO8 IV(e@r1'_"]fYϕnCMF&1WIfUNmӇe9΂0)0|{,’%w e ȜKwmQ2>1:Dycp^5L@:%3#¾m:2X R&JpQIKkYLo"kv+?MBlM]LJƴK?-ྚVyhU׺U쵐𭝯\ i3[d=A Ao:E>.Ob` L35 te #=Jn5")) SH@^%Q(3@a]-WIptȽx-]l*y>I Ϣ)ui{4A3F=8}%'#T}U2m`Xm렪et~`aQ`q cR!80O. >_X;k) Ix'Bw7t7hbIf(0c>d ~ p1}҅tPKXGRAFIX11/LC_LIB/GRAPHICS.HDRXnHt_؜g5I 8#d&:Y7m2rޑYUt6$3WU K{5x]c?~ EoȒ_eWH Bz*p%ȏi!`0$V< ׋x",d3C̄(Wqqγ&K(ĴQY %q"@znV :G 8g:ڬa4γ̏_$iʀdJb@H}i$=3CڮlK F0lx*X==녽\'b)VK |#,{f9:=I>;3oz;oqj O{yaGGoG%D=|7٢9>i bȐ!c pU/J-Ex!$N >: ɦ"Z8ڹܰ7Ǐms $ )dX>a*aF%"; 61tV 7bvkKїeӻVg9^B}u{k9NqoAC깎'7 4hKL4<<xo}9B%wL-u2C4" UYeM\.AV;Ms/ls5UОJf\KV ⁱ*.Y)Pc-0sm-ڼ mr4:fR\_2)V́,PThs-kV=zZ8Zz]OϕʽUBU/W"ȋ]}j:v , `}Kmy̶0 [g]710xgڃ{+}:g}V݁y wD+z|;Hq8/ S.n,t?p=o{'gа}"|t`llIW$ aQlX+6ǔbOH@XH߼9ǯS{1սQ;@#ٞud\?Dmpu6DŽzwG}&F` B!EM^|2|=YdxXA2@ Wr 0{|n1.vkxpJDiS/ߛ0xca]9k$B~mL1+"]Y<_$-tfx a6i庥raV;~m*2w /0;`˝Yf5OY)(?H$JLhiĺX, JogD(gBE4*6Ԅ*N8MV{YD4 KɓVd!NvR3+H Z|X k@kthS> \U4s+!Y܂R"')JTxnBsF9F&)|)@k]F:( ,<꠶Ư4O'q ך}G\@ p{AV^i`WPJIPAJ$)dt4Up&ܒl݃[!KT3wQ-P ^;(i)Y=|;- \)e>oDM90eGySw)Pe(RF(XR&-x Aԣ..z*cPBL DXA6=["OH -z\hZjfW-vv E 7L ;S_>͛Ъ֏|$>jj 2(gw\vB֮HLmҔy];f1 DD&44!I=)5A9fvgG>4x5|mAoьBԂHZ5/S0 ,KlEYtïj)NJ"[,8)Z?xD ùWA@&q50L`@kH4T>Fѩ]:}AG9zO63,aU@sM4'2;b'PKZW 35GRAFIX11/LC_LIB/GRAPHICS.HLCrJT*dm$Ǜ l@vs)J 9߷gF DojW?:z8aWu95'|6t]Mp[ 2_Spo ϟbE('Q(EΠ&s7ZD=fPa9-H{3Av_͖l>.m.`^ƅƒNF/ᅈ)؟tADcIY7o?24{1M\pIF%ml:#Ά|v^z_[,\sF8Lp!(Ɵל$ UB ZE J=]FpdPӖ4'y._Z~CN0rC b(oBR] /ZQ oP^ײuh2V3' w\@S[ݽvgɑ^KrZ5 RDB{%C>Ĺ KaKHh84ʻwSr Uxt(dy;8=wh9tz\36]ΈjTY:)ݺ^wo3Vc;˰vMEpc4OoD6oM8fج lح ˦ `PmNOu qNT>z~ 74[SK5eLH& cJykVW]ѹfWv5nW#ԃ"}cN-i-n T=TfRlqFG=%OEU 8u0U+_LrS(]-]ѧv˽Hr͏z*3(iGDse.=i#iM,ˈw훎"UvN2?Fo8#/RbYIHAQ=>֡.Xf3|.q$eDF2ZY6)#tQ1 ۿ:(.a>d ˄p-<66`C('#%0 pj{~];jBS 8{sAzX$( zE&aN5ttd͗RE$rJ^Z'wt ːum j6CuEz9m y6Ӹ3v|\N3cm`7ߘFBovC M V"QdZKoG*—ؘZf z! onn]nN۰?H0PP d6z ڃ5T 9ױGu[xႏK0@X_YDž1B& a}ȹtG٭ܠQj`>3:0 H!MilgP8bM-8t7 |6>B^Kފ&&R׈|Ce͊A~<@XņѩKǹI8,U:giTY[K&/T#%` ( /g`Cm>t!UUzN%ʳdEb#}(`2fڼI֡jVA#[F5?}0Ahmn`puqSԾ(_/Ϸ=qn<|"R JOP>f|% Y͋N|1 xMROJq؁)<Eu;jU@llf:Z)QNh̟:fgm5rCcD+=\~@*!>qQDp #N@e<"!Zo`ԐRxO%P_%Lh(-0Up~=W/ :) $G|ꇳdi٥!OFpsk˥*h.e A-[84lL=^I%IDyU!ɶIDٙD}/FDž{RϧJĵVӍdQߥ[vPFnO5fz;%\7QkR*.^{c7?r|nF#,8XH3R), DA}V[6ՁSGX+P {?h$:g?2kCpsu~Tw3C˃4筤bIiަn1y(}ECR*'7+GAs>6i= Kt % r$0 w$%@|~P#mIuf3nrɼB )5{Mܨ`B]?~?PKe,([GRAFIX11/LC_LIB/GRAPHICS.LIB|mtTǙfnep%X# @` Z`AR-!2xx=I6z78Y'0 qI:rVս}v̏Nݾ꭪VU1:c_zf_]b, I[qnd>ctXp&L0F*WSy3Oo TӼi(ؚ]%SysvjJsڭ a7VdW~˯g| &6~:,秛&Q[?fU]z~Vc/Ν3vU=u;`enzv2]ւZw>Z!zhrZĪ~WZ/jJU K;VyٽTqG:Ck5MV)TQKЫR #qVH hQkobscjyU7Xb?CtȁW ΎRmQk)Ju-ףi&jnHʘݽ7G(2@Bl %ڐꑴEѾH­yo =Klԁɒ dK U?XygG: ڪB=mf!C H"/m>꿍t0/"@ډi13x>L%bB?D:v‡ > zLvyt fQ%uψ(7STOܛKgw9&G-'zy*{Y7՟8 ?GO6{U3}%OPsS#t2"݃r^%][Vr! Jo𽪝!_R@]75ƦKA'y8xX{Z \gVZ˛Xթs+oŠ9sX]#37MZ2^ }t~5Z30֖i1/񻥆f2-EdAkk}K4gYع,jOXr-R_vjGV@2TǾ]~G[,_}ʺL z.٫&u^֝+hKucViS ѭzXѦa.Ԯ."}k-*ZMeX׽={ZZK/=_N]X}&J=5G;QNc|`ZTf-&j6g0s4j{ݧ)jA&@IQ6r/:_UAS- %VǗ6†u ~"~Ůkۙ Ln=Ubj,Lk}}Y׋%[ض5jWh'gڂɖw3cl-gٻ|'rŽIO,!^K g]^p+|M-`kkF? O(_ъp"uPwq. UdEz]mk%%LF25ӾcƐ4e!yZ(Z;R䚠 D; jcdc!R8_'7[ fy }| 9Lo!Wc5GDBdYcCBF+ƨCѦR GBoFBۘ]z^H#Dw&CZr !ƴr#%v 42=A>+.)KtǓz7$m+f22" ZKQ4ZkZ);1Е=^Aûs:Ʈ,G哂ztÛ !u{Hw&9K>G#xFT*RS^ٴ+/ ␙ 1eSJ^@C3 CrSRO!t[^W(e=AԞȀ_f0K^B%%|r訣+ʮ|gL;'=>La<\ 9B <$(anDo`t |kUN?Jz 21GM &v\x1$qZH΄Ϫ-K&&Z >q^(DՎ|.ʬ'؅5Ar'CZ[fI\훸wFS&gXMQık̨3 aRj5CITUKz2^~R qߜ{d݆K'/gHBc~׵^uDŒq7;玒ƕ_Oz5z:tEKdk&TEOH^xR%@H-uEJhRe `zcȿFώm?2hBN1^:qֹj?G@K%42"Yo.S}eþR3PV`ԕ~=Cs1RA5>jލt=_̤aXrY{Bar=x;>O3w]dlߖjמA*H"g6P`$@g({LMwe%ҩ/k4ўN}tS7  ͯFsp{osXtӄI뼰-"κrٜX<\>Y)֣P:T-Xd=eWgWW>)\=+ŊՅ~w X#-,bl֯7fOyW].a+2zٍ3jmYDJI6R5g}K~b}}U2S86~҆Z򮤽ũO)i{ڥ-uoV5KW6=<4sQ& {aw)#q%Zy p=_ĿklOKJ_727-/dX}\R#QьVIX#%ڷ J~+SGb-j_<}e[f&lW +;X}aE 7+ik+VJXCԧۜXx}b9)>9lμ"xGQG@ρ!{ /ẃ +|ߺ m-[+yR_8Ը; 8YO&+{91w+BVGZ`o̘ nW\O2giDE PC(ZŇ]LP; CVU ok{""$3ߛa8ў:v(p 8Kڡ5w "\|(_0JΜ| 0t |}E~S+I<_K|dT+M]=gn›[l-7SXAʂ5-T,A^CY{J{yydD@DOpmrv/)etX GC%ЍS~hkGV:%ƀF*Q.h6,;-ƎlZ/{4]s֒7* ˘Rr 7h k|oRK' 4sEۡ~׽)N{)ڝ5tg hBSRzӝceqcZ i4laG;?\dC_L_RXVMZY#_^?V_khڀ]ohdF@!h"KZT-e,vy"Z)cak֮ 3QV {:,$!%kn<כS]o6u|6skq-Ja][*pc K툙0})E-cM68!Z/vX\Y[ тngAgЏ|̋Hmhτh6k6k?hۼGPcҾd:YeG}SR_@zFSSʞha@75@*5GI?G)$~B@O\/Iݑ!5 eۑ|3ll>v."3<#FCGӏj" w?ð݆ac 0 !h62CA>l!p6N!(!Uv!56CKc AG=@!حCC w7d[  :PBT![l}Ekvݰg92mcn1;^LN~Wq̫ko7ޙa&hbF<)As`ŧéd;B1?}܈ S l ۛJKBYe«{Ӝo-J2iB9y1餬`)ɯ(+e`8946h5g3=LM*S׼2y0y~ebHezn̎s|y%e"L"<%Bbdә!ψx|o(ÈckY/?(S/YvDO(wg`:ձ:4 ^dyu{̂=?="/w>^F~Lκ/4T+|2/35\ ӲP8R5oMSOL2ѕyݜ8-'Ltb-7nڱi{׳-tapAZ[vnen㶕Y "߱c ڝݶaU߾aes3v[Vgǎ +W-+Dwέٽ뾝Ā(vrgc`TDtv}a'O5EɽD# ްB\Wkk}("J۬~W-6_qoJWQ[ 5K$kG9_KÒ [5{w;UQ+;;kZҞ[Bu'*eJ[ܾ{Q{/¨F/-[7nb%B*٦v(.=LFbu.9pnA Vw TJRH"JiR Ax4,P;B%E? haL"giEDq0m\Iq'7vh9/ HE9h)%-xC,L_'B%]w}qg:'cf{3rT:lhv譔3@ .Dԏ|F(b$@"=LR#hA(xOECh>%BAG t02~aNY"N6AT*FLw,œb.ZEԼi綖p1)I EKrdE>8Ii"Tt}7;ݾÃf9n#3Vq:oNKST3^A*'љ_ub81~1~1~1~H_)Gu_u_c:Ưc:ƯS|őu({AԙH_#ߊI7q[狤A/>_9<v1EZ15U˶v—|odxKbm9YZŢfAEd1bdՠ>CVHDž胯THGܚTWs|T詺,|U!V ċ⺒/e(,S1ymԦ'DŽ",&M#9;Ykn,oو zA@}k"҇/ 0NAoz|zjG99FPALQ,T=1΍:όsqwECtL0(/q*D v.PCA͋#tF6UZ1J`(*Zc~xfJiC%\g&Jck+BZxA{peNK8/DSčaN0TN0|3 ,.;ϝUe;;=wjC+_67J:҇),"dj R۰!ɷx0_z!tNePl̉ 10ttː|Wc[ٵҷbm:e5(rDVkc޹69pdnCfniYo̓ߣ_80䠟{o`4חe i?ټe7.aqx.q&;MX+F>95;:6aK'_ އ8[{U dž&uDnn)?<{M9#@W>( ~ ! Av0S MJ3!)m v=ti.c)iМ"@5IB?<-}G6r mY-TZL?B"΅??!b`[0d E|BKxT/^m [@x;K8҇khaY)i^RL Yl 14@օ0)~4rЦ ~ʧ\cFj(^D#~S烲x_"񽶳Y1ːo)%pn l\)wEe!LsYƑ笌ϑ/ScTpJŴ)yq&j4mX%eFe&?m)!-qcc-xvF 2~BKE~pTay_ax__!p*A4~ڃkr?ܑ2$W6띉">MJ>L/ ʯ+] k8˂ua߾c*%u~sCĈ[|I(.$Z<$|%`b:K0=?OoIxIj?v⪦y\ή?h'gHWU@2ߎ)պ*HQ ]]=RwYiB)%;攛%疻V'*fU": ߥ,m :KC&.F:\Ԉiu+^Z7vA9!!y""=u O^S!+^Q #YPȺx'+C.!кҗsIMJH#8_ѭ"S [=`ܒKk bbLkE, bM0͹ |@>M=Iɓqei<_1_Q)8$HWq/J,E2X k\GׂZJ] +`v0(. xmED97KT2ː[1KxVlA fW,.\ch| N.?76b0 ;si0}C|Y"0 ataܬDo\d֔`2/x'V\N%kQ&Q('8LNz- \Ii ,BF`xϱ#~uXvq?LjEr< y#i?l#X~v?BohUM{~>>Ogiy~̯ks(2оT¸ \-k/"νp[Z|i"<{==~'?~cӵ8&tz.#ԮL ï_!QY_oqW@[ o?ЧO04l|qh$Lv nqqc8K67?aظSDqmz|CnL79ܴ$n΃\'n5s/lD6" kWQ9 |=?gcl)G؛0Ĝ7 7O".oWE)>Ւ8E77X:@&=VkܪƧɭ:|핳V GLQ\;8iŭ{έ6;toеU{٤IBn U%[#xoFS0m|<-p1ޅIp,xu*8-% MPg}Հ7pL1{i:hKn?HnB4 j=BT-nE39D=_we5>ͨYSoqƩlYP߂NpODQ 9f7^N[ĉs8Gx8NϝF?PK-ШvGRAFIX11/SOZ_LIB/GRAPHICS.A= luGQ 8s3ϕeD-gKeA-dHJ2-S6##3272(2 63# :#p7#pkA@O0* _P$|ڡle228ԟ'ΟFX{.w^{7IJtiFOm>=)kyqE|cܗҽj-(SwS f.S$ teim4ASG&Y[Qy_zRKuЂfn߂Z\)'A޻uhCKS|=W--\V/=66v)zs/ʮl=}Sq~X;C7N#w~`J=W)]z)iB yKjqg G)娞 X}1Puiҿ?A^h]Ӽ LY :y>v=o7NjcO=eEƱgN{KؘF/]ru8I%|Qo{qa]bֺ+ghb%>ymqrZkط(Ktz>1'=}k\#N#ĉyZ+GIvvͨS=%)lduY̕&Ŝp,瀘;sh=s`:n"zoo ?:fFڤQ] X YᎩgfSww6~}'ķ ůbg8" @wzv<$_NhABP0 ;o@+B}_[8__xGO>| /,< %N@z{V*@ W@ y o A9~ 02` } o| oNK sd9r@9 ,x l/ @[6O7D"Vl*$X";{49!dt_l8Y(sXvhp@rXz0I&d_ B6tlOeKbK{" Jg䋅D~ [=;,rۋ"N%!B${Bzsb\a4V2ˏ|Ada*7#CX.%X*!UVMdYwNJ/#eH$ ,/Y+'iqCdC_緻~w;;1>tmݰi㦝:sGp VHٹZZhJ%hvm͌/n"/@ )Px7?@lT`+22İR,6>Bl0F~[:D*)Ry1g, ׽$4$Z6X\uY t?YJ4^b((v .rl@|?s{Ă])vQAoEVaq^)VC\ʱ%/[.)3igiBo:z DZ*&)3lcx>IJ[exX$C"9ޝ[{ Q ðDQ 1fo.`P 11Ro2bAg4H<_**JJ rC+>y"l˶w,9. C-,xT`RI`pQbiT DNr+Ň%Y! D>T,U)2\>+S) y;uI2>+d*`\I򹴂%[4٩6SLNB B!_߻>F}BgOF;%N$J\"g)9%CD]>xk~1VXD>"1HfL稒w]axV0#PF/}g8x #Dd=']gi^C9k1gJ9J$DEA_te9ڞ|uRV[n6~|=5S5Rw U&Rk!'!ޭv1: Utm*-((=ј#]ɨCFm9}/?)iaZ=o\X'1%T?y}}BLj7hcjw,F8[3]GIoyQ=b=Ø̵W+#]c%+a"mQo-AEnY.͍ͣћ~+q|2>Rk+]OlӜ&!v-5ЎUb^{'ZPR#='N\ϑ⤾U>t(|?q-jlWNq;yvmK;'`v}3sMon"ΉҦfGd{,i"T,:Ph H 4h> `u9Vmm%hH/'8,Q XGj3`mrE=mp 4maQ26fPo]o}WL}-y\,_cS=j8f)LASkt&m ϴ9He?}h} .nK83#ZW+ ҫ%@W]4p78PVkkmhmA} E& &-̓OVNpBs`5V^s/Cn}z$djAm _H!y\~'mϓH `sؿa]Sjg؆U/)=-Kѿ4xX$mw-s3n~~v`~qܣvhld="S~zZǬuJJ))Sj%_ϩ/UiD_js,I%a$}GjQA,1UqB2zԟouɏg r1GdW 6rk3<ptDratYuc4NqOr7S2u5g"e 8gf3Yy@;o ptj|kub!:mdZ 'RHecG<@Q5vX%K  ov WRZor kЇ[#Q+ #c{0OXx_!q P d,h&z{&bhCK# -;cEiG#(9Į)?S#|,o)Ou9uRӸ]b5u$TlrrkmHzw곻~VmGR1Kn7׶ҚY>SIU +Y"z WߎEǩ{x|#=d],-f}&Llk>rcm6#>SK9/%Uj!<ȢCj#jۯcK~i ۽M|LT5ބ^UK6<ӹBA6C0s.OǷv$D;(|\z^znt@;eqޘrohlop4}۝EØ !G%]iXC 6<}nBݝߙ`v}AWƒ˒sv\'%'}lW]b#S2nw!#\"ڥ]r,rEt :y<8r4wr\L'yWD{pt\k.*;s܅=^_}sXl)OU40Õ3vj;DZ zL(6Hw1o1ĕul }kљq I]ZDz*R$r5ŁZ\C>V%7FrG첹j!)ڹ?o;X;^ $it`k]YC,!Z4[Gue}*1=Ri|ݭ{vAi{vK%9#xE .ܝSq0LjO0:Y_{JmVb5!uEG sNj uxg8ށ]w*Boc2gλh=56N[{T^󓢷kW&tI7 $J}!;s/;B\e[߉gܥ5rvx3!v*(C}ymʌC=ڜͤԙN:S=c$䚝xg,j_1gM>޴*Y^Nwۭa/sK߶k+UsFPo|!uu㤪)Bz:Mj麎L 9i6iӞ=KLq ZiUkeKuӻ<|5hzou٫ Doעkq, ~IEh߷ؤd;M[y;o$Ǩ,;Hv;Khnl߱:~;ک)[HzAs~4^a|nzqojvW'k `憞G;8xӲ ]meҏ.uo{OPNy523PFO)eg1,^؃MqbӚ.g4]~@)e¬Қh!ok&YU.jEsh".fgDPpOˊ|jbc<׌"w1ʙ JY{ލ7 94 ]JάΐuwZXz١֊UEժadp}@Oi[?z&=z=WwʻLsjntx3nUR2GE8?Q?/N ׮.J1i-~y\ː+2 G]XEI&_]\!X Db)wf+v+$EA{XO^Wr1\?t kR%b}aU&%ϲoR,H{1Yd}a-X={'W9܅P>1~4!@Yﮛ3}vwcUnk 34iSNnĸα| z NО^ѵ`dN]lcs4@DvEF1l|\?qsw8?VTJU31ӈSmJbL|G􈒢MgEV\b)Nބl7@ *w=x~NQ'%~Qs9ݭLTU`8Qۇޘ>PKZNG: .GRAFIX11/SOZ_LIB/GRAPHICS.HSZZ{o8[-Kzvfc+~-Ym]e'Qi7ÇDvnSNp<}r2)Luwɷ>:<:u,㔂>Q8J4N%]cxb`˙%rx) I&m %s4!ShL(R+bS2'qn]]}̀<Uy[ÆQDٜ']7a!'4M"L52%'5bYϚxZwCZ#%c/f]>9W uw<r9#;.zNxta[r4BJ nLb?q#pi&I<x^I콈$rѥZ7J(|ɳ`A"C[c^:,zG#FYȂ% G:{C-C9D1u1f;^=S~CbnMn;=n-sL>Š7n]Sˌ.n翢3')D-^$| {hwWAĂhص/K,0w 67}M׷o 6:KDɾ {v^U,СI')R+ ykgpP%?KF+3a0>,ø%,{ PF=9KĂU%]Y,K/s$ld9Lԏ]@{F e Ņ&* 0U&ziExŲW/5TR^< 5J#@*,k78I`incf rQ5.(2!6q(}g$6n)r &$˧O:[w"X`ZK1׾,sh;wkZ| Mim[#|I݌PTWsrFzǰ=BNJ0]j->:nlnaN~XL688 ˆmGMA`B& P_s{7ij#ϗD/~QכK`ڇBZ? ?h:Ɍ#^0C$FHtTA{ uXeS0+BqJF٪o޸Uʥ*) U+v؅/8Ƕb |FJLa-2c"M=^Ia%x6ww0OTU"o\[ZWiV]hXf' ;ɛo= j2{èȶM 55Rkaiv\nƦ MT7v#B8a ^31!jT[v[4](rȣI{YcU/7&r j-aFR'~kG;ltZk;䒰yCNߵYM`KWK 0N6-; E;'znɹ@=^FKV4\)r[@>ge[,q˜\-sVeܢsrY2[aYnLN+ Nj()ME0$)\ p{L}Tѕ{,(.2.Y_!)S6Aٶ-ϬXaޯ9=_qᛦ2NN.Gq>X¶1i hb~m 6NU}p@˫?_ ً]5.^W ۥ!4s*I ;TARp݊xI gUƉٺUn0(f‘ ~pEӁpEҥm1Xkjp-m7A5BQΤŀeƂ;NF!~ <[c(@5D 8~\b)ѭÑUP!H8v ^h T οIWcLpqL;X.AJڐyi;6dr@xn0)J0@ `!N;:ǭFA뭬T&؎8\HŤ%x9+5X&[-( fP=}3%N`iYlÌgg1ܝaXZ utd*X~S 'תThh?UIxG YZе swS[ )&r"[UeMyɊ!IG HҎ uʔ5Ne1q* .2%j$n4.oWdLP}Mbi п ĒkW7چ[6LNoW%]uI6Uk*ZeS2oA>A*`6cD IO,B?̂|Wňq!TH&쾳NKtwuȞnRQa%%pw>#&D͇"W0cQGP2L Org7'v M' VfzewVo茭HPQ]z'a$ %e~ }[%,~]F;o&"AXˆ >¯,y-;w'_ԭȇ8x@2t%\lfpg,v~^Q(|=.ViwyiWL ee2A~\Q@n}ejE+{YPrg' #WgB{T%j_i[S+έ!|U/Qi"ޫ2U#>b@u QQxE/T^mr ‘_.2WrDP6l[,w~X6.k ++oNeNÛ~m0hf}T2#_Px! uEt__d43+CW.|?#v:/BF}+r߷X^iU*PK ;h&&GRAFIX11/EXTRAS/GEMFST17.LZH"T-lh1-?| AESFAST.AOAq? /ueQ j9u髯9 RRS/ksg6_^F`!ur\NwE#3$tc\2=Fo(=MNŪLj֕|FeOqp+B@U!v0v0EDP s+HRiX}똠:L*AVb_iƦtg$Er8@G2iIY Gh`U6&[p@mIFڟoߝo⦳ݑ ĭO^@wJO}qWcGOlR6T2 l c29<1#'wŷӹ&"+Fu;L )Pc4eE6\[!Q-iM'9}$T:B/4Y>f@O1`Rn[`+h'!n>RMP*~UODGl2Mlg瀅 `Ji;lˑ/Tfc9u@pyl<KGH-ݖ]P*pӰ:9p륌a@{1#e%]&wi j/?Tc>)k,{˖Unv7zV]#W[#-ҁ{:X{tETuWę$yKg8Z,!l!O("`ws3Y?*xaH!oOJK ]NqTP]4F HZi&FhjDJ25V59l#=ĸt-@M8_Q _D.@.d/D/h.*pԗ6Yzn{Ƃ.L+9WH g H#g`]ƁJ)@LGt?nW?]\H0'dKKф[;}`NP[w3!dxa*93+q {P6=އ#`3V[l~[B-NvٖLM 4,<ʾH/^l^\%_&yޯ6wCL\zy_=u[%$#Ӷiֳ >t{aOp# l:%DZLu~Hzē^H!r8~[a]]1]bhZ!,Fk|"݄rU4z~ƌ,[6SKsf9Qt\_ #[!_M7}m=h_7ϨѸmPg!GĞ> D5aNxc$'?-i PTzڝ <9wkՀFb&E5 R?B=HR6)J&/&5kT}['!q\i/ RM}D>)ms2Y+ԺHH5I* &_pXܺ@04D4p,46{}*'V~oS魳S>`P~_9Ԥ1J/BG9n1]3{\ElU= 6F+yjSv{k̼sS>~!Zw, HK ZqŽNy}e9-;vf1 GbnbY` 6qk!NjipB:Tmd.dQcZ 4UZѾ 3}p//.>DV8q:dDw+"!26d;J֮;VkIyc8uHȳǠik a!94 y>4{pƇyeU}4zmMm^?׎|ųǕ9]0Bg GpwXOmu>-7k?[i2A%]uk:w:SMTn_7)X L:ݵf>c{0U+U$*Kx`ÈԦgJc_yBIC|m^zN$LKib Oq6ۮ]PיxΡov+=ۨu-\SZ,A')9Q3P_ M 涷4,T[2G`t;a9Q}uٻ]GcB|mf7?﷋p1e4+@'ޡ]y_rGi_8/RxGz:-"j(x@H`a _DKZwj\ɊiwuyIT?o2#_f2+z># S '~+m[S/7J24>*ptRxoH-x/x@ϥ Gw +qo.?+dED+pvA C9ʵ(^h{8B% 4]Ǚh_{C qgX4u9c_ vBVo}dg0^w/_[nS mǙSOtrp4yȺ~.~g܁IĬIdJ.\alj5AV~dt::$|O;|eRfsc2͂ҦX7m5I ;jz sڒ_תklKU=K7\8~4lӲpfXe>K->pS nӽ(0yPPNkdlJw~a4zQy|砇PLJURd&Bhyo|Ǜї/wS3wǡI[АF:mH|OIftf\x>Xٿ \ȮO:_YqR99v0#fx[>*X r |^ [)Nv.ѷݿhl`<}O s7(E@`7g$ȨoO?ؤd/UJ$M!z[j fR>A"j-lh1-@| GEMFAST.H'Avw4ZҸkjO2< q(fr%at7=7u!P(ݶ(F4 [y<]Gv%%PWh$I+m!Ic3AȈqXǍ,퀐3dowCrI9P*F~"a`Ew g ?$?þDey9Dp-s>^DL)pgrVe ~jon%isUšP jqx)M?R^sߟj`Tz5N"Kȫx!.i~1iclqp oPsl{5F0ig!w}>crJdzRb_RRA1֛)}ۗ4۷]HIId,L24YC*[ókcQ0bQI';۵>ڷ`Ul{G n}wO{<#+ιF&!D]|+z!|ܼrԾp=7\Q\kҠ{ˋ]UH.Q`Q?SPEZ0l :,FI:˽ˬI߅|V-iú<+ϋ-N(vZI܀jind^7q(bHqX\\]rMΈD9WӢQbD)~ .+ѱ(vKn#|dN @6K_?\zuJ9+:J] 2:`?bOt" t$޴? gd߹{er^5ME=Tsٝ('~ɸspHD¯ų2}M]!]wM-B4+ VY-F,P\;`X8FNC/1u{3ĕ}^B}dG0bj+9 U7l4atjBi>,hRPh|M-wGfkq|c6DEaӲedMY[-1"̌UE$]MDhOQ kl$%Vy̎zIe.љqצ_[e.?{*vPqm -K}9%~1/O -@j 9i( DŽA֊;;BvN{N^MICi9\u1(/?qs& ^9t#'bV磠]g|&9CWy_MtMƌJ09C׶ pwKс~g%|Ǘ TU'o='yo:.o<;=) x#Jmq<қEwryNWQ<܄5|JY,F~k>y67 lI7nW oA'>+.0F<{י9KXm9Vq#&ss/8ixq]mUP7n|o?φ ڣQv~c3>?GTs7 MT ւ=S /v.'O{|ʜtO x.c3o}_Ehރ%]ڷVCϯhP#h!N-&o۾2ڍ,o&s'zUz"( Re<4;NDVXc!rC/y]N5G{O/qO;1އaR^#\z{rs|YtQQs)1-XcE۳j%̵[mwKkxZrAZAz{¹*]p"vߝ`Vao?lCm@˽;8:М/A\wfRQ_{ҺQM~! OpvԂ:0Cщm!Q肛4܁L i2TӗwUa쭤?0 pј{cvBgg_YeGҀ<8Y0])mu7#'r#WhGSeßJ5dQ>)aUΘLՋ_9&䯢 T r LB@Kɣ Czj#jSW?-i5?D.jc$@ʇǞ땐26{& {ʘ`ǿmwP`_ߑ]{@$iCo"YȏhLBHտӽPdG/ދ(?){/+HK a{&\s45)#?q<]$ q?n"6uM#6t=0H#/8hO^pL:0|&}Q/Br tW@ٯ4&ŗ(gv&:T/$=}SXm0_^ۢH8L4Vo =y^L*ņsKVT SgI˅࡮9uh Cp"' 7(Lldg A3?d; #i+5\MIӅ5rm ^P&UK/۴'fͨj爍_?w"նc/E[~ȾCѮڑ>&oiB5t`w^Wo%g͕WBHڒELR1Ѭ#"p\b$Q =:vudf+Y싍?|{_FE_HGtntsFqdd_3Z_yRzQ El9H6rϭ\d #8 c2s?tPu:9Ћ{3'\Imw6i™w:y³sz&ոA?^҃?_1~V(Re{?݀+ 8/U .j陑7oxmy0Xۻ At|$oi(ZMЄ҉_}g*-&ڬAtufK"ln{6c8!{OgV[aG{c)op kf}u"Ӆ%{;w³ܡNxh\TkHl&n0j5t3%MPH7r,~md&wôUvʨ^/^̪L_QJj8IJOydwp[px&֔jᾟhe_?d_o ~A R5:o 4z&O)''ēHʀo`oǔ=dtY%&tZL<=Dyw˒ TX"*- Q8a] (d|}jf^0Qbx" ~Abߝү?zd!yM,P]{M,9,=$%-lh1->| GEMFBIND.DOC Aِ{=.oD(_~lQZu n-m:9Y~?Q"ں;MIRMEE_8L8r2Xy1Wҋsu~d/H*9*| -VŀZ+ĸRy O},`ߧ-U&ד$AU{@0EV`;\49g1٦w*]٧Lל0A"s4,m`cxS!6]3kr `h34e͍[o" ={%?[}|\+ Ы! f_!Bk2Cy_GZm@ P.% \`;Ng<>8p@G N6VOw4 iQ2V6k`Z0ܓ=#u]?"(͌UT+-<֎Hf\ʫqnPMZ+wZhj9럻gOr֛&HY'_3 Tmge@-A"AE_L.'vvk#E$Xʖ%pT??JTHv%zU"AyqVZJ?z닇L.̡zvw2s 9ɫ|΀تo%>7˖m[_[Sһbz_GܮE8H9P p&27wnմ- a%N ?9:pj(ɻHaMʫ$D hB'-1N=,@+um%83}Uvׇ'ǃ dp)=3uh?h/2%e~JLmT ޡAy>O 9|V*ڛ}aYqg )Żԭ>kѸTٽanSvџ]N4~5ߊP٫F՟l4+K䃶֭8U7R\z%BnRoNjf-wI»Un-nG},a ٸF~t{FW~͸=c' cKV#KyI|5'1h_m7f\ KjvVjImoSƹXյp2(zXHnD"^[XY9Uъ`PvWu!>tGkL\{n|sj|i3#$=[uâL?Y| `AbK2"S"q`*MO~c 53ȮTvBkl $. ړ7XDz-v@Yh,cϷ7ܿc$& xq [H Z02-Y>0$,ø!v|JRQo]ܜki߻? >)-Y|X;xjcsښ?wtYo4 :tp{]k<Uu>[AXb mx.6o rZLnpmFOk|)d0֝SgδByI 31ޜm+ɷWzd5NO⏬ﻥ{/˿ݤ= .#3BJ|w>>/XitZ<{PX7lt{꟞yq~K{]io,/mKlx:Nþm7\os~)78!b2.7.1jYLX=!F؉vuzތ<5*x!UC/L%e42c~U4K1C9 )xO/|QC^_kcqyG n:#5#Ba^RpuxP)?m6g;tauzǷTK8\r':ֵ\b'GAm8CQ^7jǩ:%ke߯@o0Og_rTCĜ._jQ{x,Ti) ھgHFvlcl>B >ew#r ,ӟ $<|p2 zS؁rq)tEhk_zo^8Hr)(x:0V{ek+Iv6>)N _tfr7xkXvMoZЧ񽵢>~O-cL3hfV{@lP+?/ƀq Y-wxMyETZ}^&u~-uO!R P:<{^[o䇼TMyf/NiZ\~e&M@Y/Yc3m#VZH(H>+VIu4j Y[=O?fCddD[˓&}U l"Ig_Jt!Sw!sOmpyc3G{3SQ}!`i8N~ߗ(qn{;iʤ/euU\{k_~^G`t[Œtt~<V{$3Wqne?o{5V.g-v0)"ɴ+Y1pqv8Ѝ~oSˣM8 uJú.:ku-[E߈׿/OD-LV_%-V]5籤Y `k>Gj̶K0;oK򻯕,m7y 1$SvGGzѨ(\LvȘSQqX~N#H@1xW+Тyx KId:66>4 zd#Hs— fH{]Qq_Z`u#,G7~L%%?_5ALP`q۷}zr6ډQ>NwM޸fn!cnV2 }ߕ Ҥx :߀.xl:2D-\XHBK8!ٿ߇)@x|`A@30xEmBqxXb:?]cXz# g&#j=0=bj+ky&(rvl@kkX/ 8ӯPՉ9@o99Y7$4I?Ew3mniD YT>%dp2才C2S'{iIcR L%BL hZS ߏ7!tWx60a W^?b;NwӺ{JM=~ؗvP/4tOô1DP`+r:{ʎ"`R+KNoj=8m='J0C@`i!*kipav2xX"F4 S7OtD[!iǍЃy2y;\6UC@_8Ay˪9Ƅkl+ 9ߓq;ShfU1RS\|EQ?cG|v%e=Q ׮ڰ}gW9&^OtrM| _ =ٮJd vLJ]>7 UHb$LShHw嵡#p2n]Ptףa h$F{-yN(PɢA%ؾ995;6X\sz 3'@ZR[E:̚k =VScKͺ1Ԋ7=ᄻlV3f};o|vx4)N%b؁ܫ\f,HKI;73,{pE8iNHZ99['AheS%v{@Q@mrjp\}ֱ ,?bRE`%;-lh1-0| GEMF_V17.DOCJA嵝>g0ݯw[}ciuo GW~1JiB7S7 v5M%V{kSz*{^n8 cV|& A;I΂G3{5 )O]q0jI!seL-e.zeɠ'Τy{>6r%hhp&E&L:^@E :/<`x|U<ʽe/AMޕ7wk =^ljxV %f~oťwCSyzZ5<5`)pG﷍5vb=waiڽvPt9tx:PlP}Ԇ$3ղoZ*ރz9N3=knh%e%Mzmϱ衁QY(zo _$+RC$+3uA5NC6)U'A Фڬ 1vFi}h {ob)xѭVl6Уr{d:Njy~c8*܆4wmMysQO ~L!oUl)8͙f8AadoV?jFD T3] _LܢYxq5P˂pL{G@[3t-UI)+ۢ.օq- +D͞`G"nBv1t.rQ!:daZj0ڙ>XByux%zb]~qgMBLr5+Ȗ/\_|5eʰ#KG7WX])J *>V -Πkʣ^5W7,$rYl/+3+u^:t"`uNo®۰Ƙ"Ec;O0Ыg r׵Izտ&Cʑ؟, Ly9G4W^i{ڵ,>HGFw߭{a1s R{] vO-װ*tnOuB.#ѿqRvjkm5.QQ: f0TNBOģr*Ͽ&לFZ} >#r/%<- ~h=9NWven{TsX߼8,f|~5Y+oqg .;*'bܼ 'quN!,J>n_nZFݩe=QV1]'c1vr)J*Q+gW4ri|yU11.*WTXv6(f;wq Lo474էe>I}rT{sbLq Q6JsP$r NG̪װep˘?`;_rEhf7X!r|. 1sېm,čN)2|liSYLǦA]iUؚF?Ѧ^t[t0>c`c`۫?]b?4EK(SgiGo  nC_B(=:9ʸxA=.U&6lG|y 1V=v%yؗ|͎LJqe}P'hOeiJi m{ޠpVLKgyNYޜ?*1Kg gd{P´*_ :}0c$$Rf|[#o֛ERnx uŢ{0:f.<]nI]ұ!O^ ՝]\T2WU{ f8Ǝ穙 3}+!5FBM[ĭ4m"i\LR{:WւrnfQՏ+ʼnV; >^Cpb}#:o 3k>*mt9tݼ~<0$2ANٱ=͛MWnYN7b+_G {xuFr}{DБq~1K|he_;l$m_LȂcF#e JV]$Y}. ʞ*EN&k/`6oѾt<6﬏vjo^X{oڙ¼.:bs) dQW)ե73!d*\Տg[o_q6~(f9ԗbՀwv Bv8^2OsW^emBQ;R) zvotK0veI%&Z0JЈ%r̾z=~yq4}SsS:aj5k3RpY w8zx>vlR[#8m } a5z{_%we,MY"bWS 1^{-!哝wybS4azVEz VtQ(SeHˣwĂaPW7HYyV^]m p^-ZH~Tp8ZyҿeP,jŪþ=w#`~+f}[%?uǙ5ͭ?k0a/IܻdɧGhϚywNp\dpLK_|[<`eVyZMi,\rq(_K^~;:jFE Az]F7c]|g>uXo@ 9ntsB֘'O&xg^|!Kgީ` /l&8yK4Em +nӢ9s_',P~Oj>!*'ˑ.U> u `2"j<z v|,ezᅳ^[M14k%w7Sv?ht̥rUˤ=X㤻@ry":<YXASE:5u~zYiNVo}$R-lh1-"Uo| GEMUTIL.DOCAِ4{>WvV~Uj~SU},&7F,5010.o~ޜBϼ),,Xyglrצ,ڸXShcUi(M1' liZ#]6{=G=:7eH 2@8>#GMѿx5@K2=T(_N|G܃ U|H6}|9"..l;#ymZYrGscZYr򿚍 SW:P2j|{7J>ʺλ-eԻS}{ Zs[|극b.lZFhʍn:HEl% Y˝6|V϶ !Ibi_tcߒMX^$,) Eš!][ J٭ֲ'*1+ ݷN0xؙи籂vCPzKᄬڑC' \tL4Ru`0 lDF`L:]!**pJ=+WDPB{s0r+*"h5}SmBgI}*<UODyh^AL$S<Xx.h29 lk`&&lICާgm liuA;oj\ƞFŅfo.K6]z5os}T}n/6# o<}\fXHq7 F)B\6H42[@~fh!^V4mg桤[@kov?`* Y+\?f?b0`M0aAxs!IN`3Y W%rMN4 d1GхNV87I#Jpt?Ml@Va P?ٖa~( BrqZ=F?ߨ~uVQ[Rq)~~Ky0Z?œ۬H>%É~kp+>)7G_=5v*GWӾ{ePnN_ǜq/qDpg&3 u$][=grNӝFS,@CcÑ8WT+^U:&v2ZnR6ci2es3iܤC{Uev2NE3 ,XBVRwE|k\},MA?7O?ZZ1c YMJ10A@Jb7c)Dê_<گ?sIc)05TXjy__C| f PB(\j:![5+o?zְ/7Si-/Z4\G4 ˽9ejc+ƈ{)~l ~ȕ={ϐEu6$_a?>{86rFRż Pd%5eҞaS0ʟw9?q3zź`.I7$`۽-$ΙH4Ğ9KgnjZS[VVd<7N|ޣ^*Η3ꃺ;ˀh_W!{lXz0\!_ώ}y- ~LmRǰ3n4Ou 7wQTHyoG2)'ˇt~Oz{ܮ>?m,̛ާt}8VSx!ߎɻui2*9o^Xw=O}>uzMvI4f'/C*f!Ujˈ~?d?t$?u?|?}Dz{~t"Ѽ~_wr J9yVEz ];˳E ]B&:ֺkK=I @PԵCVslQed >ϯQ%%soҝ4sܣw~~}uz'>~?סdcyÎgk3b XQpT@dAC=8=2n* Q:cH(γh#?YH%+QBbe muW* z\?؋N m}i1՜PCT жꖫ/D4 fېsfG+ñt;M/m5īUD%SW?=4kg#Ojū}4{Hz ]ϻþMS]ͨ×WH$*mIE:Jr=r<$G }ABv {V9VYy<ߝ%2.2Bhzml @"sD1ʷ~V~^O~OG&;,̥a[v-{Լ[a'nFu/܌FT/OI_jwuQ%ww7ZmqL306~`y1K9{{k#Le6aw05[vlSe雄 ۸bKp^4`CSpQ>1Ce5*bYf:qUA1&"f32kϷw\R`Ÿ =IPw9;5*{@[~-(Wag7CsO6/ϧNտ[i3?J(K]񈊱OLU\Zt́zŐ~! - Q!L5=|ޫ, Jkͯ %n S|} ۬4K7k6d͔3q|_P>Ӫ8;o_:n?KZjŞi56[wCy7ry+̰˲U>v‡tkn$L>8.d݀tIU}x.Cq$|M~9zzq˴{O2o ?3W Y#ǻ௄*u;\g,-=-jS~eO}>ӂ{=ӽؕsOS&΍8[\ 7NZ5S+6~Zn1׸vĉ *Sy״#w2?!(Jn%ă_q͹7Sn@nKCVގ\wU$kߵ~䨹|_=er!':noH~3޳h-Is܇hnVM|]KIOaOzN^U;Nu"0JkcX2 䉹]ִ~( h,,={#nRsTHocˠkT`CKkŅo짳}ầRmLevTUG؈!8i߄ )ٕBwQC?h#Ȕ cB=tYv}w\~Ϸlh;V`:a x#kWea2@E޿fBC-H3 B%}6WmtB/u y>,Z;;ߦ,[x%v^P`<~!d9L>̗ґVAOFICY6qW' ~ Jyz{tK`p+}uu^Kg8~)g:LO#f8i_0fȆT34[2^~a {rt]Y8p~\/Ǯ[ e33mp%9\ {B8XG ?vI Q9lxM){pjG.'~J/z[o5xAXx?[Gvx(X{'c@ջţ'?L2<{߰{~Jh>kjoe2'}KWvT^txB$BThV[yiU+AuHΘ=3yy9 J ް9 jX;.xX QK ><es=շew[̫c-}sVjQĦ-z_Yɉ70{'W/dLxWތ} 5a܊YVCɭ+e DǤ&۾Pل"kùВV =)-D_Zut;{ :ӼYw=L|-o}>]nsu/-.rJ%;WrIuE_ukr9Z[y8d~EQfvNuVM{+v0?$o-^+z~y)|.^/{y-~-+ExLWT{~>^[Xs%wij̃زXWپ ,icGdusNPoNB˟GWcz@Ua5qz[sM3'A|Ws_xV2{ = 7x >äX[/O|(N9.z]vMiiE]@Tj}2Q?'<Z z<|a@#`!rTg|,rڒr<{M':\,H*ԕ`-B#hV%8=2xmQ&=>]yŊY[wFۦdX?N]q/o J;屦%U仚[~= SU50OYςZ)nqC,ՍlҰYhtP5#h rQKg`Ub|Vd\i\ &n 8!?b~f&ܹ' ZF;6lMWg+Qmw챃fn6tۖ%{z|!Qs~ %~ʪbm.U߇؝{A:Uj%XRsxI/8R;޵8ӹOO9@|y<\gq5M;CԍQ&*R)Z+OS-9῍UmĢxXd6&yv\x| :@ f^}}$1^1`-6{r-nL4?,1::xqnkekk>Sы|9|mCQN P*02AT'$QG+RJm퓠Ԓ\,2vIﮦzOۼ~F`GE>"w%. j}((B}4Ѧ޻΋.V,ژ*;pu~~&ǾE\DqnsL;[?e?>w?rNS+B֟J3?;a)/u@Q~Ahy^@M&B1VI k'Ǚw;siz>]@>] d6OwXº.CQHmA'6n8<X4w@[WsZs45M۵Ѳ0N}sn{@ &ݦixg}U-k#i#Xy|^ɧnѪ;jGITnqyf3죝`EI#{Yc5zcqa#K u~H^ǷEbf EwlyCSF^v_F$CIxUuy %XX6jSj e bkE!.bOu?=2;=JGF;,Zaw{|ä#>HHR;Wrіe=ӽM!=m|y%,5vǩBH/yw|7\ʙYb6M_D -oy^ݧίe |N̉jg5z; Uqtj-uR鿈oy?{>夃v A,{|Ups?7Իc@xzuz_<^~׷24 %V2TO }1c =9(k ?ji3S`/[T1=@ L2FqrCƋd}z&=IFě?^=˿Y=*mi8_D||%'-lh1-(p| GEMXTEND.DOCaAِ4{>Ok5kWWYM^ S*u)M"^otd|V3]c=eշ}} VP]5狻UvwZ4 +(drL"MrTC67X_X3 &ɸsI) (JB Q,CtԠ{ 5im~+ ˇ@# #2Cz~ ~ &-+ jK7^n[ :Z3^3v|c5ܞ~k0/c_f,]*e|mS~߰u펅ة7WBm;p\3GnțJn,L~u9Km|/)OU!0=X5+肊$EDGanexYG֡$3,VBfD`ZW+Ǘbʹ~*LD @`_sC/{àj?JcgRɞ]a7g8';COV[N"k25NV&0_hK5 < !JcH D IEx%:^,ɟM!gAFYax9аk8~2/5MPdPLlwS_jd3hX|:H#62;#c'^7J{dH\1د`YW_j`z[qWcvc3Xo |&6|-35FOƻ9HqOJH1Ʈg%@/wD[T5 35imW/ Y7 ,zѮӦ([g'dgsr|aA.j_8e2K*=;ý"O]azٰĬ <&kQd)itBdЗ\R-).ڢAkOv I1>6ZSռ cOeՄa]ooq: 'A l62] 3WuӶ׼؝94tQY/){h9z+ dxkh֕v9/YJ꣫g?|R{Lo ')TT9ܡ5Ka/eئ-|t;"T$Ei 9O]:=g"CǠ(b?S7Y*g+3l[tqTtHs'\ƎjaUCa'Q>=T^h3وPߎR?[g؎=d5r [yh˸y t~lժ CF16`5rτ㾧5'xA*UW3_}-.թb.h|^=;1VTvwFx?ّ ~_쬿9[ :ۙw ͻZL|ze_ߎzae >{NMKJY/@/O_I~#qgM:S!&VDi(@#?c ]kLd>mpr!靼/s.No,3qc2OdZgBFFF >5Ĕ|bjj YAd.06u)*/vmy8lb6x{̺+㸊"-4#b$n0}-O -x?V_{HOF azL29X1ދ?Fo4=Eھk)2o߿`_"B+^!7,}3}s[۶ ǷQkbEk g:O.b쪃Q nPg_^p$w~Gmx%]*2nQ:Ü;)X z6&k~R۩!0J{@ x;ԟ\ֽpOnuW)n rw& }3v-.@%_rI$CI_N'. -> q}C㿼f}ѩ4k];ߊ|#eR+bm| +%B6oBy5]7u-I©M$1$W幈Լ-+_h 6aھ:Cw=t*F;'i?׾oZU7UX*U_y^7]rQ'L=#*}' w|sv %40]a/-C1^c}OYЀU*>Rom#_|4C#?½%78p~*iJջzQ aדUTOILNĭrL9N|Hz.{f.; xW܇ HM~Zu^#VmNboPfR4~.Tt=SOt$E>WR+c}RWnVN?%QiqWO{w~@,"vr+$Gg}ng:35ƞ A]y~W5*4Zk>LӴ?[3){zGtO$R$Qe.TxE謎\7 ϢHZ<⋕Nq? ݿ]{YNUDJ(LO/a^L]HX4OSEC7&EN`/ME#sN̨ǯXK^odNV\Sv197 >uد7g bmdYE!,B#?zT$d8(lHb+NtH,O*C"Ia4g@(C*)wv"Bv /W==ߵ3<ޚQyp!o0i6@)?h rYaIȌ76?h֯c_;MCm~}(^4܇;eO[;uLnw8xiʟ '-`Dʡ ϺO~s}ùwm'27L(ntE"yY#YE O]8j7e~aR&Q"Α/bqCh 0a4k$HsKD`lw޻ȈF={Dˮ2ׯUXsܾdLw28DΧWM2FWxSa[ $-.3 PoP dUͧYc:TSjjڶ0 wDؕr5>۫aں[^gm]대7.ۛ`=-/"4zfx#kK0@O6%u&H#MSt_fo`_k|AeyΟ&o_'3Mf,Ѩei펲%W){kj Zr4 QX^oI|@;rf%yh7sU9A xv?&}Œp!se6+.`c]dM +<iUW1$,[P\: Q/DnJޓ[ (xLj;jŤI*vEn <߱ulєk땓ϋWddÓNǿlm.}?\ &z6Xìo\ME^gm'oYFTNj08C+nj#:]0rI.~yZH' z3#mԹdHWQg͛k<߿vwxmxz|秮5: i7?k&UyΉΩ̻sYcn=]F2zZb>"n&NoD|PxR?TpLy6i|xkKe`VOL<X6(Md#B j(:Ch$\6辬aͭ'ԥ>鏦qkcZV:R{&`[9y|Uz:SK`>NʷS<%ͣ.=Fb@2z߮ nonQ%wLe6=1ݜk&5 bXEY[FӂO]=hvږY"V#{nS߼[Bg+JۯFʇzە"3.#1/X*_qB9V~櫮{˄X現}mMu">mܔ8/۴S*ceGh]R\W q.Χ7Cc'|ǜj_P<~8H뗾gÅ?8[a@6Byy(U5"_/U @CR9߿?JAEˈ3eY9UDA VŵJEZ|4yr)Vk)Hr%>Eku$k%#]t#[*MaXar{cVomW޿r,}5";)Ն樂|5"k{,y7ãƱɑ;U-Ar1kG؎1\ ԟ"4)zؓJ>^F_zU_yCf5Q`:8~5'e}}xDbGwLJX+~>f6m[4e'Y1l2Z}kNp3Y炷qix1ߙqnyRS!:h

,!tÅ)9=;?O;]m5'xpI'R'%;: \S qRe|RգL|u҇|C~'!'ybG)o%P&3 ۈM|CR{OzmuOʼns%zAzvK> eG֑{e'1ּՅwG+/d̼|*_1;inf?hb*LƢ6;blOpj&~k|^ݮ4{ wa^O:eԧqGL{q?:#V.><HŸ*oOG 8}*L~d&#VWwbҩz^O(E!T(<$r+esO}͏|+_/bn~o/ J.^bhy`8R+7a_N]ߧƌi`6 N2I{kF-e=:o/A?pp' /iyBKۜULc>+VJ+uP_L"駺{6mu@ziw?( F6#Z,nL~uv &A> |?`^'{d͈ZW `g (V{LL=ͻz{5%\sZ ޯūٛV EO6!) F(prկ/~PگXڜ巯AFtQn?+9.HJFQ=Lk1ÍYh}WuqC{~{Dž}{{%Cw&#W˦g*&7ל֧v1M Bô)gv]897p*Yzo%,(*lD6AqkfG(~Ky?2:mdUgfKyxlƷإ3n?Zv]`֙u|&8Mt(p pl㼣 ª 3~^%r[X 2ۈgB!yAlxsYza*9OoH:u{yp3{1ܡ_r֛tk7r9v4,qI  H!-elo lj2댔G#r7>ܧ#\l3oVsd\8 O6f^D&hgv|ivBL v>3ſyJiX?۷S;_Ygu+_aMc%pWfmM=,+R@_kk]jzPQvV5f6ax;$}~b/gLwM-ktY>z5#nu m.kj漳FN׈M3{~ֆh~ȯwHVJ[:Zmd(XVIE(hJYMZŏ m^K*rɣo/;?y( -_tO (u RJNޥV5bSXF9P/͘A}=9$odg{ e_d/+D|9ZE}zfr&i><3y#$/&0 [d.Qqy(5b$v_r A Ɨ!OIy("m"Q[/kAHY"@텎$ ]S\.ւkSl]V۸F+?Acmw;naUq\v}MIa89 `N8soׂo8u0.bdos#OX﬍t6':NoQ:>ri{?6[[ie:ւWO1iƛet6(T{ʅ 'z(y}ut?iOd pt.c0ARǞ\OJ-i Q&9/ K{J_C3,yhܦ2 ڳ#v,~NQ,lkN- &9_ѫh,1[q& 1jQ,܌?@j*3)qb#(|7 }u[j:Jx"?X̿a~5s6 uRy೹!-RQ"\-lh1- z'| VDIFAST.A@A|>u}!.+6W_Me) ۆu`jgs{ |= y*>8X?)KAM7?<}="?tPݪ h1X}#st\jzPhw-n~7H(4.d<$m@cj xGK惔$dmխU?:o˹kbuv3sg;z2SUc*韶oB_?)G>ߏN D㱟Xt--h;!{ |˾(`po4HbW?>zc^@ԨxٹNi\& /m.VփlO}h- 9? >x.BE$ K㿘+L;Wl!(b_Fo@*-9D VVv9$ix0 m[jI&jҝrul SznEg=@X)͐@XOzj |#.ཝ8u܄eMsG' lV0軻Of:P ` ]vZ_8Ax~b3ʽi 9๖C>lI3BgXۮ,|εLco$/щ?/]mksh m+7U9>lj_wWu՝w;1<P(?Tnbn)KXC;»fv?U^LjߏpZe*ysKTłq^``Ӗu6]rr*ll=3R0 b~ @r臊<</4fQj|wlv~ؕn-(!a^uPgoW唿 ]u$&_g|ӣV.eRWIZO]TZ5: 3׎Z z!odE.^-OehI:sZ_ҹ&Hm6W(|Pr_9Y@o[饯]~ u>Or>{ e'~?;gu' >CTM OH;AF.KfA8A(dgpN|gx:7uWљi1͉חgH=|Mh9 ulf)u܃u(xPK RTNm'm'GRAFIX11/EXTRAS/FPLIB10B.ARCREADME.BINk#`{ a$$N!LDJFH1剖'B81"  ZGN8al$4 lhG&)L6e 0iܔٙ4ikiN_ʩc5M8Б 0n@dMC'M6&mB 3i]s޼mMn|NScVjoS  N2et U`NL1sPw:31`U7Ἱq]S)2z7c4.Ѐ=A7d̀g>Ju?QTU]XIԄ Axc L(UZ huYTz1u x픖IoYJeS 9Ɂ[yew ZHǎsL6ʑWwA^ .$oxfفA"bYTWa vSNE YeTyJEV1ޓb0UGa;EP*v@z%A֎SLtWA0v:`@,A3b!.*`Fpva 0, ynXnu&Zю1ͯ\QN2!`܏b>0~zж3!?|;!7m\|떐xp?Wp~ly{PP$.&n B-  (5 +!!~6hPCm@~%:%@#Vp;lj'?>hA}2ho= HB/4NW}xl "eKrfco 6jHqsD$% s'YB%O%GHuP@tL$?e2IWZK*{Uw'jdEe+uN6Q59vM`DžwAYO{W*}xPyxtda s`°] 7{S?pn%P=nv`hrsT0Ж3PS` b^Bx> a xY U(%YF>cl@hf0D %rP Y;HcSWuQNKww]P'UQ|ؓ1e%&\Du\I0 `0]`9ՊHPa{&YjY%Fys!!c"dPC2ę"Ĺu"v5ebeCn@f.`UP,0U'^&!B 0P E aY |p I 3pKp B`B0RF@mB8\:0 ¢0 6t C`` icPTBCx <%gg@g`ggg!\ bO D#D^c0N`Pp>60@2XIxgh`YxJ Fp\az`5 x`%/w Ю?P;a&t`TT8:`0` -@ j۰l9jJ # (m x!`)ESظpP` L L$ AS˴R+Y˵Lxѵ]K{a^LKX˴İh48 `?Ц"@# ꐲ# P4` %O`Y s! z*j A TgB>0@z*@ (&r"Byeu_#U ;wX: !X2u~Ȓ_()u[v+rJZdJY[u[MOZ [7پIعi%,Rvu,:dy^7{,*'! \"l$|*,<./1L|xrYf\=K<0[PGN|ơUlbmH3@4-oC=P7NV8fP7၍ p fAf;հRа+}*oHб"^2@00}AN_RPPP8ni~]U:_!;=>Yzd\L>j8~31}rMM 3Qk<:rw8Ύ =8\>~`^}ujp4 .\}]mf?g@zoR_TO\^  ^ Bv ^FN- tLer p @Rgp̯_/ U@02p @"PP%p =0` ;" f]8dpp僭M- {=Żޠ.ڥ]y'r##ڥ]Az  @ 0h/f|!!) Jt3"A@4~c' 2rL7f81p@D:mY:yISM4rdӦD3Fl 8VlXh%-۴pevnw-l@`n-l]faȕˍ[W2=CeϨky.fҍav-[|;޼ MSφyK>XIĿm@) #5#G6A:`e6~ HG Ǭ?xdž=Y ?OrՅO?60:@1` @H[,ω@ئMl `uLʺ a<+g2lXxPk٣ 1Eh@Ds?i3c`;BmzS$?كwn#*dxë6d#'Ml Q`ꌊWv6 V%jI[S *a=j&B@~IcXXp؃mkA! ^4# Ʉ1`|'At&=qE3{5Mh&0M LZO(СY/EL迉e#&%8h F@S<0WP ROk^S641^*8!vU1@g=X\rةX3hnƕLF}ȇV2T!JhҞY\aCX C-xVJTfmi&Z!,0pԧi AXh `<2F9)Rs($U* *r*,kV h-9E֖Gnw+YDIpAq@DPmJF/V dc\?SrHfRD'YPy1pdYDn1\% A\yuÖS塿 EoVS2D 3HNrs) 3zLq >j_(@юLw3L:@8ШELT ]h(9}?Kv5Yiո_nRz1V I΍^zIbua 4]iIz_\P{BTl5]ٓ=xv%0xBӻc%Iw7dn|#&* GRAFIX11/DOCS/GRAPHX11.TXTPKX GRAFIX11/LC_LIB/GRAPHICS.HDRPKZW 35 AGRAFIX11/LC_LIB/GRAPHICS.HLCPKe,([ @GRAFIX11/LC_LIB/GRAPHICS.LIBPK-Шv 0GRAFIX11/SOZ_LIB/GRAPHICS.APKZNG: . MGRAFIX11/SOZ_LIB/GRAPHICS.HSZPK ;h&& ZGRAFIX11/EXTRAS/GEMFST17.LZHPK RTNm'm' \GRAFIX11/EXTRAS/FPLIB10B.ARCPK g.(~DT     ( & 4 $" .    :  "F ~  .R60 N2 $@8L  4 Bre is called at successively deeper levels. At each level, the length of the first input string will be one less than at the next level up. At the deepest level, branch (a) will be executed, since the first input string will by this time have been reduced to a single character; at all other levels, it will be branch (b) that is executed. At each level, the value of certain variables needs to be preserved, so as not to be overwritten at a deeper level (despite the variable names being the same). This is done auto- matically in GFA Bas. Oh.. PLAY_SAM OiANAGRAMS #Or. Oi.. OhREADME TXT puj)INTPLAY GFA uk SAMPLAY GFA unThese two routines play sound samples in GFA BASIC 3.5, I have added comments to both of them to explain their use. If you want to merge these routines into your own programs dont forget to save the inline data to disk and load it back into your merged routine. That all folks! BYTEMAN which are not in the "input" string, or if the two strings are not the same length, there is an error message, and you have to input the mask again. The program converts both strings to capitals, so it does not matter whether you enter them in capitals or not. This does, incidentally, eliminate permutations which are duplicates apart from being in capital or small letters. Other duplicates are eliminated by sorting the input string into ascending order in a work string, so that in branch (b) we can select only the last of a group of identical characters. It also removes from the work string any alphaGFA-BASIC3*********448888 " \ \ \ SAM_ADDLENGTHSPEEDCODEPLAYLOOPLSAINT_PLAYBUFFTHIS PROCEDURE WILL PLAY A SOUND SAMPLE UNDER INTERRUPT,USING TWO HCHANNELS OF THE SOUND CHIP, THE SOUND QUALITY IS NOT BRILLIANT,BUT <IT ALLOWS THE PROCESSOR TO GET ON WITH SOME OTHER TASK I6THE PARAMETERS FOR THE PROCEDURE ARE AS FOLLOWS: W0SAM_ADD% IS THE START ADDRESS OF THE SAMPLE (LENGTH% IS THE LENGTH OF THE SAMPLE :SPEED IS 0=5KHZ, 1=7.5KHZ, 2=10KHZ, 3=15KHZ, 4=20KHZ KFIF LOOP%=0 THE THE SAMPLE WILL PLAY ONCE AND STOP, IF LOOP%=1 THE $SAMPLE WILL LOOP CONTINUOUSLY. PDTO STOP A LOOPED SAMPLE PLAYING CALL THE ROUTINE WITH THE SAME PARAMETERS BUT WITH LOOP%=0 !!! F:!,FF` ``"`,`F``6lzGGuZ#H瀀AJ(g PJ(fLNuHB?< NA\A!@@| FQQ/(?< NA\LNuHAn.(!G ި!GB?< NA\AP!@@|aC0(@H 1Hz?H@??<?<NN APQF/(?< NA\LNuHA.(!G ި!GB?< NA\A!@@|aDC|0(@H 1Hz2?H@??<?<NN APQF/(?< NA\LNuHAf.(!G ި!GB?< NA\AH!@@|aC0(@H 1Hzj?H@??<?<NN APQF/(?< NA\LNuHB?< NA\A!@@|aPC0(@H 1HzL?H@??<?<NN APQF/(?< NA\LNuHzZ?< NN\AjNuHK`QBG9:yGGK .5p*|L NsHK$,m BGn6+N `@| QQFL`NsQJmg.-+G ޭ+GL`NsHK,m BG9ǽn+N :yGG.;pP,|L`NsHKn,mBG g&+NGG.;p,|L`Ns                                                                                                                                                                                                 R>) 8F!F߀!F!F!F`FFGFA-BASIC3ddddppppp x x x 88CODESAMPLEPLAYBACKWAITHALTHEARRECORDSPEEDLOOPSAMSTARTLENGTHSAM1SAM2STARTSAM_ADDLAABBUFFERMUSICSAM_PLAYBUF>THIS PROCEDURE WILL PLAY A SOUND SAMPLE ,USING ALL THREE S@CHANNELS OF THE SOUND CHIP, THE SOUND QUALITY IS VERY GOOD MDBUT PROGRAM EXECUTION IS HALTED UNTIL THE SAMPLE STOPS PLAYING H6THE PARAMETERS FOR THE PROCEDURE ARE AS FOLLOWS: W0SAM_ADD% IS THE START ADDRESS OF THE SAMPLE (LENGTH% IS THE LENGTH OF THE SAMPLE :SPEED% IS 0=5KHZ, 1=7.5KHZ, 2=10KHZ, 3=15KHZ, 4=20KHZ ! ! F ! FF` ` HadB?< NA\E %@A%P%h%haF'Ava *a>a`aQaF%,j,ܪPAFaJ*fF'aa9g9`F E /*?< NA\LNuNsnNF'AaQF%NsGO*3p83p NsGO4pNs |hh h h h h hNu |jj j j j j jNu@F'#4FNuHz *`Hz &?<?<NNPNu"||@AH00@H@Nu || || | Nu |||||||||||||||||| || |Nu@F'QKt(|G"~FNu@F'PKr(|~FNu                                                                                                                                                                                                                                                                                                                                                   )ddHuZ8F߀!F! Fߠ!F`FaF,posn%) DEC f_strlen% ENDIF ' INC k% ' LOOP UNTIL k%>mask_len% ' RETURN TRUE ENDFUNC ' ' FUNCTION del_char$(f_string$,f_strlen%,posn%) LOCAL new_str$ ' new_str$=LEFT$(f_string$,posn%-1) new_str$=new_str$+RIGHT$(f_string$,f_strlen%-posn%) ' RETURN new_str$ ENDFUNC ' ' PROCEDURE perm(string_a.in$,string_b.in$) LOCAL string_a.out$,string_b.out$,strlen_a.in%,chosen$,i% LOCAL chars_permed$,char_pntr%,out_string$,j% . #Or.. OhANAGRAM DOC Qss#ANAGRAM1LST e|ANAGRAM2LST e~ EATING YOUR OWN TAIL or "Recursion" Recursive routines are often avoided by programmers for very good reasons! One is that they are often difficult to understand, so that it is easy to make mistakes when writing them. Another is that they tend to be inefficient. Values have to be preserved "behind the scenes" so that they are not overwritten when the procedure calls itself. Storage for them mounts up over a chain of such calls, even though you cannot see it doing so. The chain might become so long that you use up all available memory! Such procedures often look compact, but you do not get something for nothing! Thus recursive procedures should not be used without considering the alternatives; sometimes, however, it may be difficult, if not impossible, to find any alternative. Consider the problem of finding all the anagrams on a string of letters input by the user, whatever the length of the string. One's first thought is to use a set of nested loops. But the depth of nesting depends on the length of the string! However deep one makes the nesting, the user can always input a string which needs deeper nesting! A recursive procedure gets over this difficulty. One solution is shown by the listing "ANAGRAM1" (written in GFA Basic 3). The idea is that one starts with two strings. The first is the one input by the user; the other is an empty string. These are used as arguments to the procedure PERM. Within this procedure there are two main branches: (a) If the first string contains only one character or is empty, we print the concatenation of the two strings which were input to the procedure, and return to the point following the call of the procedure. (One or both of the strings may of course be empty). (b) Otherwise we form two strings to output from the procedure. The second of these contains all the characters in the second of the two strings which were input to the procedure (possibly none), with a character chosen from the first input string appended at the end. The first output string contains all those in the first input string except for the chosen character. Note that we do NOT alter the input strings. We then use these output strings as arguments to the selfsame procedure (i.e. calling it from within itself). On return from this call, we choose another character from the first input string instead of the previously chosen character, and repeat the process until they have all been used. We then return to the point following that from which the procedure was called. Thus, when the program is run, the procedure is called at successively deeper levels. At each level, the length of the first input string will be one less than at the next level up. At the deepest level, branch (a) will be executed, since the first input string will by this time have been reduced to a single character; at all other levels, it will be branch (b) that is executed. At each level, the value of certain variables needs to be preserved, so as not to be overwritten at a deeper level (despite the variable names being the same). This is done auto- matically in GFA Basic 3 for the parameters of the procedure, provided that they are NOT made VAR parameters, and for other variables by declaring them to be LOCAL. The user may not wish to see any more permutations, either because he has found the one he wants, or because they seem to be endless (even with only 8 letters there are 40320 permutations!). If more than 20 permutations are generated, then 20 are displayed at a time, and the user is then asked whether he wishes to continue or to escape. A boolean variable "abort!" is set to TRUE if he wants to escape, or FALSE if not. This is done in branch (a), and as usual, there is a return to the next level up. At this level, branch (b) will be executed; if "abort!" is TRUE, the choosing of another character and the call to a deeper level is skipped, and again there is simply a return to the next level up. Eventually we shall get back to the topmost level and thence to the main program. ANAGRAM2 -------- Though ANAGRAM1 does the job, it is not very satisfactory for real use. If the input string contains two or more of the same character, then some permutations will be duplicates of others. For instance, it will permute the three letters "A" in the word ANAGRAM as if they were all different! By eliminating duplicates, we can reduce greatly the number of permutations displayed. A further reduction can be made by not permuting any characters whose positions we already know. The reduction can be quite drastic! All this is implemented in ANAGRAM2. Even though the program is more than twice as long, permutations seem to be displayed just as quickly! With this version, there is an error message if any character in the input string is non-alphabetic or a space; if so, you have to input the string again! You also have to input a "mask" string, in which you put any known characters where they belong, and question marks elsewhere. Your "mask" is validated; if it contains characters which are not in the "input" string, or if the two strings are not the same length, there is an error message, and you have to input the mask again. The program converts both strings to capitals, so it does not matter whether you enter them in capitals or not. This does, incidentally, eliminate permutations which are duplicates apart from being in capital or small letters. Other duplicates are eliminated by sorting the input string into ascending order in a work string, so that in branch (b) we can select only the last of a group of identical characters. It also removes from the work string any alphabetic characters which are in the "mask" string, so reducing the number of characters to be permuted. When it comes to display a permutation, it forms an output string containing the known characters, if any, in their due positions, and fills in the other characters from the current permutation in the order in which they occur in it. Remember that if you do nothing to reduce the number of permutations (as is the case with ANAGRAM1), the number increases alarmingly with the number of characters in the string. It is in fact equal to factorial "n", where "n" is the number of characters in the string, e.g.:- Number of characters Number of permutations -------------------- ---------------------- 1 1 2 2 3 6 4 24 5 120 6 720 7 5040 8 40320 9 362880 10 3628800 There can be an awful lot to look through! If despite this, you insist on being able to input more characters than will fit the width of the screen, you will have to modify the parts of the programs which display the string and its permutations. However, well before you need to do this, you may well run out of memory! Good luck to all you crossword fanatics! correctly because my pattern seems to almost come through. A The pattern_mask variable is actually the length of t.he \d Program: ANAGRAM1 Page # .pl60 .lr6 .n3 .ll80 REM Program "Anagram1" ' esc$=CHR$(27) rtn$=CHR$(13) maxlines|=20 ' REPEAT CLS linesleft|=maxlines| abort!=FALSE INPUT "String";my_string$ CLS ' GOSUB perm(my_string$,"") ' PRINT AT(1,23);"Press to restart. " PRINT "Press to exit. " ' UNTIL @wotnext$=esc$ ' CLS END ' ' FUNCTION wotnext$ LOCAL reply$ ' REPEAT reply$=INKEY$ UNTIL (reply$=esc$ OR reply$=rtn$) ' RETURN reply$ ENDFUNC ' ' FUNCTION del_char$(f_string$,f_strlen%,posn%) LOCAL new_str$ ' new_str$=LEFT$(f_string$,posn%-1) new_str$=new_str$+RIGHT$(f_string$,f_strlen%-posn%) ' RETURN new_str$ ENDFUNC ' ' PROCEDURE perm(string_a.in$,string_b.in$) LOCAL string_a.out$,string_b.out$,strlen_a.in%,chosen$,i% ' strlen_a.in%=LEN(string_a.in$) ' IF strlen_a.in%<2 THEN PRINT string_b.in$+string_a.in$ DEC linesleft| ' IF linesleft|<1 THEN PRINT AT(1,23);"Press to continue." PRINT "Press to abort." abort!=(@wotnext$=esc$) CLS linesleft|=maxlines| ENDIF ' ELSE i%=1 ' DO UNTIL abort! chosen$=MID$(string_a.in$,i%,1) string_b.out$=string_b.in$+chosen$ string_a.out$=@del_char$(string_a.in$,strlen_a.in%,i%) GOSUB perm(string_a.out$,string_b.out$) INC i% ' LOOP UNTIL (i%>strlen_a.in%) ' ENDIF ' RETURN e for a dialog box with it--but you could also define a dialog box that had a different border and worked with your own form handler. Q P_exec has two parameters which the documentation does make clear. They are the pointer to an environment string and a pointer to a command tail. What are these strings and how do I construct them? A The command tail is an array of strings terminated by a zero. If you do not .he \d Program: ANAGRAM2 Page # .pl60 .lr6 .n3 .ll80 REM Program "Anagram2" ' esc$=CHR$(27) rtn$=CHR$(13) dummy_char$=CHR$(63) maxlines|=20 ' REPEAT CLS linesleft|=maxlines| abort!=FALSE ' REPEAT INPUT "String";my_string$ my_string$=UPPER$(my_string$) my_strlen%=LEN(my_string$) ' FOR j%=1 TO my_strlen% this_char$=MID$(my_string$,j%,1) alpha!=this_char$>="A" AND this_char$<="Z" EXIT IF NOT alpha! NEXT j% ' IF NOT alpha! THEN PRINT AT(1,3);"String not all alphabetic!" PRINT "Press a key." ~INP(2) CLS ENDIF ' UNTIL alpha! ' REPEAT PRINT AT(1,21);"For mask, enter:-" PRINT " known characters where they belong," PRINT " ";dummy_char$;" elsewhere," PRINT " for exact length of the string." PRINT AT(3,2); INPUT "Mask";my_mask$ my_mask$=UPPER$(my_mask$) my_masklen%=LEN(my_mask$) wkg_str$=my_string$ wkg_strlen%=my_strlen% match_ok!=@match(my_mask$,dummy_char$,wkg_str$,wkg_strlen%) ' IF NOT match_ok! THEN PRINT PRINT "Bad character in mask, or length wrong." PRINT "Press a key." ~INP(2) PRINT AT(1,2);CHR$(27)+"J"; ENDIF ' UNTIL match_ok! ' CLS ERASE mask_arr$() ' DIM mask_arr$(my_masklen%) FOR j%=1 TO my_masklen% mask_arr$(j%)=MID$(my_mask$,j%,1) NEXT j% ' IF wkg_strlen%>1 THEN DIM temp_arr$(wkg_strlen%) ' FOR j%=1 TO wkg_strlen% temp_arr$(j%)=MID$(wkg_str$,j%,1) NEXT j% ' SSORT temp_arr$() ' wkg_str$="" FOR j%=1 TO wkg_strlen% wkg_str$=wkg_str$+temp_arr$(j%) NEXT j% ' ERASE temp_arr$() ENDIF ' GOSUB perm(wkg_str$,"") ' PRINT AT(1,23);"Press to restart. " PRINT "Press to exit. " ' UNTIL @wotnext$=esc$ ' CLS END ' ' FUNCTION wotnext$ LOCAL reply$ ' REPEAT reply$=INKEY$ UNTIL (reply$=esc$ OR reply$=rtn$) ' RETURN reply$ ENDFUNC ' ' FUNCTION match(f_mask$,dummy_char$,VAR f_string$,f_strlen%) LOCAL mask_len%,k%,this_char$,posn% ' mask_len%=LEN(f_mask$) ' IF mask_len%<>f_strlen% THEN RETURN FALSE ENDIF ' k%=1 DO WHILE f_strlen%>0 this_char$=MID$(f_mask$,k%,1) ' IF this_char$<>dummy_char$ THEN posn%=INSTR(f_string$,this_char$) ' IF posn%<1 THEN RETURN FALSE ENDIF ' f_string$=@del_char$(f_string$,f_strlen%,posn%) DEC f_strlen% ENDIF ' INC k% ' LOOP UNTIL k%>mask_len% ' RETURN TRUE ENDFUNC ' ' FUNCTION del_char$(f_string$,f_strlen%,posn%) LOCAL new_str$ ' new_str$=LEFT$(f_string$,posn%-1) new_str$=new_str$+RIGHT$(f_string$,f_strlen%-posn%) ' RETURN new_str$ ENDFUNC ' ' PROCEDURE perm(string_a.in$,string_b.in$) LOCAL string_a.out$,string_b.out$,strlen_a.in%,chosen$,i% LOCAL chars_permed$,char_pntr%,out_string$,j% ' strlen_a.in%=LEN(string_a.in$) ' IF strlen_a.in%<2 THEN chars_permed$=string_b.in$+string_a.in$ char_pntr%=1 out_string$="" ' FOR j%=1 TO my_masklen% ' IF mask_arr$(j%)=dummy_char$ THEN out_string$=out_string$+MID$(chars_permed$,char_pntr%,1) INC char_pntr% ELSE out_string$=out_string$+mask_arr$(j%) ENDIF ' NEXT j% ' PRINT out_string$ DEC linesleft| ' IF linesleft|<1 THEN PRINT AT(1,23);"Press to continue." PRINT "Press to abort." abort!=(@wotnext$=esc$) CLS linesleft|=maxlines| ENDIF ' ELSE i%=1 ' DO UNTIL abort! chosen$=MID$(string_a.in$,i%,1) ' DO WHILE i%strlen_a.in%) ' ENDIF ' RETURN . )O.. Q_AND_A +OTANGENTS .OMEMBERS TXT N4. +O.. )OQA2 TXT L- ------------------------------------------------------------ | | | AAA TTTTT AAA RRRR III **** SSS TTTTT| |A A T A A R R I **** S S T | |A A T A A R R I **** S T | |AAAAA T AAAAA RRRR I ****** SSS T | |A A T A A R R I ** ** ** S T | |A A T A A R R I ** ** ** S S T | |A A T A A R R III ** ** ** SSS T | | | |DDDD EEEEE V V EEEEE L OOO PPPP EEEEE RRRR SSS | |D D E V V E L O O P P E R R S S| |D D E V V E L O O P P E R R S | |D D EEEE V V EEEE L O O PPPP EEEE RRRR SSS | |D D E V V E L O O P E R R S| |D D E V V E L O O P E R R S S| |DDDD EEEEE V EEEEE LLLL OOO P EEEEE R R SSS | | | ------------------------------------------------------------ Question and Answer Bulletin March 1986 Copyright (C) 1986 by Atari Corp. "all rights reserved" 1196 Borregas Ave., Sunnyvale, Ca. 94086 ------------------------------------------------------------ Here are the latest questions from the Atari developers mailbag as answered by John Feagans, Director of Software Technology. Leave questions on Compuserve for PIN 70007,1072 or GO PCS57 for Atari developer SIG information. Q How can I print the special characters in the Atari character set between codes 0 and 31? A You can use either the bios or the VDI. Device 5 on Bconout is a raw character output device that does not do an interpretation of character codes. You can alternate between output to console and this device to do cursor positioning and new lines. The VDI call to use is v_gtext. This routine accepts character indices between 0 and 255. You should be careful in using these character codes because they are only defined in the three system fonts: 6 x 6, 8 x 8, and 8 x 16. The VDI specification does not require loadable fonts to have characters in these positions. Q When I dump a file to my printer, the first line prints across and then printing hangs up at the right margin. What is going on? A Check if your printer has a switch select position for generating a line feed after a carriage return is received. Some software will generate only a return and count on the Bios to generate the line-feed--TOS does not do this. If your printer does not have this facility, some programs such as STWriter and 1st Word have configuration files which define the end of line sequence which you can set for proper operation with your printer. Q Why don't the numeric pad and the cursor keys work in the VT 52 emulator? A The layout of the ST keyboard is patterned after the DEC VT 220. The VT 52 is an older but still popular terminal and there is a dramatic difference--there are no cursor keys or a numeric pad. The VT-52 emulator is a faithful reproduction of this terminal--it does not use the cursor keys or the numeric pad. Here is a brief summary of cursor escapes. The full list is contained in the Hitchhiker's Guide. ESC A Cursor up ESC B Cursor down ESC C Cursor forward ESC D Cursor backward Q I am writing a terminal emulator program. How can I smooth scroll the screen? A Refer to section 6 of the VDI manual on raster operations. You can use the copy raster functions, vro_cpyfm and vrt_cpyfm, to move blocks of data on the screen. You may also want to double buffer the screen. Furthermore you can move the pointer to the start of display memory. Q My C program compiles fine but I get the following undefined symbols in the link68 step -- getscanf, printf, fpmult, and iob. I am linking with GEMLIB and LIBF. A There is no symbol getscanf. Perhaps you mean getchar and scanf? To resolve the other undefined symbols you must be sure to #include stdio.h and also be sure the start file you link with is gemstart.o Q How can I write boot sector information? Is there an entry in the DOS or BIOS for doing this? A Use the protobt() extended BIOS call to create a boot sector. The disktype parameter should be 2 or 3 for 1 or 2 sided media respectively. The serialno parameter should be a random number. The execflag should be zero unless the prototyping buffer contains code (such as a copy of the loader) that you want executed when the disk is booted. Write the boot sector protyped in the buffer to track 0, side 0, sector 1 of the new disk. Use the extended bios function flopwr(). Q I am using function 7 of line-A. I am trying to use a pattern but I don't know what to put in the variable pattern_mask. pattern_address seems to be set up correctly because my pattern seems to almost come through. A The pattern_mask variable is actually the length of the pattern. That should be what will make your pattern work. Q How can I put an icon on the desktop? A There is no way to place an icon other than those built into the system onto the desktop. The desktop is an application program and it was not designed to interface the other way from GEM AES. If you write your own application and create a new desktop, there is nothing to prevent you from using your own icons. A good example of this is the Resource Construction Set. If you want to represent a desk accessory by an icon you could open a nearly invisible window and print the icon on it. The limitation on this method would be that you could not drag other icons to it and be able to tell what was moved. If you want to be able to drag things to your program you must use the system icons. The procedure is to build a loadable driver and change the desktop.inf to contain the proper label information. Q In the resource construction set, what is the difference between a free-tree and a dialog box? A A dialog box is a fixed format object list whose net result when you draw it is obviously--a dialog box. Its format is designed to work with the form library. The free tree is used to define other object lists. Of course you could define a structure for a dialog box with it--but you could also define a dialog box that had a different border and worked with your own form handler. Q P_exec has two parameters which the documentation does make clear. They are the pointer to an environment string and a pointer to a command tail. What are these strings and how do I construct them? A The command tail is an array of strings terminated by a zero. If you do not use it then point to two consecutive zeros. The command tail is used by the run application dialog box for a TTP application. What you type in is inserted in the command tail. The environment string is something that is inherited by a process. It is just a simple string. Q How can I display two dialog boxes at the same time? A The form library routines are designed for handling only one dialog box at a time. If you want to simultaneously display two of them then you will have to write your own form handler. They can be displayed using the object draw commands. You may also want to try form_button and form_keyboard which do not grab control of the screen. Look for documentation on these functions in this space soon. Q My menus seem to have so many entries that they are of a certain size which prevents the AES from restoring what was under them when they pop back. What are the maximum size menus that I can have? A The total width times height in pixels cannot exceed 8k bytes for hi-res, 4k bytes for medioum res, and 2k bytes for low res. Assuming an 8 x 8 font or 8 bytes per character, a maximum for low res might be 256 characters--16 entries of 16 characters each. Q What is the mechanism by which ST Writer reads the directory and prints the file names? A STWriter uses the F_sfirst and F_snext to read the directory entries. Furthermore, it uses some special data at the beginning of each file to indicate that it is an STWriter file. Q How do I get the command tail from my C program? A TOS passes your program a count of parameters and a pointer to the array. Here is an example of how to declare them in your program: main(argc,argv) int argc; char *argv[]; { /* your program */ } Q Are there any variables around so I can get the position of the cursor? A Since the original line-a variables offsets were frozen, we decided to expand the list. At a negative offset from the line A address there are two variables. v_cur_cx is at -14 words and v_cur_cy is at -13 words. Q How can I ring a bell without going through the trouble of do_sound? A Send a control-G to console output: Bconout(2,7). Q How do I access the data in an editable field from a dialog box that was created by the Resource Construction Set? A When you create the dialog box, use the Name function to give both the tree and the object a name which you can use later. Have the RCS create a .h file for your resource and #include it in your program. Define a pointer of type OBJECT and use rsc_gaddr with this pointer and the label for your tree to get the address of the start of the object list for the dialog. Later, you can index [label of object].ob_spec to get the pointer to the tedinfo structure. Do one more indirection to get the pointer to the actual string. 20 Fryent Close, Black Rod, Bolton BL6 5BU (This is not a complete list as some members do not want to be listed) . .O.. )OTANGENTSTXT  To ICTARI: ICTARI 8 and 12. From Leslie W. Dewhurst. Calculating the coordinates of the point of tangency, the slope and the length of the tangent from a point to a curve, is quite easy when the curve is a circle, but the method serves as an introduction to the case when the curve is not a circle. In the case of a circle, suppose A is the point from which the tangent is drawn, B is the point of tangency, and C is the centre of the circle. It is assumed that the rectangular coordinates of points A and C are known, but not those of point B. The lines AC, BC and AB form a triangle. The length of AC can be calculated from the coordinates of A and C; the length BC is the radius of the circle. Since the curve is a circle, the angle ABC is a right-angle. Thus there is enough information about this triangle to calculate all of its angles and the length of all of its sides. From these can be calculated the coordinates of point B, and and the slope of the line AB with respect to the X- and Y-axes. However, even with circles, there are a few problems. Firstly there are two possible tangents to a circle from a point outside it, so you have to make certain that you get the one you want. Secondly beware of a user choosing a point inside the circle! In the case of circular arcs, the same method can be used, but the point of tangency may not be on a part of the circle which comprises the arc! Obviously this is an error condition. In the case of non-circular curves, an iterative process is unavoidable, so far as I am aware. One possible method starts by guessing a point B on the curve, and finding its coordinates. A good book on Differential Calculus will tell you how to find the slope and radius of curvature of the curve at this point. From these can be calculated the coordinates of the centre of curvature (analogous to the centre of a circle); call this point C, and call the point from which the desired tangent is to be drawn point A. As with a circle, lines AC, BC and AB form a triangle. Since we know the coordinates of A, B, and C, we can calculate the length of all three sides of the triangle, from which we can calculate the angle ABC. Only if this angle is a right-angle, is line AB a tangent to the curve. If it is sufficiently near to a right-angle, we have found a solution and can calculate the slope of the tangent with respect to the X- and Y-axes; otherwise we have to have another guess at the point of tangency, and go through the whole process again. However, if the curve is not well-behaved, there can be problems. In addition to those mentioned by John Phillips, there are curves which have such things as cusps and self-crossing loops (which may have more than one slope or radius of curvature at some point or points), curves with singularities, wavy lines (to which there may be more than one tangent from certain points) etc. There may be problems similar to those which occur with circles when point A is inside the circle, but now much more difficult to foresee. There is also a similar problem with arcs. I shudder to think of the complexities of dealing with a curve consisting of a sequence of Bezier or other curves, or even a single Bezier curve! (Incidentally, can anyone tell me the mathematical equation of a Bezier curve?). Supposing none of these problems apply to the curve we are dealing with (at least not within the region of interest), what iterative process shall we apply to make our successive guesses at the point of tangency converge to that point? Suppose we can choose two points such that the point we want must lie somewhere between them and that there can only be one such point (i.e. so that there is one and only one tangent in this interval). Let us call these two points the "bounds" for B. Then if the absolute value of the difference of the X- coordinates at the bounds is greater than that of the difference between the Y-coordinates at the bounds, then choose a new point with X-coordinate half way between the X-coordinates at the bounds; otherwise choose a point with Y-coordinate half way between the Y-coordinates at the bounds. Then calculate the other coordinate of the new point. The value of the angle ABC at the new point should be nearer a right-angle than at either of the bounds. If it is sufficiently near a right-angle, the problem has been solved; otherwise replace the appropriate bound by the new point, so that the angle at one of the bounds is still less than a right-angle and at the other bound is still greater than a right-angle, and repeat the whole process. This method of iteration is analogous to the well-known "Binary Search". There are other methods which may be quicker, but some cannot be guaranteed to converge under all circumstances, so if you choose another method, beware! There is now the problem of choosing suitable initial points for the bounds. They need not necessarily be close together, provided that they meet the above mentioned criteria. Whether it is possible to choose two such points, and if so, how one does it, depends on the nature of the curve. With real-time interactive graphics, it may be possible to ask the user to drag a temporary line from his chosen point so that it intersects the curve at two points along it. The equation for this line and that for the curve are a pair of simultaneous equations which need to be solved to find the points of intersection. But would these two points satisfy the required criteria? If all this sounds horribly complicated, that is because it is so! Some curves may be amenable (perhaps an ellipse), but one may well find that the process takes far too long for use in interactive graphics, which is probably the kind of application the enquirer had in mind. The traditional advice said to be given to young men thinking of getting married is "Don't"! In my view, this certainly applies to handling tangents from a point to anything but a circle! scan utility (S) Pixels program (P) STOS ICTARI acco ICTARI PROGRAMMERS GROUP ======================== CURRENT LIST OF MEMBERS August 1994 Martyn Armitage 101 South Terrace, Wales Bar, Sheffield S31 8QL Tel. 0909 773564 Keith Baines 8 Lumley Court, Denmark Avenue, London SW19 4HQ Ian & Mark Baker 256 Lower Road, Great Bookham, Surrey KT23 4DL Tel. 0372 454875 Lee Ball 117 Millfield Avenue, Bloxwich, Walsall West Midlands, WS3 3QU Tel. 0922 402815 Michael Barnard 52 Westbourne Ave, Worthing, West Sussex BN14 8DF Nick Bates 17 Elliott Close, Forches estate, Barnstaple N Devon, EX32 8EW Tel. 0271 24633 Mark Blackwood 64 Chantry Road, Moseley, Birmingham, B73 8DJ Te. 027 4490936 Paul Brookes 32 Dudsbury Road, West Parley, Ferndown Dorset, BH22 8RE Jamie-Lee Burrows 220 Broadlands Drive, Lawrence Weston Bristol, Avon, BS11 0PN Tel. 0272 384771 John Charles 'Ash Tree', Priory Lane, Grimoldby, Louth Lincs, LN11 8SP James Collett Park View Farm, Carlton, Nr Nuneaton, Warks CV13 0DA Internet E-Mail- S6005/46@brookes.ac.uk Martin Cubitt 14 Deepdene Ave, Rayleigh, Essex SS6 9LG Robert Darling 11b Turketel Rd, Folkstone, Kent CT20 2PA Tel. 0303 245203, BBS No 0303 249306 Leslie Dewhurst 8 Stirling Avenue, Leamington Spa Warwickshire, CV32 7HN Paul Ditchfield 499 Owen, Ashworth North, Maghll, Liverpool L31 1HW Tel. 051 4730303 Extn 4364 Marten Dryden 21 Rowlands Hill, Wimborne, Dorset BH21 2QQ James Ford 4 Berceau Walk, Watford, Herts, WD1 3BL Tel. 0923 248762 Vimal Goricha 29 Abbey Way, Bradville, Milton Keynes MK13 7AQ David Gunby 12 Windrush Drive, Oadby, Leicester LE2 4GH Tel. 0833 720246 Ian Hancock 74 Frank Cowin Court, Sussex St, Salford M7 1QX Michael Herman 3 Sheridan Gdns, Kenton, Harrow, Middx HA3 0JT George Hodgson 4a Millicent Close, Hednesford, Staffs WS12 4BJ Tel. 0543 423804 Robert Holbrook 3 Windmill Close, Haylands, Ryde, IoW PO33 3JB Kenneth Hughes 220 Broadlands Drive, Lawrence Weston Bristol, Avon, BS11 0PN Tel. 0272 384771 Steven Jordan 38 Wylam, Mill Park, Bracknell, Berks RG12 8XS Tel. 0344 427581 Peter King 5 Marlborough Rd, Dover, Kent CT17 9ND Paul Laddie 29 Elliott Street, Sacriston, Durham DH7 6JH Tel. 0913 710554 John Levon 12 St Johns Ave, Wakefield, W Yorks WF1 2RE Ralph Lovesy 25 Town End Road, Faringdon, Oxon SN7 7UW Tel. 0367 241940 Andrew Martin 23 Earlswood, Hanworth, Bracknell, Berks RG12 7LB Tel. 0344 57308 John McGarrity 1 Hillwood Gdns, Ratho Station, Newbridge Midlothian, EH28 8PX Tel. 031 333 3982 Andrew Miller 19 Dundas Street, Edinburgh, EH3 6QG Jason Murdoch 13 Woodmoor, Finchampstead, Wokingham Berks, RG11 3TT Simon Oke 10 Symn Lane, Wotton-under-edge, Gloucs GL12 7BG Carl Pattinson 40 Silverdale Place, Newton Ayecliffe County Durham, DL5 7DZ Mark Pearce 5 Marlborough Rd, Dover, Kent CT17 9ND John Phillips 20 Hawkesworth House, Cavendish Road, London SW4 8NA Kevin Preece 17 Chislet way, Grange Park, Tuffley Gloucester, GL4 0QQ Gary Priest 167 Ludlow Rd, Itchen, Southampton SO19 2EL Christopher Reeder 101 Icknield Walk, Royston, Herts SG8 7LJ Tel. 0763 247913 Raymond Reid 10 Daviot Drive, Hilton, Inverness, IV2 4UL Simon Rigby 116 Rosmead St, Newbridge Rd, Hull HU9 2TE Gair Shields 73 Old Castle Road, Cathcart, Glasgow G44 5TG Tel. 041 633 3358 William Shields 19 Tennyson Rd, Chelmsford, Essex, CM1 4HZ Geoff Smith 6 Humber Road, Beeston, Nottingham, NG9 2EF James Taylor 12 West Drive, Cleadon, Sunderland, T & W SR6 7SJ Tel. 091 5362165 George Voulgaris Larisis 88, TK60100, Katerini,Greece Justin Ward 51 Vicarage Road, Sutton, Surrey SM1 1QN Martyn Wells 86 Cornwall Road, Kettering, Northants NN16 8PE Tel. 0536 520240 Jonathan White 20 Fryent Close, Black Rod, Bolton BL6 5BU (This is not a complete list as some members do not want to be listed) GEM shell code (S) Code to use interrupt routines (S) Random number generator and scaling routines (S) Hi-resolution scroll routine (S) Square root calculation routine (S) Notes on sub-routine library files (D) C Tim Oren GEM Tutorial Part 7 Menu structures (D)(S) Tim Oren GEM Tutorial Part 8 User interfaces (D)(S) GFA . 3O.. EXTRAS 4O. 5O.. 3OX_EXTRA TOS W%READ_ME 1ST 3N^`*|N Z@ZIP!NV/HxHyN YN |" ae zb_ YfHxHyN |``BHyN B."N^NuNVH xGItCzJ1 f |``Cz 1\ ftCzE$$$$$$$$$$$$$$$$$$$$4B3 C/ N UHxPHS?<N J_f,fUHxPHSN J_lB.`RBCzJ1 ft|LN^NuE*Gzz EfaHx;HyN "m0")"m0ҩ+A "m0+i" x"c+|x"Y(m0","ҭ //-"/ Encrypted file not supported Error writing Error while extracting (disk full ?) CRC error Unsupported compression method Press Return. _/HO>N _///O.NHT _" "_x$HBJgSf)f&)f)f f( SSf.LTN _0g HT$_"_S@QLTNPNN NA=@ LN^ _TNNVH``/./. ?.?<@NA-@LN^ _O NNVH``/.?<ANA=@LN^ _PNNVH``/.?<HNA-@ LN^ _XNNVH``?./. ?<NNA=@LN^ _O NNVH``?.?. /. ?<WNALN^ _PNNUNV2J@gA??<LNA o"h ($I!Sf+H0 ( ШШ"h$) Ђ"҈.A//??<JNAO +@,#aBNAN vH~E#*yBG<9F(yQJ9f.raraJ@g. @gh @gp`a B@FL~ _>NJGgRBGt-JTv-KTFCCgp`SBNqSFfaQ`tAp2<Qp 2<oQp2<Qp2<QAp2<Q3 H aL0EG,y"y`Hra@<raR@:ra8VDpABQAClra2QHIG,KBGBCBD|BE4Pf"<2tQPQ<<żGg pFvk>CRE EfRF FfEIt042v@xlSDzm((EQfL MIEA0<BQApBQA43Ea*HaL L@E`G,y"y`C Nq-0@64 GcGR beNu fraT@(Q`" f ra|T@` rap@ BQeNuIG@,KBGBCBD|BE4Pf"<2tQPQ<<żGg pFvk>CREyeRF Ff$y(yg.t2&4&0&v@xlSDzm(>G5xEQfIG@,KBCBD|BE4Pf"<2tQPQ<<żGg pFvk>CRE E eRF Ff$y(yfNut2&4&0&v@xlSDzm((EQfNuNq-H@-06Ѐ01 Gb GcGR`GT @l SFfa` @g @b4B`4@4-0BC3 Cr0 GcGRB43 <@-HA-2 y0 y0A Gb GcGR`GT-H@-0BC3Cr0 Gc GT` GcGRA23v@Fea< LBSBQ`-H@-0AAr GcGRNuH&y, gZ K0S@*9MrAA"6Q#/ /?9?<@NAg LO?pX` 0< L(yQ<9FLO?Nu  #+3;CScs !1Aa  0@`?     NLApBr4Bf `f J Bf R@ @fNPK , PALETTES/BANDW.PAL""333DDUUffwPK tmX" ~ PALETTES/PAL1.PAL 0@P`psPK tmR|\ PALETTES/PAL2.PAL!""223CCCTTPK umѲ PALETTES/PAL3.PAL!!22CCTTvvPK umP PALETTES/PAL4.PAL!"233DDEUVfgwPK um30j PALETTES/PAL5.PAL"2BRbrsssssssPK Hw PALETTES/PAL6.PAL""33DDUUffwwwPK um5+ PALETTES/PAL7.PAL#33CCSSccssPK umUV PALETTES/PAL8.PAL'''PK umc PALETTES/PAL9.PAL9:";nPK*+ՌTBLUR.BASU]hUwm1kh.6F[+cRH0I&ݡ3LB|XPR ) *y膢T Vh 93ys`{9wιM#c:)3֤bXSh ):^f#/:;iZjٺ!ݶgW^tv9|ڞNjR?x)ieqѲ!}>=95Vs\Kj1;3Jw>(oӾtϥKe #N9L0Bz30}ym_܎<3C}:&2XZ @MbCNÈf%gtϹt; Dh8bZDž"iNRh9RJ 1QI&i5'?e0c @މㅷBeӬ _"a5-Nj^^sS; ;W>Pe߸ҹ.`!͆3?&̡ڷifc!Bȷ~J#'W0odY,(2w$ ]j6PqгI NҲYWئf408*j+!=m1fNipGWOgǠd'$'&Ύkx5e7@xpayR/'"7v#=N'y#Kp~oh4_Mxձu|`c)=_Ư3%OT-?걪X0Hr jxr an@(Tu8rX$V\xŷLjg޽.^w7)Vc k`ȳ,dXQ+|cm{),<;O\.}3?II4@'rNi{s_y~SN%r*uq*>8oTr $ EQJwN/%vr;}YK%ze>r.<2 ^ۥ*񂳇@9<*V9+]*KKE)Fab}"֏RnԼrbݠ\߈}waG{໧Yg|\5i-mZtYX\elKStiؽHYFJPK'<` CONIFFEG.BAS+//f``` WBr~^YjQBfZBjEbnANBRobQIfsiRfI1P V .Zjl uo<~5T>دUKMOLQr 25bz  V dZrjU/CІ_MEn6Kpǫ}VXqq ('#HlVHNէPW 2PKd[ DEGBAS.BAST]hTWs!L%\EnV.BfKC!Z(>vTfFK <"}rIMBQCC 4DPQ\8$gg]{Ιo曙3Hqxxhq^{_獇u< C)4&`4tnQ5vgZzw~[_P,|qh49r$xPnCiG|Iiۺ@LbG*oDYr֘q-NLc ZMe ZbٻϹ/%{;w>"C~TBbXw+o45r _56mԦ`|O#Y(-FZ<'iC|$z'bTKKpPA>/Pp-q#儸K]kApUvYK;&MH67Iw|/i$hm1x˄ 4X!Tv#TO( `@6w8uuY#f76q2#\[]z;k+G-,UQ:mu]w6p0g aBML5KQ7 #N;#uma+DLKTZ@t1=Cy(=N#;E0~LO _~Ÿم\&}p F:JKÑm< ydwgYZпvxJZ=ZJ`E*1 PzBkaJ1ślu ̈́G|[^+ԉxG3VEXY9#A.tp3R[nmGtr #g?uMΨ\ה}][SN:Νc'J#OTUӎ5S# &3,fG nPSWʗ"RAWsg9l?vR?,8i5'PK4`O| DEGBAS1.BASUOhE3! ! aY6!ٴaK! =Դj6*kUDWB)!CRh=tCtޛk]{77w b @SiM^}qryr#5,Ny;W*˜c>h0/+4SLrvY&ewN~b20hJξ4 5RНcSԽ_1By\A@?gЛe/ȱI9Mz1( a&Žv5(.7:/1_/.*gVk{j K!B!54ȴ4Ǹ_"!ͨ7L?C:ڃZ.n L?MAcᘶv+bM fMhM^OAMc 5BZ{@khG`ZJ{E\uxk^6{356֜z$搩xuӌ8Bc_ƒOq,#ĺMEbj Sdz*KL/R]7oz}nEs _ra/|=>fMc qlV$j4X[`;ۃlNW5ɬ&jqVxX LuHvL^iF=ZvUBܲ/];P|OaY=sANr4i촚wT 5o;8/Y9-Kط?W'!6#O%|ns~y潀B~y=ƏJs(GNxk=kP! _ uUutREcxc+1sZ-fOPKdjǾ DESHADE.BAS+//f``.` WkEbnANB~kBr~nnb^ P HobQIfsiRfIAIWiN1P \FSjqBiqjBy&PUqrb^_Y MLO-3bRt i-ڞ```hj[Y T֥ 6,TkhPXT 2CP|ļT|y * 6K1< gY-``6A!ok@P2'NHHfg ׆gF_MrT>دWK_OLQrAII-HLI0mL'X,F ە5Â~1@TaႫ`&jH`زBrCZ0hե `)+T*U85U<#D!X!=?3/]!?OO3=/(E   )y% ii@%ȁZZTYҞY^C }"M]0%ZLa` )'G!/\! NW`1a4185,iWZQ]XL& i@pi5$ `E ٩ 5ja"V Sȯs# `\Ϸ}s)kZPKUG8˗|f DSKST.BAS+//f``` WBHfINX){000t)8d)|J2K2KJ@j\KځjJs* --v0hդ'eRZ[5?M!%8Y83%XA ))JL.VHMK!!eeV N;^/z,f,P100je`w sx c8< MA& 6aY$䨐 u.T)0m%0) H;Ur0 6e )" p5E,(X!78U!;R$_!5/`&\6,rg!v̲T+G36p+MJ-EؓV`YAY!Tȇ+ D2BQb&Xd(A$(gd(Ĩ43":V o;4kRfV@2 0&`e^VVDb 69N 3&3M."m-ƱȩՂ@yu@.oQx ,<9~9,q*p}<ɹ BnH|PcSfYPK hIqX7 DSKVERI.BASV]hU>3IڤQ,뱍e&F)t6[ِm#"Lvg03!Ra)!:Fm %CE!C|Pԧ&,m=wv1Dtws{w1jfҦ PAؓ~IkV: _8u4þ,2ΰivfu!L0aթ0L{;vgғxԩX@bNX@D&ԑQLaR8YzjMY3„92I%삗!n(}^xYuSs>0+ u#yhz0]`n%\H]MK[K,j4LZǨ˨&'$ѮLn1oJ0}:B3Pcu(%'NOVꗽYβce# ?O$]Y8V(LkDu-){1r~x"d38jig1qD6G:6 -ͦ~vӹ.C&  aW-tJ2YRwBjg1\,kikAk|Xe=˺n֒cO^tf םaX4J'}Ml^,E?zQɩa=qCN_fw.[> StaY%´1{h _!ϑZ*uU_Q}PW=L[<Ǯ x|uEW~a] ZTWx+/,/|VZu;/z=w(K.U)L}Խrzb}bZYvʊNJP}paٛ[b=֙+g6K>nھA6#d RJo݀Eh;͹Iqsߎ`TnTLjjd#*f9ްJiƶ6Cڌ^+nV$W:(m-az`-ʼ"yoݑ%"&{仳1NeiLYO9_2'_=K"x62@|̯?z4_*(M_PK/! EXTRA.BASYopgyݻ,ζ윍(.#Ŝ]&'YSƅӑkeGE6v& II$fLLOJ)n3鴩!%iҘWYs+-h 2J΄HS OHm߉nZٙG G?226q`" ֳWJyX]_ _d@~8ID9\DvݻxmhMV>Lܔ4Ql )JQ,uᑼScyM(SUQ޶/,h"8<>ɼ# 6v3 @]G/ v0֦|H1g3BXsDQ[n"e ll nw(̇CE e05eY "Dپ9a߾hBt1o΂(T?-a\4+?>Lk?Țk7#̵2N3֫x3eW|uh£ޮ9yBZ~~`x _9S3Wd~)IJ1_$Ta۹AIY<]h]QrxO/'/+פ~p fp.#uhtdFVRT;5+<yaM2TI8W?Skc~;~g k/M:[ \yɜ>!Lݳx*8 Ĥr+ʹO4XZ]c`Yu{רw!BsoT ^O#K DGh }ƈ@CD3 K zL"=ƈ~D݀Ȏ L~k@tN=~CDZ[CCDZlqDZبm@D_1m(_XHAtm[D "#:M?րh"1Btz D>fR6%mܜ OH5ـnhG:0 H鑇yPBޜoY_n#۵XA 2l\)'۴7ͺ,٪4i-ӔusLh8ٮAXPf6QȃisqyfFy`U1pvم D;0 )jVclO }7~yۦCzVVᑉ8gݡ);><7G'͖CM7;G&}GLЪNw|efᡣQ".ڠOTMǎ;G}\l i:oGG&GI |3w 498rYE}7Ю᡼cd섏vh_)/NVbEem_hwD`6J% r6J˟G –Qpz ܵ hW&m̨ՄPd2 qf;ϩB]!SUuo-C*n];)Ԫŝ.詢i^j*xM]n9`YNȕ2$^✗Vymju]Zw}Z`;lVv( +(;3@F *846  %X6޻B DiXx$:q4Y*! " lŊ)-Tb0eH.dYT&Lh,q-%m"ءj..E /Fqj 3#.֓{%&ɤoQ%%$v?&D\dDX]p4I`4XpAr[qņ'Ɖ,P9 2[+P|lP2"}87o64 o1_'!Q@  Of&+0b7ɓbҽQ[&gG)hǨOCc%mvViDlE8n~pĹ3؏8 Np5y3p1ሒA.fR\G EI+a˂b[Z - dE[ ,|2Hzb.0*֚tUXuY*,O*NUNcdbdE괃ZxTM=UKPϯ/(|~}(*L,I5:I}@ 0eOC,TQ4Μ<՜?]\9  - 5. HoX_dǁ(d9 رɘ#"^w],BBEK.5~ڐ[N/)x%ϸGqW{H >0W h lY3}(;⒠Jk=*mHǂ^Fۜ9 |unH.'}b~G^΄Bu]P)=JXKss;\-ɉmkNU :8QRM^:hO* ~YPɐA*NNs  ۰i2%O{Z߀4JJ ct.9)8E:؋`t!+@V " φf1'|* f'/7P|Yxj%2y8qJ-b6[r jMww?b<;͛{A|X:{TVZuؚ9n).9ާ e5j w,GֹUxF쌖!+v29p2hg-mm4O2Q~<# ]xi33iy2%rA(jm"oԝ|)[alYo0׏yPK;i"/s3ⓡm^…L V,DPa4ʥ$a+10/ O%Xk@a)!P(Xoy{gbur=Q۸׺WO )DiWӎI)*LUX-7?!uvrupA2 bBx$D?gC}P(a#^ZCE 6H6W| f3<$ si²s$2 p~*Ru[ fʣX"™U8FRFh&Wsbr+A"Cnpv/}Mߗ`J ExؽF](ޤ;3X Dn$5.qK~j ^,q`͛[ qIiK8.Y8<< q*=MieZWxA0bԑuUR_!GByQw0 fXBgWs<ޣipm,P|t'j \['Ҏ_~tkQD.}HfOw'~'_yTK'K&beXyt.BL h;JE,  J|mXXƆzߖ%|45J vԲ`hlxꧪ {cд叽y,G ˶@~PKP}}FF.PRGmi4]6"bYИ1D1U31\U%񮡊V*Ƭy{}g:W콏خ)^뺸"h%mE=:Ӫ9b Ϗ!ZkYps6Y Q0`&v|IX(`>Jbx.oh gor\}c0P d||a/3SCSE6T7I%X],]SM) Ik`*ts&ѺǀH,6W7u,̀ސ259#AfS`oyи\,T0@oZW:z`;$J7~Z\ };m!\ʿ(KtF n*&m87F%1{4nqeOXvKP!hҸҺU&4,8=xo 9$ñ˜Pp7 qbɕ_x?`6?Zpv 7/Ϋr„ vesv@`I#/롁n^"7E"Rpˍ?~jEFW?V::Y_ڙFN0tnZYal&(-/Mش pgS^1%U?L}d*JlI9_;/%  wdD3=tΧһ:qq#/75oiqJz+ǧOkM3rXl/XkՅsel^W$U:4< g Rbd zutİLCS |X.=IJ Q^vfz&Ö? rsD*\oњ>EC[q4a.yD劈K>f+#&b:kY^ܟA^#} &xsaWz|7}caX2u kz_AC@U_)[1`i?ߤr ұ7.'?,j9Z> .dmOk\*p.$4J^91v`9![aŖ@q{ kuK$Mw TP y 6F,&TփPܦT9H6!4|rcbANʼnde07 2\G-ԋll ?1e TLHS"%"ȃ naЈT( MMr$H\0X%0$}iר\$tj_+/x}ܸ0@y{E.Pg@:_*^H] -"\sӻ!k,Ʊ Lyհ>@-N,3*yI/xzqGvC%ڕK]bϣE+d% D HW!%/)p))ݙsЄmexs>!q8 2i[%K =n L3q5SӤa8 M۹} {< ;hCNqFc"Ǡ-7,k6+^L |́k& ̓o.V|%1Iw~zjNe:]d&s0q̅`l̗LAeA{ aݓyWtHrɝߐy׃`8%vɣU;~!ukC꒢βU:MȬ/aB_X&|A0֬$sN: ]+u-a|*2[!js/z)cw\{t7S*ޔjKFte;)$DrsziI2 _NgiB*MO,*KW̚^n<[ ;R7|yUd}֐gTݩ aсu-y*ȿF:gh h[t_k5f6cYq|u<~V/OL lɮ4,2oV$\3.&^ &+욈{8JWL<8j  |gNW!;Q'sDB7V00 "D"DX!u_P:kn);Έ]KmU>_-uvڹ 7hz= ԗ_/[e7Bncoaԫw$0ڱ˒ХPH~\a ֫ 4ߎm0zɄy*6rpA'Vi+F}z0hx,spXq,%NL/(~Q$3# ޙJ2jATh,S;={]ⅧG) 4YSƈguT}4f쳬Zw ;^x<=>eƯ|9lFfї|][QD]vSag}Haq5Gض"WV}T2GܟW?rQ}Ц^1Յ:ESHpD>Mh@QH©+gO,UзHlRBpmI+" !<$& L Z K2%|6דXo+><eAz)ᯂ&]/3QKY=wP~BAe>W0>('l,Xu<)QMLתw>JnpJ;Hzu4T,crDd똽f E0+X2 xϔ_)qڇlf fkfyiLt,"N f,NjuQ2MR4 74O=gc) MɩHW-EG/!rTNW1ycIq #_~uv7n"nz/"{4 OR1I)nFh/6}pQP7i7f=ѕL`itOCy5fYٍ(0 ͺ@F3R><{w~ea@K X٤IxljHQ9hS-+1`pK^TMoc[w!ȣkfQ 2AhӐjyκZ|3vzMGt7ct4*IX UI[cӱ^JP@TRːlm`&`{v+TD$o1\\~M-14`kS8hZF|?Cr\j:R" s Z(FЅVߜ.#y $Dpz:|P#g>tէ iXQ6SZ ;d1jW1^d3L5^ݷJD2Uo*].ljUk^ak_i=հ=^- |q uT +Q-W',uCaYíU}zjҚ)Rz%:w+M]}]}"v!!:b~+MMTwgSUUKQVPgW"~n(˩H擮 ļP]QW})4BoȆǼ1i+E4%DĘ8v%t,JVicn#J$Jxڥh]~*"&׃20gˤؓ2tveo36|yX>`v ߍj`]1;_ly_ʧH]TE+>:1V~w5_%jM-R*2&_*ag"cERdzqR%ѿ992ٓD\YPIUR³\uZB3w\!?Gg7|r =޻XO.jqZTrJ Tu,M}su\Y*GS 74bs*&-/tgˆs^ak̳PsŒ% vy_F.ı`J '+ ,TEyL+.Js}?ya&1 ̱d^Ti*ZV?,0nN 㬼 ^Q/WϋwYޏj{{E;u<€AZg ~4CٷŢ!JμjTlIYPΚ&\R5$Z^`;AZde=;P}^Z„./3,'|b~N>wTwJVܗI3H:mjv%W䀘>$#[ŠiX'H Uhi*S+=%o'mб~VuS*AX5@ S=PpN}wMwtt:=9م~bzY2Ffvɾ0igU0U$xO`uzR~]vK\(W u"N.mA55ZRpj/Bjx i"}|h,% _$A=vv>yz7P[ҢH)@?EēBCcvOvO/i #mrT-a,f,&$X1W:V}#2QFR2^6B..P?a*Q2SPR(/>> nx <ѱ oV 9vA|w1vk"/}hK*Rtck%e)$LNK f!VP c_CS(AUF |`=r#<ѥq`rSMuڛ g99֙~^qcK3 Q 99g1as R$%Qnjpoz Jezu7w1:V a@8: #M4>WXxliH!ތGP~'3.ٚ~WB! vL~ '5ٖ4aDl2X\a{wXcL,uﳁ Lqǖ&46V2)!lvJakPR)NB̓ە>X@/ƶ'[ƠY!,Cul]%$2}HLO4ؑM(H/"ܞnAm1 j0k \^FT7'ie>kZ=Yҕo}n;2&ϙ3!1!!:6%hOQI2a ԭÍZ' !AЬ׼. A@& &F}Ǖs/x78daBK<ŵ)+ p>~>apBo۹rd|  ^_G`kj%u?C<שyVi1JcSq=Ĉml/ c6kGi$J0/*/~ӗ c{  cn1>o7+Ɯxc<>`W;_U iyb:u#zZzYZ&̲Oإ}m/ć^M!#Us>ۦɓ/qH~1|c™)ꧦWt³OO ЄJ4 Ij[?~@fbq9ݭyF&?f4H"'^އy_jʳaJo. :M4{ĉwy I00Gݓ5wh)59wȲ^;X<[${3Xrf>,5e$&|?PsAcl3~E /a:v CMURm+m n_!+f )oOҭmdXRB.)-hzv-ͷ%걓mYeB<Ŧ1Sk(*ˇ+{ZF!`N+(f1Z5{a.|Ok&:ǘzag\fgX+`Pשz=c籂[VF]߼714H?ț^bw}h˺$&{:27J&?~歰X$dW97S$ 9Hsg58V?l0?f-|m qMHb{ADxIfd4 P1n 3g!P =$hg+a{ɓ sv0 bc.MUa~$&XlqJiHMo:N׫?7+X I/k'ix-b XLNFɝGؕۉ&06Yw| s/%ixj{PxÕc.;%]#`T[lud2L)fE5N e*v(OcgwK8#-됵1#*TdCb̐I׻M{]/vMj߭->W[`-IJMʻ]w\V Yo^a$zϽo{Ÿckk L,n fœފZor 9ZsFƚa~\xB >ly~ݘ6Od6I~&R_V#l { D2rVt*5WBfn XVwYHpzŋ,PeM1pFXA!ΤK1\3@{IJcQ5xj,4Q{cD0ɮǽ .%Mߜ^臰ƨM$P'l;Z&tJ;cV91b[;IMH|Iּ0aL϶ս3Ĕ!=:DW [4X~>Ӑ |a!$m4 ,?Z:{~pg,QK򫧆:.AFXōT?ݝW^=ڵKH&vۗaBflՠfw#y] 7Y^uy7|LLpfV\I?Ex.c:WRLz\Jfc&Bζ.ե|0['7AJTŧR?3)ϳ1GLx0A2j;Q;{vfb^_y7E$㧔Q[O>/yuW%%扗x/M9u.JNRVA|+ bpTW.)$Lg,aR(6@hW[MZ^'h7 \1[%|մ.|MZ~|#FCZHHznRʽRW 0٘ IiɮMi :~PJ>QR^)[08_"/^=J5|J-\~RXTB& Lm}!]{ +5sv"f<\áɮK3ۊ_bBVaU.kaܵ, 54^^",ZgO/o ?Cb>a6Ǝ>э!=􌱗g6c 9g3K *o Ѯل;hdL>yoT-ǓYi9ofsR,A;+; iy`{5Vn{iاR_# v>i4 رu2Rޢ^~Wys[8"+`:G8rIxY^e/RJ్zoCB.sO+ϼ {oaE$բ L`_ozGi _t?Tzzd+ߥ(G[L:§NxƬ1v0G93qudHϗYgXE{Vx@tğC5Š%>nBî/z\ VR= ƟۤTk>T5Yu\ ~k/sOeHTrSj<M& [5Cf`N{ +DR\9w'L)&cAWx9?07Et60_C8elKdb|""+ ?+* O'7s.Uq 2- 4cɢeMeă$ "4pA{.64%`jݡ B"_Jo_I".. 'Y-V5]g>v{@o.t l ͩ@u-s{߾~aQ{px=eJ8FV":(b# FdxW{ĺ&I #C䐸F=۽%!cetVF\V&林Њ5VeVT=Pw+hIZD+٠*2tB>E;B2ro,D49~bZ~_qOkN՜neS|X̀`AvML_Ւ) Q5}nܾEl|g'zndcO\jJ) N,Z4s&u~Xn!k0ʻ{wMڕI`GP`;@'@WJwݬ{LY"ɴ DB wV9X%X>#\2deg>pǩk%_#5m3$^{=)tUF6f5l!{``.lʧAm[ue= 8~1eCUO@j`;fǡOuŀ,TNlեV*P$T{\Ӑp7L~ C lǴ[wW>kL0 V|M1!: 혂%j`*VYI:mji: KŽ UN{T ztP]@PŨaW+  98g!I TY5mj]RxJԜle$#Yh&݀Ac/%fJ>IHzy0_gy-" ~~uPؓσ௬ 9|MPk?JMUR3HI 4`c0v11m+.D5Z%aQ&1u0yF>{*}İ!XmZv]U +2Iix Ίeq ~뗆'is>MS&xoiS*Gdډɠ#[̫\ >+rk= oQ0N7mC-̥APC7NBׅT)Fp)Y>Ӧ[}'?t LB#!"5E ƹzuCl9 j I-Dz#Dcmp?pXNleA;q&/'D=-~30aژ¥C=< a]\ NTPpbW;]kb)sꝣҺ\flOPÈ0ůPtu9d1\꘧/Eϻ71ͺ[VDsd,ހŐZz ]ٝg~my;x$Q!URZ{ca&1(etm.pn"VL]2of}/UK 2&uyE_h)h]Z?1'[a=k5:3/ǏU YZGl.>\ \2_99&5Phx'oє>2^g'O6ҏlOmmsk & ,|[ 꽶H4%OU0iqWjG~+*)ٷlQrĪ Wq ٲfqe~vi '̪im&2 lPUAu >CןЮGA7Ð֕ϮUQeچm?(H>2<ܪ WL6Ҥl35oDgSϸyNJtϽTSU+yhdooBSTuw}]⨲ۭy=Hc 'Wii+qݺAM]ҕNJĜݔQjmjS?;qYL9;aq ޖƷ j{6ĭi{tu~6P~ +`5|XJ)U3x5u-!C}axZTn {5w+プP{G(_x2D¯Q9!.1@-ƀ5ֺKb97YlOi홃Dt._hjO;xv bC#=K'=FUɜA"yE|0 @=nsp*y=cC݃5KstUcZqf&=3n8t{O)GVhsi|7KGY!LKn5Bo7"".Z.Qp;et}O/wՄIuȞ5*_]̷aTh/r/۟סD56$Y3iKXrِ(Vne1{'bm7|38W8%KflL(Ňݖjn&Ws\FS3%D,p.xW)fZ!^2ibIK$vv``M_8=O4w՟~A3gkV{t}dz}"9mye\Z ]t' 0̺W"h,nj5VgeS5C4of*up5=#((7*|0|nWZ" x:cu|=wЫf[w+3ܪ푾ej=^ӡ<.A{1вvh?(O#B,T'摒ܚ 0N14*K߯d)FRv :XR3nX?`ҝy,U `Y`1.Ά 9?CTh`h@fioVe,@8c|WRz^ z/Īs%!,#r6dĺKwUi̛w{L+,kWe`"%gBJ>"#{ZuRjIE kTKdsi24'ND_5㞉l[ TQS})^j |B(G$1ܬ5v>^W_hCdNLӎp&W/_3TUCK&'U+CO\gߔ_=W `XWWYy܈;orۖn!^5J9qü6& Y,&eys'lj%3&N E/'(-1bƇrWSp!/1ezI+7ѥIpYM0(==cB i.[m;95cbD9/su !=-o>Z `*l/ƟMmj5ُ|CXo  Gbe Y6Vv@h~b!t A_|6Qؐ%U^l*V۱jz1JG~}oFMzŸtܑ< #L2b\( $n$PSۨmEuGBf]cT>F C9\µCrG+^* +c6*¥E5O3z歫3-{,ΗO *PT>]?RʂQX%đW:~ |:*F9po".rسv('. ={"z2͹14<J[oWCCH/97?WM'׮xޙu=9NV9} NuqCOj S]{ůA4)P<~c3Aku}JG(͌+CjsK!mX/,'Y ZNC=Js,:#E+qJPgX"Ф Hr9SUyrЋ0y&,v =E?z {JeJ㝣.''ID4W kُzdCN_} >* ckOw>r"/((֮u=ԑ`4n,ˈbsq]Mwqz~#7$4@gw3ouc|vYV{䦚C_Wϓ'h6Qn5?qxLWL`/ynDD /4O/[pe]Na#d#UVG~U ?x%Tn b5t ә *d7TtFsgp{)=2(\ok!!:Lެ GCAswQog !͆M.ؖ;i1smb/ʛѣ˿˽ɺE2?PQm6յ*1"BJ|!ĭi..ooqpptSX-Z3N 1zKP%Gaoo?Ķ|H=(f ")@̕I,rXbo?u<#eM} vT@}3w, ; gn !OG^CEQ룯N6a[_3΀]':朐9o\\/zPFs G߂$=քGn?J<{XLChP R!?5Ͷ ?Z`gVgⱎpOtb3c!Lt#L?RD|vտ#~Ggv^ќ`\ Le|َytb:.G& @?y_f*6*jAWB1f10„r)w 4#Y]mקN2NϏBVA hn y|A(D"ݕ-2PobM&UĽB?U?Ё;&w!ppȓĆLi1ւkQbw5Ӌ:]݃G˽I|zI@WL mI? ti4݀K> 9ۄ }/!b!uR?+Bp q œe?ōx{9uFK'o'pa{/p<^ENJ;ZHWmMs3|ʩBlOSc׈O Nd.)7LR Յr kz$-~ rmfNq?_7vg Jӈhp<麫Yzk""@xBmQ\_uq9uvBPX" Q".Ħl?  F+FS>%u;EHGl*__WTJNi G*9'>vL4ّ-oPLǕ]v.oRxqNE12갥L=n^폡!9-J;JֽW-89y^Mͦ޳62bq%HNĆn"8D2X1ꂕO%Xa[ %Jnr^CA7Q1yN.nK4P>~0@4VL\B.+('UjQZh]=a4"1΄ojfN Zml;:]sv{yzy||A׃CB7nF܎#'$SR32Yͻ ȿWPXtA1RJYc@œ*W|Mۚwں M[>Q[]={_ |1s`brw5=刖b`Iܛu z'` vW=Ϝ&y"8xj-cNNE;3\B(he%&=i-@wI}l6M+}B|S1 r v[`j9ԗmcO}n~7Lt.5À+QLEX_u %u 43 &sK1mO'32g ̛#7JV}NPI&C ]v6L457;mMmrL$07'YU[6Q_n@Tmja[/yÕJօ*}ezț>0fS@,s])8J$"mf~@Q)SC6 :bc#S,N֥X/+]d]  ɀ.a'aPdžY9H8(8{nBC䧧`WF# kgEm^Ӓw_c^&J #$bU<|h a6 yҍ_ǂhmLw: Q3eQ qx#ڌ,:cE.(0Cbi3:( uT(6[.?`)' $5*HE ųYjrmz;7zZtaF-) oJKiJ?ws <&I݁\-:[QGR$NG[o!B~\l[X\*H8)cFC|ooHHutgM&I~T' M̓M Lws`.* @3YF7)]w+< sTH9}Y1z|2plj"'\ToQTg*h: /.mVmԴ(B..! \~Txʁ-FFCٶF!#OP~?k6`U`' _mg?ER:':q 'bѻ5F(eQc KlPva/Rڅ*[~3&Dk0x~P_pCG1 %NJoPyO5:FRH/NEy?;W%o8L~,J ~Vzk(rMN+NL& F)ZZr_SUqB|ȣMF!YEhar-ݝwjیY#ENS;zG=\  P;}&*U2DQ 2,L ;>xƴtĎI sc6\T xu M.)핋qwUro'T'`8EӹZ\ӹyQ< K¿^ 6s'+UŦH2 F5U%1Pa-ܦ[/U#mb+r]nbC! 'd$]1EƢ*SC%ط57q 5*y0y T0o6f{M4'SGA6P;Xo d/l%\а2m3=o8]Ww_ugو`p;"ތJAq«YR4js+ "` bx8h)WeNs)cT29II˓&M_-I8g*1,H%zK&(+Y_p_i*ǂ}`4xJ=op+kouCҲB-'+w2+> .q,?#88OprXq&+ L̏griĴz&ach*Ted_Xgw'qOhWs0pfۡ2m*u󦯣Ra?&UF@Q2▙|9Bh\^|P q!pe\fyaqiCypk J޳6yx:}3et\]Oak3͏~SOA#FGQ:؎47{`mla%<|6EvDTn OԴqrB g-.K`M,ivt[+}6Rͩ|}p]3fj;6z;5`Aʳs]_ lZgmmޚHX ey Bt瓜3#,3e G$BǨ0"]M#O7%m^smU=VrGKj˕ Z΅o;>`u?rއͥ"~#Yafz/s)4hNbt_`3!J܄DRkPo4s(4EM !~:P1$q6y)3 OȿqQ&ɪ00y:rn@ @*_63&2QxનV1eC JL#sv=X{rW6A3Ac?asQHUHFe=1Щy$(;b\sX-D)eE3@ ν%OM-xC?!lA_z$+#{4UFg>n=1iGf ݡGopp=/A>* -] ɍèn &s R3|FpXpW$mzpbqXtNp{M/`}񏔔;Z._jw[鲘։ZSdfg"j1rĽ`HFNZ~$Ŀ6d7gGkGU 335XM͵-c*[Fg 2O".V>-7Cr w)ˎβ]k3Xkch5Mua?*e#Nfy*>>M|0U2HaD*fl6uý^͟-Ͼ swGzl|]nR뭽+<-r ghO=K AQA[=]2il_MGrL$<0NW3޵ #jΦcWN7Qz][.EA8( ! ~>z$A鷠F~ \% YL} A&Ǜ 11lw~ƕ =b3GoI޾Uo2lx} :A=nL"jd_68j#[u#9q!Dw{zF:*'*ue#r7?;vOQ7e $lha5Qsz'(׀y"#0%! > N+Ctn-!f*Uaq'+U_\xFh,N,6٬I8ZVNo"b1~8J^Mq+!-}݃LjDzR08r)`zrͬh%gs [`9\U{O3TYG dX b/Y%P&"# (&E/Eϳ7Tޣa#Bo*`5Pes}f73(-ޘpiLO#&򟘨%?H.i{d0gxiZj@ayoį?icSsfi:~tlT,; M[-O+VN9~՜oį-2N+0x)Q}rHt唺tfF!s2^0Xzѫ?RNDǻdjȴzc\ԔmP S\7{Rbgemw1ZrW|SI0eL/Bt5/Oz' n̎FFp;DWvlmZa &!_ ƋQcXuۧkn.H$%P΀B1=\QĸQSΌ/>oirA8n2=*Uf5?uuϙ1KjCbK ݄$ ng W|zk|ޕC[׃sۺɰ2k2`.ט9_O DbÞ2ƀo:x]+v#z w#ounx*"Wk\KǼ,5[/49sB%0g}@;w3S#7ƻ#lw H ~vxo8ن!ߕa)] A p9T &Ļ!vwS80|xx H1?V%:y!O<8y7`xߛx& sL D+$Ϯ'mn ͱV`ߚO8|05[a $~htxŠٛ nFvٵqT6lŏYC*Z^Aƞ$cmyQbQa2lT-gloko`ե'PTyI/K8vfj =WaJzuL! $уF`Mo]46P'̷(LxzU/!P#HeLfD&\pc&{Dšqi+Jxh>k5Du/z`NBOw.V%0vڦ6v+t]GIHg҈=ӟw9jo{/+0;E蜉Z5+YaeEY+cM:F#$DgB,]ܯ4*mupNU\ n2OYJ=5r+_09y q}MHD¥'Tsfy-ͷ,<'dƟY3>AVRA@`e,WD=,IOӘˢܱ+_>jyGMYޫ f}G#?;r= viF[D[Vf1XO.7=OE +ڹ#F@+[׏7-Ô؆_U.RoN(ޗI!}P  J^%9UW/1Q`7dne }IO෕{4ﭿZ[>Wbg罙)ֵur=r׊rϡBJgBB3rv`H5רGՉ+z#{&U36%0j;/SNsզLI32{;((2agȘNmB*N\1Kak3f2l0̹cV{Ggi̭ i297"Êkm\cά3EBn}+5v4>jHA5@HG 6wlҬRWrvY0Ol]oEխMMD: uUb~)YpF˕0+v&t8"JU<$n R^-ٌN?-L$+roS;168Q4"v urtLH (P&+i(mj%up}xvack(6"вom? c6j=R,bcTҲ B,+p yqhr5P!jD3fD$ɐR znG`ӿj#h~\D̬8 )kuGVO)-#Q*Z?S ꭉ{_>{QIԇt((] L<0u"îi9~m p.IX]FѰ BbcTQ,~4|Aq6V՘E뚻;Y(6'[l 7=C| С'2=a1QU~A~r۽nV@+h@w4Fg ) \x)'+9›[XRR!i߁LEf1_x@:61f6ޠ[`ͨ5 -P À7,"B,]}ή´in_e$`lc?A4eӫ s:ؕH|]GsQ& `nr1-MKy&`cG!T.5(5qAC9wy'đ}jZ>zuA=Q(AxLTAn<Ęye0HCCgìs ~$9Y:n85jM Og3~>xw3(w*!T=/ <=G30HDȉvWPG"g^gylll>e&gWj/ׯįty잼={M>Qlog b7OOj~$ͽSmJ%'y'>`V~@!S`%aZ2*ٮ%rηhQCo{(VH{\*},LVK+FI23UrxIΕ/{Qo6d7&űq,h[4]ϋq}t݀MBZitͣ,|6"6.%BUY"y1/񡊉{F+4]%@ҎV30 !I Bc.*5w6Dy폷Ő-W܅}}.=,%rEt]dSn)9'-m1zc)]$ ʐdK\ /9y&;'\ F?kojT5vZkU C8⚊[\p(OC(M {|0ػ=8˿wxt^1wv@wtRq%xV֬sz:%;%S{Wq{6J=AeaD<DazՉ>Bi2+'Zih mǤ eBz|p #뜉TXK2e}ӿϏl|7|raa8XnF><]їD;!9rQ(g'dQ09NjKhlkNY%`cH5g=)(O\J opY? X1 T?ZRHV{3^?I 9ͮGD&_ C lH{v(Q2uUӀc~ Uac`}Y cŔb%J؛a{a{b-gާ4[#{9QC9m-0t\Ã2c~oBwǙٌl>3Ƿ+`3AcІ d|zF e LZ%%%%%N̪̼̉[~ Z]һ$ vIg+x&{wσK ޥ߀9U):6Mr@튭7-3b%B0,v݈a=xwE3&* (48, F_Xd${5,ws>{bi$%B>umj2&~Xc~p6BڶN[WxZcloH]X^YCEt@-<_^oUrħ s&sVx~{̸.H۽ܳ"3|q7TC)E]!L?Co" v4Mi27_Jq3 9 sȐp<y;9EW}+&{~櫶 >:N vrگJ1PD""o-R6WV9n=N]+^=}LPC2apmCmXrPCZ$y%:]{C^y67#58_;kڙ/HPy4=chU+V^H8ϚY,*|rYن6/R6r)WPPV=>S{: n,S̓,62[G**VCe[ l2ր:=z}C =4kvǨrxM7-xɄApxُR޶IG,3y`inY9\26|Ȧlc!25Iγ#x%n"ZQ=nS^2lT'f-*t{ L2rwU*07'q$/B毎ltI}&PR"0t/Cϗn#ÂOSe,0˜uB-At BAW͹j+@NAS6mu1&a0HkSkޡ]"Mpph'W8~$呍8OFfD5o˚E@*jDC#jVR~階 sKɵ VhZcO_7NwHc39>4ME KWͅ]w;twLmUmEd<1@!vJÉ9w⃥Hݩ+u _x_yŠȇQJ^/Ei')<~-v&rch3^3б(PKB3Hy>HREV.BAS+//f``9.׊܂T42ļ5.Ģ<Ҥ̒ ܤ"CKKc6.).ԜLi 6 #LbQjԀdlMCʸu)+$'il `RyjeV 6X- -c``[r$+s0T,x i`O)r :0,h7;k 4}S\ҢT|TM tb`de !ư`_ :cX r2({bX!w {Vsgmd~k>0YL=d 0Xb _ jr &il F%&*bʿ0xD~+'/:XJ$DRF/K?haˀV &Aҁn vIT+,emD3-f %a6 fae j[`ہ^@I<`(L_('xj"PD5t>|I0錄ꌄiR||I: z8A&NpU`zPJ#\Pl3,Xdj"P3 .d6MɊ).Hp0ӿ@O9J\/,qPKl3r- HREVOPAQ.BAS+//f``˃` WkEbnANB~B~AbaiBqrQjjBb^BFQjBr~n.SYԧ ҥXT\YR`V_Z`hii t\FBpjNjrBZ&]]]\&(5Qj@26@!CeܺvC46m)Of2R100-X` X9*<\Ѵ_pp)r :0,h7;k 4}S\ҢT|TM tb`dercX/ Pw1ZpUr˂` =1,̻=6Xق`2E?Ma5e [/J|-PgƷPާPS%Cf00LSI0*]6QPM{`$}_;FAԁEW"!@ 2z\:ƐA+cHfa`,_;|`YAE.ʂ]F9l0[fCafXq<̠=`(1P@9 3V@&7 $xH X|FOLg$Tg$DfP !P0q ʼn8 Vnu&0]+0b`}$#̧_)CI ,#,|E&s48iHgCLHC) 0׋0)<1:KlB/F["@ [ J:6LSb~yHCe?Bľջ. ܧtI/&X/H  a>z u7K. !V+$b (´ ($}:HjDXP*1+h<| - e !ư`_ :cX r2({bX!w {Vsgmd~k>@#/&9/J|-PgƷPާPS%Cf00 `T l/Ï|0I 2w">:EDBDA.e/!->O8PZḛZ0 jTw/`>TKPXAe.`l#Ҝ ha6`-A0[}@,øfPHrCxLg @q  gc s ,n>#' 33K3(B1P0q ʼn8 Vnu&0]+0b`>ӯF"9`Հ $3!!”oErʘ@~=ylB/F9-歋%)V~1e}N !b_AՀ΃]SHB:hD iޏ0 pYsPadBrC`#4(b/Xz;f @a}_ # åjrPKLr POWER1.BAS+//f``` WBpBA~yjBkDH#[XY ҥTXT\YRF l r] ^ ] ! @T 1?7$#?EG4O!DG!/$U!%<Hdf+$@@e ~ F]@@f@UZT =gRRŊ ~ #K2KLLI,U(ՉlZfnBqb:vW5u4AĜ||ɥE% gƐ`2'P/:iXjY V -c`c[(XPYPPZ t===*1 d˭f`ch:,z20/zQn'QOs3E <|Ue~ 5 7G|P?xG7&n7Ǵ 90qts`x5O,0bP-.&ĢHƊSH+K%uHJ'`϶6$E@29gdY0{Ղ@#Jp$҈4b`PNd``TZj0Q@PK7 POWER2.BAS+//f``)` WBpBA~yjBkDH#[XY ҥTXT\YRF l r] > ] ! @T 527$#?EG4O!DG!/$U!%<Hdf+$@@e vL,z `e Z@Fd$(]YTPR`6+37U8 dH7ث:I twbNqBn>ІҢĒTE܀3cHY0{ՂAz,c,P101-T IM,NU(O,Q(IUHJKP(I-lPCV n3014w =s=(7DƨDـ姁o9B"``s`\`U`C`W>ha [2@N35 li #9,rDyf#3L',D06bP:Giyɠ|IwV`u\)V`Xx٥H&g, f/Zb[ N:%(6;(S+,ZL@r9PPKzY. PPSCDEMO.BASUKlESJiѠbMڎz4i8 G{Mm](J"qCJx@Sv\ 15F]lqQ*趃qO+4\My[@Lw.@L@CЮ fmiܓaF#_L-Dn ۓՍ[9 &uh1:92MgVmH7~X2Q3_l&:Nk{s1u%]V=p1Z!gwI6_ X]gKyW%vFG1BCyv} ('o־ X.#C ޮm!-xHx,¸ :Ptk>Ely Y 8bKDT U=Svÿ2\kbKSR99ȚXiԿb??Wq )p -꾬p%z?{jo8& l\2MȴT||6GUZy Ͼ| >ȱOՆVSf):҆"t} þF 92kB.m,N ooq0 =@|t,\C` v̗^R{x1{G#.9'Fe>-07YN яMQo}2/B Y.mI_ i@ ZσJD%\cxjӀkz4MC=%2Z"zuQ R^of~NyȪMupZvY;ԥ,Nʁ>ߣʡ7[{+ȵ d[  |*x:MȧkC+b 4'伐W`PKEQ PRNTR.BAS+//f``` WBHfINX)100t)8d)|J2K2KJ@j\Kځj Js* --v0hդ'eRZ[5?M(H!9?771/! +eeV N;T/z,f,P100 3Cł? %!A Pt!1014"ŁXGک՛:ad$SD@ jX@QjqBn~iqBvjBIB*< [&0M6l7؄ AHFWZY\ZTWSp 9\A$k)dN f0RpHMΆP\XRZTM< %?%|@Qy&% % IJSHK)j(·+wsc`XpKIO!3M2T!#,U!agA~~y E 4<3'G85hYIFb HٷE)0+JMNXZ\Y V Ks5奦\ ;Zc$jY ap3)F|ǥjr,PKL3qPWR.BAS+//f``_ ?YX{; ǯˏ֦-k?ܽdK[|њ\QJ8>J 8;ZZ$xܞ<veL߹eoiǭz<_)/p^ݴ*jU*֣Jok&pMoԱ<+YǸ\g.z)q3>uN5 / p-""ee? H~ha4@gUYiѿb qz w53L{O> +M똸z)m.m۱AlqO.k(𦹾!}Vv쒡R|) pn~>7}ޠPKkN *-Gu(>ݻ8{{EYsWR noUOyCP)'w [R2imZT3P@8lFv^g_lߢ/1ؾ+ow4(lӰ>9m،7[QO $}CBCGD8@o:aL &=[b«i2 ТEq="pо&F=cv-cط"|ga1|Y8=fG %ܮjpWQ+7E 6\8(ʮg2LQג? OP3}az! 7L>|ޅcp]9y ŋ _N-3-onYwWm=Gr*>DO;` eOvBK!pjo(9OʴQW('WA%;ف79]\/[r .{W Zxs]e wslеX9th9ݸ%Q_1wImW:]|͟%5di=/Eύ%0V/"==4T(w7swԁv{>g/nKϻn76/V!!$Qu9|sd[˝ 䎆c"6*$=6 h|fx+ۃ.| 5jи8xNtp1"Jac{|CSwA N3ԫv=$P-x2dRpuVl'7Ȕj+:ޱסfl3i +/xoX8D[UАEɂ<FD#҂SIS(`e %Ȟ5XC9h80dSsPj\, ߯`INgTppEQm4yVZDu-VHC]o+4 a^ZŊU8cZX4F(#0f#^̴SqvHd6&S&0p76Zm)W7B4ZMI\4`jݻ @JeP&s SК٦hK0Z=DuuZwwwݗw;e1{*gQr`qoٜoK_b1n5|Z[o:,.җC3d\EUē30 7$lTk%7*ѕ9gfU27X<0cM+9J:.GtaZDZ '^|9R9={{X]iffGZ;Lpː(^eooxtUeq_Q+lX6T3/UQ<]|Y]nܮHwveg߬WY'`fl/z>,ŵ>oxNeX;PتQ\H_Ur[gAS47teYuK+i,KSSZ=|YhjU97N6)V]Ry\#q5Uت 4Kc# jl¶XQh,yU-%2elllh]hWo3{CiWR9 ʽ +?gϱ52RJ5EڿM(<npn)USߨ7YmiAɌ Ir 3[1~W%/v@mY*m#R~TM$RFaiTY0ns?f Hz+e5"{3N1 Y˳]]C}yK}MZ5_:<5bYͨm*<.rM_qTP孅{*m)q,˺ZiYAX L;U(զ zeld)CFȺyTP~ly -2.>jdgH=ZP(]^[෉tK׶t-(zlHPmrG1s#$•a3ޟBXyغj/Z:֩"}cicfCNZ[2r6,_ L{G[4vp5lQ(Te[5(*.q I`3iuޕTg@ :2s˺e4:onohVeM%oPDɝ~q<4"Q,^H3WWW!Ouj(=kC[VU]eûbÜ,>$"- 6di~F)xB7Js?;Ʒ/ж{]nwA}z0L2WH{f_ZkZ)@o )34Ms/Y)$)@Ovݚ*E6;ƫ`sv>B9:IUtUty [ϻiSUVG}nIn:+p:!2,hP[' TvxLSwSh=Bo0(~Qѧ qqx(sú6-\%VQ{M7ftm|TqBg7O[vvӬzlޭ qSk Ptt3:}BgQQGeUh8I`k+WCķ[xc'W~B#)M( }ju4}鞆48hSc|ע8̺k6wH0NJL\?hЖmoOصEOoR.f1{_H$ϙz!r _iZ'zmloЬuSM}ajZp"'hYu3T;UVU%R.UK>2w3z9p@;i| u;ҊWfJpL;Sx!ٳhNC$$É6縮\'㏄)΍/ɱ'*1=v (!Ell DyQ'&< }ܽH-?ɻx$_?D]}t*TW'$4տ6Ckߨkgo|>N|k6uv1xn@FvN_d@1KΦ[;`S3`#k֓05~x>?e1 18x:)ss ं͏gȊnnmf+(Vy:Xĺ"}yan94#-9 V柉բ-bZdZ"(X-բ&EIUD31>qF*Vb(kuh:F7#Tt*ڦPѝzXoEOPȧ>6ECX\lY%/cQ}lbLuɿX?Qwa򣧤h}Y!ZE/-}KpRmHT˖BDQv)f51+1g2UbSl, ~)=8One#a54A^TLT(;qR8vl({BbjTllaQ*vzùF؅Fؤ>JŮb3 Ryhj]܂Q ’,T'>^:JF Ў׃Wd-_>SEWCGfLlTe '͎Y)ц^6]E-=> (fFeb˪PE*?Zk-j׭fYoZg"hO7g4s!+sdZ3G KÚ,w0u 5p(G%!SqK6Ҟ,;U:۷ %Ϳ/{hh v`ڤ2U/PFfNi&UCuXg #nU,C( Oi[SÇҗusWՖ3t~3ti6zWo9Cg9C&n9\fź_2{gwYk,ãhQ X"J]Оl8=Hq[R95Si^DQV}! \IbÉvml W.{4wt2MLS)1t2ʚYTN${D)Nk(LFwɜd#$SY3!_t::-5vO> ?1%ғD!8.Y 9z&<ܸUW|~\yR`9q9G#Udju&L͆&S6=Lע慡sZ|ԃ ECzN֢ԱţIQs)8.djLoIzN/5+:ĈbXjRR85[$-{$#rf!2ODU'&Gh%VvNߝ/_מu| x|;;±omfl^+RGY޹ScQޫvﴜQ;ޫsIxA_M>Lڶ j`l5eiA]tGe/5Ҡzܗ9+y]YKطFNJ:pz mO45y)*]ߵR.e_кwKo1iCbWܟPKChB STOSPIC.TXTURAn1 S `(Z-6.:iԐÙvݬw"S%_0kvG =>8%1ʚGq`O\%94[tk5+O` 9@@a|f5nfC6' 8ȣo%fd&hqJ)'uȇ'T@KaS\cMayl0oaBJRXP(.tX`T5%DnFs'%P-g5&E"sGk Pp]x3󢪔Ǹ'RM:b+qN/B1.)qsIΝl &݅ s 8'p@Qni`¢ ihG]M3bpGk)ѳ??PKG{ļL STRINGS.BAS+//f``;4Ղˀ4Ȃ @ZAn&XHpU{jBBYjQ1 @a_ M@_=@)3"58DUc0Bqj 1 6S"!d"+H!`5$C5HA\A#H!'XS!9#H(3/(+O+@]YWPZk ĕ]j!C=L*$k ҄ !&s6chZ Ⱥ`Ⴌ = no>RT VOxbp/cد:z5܄)fjBQfW\ZPPYb<Բ<ĜT~1!d'P0płu;z4~a!ý >zpS70dfB"1tܜp Cǝȉ>a8bChCdz@1tZp JѠQX\ 8NˁdVHxZ]z tZGLǐi1#Si;r Hck=PK {i!VI.BASTOhUiSIB[vAgmDT76MI$ZzPgw_vggy3$AE^*VsQz^*x<ؓ*Њ{n:{;|~ެuǷп^쇁 g1<:/ð7U76\ϴq/'0j L#xʷqѧ)x5`Y%Ez5oA:82,9Jvܸv>-2RW*dSC"2.cvհ* lZ.Pa$Y{P/2KpjrxݒenuwM'z%A?p!|̟+u8Yg2XF`dzd>D'NZp)k[DFI'NFzb[?h [Ǥ-gGo!w~/PK|$~/VREV.BAS+//f``t` WkEbnANB~BYQjBr~nnb^ HobQIfsiRfIEI_~YjnRj16.1@Z-8j101e`>2?J@wcX_j9 GD XQڪ ACo*_h<+ M MzVH$EVA ./ٌ ze"orPPKTS: WPCHECK.BASMlEgܐڐDДzi&"!:Vb'6]kw]P [? q8DUP!@5ГFu#zw7o=O5rabV= ?y CHYBHWFrv0aKzQ)+c("_VYD:3[̴w U+tD'|i%+E2L R_=- + ݯIgA1T8L~C"|qsbSOޙ% ԩOJT_GhR'n&٤mla lr4`@RO1Ww8iU^iNq;R\e 4^856T${8K Rwz`~!k/PK:UiWPRO.BAS+//f`` ` WBHfINX)TDKK2rE%y ΥI%% 5r] .%@5FF ^9 @s4jR2 JWqH-ښP^ _P_\``ӥR,+g((ey% eE @d`TYN n] PXX^WY\W_Z]Bq%P$(_r4; >% y i e`O$+WT JgWgo_~1`HY0{ՂAZ=Zp`ՂD~20y~<d0T)eiehZM5"$Q! гlb iPNQ< 623LYd8l"PZ\_Z JPHcaF '&M\Z2ݥ(,$rH#KJїS U` D2M5EY~5*wig5$*"F +cts1*YY-X6G ZQͬ1:XY^V`;C3n'# EX쬁 v0΂hgP@0E$[g0)F⹹LXȓP89mZZPKΌnB}CH4.PI1\{teG$(2_tȰ>3aH&"Pp83<e  tRQr'T.h  qĿZF}!6"S Ŀb!;h~#.pؐ-qP Q&}O$m:J;6<#8>v}XrΥr4:(m9FȺ\ ՗07m-Ϭh+ɞKl˪,\Het! 4{otZsۃ|/q%ȑOJFd?/Nx"(F5fDg9y/BX.`Itƒfv P`>ǽ-GX@7`Gl7_o~.kY4Gj5_ 9kƁ/l<\\3N-)Xl|An9k֮i\ӵp%<:+lSޣcjX6 p'}Y{Wot/ķ@8G6mrCoMg=*gY^a:ǘ.}mٶZXFO[p5U˦mݎs:AQ1cόQ+ 9XKw kC7鹦!hlUц(3?O9ᜂCk&lS=TmD>[+L@=rG,r*h-d3'߆J[h`m%*ɮU"wrfpTQ|$~`~N}|K|Џ"uD@=~Nm$(_ ,J4K uCJOT}aO~{|'~ k~J:YdSV*pJS9'dw(rZnA [3_CXC{2jdF|68EDwO#qP(7!L6㫂Yp(Dhmq ij~_(~)t؎xm3D6R4a\HK,w:}V`TPz_*̂G]=͎9,er>?QM/nk#Gs1ΓCǕ]E|'mPɿr)hXEQ6!z#W(>_ "tPMP(5pDp.ťܾ(v0>"؞80ː㖯ih003'P \%o6Z@ rAC7db,6}$ 'A#bI&> VQX>Ns[w )d8 dߦ?,܋WiF "-FF-vˇ7!2.n񁧚⎲;뗛>44</aj#/Fc*!$ R'd, :!@zO)ŭŭ ߫0X%GXMIc.7&MdC— +|)S_[:̡P;J5niw絊CjbƎu-+u-]J+G';B )0Ķ1Ng8c%)&ԋ["6 · D|mETrX:EJL~،+i=gח9;>LƢwyΫ]a]SȳЎgI͓5O I)wwTgԾ8<[[EٜqW" XJ^` ^P`늏jH>1l&+r_>u$}[[T:}p " QW׻,0 9:}?U z){=Sc~-?{in - wγjb)lCZj7~`=xcUx˃#?*O˸uc&ӆv%B+b geT];&x0w)x<<;1OaRDD1hU*rŅ*uYB^c})/2(M$#l|f5SƷ I@OL>d LK/qc3恪{9Y~& s<x<_Җws'>ޣy` RRs0ގmPA,eu)6a]QD6='BEP!/K\I R~?KW:(k }"z&8]]҆4x'<8)}_J^j\68f2-=ńJ˜ze+5[H]>+sPȤQ&3 'U^%_z.gX7* |4_jLRXXYeqK"7ݤj&f4df̯`>X+%ᡚ?C>M]08ϿD*°-|%/oUXӁ|T4 gZ-%B+MÿYI7O/ :$:=B.Xr,=%o&B/ws?t&!1uH(EIطtqцП(ܘ>s)Lŕ-0#ٿ!/j?+P҆Id(ܔ>< }:w"~fYs3|s~y a\?IEcp:htu ۄH"Qg%Ju_ Wf 6VJ3|+\Ȓf V5QEEnbζSNcNn˄t/6(M8g|`9eHa¾j7[' vawYP?ޭ[=GWԔz.AЌ}\IEQņ^JQ|Dެq pBq+&?oYä =PgưV윌f)Cgi ֍ʇiI^d7QnЛw:v ]Mޗ;#|<3i34RIeyx4o?OD9ݷYҿ\X 7}sU?3A >9ЄLp̔GΛJFq0T@-; ЅXeJ.cfc|g⍾-ls~c,Wɲ+/u--x$2,"S5]aw6#Yp0ă1Ղ ?}6>-ƷGO&)!n['gv#QYk 1Z9LWƟ4!9m'X J&8-ikImz|ah \stK'gVѫ\ؑk_sT9iu$*+JjݑuGS< w|BmQ8E-us1ch"e>Ke2[q;)1|/Nd㫓@Q *ӏN4rٝ_K<o^] yʵP+`DL=g3!lwPEb;+hL?^c_Du>Qi <gp@ekg)j/ǧ L`˔ZMOb5-FQDtH/hU: P%'b0uC 4͜16r;ޘ~F07YdIYubu9w`oc*z@+5W'B%_T.ƅWt\Cҳpi/עv۬'ˣx| *QravྪB:,AW`*m>"/b#6{'8 h$[+Ne,8e ٘n0CdfG)]OKH9Ld~FG3{1|~"vc/ 4/.Oދn fW'wtZxQ%(\v;k :"!0Ƹq}|!s K9(>(FYʫ:q|6 A*Mc2n|kj]/0::7 ~zB\#|9Z |6 H4/Nى =n;l Cfs0>q)$$A~j1䋉ӯzE{<Wf_viOZ{G^c#D+\5|e}$E-[5%6%/fN%AbV%;_ӻQJ>w,& 䐫Jgb[11tW4/Ʒmqck&' 83Kv8|Q|17v_1~u<S>_#G% ZャLR1S%'-}>8v׸^k/x-ӖKId?f?a d6fglQK{k$Wӗd2A:>gՐ]\.: z.u+{ f.ho _CkefoݢƚiCINb;%nhRy#EVȡG)qN,UMF55VJ%@Õ>{m[Cb|}$I&k/~D>8FUVWEH|.a=5IO=(>_(z pL_RM-嬐+c'=n]&EV~ S# éuER$мq~wAH[q=C/!N,GxaY+|‹)|~S9/4ɿ3I_H=~6FCڝok/:._,>sel6|t7=P#Ǭr'{˹CߜK0V]W`敼>Uuy2S/c8'ɜ$g''+{k{rY 20gN G}YN-:rlL%?B1BNZͩA@Br@G2o'/axZyqh;ac$/r'rF:n_G9u>Bz)OE圝]¼/[4ݐOo8*.1ĉ~<0,D&tc{|=ZKTR]Zu݉}BʽCHH;9[+Ʈy3-^))7W>^癶Py-Lt-{8xK`EkL5 ęEw~蛹=u̡?}Dyc?XS_{ ha]K*w2B7g5zqHY$) ŐE9UlEOJ+!eŠ8my)oVv=b8[4O+&aO@viuWڸ~1/!ڢ^ "Gz"F>k*~?-מdͬ AlatîW:mD:9tA$:=>xw61uPN\8iiG7%p_ˊȌ"ٟK>hn R:6>ړ>Ѐ 3S§}y)>iN#+s kY?%ϸ/ |+oZ4y!nXH &{ϏeCfgu%Ki\}+MzH`E&c#.6$Nd՞O_^2$?ĿrY뵴Ȥ87?ܾmoV~:~ i2MZ;9LI/ JtۼI:vBKX8ؔ"燽3&?S),X|PH%7[YZL^b/d(t KvÓEOjs4 i?#NG4qϊaX?rY3#Ifԗ~VW4ͩ<> 3ӌXy%|B?.9y2_Q@IckWv+Wcي{Ly^Z"U r[_tR4akf8=H}\w$p{ʰ"3;+m ];wMcFvjʁ6m_\vAZсwg!yTJC髦]ң "? M#P+cQl?q^KXڽc7,w M'mS!^@cDPbO%Ғg ,ꕾd,.Ky/۵-w6bOݴBW1E\E:=/WЃgĦ&XԹ+sA* mtW;sܭ`6qf(roҋ̨ޒCkfDs_xވٷ=/;,x7YI);R&.~-'P:fݢd!h^T~*4DX~?4jAzF5{:.5Z<<__e}nQ#Og2 Ei/IdçcZk=]%i`Eњ)7ǷlLQ_[ids|=CbpB+la-llf|-4^Wĵ>᭿7RoXn؍thDc̖'p@?Ш:0FU n'p13I$NR,Yvd?o -a=HqOb~ zXDm~B//>Df++ϴ !Q¾invWKɡ&OB/`ѼfCL[apx[w+a)15yR*mL;K47^_jW0X_;N8 Rjjm3,Js>2=TOL-~e=!vjԯm" *sbu vx3y W$4k_P qz!d^߻Y(=e [|B3׭ϗLm5 H÷m*)K>3 `!~*&bq}fksoP&C`M+o쫧- 8}y7Ru{5h[VMIZ/wΊŤF5=._Z !C|⢶XHl&- |?Is!muGR@?0LMWzӯkR5 3ݻ|NytLjw=_7ߌ:(WjrԮ^d{Z&jC]õ-AA:f뾣0JW !6_0?l_tݾ$/R6uMjoԯ5FCV=/rlsf%Z wyg9F?^c+!j:Ej%oӹ{`lfe.,g#bDjC)C&V8rWn|-; _kDގQKӚçw09Z|\_Ӑ?tb?@z@oz/3k—qܡB-Z}k^V(̡>;Zߣc3"%SrT׭JbjD]ff)5ujPAl/X׀V~B:an*R([ڵ sAmzyCZڨŲ2N-PN>Ѻ%<'<(5-9H_2lX_sf%ǒ{t`"k/4~tI(ʞmJӫw`ks|qRXVJWuE]^\!W(;*3Qʵn`M_s˰r9M]DRKZ?|$ȩr[ׅn;$s oEEUTMY*L&R.Nt\yV<|y+]Гd[E>H| &}*\2=p4e=r6ͦ2*G׈#:EAWpNS/ZLNGX~6N3_qk}Җ3́d/}[18M>v(n~@nI7Ԋxz|_ΰd/Z}zM}]f[QW0R=o'\Wb_jŰcJynK&eHQnVPf{/_l+< ;7^"i^Yj~3yI»uaR].-)*t|kFY-;BPUͤ%|w]_LIg$e$a|u}kUڹg)KD{ZP3H=ﲔ}!\O?(#N8J2l|υ%4xRZknխQ+ߏ 0WH>*.7`i鮽Za3e<o*LvuJ"z=_6C&|FAMއτvFpNbs(-<.!G~<  Hy#{L'њ)nH -UӨ󍚴ysjTzTuӅXVtszTRZkJ:m~$LBgяy{?xeOFg.l* ʃ3x$+ :0胎e-2J3Q4L>)Z{AS!n O zۢ b}5rKԺ4W$^y÷ymp?/_)$>JWj24\:*|aY ]]tYz/TԥdrxduӇr o}n#6ۡZ/|b#(4C꽍s~}{IsE^%+(CQװpk3jȔ"1 mzj #yM՜p^-`U{P([n7ӽ8[,?GgE7tПxMD_?<X\Q& %:ܗ7dW{Q>)P/)ѱۗ?gWٸ^h>=UG<tH^;ܷl+&)ox[љ =ۡV]ߑstۑ%˧Q!=o(u:KYbJ&xTb|XC{þEEO*ɋV>l&'[NALj&8._H߇Ww>bG8Y| o5U}r$H]Q)2*{_θ4nl[> >kx[M𻏾3qD{Q۝:._r42BKL@EԶW8.qp(N4hClT7^, U+8>3\@Xo.ϢE Sv3͇lh!ձ5-7>E?{+Ua]=.|o푹6pហ;=~ՙJ`&m÷o.hRq5_ 턨WA+h˩W]># wOs.Ӡ9l3WPށv8ӦϠ7g$=9h+׭lߣ"H!||+ w\t|dK" [eS.ڿ6Mw-SKyߞ}HNu+ri# SF=KiYg%ICNP*<3iΡ{csoy=5!7[UiP.}^Sw(yqV wNJHcFsN;ql wE=S!럷>#V|6WINK)=i+"3^3]fѢlŒAĽ^)\ѻWNA!Jb;k,l!+7N=贫rd[e92_Yʳ6 ?P9{nm:>^}'ZԠY}k]rޞK^]1ϼ: :>>$ƞk۵-mA©b5h!zhgcCJ{֙} # 'b(XlIxec śyU%{3K7gvF"ɯ'44PRQz/4y^8Kf;_C.%A›ѯ0~6rEמalH F)"gfBZ++?IHQ@D ?󵼞>?}l##EzAC'XW'-sBC}.@`$dž.-c rR7 x83ZYv!T(E; ͺA!nE8 h !ijH>>ٸbSLQMb?%,==2쵝gu.mnJ`|?WvIqC3wP$k6Jq9q3$h?jRl[*HHUWڹ1Ғu1'YNmk?$٦X&՛oqfŃ1=džR zEE*J >IFbo7"=,6Rd;R{Y買s'n<ڍ$c9ZhSp0@m'%ѣV×j,flU*'8?p6*<~&D˽<9Ɨcz?2^JRK-;6\Hʥ_)K#`3'm+e$VkՏ]\-T|>2fraFR뢺`6NtoE:ؖW#fH\AbK^Z䊼 .)*}*W$|C. %JKTΪw OucGdXݵDȪ딜|}=9?\L=Ҝj ~knCx,&Aձ^k~f-,Un/َTb"MC57+ٻJWyzOՑ>A#[%'JO$,ɽ[ i }1+E~D[/A/Lv@fB~.{B ޿V20!2(>O7C$}74SeUջ'>J@u5>n2t`pTۀO-Gkt@0HOFiu㻦rQb9=^E.dWfk |FNu'8Nv'9c:>īgS POkZW|%eP“E Πlo)U肫f-"3AS!>._7p92KMA GL6rC޾[mP_(|STs|9U="DXI>[xCmԾͲR>f5h}`~j(r+ | 5SH ]eEF#_ i:Īqo^x=U sorZC xd5qgg r;] ӶLU`SBz_9q K)z=-(uty`db $ȧ[`٬П[ZWHRe&brGu hk;`)*6^ḡ\`2qZgvtg,TUՔoYɴOdSj^8wpt\lϥBy34GC, ټ&"Xh,#{MJJ$Z\] A7L74?Q^Ь )>eΪ{oythTC0/W|gX"( fݖ?ۣN?x{ݚUgVO=ÉkcZo)'+ŬSoř]T;HIԐ9l tr)})\DFlwoq\vtWgL֚h}[:7B[7xwٰ3Ԫ2'k2*z4 #縵a>>>W3م%$ CRNdO^\ߜ@iD#5-zĹbvѸ m/bH6~T=e3XL+'v ! K? ; 4`L{O3Ro= z̿HR·zaǡ:tݧ?_xXlT"jSHKڽ|3+S%$'{Ź|}`z6_`zBoM]8@Y{i~*Vl8LqOpg=fMw93H5~{ϐn9,w^*~) ̳[)Hu!!8V dL>! |!7q)Z* - e;Gŭd{9{{J[|uڼ;~zvwUv:+|g|"N~{E޷iA$Va+]^tk;=~ѳϤh2U%w:"7wM@^zkG ԁm%KqޯB~҆)k ,Of靇eW>%2ÕLw<_Kҡ9㿢jZ}=`żj9aRҎߛBֻuޒZ=V8xR[mEu+G>;RW.$qt?r,Zڐ~'P,F|—{dv{Rڗc{Eәτ-'gsxh$k4[ MXvA睝G9ܧYk+PZNo}K>>i+E ˾n *H=5|_wxn62 g^BQEP/tǐMz uq _ڧ2ljםPZvrWJ&IhHdj%DKTl{4ލ7tQ[sncKo a|G&g~_OzQu-O9_eGzGaF%i@Q<}rmUG6nm"`,Rs|H}2 ҵS> *n f׭Aw:©?sqt"MU{KcHX]Ґ!MO{}\Uh[հ4Y Y:$dZvݘx* PK4ߡch}RACE.IFF}}@} $ 5(V@T@D:.m]qTlPPQڊ3XY`uKPp F!!ss~ ҟ=9sΘ'"Z1nBĨ1!J*+ }86_~EkBaCBUVïZmTl'|kvσ_I+ ڻQwB!ФwtQ2!{"Ұj@[kD-־acH݀uFJl"ٸ!/xm.:]ynGEn^b@Tm4\O-B(uu?@B3~aǚ4g頏e"/}iدmM=Up]znzcw%-e-?;t=2PReKyOSL`_Sȧ,z u Y?!$E||aSZqr.S}a'?/*XTR{=׹1cR AP`|3FN~ TOGo'X%%hmkav r=.lyقs7ChAn2K+h4⧪oѾ>:QHWY$QǒVG戸G⃬fsj՛-hU+PslCTѦ/mĬ:@րJmNg#Mؒp#\V9o+͔56eb ,\ުvLӄ7kě~x%EB^Nͤ.1J"" 6@eE>oc07}^+Zw*?'-K4I'(z]MQrq Eߨ6=ǖ:H0 KkrPlY@sn+#rAYOG;hLRd5~4:}6xrY&КjCN(łM3cy'+쎿^I_/D|ȹicӫ=5h37k6n.Uy1mлIKwr3nmf 4)"R9 F oxϗ>=fob-ë^"iZ.O/FjhQo)qy+. 3i?\dϦQyVLV?6]dUVMsG0M-9F!~6P(H3 7y,\ȇ?蓢_;7g?2TU[ݐQ^"1N/ 3F4{vB ?om`\jn?+Y3.ڶfȚ>l 0PUV }OBށ}7׍Mwo~ލoYd^aׇ>˗H~Peq.QzOs}h+{mXa'{tkko,2iMDnj*@U/U}XO}QNj}xAjbw`K!␛vZw^eak1m걬L%= y >9YĔ uB 6꼉Y_BU&k#0¿9+l07˹B6]|iխ"~Yi^S/o*9')˹@'JMn]jizfW"РSE.2XngqڿΟyȁEJN2[12sk?w(| d~`Gn[ow]nؼ?k*Wwl3{ Q EONSZƘ1A iق}*PiA牶|(3@+.; uä6$ -7%uْ'6Y *w`ʡ<͏gMV f3 胲 DzG[}pZaPwG:wf^oru0\ҾqÜWRV&_:'=%nΦIdOev޳о4KV> 3@fk5/t\%+l;)XHiʘp$B2Kt?BEb #QH]ɠ*Qu^Fx87KѨS ~ش'/k~bC*ܨ#/-}m̀W|1rYCzA됌A#ߩZ}PbpkJ=ߞ?EZˌ7!YfƤ?J_P=/cZK BGX7UhwCyWT Q?)<>i+ƖHc_w.H/ϻ`S[JHk3}˿ٳn59m];iHZ1_]]ا߅LJ }guf_g??gjSKJ,c͞i[}6C=iaj޳Ƈ[a/ά)r6#BEZKQV*sݳ}dwajJbY'yk8[9_KL F-{ ZRTZYp&qIj E.~b7|Tآ? iWwS j?_6b/knwssVN%H}iWzBH"K-Zx9k]DTqT /[gy| 3S/:Ζ{TM#uE_ZgQc( @,v̔ WOٻ)o3YIu/k~/Zw? 'ԥ jrWw&N0/ #j=^ZGJ?BהAV,$*0`-jw8=X# -DkTQ">0Jdɿ'ߒ)D濵q jA0~;=R7cr^76_*yoXQvtOEjɿ:7G<&aX4ۧM:ȓ/H& ="9dcֺ_7{|?˩;wd )C_|}@4u?{u]n*!K@*όeayΚ~Uԯ, ap)cg%Bl|oENr<;d]b!Q Ls3OUv)y*5hA'˯癈q|x#m!R;Yq^O[mnRfz9^m'}Ypv ϽS~b.?}d]FdI/J/nN2/0Q?p/\3 dƸdiJa7P*{Q[ C|)~f;賄8J:z4uBD1iQÁ\1vQ]w*AiKC^ۖps%+ לT#VD;bxf1y}K)+ "l,=h 9Qs|WC> }CԍsqTI^8`V6J1bd%(K|nwa}:):r $l}`;cC[s-4K2,j7_n"gnBb-lSK R"aCc`]K9gyz(_X]9!}25YX䕚 6u7}v( 3Qi0-|1dlk::%LEa6d2~ nm¿D6r?h;n,TPo~juv -Я>'ݦJ.9=EG 4G;5U6L*DT5$kk3naċIf,DJ- E۹BMȑ"ƳRim31e*%BJq5u>v-TÊܥdڵ G9NM22R^\ 8l+B5|q p@ .^D4L4zB ˌpGmԹ@j i_ݥOP.Hf>bz;)u4bF=`'գǯ<%I(P(G JVDH[ Vмz|;}*X sP3"\(aLK'($|4+ba /G1WSȄ;?-"{Y\䒍T6mRB硐je7u!:XuHӶi_֟hE{Ϯ>ęF?adq%G{{̈ D=/(G_,!2uh/6gU#QCכx+MV& Bt&–LMi;IO=ZLmv]YqC <֫LJ|8%[3y2RJOK*/' nd>b _:z '[5r%Y+CG5D!6MNH+Ķ3)P8?y~CMk"h~*镓 pnȈ;OO.K pdS_~?v=g7;UܠEyM[rfZ̯Ɗ:2aY_VK e ab%xr_{C@JߤѰ Is>E?"-SX֖󝊑#|`bsj(kzȤ~³ҤGȧKx$%E,W.3/<8B ->nl fng|2lȑhދMt+~Ɗ3sitϠ.>M}1UuZP90Ս-3(?eJT+*j]8agSL6 .Kǜ)012[&C< 9h@CjavTΦwԖ)zns(l$uR7=hNj8~أڹ4N9hoHb ?䇥;_HWrqb-5B-DHyiZ5tTH?D cQ0p3O˞gS*?Z7)~_l9Akq~K܁gGH=ޝ@rs;._o!IMJWy߸5*8<`$^n)."aqlM`@ޥP=O[a+yWScփ Wnb$OI[<MEu?bK7 Qx.vY?OF40yJfVzw#jd3^1V:W텭Vw'Bg p/X_M~,W2A/PigEъ 3/N/ڎԯ}2nrJPxlg- ;9Y¦\PwC>w\mykSAi5b*E]z,NA¶Sh8 P!PV<1 p] j75 C,Y8w y%#mǶ˄ЊF9+^m=KyJ)?9B8=r[K@;ufa sq=ShVoExfދj.np Z^Z}A6}>Ckᯑ¨G[]7nbNG[Qh+]=!D$y`N{̞y2 L24,.}  &C쫧(_ܐکY+ž:Xͽa VɺTx2տ{,%({÷GmLx"OVKDHV4 b S]C` X&׏ڌl5V|σQjQ(J?Zh>,AvJwn;| "ߛ7kٯzHmјj}Jw.(GTVYui΂\F֡Slɶ7>VU!/}#?J 3h\[.QOpfD9.i_VBCK'$.|=bP=H=$E܅7NhK$D}D}U:`s!9NgJL-$Fo| `XlGȳ@ ⦐情]ҳ|Aw9ay!xԓBXlC{'@l=0c |if@0[S@u-ƟߴVGiǼЧ{hV!R$H,PTi"JƯHW7V)H?@0 ֽ8/ЗEmKwB|ogT$%ql\ͽgY[Yb>+ۅ}bXm3Q̍𴆤\/CtMH*BsmEK5vS!bQ$No /!lw]$~yTHwHxM{ o5C<.-G:'nAg"X6h*8 B_#'xdwe eIUc78AuOmxF`BApM/+L >_Ϧ׬A$lh'w~՘8/q鍴sXi=eFCV[y%r' Q(C"E|am)iR.!(D,"~2H \r5hNd吟 ޲%*֫?HHwx_+DQޜK(P.#=gzWR{v!n~-EZb~y$PsL DA m 8gl6ݴ KxvC$،<u".b0^q޽["6Ep7BPD~G=G^ d4I)ݰ\%]Isu9b"Od4ycBt} B2Iw >TwoC6Yh޽}5頋OK~uK >,|آZQ^ŭ2]Dxۓ aKƮFဳ#Gl_ЖP;[b/^ @9G8Fng/zi.Ԁ.4 4ˇ܁GzCz$bZšIPȿ;=e͡CBFF=@G"*&i<=~Hҫe[+t %YYHBpRtY5F;g=Y1̴>OF* r|+ $I4'켈'JB^"V-rrvԒm.Հ 028ZۂF"L*W ~&:y4*xC,aTp=zsOl4rN!䨳O6{Xy]KӺXVpx9o<5x0}AjnhzΫRXc . PP/BsQ I$aDy|1tZ+zK՘vʼnuWJ_LgP-X پ Gc&ɦ Tz5m8B!ڻkp _Jmsi .$Wآ%^vja 4Ĉ)Te?ɔvo#jkg[c=YU]Fqܾ2*%{dj]0o9[^su;enKm ķժ: :fmxw]~[2Ċkn@$M<=T֫^G?ΪL;%k/ |_hk"KPm.ןzIjqP[uZ*͊"|c!@AɥRYt'}UP%A<$#`12ST3qee'DL[!p`oMtvvYzod >YGMKt{It}jA PLq܎3ꮁ"3~sB]FkJB's t_*_ l6)Ҳu@<>q;F ;|L+}!#YnK ~JԥRvu-_\[e=ožy6\ƗDO\*KE݊;KO~%!lOb[tr~Q(E8{]>1p55ǟٍ}I=ʾ>+iy[{ٮX9?=pйԩpOg fyEO 8V; )CbI3o^?5.:^8BݽsH(q:K2 ]SJ}JpQNa+ZrJF; :׫PAKtK2 r!t-bԷE_bz^-V+BL1]h 8qf*'D$˥_fɧRutΨ>|i]xU/u.aG͔Sn5KLxW8]T.wƐ`g@sSY,kuߙ*ف|O7S\Ҕώujk?=fA!CNm6W"/}{YQw sLh@D2sO[r}ݕ5MчBUF56zZq[^iQ?f]Tt0 1e9liz8޺Obw5Je>OEu66~:u-aj6/]kIf& <\Fuz0ʧp'{UpxAhC?^qNF"KMv!Tt"@9 kxsWÉ|3t`G]B{mV]{Q*^mFb|`nXp엇<`O\:E+̇JndJ_=DЉwz0ˏJI.NO>L XPb(ѣZL}\YWgKScT*_;y+d46xr({5Wywgy~,߅ȺV[A&qP]Le!'=}=BDKBRDL+~-ĮZ~B;RgQ~m.ܞ5qȣlzQg{Wp'S2=Yu1w߶.pwshi$bKA-5pl?בF,zaI( ~plQi=5yW?A"+o#y&샌`;z f/E!v5P.|\.ˈBB %UMǀ>%,&m-[% ճ{1i:9aYإ9LF=ؑ%sȽ=b /?u5K0}? c{o\3eE#mJ#V(zG|z9Xb\Oo ~T ˼Xz6dBS q$cmmw-}rͣ*iQ5"n/t H8J ;l Wq]>}̳VDys+jC7/b]VjYpYqF=A3&Is4+m8Wb#?&ǥkTRt]44NiecےIㅔ6=9㑶5@;hr cb7UQݮլff0 4G|n>=թQjWi.qЬHQ,k(6TzOvfE{$ vBҥDT -C3I1}b y%nw7<}e~2곉9u75)45(P8*MPdUٟXOuKX3h^+'G5j>[vd!録4{^b$ym ] I,j&X@RտpyTӢ\]^mͣd(C^wiH}ra&, >H/ՙO)4.o%bR]+:* Dm>0@|f9)n,}Rt1컬In*>}7J~GCqO}w5& ]ߔqPƷέEr8<8q$!q}sMЙKt4a!3hjѨmlg{'9´L#ē 83MH[̌DfCkiD2L6GokdG" D]3fZH >3fR0) ?R1N]?#;_?Cg/jϠ,"rL n7;֝uT11 |9FX Hq:ו;iы(pP f)e<M>Pu~ ڣ`@Pji,{j1]I)׏Oz1+99F:+-'Gg:RT/z3ΝPVHKNrmpƗ\$*ER։z0/W( 1TlkǛhRYIHvX>^ԯ6u?ʼnm &o@I!9l |g?l,Vk0cXQ'i[,*EE*aj ݐt֧RIgd;zgH%SE~.םP>DC*Zp)[q޷*i60*t UE$ΜYx)+Jq9SW5Mѷ{ qJ3Rњ*Q_B2#$"9ˀ߻XG6n}ΙAZͨy\d˨C[خyڏ}-jU2q>'iqm4AyOw6X+xLP̠Tk/=0䬁Uwy;gQyͣ->}lj5uor|it= 1:Ёx (c|d52NUo6c;țid߃ ru KY~ jšw-v!an\x`eT3f|[@_ΚqPͬEa94q_坛6sOe7Y“ohix{nb ؆-F,`#Y51OHv=B/ uo(e^䬱^ 2g-U2>cx^Kѕ7بt/zlG_xCHJ1U[Cĕэ\}_10nI$?KsHɗDzu0lH/\XOc:΃JA9RmK)_)J:ʄXj&!SXZCA&#zj]،n}y'_,A?/czk; y-Z&͡߃w.!Tz}cZ-͊x-g^)7p;@,XbK"ybrJEB܍%,x 6!a=z8~sHp ˇ{ΡP`SMSt]a2" x7]ne ΈKZhD4WfClzp$Kηq]?Xʰ(443/;>ۚ M_!S5ң+ӬG{Qav1+zk(?.mAbC: :q <JJla@HO?;5 l`Ǽ>buV 3ړQ{]!xuQOBdV .r)y‹*ʁvrVnKk7DZ|Ukbm]ݩڧA/žBEg1Rq;Wm.b8@*eA̼BR$gھVB/8B 9K|4My/m12n =vIF>:axM g#վ%C~Yc)>If˞Ý͛{ >[Jh$v#29ujh8bgivWi=ôRîc[%6<1g$;8CaG|r&z1z\w潄w**ft)¼>5xcL[%1JrͿu\R/"8` ^mJ]X|?-ͽaqmGgBVQ_ity 3TU;wyx1:YJw0Uc7Pb77۾ }dngCw3?] FfJ v.[Zy:-㗏𐴻jџ‡+ge˯h֧"{QVK,J-Y㑘A p*| Ebl](Ei/MGmdFukYy^ާ ?ަ^R7&DRAʛaÖlΙZe7J꾾s6h֩l0z8Siv kNSp'?GS>fUWAK!C$<#g3Wr?j쫢 4gP= Qe>Xv8mo/ V=4H^-}[;2ɰv3EV+i fgkJ.uGORD EpOȆK΃:ҺAhNt ^Hl}g2Kmz :㔻;>z6}a+@5r^0"1QٽӚ9|aC2Oͷ$8WPÙ-X-2\#YH#y.?5gԖD:5z >qJK/I'6/h:[t-_i=zp=&:fYp 17:8}8D,~yi ; (WLphϏC] ې:"* tX_RNySlu}8y 6- Sy{1䰙ƻc#8b(]&3`Ÿ_'ܬ6|Ѵwt$zQӝ! m8ͼ2XHeN2RKNy!CRA՜9G9 39r O& Xgضx/{-\q9-EVq[1^62$ ٫MԪܿ4pMZ%#8^^&ȳ'S%*oYę?|_MB49X|T5Dw/{sѪ*ٱ_!~Cֻwy%;֕YU<1cSo>z٤<U?px22HBDܜf؟vUj잣ƊNR ?ULж=]-[¹qaի-7g 5rd#q2n~J87.LcM8w ؜0MqIO 'mM Hɻ ёr)+yroT\U1n`{+GENqs8pp% Lp8pT2oOVQc~>:6.;uBeUp(r$Q2:C:rdc 2Z KIIvI*E'i6(~tnUSRQ9&m)چׇCj4bZm,*,?9|ls[ 6_ccYJ%& U+*rRJԋE7z3RSxEo>W7]j&~YxHU'j[@'ڲ.VS]]3i|*^au"nW6\$."d[!Tq* ]u;mem/[.}-On+<+㟹5{.b)m4[vrnVPI\ Z,>3m5N,߶Ba_~hBa1.omJm|xJk 4qk{ 4=.yn@m "ʴ3Is]MÖ^ejJ#~w"C8Łk##xh80Da0J;mh]jQ~/~Y0n{F}^/oT `I|[F$#_Bf[FZ7hzSQa Nhp0̈GwS(OmhB+peh|xq)ᩄ b݊Mt{ro٢@}O!G,GQtܸİu@p,#"}N΃Ch\ `va] $aUwg9wUMZ&my~P~Kpkrv=WlJ^JuA" P{pc!E8t1բP'NY,uL̼U4IYaɔ^{vOi*AqoɾA?{,68d}݄^蕶S@XAr<:Ef (KAoO)\;CAF-GrpWuT0|Ag0|WAhizi$ 61**GTo[w}Xڵ79Hd ed󠴆ӑT, zX\;W i__80 iv.2+;6)8IW7$I=qq|ԇ*ES"SŕnA 6xܺ$6Hf 0W2\Z6OIm 12fBy_G!Zdw N0ᤸ2㲀D3=w%>:7wIUAytTɶ ԓT}n .:]F'{O:@_E胆6i/Dw)@#vLƭnb[F0M?8wj$ J^dBcg0/N+ bICT~ ڐ4{IUNGԨ +/{+(O H$F6!uIT& sn.l@qMbay.꬏Gh? !>9^P9*2elN ͅ\=VvaIQ_8vkI[)밡 j!X,.Y.%S6ec/+q}Ƭ)+쯛7IZfG5wT՛"QT+uueZpM]RԿK88D JdXg6`f5~ݢ1iˤWs4AJޗ)<6qB5>Fw ݒ!`oCV{"~VZ(s\DRRNSK.P?ITǶ@#5a$*eEU0.Iu12$Q[xgrl*qȽoz|S1m+'з̊Tj*|X6 RU05 RB&quDPFDli'jB^9VZ/?F&> \|_Ύ׬dtOZvT.{PMHr2hb'IK~()\l&Ql4OTGNPf3^mfvTeyxΟvgEN{݆Y;l j[M(]Gsrwvʺ2F&)DR+=ZJM̦* T+_f(ҫ`m8qfpEI*XӘJ Ԙ„ G=xɁ]C;˛wmZRrb8vBѻ4oM$-1HAi?b_"ayG"AN@ ())Ir*sηj:*(V *MeVV^OٳTqZɍ|$Q IX0ޜQ8/˻xGnqlpGprw6:}2#01)3qe}[}Z(dge/ =87,̎>PN@UI @R!Cɷ2")GjL~rݰGw.5-͠>+^U9L6Buh]3Ǚns=K/㺬g#, TZDžBJJ̉Ck9rMu^ !V:dL+Ԇ[3)︎l4Ed1i2|@UԞĻgef6&u;{Ndtsߕ5.okjӤKI]C =|<s8fɹ}rqEMX=C$k䰷!.'K>uhב]6]eš7մٜ#fJ .m>ۇkfQgit+ﯛZzj[ç"GUyzJӜ6N$v7,cSqEӮpoq6kc! ZGbj=Eew3.n:flpGGT/玓ҎW+ap[f 9)H? t5&dKJX>'6D/kM-Rklv e.[6ǾWڸPp>,i׈׻,54Ev;8x|H }wPϝ):g@>G xo3Ԇ8OcNFGmS>\l GsdSIAc}O\*暥a%u羛RՉʔ_ T_P~]\3Ԃ̯қΌRh3̯!^:/p)=P8<`leBLΡ̐&I"X뎫/Lq|rιWbG;֯aþxA6~ ) 8J>H H4;KL*eJG Wl>Bq6  w0fV4l14u{V51*Xd0V{3W3Ȧx?s[j RXz~ qӑ+SJy]!#{j#Ft f6J ,:pWq/yK[45w KޡIny~8PvCԱ3\r dwUM,P"ߍ#}*.ɄBlEB89X:mᶷ)x9I "^uNiڔs3nu~m6~n9O8.|鬘#aTҊܺ'P$;7&{ ^.\BjCLq[B-EWlAw(eE>%n銯DO ݬkdr{GӦ'&;0is/lF )E]s؞gD>Gq\Ce_|q;bYvQ* hmT'ʝK .NV RP,=KcR1Zg[7zEޞjAoKmߞ4e&]u#.TCaH3&nʧ9N'-,鲇z+1%-Ė868v~#2q!p|I2l϶wAIߕ=ܚ'!{Oi^дB ]oiupPF持X/OK+z_:~*ˏd:pCG]Ip@l,?ȝks%ZM]H[u#KAW|S5>sB~V1 n o5Pi^z@j&ќr~N"< ],f9MJ~&86Cm8`̸wY;9 g`0t_(usȗISAe8-u/ض-% zqE~$#`އ2s%w*c!E5?8ȏ^fHmٳ1LQmPe, OUƔy ݵ>PͰ}߼M]khhͶz*X&ᖁDS?}W%!g1Z@/IhW$*6D8h'vptEct/(u1 ^4(u~~$7|+':Š>%;)y+Csem7aQƐu8?qJ8:AIE+/wo'_ T_i#q7*b~Mf'/&_txDtui?>z3+Zӡv{/=89Q-j"0Ry 6бw` 2n=RS'T7Ui^<=k!+`8:o_ufu#q=xZt=16bWQ#1Xl*aA\aEEqԒ8(w"`S 8Dp,;qV2LWtB(c5MyXf= MLe+qsXW0ohoM9 Gߕ3P;{ v_U/ Ds_]- +"S 7o[3f-m2HKrɪY hRy-CdgۺP;R|ųܿ4!үZ$ʀP6lR9b5*O #Wڱ.Ξ͖|rGDNm']X^ [FQ/\K۹`M[7uv=|d*=~ =]σy9?|Ŵ[V3NLkdsJÍ04jP4"|'{ntc7u3˰`Kj.ՉajJESd>me7Δ5,^"[{O9.+imY m\O^2ٖs8fx<[8pyܺH$jaGD+]iŽup +g˪v^"T0@8&%mX<{%ktJעџ|zm1ߜ=~.Wt8ƓG/\orJP!ÿ,8Jo[s"isȲg%ӿ4_YRY 71eёejחe%!I@z1J+m̦kGk fTtѭkd7C镧bE}~uۋC4q!{$}.rT AͶU8*z WCpg+zK ` ,P?{̥&&+?O?HmN#Q_ 23?fg׎p|u)t0N]EggA/aJ;DXMJJTnñR#p fYeZg"PS wyӶ^kI/3/ב(WmN,TYppOȅn:Rhcl7BuBa8cP!*^w IYm`dRiKZ,|g3w3ch" y0A9/|sGu/q75 ( E 1^<0 pN,{iҊ771WF*̸JRCiWV[}w UWXH|;Wf, O:4Y<=[IaiދDmRɒ`>KQꝠjP-.ʵ2m3p^rE֓nx7ɻ{O <'5'pPs(d=v+}#i]c2o.wo+SU tRܽ]ضb|-gX\`MZ|yN DZ򈈨12i{+/3Ļl/7i_*&ܞ{tz1}H\Α**OUs]soH.rV]va-,yO-3V`UȪ-* m/4[4PKZ)^C}BEER.NEOixSU6v6@JeL(  SvH2H8Ѣ{I 8PA-U ݻ rKd,Ilii鐴I]k--=ylIW\kk]B Q%0L :=4,ށ$PrÒC" ) J $^Ӂ#I0 (;9b~^c׃'R!]g]".JU%dspe|Z/Ƿ 1xCC9ծ]BQR2NN-֒MW_( *aWZ p4NK=zS8BtJI,c1#rsJۧ*[Ka"MeŻgcgZݢ3X rCQ><j_/#>l13<{tXJ0y6XP@P"]MzHs:PہGe5_#.U)Q 9oXJzyL;> '靣Nҝh>¾FkJKW_Q (\$#~0 қCՇG2`}oԥO|s=MpdD#W+$><Ө(UC3eBraO^P3D~#)K<nدʵ{&S\L]dX2ĩ #) l:yW? f 6 WYylQmIe=/#tG#Y#Ucno2 Z|c SR,; Wu:؞#|(ުR ^ݳ,O3*$Y<-Ӻ~N9wR#>HqG~{#( (qlmR(QZӊt3q|opAapT0@=I,&DԒrS5D  luzzXO^kxUq|$ԙuwC)ykuNl(B/>0\}/X{ct9gr'nOՏ GůvozS(vaoNJ_U*Gm.غ#?'.l)^ U/q_09I½=G)P7vovQ pPUb{_u(tu VSQ8<:Ϩ>R1~eQ ]Õ[;d^D㇥Pe9xB!@ʇW>y9!Th# <5h)|u_},RyJ/ +q|;j2h` J?Җs6 В)I$~s@6O܊G~ҘB@ ބzbC)2L7~8|jF:ҍ'VKGېG=13,Va+._F~$UP0A8>n GfXEȃ!laЗf5I _ʿq5~tZ6MXba M&ۘGW')ԃ5,oX,w&;s!W4#\R.SY,LzTtCB>zbt;lt<Ÿd}n}qU}:(-|&i`&~3t.| hr NV p\.}2D fRey#)8^3=}c_{ĐbD;]Ӏ3⾤me(,>u>G݈=Byws1P8zi-64O;1!UҖ}aҏq|} Q™',Ε*|5ӫRX!AH=A} E2kE |"Q~R 5g\ɂh!P guQBՆ~K %D]g>괵kFvS]{W_/I|]C7)LM/B$>uFsZ a̟|'3[7CrB`^I YmϩUPu*8<jAͫYg(^PRv*B{moQCAl+3^ @9S<34x&Rd)5t3g(8I&oTP|ۛa^%w/œ8!BQgAPŢ)̈8d~_,Bgܞ5H%N5kdժC@RJ_GK}IKO:pdI(HgRaӧYIl&/Y)L՞tO]ÖQy#G뉝 xt/hH).eiUeo%olyEZo(Ȫ $'t o' yb}BehQ@~zy$32W)Ya`d"p?]Ko\ѝL!xfP(w2y/?xoƿ }ϰ) ,|x'`49|Np 9v$X8o4KĴοJ#E9hƳXŒyx՛+9eo%CUCמ-Bt$zl+!&|nAw\3d ^^)moĴiCk}9R_;iEF=ɣsиI\vSwZv!J!\TΨA\gw 󏐳ꀥ}Y z5wTͯ#& դ:؟6'UچzHK%'́WT:aʪCo3EšO~H>n{nc {Y۹_˔u4MMHM:fLp2"*wG3WO{E4~)ǧxӰT<6_҉hhvs9D6SJ2Ok`-oiei$ܤ^Tn@n0 \2 I2Aёοv,~84w\E/liu&8vΤ/"*'OWcq[/EفDuQv h2J(}'~¿ UE ;*IrHXCFңA?/iV":OYa5Z7c o~'},|.[n~|zOhIxBF\CAv tdc 0UycQ ÷?4z!y_e }8/r⺥ 1^M'k>@!XM|>'k$nQc?–BkeCŵ5MQ4ElDw;]0tnz:ǏgC +xƎ|hFF$qɯaqTCyBC 6lOS=aIT ]Y܂]HWjkD24b}^yP1T$s[pEp%AjGׯC QQZ%R23یhd}1W@75i?Nkxik|[)~D~4 Mx[]tߧI]^`%Tk~CSŊUaS} #Z:}vy*_Q1kw{>j%] k3]\Ō+ DO2ޅ( eu }6$]I*.!l>דLbHgAj.H"@ K!x9wtmvA2N[Ɨ1ʟ#4hʄVC"Kqѷig$p|Q~RLAof%}wڶOk! 3 64c֫^Sq\wYoOpSf|;-_Hu͉byyq|_WƑi[(3_8:?~ xMKUMtD{ } ?PH>)7=H_*}C)p]8wl?aW)O=il1t[}$Ȧ`6|.&1ώ{9:}xpK|m瞂xﮌvm͠XSY ~~ǷACE50m>L99*13%RCrz_0mEVǗe|+UG-tLLZJ|NaAdp+Ѩ@TVy}99^yNG5}&Icc PТUB= tb^KWxl¿n0P,l._ƗK9?_AAϚLM3+mqSU$aN,B;oS]u1mx"y߳ۇ[>ݠ=bel_WS9i{Dc)ʎhk&P>~,|LCD=GU:p=p,7N, <QG:KX:_tFϦ?pKqGS4O'd.jN_.it?7PRA0 [jg&j";u?=b0 nG]y4_F-A|]QI-x6Y$LjB>|ѷ3FYY+dE&v{yǻRo)M 3u;\t)(d0()/ 7;cfe $~&Άau:C&&']P}'[_f@&=Pno?ۤ59dETbTfxa}8;cFXspƿ2w ̾Go|pos|kI?En2٘FR.}`QqǤFwFlv@~? c6y:4s -\u*YKcƎqQxמvٜ/> }zGR1ʏ_B!L't$##JmyC;AQ]2*Y![zlI" O_l@2+c V&<*H_*C}fy'n׺U-;rRVAoer3FVfzsďmC9p?h#kC $5I>H}<-z{O3$3o闡1bOd.qJ}lsgc @@2}9ܠ;M)}5mXjdnn҇K7khc)P?u\-"cI\!G%s"~|EĽ(.}HׄwӞv'vX(0 }=kk*qv33B=ǎ߳4 s9 "~϶~1}CߔrpjFh88:" #qng][  o>rS=F8JƵlX;~Ǫ{űA,|V,ʬ@qݎ'2,p!Wv/<@~¼LR`s.smuc_T/ U %ogQB\Z3a(gޗ`]? noRa b1ԺQM̂~& %aEDPiSK>U4]>7՝BSS`XOS8 r8l#5_>%zp5C)抟ܖ.m%(VC/r_ ֶ6Ke(TP~ Q p9/˃K=o^f"`Xσ,X[Gt¤[@Ө+pm1((K`2.%itA U czoqُs+i<Qf[-7/}B9+ [g'i}eU[b(:FP@c>~$g|d!X9uHgЙ슯./p] I!e4sOl{\S($&69фthUogw=h ^玿?xf3 +X/̅O{0}J;Miv&Q L(tXŘG,O6ڠ19=y䳄ɰ?o>"s+{Y?E D=6^a;1mNWDAx~ۙUTHg?LAK u8w#ZSDGt]IeY1ԖJL(ϵr*?>hPA!<͓+Qʺ>//dD`{}藿IRO -~ZLCZc>(5CX.#,I70lSQYiZT7v)djϷF  D+DI_=@BęLsX?{ kÍFZ3*ym/%:rZHH@uB(XEbn!7Ci P6uqS9`[a[=g3a ~S $ֳo.Y7=I/JPֽZ~E{}7GjG =UC1(yw %1 MV~E.pJ7QTӔ>_ o2Ւoo`om1X:{OT߿b=cel11kF84`5ר D G裹6KRv0ݿ$3ɚGBU΍~c=:N5>@;].gRTH:#) >u89o?tp}`'?9C1],p\⑋,p|D&]vԒwH3d:8wΑYSf#L%GOݳ.9#!/YHDWE&}AoQuNvǐ:]C}9bPອٻSC('Y:_Z\9!ID#c=+ om:y|}Z̿ҊRgH{\7 Qu6\$Bz֪̾6EYr5uAGd<".]f5nڲ˿S|O9Oډpj $)o|A?a>#z鿖 _\+a'nr[M3W>[x,ڣw2ؤ&H# *9қxㅲXD4/WcT& I_<]ܺɻ>-ƗӇpL!4:Gt`D ֑Ⱥ5B+7[ ڨQf( ߥJ1|Za5`h>O8*+Qߙ'2%a'%T@z&Ƨφn PvՄ˽O柸a0F?kH'd]$znnY*DyHZzka5EaqUq.jn<)8u}`iMl`g ȀCf%~W& ȇԊ爇')kX;Fp_2 HLnѿU柡m|jNՂ+rmfO:b Qq4.dz~ W6 %Y:Tp,y/pijN/GrOE@|o& ˁgD1z*?)_mi?_5hk4<,VOSdwH)'F!LM0;;DrY[%M7Ů)cg#ZwS Ss0Šub񕖠( ӏWOw, +Y~nO<ڛ0/C|0oE)_HbY؞Sꑵb%MUUEwhgm7~:/v<˿\SZ-g7q;sX1Js&N8}aRAh- kǷO? X˓FZ)bO)!?V hubp jkqNmjMH5;jmʿΘN}߁RW07ff3}wȰve<_5o fM3?DT{AAĘy;iŃߑ_do+jX,JC$mBk\<d#`Zkǣm#mĸD_^AICBߟMT?7 wq24i>0ж̾9T߲\ i|Q$PQ* A(#7-2~ y-^?//O4 -lކ^[\'GEC̯[.} QAݼrChK6o'h.i_L(2Ժ nKv|1(2pbILhTy_L|C0#i>f0\: <2i!$&;3>W. WtƧl4KCZ۔6za`dCѽD9?%bs~KǗ/ջnsN_62rƘ :S5Wt5qeeo"o/N.kN B;_GfM:/} ,O@~y/Ld16~|x +ۄ'*^w4^Cگc"ԗBtz kb$)j=4k%ffFhn緖.[W{q -A/ش΂qc__^P$Xmh3KUC*,HyF$R4%ZEq _&:1ޔ|~L;_m/֩fBr(}ܒvP`L+&W?.}YV7cGWblDk_oOCѲ؛/Т?iG/dZ4τȣ/Ԅ30~ιXU)@/5&o+Ӄwב/Fބ3Dz5҇1>ȅT`OyO_{}} RX/=Ww|>%bDLFAW!zx.D@Oh\ Zz578|ne.٣p5KyńFl}FzCw|sKԱ u5 h QYPKd;&%VZZ>֠Towwz_? A~MVEj\@7z{}/$\(RK)9FFܑQu0 4Q4m+)Rsϩm)q(5B}-?^:dCN=>>Eڂ #;vzAȫB@<=x`1;T rKdi{~3ݻcS7VM\PΉ靶#v 1.g SB>4/~jAmAq!G!a>Zɍ֪b Nqq4|N}TR9|CԟzHNDb7r‚4qYZoK ÆQ|JJt^:} [1ž_Kwߧ6%)eFRu (.@bo\>/]'tGz=s ]I!zcVTm}Wx2TyQMnvPg]=1yThY%z|; oz,suFN)8%kdUc 88ѐcj|?AS\ "7n@J~/p}|⒋(wwaYbaz-֓i'\zWRxҚ35E5:?UNĵ{#ar7:1kEtr7 h^7GZ#(Ҧg6]0Zj (Q+1;%MMnXZkZ 6b={)hm]qb묿ZXz9f|Uo܋on\8H&dm#C_.{>^D3ٱJ'݋]0jEW ՉIIԦO/oϨVb]hǿ  &wvyv_S}Dާ?`7޾_~h$Iw[(*!PƼ˿?ݰU*2pһ0Puoī WsWD ,|\0klFr<zޙv6~p iTIZ|56`G й~7̃ZeqP9zu٦в SGS㨲(G\K8 |JYEBک_(j{/ic7C%Zma-N7@nѳyZ쯓s\i&5Fиj7݇l8w,N_gA9 = Dm*7`hl0H׎|:Rf/jϠNy]Kݲ9J0Lˤ@)#8q̈1&A}tᣎaֳG?~} Qfoz6fq81S3Ia8VNR_qHPKc0BCt菞j(<:S`ڈUCCn/yʨ|j #w67WTJ5>7ߤ7@@QITwt(q& y4-3`fvΛhn``Cjg[c,Grs_R:qԈ5p1q>d-(F򧎘V N<: 'u~!s;w߇R`%gvJ35^gj.K'J Hz+v7@?k~!u zcaYᅭOܟAѤ2b#T*Ǹs%5u}?!o}[g^VRS)+Z5'?7`$I2djND}?ߨssHVE:3ðu3Ǎ,KLdW媎C 4i! 렟|#W5#+|UړV@.|c ,DPX=T2t^T[g`S6;Wp3*!myܗE%cւm? $q$}Rq~%6V|[G}x^uKB&:n} ~qAms\ѸƬ<4i!is4G@F.3Ya򅑄x ¹ږmT+YX>WrEes "͹Hk0ͧY;\TC:/0Dʵhh RhTyޮ{\Ϳz j诼Gacʟݓ8mޕOpLRYZj0A_[5s#1"~xr=z~SxdQxzb4낤;`؁cnZC|Za;XUxO? ݣH^:Z׳BQ߈:^ӳ,ΝٳKaV8P쀂pR,HH$b]Əŧ=1LJŅ@1儍u:3SٮJml5;of86?RXLeY#:i\~aE^EXDnE g啘2a0gET.Ϩ RoCo tMA0$tݗVۆwp*+N WStǮuOhۊCʗp?_"k篵IC&rm?&dG5RWDc=QZZBootPbM"0պo,sCV]s܁M>ǂα.}w7 Ld}Xk6У QB1a '\MyqP2R} 6s^)EVy|%Mk=`)R=?y w&OtN/{?6f279{+0e`Du&+: w9~^ ^P۸w=DCɬo3ۜ>,ՑDSF}~uw{R &ڧ@Q**tg+ ޭ|9pGn0#q ΉwNT_!!鏙m޺ ; DrgvhD!d9耕 _ 9k?C)<֕zqI/]G}}}USan=9}xI l;o`#!&zj~.Жvb3Z#:( /t %#p\տZ94s5z~/6 iC]eyO~5 ٽvO|5flsF;$.[ֱn]z5/.(w_lv~}ooDo-;#bԞm+ߑݡ~nn m_YLTy&sH\cFSoXSܤH&[I:d? Ǫ<) ?fZ[./ g#{Nk*Zs]i|v/0_<9K?LyyZ F쩴rz_c8H۟W&2JGIY@?xm->qB'L>m7]؁d)Pk!HK&\LQ8/ZM' \ GwX[TdCƋ|R^Gj)1!]PlF.SPdo,PK-d {u} CHURCH.NEOw\[.g2 P UDP14 c%  ElDVDDEE(Qds[w&'5l3jB j6!p-/Sрf#7j;]0tJ'^fXbg:r;c\|6*UpwU taV K&J~68r"LAxy #}{&xR [[uYއ$.ð$0*`plj\ #rS; ~ ayiUJW_XS sd K,BD3Pgp |Us eQ]-ePm+T'PUJ`< ˋŊ04'?a2\FP\92b}e F,?(l)=%Ot1W 81LN2ҟ`)S020 rJ 8~(Z_U)Mz?f~٫J9b̨bZ{Щ͛J%L%Wi?b^r7P{ 0s.6 ,ݵw3>qv 9?0rE? _hiD5[sT8X/,K|%P;8qâa* 0P8CiM*D ӫ'†PNa-GBl9?I w~ V ǫkbdwHgY39J230#}G@7cicE|-ҋNЛ|;ghB}N_?|=J%V9c͑ LMWFSН/磞/KNTZbk%k,&``mM1~MLFy0OFy*3Z ~6 :#m(44-N/ ר| ;# 76n{{W1*DE3,V 1*s3YCuThщzKT+_c$G>gTz ]HaIأ أ TXR6BQ=CjYH~񞎜ƩŌH5=#~qF3f4h`Z ח{6XF5,Xڇ`AA (Q!CWȐ> fyNlVv;ևe6gmHU8wm#x#ăK}V/DF_Y|F$ҠF1 [ٴ#q#E;R3LӶc`+ NQGw= n`Ucs% \ 3tO57w~ wdg!.|6 ,`8NYIג#tW$F>ƶikU@Nr 5 w ` Bv _li { <rQߣ[{1<#s<22ifw ѽ//Dypݜ:aG9Gn Opf;yȒy!2'E"925} 7ECuz!x( $+F{ؕklg0RwO͵A'/X- 2p6 %PLFHǥR~|%q$)! h"FzDu/T-3?/>,RW#of}dh4#jmƤ@3/ڰsڏ|ZUE[ 4YXp4s+ D/sWWN15ru>)آZ`^kޮ]Q!=2پP!X%ǡ?j^Vi3}ۃΰL+442B 0a,mJfѴHui@\|N#|:70~tA:\K̝`Q Fm*"Ȉ9\Ya{Y>f]kq: Yp&A5<4!j!7䳴P}7W_Ga>ß@ّ9vîDᾆ6ikp|JB?)N`--4hV9jТ94 ;;B^a} {Sl+L.#wG/F9^Q2DڿLAَifzݽp1gͶXyN*ڹj)~ԉ Ix% i΁ݜ3Z~N</z;QjC :pRJ$ROΈrn0#sPKn[3fv :{uK|\-wosk@Kܩm-~'k,'zUe.)Dl-l4Zr=M/!rML!$PRs"T 6 @nrtl1Gz5 fi)6!uCM90$ң7Z0s)hzꁡ KYtkuq _ffR|ʓ(wÁ TQHΞb'%\x3=6ם9Cq:oj\A։Lɒd%az 0='L!>⳪ھ+ =%&n vRpz@hraƳ93tA-yfOdɃ&W *? &xV\P8ϸ(Ra_ @Y '3i ^DG(^u89OPxu뚀W0ONGOpnTpKfm}lPo9w@z*,Ȱ-VTЃ& )ʐrU=$pXxe(ߘsCn+dYs( 65Ef׏]{I@i/"=,xXx/-^(v=8O.[Xu~%r1[SA<&xhh_T0T2@UfW)i a<FrȯOg}UoWϛV.K{;kܢI !J T_W\̛[R ܍CP Lh]ih?"EFA;^-zQ׀w#ۛהЯxF~C eӕmA&젵N''G$G|ox P3aȱ%;{&j] 2;Y(lTvK@X(@OW<{Ǭԣ0,&#I9u\6uֵəKT0na >vI\#A mZO?}!0E!a`a>v{p<8+ué26XNqQ'Y\D>~/??S"Lj/ޜsu[cDW]#z77^}f7|-PExl _-[X븻 ƕjvy.".m} i/U'7 zl!.VxA# +Fڷ̱C&3Q^2]%9ÈhJr2P80JQb5DeT R2S%Ngz!ygg8kWP[hW:$K Pɢ8M)ed/2x7džo_cȊHm4Sҟ%~OL~[gv])})cS2ҍM%;H~E3 %Ep~VQ#\|y)8‹Gڏ5yCf+U&*˺m{`nw w]ḱ[RiԟN/ Ifvv"bvhg1]q7 nwlʂ+PLY0<s'~NcRuW0CӢ-XD;`j;_?)?-%?i=anzPy&'Ng3T\d-W3Ò'g|t`$WoO-/?$ ?PLp? OT6PnN{#Ϭ4q^b^ jѓ_uVg"kqiSjFħz,xzȓ#Icr>} kswғLź7&1kk2td@Fs~eAj_aJbO0\}Wb~oǻ^h5늁ŗf2I|=b~lֺ?J7|:PUNU5}?a FHO|Ep}q gQ+6ЄvL$1'>sy99Q x{ߡ8^-n=Z`5vlv,~G{scЏ뾂~huFAǗptp7z_A0huqo@Sq] mQ_%-Fu=EGO[bY^ ggpfw~úLZϻ6KHzAAAb䢞l6J~JvIO7 [@[2~v:unNu %S=6 X vܔgv̘pOaψ_G w%B>To qZSH~coc>8O{`iS߆*{m2/B\oJʷ1qZ}೬՛ z3cŴ_UN-2v^Jb余>f}t=.FgܪvmwZ~ e^MN%ikZ9alOMlj^3kG}rQ$̓W.g }]y1Vbp$ 7xM_>v7ʔKwu'I$kˢ]5WYj9pI1cϮ~N)Le62@nLn* pb3dcf+o sTWc s1rChG0k3}~ߢ 6xBgncirWfL4"C S.F6n'xy?a >w~_^|q 6EG>}J 9,xt$Џ9:sz`l/x8i/u+ {P|y=iΡLјcG̟/uvsiן/(!v g#S'l@)p%sETY`X1w PKJXBcoڮ훸]Y{o jh0p@1*P'MkKvݦn2LPQozn: ӚQCR(?B|(43;?j^S]Iiu8ū寂O҃5IA91$y*+.Asؽ?- 9S'E: jB&']vM S/Tp RWy6Km)&4!S` }Po;"N(_^|GFQ`ltǮ^&C,ĎI\^0?mkә}.>(ԳVT d 6(_.,bklWQlnV`{R*=od$9h#2?:LuL]KuTJ1i$)ݥkEѥ;coZM(X`9 lh>}$ZW_4%a)Xa`|ˤP.NpHbgA6kZ>#ܾ*=ݯn0;ec<Ga]ijgg{^6OlsKEǪ=>4e/=%#vv~1bg+NzP'5eaJ=3}]VPqIqvM?rL&KiR.V=ɺ7ً+]x:B A!0odSǗPرеaU稺 ë|0VG}|* musB eЎ(ߞR"n)z+Fb 8L4nKڙ%]Nz)[}飿*2gBSIctG[Ŀ;o(yq")^[K*uq$}JX^Ytz>p,+Z0Rz>.:{h** km.ul^ǫ]湾{//V&N<򄞫ES3e}V'ZW_XtMOuckpZgq3025s9خd]NNp5+T[rLx_ڛvp8'a˘ǔE8FD-Pr?Pj hZg4UrƝXϖ]][Lw-a!YI;D:NZpu&hv*Rs8`0 `hЏ#l6 &9eqo_WjqǎlA۬q!ԁQK@%_55CCJ藜fU۷[(^nli߻# V}v{P䃌ѢVOz-wr׷XoypUMq!h)=Y/ b[+B GY~(dݳA@c.s`M`F';W|RÊ'1/"hR&)m)y凋9/ﬓOGκ._ccaԲק,-ެXR:Ň6U/o&Nc=?XtPp.+xq糹KVZ$C%ٿ[Y]t3lֳ5@d(K44vC`755eԤw>Z3 L,<%0Й|>kNihۓ4j:R7VI(ezI W删ot3Ƣ\ syN9>4&QSa"12nAn2m-Wz`5GQ< X\gc#/`2='3;İt%YKj J~;nPgO5LϰBB&S$/s-5T]?o<djr֙+4uQlm ⻱Vw$m䙂~vs_" Cu&0- oݳJJz45&y ~XĞog#qy*|D8" m h_TُM-,{:8b !g*?;엦Y׋FSM 9 ag=5z5\ppK*,u+$SXӖ˞^vzϛ9yaFN3:=/<R?kǭ6|"#+]cVU/` :=bn?F-ϚG|Up3bq6M(:3uOTߝnok]7׸=7J{r)YC/jȮ[WYC_x{F`PijKxmn EcUq#CfIĂUꂁBȫ3+ GQ+$6M~cT˘%rV]KDϟ쿌|"σ^A0ђmt:άaT29S51#Т* [z={ӎo^X3Sjd ӍOlSx:p6=FzhT7M*Ad}~g42_f?1 6SN/ܞF3gh[D{n@mO~#ӓݝ"eك;BLou8cJ ڴ17Ԫm9+KǟSŞċiHs.5ăq٫awVEtR8<y=rKT-i)?W$1@HҚQ1NR2`&KÀq3$ H6?8:dUO3 ~F^CE|AcgRD8U*Uh0(q[XzKT+UO]ٽ}Jk|(qcCml hPaFyeι=׫nEP>FAySn^ecq9wB?=[Vy#Sm \m8r֥ n$[e\(l+WqgrT6u|[M͖O7{5 Waba\JKH?@ K4и~#ǼalvaOE M*Rɖ)݀V,ە#ӻ/Š>KFھ}y zJg1;XLӌ޻nTV>\EEKG瀲=!`g(oclk G[g?-r +KSI1zZ]ҟDW={̬g[=1,W3]Zg?|Sτ-0"'.lO7[dJC;|$CIIHh72 CvAi@hG[- j|_$]3cYٙϏ6G ~ʼnm6}{cZ痞U^N[e̍J6ﺄ8Tid+S<*YU@]YL8ZAs) `yFij$)DCSi,ɯX]}Osjۗ~Xm-Z*R8m-;;1e CG#s;o} O{^*|Uj珚 7x 5 2mX"~Day*vdY098i{`~ʪI{wm?GQѲ(p/(k`vӈ`MySvjTjk87wTT 'EMяԍv<R-.e㪯 =]0DO{3n#!jjr/^57qvyT4}g+[rv}=[vO;7ԣFQqͷOp%/FtUwdcK(,}9B Z̎ho,VbgF|s ̳. M2=j!n|Lo/܋}J3脴!MSVu\u=q3vO/lXu!;wOǾᘮ۞zsv:Fwg%,L]w:Jw0S~Ҏ|MԞeYsE"$@>_ ``t;m~=x?nX*^XUcRgJKbe_})m5- 50{wBdWx`O;L8Z"}p(vjAlt~Q; v,js40Ȉv#ݎRx3ɋZ1 JN.cy4`pp(bQN[&?OmK'noiX{͞@0XݢєE!kTqL% <|v7= z½Ʉ>輰p|sܢ^$ !sdd;׼Voo2[ۭv!@2 4tzp'Pq$l߇~lK[.zbpB2ir_kE'헤&}z%c/5Ӵ/mn].lVZ6oN}rdXG8d{>v.٦W/},51(Nu4jȆeu]jvxpfCDQ'գ A5N%`Ұ2V蜅 6Kv;11ٔ{yu?&2N-h҃I2o~?Բ(z)!z*"ir {X>jM\*V@ zscY쪺0u`N z8UUĘi?D')Ϥآ0cj ̓UXV~TS!? OwErT2,o~аņ!;eO oD TI9JBZWȰ:O@5 t[:uכH0 _3"3T'e}4"CH>)BS T 6Ko -jG><#)H?ׂ ?E'b}M^?~1ym;18eԍm7Ld[X SםKR:|%*ґ-z-gsNQ 'KQVyi:erRl4Mz4ݱ#ӱYwCߚ/>wB9A@>Ꜳ뙒On?UϏWs/nLɩ-mg 0~a^VUthb;HPsuN`Q45]FB-={Z57h52#_kAL%8L =wع"-y= s)9#V칷h fve #69N%h4q}lL^^#ۚ<Ӵ8촷79տk'[m^&9rE6"~+l:5@IۧΗ-Q6&(2>NE?d+?80C _1wׅ˧+YZ{-%V(B 8h ?Mqo6Mew>͛j3x,8!r90w/{g-d{MN֟r-oMk^'[لv RCT}2^?bߴOƐ3O>? cVㆴ@vȭԿU&]TnŪS dKЮ(qzL_6SǼ-ҋvo/rB\dKW-{T̘҆v6</ Kۗv-sEHKVv80F'MT&>ytpt;7pfM }i>"ZLT!4,ʧ6{ZpRt;au,;߉fͷD u0z֤*ܝ/LUP)NXmmWRZaH'>9X <o%=>*C"*V~-þ O6؈9ĥ'c4/L,\gZrKQMY@TYVpFL&ػloi|N~S鉜|UA/JDP#VB\ѹinW7ԒuIDL ^hf1 ۆO]Y{̭ڻ+-\)j˼%J%G8+ ׁKgq=^pɿC@Z}_κtQ*1%":7$Rov" 2 ه@yIY̲ثHieTOp٠f_U٭l2]-i3G⫋.@~SދBg&%=Fo튱6)"qIE?ɡ B۫\jSMNwͨ? /țJ̣WTy0 ^m7 ]fq׷hŻj <;C)ћ2shBlm58ЧCy+'JqI?92u\.<3YqlP*peO8˩h_}F0/=w/prr"S՟EtkAnԄtdhU/I}L,}Yπ3D^pZ{dpQ'\?\q_kwHqq9ao| 3 5V+X X9UwrcB. K[ؠX,x왔=[aŜW]_!Xozn $l~#aD.ҪÄ<4ݜ;1JU9xT*EN~n׀Խ%Se?Yp l %v镩[vXoۧ`D9G&vg5rݑeȬ\ke3U4>%ItU.t?pF}q{W+M1ރc7 xZtS[5-6!HH$S @\bF6$1.:ئhrz)ju@ $5p|/vn"ɬ Yic7a fumӲV62cQ*8Ղ5^u'w?_ʰebt)F+;^r9b +k}F.)X:~ݘ'|;2]wɞս[bhq:|WՃ_|+?@䠖9byµ F4Ɵр !%`K9G}{x?% ʧQ7JJD>`rWZ@⤚blzfoj[ޟڸ>bDx{fNO+~2y>ʁ M/#"Qc!YU{*ƛAA. ߦ9j -Z(xt~B񆈀$piam}YZN6&~aao}.) zuF{d 2Z_[Stc;~FA3W-8o )׮cご6R` ۦ[~%UMqMFdH/f/Z?v?\M^^o*θ9-r*GL:PlFiZJvmwoc`|}ꆰx$[׈"9#!cQ7PL%D> X%]*?^7rs͌0=yKOtjP%A\XTWCݾ*>e6]9pHݒK/f.#b.y)RKhszq{)! #h6pABqx N#=39a*u O p\*lk-sc#:e'nO;}Ac..~/VnŨ[`[p0in|^HDlԼ41=?:/qmzg"[ŢXa{j~CQ+!x3*GBe}a1lFT$d{LIɉ!-Թܴ$?TDe30?ӳ; V 8Sp^o_jr(*\eW2W-VR{%tT"-`lKLF\5_8gJ2sODdn2hpSWkư-TӲ^vvyg/O>9ki$)&A=$fa,S^^!0]×@| \Oޝ@kh)rM{CBHC0֫4=?;2&F.t43j&Wow=,ohvhk_ 8NW$Il ]2ڦk)' L/'_e`3[4LnAY/5Dr461 0,a="cQ! Fe0W-;cR˅ho<&ua"TO: zOR q2SC *U(pa/m$Ӊr:@q'1l7tQ¤U!Vw70u#2-[Cv?"Lv_}{4{y[|FOiW4ps Z1g|7 뾟wt*s)]6>5W5-t 9vP;p@!&ŤmzAa9N#(QfRh WSQ|t!`F>"t58!8AB}:dF ;qV]q :5iF7/}uO\ձ"\ZGϡP `uW,sUWuX@8F(Rd]˦D V@ô6iK&<.[v,tkgߚߖF2W[恳dɌpITx2-֣]<Ljöe2=o:46Y.\I"1/SͣG"Ff-1Z9:zXk>ęx3/M"O=C9IҰ(:lktZ^˂#]C{ɡ܉^gEtU4ôio {j3Z\X=&j]JYM@<1jxMga0]`*/LwҢcӊ RZS5kh& ޻C\J.`6Wί7 M&Ng?Oaq ^Hd ]|'96-&ͺyY2|v,KA9lKăa]lZ>;\$A+@P̝Fe8"\O!cx]ȐBI!o[i S?VoY8c1-i ra:9XsX/]Ls%-T#L1ЎSH?4٦ypZ64,xص^x۞H,?}qy Ԋ[Y["t תk2)YqZH;\]7;/ Lw= ֡mpKֶ۶o2f~㣖#ha A@r##x.i֊Xߟ7D["}vb;dmxǢ~;0(DOCNY:6&iQU+=kK~7orF@(8T$o,9-(>V/{f $ecfF#SI-(\RIE$ u ҚEU\{Z~AܴG~ 0?[W&'Ľ?drv"Y~z?أKZSx~7{Y=ic`UP3CHw1./8P%@'ϓcș dm}nմx@'z4'|Wiw&7җ FBbQ@Ozš-zUWw$Xr+U㲗^5R9#^VO?֢bWf"4T\7p.y-{?NCYl#` n3w~¸X骹9D|)@wOܚRyt(D]9-w~?<רfFIUG̱δ|q Pj-Eτ|C#V1_c&H'@%r,x鍌k y|D`I=&K诘d$i_Ͻ<){ ܺI?7{%"2̔ O\I|=nh#=2qccFא2ѢQTs' 0tr+mhSI-9:VofrO!²iWVƢ+[@Z}GfdQ@ "-f'nџG/5oW| cI:͸%Yx=; GϤytgXw7M 5&IvT4O 0rD>tSl|:C/\9`tҌa?QϺŁƇdY#L~ .$qxa: z^!5'L)u>yf]k9@S*'_柶AQfJpBy ]? HڒOj^杹gKGLx']dI|Ϊ'\'XZv~ 4Ys؛DodY {"69OƬS_+)3Zjj $M(6z冚<5,2}ʆ+ 0'1<)Ӷ&i$?%ljsw4{FoK]ЕBX_wm ֩jM @tzY}&Ny T`05g5S-fBg%4yKQ{f) iþ3v\iÜ!?gӳ ?e4Qv xz26}R<0{si)DGV8ṩ#E~ a~f(l?>ָf?ew ѧCyI6mKׂ=@O3x ĿTO@ϔn`ih ^.#z58ˀ/̣38pCcF5/}n9CטR6{mdŷ/id?h:sz=͙aT7[e0BZ@P3xÄɘ/E(||^\4q~X~;z"M9)Mv jeh/|B1!Ƥ ٣G^7oC=ؗl(倎2 yjUc(o&G n',e4fб_2 -9=x G v"Saͽ :NikC*143llg")}[7{pۻz `C A-0-3g Ep=.eJX18hoeH ˢn2ۙGa$R[c=cu0|cPM_k` ?u kNH4?]F:a)#FL[=l  }E:c7#ZQ?Ъ_@5wuIҜ5%8a˹4dx6 ֍Dn HeW$*KLQKr3o`!3gy'H\ K=ZEyR*jory ݑpXuړ<# dhF9򈊫MH"xF;R(d{7j3&7e?}@LGEW[<(Py"\0IFB7Ŵ6VyӠչQXIZ&8t`?/5fA'T-3pP`O8O)Z$?Lq,J !m0U1 ~bxrUy h&9ayY/7ƮDS5U :< }d]'Y&nݵ<%<2/!\+fUa|3ØHO ƙf32/S_jEcwT/ &:yϗ_}Q45ZS\5B0zg' _K%QX6K]& xTѰạ́_㩙iG |D?tIUq6E!V4R"~1ć??n68uo:Qfzz0\?KøR1}5i]ԥ-"F 7|0; h5sg\hf̮ 1xX@ӯnTBC"h,ܣYgf߾iL ޹S̸E!/dCZ5kdo ApKR4&TVMR+EQ!/UW򅑝I+.(٘0N94wW)BK2`R7t &.n,T*@:D=eFR ܇P>CBJn:`X'#A43QZ.'Š_VCK)Ag2BR.2ĥ~̑k< Ⓡ;b?88T%;Q0~zRjz#,^I:h(JOoQ3qȚȰ:6݉8JExm mm;1!b t KJ?o7>ho1ġ+!@Bp8Ok:2 Gt  8q;~A!F."A(J2>2)ѷj)gOdz)gR`|t's!*:)R{:Q;AhQ{t ڞnp5Eút3h5K d{ZzNAv-a5Fz|WS9t:my J4<3Vn5T2ޠcdMPLgm-:f9W܍> @XgTqCDM9u0CX s0W [q~)hcH.2KHT66xLV4kZpW2vEkv!>||fAu{H,s+ChP/lY1*]+Ju;V4vYgG&6 MB1̥\OpѬƃgSEN u=H; ?2qe;S-K ƿ¦7waÁAW*乨KJ5/Uxؕtdy 4Dcu2g|im5l\:8h7FᜠRBNFv4dCI77 # OG ۏO OoJw z)) k\xsYsK{ Hݪ4P[z9Y!,eR F/A5VzY: C=t;12h6)@+{@;ݔ>]߁V3>y &!txdu1܉++&٧2xNxspd{pjz˿ߧT]]߄PSqoa8)'JUo8==%ƵGd+ky o3Zuy) fZ:9Nr0ZWcs蓌4v2F^Z& @s:x^+) יZxkV4${PIGiN  GSL:3~Q[+QoSN2Tq.F @:#)Sx4C5ϣo4UE8tp72;tuʆ`p2w հWEХި^fo>elx(UpwsvѬ| w]mkvCA]<<hBjy$'dvf4B(gD@ڴW0Hjwq"x2) mTG8si45+W" =fv(Oׇu~?&XWsp1u;pyiF$;gaR}ƴD5swwJOeo)~2zڗ0 OKۢl2y?(rƑe*kz+h s@sCug E=ku]Sɛ77.& O;2)0)J'enzY{8=p^dhBpFuYݩRʤ́Gz kDD[qd,$>/"FTmG7 ,LSUAE|"g}ȡޔ1aĝ P ˩#@_ZG{|KKSڟ尐`ږY]kO:qZmqWMNfnßd .Fq{ޓ).UgvU)TPP=#9_3_8wYƳq\cKj2 C2At9JW(vP hN.+Dz+u= t1;_s`o6G?dl=g[̮M=k}Yjo<7tC45щ[r@צ3m"8~G:*rcgQjs n3R]2 1rҬFp|ʧj()gQֆc0?f:#YK/7{2Oɣ*Ftg$ czdzmY.a6 syH].΂aRD̗&zeD˼hcHljxI4ws:kӣ1Jqmʆ SYzB"|N)Oѫ qTߕ7i4Y?H馆T+B>sݽ lHEl7z@O0Mii OwL>=B%,(mâ)-sKߪj5<܆ژ>\-Y1w >zWgm| ;l3-1aqG\=u -,,'Jn&ݞt[yh?OԕeJ\UDkۿ`y{~?(_뺬wENUX~p:+`wli7Bn4$GݬW'ɍ>ߙ;;;wxj@oΏe T:(dSc#׉6ίp.*=Ь\X=@)$޹q]$m/M-usSѺSsߤB @'aE5J{>!1c遟DVϵXRU6n=x椰UQ(cAȴDOBQ FDʫeo1ej0=MK|,YH,1 = t?Nܓ/TB,[n֚&^O|um$]{_o,ajI? ? Q.CK7n79:"vuEcx-Bځ&s%PG9i¬>k7;'*X*Uj͸|淒iH+mEzLEo֏No:u:`>ne9ew.a"ICVM2JY3wǞ\j*XKF(װJSV_WBdE:)vc%E۳c/Rۥlq\^m1` 譹&*+T3+kD \+4&V @sȶDb85VZ3LT*7I=3{6&EB5&\9$b]AX0}$_Z6ex:Vf磰hgGd~DYj,7EQO;7kKj9D aK俛F ukի#nju[=%Q3m.]c^GƒuZ:tvG~IE1=Zv:Tj Ӄ܀K,D62CH=Ց#Ww (tGJD^0q[6zQ{E}"[wV#ȯYz.'-G, UgCbc>-zj1=,ڤ)dmJHX>L5b{Kߖotid.e{^sbscou>F"!bц`d_z4Z+|hJcSHp:a291:J[}4V3*g5Əz!EOPk&c;j;5O*6}y嘂կۏd?@ʸ|k`)qcRKgnX3r>#qwDkIF6*nV/S3+Vw #sB>R^cOOcRRpcG~OK$DGѴnD&̙P#}kDs]kk G,6%V"8+W,"Zwi /1~)C{wVrX @RKvȌyՉ"Q]}Xrt܏O0~*Gn*6{IkWrq716*ϐg'x B._wv˘4:''GC>l[T ͎aӹO'bjD7 LZOTSůT}> @w.rJ? wbιH81zb;s ô\ ]߹*zFiJkru+>DO+I퉤\K7$̣3ճXÑP{#_JsaU/ws7h>ej,Q! *xd2 ?zNSI[E^ =eqK9!,6 =xVK QK.f(T|Ya?M;-ѽJiTC}:{K۪)N!u:_V bd%u߸-"%wC7Bv?bs.N()dgwrUͬT)P{l cZ!tAdIp?wߴ׺ϒiCQ2{J0o`|kH1Za8[t^bU<Eb |L@tϸG`b[5%GZnx#mFtzM=þP45}wjym_U;1.ߐ&34ѳ]bBn)т׷1 m3ÒCMRHp}fmtk[s],DgG[n-%)p#u4}$ĺ}>YFW7^ybs. :F1TWb6op=߷'&B@'hK_zΣ2/yk]w5 J4Ժ,71Lհ~iTD"* a3'իoG+S޸|fE,wDÄf]{@MVU6JXuK8!~ZDS UĚZT7 6`_t& @81w^[} bY܏ogTcki6uk8Aa!OɣAqB*;ԇx~8W"m"^k'kc:ݔN?߯0*_,P zzk`S3Ym CpM Ba&_Y2 1>~Sl16R=vo?'[(Ve^O_ =e]\>j^=heRA c{4)J/54'4fpaQq#'\8o(f]R.藮0i9úKqX=j!2Fzo^l B<0`c[){X]%pFn<ܡGҡx9ľw'k$T4ʧ WJ;ŖHV*X@C.+QM'yU T'FsY;rX=ډw1%48Ɂ;; tL#TSÄ}ͩWCZ16m"c j1_4\݉FORzMeItzPT`?<.ނ&O_҃҃w-~\êhb5=%Lb?AΟ7]o>!EFw^-}T(7>sjȗCA9bG qqѺiqǯQJە_=F#ʰ.x[ݳ5c_~$0%^DAVtko i opPaq[&z[䩅WvtR*~K!ׁXlxOQڒYv0(ps.rl`JM_T1t*@|4b1~P;+}2~s{Zoru|,_$_%yCWfZ_>ʯCʁXB1hmY8hs9 cN\$HZm7;Oljvc+sTuҤ,O`5-cl\Iry ^2 mXs[QZ|v$]dr}:R){'>)\q_iȄFvHljVYk7i3%Zfv:6>q'z}r]<.դ`ȏtxAzQ))9, ǵ{{a1uKj%.}EobSn/t$}>1[*}COn dt:vUgjKS*mLhǯOǝS;ƪ5`+[qg!_;ϢaO=~/'wt@vF, `В7̝IТOE  ,ȔfS֒Lu/ߊĔD=yC5anqr܉Y7ѧ'uL'T j{taxʺ9|d #/Mc\Mpa8頇yתъT;kȈ-Tݱ qxV_ T%׌QA}rv :w9iަ}}r};`'g3ITK@ݷJz_gg_fL_?/F4J&Y*T|jܙԦ?=W8 q-͌}f-q>W>zXƸ˴lpހf?t0"o@..#O#fK< OŐ%`C)//sr =v+¤K?(ۅ{f1J*{]N^ +-cqg7ecyLyeǬ_\~ey?ڍ]4bRr~ ;BEVkjfd#j >iooN[?-dJa.eձǺE\ 19^?kȴcww͏)%M1+ qvI4rxvqgk)3C uJנC=u1PhB??Xio@!7(B3Z6)c4CMZDV2dBF*損K<~*$v3}!\+:$͂kv:"Wcy\\cw'َZve/W=:4zd?Z q40ageT:+F!_DjCQYaoc+KcO_f*{Z%gI HK_hG/D /+R0~JgvW/\`Oq2R'V-#JcnNIA,)?`uԞ1}+&nذ=:v_ tyB3E;|Êr!_k<7g/^lA=ఙ~{ kvܡ@ ׼Pcfg%&]a$a CN Ksܛ5ig製L+h/A=-Xp{Jknm&]Wx-2M Վ nfUOze)b>!!j3unX˚ Hr⎡N6dg+Y^!,c}W:U.-iV_#fSx*몙:`G 74AA}Ö"Qgu&@ wۜ9U$U>0:<6T[곐_Ի*g|v>^rngUN[jSe:7|7iӘyK6L7ݔ 1Z3M[D,Lh9JXhZr' HfzE>ɀYUI.+FQ5_Ǎ,8{,-FٻCaq4uK.1Wyؒh9լDT {m*r>< B,dE/U|Q|ͯ?R7S}0]Ϙ&,dԫr?ÙWB1Ə<}nq{*>]ϷsegTdaK?W|4/b}|ᩢ2AnY|ޫ '`+CcKm+:nY_-~,"υM6f'1VH{$(Ժ}um?>`T^4y4Z]Vs2eҌܖD7}w.ŝ$<1Taz`G1c+ǐ0(+!_wsvY܃:dFt(W~_.c:;C>_8.9fa/v.KsPBwE#y0K/W^2#z/,}!ΘV I˙xW2VQU)!-ol?#мl5Ζ6) @Cnhk/W"`Rc-y_;*v;ϻ8g@Icw ('.3KQ/a$S", hNqi<ˇ7JH)Oo\4o2k,!UJ|z/ ~zWyVb9sӧB&2:~AQb ǂ'Se^e <411Wd-Z:3~eԯ"u'SyC%cvNeCZ:z Vs㤙yfSk@.5)~ަ+ 6F풗@;+D^U]U䳳?(;]7oʔ :;58#dڧUW{oҷ!t7 pdĶuJCJfL|gzc:c[]ȒY/{rELyoԭZMm ňg3vЋAȧkl'2j: ez kM^rL^|~wWʃ"w zZV'RljIbLUtb%v{ 4{49'́=gdV.?LaY!OiLaZZ%~9}@,]?#f|B|WhqusA`Ee%g Ib&Qc)ذ,' b2>RMT;9>`{K?0{ű4.VnfnkgoaCU N9Bӛ?*|r1 Xi;U+Pr.Ê/ޥU78{i"KC>QNO8HÑ0bB\x$$v9I(c'a?>A#^F =߮T9YoVU{ `K?$ 63wɻ`l?ױ!+h<o dzhEY#_x|4 ?lЗJ[nWװМYZ'sѹ)-Ңl_ߗӱTGsp(j6VVGXzgH> >A~dk.l.&nÜ?r&?ɤvj9A=(sx*%`sEFuNle𮁵}z;]lI,p?e/f3"R`x>7ËydFVƻ6-u//izgs+NLu ~R^vGwy9XTrln/ ſ RF_CX<34П3!;5}T1~V,P4AΨVV[Y|4~[h (p܁sb[PJLXN0L5B6cI"ϸq5m, rbӸ'qp[ nd6(sd.ẜFoSDo |Xa?^zmyg4zqg17_UÝϹ}}5?}Y_%+,9Ӳ9p¦intY'5P^ 58̹xājs  b3/ǣQl|!'LT@FQ1E&.7Yu}7 ٶvL&c^B#6nϕZ 3-6@b<U\ZCP_3{l}bxF^A|QY<8L3u23|Xg6`Z7/:Hkc%dp8AJD݀]a> ~T32|Er}:,(8]n¼4m?sW\Ά^44i25rRB"6?.'yC"plgU&n{x4Z) /`s]Ǣ )jzw}FWws-jAM3`A8.ɧBCp|r\U9a[|*!N9Z@Em^>BV ap -Ok&W 2q}3uz9Wr]B̠?\O\%2%+c eL8LݷשaŢ(GK 7 X* ")AsF:k.uq}:C}6ҫThK;W9"_gf=ayOД_I|((s8G~.gWVO-O#'WV[X0I8B@Շæ>QCEj#3] ?k8@z1q)!5F 퍘 [^=[} N $!Fԗ6^ȗ)o29#R QM^6Y:^ @ M꽅/ƃUhra\lv%q\ LV@F$6j5C3J_ҡzn.28R(w^tLoRI`wQy^)8Ӄ./@W$@{avʮUCuulv1U6漥BcZ:%.wi{F)L_Gf/cfٛx\rbɶsm*!IGR\`ʒ ןC1;˄>p 4lS,|fp_>fBm<4=( `ȷk&%Z[LvW7kP|7X }!q_75cO+}8$Y|l@euoBH(wpWQd虗bk_tݛ0ҴX4M0I[F;g>zH!`orS.ߚV{-S955; ilxN%UesnS?PbLM6~0@,'a_>J =^E'.fhqwb90r0`sL5pqg;刟= p/Ku^Ϻ8VGεqV?+)>KA^_@|7)%F$Ff<(Ag[ҦiZc|},\Á01/rHkvuBMEIUxj G}BKXrZ`搲8H>E7ed xOYA!NguE.a xk+cQ`kwrJa`uUc.Ӝ,?^)9f>f>Ӟμb<% Og3 q=窺Rև [(bA{G;T8 vs|jOo&n)q{(2wlAg~x+Fs[E]jvӱl&8@HQMe+6̗+ S<e:: ah &D`Lziƻ03|U?3~Qajp搐ox?Fɹ-uQl- _%1);]o?u {Q|SjSj9XFcXMwܕ睠B^)"!ǯ5C{ P1R'`o;D%K/z]'KWܺ&P; U{ x<#c6,ߛcy6^`HQZ3Q{ 7+_m6#R%1)zmgQy5외'ym/h$ Ǵ{0_йȆnɃy߰o\]s`Q5B6t [u "Ӕ՜ssBU|tK02H&\ Tss7?;] V+ .P4\k*&QuSo/ۓ<>m23C{U޿$jk$Q gu;rh3-rV{S})˟n۟S)Z$,vM՞n۝r!VC01wD \3F?eu~n9P5"!+;zq %$PDs3ʇ݇aO2~@$w: Q~j3O6\8LvyR#A;㣒I[!כʑR1q8+@OVk0 D"a W)OTZqzubIt?Ϲ[ nA:Yx=x׬yώBO8!aK''S jSEag?PNj̳Q)~ ܧKDb"[ma$LO>M7Vn5&Mo<C1}tLl!_q+Cм(7zo Za@5_Ec932(7p&4#ԚbYF0 PfI2v*^58 u }H5 ZskOS*a|gW"UnPH|ez(DM^<|ۇ뢞@K R#P~ b;}EV!aXK\T(zpy\30kN]{:{RFw!6y|:: 3S/?$ac%񍹮U"7EL eӛ' jB=pod.!X:̮mFpzs`K\‚q,dZUHʿVr[wٸ|IZ208 m664n7]))7d=Dh@7_fvZmͧZ-a} [zeai>}Xv BGu2[.QMy6OWOz_|>bsz +7cj}BV%R(˺͑l _`O?փ7- ?x8f]([C1hqzk\AIVV^!\|gV4SB 37ΦFZ^ض?T%2x yNe5pH ћc}rٴZ[DU mF={ swKV<~b|VvKdvsC6Emowt`srsX,̢C-c57Vܕ'{)͉ᛴ9 r}i[{sʵ0#'2t) so j1k7/2My}ݶ#Ȝm:eRMOr71µ:^@3֑ &Mx/$ &:pSg;Q8nGM+M}|ޤUM3V#2/ 1%$f<=Vf>Yx@$v88{N?AFVjgN/Xnvlg휩nuݜˠ~eS࿌>سRR u Ĥ~$c-oAU} yU>IߊxY'@l/AҫE>;k>s "05 s>F F/͏C\{tcX PGp룒j4=fK LkҐG .:hY_NӜ<p|򇙨73MaBLeЇTvq%unƏf+ozI+ؑgt;[,:o? B{ӹ wcw08#]՘_e$;iVѪ(9Wy/ j[:9in:2 #<$L=i?*<_:3Zk4pb!f0fr԰D|Ntۻncpp;C֦ yl6D%`4PQlKR~^e+O\ҡd =^.[(o}z6KoC %)$ijw~_ Sяa(ڂXM㿬?jWo?V#|& \@r|,g/sSvv#:> WT-=s.{}l}t(֑kN_ .=ݱxVOg'2öB1s) nx^j51ϸaG-]lTTfq3& N[h& ;^yb7j=/{Orc}Qj1V~OaYu!Vf.1W&y02"v[Bu2y , `wMGeRΟ.|__yЯ[u >g0Z{ OH{115|:wn;C˴EkV&/`um 0HY!g8zYNC`>Bm_Ob-SOY^>\&fr J{2*X$37/:~z!ҼC϶ow|OF7bٿW+)5@k[gӡ1#.!)e)߿Gd@V'7NG6h7Rb@YtbjoTf/Kc#&:x~L)!?>O__q2N"&5KhGidfaq~LfB?Q-b;?}H YֲA?wyC甁:Ǣ0_V51i| ?5f/x經{~@q.Ym!n?J֙1ߒaw<ϼ JHhAj"qoQ/^֎ z(x֗Z,ff@ꃚ ڳ:@}XǼ؂Wh;itȈY;*nIx/ԱS;=VjǗ+Kj؎LV!6Gەea) ne^7;cCܾ 1M6/VFvsPGe*{Yv{ZZ^r)yzƯ{!L  8sgMG2LR+ft<ס+|qB[G mMYӲDV_Oޠ30nJfP+:·Gv]P41c+ݓ Y*-ͺuwuX|7^]}}a62w9:-NJ/b]wzMEm6}'Rl+Z2}~AVIwT]!' ރ}x;O|X{ !ok~¯t#Kh[VǛV0q--@nzl_\jma>Zr&!Tq)^w_aTj ɮ9j]l"-7;CxHDe;<2%\eyo%dgҦpc3Gywko C|pBv²0g4C?Q 56KyfybDWVƿD oMK"kL(9 ԫLjv{Sw}^:P;M!1m]rDaF ѽiQw_ؘaל [G!&p`׻uAxG3.k4R@W 3̉>tcqj/;]@-q6aě~ R#Jy| KlE|05[tfi@Te8}>$38b,[Pm@Sc㙃ϵz_r&)^7Bm:eCB$w[o(ksWiAGP;X6(2mغ.L^XWD_Y#؉":)~s/{v4:ap1ܟ_2wP;2k'B5UZ! 2+⌽H2tqZ3v0j4jV5bs%7_"߸=a;y0Jϱ=RSv8r!=ďzϽv>Dg8mIl=s9g*K+2-{42kMK\F4FI)M%d Ov 'veUu/c6TgJd=;|mNBZ?b?2ޣoAo\QZ05G5hp$̂Ev /Bu 'ÏT D-؀k֛ǙGu:i 9\5 |λ~R?=)/hOmBaK6wz"9kXX cdbsl7ziq٫fJ2:r/:=;.fT4ҏ/XÏp+ETdjZywcĎHIhK#au#CAo*B]xC5bέk7v<t/ÚG+9/o$vG.ݰ 7Ltb>ƶu}x.V<0NwѠ_q>;!_HVn-݈%̴v*oD/^&!PF7O(Czε$ZᵾI=g=6ī[i9RfTk[_ׁmP =|*wXz~v,9bxG_WQ٤g*^gghD Z[5FF9}gX)i~NG[Œ v7 n{{S(6ٸ=q._U O@(!-?kdc٥?VP(47i.~{(bpwU^ jiȱ >~*?/澛xη_(0QDt;pPM2!8Se^&r 6Gakp}|ٜ<{2yQxsPz3ܡc&0 R:$F-ǧemTvΜSLhEUa.9BN~j %Dbiф^+=4ϧhjl8!&eGvd\5a.rh__y?ϻUJg6FL1oF/ c;z=wo07״ִa]T'}ЏvEڿ0|yPꇗ_:^%k6TAb2*}Mu({)ĺŎBxrd"`):Q1He)_cۘX="[#ؿiy(V%zXhLW&vQ~ڐ*L.;hXCzzP >?{`g:j:h"'kcM}-4w ^<ӳ4Y)bs}H@ox= zH*iF:gFM>^hހ% 9xIlыo~l{Daa9vyv2ODA$*:fߋ@iu;0ڤ\ەDn7\Kb:\sρ5kTfGioQ?-S;kX?kC#M1j/=@/IVN;{5%'b;<, [J V}F ٩XuPvo̼ߦv{4Zn'Q]櫭xa]o}5 k_XhJ|ܺ#"ž}@l(t q_Ѕgo Pl n*'Tlmq>F%oߣ]|@M-9-G?:~Q6RZSOYH> [tKUޤ_f~Kz3v_HZM΄V א?XU xVBԣF/ϳLү+l~o8jR_TTk&9 Y(cT\,ѝ.S |F{ Rn )m`Y>HOy]WoV.?3CXs܄AsN bcW?D~` Qjg&g~%gdp [Cg0 ?#66'|2Kz;]-WƏvO-¾ Zo@44mՇ9o1V݅L8'D!Ec[Ϟإ1/+꡽{|Q@YFVO)vDza NYE]]\t?mb:[rCpF_)Ta-&Bܚ#_RwcV|0/Mu E`w^-DA&φj7:Kuю 2YV)I6'KQ_x>#k?{,iw6O' AovuT~lu:go$ѢHNSo)hRB|vui- ]B_p ˜]H| tViHEU= ͍lXom, r~f]͚(--U8ܐ/R9i5f3f=Zْg [hT\_ǻ]b2Z;lГ]A^'NHj.1oLQ| oQq;<ܪIa>C挟+,o\^<Ʋ?C$x 5Q+./ÔkAkGSB"I~!Z=](WaZk ekN+R?@y_PTH:! ao|`><yM<}q>1[oHe{W.1-ym3qj w!/?ѽ 0'`[%ZSrڻ?mG;;dQfig *j.t@g=>utj^05;WRsNQf/IwDy/{ljK]hA_N擋K=Ǜ<#_-޽iۨ)[6~ja ߋeˮ(qd+}E[p7fztXpjYjh>X݃ܫ<#0ORfdtf%Oq/hv5&+W-wOgeȧ ~|.o]kzA?&2ു>{ X-gīAC pŐk9/Oa kQx/[ݛH,_[4c`+Nhsdq9G@_&DIJ+ʰ85E=7.Ӏc;?/%ҶhJ+^Tg|p5.ۣ ճ|d&fHGh->}_NmE4k3AVhOe++]׍ N̺ض]>e]&IT%_}[P k r -X/cvߖJRrl6PZ7x\q469F1r4)L{8Zœg/RWFj^zG>3p fu,QJ%n/ #&, 뉏z "$MG2]o9c_Z}@1& I xfʭ7uQ-S̯|.2:W2$`.yrxz :~NӽahwÊ>UܪeJݫڤUquI^2Ϫ6XNi/f?G1X^>\8߭gf`ڃk.RKr0늾a9>Gkl;LxvB]te8EE O("enǽd *FDPGAm5~61TL*BUAGz@g^W~8l5]u'ٷhYP6 PKnm^  INTEL.MBKY |U?I3L*PRI3|B $l]j**BJeICRLi+U]ŵ֏JYVZNni)Is߹)(L;s=sO֭~@ǥg ; X  |1虆ˀQ/%Х'E`g0:Fa 4?@;6 W~p- +30b` : TiAH}&K+@a4S9t']mZꖶM'qvIkf+nb/{D1ՊL9%Bm s7cj)֘pDamLW؞t}2;*1Dmir, &h&"Ön˿oM?g΂ʃ:APQ\S?Za^ k#eFttpW%YԀ"6Lwnq%HyxFnj2=!{(VL8m+񢳵m{Iҿ.q\zV Kݢ&aw7jFzFwT^ahç'zoUd,:4)My4GOan_;W&}#@vVgeX~Ss/C< U=񖶵Ʈ^_޸kP9difש:v o1(}tm"eD3vԫ 6f)0%M/4ƙWmT_jk?{G+lMAHdu9u`[d].Pd / a :GéY`/|5@RK$N'"[_402c1XL%wMZF uPI [Zq%#2ITCK0ƙ.g\D=:\K".?=.@*j`)-AUȃ,+C qI2u'UUYؽHǔaք[\ X~n~nS8>%Bp`gϻ`Ws=E;0*̮|H`3MŸ5=QԟTj~uU&&* pB ñN0ⱥkW>ַxYp:^OO˞v` eI ͞BRXdG Ă8P88e]Mf{5ΦpG@j,k pES O\HgJ>64t GzLsܹlnAڂk7:}|ڬ͌UUW)vhLF(tLiȝ9n$Ug<<$hK&,0{<'ULL]k%{_##r0j9iN~W81JHꪓmm9b֛Ѯ=v4V{ߔ~h2cCy>MUhݐ5]P8k£~UTP> UoA-̻ Ÿf Ǜ3r!3XF߸zٞ*f̼}盅ﺛ+HUuYFOJ0N\pPUSRCjFB:c$PKĵ<-@-9ZU3Vx`(~1Z|r<U\ ynT9=  5N5rZpċGY8`uH %e/4]E~"Gg//EF 7omg9-VYtYjq0h+v5s0 3cCwp7b2 `@I%r!Nh 1CpĿ)n9b6sLB\{(jt%'_{_>O<@eׇr腄Fr.xJ@-x ,#5}e~8M1j<EA 7AjGwZ!~G&I? N+Z,%ճWff9~(ZQUx8pP\&k*oA)1"&o*yG+B?XMa%#5YӜB}Gyëzeɗm5Қt*BKQBBo;\jt"dt 2Qq8 ?<3;šNsjF|"#$8̄+܈.Mng3k]!-u*B PkЂ[O{Aנ}5xÀ֌ \MtZ1zDZ 7:v70+X!pcѾ?@91ƃV/(|t cc@0[Gaz-R0yv&ݭ7%rz,Px; zga#5cO*!ZwB`" 46 h0 S)$,㗸YHPF@$$}GX@.!n-˼nm&B)6tZH.(ϋVP0&lG -8C-l$0A71Xf/^GmB wf ˖zXQ&q.qYTSŽjmt9:HÎbMh`%vmci {≻atXlN0!&jteCtP!c.%aǴ{ NcTXDSsu&Kh&=76MTApbQndBխy2J6]blÕ n`ѿPBi=L8ɋ9(!ˊfF_F눃*O`_1!W^ *'$@_:!@D9h*b" s8pq?m"QBH <9(P .RBUD¡zElk$ЗY $ΓAt`!p/E$1M AΎ~quK$.ReB\10I1zDQ/EA1fmJ2r)%#$!"9Ɖ^#ua; L=lq 9 C q!3jj*C0 gT^-VSC1^ |zu#w-#Rk|KAsDҩBJ{bހ&9v `@c1;3xrW+P|<9Gg@EWZp 4 ߆n" A'#=% $>(B;8YQs9%IALs`4bguTh;b%K69J8q cgHZ Fݸf!0Ek(1܊auo;zsRٞvZ߻Ɠ99CۻnF4 'qyepNckxu,{??>dVzz`Bjz͔Bz(\0U"q 0 B\8Dc$ z_1 IBj|yJz%N2d>r1]>Aps8ϾJW#n:\DX|[t12'fHgXr ɸ+4/wuh6Cɜmb(,EIVĹܮ#,,fX"N` NMMVdEY P1`D^/fn:UOGBo Du_ g*9%.vOO ɍzI}oʥJbFSi$LX"">lWAU0ma ~[C .%y$_9T6r#[GDNGH=]IIE=*iIu.K eYpx# F[r;xga`VOvQ": pnepq ,k$/YYIZ pr#Mêu . .h%P7S& Y.48݂[$NpK,Lh^j*0UNZu'/RcܷU'(Lv6*]G[x>%Y6bJ,06a`y`V,+x_Ea@Z{x+MHxk JV֒u0I;D< 'MUzÒz?ç)dټ~>|M ̮J&c΋% Ki!o;b>0]Nm -d)xO =e1Y{ W?lVEFYjwpD6 V.BFM  RJ  Jja3)Lg#3UI [kdʱ_c9 n彃8Jag:}=LH 4K)'9k j[y45`\TcfUk؆/c __ ~ q-6Ǎpbx }_?z8Ƿu؄cp]#W^Ջ5/^ ;#Rx-<|^ ||*Mf'|.Hd8F'Nf[sv(Q3Q𼪓mΓb1\@y#e3"9^ W0d}E/eDgrdN:VK&t$q׏ BwOc$*|{_/K{fVOOc jI;"twK){B)Uc* 2s;6cb>mcH}m1+R٪7t3e#^ g#PqSqvhNi}'#-Tپy3ڴ-'Bagwtl߅y0 ;dKѤJz*̂Ѕ |F)š)h_PRB#SC)wH$Gh,cq~hrHҋBٝfe\M-ߵnd;:w yr5Qo3!G$QI#:R'Fhr,\+a&A.pI\?̛#C[E뉋aMwo-Gܝ7'|<}Ʌ_ؽFTW n~UHɛ'|@bsf2,?yE7Gnj:?7{Ga6{OKbkf۱Xkaf֬2*C !+c@EC1|!nj*Z-[.ST\q]M|VybG=VD( 1NuDzG) ahIIEI/7rz"EfrI(tT_ƉKR\#IQB mGdHJyh]5J?bgWFNHPKS0vmKn&E(~|Պ^]`]#D h50}tN((}up:$^+'ve*Q4+,3RV.%4H!|9Z?5tZAN39K%R4~y'Ú'L*ҏ_(>$!O4a;fbD}e&(lhe׀T20EU2e;Wn &"mżU)hxMɍpg@Opn)>WppM%>M BTJl"V#QةHqEK,!{ǖ%w{}Nv <%q~ܼߖN% 012GI+N=!h#HSʁ Z;ZC$B &6uڭKLN l-M%|f סQ4 UE|!ʥ+mʋRW6ۛ,IuQHv c=k+rn?M(s<)CZ$|(A)k{h/-J䙎xKD}b{tƧӹ RiTorw:ˆvcb;N\VVR|wʏ.T`C6RG\>1\lBTC G!틜1Od3ǚ3ޚrk#g:z >0IC{ڶᲈ85XY7S r%ef<;--6h]xf$ov>T.ЫqVy,8R4;˝XO>d z]Ng;đObP`h4 kCkݑOy7r SHf[nz쑒{3v c 9V$!H.e`0:xL!.RQ0h B|;X195nFCdžn Y''Mxt ^YSE%IޫDP$í+'Cۻ3n!87aS0|$ZRfCX3Q,~^uTfVN;^ m6s?dp[L`j9Zp2 *Z׹ ڂ:ge;j (mqR԰K2E HoW pz;ڏJtOO6zqkW]e郾16OstU]>(r4}<QOdys EHb:Ld&9|' N/PW҈;4}gFWEOH&Eh(0p a"9T9k_a)mL}^,$™i|]Qlv*B:~`n9p]:ObyžߒLs I_:ZzJ$,Ar#ȱء賯ttu%sFLd9MIO!\yO2(ZM^Bb5(k9Te$,tzAaGʣԘ1?*H9SO:{PFðWæcM*H1\=JXD0/0|T:pjה 㪔K5'y̆MH^c^\zB/ \sf#%]\Iq~M2u`0BK6..™>!QTx4N39jeT2Nq壶.بgaʰ$lgG0Ał7oj#m%=A2(l 0|-Wc~S|^ A$XqsVFpCiX[?MmIBIZ-LztY_-CHnԓڳ<# L hPӺfˎ߲.N޾wLq{cy(X|ձŚjEe5PVػ<]&̣;p*;g핆Mm++I\;S#!ƬR (#lX-c}Rjub$s\ڴT: EewmTx;qS6z}#*DRq/E)'K< w8}@- WKV[")N K LGX93eTS| zlJJGa ήD( HT*L .a`Ÿq-w;$&e7وacOKTH$Ec#eGPʣsƓϧZFXؒU?bVBVE[*Thl 7<ńc`kIq)I01u˔z(~l2aIfOn\'Z)A.Xo(x_?WmDG{HHCK[l ޏv7Miʱ|7 :1YdjkFZ!8~}\# [&=7$kΘSF}8D])A,Aӥo^~_y=k)|?"/2,`u[.g/\taYU_HެHoUR뎅VzC*=\̏(@6.$բ`}~3} z/u8G^I^n ri(g +,$1 ^CеtʔFKjIhdy--ފ?gH\E<֣WZ"JvLڵ#>K 90ᅵ1bsVLީY<$N?懣5ikKNWRݾ˫Lo~9B!nH:5ehDؓ,aHM0( !# 1Vj  >g ZM'~J̻d Tdٿ1M-0[{1\WI+;|KgN^ k+A߫`EK( ўxPžx2G$*Lvr˥6A_+/1#3[[ڧWPe 򏑂6z|(#iu6U]C $bVkҾgw:I;\Cr$_b<8bG.j ,aU3%t٢c¯ z{l?c;HGpZE ' WSݩ^~mXN\dQx%m#huK ks3B H^&?7LXAuݫFHz ¨u#{7-_6nꯓk֍qShnBLj{x^ܬ1&=gh!7_w[ n2VuWl',>I:[l>u7]}ß[V~hZJ(nuO 4Ċ-k|^5b)ZpZQ iEЌ #O[ 04@hp4k*P%,1k2ɜa}aQ’Z0nF3\}I.w{?I ћw=]hC6W#p㔣ޔaC2A<0}K~%e-norݘ d>М2IOy5!Ab2CnS[qRW%/wD%(T]':<3'rEJu&"#=9eϔ]S]OE̗Lc^~ɥޅTjPV=Mcb~k!',`HdvRV$B;( k}>pQplz7FJZK0d"F0ta?^DgD0/bd_ [u2[z)J.x\]bOK23KzfőNϧ`t#]]|R[,k skd<\1AwGհʰb ђbC .:\t$/pR2ݕ4t%^"ϷM$ F+?%Vq~ncUE+ʁnb-xN 2}}~<YO xwW[!=vWTòZ֤)* e_ݵWK=1#;fgl?kP$qg< KTnUzK˷AV"J,MFXas\=FdQ~?P[H*rv$l\cb;:9MAӵoƖp ~ɰc:gBќ]Hpk4QU,ֆ^}3 2fM!+ÞV$7];ShȸDQ׼An7aݞk{,o5Vү2O+="O5m3FG-a-<"`3NjM{gal@C7m^#ehd2M$kjrJ{gc_ u'$i 9އ_G4$o3Ս*] 5|B RG&V'^ZU`5&/2Z!oW+KV/d6+lLOpo=8~Q<[ךr¨,VFɻHJc\ [/~ΑW>Znxxbdg.bϭ#3Õ}zN׉kd|)@kxg0lBh_?E[yVB]获Ҷ#P6["y^Np϶u j3β!x3=X=p"> DrIRq<$|GopE5?F=7Knl,dFld/s{f }}` MhtDc YhW?})3OW}_QTU]eidN40b9/mPC4ʍmSa'ȑ !:#X7> 0εQY8W|"1r5߄ec PT˨V{XY*_6kr]φo<|͕<r`с# X LE &_KO Sd[=PzWVVm0/~NhqfFjN\ftʗ O sE(f½G:y&w$:r;B'{m{ۍ8Ǿ%-|q0' $"¬{  j2B XS'EY~\DIWml8vGpGKw7;v1 ֚ $Q '_嬀_(YA$& @!~ +ICmC(ϴ4wOV;"TRa ɳjUEaEO"}o5U ۈ=ެNF$[«h h^K6bgu, ,E63^USAQ,k/{Զ)S|CA%Sm6\Ux:.\ζ?D׆uC;LKX //Pch*u O8>|}W DnoT(d2Ty{N9!R뚽ժi#{>[|m׺,}쥏zW[@}x_%Wu DMy_ºuAv+8 ҤCmXlIX򂃕Ph`։Cs C,c`(>Hd~\9xZcSSkOWx~Vޖj ڏ0+&,I9 k *& d8>#@榽ߑca#aRS)n᝗\ĪFߧ$U3˪g+ńߚJ_ipoR`>S̛55#ktt8?i <_*i -)o#a`Jcg_;gAw]ސ; utBj_ hEY -Ѐ&)dOǟsݢa-ceiהn5il6\ bm*bkEA$guf Uai y(52 36n2w mduE їa !3`žӍb1$W{uAyLAb,EMl8kLY^ӑrK%:o6ե6LnFN԰-.:>^z!nn+kmW޹vΆ d''\ɧ͹e&#lnR56Pk/\ly.S3lc+͡v Nzxi~dg@J-7"#H6|.X*%[L^ymB=]|o_wM2KTM\'^S2cZ,_V(NHrCNHaĜcsyc|x=E#R j|#|kn.QHKexRm¢18j Q@[ *jkyyN92DAөG%NA?r];!-E -S{].ꗬn=TZ"6aDQP5(֜,? px|5](ft*X~H[cչAu5 @t2\J Rj7\N]рnGu+.нN?XezUWއ %z6鼔ju'&UvR:PQ9مڍ ђ뢔szKv蓎hHǔ "25-; L?OJWݙD#Rd- F<#\JxzWpԮ0rԚ x5ӑvUp/pP*sZAv꒮w:•HIGAµ|(MEqrb@"~Yr7Z0NQ60tiB.+Bo^4TTO J 򕖯וྉpOoEKM!9^mt$J pKpAy#G%(Uw^GmDED'KD E g]:CAO]68JJ+34 O?z8HώTCDcp* oH0!P8SmS%~hJ2ȝ 843]#Q(ٽm *$rX #6#z;1PQZ&ٮn4HX9<83 |ZNlF48QPa!>;7e.yQ6[%m/-lXBy!A C2|frnK 'vfwS@>̕ ޫ3/m~^-Ar/,rjMɗk.yۥ?l#qq:}|`6;R=k7De 6C=kփmߋ =KbѮJ!Q /w0Ѣ׉̭ht\^Ey'euoеp#Yi(X?:u1g~?}j_rP*LڰP65 \B5GE \ ̭ Q ;U>!z(?L!hzmɷXo<Ppzv@8]^MB]2> *ZBb1_~o^K!ᧀݜ)L| vָEļpqH><떹k4&Tk-Ch XˎtQ hur:``\^hj/Akl7` 7^۔v>Cݟ ukX ![ R_K+K]rHze\gLF:V%Vh2w |΂]ݭD' #IR-ΥchtA{i[}!8k误B;̷lTRfߏ>_=6ej!V?f;y#z“!>RAua "e06,S@]n9.5W>\.qXkzK+fgdu$&!JHD~FWV>PghdA7E! $!n+',@A 2Uv& Έc`;@ޮXV`M4ƬԻ1uʃmf^#mC!|7~&>㗌Q-qZ|%p&qx*J)כb~祽g;&]N:t";Vᰝ4@.\~[pnڷ+\njօ,F ئ^6gv Z,`ǭd3&#/J(MBhG9<V~?8|$k6sWx:Jnũ͵K#n1iE-wp:;eT1h;l opé"}+E Msm-m5w@! LP2jD"yE- E} $_ \SAAR@R(b6cd`dT5s_< y,Z}.W)1%f."sz%ZkPG ~tʓ[ [4Cú_\_XK`Pz?A[ǖj]fFv07NDɟ;˖kϕd/4Sn c16HKxŖͤ)x' e4j\(KQSD28Nu쐄sN' kלvV["9]*r^O'\%T|PI$dA>t{ Si&X rP$tyn(SP { 74:W ~oX9"1%z؅ P`sXr7y|3tG2;₯}{HSP14dk2nׯ|WPhKX[$JCaRs*U6Q_sP0[uce0D#iDY< X%#\9LdS_<@IF"Jn .wafJ45˶1f?YɆ.i1)//2uhU) "*.K"&rBF @M T > n` BL&ەwug &85\by˶]bɛ좽G8=.H3t݁޷u <rcO0*,{U3Ρx5n /%äj OT߷/bl}\5cw+w3M1\uiӑa0_ m@addTF=[w2(^i~{UmiəSc.lH̑C5uLa(yy(L*+z+cmQ`H±aƿ(ywGsߛ»OjTC{gDưϏNÿ{4lc.\paf\~_.LP ׽ kBEp-4.Qǟ'f So-^jڌ=WeLXSk߰cp%A=Lby\:4wzzcݏO-7lw<~4z$ n3 ,<H}8V75b!sj V$E0á_ oC1RV)tW&f窐ձ!s-]u? f{"ܫ8|6S^2r5>u7><鳑_=>X^k*rqe|uw%ju&#[^2|@-B"U\ 38r&f{6w#x 5xſ8d#{x{.7 zՌ +Ckbw>"aED-q߮%擐=,ItR17IC4B4*,jE ӾH=ue& ]0v5gR⥇ڶm%%UœuU {~5ѱoUC>^)ڕ|QCfZV4FvmBN,V;:ȦiImk_(8~ Xq@@7B4\x.#Jm-m]/jiM'/,Cc{$Տj;,#gDK.m B'5'nf Z\n8 VY*ߡ~"ripd1;tяWG?] Yp3߸"(0b E&4=A3/6afm|i|]I$oK?HO9r>֥m:4uY 3 BP:ga8mPP~a$PC ޗyMU x:rD ɓPsSYWXr_g[`Y[Bßz;?="]/h-!/o,S\hPܠ#tYW%O)l`n"G3>@P}Ad~bDcz'ݝ&ޝ*qЧDy[A\@QD^ tmwXzOz8/8ze܆]~zoRmWΩI2%@isr-Ũ=G~ſ ?USm;Y+{ΒB D8p%nO߶Ž;}㊵[1 [Nv!(sN`c{)S 0ގel]#T-QRh};+hv$4n(SIԲB8 * E"B2;E%Ԉ31J!r٣3 N>}^# إWԼ-F3#aD~H٨ZY˼㬵NNMޯ&)hr(<1q]l2g𬵓>UH|;$@lDgw|٭eNN?ݏX߿f;ܗ'2878^ƀ-(+ [sI)ąu⟌].ϛk2)xoz5 (5U,xZmjD5f#xCeh3CTf6y0pȧFc4h5g ,cZ?Zgˤ-!b~L>o<qnkaTM⟏v~䣳GGv9M"`}Sl¢_|o;;~mlkmN4MCV.ͳ>_o G^5=ZՊR Pr&7%ӗ[-#GT'T&G O LezG, )!A >i`p5ӶŦFK`ia׊= C5ǡ|ciGt<Ŏ) ?sM1(>שv;W@Yv\ks\5tK'VWnN WVvw3vvIT#:`oz"40,p -8UAo/#,˓'2c~Ufs98vIDߟ֌:!)= ;L=\ AІKVt?Z/ I柌h6[!2@~\L{[לoAqدFw 9`Ui~%p'_gf?#cYbC}o=c'BBmkpv1မu1y1t`f&_YxxWZ-m\P9\IPYխw:eQV+4GD JWp.ц4}%fOjNuⶦ&9[ͫP|SZu,, V0Ŭ xgmcl˱A(x稷.:}6T(Ҽ%;| USbjS2ՅB噛PyƥGTXy&8rrdk э8<Ψ9 ԝơNvH95ٵ?C7>Lt*}p7ve-E5M+]-Toť/άr'($d&KvsB)[_Fofo#iU\{.';Y%G:!#!D? rR B8}@W8J&c98zʯCsL_uZ> l18+k5 y~%$0ZcMh~ B=Dih%:2Mw̙75as6cX^eh y4L=u+P㥔qC#gzXᤄK]6o= UgspP]~0Z8e]\u]TwL^E"M_BC݄ I4<!$C&J_ze=4L \5!#Ȕ }!,B2B-jO*Ah['-W4d9Wcu!G!{i[ Ǩ5_im~kJ15o3+F,1ڊ?Y7=?P({^&38qOZ](SZh:6?/<ӫŖ6oږaPS#. 1;7rI3=~yF }mkIVo2 j>վ|`{DW;oY|^/jSN5Sт 82:eOjs6b=X,_,ؗsNˡ|U|%Pʕsm"#7^:1NHҐP `]2i&d# !e{ F3~Sگ~M3􅾍!A߭gC(?'0]5_:m=De7`YtXj׷__<.ǴT|KNXVO1w3'N |CSNuB?˃틫p^) jQNrxpÈ,T4$MP)^@`g1ߣPLdz;@ֻ@'Hu;_Ql6E}}%Pr \@3Tϖ B^zz`+ 5cmY3֩f, j緻Gj._3nm3ZT/}Y o0ZK~԰4eʥ<*9:en2x4NAO_h?6.~뗘kiŭjJ_E2z7.с`n}uqm81[Ǝgg"gk={xG{!o< Oe7mBNJwTMJG* y"EG! rB\X- 2Qh }zb -3t:`OLGeFEj83%)3͇[o On@ɟ>}7Nz-m/"UC d ,5N^w ;G;@E76u7è ?PKue`{V FRUITP.TN1UY XU dO2Pd׻%,!+(& J@jBjjy,ubF j.b, Y'EJ/'tSd''ϲgd.;i&IR"|g#(w[eme=-3Y}kRt `֝ ԓXN_lB5ɺj/VJn얟J ;ju&Xx+I_m$)߶䷐-]3v `|;j\dd; MXyZ/J1$Dl EhI iqO7~}r!Ibnv&Cʷ87ysO}_ m\3g^GH^TׇX2|eƒҿW,p +jn읺$ơoSE}3y\AfݝU;e{LzV09r⛏i=mxblT,7\v3t݋/́vgLJՈォ+|g^q%۸҃3zW1Żۮ~ѡ][n6?xfs-҆EU6+%?\$НJ鴕s!cY[r:uDlm& x s;[ۚlb:>H( z%8Z4ŷך8WҘas=psw$JcWrTs]i :BZEP(#+< *<~n\Qɉ{-n+̣lQ=ŠI:(T*}='#}ő}FvwMryfcqjz~i1/F)`Y=R,Gro~5▸)=2P#ݡ0[v50l4K1)v~AIa:4 x {~~vI?E|>,bDLQ&W'#>8 7^ػً ]n?dqˣ gݝw&/8pj~ ~]起WA]}}'4/F@lj؀$ά0Lb5{ɪ@֜:GߦnM]T<>,E+7Wd?7N7uo׽:!mhb_ްNz9Y3uµ,\v>bBj^Kv_Tm~C{ ! t/ECfKÏȗ~W^ *ުWS*mTPYW-]5.6<gnRnT׌,%ṁ=UgدϹqC/ =Ϝ"qR/}avKu\@r7W/+>yϓPWEh}8Ff{l܅ġWϺؓg}l2j1]'Q.\ޞҪ (Mzrc b0[I流4MS)OdP wxǁsc>kb/P?qDHRϥ> ͍w8f KOz;m{|59r06̋M"f=ȓ)CP-qM>L5q ޡ\{@;>Џ.GO)q WUƲWS^< ;cO Hq<oO]|B7ILXxzI_F\~Ndf gЭAQzz[o2nIguy@bo_y_GQ/s1CDyd^R# ?RK y?_?]ZWPWMuhưm]&9]%ˮ)əH6cTAs.7kuѪ%8ygٗ𝎎:Psxۖ+Ɩ&)Ǎ٩?\u^s7wTL)6`7I{^5x₰^07mJw3XuҳbYOE W^c Cu `uE 5)zJ0'/5GFlQqfL MN$+1f{[C{|>[z?ETS|uQd쒋%ƒ¦́bbc\Cx˴*m aЎud! SOWkFOX9Ym_^[vݼjGTuOf]Kq'Q;3PNa'Q n%2mtMGzG5y{c&5:']ߒtAxm Ѡ7W{g' G_^=BksЉ9^5ԬHvqD$=3}r)ÜBâXiNsls%FϪA [ ~!os_]9 p\Apo8pZ*5_dbY^|>.xq]?{?=Qz_פy'sRi4kIݰj9yxr|mZۿ$OoHdRsF^29Kb=qHD>:ek\B ?ͩ ْ \i$u| =r-MxÕSO9QٗC:*%PYC:-KSp X>9أiςz[\E3ۊ8UŹ󲯊!+{{D.R=^qKB 4UyGUJQ}NE ڥ:UkP:|Eu>mI={[f8GV e{6~a]lQ+6d%6$7lN$YDqOLe,Qg*yb Y rI?AnY3O%Er9rLWiS^`_DHH4" 1Q2Sc>࿈><#~={o3"4\uGfVΡ: W-\3k oScuZ3:*vDZ\J'  0GOO}30GnQmᇇ|q5ktӻ ߆@OXC3% CL @"}1J44! <5,J(J6 (KW^|R#:NpqU P.=w3|Q&)y&x@0XSp֩h׎!6.("HA b FVdɵ0zuWS,%%&7=5Cj;9bY/lܕ R\2{Uk6唽uj0xrɄ܀#Dy"&?1Ovq~Z-˟kuzK$=E;)3i9Bb$f>Y;>{ K뻯K}J5XL<9Cwl ͞GGȉ$f#VDHsO>CK+Nіf1Wtd ^Z8 -wA9BSp_:Hcȍq/l>|o)<^uVy,wO#}!E $N87J”]G<Ž^ÑZ\1ׄLՖ7!ve0Uz-nh݁xw(Y0D@R5G{ߢhE|*)A )Lxr6VrER E3Jk@%8rP%"/q*"}E $zsɒי1kԺNQ\K%mfwv Et;!d6*$Z;pcMS8){ovw/u;WhDQjNA_%V &Ų!QN<ۘ i\+ r&rh`V\6)a2YVVioB84tLs gq{ҢM`efvobV/򡔾SIFYC:l\Iw᭩_fER8 1ù͙kS(mZZx,+UOCH)\bnɘ㽾F鈜^FWeʳX*P-uH.t*USHH("jL;h't7UKßrz#; Sݞ(%2ٶ $DD N!mRW͉Pjp2 ߻V#NXH+j)f<쏳"EjnASv,ސl"،~eCo%K,e:XdZdN-rZXw2ǹcG1fјj"D, ]kC6\9o*\x*sô#^CrȞaj Ѹu 3 1: 8jKj!%ţp˩e4pc+ʤ ?GE`&tEπ͸}#.$;NdCi'cX*lxZE2 U-xN^Q{x̚il%W;{g6b.dq8RTNӝR$NPX Wݏ@ʣDiD&8wcQreӻX++'Ǖ, e)O#X{|X+`2k 'iq ,gS*y0OWםR"x NbXddrjEQ)Dg)}&)=_.jz kDHBH d0X2kb%Z"x% z,Dti'`B:J&2JK:3C6_ƪUAJi0 ;G--g8ITBYasڊl6)[+1eRXRax染 $#(8STiq E2Z[({gIF=zG+i^yЉKXN8Y^N`Q֛J^]ʫ^]4*j 5`.N6bSXVj1 ~T'xFրC 38z6"e JXj:#_TŠG y4@hG6 RLD!"X,"v_yG?8W̨˨ˬLKBb*S[QFQIz]Fm)2+r+rrPKԱ+7?g5@R PEARCE.TN1]| |ݝMl$*(Y!Z*UI !3!@"AIP[ik%j[Q$G%c' k'ls gv7;{=g_:ΌbGllۯ?xȱ'&˦XCٷYkKjZap? a?lԡg QpbpaaёQaOa{҆a\ w<Ɲ C΋l …;lW}k ,[c0L?{~&fwL:ҫ-ė\hd9ɗ8w@?:^c;`SmapS_GErdJql7k3Y/Dd03Ȗ?:0{ti]܏e4Ӽ.nKDm>ȩiq0ǒH8;qa {ۉ>72.·Y.Nwj"$wa9Xs`Cαtq΢ Vũ."ʼ~[>2cuw;ȝр"ó`~XIgࢠ}0:zpT 4q\GGQ{q!-zlr?ah>6PB v@F)&t;0@D'ؚpd:r\;ɖɞ9yX"39Djg,`(Ǚ)0:`~LLS1;#v/Kq*U%kpN~2`ɖ[pNaxPmH=ޜr`=Qd8gspNZa(ZHLNu$2ёixhe]gQEm1,GNp[}CT&N}fi`(%}rw '@5awTC|GLƑ,d"=pQzmq1Oao%chPgݻJ勝5thќvdtaμv:r4N8 'qw} 8fAZ3;cxzo=SH=T8Q\2~uGm:Ay?Kֺ[{gߖϹo'-s)>F _/]]KW[s!+~mʁuw-l5F @ :(D>W5]-˜ʤnlc;q{lBC~BM;{ ^ u#ѳCHb;!7U״3H!=27[qnsĢ-f~_8OՃ}a?Ul\;˽9+3sQ+|bȡt>eV:qm2)+EړC+ؿM;Unh:ZWeN;U2x{K8w/z/}o|y9_jܕqb~`~ M|L!X(a⑦Xm%Wh vԂ.@L͗99{YxK&__L˘LJ1p$fQ__On"u=pWzcZRڮ +RVd F [: %?yO*ZZh y(O μ(pU/m,6:qb\E2AO_.gN/#xC-r=Xg}i,WGw9VNZ}rw.7( 6{߾?O\ߜz}1i#k3QdS~:o #RY?}WUi1OZ<9X`uW>q4=k{tκY~x$gO7~zӆ_#զ5܄^ʆm-jޤEޯ=T$hQ)uײ@4] yi9znFlJya_wr D~<Vz J\v 5롮M1/0hy(Fp1\x 7 WyǯbQr7 /7s(V,xrANXwuyڍj该q2ڗ8x0o=Êvu.3qq{? #]w}֛G>|S4w Hoc6 n) 0_ Ls+vXY/-.c _-LVz<˹]D\CG^ƂrRI($Y:_$qӏ?H}t#~ɚ`l/*5͛u\Q~T[]u>? Gȶ/RISSĞA9:XCB`_"[$߹<\K!b `w;]oƿ+[;R@?Wu:`<}m~/r}O骿ay7=[Z矸Ԝ}]F݉y\Yxvw` |G"[6RӭA9> q7>/6[a&K< pu^Xe[x{ﷶQFR 9L=әL2 I;~~lq@d0dC2JE+?o\?M_t6Vݢ,R VS'X;|\]?tU}KhvykFƥ˺㟜*Sp)[`j/~aAO[^x&)}u'!tiN᭘[Ç\yc̬ÒWODE^xNBpOF4x1%Ŷi#3_y'$IHv/R[:' 4b%*V]/GrB[6e~gǧ̌vߚgW^q=ܮy%ϹgL݇2[onFێ_vfXMoe AO[7\,s鞟v™mcJ&;)Z~ !ڎ޲~ɿ=+D9⋢}n`b6i_iO/q)GXgx:a)A̭z_9us2\"dDŽ1^/Rdb$r/aп}~n|D9o]O/>p}k9붒wNUxgfc'*>x~M`?s?H݁zqݓ'7_,Z](0gG3%jAL`92{޹xM!},T^xW{N;,Q|_/nׅ*fL\UFU'$}#WPZl QR}iA됇S01 ~f,*9"dk?|KIZDis\C*O]R[ʋ5(C QOy ?kſt#sg_$*( y_^jcx&곓Z?p^*NdL/<60iXdΖ 9ySȖ3 _j wV;,ws`?s/,x5rNX~([잠 kY0յ}61׷^sI=,"1%Y):5Y{nx{>O{WfM{;uOa}?Y_;e>m,]֜W^vɖ7nyhtrT;7kʂnwNF0\뭺ElXAVџ>8s>N9c*XY bz|뻭5늬+X3Aˍq /gmPg4d,M=^;#Ct||bɘmo1kz_xE𿣂bX;eIۯ|Dx p(eaIsNL Q֡V(>1ILQ EԮ 26Uw9B̂2\XQob>|Sm)Iwܕmc4S?xb蜜yn2 9]FC)?}u?r/7OэG= eM'k$ B^M^rHPRihu"%U$)0{,ZN̘f NIn料_ty+#͗%ޞ@@L3Vf8JZɭkeMt`zԌS aͦL/^m{Z(PyτVvNXҕ*5ˬKs]e$TrnLʺYJَx~+aqe2+͔=ty&*&,ʣe9N.◇9JM߮Wc2*}ìƻ3̰8 葴5`]:u#Vj/`Q@q#T2ćkw x|HK߸~ig2_L6 Wgam)P|Mtw嚦k&8תk2o[!9u)w]~{e{{KT5}=1Wsj͇b=Mbݲ=c p_n7Nt8Y8hkC6L2N 6AfȇE'r1`FЦ~i-b~j ck,WDJGhRG-xώ&i/}%d4G &`X)2'y/ũ8yߣsQ :4'GSRZkUothM)$-̺CxYd/N\/?^(~5'Xg:`olۍRn)nJ5h$TF2 „^qٔ8OO^Qi6~Tn?k4 8yⷕfq_1R_$,) ONw߼V~s VFӜ)r%n0sX4-}Ǭ2S7_67߶ެLy*ܢx-̊j {Sn{31ϐ K6c ¿cAeއaZcE"|*-J/,~t.@f`Gђ%B hXiVs 'nPcBfXfAv]C!ʆGܸgwM?ug޹*?ٛ$uHz+ҟN|7Vn`4Pr6`] |Bt /[>5<% q gR9K߀MhpN{p`v2W07Q',=v .$հJ)' Iۋ6Te咬a̒SZ.$׊ڝXpWdݦ;oBEA %KiRF?X#P5(:߀Y!e!*Wef UiT2/M_ B|vnAx~n1ƂQ¢3qMh0x5-Kԡ[@6NP%8u刄-.ĤOZP*̀5-`"!îΖ`EXFLLiYM3쎯tp*袲 z)7'e1煛S>Ɋ{sx(Fߥ~l?D;v IWoih|^y}pwZ sh9$Aajc9тOG[oN^i-VAD2+q*HiȮ0*K+1gpHA,wHمnnJ o&| b@o+1U<4Tg1vu@!p8dz!>{w|keN߮?jΰ2SfF[G1 .PP%CekЌ)'^Q˟xпRlfʔAk6ſ`Y2(AU5}!Ƀ >()DsqOtT0>+qZNUp:@Qt(.90^K(ei\lf3KxꉂG4AKx4}lrU@9*XNUG"U˴N>[h4#u$'kMݩFX$Iok xb e@?Z@ mY:`ZD-FId֑[6`&ϺQQW8Ha$2SM B!̏D`wШ9WniA~Cch-_B,nL`ӈbHXg"'l||o.Xc,>E5㪾xr2xRAls+^D^<;nUT#F].<:gLZ?DFa"X7vRxC>/X]/?&++>ADxf`\Lm,H0@RuWY~]aGf^`w: @V2U)DV]H7r^(E׭ʃH܉" Z&cx=/|~rտإO|Ⱦ?; 7{ؙ8s0@(|T-?,0'?x#C@7q } < % |u4'*Exѫ,ZQ:XopR(*|r;dGI Wgc|zUW|E; >N#,W&|߉k.oET|DߎW1VlI3Wkaԁ{?i8t[[BzK 0<ĺ~euMIHJ sfL2G^Oq?TL bAրV}Jһ_ziM5ulF~ާ#v|+wӶ^|V~GR@py4_olr"4>@o̭)++b`;ׁZ}})5>t-a(^@$D_S7j r#=.o;0#'1FL8Ճ΃1ہK3~/Wli{JQP h9fP|qV-RS?,Z򳟉Y6L{cO"dy2K4ּ5 :jȕ?[5duzɧXVrI7ԗo݁OT/Dˆi];DVSa$؏׶0Û)$!8T!$ʰF4P].j!td)[(*Ob䷸&̢:[!M1TÌXz oS¿'KYǮQ>|_d&؄zWJQc,^DBOo1cx̟6ݞ$rJ6:zd)r5S:f? 5OoK0>m!$B,Sc})ޓv+Ĝ=#ݿІ>`7&mRz\gvsg٨WɐKp=t EPLvW#|>B[ǜۑWk^_Yw¨~)Ʊcwc]YZ~7kG= *W\Msg=]-Kt!Ab2饜n^BiDmCC r~ 1(Dμ2e 10*WIN[)CVel+lLـzzB3/ Ur-\E6%_jtb%M /X{ =$״ PWBm] )IBvhMeU:!ߛ%*IHVʐZT:wk`(Q8,I5J4UXܻ:#+ ïߣWxm)13+};"iJy{`^ʲAjgldV=@biүU?TT3'WJ} K2.0cWm*Yȗ+mˌf>ڱKԦ*+ Bzh18*OcPl̛sZXrƧLok>gFu :L {D7Yq+"Yx50V\ ҏw 39GB;! 'x>$,B`-A)z騨6cwgQρ XrAk乴ktҡQ,K}ZW[HUb+αVgqJ,%u 6Bw5b#z`ZMVDah2 ;3ZKz\:5\4EYJ81Eg]R6kɽ7ʓSt"e#: Qif{ QCTO<4n="u1HQYA󋍸{Bҧ~Tq-'JpVЏ)):|r^9yCE%C"2~ĥJ.SeZHnX*i1ĉ(Y%@ک1-Nխʠw@< SuD~ʆu-t r'CE6@e  c±^A UOA%![ &C PSJeĄ/W9˜YUG. B$"g FKLW-Ĵr<؇m6&tEYY[dMާ3QH2ȫ7 gǤ|UuԬgkL|V `3[av.[uԃă4*%*/Q `plʑ&nʔ A.اu @`)aF낑d@[ד=pJ%DQ:^wVCK0%:;GET`oς MirAi=d$Ո f+赀IV#R;-)@6\>fJ[)Yu3=՜::~#tE ?q&jxQkpݚQb@`W8E ӽvCX4)D?HnH,#+g)^%{YdНd]pTNk$'}uxX&`=} WsP2=Ht QkMy_]GU^n:4uhķ N,؅fM%') r'UW,9 b KZ[a1.m^1wPӥkq0cuk{m鴀z<ͬǜj'y>P!bQbW;Ӻ#XV7q?ֈPqXKCmQŰ%4*D/P3}b&**wE>7y[RBBY+0Mrj< D]qaJ#l'Vb w"'I\%hBN0d|A {y `D_8gc`Uenxͭ˜O+'kVZ" eNQTA,YXq#e`H'}Es(FI| 5){ >n`%2B`o2%B.7-.nYCFpjٔl峖"CP+!D+ǔ] !Mo&VqCյvGG'8Jq9UY:d4 TյXyp8 P |% f<] q"C.rP' ‚VW @/hf='1VsE$4]K<#']^ ,86:qJz .,"i|#4FC `: 8aƨw7_UD6Fi (kp2i{Jf/!?#oa2m2K_bi=amvY0f3G8P^2dg(KllTKd<%,3N LzF!ub YZʐNsneRpd7FFBzMTD!QRL]]P;uEӮ (5tjDEړc#^s(c!,%5Q/tSߢS//`_A֫fl e evD-!9v[H&aa-Fr0x\Gn2?"F5|Sĉnlkxi繂DKْy3$>" WjY %P+/mT*Nφn|-YIS/,E&ߩjDlYP>O%䍛xrtWqsc.&%)whvqfF#7Z \l,4k>KOzd &\ѫR%,4MI5sd=ˉoWe(y;_*y6+-)ըPxn4|\ 2Mh˕q^)AJx6XuzBV@Z ox8lzkR cYK7q_w# 3s{l FX Pm@}vŦ1@ <M ҫiZ4ʢqOb47\\$4E#\9,/9 ĸ!Wɍyv/&z hrs l8lXqv"4]*+3}I*ux0Bp%ƴ!+7F*%>.I/I*}n넿{4x!{7hIe ОKR='daM<?<::q!T]'.AC!L^z|BH#l(FOrLC螦[?K$t4MՃ aj48WFr$xz 0hAubhA M- d>OXz%2n<8Ld=6iVWUAxӤ@a8[Ud6D{`<>yè&k lR2Hўt BkY|P[8!I$X-T uI kP&I.%")3DpL%yFb&I?n&*ʹ=u:BVV9Z+ljG5#{`ˆ ]`\ϐ*E?{R@CK.J҄ȯLUpJ"2 E]ӈ]Frw+$D&w& XvAtdl(xh 4Q:% R+C?Y.P+d#PC0E4dt20@ڙND Q ]r)>WA.T%z-*fԬ\C`1=+ Sb rq1)oD"얬HB ASESmyS.'B1Hځ7&'8% RH%x E>%_kM/W2'q v2"8X* *_pU$` ds@D~8;dwT<$ń!C"álX%ac33[(Sv#f=;ur!J`Aj "1?kD@gV<oo<:+pSEl/FI!p<=LA4 YʠKA׺ 1 &^y2WHgGSUA7w.F܄MLUTF &A DAKX2;֎;UJSdt2n!gj!ED~`@yfn*"1F/k߸'EWT>(S=WH.DP"NW */$fE<$.isGo<'\5q< +Y̕ "?O<${u0MM6:/S~Ai%~(߈ybH`vDAQ\QpV?&Ѕ' ϛ :2w/33 vzotrQ.bCr[W Kkp{=ޝ.:i/v9Us݉;i7^XXz^7a0 p,4&wBk?&WgLs_$бS N"ȬF`EacZ6w S%~wgusoG"tw괷xXX%+55-NJ ];t`;I3̙_u^Om  W`=28+99kwOpF#+rqv1$X ?u dy;E2ujqQ(#Z~ӛ99΍ۖXNc[G߳jVg=n.'G_,LJ4|]I{zI8k_E3s1:\L%O=$mfp] >^ ypk=z= 91h؎uq,` 7Iqsgڸx11 ۵@47i }gfAڶRںz}ݤ:AH"dhf2 /cZs\Fp&0?ZAcye ].{Ly_{w u9_al1@<]|ikZ,X܅ /o,SgD-[$M y\L6yȪG!- *>pG#rB([K7i^oRP!y̶QlFy_ps8ؙ/k-gG3:(">{9R4/ ='aP$cM'ա4xˬcc_Ȕ 't:|IHS46YkWo/sJ c1|GWCDI; ]gUYwTX׾SkQdE&EͶ;֥5 (Xtd-k[.cg4ޜzOP4 뙿gF#WD$u۽=Q9z<${5f3ƒEv`OB- 2)_P3 RSaHp,lo:X3nۻ?ʚxܡ`ؖ6coLvԾo~.|¾#@QԺYw&K"`Y$S7 B-%F4FKT:E`TOOeE Q dYF8 رf!:ߪ/g{O}̈́z,dYW+4,0'v)=XdV0E6qZ* ljGZĺ@h`%ԫTn`[;{ /!?] ݐЉI#T@buPZq^x֋SZ'' ,X">1|Gu&Z|E4H#ވ"K#8M^S0X-2b -旈sn`I!|Yp!ұ4 EuHqcN>nc\]<- q0wX{бX_^+Wm] EzyXc8a)IӞjKX<t`yָmNStFw5 ` g,P Ւ PõHu3 ׯLv ߡvF)NR0׏QdA}%6hH1d a~Yy c/dְ.RG`VY!V22ec2;:1:نb51G/p)q6UF6^A ̲ti#ae3Lgi|h46#;iς`> kyq!_i:/wL%F&]d{L4s#ھ6Ԁ6MJ4:P]v@Ev?$WNC/Y3[ө电5!hO6%Wړ"[)rnx xEi G,&GL|bŤ0k f;ђ3bf]lXOlz5Y-A1d@jatJclB ŪyHǘu^UlĊ;DLJ^mXl!*+ot$kb~+?5%^H.Sq^elV^ :)9jEqg@`IJʀ- (%0_BUjYH:lOs|$jIkDGÌ: X|&n`UM'։Er|8$ipc;[ °z'&J}o|$ ZK(Oc,<( ?.v}ʆ~Cfw (udւ1ۤo<)啕,RC=lON"ѱ B4Ev׼(eסaIUSLdhڜL*lD"L0fDtyA4pЙZFDor=dsљ8~"=Er$D3 TW"C8cffesp/(4i4ݻC P嘀iNn2'xԸȸ(#BzM`VY 3(H{YitgnamkU l''C<ZW$vSE&saL R916y8(͌5Ypg™[ԈU( Wh搒@d1kŽE=\JM|PuP8I熠Rq%>|Lf3)dY'-n F9h!j2^<;U<|QUȌظ9J [E&a^676jlRx^<gLD7u|ts(veNO;?&$,AsL+pH<$^ sHCcO/wOO!u^W}"KTT "2I>ɣ0triKW/2vr"7M`?7L!G21u*4Pu̲6)t@i2Ge5ȮHWq#KŨ@aYvck`'A:Ă$8W6Œӑٍê2 & KNiQ l6Pvj d۽.5Ms;)KqւVҰ-z{'V<0wS;,MY|u=7߭M!J}AɗbsO1׿ԯQ-cqXp7̑s2c tItN2* Qжk &2]ŰU :Yӥ 5ly*A F tJ 6a$qVHV-N.FL}FkPY4""Ҥ41# iӍu|cwp{bW:q=T#\v2qN$%HE43m0#MDY(Y$xIqQȜ2}~c3wb,wL! qZ$٬)Ȧh o$;9 1OAMGS@& '-4Iݺ\v@P>rIUZa–c$JOT]^tOoJLkxJpTo?;? 'E'9j\F mF3< 8Nk&΂>wAԂ :nI">C0 F=4:(U)frێ$3jQ 6pUU%Ҭme[YS!^`J KzY AdJS`Sp\0b2n>Aхk Ͷʉ"{1SUD} 3Gli6MA5Sڒ'dL?yVp|s-nGB<*ɜJ4qIıE˜ 0!skN;O'yC?ۉED% i0 q*Jư99.%)/lTGKl9>qE ǘrÔYuxܹ3r6ݫ+0.!"am}fK;5 D$O3aUuJ^2|KhuME!d9U%Gg\ ‘$WRx w㞲#Ơ`ce& s561(ѮJ'1k*CF7'WLBwڃ6N)rޢZVv/ "I ߻ I=. jM&ngE]-[^$3\43 bLWRxq@ nϧH &.X~dcs0IJ v_0N%DKQE%{$H΍xĹuuDA_zoN(P0wujK7KI s G^j3N1 ޳$iP"DN?TTyJBoQ6I/y}N cȸS?1 Nt"S@W7yLVf\٦;MGC@F=GrI0͍ȟY S\Nڄ&=sx[۪#yXl]󪒹p;* ^}B q6$"bkUf+y,U$fަOHsg>v(kU@OP'"rB rpQׯ2M^P{=J2b-rҠXЪ[ce*g=@|>=gV|~1_ŹMAb< qWwkˌM} OF= R1?>3;g)P+2P,BxmSetZ12X BbHRliCP\Ě85],qBgb42p{uYlI2ZdVQOZ2ݮ+X$G~ v`D> 5բWFi=/HREWU854MbBok0oNjU*֕&"7~&I:wPL]GFW밍` Җ,uFD},)5o|OΪT'sJMOUN5,}Bs[H\9,;Fw7{)ɞV^1c[sfUAMi> _Q^2N?J@gϊ0H$瑀}P0'X+ѐ夋FvM.-tUc}I!dVH' *Q5*Ztíg)OT#>#>)rzO9\3o2IEQ0*i䘵ädm&J)Ǜre5nȡtۛϊ\A.*.x\vc@y >RXH>PC(BtQp}`QO^oiUrĽ3NS=w~|I ^{"cԚK+Z-xHk@ԪNhYU,&cHBcm0/{6]+El>0/*TdL}Cɨ 9Ow*YhWv?D ' ~C~MV*鹟o5?= [Jc<<[ը,^٥O9mXqwK4]j^u_9mĨGw߷*R6 oEr?JV2ElF~Ä9U]25s\Nћ{>B<ׅ,r!`i5l* bznxcGZ<@h";HHY|cTjjH%T{eF| ~hKPʒmpI&ȭ*&7pÁu)%24{C{8?}-{%Mc*up7'?gNlZǹ{ZKg1s՗8GUW8#r!bZ_zV'x,#J$Dqā.e=@r1 LR*[5hu@vjԖ6FfzjnOKk6E HU\ V9js n[~[9Q4oSV]f4R㷍݊+< EOodd{:t6*F:[4'`mFtѦl fyf?rnʩ!!tKp1̘ZWABԼ[RDuuAdt!йA *}twxtV߽;c I<%W] C)DC٪:KwTӳ1Rc]``+.S |EG'6D:ˀ HqDP Za۳&.D;qc n_LtZ]~2ڈ%J r5~4X~tvKswz,+ǩ6܆;5Ǐz47{E?@xH|{㑑id W!yHrʉhmωr&ʅgC9qjbofaLʡNTrNY"=ޓdj)jq уªFhW"M.6=w_MFJ| NDՒزyc7+X!p\fuOdFͬuܞ٢P%qѽP<+ËݚGu>3S(vu秽al,%V @"DNd'S7okfRuM-`utq!#VrvKÆId,]$n=2)s+@ͩS+x˹o${&mwj*@@c$89NP5hՈȶt(s'҇ ]b&\gfyt&$iRd3WiG[eė>ٴաt+fnʄԸV,}ouD`=Q5=_zvX,[TR%/ ?]^*s.#f`@oeқ99#B@  ?kU|%r.Pȥwd,%PN |P©/Bo"B`gKE'݉@o9EwBEI3`av\ΘC&&Tb2_*e7ΜSaps&㬍iB}῀p#y|iH\l~H\ĤpbU/W=L6-Ze6I.ЮwVrFM"=@YM[Al@r364MaK@봔:YBPOAUMq% u *&_ȋPj բJd90eAPJGE|]zMœB71LJ$c(+c*#N+\ K֜Y|E# BZ@٥8KԩmH^M^*D|Zʲ`ꛢf9٭j&0\MivEa`9SOYTLK(e!O#u(KUb6VkBˢh:: weQș:\UB+3ksۍV㕑sjSv|L]]~*S򊮈2?; 0v" 5,O-0ībM4J>/#"oP'Kпiۇ)_U (r7 _R%85HeIɚHe⧘V'0 8:jX(Ql8\uL.59dHN#):# 4ƆX4kEb.2Z B}y)ϐM Ո#g;.u; E!X9?"+~}n0>M to~5.Qĩ#ҔR4e)MY!zb5PE6ЩW%Ε.R:8%~it»7'z;f5mHŒ z$MnIt 8Suzʧ:o=dЩWaX"R4kOGÛ-O~ZBo*f 09W/!e]?ԹUl n?+\wKCA'5xW Q\cYx{>jZk&wMbOQD)SJ#;@-D(L)l7[-qr҆8Ǎ:ǬU#-3k=j쮊g4w@n"en^ _&v35NJ۾~<>!g,&XFJ±`1FgnaDztR]uEzD\ 'R{[a./}ᗪNL1i$ImF( 渤d`|,ŔYNV|A#<.^ЪG6%Іr癈U vb#U@$b$(Uh<Ͻ*ϟz}TG9Nġ=JEUJ]d`b?|x"z-Mm9xzuQ\Sh),o8unQJ~NJKԯC;ʵ42]C|Em~rtZR2g4](lu)wĕp,Q͈B'W]o_1{&\{aUu~pi^5P9 [laymAU$YU~縚@d$p$/8 ]//CT5ʤuprP6&WSh5pQ UQcqe"#v]ii/D<|[E#ܹ# ֶk><]kSL*K"0V˭bcV_鞙vHa'˭ԕyt>rB<\DGE8K y1FbU[QW~!GxGZE@<ѫ^r֧M/Nb\`۰_aQ*6YCJvVC g:6?ȷq18jm 珅G Ei<{ ^ZZYy#MR 5?'3%J2P]7xVwc{=Iڄ"FxSVtd:d"U@G2~G8T& 95Pэtcdjk*F\5ֶ3"j<HsnGЮdD`v_cEubƪl UmI$ pTgu;Ha6\Q+h'L8c;/ǽji7<4k\F Z@jVl~j4dG~cQD9Wfx:.ʮ(xq~qhil0hyMmuo:Qg7_>>I|)n89[rZv'F5gLL3Zvx|0`cC^qC<~ !5 r04F%o07@2?/='NC 'b#73csE*)eTum([@ '1`()4DSxԛ3 !9&b~ȻcYfGM )Ў`FʞQx9 @ΔEC5͑Xnb&5^QV+| vq>V,sY/!%^𚌶H12'ռ(=Dvf?|aVLDsHR-_@n]W; _W wKj<"=I~a } ?u*͡]ga㾲4j˾ n̽YRG!h!bAf*d,Cىg/i_Mg5gR|,h33xs*kfk$WK(_} Qw+0[^%W`IUUSK|A)GL,sx9BM(Nd62K[Kӫ'c"@TypKHLֶ-v9İU$O=z%#9bE'sNқ*.dl(TLҔ}.$Zn0:'k^&W\C$E^>K)a5 |E{z-ԦEUMž|v7)gd/z[|΍\_ @%m*k/jgfPd3 mg8EYMg24!ΊaB^YƤe= v2 lvfU2P Y_B0U0ud16@tӓ˅C$ xn-wv3T!,EdLJ`ǽ3l̛jr^t`аWYx|lY]CkHL;]Vnyja*tdSK2\ zCNԃ3a1 ["PaHpjk#o  PgaIk×r`8}6l`GŮ3wda6e_aU s9R̘fO*'st|Zk+[W쨨:\ʫ$W;r7'OkA~82B3Zo_Fq:,o(T6DŽtdb S|Du7p; D.䷱8XϞ?^QѾS_J~X/fg[A3yWɄf!zems-JUs5V(7S~l'lgϗ{AdAyТ)? sKXe*5 zm3*` Wm;<*Z{ZTn~G8eNh e{;Knn-ۂˉ&`$vlv{*uQNXH0@}>}Xx0;^ +pZ;>/. 2ӷ˂,+BWHmiWgg8Vvz׉yX46WqcW讀4"}ߨgY8"r~૕Rʊ24+sDߐ8M˜ !%q^g9Bl U@tDNfH<8[jh}h57$=ZV 5t؎Y[g5Ljuaz^PvUZIZ[xհ„uiw8|sq~vVaA1̕PN_4dJ %tK85l8\ SZChPؘ6P""(w򐏇tD%,d/ƴԷtdDƩ*(~QR6+RH oy]]J'HBGxA]\f5$Ph`Ouʄ ,(\Rp/ޒNE,#)#>K0H$utnZB֧VT($nkQZƲH{+mhC47'~w|A|DN*Tq?I;6cuј [&Q.g8 hAt7;c!=h>Y-zq%ɀ/:B^/|a%/>W*>`ކw8|y7!%A*Tq{}~#҈P36+$)4;EL?y%@'k̯a y .|j>=P:sZ p4 Ny+߬k3:)fId4)Z.͆)( ?t+Rt**m^WzcNKN PG{`C't(* ,vl8|=Z*oم".:g7̲ݖACL@xH 1:mq[?*{/^+HPO_lB", G)4`2;Y=%7Qu1iU/d_x  5^3\Lg5^0"51aF]b 5{B?~>[52k5q`$0b0k8k2jIaS0)h__] ܟꊤ Jp)!Z{-2ף,0捆X-R;v0cIF}K.)ԀDwZ11p1 :('Pj{MM|->qϧQ\=] ֭@Șǖ3UL5bTT&6K!M@wo Û*n*EnAXz܎0^X} jƷ^K9@Z |Ch/^gc\emʷC8p-Z")9ZX4`Zy޼n/_irb#Vb#w?K H(?FMIk<0}|" 'Nk@gYѾ@qjvӨAUa\X}jq>} ۭ>S *ppwl7f }Zi7E9Q\T;qQ!!.PYcUl8>,dm djǐn7sGG?6b?٭Ŵ%w=(JbbsiVO]:ѿ_)(DJ䳚5`ڌS2 7p~yw8qtqŎQ5X-O>yBVn*?eZ Fa7疨#/xK"Īdճ_bxEaK9|Da)|i6\?}ַ>2JP]f1C4:*/F2^F6oyQ&Uۭtv|O|f`:.`H6i7|{]vo잎rEԽ![qj>r, QG=f p2M̏y\"_QtqE.7߷7ˢ۾]UG9r93lȃkعAxiKAS6ŔF|}AsPUytt"8kmP)EԸa{Y~nkfڮN怽.$NOQ{ݖYO1{v97֘"('6RZ=9LoǷpDZE?6+  q+RI-JQ菾q񿕄'dc KJtV[LG_9{ݫƧePB*P hCXB?p@)BʼnjŠx5bn$~<|ψ2KQ,{Fwu6v\RY撛Y%%Cٯ.ƙ5fڴJ[~hgx0С+0@g ^iiٞ%|Ziɧ%|Ziɧ%|Ziɧ%|Ziɧ%|ZIo  ɨzJ]],7 :JYax|](fX) 1tFQjF0Om@V/"$d~"&cQ=NqJA'uzd!,~e'1V{X(/PK N EXTRA.EXZzmtTU[MQ1b<eM[ !L$LBRJׅHi}Y!BL;20c3e; C#C3!46Cj?rhd[_Jq5?rg}>Ϲk%dPqEBH0䏄0!ܚq6<' geN#&P N?qD}p?}6ǽNWBW#}t3uQk(R"Ӣ3Zb~X=AEƫPrc@F=عc}4v|Ҥzwk ڭbQP;=J%;*lmC9zSm#G .2dդNMeM_~vyB#D} e}EϧZRM.TK93]?VQ Z*wk}@BZRk}HOWa6A} T\u瑾Oƾ-D*yHtPk4l^]rZ_yHJ؇` Z$BYm BGԲq|ڈk` Vcd%rd)0t}bA9!mɅ]R};8HX|BBZXYn+&[eЕ'[}o^+=/'"z2[SJX})HH#Twf1v{kws[7ޞT Clb΂NWCb a*,觷M7\f޹:[e-=C`RP1Q_:}A73zhG}~J)gc(T):i`-{M%*M(Iu@,9%[U.Ai*C!\y9k}~ɣ\XxAe~MM"7duے.˨:YTNj-8Zse]SY훴M(zQRȳfo4-} ]W.\p7Tz״MPpդ22}TMmB*6DMQHpaWт=5GFqEuʾs"$F): {.>od+9έ@U}R572)/HQg9cnZ_A)BGp KrJIό%i#nMEժC 2nf`3_WYE)/Shg9WXN\dL7yc 3XN%S}ȁV\-S^eZ!wV@<u%%8)[z ™m0h0Fd~u{-B~_fSvxƐ_]))6ה2e##xdx]m#K~Fد^BwRbT%Ke#쉣O27J)r%&3j% Z1L?dUtJ`,2ar<ǒ4j$}bY%GX[1;KHD֦ cf CᯔQRz/s-Fʜ)j'Hvj=yZ'[NqP"NJ2wQ0Jz80j+MrN)Ӱ<.}.J)uy'aYe>*3wCg2#W[ѥКx\:M^#k ֆ86" 80G߶ 3 \WPN,8j3_lW>=Ƴn%Gφ' +w*|.…`GGRPET!;YNq& Crf4҆ d\x.̗M9o5b;LQ[ퟩibqru}QM tJJyDc:X-ˇ f&1k9a[_A\S 4iE@`A>an)usʖ5o.L9.BwxXl3L>ͻ巒VO fN U6V~TxJOY}ꇳ֙U dC+jRjeޓ )15tǔǹZ?ݕD X[8sFr23z/${e:XG^SmĨ{(Ϳ9\3 iP=н\amkPZi5oǮ:O~\#qW&ø61X`9:͸:U@UU{vtQѹowŇ{D}}]:Fe]^h}m;ЏVb ou_hdrv/1t0v+gSkQ)ExKɨ-Z1g#Ǯg>渹4UV+@(;JYxzH +ב~'um[@s_.^zcŮv|C.qvqKWz䷓[pŴLDWjIGƂ"5T +lRN[en2m}s>m]f-rѢۢ!G(3X0@4:[g`ߠ, ݖ~rGPtmr[\sQ(-(f0E#xdQO7 (i9(Q?\U(Q; i;z:t[G /:A.qS(t4VJ6P)pU7rAq+J{@(FmRZ ݫ/HeRbnd܄kșr̡~&nN(ZZts|EݦНmQT:YaS5VbICge삛_TJFo~ɁKs\7mte/ s 9eu]8ĥZJO{ߏ_ } N5l͂~2l=i[u6b""#p ڄEuu( bn7.idHQ\x]]A .DOa{ؤ7}Ԯ7k}(R [P(U9\/bͿP[!\&e@/~֞{iy;ߵ`UVqJ0D[.Ĩ^U|N!ng}{q[t3FA!ofލC]ߨiΥ_A/^0@OizArjj{nWڢCPR5UZ4e{[v7H,5:PQ_JMMǛKw,Q;pr pVIzXC0F8ra؎qK8A%C>smSKK|&)һTPT%wT%UpcqwS?U!wr9jԆM9M*IILn &/K5=?=8օ.mOrNeĨP\O>Aw~)qK8ϸ wxr'?[cmY_(su״2SAMf]ps!:kVi3J1gb&7)JL"VZHJ,E7=`}Ah8 eGjWPڶYvRJKzRH=xesH Qj)?rH=vzU"(R:T xʙ*bv4,w?Rx#uQH#5M<R'(uFU"N!Q}H̨SpXxQh)L0ynŮcoEK`4-HB_mF_(t1zHX:.YY0tP(c_(8-[Zd;LKl'5D:*sRgҖJӪٵt]OM vޭ:ZNz^w6iSαX(Nc TRgFH3:;FܘCQsQ"Ѡf:Džh~&@pL)4IVR2&?R<Ⱶ4&?~>4[.J[Ś<,5ɏKL"V N̟s4 Mɗ ~jd~AB'$;9<|7s2qwu[s(&5_ҕ"y/aKmԙyERy{LֱsffG>6R|Xphh(.GB0 䃅Dt8B2*wA'0i2ؽ~[/AêV2geOF\1㡏6A@\㥂iƹ Ɠ@#qz]NOLɧIb tz_s 6'̀3Ő/,ʣ.*N[֦{ȌZbnPi8H>EP.3߿̼|y0k doWLDf 3"L#͌N9s5'`e.[Dws]%Syȼ<2otÛ~38(;Y5R6dXjDxȽ4*9Z+-+]H|MN&.X31hňvKE/p -NUd`gOɩ^f* $3aDkTog)X/3P2^'g;jO1׉,oMI@~k eGtd1L<=g8yk_׼5yk_׼5yRПB^:wԼ/yuv+hد8ב |+KLx+]uegOW͛y])<$Qya25zV\萡UEZP[k eR_\kjZ"]<f (%|_ܥ.V?ciy ]ʧEBo5ju5VE! 弅y~KZ5c`pÊ%jqLJPK ,  PALETTES/BANDW.PALPK tmX" ~  PPALETTES/PAL1.PALPK tmR|\  PALETTES/PAL2.PALPK umѲ  PALETTES/PAL3.PALPK umP  =PALETTES/PAL4.PALPK um30j  PALETTES/PAL5.PALPK Hw  PALETTES/PAL6.PALPK um5+  *PALETTES/PAL7.PALPK umUV  yPALETTES/PAL8.PALPK umc  PALETTES/PAL9.PALPK*+ՌT BLUR.BASPK'<` CONIFFEG.BASPKd[  DEGBAS.BASPK4`O|  DEGBAS1.BASPKdjǾ  |DESHADE.BASPKUG8˗|f  cDSKST.BASPK hIqX7  DSKVERI.BASPK/!  fEXTRA.BASPK0P< )FF.BASPKP}} 1FF.PRGPKB3Hy> ǮHREV.BASPKl3r- ܱHREVOPAQ.BASPKLwɟ ƵNDRV.BASPK|  OPAQUE.BASPKLr ]POWER1.BASPK7 POWER2.BASPKzY. PPSCDEMO.BASPKEQ PRNTR.BASPKL3q KPWR.BASPKR,hS) SCREENHZ.BASPKc,C\,p HSETHZ.BASPK }? WSTOSPIC.BASPKChB STOSPIC.TXTPKG{ļL STRINGS.BASPK {i! VI.BASPK|$~/ VREV.BASPKTS: WPCHECK.BASPK:Ui vWPRO.BASPKΌnB} pCH4.PI1PKm?"} DIRECT_L.PI1PK4ߡch} ERACE.IFFPKZ)^C} BEER.NEOPK-d {u} CHURCH.NEOPKn(]} \bMARATH02.NEOPKnm^  INTEL.MBKPK=!'Ӟv\o BARRYMOR.TN1PKue`{V 4FRUITP.TN1PKԱ+7?g5@R OPEARCE.TN1PK!t+H21 EXTRA.DOCPKb!4  EXTRA.ECZPK N  EXTRA.EXZPK33\ <(Require blank disc to de-archive this! (~DT     ( & 4 $" .    :  "F ~  .R60 N2 $@8L  4 B( ?t+Rt**m^WzcNKN PG{`C't(* ,vl8|=Z*oم".:g7̲ݖACL@xH 1:mq[?*{/^+HPO_lB", G)4`2;Y=%7Qu1iU/d_x  5^3\Lg5^0"51aF]b 5{B?~>[52k5q`$0b0k8k2jIaS0)h__] ܟꊤ Jp)!Z{-2ף,0捆X-R;v0cIF}K.)ԀDwZ11p1 :('Pj{MM|->qϧQ\=] ֭@Șǖ3UL5bTT&6K!M@wo Û*n*EnAXz܎0^X} jƷ^K9@Z |Ch/^gc\emʷC8p-Z")9Z SELF-EXTRACTING FILES ===================== The TOS file/s in this folder are self-extracting files. First copy the file/s to a blank disk (or spare partition) and then run the program. If all files extract OK, delete the .TOS file.N:sۻ"%*bk ISKS~YB1#o]Du࣏wh/+{khP_W߰?7/V̦ O4Bﳐȿ^Vz0(J+[(?'ex.Y,ʪ٨qƁJ^bzoc%8h+Viӻ="]tHNU]3J]gv ]~k]ȏ<mVfh|y)a4y?3RPGxCj}הLnʍ3ƹ&( 4 Xnװ\sF#M)89G`82:QxT *$a._f7$(1!=Y-JFya|=jd<)s0yYs ]`8:ùŲ2l n +e}3w+m=̃R`4c;kyXQA %l-'ʂ~3 ~7:`΍OBgA@n<#V-ke-/4&vO 'Nk@gYѾ@qjvӨAUa\X}jq>} ۭ>S #a000000 #b000000 #c7770007000600070055200505552220770557075055507703111103 #d #E 18 12 #W 00 00 02 07 4B 10 08 A:\*.*@ #W 00 00 02 0B 4C 09 00 @ #W 00 00 0A 0F 34 09 00 @ #W 00 00 0E 01 34 09 00 @ #M 03 00 00 FF A ICTARI_MAG@ @ #M 00 01 00 FF B FLOPPY DISK@ @ #T 00 03 02 FF TRASH@ @ #F FF 04 @ *.*@ #D FF 01 @ *.*@ #G 03 FF *.APP@ @ #G 03 FF *.PRG@ @ #P 03 FF *.TTP@ @ #F 03 04 *.TOS@ @ >r, QG=f p2M̏y\"_QtqE.7߷7ˢ۾]UG9r93lȃkعAxiKAS6ŔF|}AsPUytt"8kmP)EԸa{Y~nkfڮN怽.$NOQ{ݖYO1{v97֘ Does anyone have any type of compression methods for picture or PRGs? I coded one about two years ago, but it took too long (about 15 mins for a 50K file !!!!) Also, anyone know how to load GIF, BMP and SPU/SPC ? Docs will do! To EVERYONE! From Diamond Software (again) We hope you like the source codes that we have given away (see next month). Later we'll give you a lot more source code and also some documentation to go with them. I have just been looking through old Ictari disks and I saw a notice asking for some more STOS, C & GFA source code. Well, we have been busy coding something in STOS for some time now and the project is nearly ready for release, so we'll send that in as well some other source code. We also have some full screen GFA overscan source that we can't get to work 'coz we only have the GFA 2 compiler and it needs compiling with GFA 3 Compiler. Does anyone want it though ???? As for C, well, we have only been coding in it for a few months and our programs are pretty crap compared to others. Maybe in a few months. Quick hi to the Professor for his great GFA sources !! Love to see some more... */ We second that last comment. ICTARI /* ---------------------------------------------------------------------- To ICTARI From Geoff Smith I am particularly interested in the forthcoming article about playing sound samples on non STEs, I need to be able to do this from within C and everything I have found about it so far is in assembler. */ We suspect that C would be too slow for the interrupt driven sample playing code and that you will have to link in a machine code routine to do this but if any C coders know different, please send us the information. ICTARI /* ---------------------------------------------------------------------- To *.* From John Hayward I need some information on rare Atari computers/consoles. So far I have got information and pictures on the following :- 8 bit machines. 400, 800, 600XL, 800XL, 1200XL, 65XE, 65XEM, 65XEGS, 130XE, 320XE and Portfolio. 16 bit machines. 520ST, 520STM, 520STF, 520STFM, 520STE, 1040STF, 1040STFM, 1040STE, 4160STE, MEGA ST, MEGA STE, STACK, ST BOOK, STYLUS, ST PAD, OPTOFILE CDAR 504 and 505. 32 bit machines. Falcon 0303, TT030 and Medusa. Consoles. Pony, 2600VCS Mark 1, Mark 2, 7800VCS, Lynx 1, Lynx 2 and Jaguar. The machines I still need information on are :- 1400XL, 1400XLD, 1450XL, 1450XLD, 1600XL, 130 & 260ST (128K & 256K versions), 65XEP, Laptop XE, 5200VCS and entire PC range. These are extremely rare or unreleased. The program I use is called Atari Museum and covers the machines listed. It shows when the machines came out, memory capacity, picture, etc. The program is only available on the ST at the moment with the XE version in October. What I would also like is someone with an 8 bit system and an ST who can exchange files between machines as I have three 720Kb disks full of Neochome files I want converted into GR7 or 8 pictures on the XE. My set up consists of a 1040STFM, SC1224 monitor, SF354 drive, IBM printer, 65XE, 1050 drive, 1020 plotter and XC12 tape deck. */ Since this is a bit specialised for ICTARI, if anyone can help John perhaps they would contact him direct at 42 Shelford Rd, Milton, Portsmouth, Hants, PO4 8NT. ICTARI /* ------------------------------ END OF FILE --------------------------- ions as well as good debugging facilities, trace mode, variable dump, memory dump, pointer tests, exception trapping and stack displays, etc which you do not get with Lattice C. There are also a large number of built in window commands which are much easier to use than the standard GEM window functions. The manual is also very useful with a C la ICTARI PROGRAMMERS USER GROUP ============================= METHODS OF PAYMENT We will be using two basic systems for exchanging disks. You can either send a disk to us each month together with the return postage or you can send money and we will provide a disk from that. If you send a disk please erase any old data on it so that we don't have to check through it again to see if there is anything new being returned. If possible some new material for the magazine would be very useful, even if it is just a letter about some aspect of programming, requests for help or comments about the group. With the disk please enclose two second class stamps (or the money equivalent) to pay for the return postage and packing. Don't forget to write your name and address on the disk or we may not know where to send it. Alternatively you can send 75p for each month that you wish to pay for in advance. Any cheques or postal orders should be made payable to :- Mr P D Hibbs. Of the two methods, we would prefer the first one because this means we don't have to keep buying dozens of disks each month and also it is more likely that members will put something on the disk for the magazine. The only slight drawback is that members have to remember to return the disk each month. We would suggest that you buy a book of stamps and a packet of envelopes in readiness and also return the disk as soon as you can after you receive it to avoid any problems. If you do send money and then send a disk with a contribution for the magazine, your credit will be adjusted accordingly. The credit system means that a disk+stamps or 75p is worth one credit. When your credit rating is zero you will be informed so that you can send more disks/money as you wish. Back issues of the magazine are available from us for 1 per disk. The address for ICTARI is :- 63 Woolsbridge Road, Ashley Heath, Ringwood, Hants, BH24 2LX. (Please note that this document will not change each month unless mentioned in the ICTARI.TXT document file) ---------------- ts overwritten by the end of the track. The solution is to reduce, to the absolute minimum, the size of the gaps between each sector, and the bytes that fill the end of the track. This can't be done using the XBIOS routine and so one has to resort to writing routines to create the formatted track data and to control the WD1772 chip. With the help of 'ST Disk Drives: Inside and Out', the 'BIOS' listing in 'Atari St Internals' and disassembling the ROM routines myself, I wrote an extended formatter. The program didn't get completely finished. I think that the routines for busying the FAT entri