Fnf~0>FwG >8<>9:!@u~ H>9:!_Failed testing low RAM !~Error reading Operating System }\_~ CCP+ v2.2 (C) 1986, C.B. Falconer, Tel. (203) 281-1438, 680 Hartford Tpk., Hamden, CT., USANo FileNo roomAll (y/N)?File existsNo UPSHIFT*=)< a{_0:?> > _>t 8/ 8 y0> t>j2:8 '<'>t<>>>>>,>(>>>KylOC_> > O:i'(':=2SD 2!w#5.((:i=2P:i_*=>:Ą:A>>:!>> tog#wɯ!+"͕q#p:n.n#6 >?#  y(#* 6?w#6 0@Q:(:( :0 @G:O:8SWy?؇O~(#~7=_.:;<>,| 8#0(*{G~#>?͹`e21!c"2r2y1::(͹#!"~*(;(<(:(:2o$*~*+0e> (y<[yOx=:Oy2: 2 3: (K y>?!3~#foK :< xԺ=!E# y # y[x=u:GC+2(+8S(O 2+8; > (j!~  6?#6(V=`O,8? :_WA:> >:> xBx ( 82 +Á> BG: xSx/!~9[ (Tx8AG!~(9: (! ~ (+( #8y2#(~ (=y9j (=L(52o&):(#|(+!SH( .!!~/w!(!'( !;5#~_Yj=!~#9j6 :!+=(_ *9+0*}< "j6(>t!=:! =w !> (![ (!}|SA((3>)22\!!!: ~( (#:~(#x2KGDIR ERA TYPESAVEREN CAPSGO KILL1!q;cCCP+ Ver. 2.2$$$ SUBCOMCCPXTENDSYS 6U{Z F@py2s1!~@22go">&8y!h:{{*}Dɇog~#fo{!|y  3$)B.+*Emy?xr;5.!~#(<(##(h%is_%KK-**|r ԰Û:{2K((: (y*ĕÔo& )8#|e0Ͱ> ͐> > O :!4 5( 6455!~͎>!~6#~6! r:> 22!  ${x~ +( N# ͅ((( :2(( (# (#wy +>{~x =#6p { ͎: > {>^{@{ (2:>(:@d~ y:! ͅ_Y/Eͪ_RA(I N$W>ͪ:O{*!"\ A)bort I)gnore R)etry?$ Resume (y/N)?$O:A2|o`:b878( !8+%8( # (ͽg>.{#~ {:>" t>%pr2og""͆:VN~?( ~?(6><9*[*NHN:N!*":2**N*{(2:NQͽ! zݖ!yݞ"xݞ#H ! r!q"p#~! W~O##~GO{/_z/W*{ozg"*{ozg">2:2_~2?(!{(~=͆:w* :w:_{G[(!C(wO!|(^#V#S"*C*/"[>:= *6#z [s#r*w#w2>ͽ(!( #~$ =2͸!:()= zg{o*<<"!K>B0 ?=(j*DM![!0DM!!N :G9/ G:ݦ  O :^W ^#V+*:og~!"*|<j*[{#zO*#"[R(0}`2DͅP*[R*#* w*/"[*s#r!'n(!*n(* S*ÔKK!${2>2"(i[(0Yͽ!(2O:G8" ~(~ 2# :22?/(y (<( ŮG:/>Û> 9ͽ6ͺ͛H ̓H~(~ w  ̓H> 9:2N6'G~ <~ w ~ ͽ F Nw (0q: ~ͽ HwDͅ^N~7  :(½#@(# !~ 8w###~w~@(#+ w@#w#+7:*|:G~##ʺ$(=(+͆:G~#$( 7(ͽ:<2N6͡~6>9wȯw w#ͽ~w ̓~ ,ͱ:< 8 $7 :(͂ ú 8GÛN Fp7 yO x?G7:~ q O~pGNRN2~ : $w ݾ0͎z(~VP:4 >!:G#:ݦ _N>RN>2~ 8 : w ͎z Zy(=ͨz>ʛ͡s:(#r:( 3*w#~:G/_Vͅ^͡~V^~ ݾ8z ͱ:<(.&7:< :<(&>͂:<(G 6{2*` ~!W:__4y(4>8 ~Û7 *|7:Disk I/O$No drive$File R/O$ Fn: $ File: $ DOS+ error : $Copyright (c) 1986 C.B. Falconer (203) 281-1438gÑ>gVIÂæÇÙáaÞguguAVH?% *P'cH %lO1͌ b:fOͦW *!~0>F87G >8(22>2!"2!"͡:O! v FAIL~O>#8!@ +| ͽ(88W(y8G(8˿8o( 8a ( > 9> 9͌y2::y2C!y2L!3  ~#fo+F+NC ">2>2S2y2 >2:2:2:2:(*=2*[R !: 4~H86!422<22:??2!~6(*[R !:(:*":2:2:.?g[: >2::2:>>>N*!:W8>2z?BL!3  { ~#fo^ ?#!2~#fo7utVuy= :f=7*Kx! 8 <_X2z22f!<"!ͪ>9 > 9882F! >N #  BIOS built 08-Mar-1997 8w(  7>8Ae!~ !#~ #~ (&8'>  >7>78(98(8F#~X!:/wͳ)#!$9%>9 9!9"ͳ) !!9">9#9$9%{==ݾ0c90>X !@F)T]!)&!'">>XeGe9>7x >7B>2G8O 9y 89~  = ~ 9>X~X~ˇX!: >XzX38:w8>7Nد!o0$~#foNi!s! !!">2!">20( {:= 7[729> 9!dpq+89XL͇>91͹F@XL͠>91͹E@XL͹VL|g8:o|8888:o|>889Lo`)))) |E`NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNamo Ching-Hai Wu Shang ShihRECEIVE PASLICENSE TXT LICENSE TXTHARDWARETXTHARDWARETXTd@AUUENCODEPASJ !"#UUDECODECMR'()*+,UUDECODEPASM$%&-.UUENCODECMP56789QDUP HEXRECEIVE CMC89:;<USER MAC1FORMAT CMGZ80 LIB23USER CMIDOS LIB 4PPIP CMMNDOSPLUS HEXD:;<=>DOSPLUS MAC?EFHJKLODOSPLUS MACPQRSTUVWDOSPLUS MACXYZ[\]^_DOSPLUS MAC`abcdefgDOSPLUS MACahijklmnBIOSHOOKMAC oROMHOOK INCpBIOS HEX,DqrBIOS MACstuvwxyzBIOS MAC{|}~7BIOS SUBBIOSTOP MACDPARM INCDRVTYPE INCDISKOPQ MACDISKOPQ MAC!FDC INC LOADBIOSMAC README TXTBCASCII INCZ180 INCEZ180 INCEDPARM INCDRVTYPE INCASCII INCROMHOOK INCBOOTSEC HEXBOOTSEC MAC@BOOTSEC SUBREADME TXT Z80 LIBCCPLUS MACCCPLUS MAC}CCPLUS HEX'Z180 INCEDPARM INCASCII INCDISKOP MACDISKOP MAC!FORMAT HEX&FORMAT MACKFORMAT SUBZ180 INCEDISKOP MACDISKOP MAC!DPARM INCDRVTYPE INCFDC INC ASCII INCROMHOOK INCMACROS INCSTARTUP MACSTARTUP MACDDEBUG MACDRIVPARMMACDEBUG MAC   ROM HEXf  ROM SUBDEBUG MACeMEMSETUPMACg>?@NOPSYSBOOT MAC* !RTC MAC."#$FDC INC %Z180 INCE&'()*DOSPLUS SUB+CCPLUS SUB,!!READ ME -ROM UUE./012345ROM UUE6BIOS MAC=ROM PASoABCDEFGROM COM^HIJKLMREADME TXT_QRSTUVQDUP MAC DISKCOPYMAC?/0DISKCOMPMACYWXYZ[\DISKCOPYCOM]DISKCOMPCOM ^DEBUG PRNklmnopqrDEBUG PRNstuvwxy{DEBUG PRN|}~DEBUG PRNeSYSBOOT PRNSYSBOOT RELSYSBOOT PRNDISKOP PRNDISKOP REL DISKOP PRNDISKOP PRNDISKOP PRNDDRIVPARMPRN)DRIVPARMRELTEST HEXeTEST SYMtype receive.pas Program Receive_Text_Files; {Simple program to receive downloaded text files. Text is processed until a ESC occurs at the start of a line. Lines are terminated by CR. LF chars. are discarded. Invokation: RECEIVE The file-name must be specified on the command line. D-X Designs Pty Ltd. Perth Australia Author: D R Brooks. May 1996 } type xline = string[120]; const cmtail = $80; {CP/M command tail} var lfirst: boolean; outf : text; iline : xline; cmd : ^char; ctr : integer; procedure xreadln (var x :xline); var a : char; begin if (not lfirst) then write(#6); {Move to here: Ready signal} lfirst:= false; inline ($3e); inline ($05); {ld a,05} inline ($ed); inline ($39); inline ($e0); {out0 (sccacnt),a} inline ($3e); inline ($6a); {ld a,6a - RTS on} inline ($ed); inline ($39); inline ($e0); {out0 (sccacnt),a} x := ''; repeat a := chr(bios(2)); if a <> ^J then begin if a <> ^M then x := x + a; end; until a = ^M; { write('.'); Moved to top of routine} inline ($3e); inline ($05); {ld a,05} inline ($ed); inline ($39); inline ($e0); {out0 (sccacnt),a} inline ($3e); inline ($68); {ld a,68 - RTS off} inline ($ed); inline ($39); inline ($e0); {out0 (sccacnt),a} end; begin writeln('File Download Receiver: D-X Designs Pty Ltd, 1996'); lfirst := true; ctr := 1; {Start of string} iline := ''; cmd := ptr (cmtail + ctr); while ord(cmd^) <> 0 do begin iline := iline + cmd^; ctr := ctr + 1; cmd := ptr (cmtail + ctr); end; if length(iline) = 0 then begin writeln('File Name must be specified'); halt; end else begin assign(outf,iline); rewrite(outf); writeln('Ready to receive ', iline, ' type ESC/CR to end'); xreadln(iline); while iline[1] <> ^[ do begin if iline[1] <> ^J then writeln(outf,iline); xreadln(iline); end; close(outf); end; inline ($3e); inline ($05); {ld a,05} inline ($ed); inline ($39); inline ($e0); {out0 (sccacnt),a} inline ($3e); inline ($6a); {ld a,6a - RTS on} inline ($ed); inline ($39); inline ($e0); {out0 (sccacnt),a} end.  type ESC/CR to end'); xreadln(iline); while iline[1] <> ^[ do begin if iline[1] <> ^J then writeln(outf,il What's on this disk, & where is it? ----------------------------------- To keep things in order, I have filed everything under different DOS+ "users". Think of those users as MS-DOS subdirectories. I have not included source files that are generally available on the Internet: only for code I myself wrote or altered. In general, the code is suitable for processing with M80/L80, and Turbo Pascal. Generally, each "user" repesents a separate project. Each user therefore includes (unless it's a trivial matter) a .SUB file to assemble & link it. The more complex projects also include a README.TXT file. The DOS+ and CCP+ modules are by C B Falconer (see his notices in !!READ.ME and the source files). I have made minor changes to assemble with M80 (documented in the files), but have not changed the "sense" of the code. The disk layout is: User 0, "system" files (accessible from any user): 1. PPIP.COM A shareware replacement for CP/M's PIP 2. UUENCODE.COM and UUDECODE.COM The standard binary/ASCII converters 3. FORMAT.COM Formats 3" and 5" disks for the P112 system 4. USER.COM Change user numbers under DOS+. Same as CP/M (ie "USER n"), but 0 <= n <= 9. 5. RECEIVE.COM Receives and files ASCII text. Enter "RECEIVE ", and enter ESC/CR to quit. Because these are "system" files, they will not show up on a DIR listing. User 0, non-system files (visible on DIR): 1. README.TXT This file 2. HARDWARE.TXT Explanation:20800000AF320081CF3E021600CD2A803E031601CD2A803E041601CD2A803A00813C32009A :2080200081FE5038E0214680E7FF0603C52100814E06121E01210181DD2A0B00CFC1D01072 :20804000EB215180E7FF46696E6973686564210D00556E7265636F76657261626C65206533 :0780600072726F72210D0026 :00000001FF FORMAT CMGZ80 LIB23USER CMIDOS LIB 4="!M87D@;F]T(&)E M('1H92!S86UE(&1R:79E+`T*(&)U="!M=7-T(&)E('1H92!S86UE('1Y<&4- M"@T*(&5G($1)4TM#3U!9($$Z($(Z#0H-"B1$7!E#0HD0V%N;F]T(&-O<'D@=&\@=&AE('-A;64@9')I=F4-"B1! M8G-E;G0@;W(@:6YV86QI9"!DJ!KS)6@CI<`,T4@#X"S2>`.FP`S12`/@/-)X`Z;`#-%(`^!,TG@"%6@C1^ MRS_=O@LXTRC1$4>"P["`0V]M<&QE=&5D(0T*)``````````````````````` M```````````````````````````````````````````````````````````` M```````````````````````````````````````````````````````````` M```````````````````````````````````````````````````````````` M```````````````````````````````````````````````````````````` M```````````````````````````````````````````````````````````` I```````````````````````````````````````````````````````` ` end sum -r/size 10924/1265 section (from "begin" to "end") sum -r/size 16667/896 entire input file m -r/size 57242/1443 section (from "begin" to "end") sum -r/size 64639/1024 entire input file `````` M```````````````````````````````````````````````````````````` M```````````````````````````````````````````````````````````` M```````````````````````````````````````````````````````````` M```````````````````````````````````````````````````````````` M```````````````````````````````````````````````````````````` B```````````````````````````````````````````````` ` end su;Fast duplicator. Runs under ROM. 3" disks only. .z80 cseg xor a ld (track),a rst diskop ;Reset drives l1: ld a,2 ld d,0 ;Read drive A call dfn ld a,3 ld d,1 ;Write drive B call dfn ld a,4 ld d,1 ;Verify B call dfn ld a,(track) ;Next track inc a ld (track),a cp 80 ;Done? jr c,l1 ld hl,dunmsg ;Yes rst putmsg rst break ;The end... dfn: ld b,3 ;Retry limit df1: push bc ld hl,track ld c,(hl) ld b,18 ;Sectors/track ld e,1 ld hl,buff ld ix,(parptr) ;Drive parameters rst diskop pop bc ret nc ;Back if no error djnz df1 ld hl,fltmsg ;Report failure rst putmsg rst break ;Crash! diskop equ 08h ;Diskette driver parptr equ 0bh ;Ptr. to drive params. putmsg equ 20h ;ASCIIZ from (HL) break equ 38h ;Exit to ROM dunmsg: db 'Finished!',0dh,0 fltmsg: db 'Unrecoverable error!',0dh,0 dseg track: ds 1 ;Track number buff: ds 512*18 ;Track buffer end tmsg rst break ;Crash! diskop equ 08h ;Diskette driver parptr equ 0bh ;Ptr. to drive params. putmsg equ 20h ;ASCIIZ from (HL) break equ 38h ;Exit to ROM dunmsg: db 'Finished!',0dh,0 fltmsg: db 'Unrecoverable error!',0dh,0 dseg track: ds 1 page 90 title Disk-Copy Utility: P112 subttl 29-May-1996 DRB ;===============================================================; ; ; ; D I S K - C O P Y U T I L I T Y - P 1 1 2 ; ; ; ; ; ;===============================================================; ;=======================================================================; ; ; ; D-X Designs Pty. Ltd. Perth, Western Australia ; ; Project: 112 May, 1996 ; ; ; ; Copyright (C) 1996 David R. Brooks ; ; ; ; This program is free software; you can redistribute it and/or ; ; modify it under the terms of the GNU General Public License ; ; as published by the Free Software Foundation; either version 2 ; ; of the License, or (at your option) any later version. ; ; ; ; This program is distributed in the hope that it will be useful, ; ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; ; GNU General Public License for more details. ; ; ; ; You should have received a copy of the GNU General Public License ; ; along with this program; if not, write to the Free Software ; ; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ; ; ; ;=======================================================================; .COMMENT $ This program runs under DOS+, but uses ROM functions. It is relocated to high memory to run. $ Z80182 equ $ include Z180.INC include DPARM.INC include ROMHOOK.INC include ASCII.INC aseg org 100h jp begin runat equ 8000h begin: ld hl,reloc ld de,runat ld bc,size ldir ;Copy it up jp start ;Then run it sdv equ 5ch tdv equ 6ch ;Drive nos. from CCP+ exit equ 0 bios equ 1 ;Points to BIOS+3 bdos equ 5 ;------------------------------- reloc equ $ .phase runat ;Moved code testdv: ;Validate drive, passed in A and a scf ret z ;Zero from CCP+ if invalid dec a ;ROM is based-zero ld d,a ;Drive ld c,2 ;Call code ld e,-1 ;get type ld hl,(bios) dec hl dec hl dec hl ;Point at "overload" entry call jphl ret ;Back: CY, E, IX jphl: jp (hl) ;------------------------------- spars: ;Set up parameters for drive function ; Pass drive no. in A (as from CCP+) ld ix,(hwp) ld hl,tbuff ld e,1 ;Start at Sector 1 dec a ;Drives based zero ld d,a ld a,(ctrack) ld c,a ld b,(ix+EOT) ;No. of sectors ret ;------------------------------- dodv: ;Basic drive function push de push af ld a,0c8h out0 (cbar),a ;General Public License: Free Software Foundation Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave, Cambridge, MA 02139, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 1. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 2. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 3. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: 1. You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. 2. You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. 3. If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 4. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: 1. Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, 2. Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, 3. Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 5. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 6. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 7. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 8. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 9. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 10. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 11. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 12. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 13. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. one line to give the program's name and an idea of what it does. Copyright (C) 19yy name of author This program is free software; you can redistribute it and/or modifyneral Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. signature of Ty Coon, 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. ompilers) written by James Hacker. signature of Ty Coon, 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you mayZ80182 CPU card. David R. Brooks, daveb@iinet.net.au ---------------------------------------------------- 1 Introduction The "P112" board implements a stand-alone Z180-based computer system. Although primarily designed as a CP/M platform, it can support other software. The board is designed to fit on a 3.5" diskette drive (some drives may require spacers). It requires only +5V power, so that, with a 5V-only diskette drive, no other power supplies are required. Power consumption (board only) is around 150mA. The board supports two RS-232 serial and one parallel IO port, besides a capability for bus expansion. An expansion socket permits 3 further serial ports to be used, by providing off-board level converters. All ports are fully inter- rupt-capable. The following goals were set, in selecting components: * Parts should be current production, recommended for new designs * No specially programmed logic devices should be necessary 2 Logic Description The following descriptions should be read in conjunction with the accompanying schematics. Data sheets on the various chips are obtainable from the manufac- turers' Web sites. 2.1 CPU Zilog recommend two parts for new designs: the Z84C15 and Z80182. For the present project, the Z80182 is appropriate, providing a Z180 core, with enhanced memory mapping features. This part is available in a range of clock speeds: the initial boards are clocked at 16MHz. This speed, while the highest the CPU chip can support, does limit the choice of serial-port speeds, as it does not factor well. This has minimal impact on the standard serial port, which uses the in- built baud-rate generator. This generator is very flexible in its range of pos- sible divisors. If however, the expansion ports (see P16 below) are used, they have a much reduced set of divisors available, and will normally require a carefully-chosen clock frequency. The boot software can recognise and adjust to the following clocks: 12.288MHz 16.0MHz 18.432MHz 24.576MHz The last two will require a faster CPU chip to be fitted. The Z80182 includes several in-built peripheral functions. All these are fully supported by the Z80 vectored interrupt system. The following internal peri- pherals are used: 2.1.1 Serial Port The Z80182 has a total of 4 serial ports. Of these, one is brought out as the default terminal port, at normal RS232 levels. The remaining 3 ports are available as un-buffered TTL signals, for use with off-board level converters. One of these additional ports features full SDLC functionality, and can be configured for DMA control. The Z80182 serial ports do not support the DSR and RTS modem-control signals, so these are provided (in the main-terminal port) by two lines from the on-chip paral- lel port (see below). These lines are not used by the standard software. 2.1.2 Parallel Port The Z80182 has one 8-bit parallel port available (the others have been overridden for other functions). This is used to support on-board facilities. The pin assign- ments are: A0 RTC data I/O line (bidirectional) A1 RTC Clock line A2 RTC Reset line A3..A4 Not used A5 Set low to enable the 12V Vpp generator for flash ROMs A6 DSR input from Serial Port 1 A7 RTS output to Serial Port 1 2.1.3 DMA By default, DMA Channel 0 is used for the diskette controller, and Channel 1 is available to an expansion card (if fitted). Jumper P2 may be altered if required, to provide DMA support for Serial Port 1. The Z180 DMA only provides the TENDx (end-of-block) signal during its write cycle. This makes it unusable with the floppy disk controller, when reading from the disk (the FDC requires TEND asserted during the DMA cycle addressed to it, not to the memory). Consequently, the FDC is programmed not to use TENDx, which implies that all transfers will post a "end of cylinder" error. This is allowed for by the software. 2.1.4 Memory Mapping The Z80182 includes two levels of memory mapping logic. The first maps the 64kB logical address space into a maximum of 3 "zones" in the 1MB physical address space. The second decodes the RAMCS\ and ROMCS\ outputs from the translated physical address. In normal use, the first map may be changed frequently, as the operating system switches tasks. The second will normally be initialised at reset, in terms of the amount of memory actually fitted, and not changed thereafter. The boot-code includes a "smart" memory initialisation routine, which examines the chips actually fitted, and locates them in the physical space in an optimal manner. The sign-on message includes a report of the amount of RAM available, and its location in physical address space. If sufficient RAM is present, the ROM will be copied into low RAM, and afterwards disabled. This enables the CPU to be run faster. The memory setup routine makes two requirements: 1. If two RAM chips are fitted, they must be of the same size. 2. The address-decode jumper P1 must be correctly set. If these requirements are not met, the startup code will malfunction. 2.1.5 Interrupts The Z80182 has full vectored-interrupt support for its internal peripherals, plus 3 external interrupts. These are: INT0\ The regular Z-80 vectored interrupt input INT1\ & INT2\ Auxiliary interrupt inputs (vectored) The NMI interrupt is not used. The P112 board does not use INT0\, but makes it available on the expansion socket, J1. It is therefore available to expansion boards. INT1\ is assigned to the diskette interrupt, while INT2\ is shared by the parallel port and the auxiliary serial port (both on the SMC chip). For proper operation, both these interrupts should be programmed to be active-low, level sensitive (this is done by default in the ROM code). The initial software release uses no interrupts. A future INT2\ routine should begin by reading the interrupt-ready register from the auxiliary serial port. This will reveal which (if any) serial-port condition has issued the interrupt. If none, the interrupt is from the parallel port. The interrupt routine should run repeatedly as long as the INT2\ pin is low: this will process multiple interrupts occurring together. Note that the ROM code leaves the INT1\ and INT2\ interrupts disabled (via the ITC processor control register). This must be enabled before they can be used. 2.2 Memory The board is designed to accept a wide variety of memory parts, in both 28 and 32-pin packages. The 0.6" DIP format was chosen as being compatible with the widest range of parts. One ROM socket and two RAM sockets are fitted. A pre-programmed ROM can be fitted in a RAM socket if desired. On-board RAM capacities from 32kB to 1MB are available. The jumper P3 can interchange the select signals for the ROM and RAM-1 sites. This permits a pre-programmed ROM to be fitted in RAM-1 (U3), to program a blank flash device in U4. (See below). 2.2.1 ROM The ROM socket (U4) can accept a 32kB ROM part. A pre-programmed EPROM may be used, or a "flash" ROM. The board includes facilities for in-system programming of 5V and 12V flash ROMs. For normal use, the header P12 should be jumpered across Pins 2-3 (WE\). For 12V parts (Intel or AMD 28F256), the 12V converter U12 is required. At power-up, this converter will be disabled, causing a Vpp of 5V to be supplied via D2. This makes the circuit safe with 5V ROMs also. To program a ROM, set the CPU parallel port pin A5 low: this enables the 12V supply. For 5V ROMs (eg Atmel AT29C256), U12, Q1, R3 and R4 may be omitted. D2 may be replaced by a shorting link, to deliver standard 5V power. 2.2.2 On-Board RAM Each RAM socket may accept a 32kB, 128kB or 512kB SRAM part. The address decoding must be set for the parts in use, as follows: RAM size RAM part (typical) P1 setting P13 setting ------------------------------------------------------------------- 32kB / 64kB HM62256 1-4 (A15) 1-2 (Vcc) 128kB / 256kB HM628128 1-2 (A17) 1-2 (Vcc) 512kB / 1MB HM628512 1-3 (A19) 2-3 (A17) It is not possible to mix RAM chips of different sizes. For zero wait-state operation, 70nS parts are required. 2.2.3 Expansion RAM Provision is made for an expansion board to carry up to 32kB of RAM, which may be mapped into the main memory space. By convention, such memory will be at the top of the 1MB physical space. The purpose of this is to provide for dual-port memory for video drivers and similar devices. Of course, the 32kB may be extended by a bank-switching arrangement on the expansion board. Expansion board memory should be selected when the signals ROMCS\ and RAMCS\ are both high (ie no on-board memory is selected). The read and write enables are MRD\ and MWR\, which enable bus transactions. If necessary, the WAIT\ line may be driven low to delay the CPU. 2.3 IO Cycle Control The multi-function IO chip requires two additional wait-states in every IO cycle, to satisfy its timing. This is provided by setting the IWI bits in the DCNTL register of the Z80182 CPU (IO address 32H). 2.4 Real-Time Clock The Dallas DS1202 has a simple bit-serial interface. This is supported by 3 bits from the CPU's internal PIO device (see above). The DS1202 also provides a block of battery-backed RAM, which may be useful for storing BIOS setup parameters (memory size, serial communications setups, etc.). 2.5 Expansion Socket The CPU bus is brought out to the expansion socket J1. Access to expansion memory has been described above. For external IO devices, IORQ\ low and M1\ high should be decoded to validate an IO access. Valid addresses for expansion boards are in the ranges 40..7F and C0..D7. The IO data strobes are RD\ and WR\. Support is provided for expansion boards using the Z80182 internal DMA. The EXTRQ\ request line may be jumpered (at P2) to one of the internal DMA channels. 2.6 Serial Port 1 This is implemented using one of the Z80181's internal SCC channels. These have enhanced capabilities over standard PC channels, including SDLC operation, and fully vectored interrupt support. See the Z80182 documentation for details. 2.7 Multi-IO Chip The non-CPU IO functions are implemented in a SMC multi-function IO chip. These parts are available in several variants, and the board is designed to accept 4 different types: FD37C651, '652, '665 and '666. Further details on configuration options are given below. 2.7.1 Address Decoding The multi-IO chip occupies the IO address space 80..BF. These addresses are mapped to appear to the IO chip as standard PC addresses. Programming of the multi-IO features follows standard PC practice. The address mapping is described below. 2.7.2 Cycle Timing The IO chip latches address data at the beginning of IOR\ or IOW\. This can cause problems with the Zilog timing, which regards the RD\ and WR\ signals as basically clock-enables. This is overcome by use of the CPU's "E" clock output, which goes high during the valid part of a bus cycle. This is used as a local enable to IOR\ and IOW\, via the decoder U11A. This decoder also provides the interlock from the safety-latch described below. 2.7.3 Safety Latch As pointed out by Claude Palm (The Computer Journal, No. 76) the Z180-series devices can generate spurious IO selections during interrupt-acknowledge cycles. These are normally suppressed, since neither of the RD\ or WR\ data strobes appear. However systems which decode the DACK\ (DMA acknowledge) from the address may malfunction, due to these spurious IORQ\ signals. In the present design, this is prevented by the latch U8. This is set at the beginning of a interrupt acknowledge cycle (M1\ and IORQ\ both low), and blocks any address decodes. The latch is only cleared when IORQ\ again goes high, at the end of the acknowledge cycle. 2.8 Serial Port 2 This is the "primary" serial port on the multi-IO device (the secondary port is not used). It is strictly PC compatible. 2.9 Diskette Port The diskette interface emulates a standard PC-type diskette controller. The IO chip is configured to logically "swap" Drives 0 and 1. This assumes the drives have the DS1 jumper set, as is normal for PC-AT usage. Given this, Drive-0 connects directly to the PCB, with no ribbon-cable cores swapped. This is to enable the PCB to be mounted directly on the disk drive, with the PCB and drive connectors adjacent. Drive-1 will be the further away, and will have cores 10-16 swapped in the cable. It should be noted that there is no universal standard regarding the placement of the data connector on diskette drives: it is not possible to have this card fit directly to every drive available. The direct fitting has been tested with Teac FD235 drives. 2.10 Printer Port The printer port provides PC-like functions, in basic bidirectional mode. Enhanced ECP and EPP modes are not supported. 3 Major Components The principal components are briefly introduced below, with particular reference to their use in the present application. 3.1 CPU Chip The Z80182 provides a Z180 CPU core, multi-function serial IO port, and two DMA channels. Extensive use is made of the Z180's memory mapping ability, to fill in "holes" in the physical address space, and to switch the ROM in and out of circuit. This part is available in several speed grades: the initial build will be fitted for 16MHz clocking. 3.2 I/O Combination Most of the IO functions are implemented in a SMC multi-IO part, designed for use in PC's. The board is multi-capable, and can accept any of the following parts: * FDC37C651 * FDC37C652 * FDC37C665 * FDC37C666 The '651 and '665 are fully software configurable. However the '652 and '666 have some functions configured by external resistors. These are not otherwise fitted, and are the only surface-mount resistors on the board. Space limitations preclude putting reference designators on the board, however they are all 1206 size, 27kR parts. Their reference designators are R101..R111. No harm will occur if they are fitted with a software-configurable IO chip. These parts can be programmed to generate active-high or active-low interrupt signals. In this application, active-low is required, and is selected by the start-up code. These chips come in (at least) two sub-variants, identified by -GT and -IR suffixes. In the P112 board, the main difference is that the -IR version only supports 3 disk drives (Drive 2 is unavailable), while the -GT supports 4. 3.2.1 Port Addressing The IO chip may be configured for several different internal address decoding schemes, correponding to different IO assignments in a PC environment. In the present application, the following addresses are used: Function Address (CPU) Address (IO chip) ----------------------------------------------------------------- Parallel Port 8C..8F 3BC..3BF Diskette (program access) 90..97 3F0..3F7 Serial Port 98..9F 3F8..3FF Diskette (DMA access) A0..BF N/A 3.3 Flash ROM The board is designed to accept a variety of flash ROM parts. The inital build is fitted with Intel parts, which need a 12V programming voltage. If 5V-only parts (eg Atmel) are used, the voltage converter U12 and its associated components may be omitted. 3.4 Realtime Clock A Dallas DS1202 realtime clock/RAM is used. This has a serial interface, which is implemented using 3 spare parallel-port pins from the CPU chip. Be aware that this chip, when first powered-up, defaults to write-protected and oscillator disabled. Before it will run normally, you must first turn off write- protect, then activate the oscillator. Each is a single-byte write operation. 4 Connector Pins The pin assignments of the various connectors are tabulated below. All are 0.1" pitch headers. 4.1 P1 RAM Size Selector Pin Assignment -------------- 1 Address decoder input 2 A17 (128kB chips) 3 A19 (512kB chips) 4 A15 (32kB chips) This jumper selects the address at which the address logic switches between the RAM chips. In effect, it defines the capacity of each RAM chip. The pin assignment is as follows: 4 3 1 2 4.2 P2 DMA Requests Pin Assignment -------------- 1 Diskette controller request 2 DMA request 0 (to CPU) 3 Expansion skt. request 4 DMA request 1 (to CPU) 5 SIO request This header selects the sources for DMA requests. The Z180 core includes 2 DMA channels, which may be connected among 3 possible sources: diskette, expansion socket, and serial IO channel. The standard boot code requires Pins 1 and 2 jumpered. 4.3 P3 Flash Bootload Selector Pin Assignment -------------- 1 RAM select from CPU 2 RAM socket 1 select 3 ROM socket select 4 ROM select from CPU For normal use, jumper pins 1-2, 3-4. For ROM duplicating, jumper pins 1-3, 2-4. This jumper allows the ROM (U4) and RAM-1 (U3) sockets to be logically interchanged. The effect is that the CPU will boot from RAM-1. This enables the board to serve as a flash-ROM duplicator, using the following procedure. Set P3 in the "normal" position, and fit the standard boot ROM in U4, with a 32kB RAM in U2 and U3. Boot the system: it will report RAM available at 40000..4FFFF (physical locations). The logical space is mapped as 0000..7FFF to U4 (ROM), and 8000..FFFF to U3 (RAM). U2 is currently inaccessible (being overlaid by the ROM). NB The following procedure will be superseded by future software. Now copy the existing boot code into U3 as follows. Manually enter the following code into high memory: FFF0 di F3 FFF1 ld hl,0 21 00 00 FFF4 ld de,8000 11 00 80 FFF7 ld bc,FFF0 01 F0 FF ;Copy up to this code FFFA ldir ED B0 FFFC halt 76 Set SP=FFFF, and Go FF00. The ROM code will be copied into U3 RAM (overwriting the Debugger workspace), and the CPU will then halt. Without removing power, hold the Reset input pin low. Then interchange the J3 jumpers, and fit the new ROM in U4 (do this carefully: you are "hot-plugging" the ROM). Finally remove the Reset. The board will re-boot, and will report RAM at 40000..47FFF (physical). The code now sees logical addresses 0000..7FFF in U3, and 8000..FFFF in U2. The ROM is currently inaccessible. The system is now live, with 64kB of logical RAM available. You can boot the opera- ting system normally, and use the ROM-burning program (not yet available) to prog- ram the ROM. Remember to use an OS version with a RAM-resident BIOS! To boot from your new ROM, don't forget to reset the P3 jumpers before resetting. If you do not, it will boot from the RAM image: this may be a useful technique for checking-out a new boot program before burning it in ROM. The above procedure is not, of course, limited to building boot ROMs. In this mode, the board serves as a general-purpose flash-ROM programmer, for 32kB parts. 4.4 P4 Serial Port 1 Pin Assignment -------------- 1 DCD (in) 2 DSR (spare in) 3 RXD (in) 4 RTS (spare out) 5 TXD (out) 6 CTS (in) 7 DTR (out) 8 SYNC/RI (in) 9 Ground 10 Not used The pin assignments are such that a 10-way ribbon cable (with the 10th core removed) can connect a 10-way header to a DB-9 plug, and generate the standard PC/AT pin arrangement. This port is implemented as a Z180 port, which does not support the DSR and RTS lines. These are therefore implemented using parallel port pins. This port can support synchronous modes, in which the CPU's SYNC pin (normally used as the RI input) becomes an output. To prevent contention with the RS232 receiver, the jumper at P5 should be removed in synchronous working. The Z180 uses the CTS and DCD pins as hardware enables. For the port to operate, these must either be strapped to the DTR output, or connected via (for example) a "null modem" cable to another PC-AT compatible port. If left open, the port will be disabled. 4.5 P5 SYNC Jumper Pin Assignment -------------- 1 From SYNC receiver 2 To SYNC pin on CPU See P4 above. This link may be removed to prevent contention between the SYNC output of the CPU chip, and the RS232 receiver output. The link should be fitted in asynchronous working, and removed for synchronous. 4.6 P6 Power Supply/Reset Pin Assignment -------------- 1 Ground 2 +5V 3 Reset 4 +5V 5 Ground The reset input is intended for a switch to ground. It may be left open, the board will automatically reset when powered up. 4.7 P7 Parallel Printer Pin Assignment -------------- 1 Strobe\ 2 AutoFeed\ 3 D0 4 Error\ 5 D1 6 Init\ 7 D2 8 Select-In\ 9 D3 10 Ground 11 D4 12 Ground 13 D5 14 Ground 15 D6 16 Ground 17 D7 18 Ground 19 Ack\ 20 Ground 21 Busy 22 Ground 23 PaperEnd 24 Ground 25 Select 26 Ground The pin assignment is such that a 26-way ribbon cable (with line 26 removed) may run direct to a DB-25 connector, presenting a standard IBM parallel printer inter- face. The interface offers the basic bidirectional capability; expanded (ECP/EPP) feat- ures are not available. 4.8 P8 Serial Port 2 Pin Assignment -------------- 1 DCD (in) 2 RXD (in) 3 TXD (out) 4 DTR (out) 5 Ground 6 DSR (in) 7 RTS (out) 8 CTS (in) 9 RI (in) 10 Not used See P4 for details. This port is implemented on the combination IO chip, and is strictly PC compatible. 4.9 P9 Disk Drives 0,1 Pin Assignment -------------- 2 DENSEL\ 4 Not used 6 DRATE0 8 INDEX\ 10 MTR0\ 12 DR1\ 14 DR0\ 16 MTR1\ 18 DIR\ 20 STEP\ 22 WDATA\ 24 WGATE\ 26 TK0\ 28 WPROT\ 30 RDATA\ 32 HDSEL\ 34 DSKCHG\ All odd-numbered pins are Ground. Drive wiring is the usual PC/AT type, with lines 10..16 switched around between the drives. The Drive 0 & 1 signals are logically interchanged within the IO chip, so that the drive connected without a twist in the cable is Drive 0. This will typically be the drive on which the board is mounted. 4.10 P10 Disk Drives 2,3 Same as P9, but decodes Drives 2 & 3. 4.11 P11 Battery Isolator Pin Assignment -------------- 1 Ground 2 Battery -ve This serves as a safety-isolator while working on the board, and to force a reset to the real-time clock chip. 4.12 P12 ROM Pin-3 Function Pin Assignment -------------- 1 +5V 2 U4 pin 3 3 Memory Write\ This jumper connects Pin 3 of the ROM socket either to MWR\, or to Vdd. For normal use, connect to MWR\. 4.13 P13 RAM Pin-30 Function Pin Assignment -------------- 1 +5V 2 U2/3 pin 30 3 A17 For 512kB RAM chips, this pin should connect to A17. For smaller parts, connect to Vdd. 4.14 P14 Extra Serial Ports This connector carries un-buffered signals for the spare CPU serial ports. Uncom- mitted inputs have 47k pull-up resistors. The signal names follow those used in the Z80182 data-book, which should be consulted for the capa- bilities of these ports. The pin-outs are: Pin Signal Pin Signal ---------------------------------------------- 1 TXA1 2 RXA0 3 RTS0 4 CTS0 5 RTSB = TEND1 6 DTRB 7 CTS1 8 TXA0 9 RXA1 10 DCD0 11 CTSB 12 DCDB 13 Vcc 14 TXDB 15 TRXCB 16 RXDB 17 RTXCB 18 SYNCB 19 GND 20 GND The 3 ports are designated by the final characters in the names, thus: 0 & 1 Basic asynchronous ports B Full-function a/sycnhronous port Note that RTSB and TEND1 share a pin. Either role is possible, by suitably program- ming the CPU chip. The standard software does not use this pin at all. 4.15 J1 Bus Expansion Pin Assignment -------------- 1A Ground 1B Ground 1C +5V 2A D0 2B A8 2C D1 3A D2 3B A9 3C D3 4A D4 4B A10 4C D5 5A D6 5B A11 5C D7 6A A0 6B A12 6C A1 7A A2 7B A13 7C A3 8A A4 8B A14 8C A5 9A A6 9B RAMCS\ 9C A7 10A Mem-Read\ 10B Mem-Write\ 10C Ground 11A M1\ 11B WAIT\ (input) 11C RD\ 12A IORQ\ 12B ROMCS\ 12C WR\ 13A RST\ (reset) 13B E 13C INT0\ (dedicated interruProgram uuencode; { UUDECODE program modified May 1996 by D R Brooks. To enable it to run with DOS+, which aborts a program that tries to read a non-existent file. This precludes the standard Turbo trick of issuing RESET to see if a file exists: if it does not, the program will die. The test has been removed: it will overwrite existing files, WITH NO WARNING GIVEN.} {Fixed 'off-by-one' error @ EOF in routine ENCODE1 - B.Eiben@MARKET - 16-Aug-86} {Functions to parse the CP/M command tail. D-X Designs Pty Ltd. D R Brroks May 1996 } const cmtail = $80; type argt = string[32]; function paramcount : integer; var ct, ctr : integer; cmd : ^char; last : char; begin ct := 0; ctr := 1; last := ' '; cmd := ptr(cmtail+ctr); while ord(cmd^) <> 0 do begin if ((last = ' ') and (cmd^ <> ' ')) then ct:= ct+1; last := cmd^; ctr := ctr+1; cmd := ptr(cmtail+ctr); end; paramcount := ct; end; function paramstr(i : integer) : argt; var local : argt; last : char; ct, ctr : integer; cmd : ^char; label got, exit; begin ct := 0; ctr:= 1; last := ' '; local := ''; cmd:= ptr(cmtail+ctr); while ord(cmd^) <> 0 do begin if ((last = ' ') and (cmd^ <> ' ')) then begin ct:= ct+1; if ct = i then goto got; end; last := cmd^; ctr:= ctr+1; cmd:= ptr(cmtail+ctr); end; goto exit; got: while ((ord(cmd^) <> 0) and (cmd^ <> ' ')) do begin local := local + cmd^; ctr:= ctr+1; cmd:= ptr(cmtail+ctr); end; exit: paramstr:= local; end; {--- End of new functions ---} CONST header = 'begin'; trailer = 'end'; defaultMode = '644'; defaultExtension = '.uue'; offset = 32; charsPerLine = 60; bytesPerHunk = 3; sixBitMask = $3F; endofinfile : boolean = FALSE; TYPE string80 = string[80]; VAR inf : file; outfile: text; infilename, outfilename, mode: string80; lineLength, numbytes, bytesInLine: integer; line: array [0..59] of char; hunk: array [0..2] of byte; chars: array [0..3] of byte; { procedure debug; var i: integer; procedure writebin(x: byte); var i: integer; begin for i := 1 to 8 do begin write ((x and $80) shr 7); x := x shl 1 end; write (' ') end; begin for i := 0 to 2 do writebin(hunk[i]); writeln; for i := 0 to 3 do writebin(chars[i]); writeln; for i := 0 to 3 do writebin(chars[i] and sixBitMask); writeln end; } {Binary file read added by Ross Alford, ...!mcnc!ecsvax!alford. The original MSDOS versions of uuencode/decode just use read/write on a FILE OF BYTE. CP/M Turbo expects some file info to be stored in the first 4 bytes of files of any type other than TEXT. Getbyte (below) and Putbyte (in UUDECODE) bypass this 'feature' by using blockread and blockwrite. The only global variables either use are 'infilename' and 'inf' or 'outfilename' and 'outf'} function getbyte(var b : byte) : boolean; type bufptr = ^bufrec; bufrec = record next : bufptr; buffer : array[1..128] of byte end; const sectstobuf = 8; {max number of sectors to buffer} sectsread : integer = 0; {constants are essentially statics} bytptr : integer = 129; notopen : boolean = TRUE; j : integer = 0; infsize : integer = 0; listsave : integer = 0; var list,temp,temp2 : bufptr; begin if notopen then begin notopen := FALSE; assign(inf,infilename); {$i-} reset(inf); {$i+} if ioresult <> 0 then begin writeln('File ',infilename,' not found. Aborting'); halt end; infsize := filesize(inf); new(list); list^.next := NIL; listsave := ord(list); sectsread := 0 end; list := ptr(listsave); if bytptr > 128 then begin if list^.next <> NIL then begin temp := list^.next; dispose(list); list := temp; bytptr := 1 end else begin dispose(list); list := NIL; j := 0; while (sectsread NIL then begin b := list^.buffer[bytptr]; bytptr := succ(bytptr); getbyte := TRUE end else begin b := 0; getbyte := FALSE end end; procedure Abort (message: string80); begin {abort} writeln(message); close(inf); close(outfile); halt end; {abort} procedure Init; procedure GetFiles; VAR i: integer; temp: string80; ch: char; begin {GetFiles} if ParamCount < 1 then abort ('No input file specified.'); infilename := ParamStr(1); {$I-} assign (inf, infilename); reset (inf); {$i+} if IOResult > 0 then abort (concat ('Can''t open file ', infilename)); write('Uuencoding file ', infilename); i := pos('.', infilename); if i = 0 then outfilename := infilename else outfilename := copy (infilename, 1, pred(i)); mode := defaultMode; if ParamCount > 1 then for i := 2 to ParamCount do begin temp := Paramstr(i); if temp[1] in ['0'..'9'] then mode := temp else outfilename := temp end; if pos ('.', outfilename) = 0 then outfilename := concat(outfilename, defaultExtension); assign (outfile, outfilename); writeln (' to file ', outfilename, '.'); {--- Code disabled to run with DOS+ ---} {$i-} { reset(outfile); } {$i+} { if IOresult = 0 then begin Write ('Overwrite current ', outfilename, '? [Y/N] '); repeat read (kbd, ch); ch := Upcase(ch) until ch in ['Y', 'N']; writeln (ch); if ch = 'N' then abort(concat (outfilename, ' not overwritten.')) end; close(outfile); } {--- End of disabled code ---} {$i-} rewrite(outfile); {$i+} if ioresult > 0 then abort(concat('Can''t open ', outfilename)); end; {getfiles} begin {Init} GetFiles; bytesInLine := 0; lineLength := 0; numbytes := 0; writeln (outfile, header, ' ', mode, ' ', infilename); end; {init} procedure FlushLine; VAR i: integer; procedure writeout(ch: char); begin {writeout} if ch = ' ' then write(outfile, '`') else write(outfile, ch) end; {writeout} begin {FlushLine} write ('.'); writeout(chr(bytesInLine + offset)); for i := 0 to pred(lineLength) do writeout(line[i]); writeln (outfile); lineLength := 0; bytesInLine := 0 end; {FlushLine} procedure FlushHunk; VAR i: integer; begin {FlushHunk} if lineLength = charsPerLine then FlushLine; chars[0] := hunk[0] shr 2; chars[1] := (hunk[0] shl 4) + (hunk[1] shr 4); chars[2] := (hunk[1] shl 2) + (hunk[2] shr 6); chars[3] := hunk[2] and sixBitMask; {debug;} for i := 0 to 3 do begin line[lineLength] := chr((chars[i] and sixBitMask) + offset); {write(line[linelength]:2);} lineLength := succ(lineLength) end; {writeln;} bytesInLine := bytesInLine + numbytes; numbytes := 0 end; {FlushHunk} procedure encode1; begin {encode1}; if numbytes = bytesperhunk then flushhunk; endofinfile := not (getbyte(hunk[numbytes])); if not endofinfile then numbytes := succ(numbytes) {No succ at EOF -BE} end; {encode1} procedure terminate; begin {terminate} if numbytes > 0 then flushhunk; if lineLength > 0 then begin flushLine; flushLine; end else flushline; writeln (outfile, trailer); close (outfile); close (inf); end; {terminate} begin {uuencode} init; while not endofinfile do encode1; terminate end. {uuencode} terminate} if numbytes > 0 then flushhunk; if lineLength > 0 then begin flushLine; flushLine; end else flushline; writeln (outfile, trailer); close (outfile); MT.MQ(W#)/ID8!C[P&`(^!,,@%L'1[5/B`,7ES5(;T;?M4MH?&RKB``$(``ES M(W(!)``)>+$@&BKB``$, M``D&`(Q#[[5OB``X/S04`/"A(*N(``2$`">U+Y`!Q(W`C(^OM2^8`Q=4. M<%`.U;X@`.(+$@U2KB``$D M``GIW2KB`#[PPW^;\7R'M`"+K`-TJ[0#=;@+=9@-] MM"A([5(P#]UN`-UF`>7=(NL`W>$8XR`*W5X`W58!W>48&TU$W6X`W68!W>7= M&=UU`-UT`=UQ`MUP`]WET2KK`',C7A&2+-`"KR``$$``G= MY<$)VC4=[4O/`.U"`0``(0``VO`-^(V9O$Q,3>^;\7^LB\@`J M[0#EW>&program uudecode; { UUDECODE program modified May 1996 by D R Brooks. To enable it to run with DOS+, which aborts a program that tries to read a non-existent file. This precludes the standard Turbo trick of issuing RESET to see if a file exists: if it does not, the program will die. The test has been removed: it will overwrite existing files, WITH NO WARNING GIVEN.} {Functions to parse the CP/M command tail. D-X Designs Pty Ltd. D R Brooks May 1996 } const cmtail = $80; type argt = string[32]; function paramcount : integer; var ct, ctr : integer; cmd : ^char; last : char; begin ct := 0; ctr := 1; last := ' '; cmd := ptr(cmtail+ctr); while ord(cmd^) <> 0 do begin if ((last = ' ') and (cmd^ <> ' ')) then ct:= ct+1; last := cmd^; ctr := ctr+1; cmd := ptr(cmtail+ctr); end; paramcount := ct; end; function paramstr(i : integer) : argt; var local : argt; last : char; ct, ctr : integer; cmd : ^char; label got, exit; begin ct := 0; ctr:= 1; last := ' '; local := ''; cmd:= ptr(cmtail+ctr); while ord(cmd^) <> 0 do begin if ((last = ' ') and (cmd^ <> ' ')) then begin ct:= ct+1; if ct = i then goto got; end; last := cmd^; ctr:= ctr+1; cmd:= ptr(cmtail+ctr); end; goto exit; got: while ((ord(cmd^) <> 0) and (cmd^ <> ' ')) do begin local := local + cmd^; ctr:= ctr+1; cmd:= ptr(cmtail+ctr); end; exit: paramstr:= local; end; {--- End of new functions ---} CONST defaultSuffix = '.uue'; offset = 32; TYPE string80 = string[80]; VAR infile: text; outf : file; lineNum: integer; line: string80; outfilename : string80; {Binary file read added by Ross Alford, ...!mcnc!ecsvax!alford. The original MSDOS versions of uuencode/decode just use read/write on a FILE OF BYTE. CP/M Turbo expects some file info to be stored in the first 4 bytes of files of any type other than TEXT. Putbyte (below) and Getbyte (in UUENCODE) bypass this 'feature' by using blockread and blockwrite. The only global variables either use are 'infilename' and 'inf' or 'outfilename' and 'outf'} procedure putbyte(b : byte; flush : boolean); type bufptr = ^bufrec; bufrec = record next : bufptr; buffer : array[1..128] of byte end; const sectstobuf = 8; {max number of sectors to buffer} sectswritten : integer = 1; {constants are essentially statics} bytptr : integer = 1; notopen : boolean = TRUE; infsize : integer = 0; listsave : integer = 0; tempsave : integer = 0; var list,temp,temp2 : bufptr; i : integer; begin if flush then begin list := ptr(listsave); temp := list; for i := 1 to sectswritten do begin blockwrite(outf,temp^.buffer,1); temp := temp^.next end; close(outf) end else begin if notopen then begin notopen := FALSE; assign(outf,outfilename); {--- Following code disabled to run with DOS+ ---} {$i-} { reset(outf); } {$i+} { if ioresult = 0 then begin writeln('File ',outfilename,' exists. Cannot overwrite.'); halt end; } {--- End of disabled section ---} {$i-} rewrite(outf); {$i+} if ioresult <> 0 then begin writeln('Cannot open file ',outfilename,' for output.'); halt end; new(list); temp := list; for i := 1 to sectstobuf - 1 do begin new(temp2); temp2^.next := NIL; temp^.next := temp2; temp := temp2 end; listsave := ord(list); tempsave := listsave; end; temp := ptr(tempsave); if bytptr > 128 then begin if temp^.next <> NIL then begin sectswritten := succ(sectswritten); temp := temp^.next; bytptr := 1 end else begin temp := ptr(listsave); for i := 1 to sectstobuf do begin blockwrite(outf,temp^.buffer,1); temp := temp^.next end; temp := ptr(listsave); sectswritten := 1; bytptr := 1 end end; temp^.buffer[bytptr] := b; bytptr := succ(bytptr); tempsave := ord(temp) end end; procedure Abort(message: string80); begin {abort} writeln; if lineNum > 0 then write('Line ', lineNum, ': '); writeln(message); halt end; {Abort} procedure NextLine(var s: string80); begin {NextLine} LineNum := succ(LineNum); write('.'); readln(infile, s) end; {NextLine} procedure Init; procedure GetInFile; VAR infilename: string80; begin {GetInFile} if ParamCount = 0 then abort ('Usage: uudecode '); infilename := ParamStr(1); if pos('.', infilename) = 0 then infilename := concat(infilename, defaultSuffix); assign(infile, infilename); {$i-} reset(infile); {$i+} if IOresult > 0 then abort (concat('Can''t open ', infilename)); writeln ('Decoding ', infilename) end; {GetInFile} procedure GetOutFile; var header, mode : string80; ch: char; procedure ParseHeader; VAR index: integer; Procedure NextWord(var word:string80; var index: integer); begin {nextword} word := ''; while header[index] = ' ' do ͫCopyright (C) 1984 BORLAND IncAM-102 120/Apple CP/MP[1;1k~7#~=% o&ͦoͦܐԩͣ}!!"8~#(}:$= +*!Z!*B!!:(=2!Z: <2!!!:O::O:!*B! !45(!.+/ 0y0( d!kZ!{Z͈͈o&  :(y ͠|( *"x2y( >28!?"9!!>2 :D]SXN]D [ (!e}̈́A8Q0G: x@!\w# (   yV. V!h6# (*(.(!8}(*(̈́w#>?> w#a{ |͒}͛Ɛ'@'7||}>"C"6# ""͐ͩ*B"[R5*"^#V#^#V#N#FO/o&9O/o&9!9(> (G!9 w#E͊w}8uRB0 >R@RR!+ͨ z R!+ͨ z <!+ͨ z <!+ͨ z <!#ͨ z <!+ͨ z T]KB!z> S>))0 = |JJDMgo>jB0 7?= H\<z5+)+<z {0Gɯgo||H}||/g}/o#}o&K[xAJSJDM!b"!6J"DM'ͬͬdͬ ͬ} wͦWͧ _}8(8J`9{T]=o`9y w >uJ u` }>(; xQ }} ˸T}ٕ(0D=C ,= ( [ 0%D , 7 ͏ ?(8u x O - ; 8˸x X ,-xG}; }م 9; .>#n0[ D = - nx P ,-(-˸G,-; }ٕ? 9.>͏ 8u ?= u+-(>O 0u O 8͏ ?x P , 78ƀ8ƀ8ox٨!دoGOW_gɷɷ|لg{ً_zيWyىOxوG|ٔg{ٛ_zٚWyٙOx٘Gxٸyٹzٺ{ٻ|ټx٨ xx(ͼ ?}ٽÏ }ց; <(; 7D = |٤g{٣_z٢Wy١Ox٠GD u J }x>uu}ƀ/ƀo; -J }0W-J W,}l˸ͨ 8 ; ` x( -ͨ 8J -ͨ 8,J }l8;*!` ! >u` ` u--- J ,,,-xGg?+2n*8t z~,->uxua}.; OJ , ; !U >,k- o&0%,` }g; }؉}颋.:}8c~I$I~L*kٷx˸; }0G,͙<},-(-J ! >0 a` o8 Oþ >um.`1pF,t6|!wS<.z}[|%FXc~ur1}Oٯx(<˸ͨ 8; !~Jͨ 0O!><ͨ 8 =  7 <` O ; 7 0 W-J OT0 j oD,:j !I}袋.}8c~I$I~L!>u` ` 77 ` = O nf^VNF!DLT\I!!53!r1!\!> x #-= o˸xO(- }(x>8(C ,C `iM!>u|; |J>| )=|(DMbo˸ͦ88ͦx(0 8> Mx(>-Ͳ{(ay(Ͱͦ \z(>.Ͳ (Ͱ ~ͦ{>EͲ>+|(|Dg>-Ͳ|/ 0:p# ~# +>0w#,-  60#J˸}րogM| .(C = ~> x0w#xG%P %P ZJDM%P = _~65i+~hìx-Sx9?+{Η@}|C C gZJDM0D ,7}o˸  #yO!@9i&   # w# /w# w#!9! E9!!9~(+F͊!"9!(#>2*Ͳ"|>" :( ͆ *6#w*6#6 !\$![ (̈́( #:~CONTRMKBDLSTAUXUSR>2$*#~ Ͷ$*:> >w###6  #6++p>2S-$Ͷ:*6###ww#w$w#w: ##N#F*B> w#w#[s#r>2S$Ͷ$*6 #-Nw#Fwq#p#6#w#w#w* :( ͒: *^ F* < >26"~͟*-w#ww#͟"~ <@*Ͳ!\  <ʮ!\$> >2*|>! * \$\<(!: [1Á\!(f"> 2:!<"F( #~#6e>!["N>!~8>O6*"w (=(&("( :(N 8y(~#x+% (6*#~[*#~ *~(h#"b=  8 J= B== ͯ}8= ͵}/ͭ !*###~-_~(4Q6*>2>*##w:>*##~*#~(E[ ( ( ( !][ ( ( ((w#(6!]~-#8~>7  [>OkͼMs #rkͼpX á[ [ (( #w(q*#~[ (  *##~6͜O$*#~(08ʦ=ʦ==ʩ=ʬò+###~-_q46͡> *:4^q}Ò*|(M|( M6-#͐ͦ[R8 (G> ͒C~͒#*ͦC!h !lTRUEFALSEͦ!9^#(~#(G~͒#> ͒> Ò "F![(#RR0*4#4> RR *4 #4(>>2$*V(/˖:(#~+ x y2!͵( =( X:(R*:(###~-_-͌X> :("͟"*^˞*V˖0 SRѷR8A* N#F#s#r$ 0})jS\*###w* N#FB ͟r+s> !T]>)j)0 0= UR!#U*^#V#N#F#^#V>">!2DM"~x(L* :O(o:" C}=( ?*-N#Fp+qq#p! * F+N+++V+^Bq#p>>> SRѷR* s#r$ s#r"S"! N#FB(^x * 6#[<(H*! Kq#p##K[! *! 4 #4! x *$ *>w""{_!"*nf}(HR0nf" ^VMDnfutqp*s#r*s#r"* 5KB!>u~#fo{_"*R0RnfR0KqputsrNF( ^VNF^V*SutKqp R*R(~w~wnf ut"6# * *!""*NFy(* "*B0Cnf* [R*"*RS[s#r^#VS>O"w2x2!"" @*>2"!"""!\Ͳ*: !~6go(\R*s#r_2x( s x(T]DMR0 -a%}̈́o*!~6o&͠|ͣ}%^C User break1:% I/O% Run-time% error ͒%, PC=[R"͍% Program aborted*1!͍!)Ͳö)!"!"! }2!*"*n&!aEo *&! N*n&! a}oEJ *!"*n&}2*!"!*" *"*"!"d!"b! }2f !gͲ!*b"`*`n&!aE(!*f&! N*`n&! a}oE!*d!"d*d*NE!+!*`n&}2f*b!"b!*b"`ì Ç!*`n&!a*`n&! a}oEʇ!!g *`n&e. !gͲ*b!"b!*b"`+!!g  !Ͳ! î!}2}2*&E"*!"*"!*!5z""!*!gb*^#V"*#!!Sbí#*!&E"!}2!!! =!y5!aEʋ"ŔCannot open file ! !q́ for output.͐b!!ͥ*"!!!R5z""!!ͥ!*s#r**s#r*"*#ï"*"!*!"!*!"*!!͛Eʉ#*^#V!aE5#*!#"!*^#V"!"!É#*!"!!5zw#"!*!gb*^#V"*#F#*!"!"!!"!**!+*&s*!#"!*"!P!}ͲR͐b*~!͛E#ŔLine *~!́: b!} R!q͐b"w*~#"~R!.b!8*wP._bø&!NEo$Usage: uudecode ͮ#!y P!Ͳ!.e.! |!NEʴ$! .uueP!Ͳ!! <b!5!͛E$ Can't open ! ͮ#Ŕ Decoding ! !q͐b!&%"i"kP*kͲ!*i^#Vn&! NEʗ%*i^#V#*is#r*i^#V! m͛Eʔ%Incomplete headerͮ#6%!*i^#Vn&! aE%*k !*i^#Vn&e.P*kͲ*i^#V#*is#r×%! ! e.P!Ͳ!"m!t!m%!!m%!͝EE&Nothing to decode.ͮ#! $! !!5begin \!͝}o}oEʇ&! $L&R͐b!͝Eʴ&Nothing to decode.ͮ#%!"~>$%!- \E&Blank line in fileͮ#!-!n&Q! a!`a}o}2d*d&(*Z#"Z*Z!- m͛ES'Line too short.ͮ#!-*Zn&Q! !`k}oEʚ'Illegal character in line.ͮ#!-*Zn&!`NEʽ'! }2L'!-*Zn&}2L*L&ó(!!5z (">!P*> '! Rs*>#'!M!!P!n&!!P!n&! s!M!!P!n&!!P!n&! s!M!!P!n&!!P!n&s!"X*X!NE('!M*Xn&!͠!*X#"X!"Z!"X '! R"V!*V5z)"T'*T#)!͝E=) Abnormal end.ͮ#! $! m!ͯEn) Abnormal end.ͮ#! !!5endoEʡ) Abnormal end.ͮ#!b!!͠!;$!- $&E)'!- $)) Abnormal end.ͮ#! !!5s*>#'!M!!P!n&!!P!n&! s!M!!P!n&!!P!n&! s!M!!P!n&!!P!n&s!"X*X!NE('!M*Xn&!͠!*X#"X!"Z!"X '! R"V! begin index := succ(index); if index > length(header) then abort ('Incomplete header') end; while header[index] <> ' ' do begin word := concat(word, header[index]); index := succ(index) end end; {NextWord} begin {ParseHeader} header := concat(header, ' '); index := 7; NextWord(mode, index); NextWord(outfilename, index) end; {ParseHeader} begin {GetOutFile} if eof(infile) then abort('Nothing to decode.'); NextLine (header); while not ((copy(header, 1, 6) = 'begin ') or eof(infile)) do NextLine(header); writeln; if eof(infile) then abort('Nothing to decode.'); ParseHeader; end; {GetOutFile} begin {init} lineNum := 0; GetInFile; GetOutFile; end; { init} Function CheckLine: boolean; begin {CheckLine} if line = '' then abort ('Blank line in file'); CheckLine := not (line[1] in [' ', '`']) end; {CheckLine} procedure DecodeLine; VAR lineIndex, byteNum, count, i: integer; chars: array [0..3] of byte; hunk: array [0..2] of byte; { procedure debug; var i: integer; procedure writebin(x: byte); var i: integer; begin for i := 1 to 8 do begin write ((x and $80) shr 7); x := x shl 1 end; write (' ') end; begin writeln; for i := 0 to 3 do writebin(chars[i]); writeln; for i := 0 to 2 do writebin(hunk[i]); writeln end; } function nextch: char; begin {nextch} {} lineIndex := succ(lineIndex); if lineIndex > length(line) then abort('Line too short.'); if not (line[lineindex] in [' '..'`']) then abort('Illegal character in line.'); { write(line[lineindex]:2);} if line[lineindex] = '`' then nextch := ' ' else nextch := line[lineIndex] end; {nextch} procedure DecodeByte; procedure GetNextHunk; VAR i: integer; begin {GetNextHunk} for i := 0 to 3 do chars[i] := ord(nextch) - offset; hunk[0] := (chars[0] shl 2) + (chars[1] shr 4); hunk[1] := (chars[1] shl 4) + (chars[2] shr 2); hunk[2] := (chars[2] shl 6) + chars[3]; byteNum := 0 {; debug } end; {GetNextHunk} begin {DecodeByte} if byteNum = 3 then GetNextHunk; putbyte(hunk[byteNum],FALSE); {writeln(bytenum, ' ', hunk[byteNum]);} byteNum := succ(byteNum) end; {DecodeByte} begin {DecodeLine} lineIndex := 0; byteNum := 3; count := (ord(nextch) - offset); for i := 1 to count do DecodeByte end; {DecodeLine} procedure terminate; var trailer: string80; begin {terminate} if eof(infile) then abort ('Abnormal end.'); NextLine (trailer); if length (trailer) < 3 then abort ('Abnormal end.'); if copy (trailer, 1, 3) <> 'end' then abort ('Abnormal end.'); close (infile); putbyte(26,TRUE) end; begin {uudecode} init; NextLine(line); while CheckLine do begin DecodeLine; NextLine(line) end; terminate end. infile) then abort ('Abnormal end.'); NextLine (trailer); if length (trailer) < 3 then abort ('Abnormal end.'); if copy (trailer, 1, 3) <> 'end' then abort ('Abnormal end.'); close (infile); putbyte(26,TRUE) end; begin {uudecode} init; NextLine(line); while CheckLine do begin DecodeLine; NextLine(ROM on pop af rst diskop ;ROM to do it push af ld a,0c0h out0 (cbar),a ;ROM off pop af pop de ret nc ;Back if OK push de ld c,9 ld de,fatal call bdos ;Error message pop af ;D => A add a,'A' ld e,a ld c,2 call bdos ld de,fatal2 jp exms ;Quit fatal: db 'Fatal error on Drive $' fatal2: db ': Exiting',ascicr,ascilf,'$' ;------------------------------- start: ld sp,lstak ld a,(sdv) ;Source drive ld hl,tdv cp (hl) ;Drives must be different ld de,samedv jr z,fail call testdv ;Check source ld de,baddv jr c,fail ld (hwp),ix ;Save hardware ptr. ld a,(tdv) call testdv ;Check target ld de,baddv jr c,fail push ix pop hl ld bc,(hwp) ;Must be same h'ware type sbc hl,bc ld de,mixed jp z,ok fail: ld c,9 ;Report command errors call bdos ld de,usage exms: ld c,9 ;Final message call bdos ld de,sysbak call dskchg ;Be sure the right disk is in jp exit sysbak: db 'Replace system disk if necessary, & hit Return$' usage: db 'Usage: DISKCOPY ',ascicr,ascilf db 'Source & target may not be the same drive,',ascicr,ascilf db ' but must be the same type',ascicr,ascilf,ascicr,ascilf db ' eg DISKCOPY A: B:',ascicr,ascilf,ascicr,ascilf,'$' mixed: db 'Drives must be the same type',ascicr,ascilf,'$' samedv: db 'Cannot copy to the same drive',ascicr,ascilf,'$' baddv: db 'Absent or invalid drive spec.',ascicr,ascilf,'$' prompt: db 'Load disks & hit Return$' newline: db ascilf,'$' dskchg: ;Request reload disks ld c,9 call bdos ;Output prompt ld hl,tbuff ld (hl),80 ;Buffer length ex de,hl ld c,0ah call bdos ;Wait for reply ld de,newline ld c,9 call bdos ;Final linefeed ret ok: ld c,0dh call bdos ;BDOS: disks are changing! ld de,prompt ;User: change them call dskchg xor a ;Start at track 0 ld (ctrack),a nrd: ld a,(sdv) call spars ld a,2 call dodv ;Read 1 track ld a,(tdv) call spars ld a,3 call dodv ;Then write ld a,(tdv) call spars ld a,4 call dodv ;Verify ld hl,ctrack inc (hl) ;Next track ld a,(hl) srl a ;Cylinder cp (ix+MAXCYL) jr c,nrd jr z,nrd ;More ld de,suxes jp exms ;Done suxes: db 'Completed!',ascicr,ascilf,'$' size equ $-runat hwp: ds 2 ctrack: ds 1 ds 256 ;Safe stack lstak equ $ tbuff equ $ ;Track buffer .dephase end  jr c,nrd jr z,nrd ;More ld de,suxes jp exms ;Done title Dummy USER Program ;=======================================================================; ; ; ; D-X Designs Pty. Ltd. Perth, Western Australia ; ; Project: 112 May, 1996 ; ; ; ; Copyright (C) 1996 David R. Brooks ; ; ; ; This program is free software; you can redistribute it and/or ; ; modify it under the terms of the GNU General Public License ; ; as published by the Free Software Foundation; either version 2 ; ; of the License, or (at your option) any later version. ; ; ; ; This program is distributed in the hope that it will be useful, ; ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; ; GNU General Public License for more details. ; ; ; ; You should have received a copy of the GNU General Public License ; ; along with this program; if not, write to the Free Software ; ; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ; ; ; ;=======================================================================; .comment $ A simple replacement for the USER function (which seems not to exist in CCP+). Just invoke as USER n (0 <= n <= 9) $ cseg .z80 ld hl,80h ;Command tail l1: inc hl ld a,(hl) and a ;End? jp z,0 ;If so, exit cp ' ' jr z,l1 ;Skip blanks sub '0' ;Make it a digit jp c,0 ;Quit if invalid cp 10 jp nc,0 add a,a ;User into top bits add a,a add a,a add a,a ld b,a ld a,(4) ;User bits and 0fh or b ;New user ld (4),a jp 0 ;Done! end  .xlist .sall ; ; Macros for CCP+, DOS+. Intel mnemnonics, z80 opcodes ; Needed with M80, not necessary with SLRMAC. Allows slight ; source revision to assemble with MAC and RMAC also. a equ 7 b equ 0 c equ 1 d equ 2 e equ 3 h equ 4 l equ 5 m equ 6 ; pushix macro db 0ddh,0e5h endm popix macro db 0ddh,0e1h endm pushiy macro db 0fdh,0e5h endm popiy macro db 0fdh,0e1h endm inxix macro db 0ddh,023h endm dcxix macro db 0ddh,02bh endm jrc macro where db 038h db where-$-1 endm jr macro where db 018h db where-$-1 endm jrz macro where db 028h db where-$-1 endm jrnc macro where db 030h db where-$-1 endm jrnz macro where db 020h db where-$-1 endm djnz macro where db 010h db where-$-1 endm bit macro num,reg db 0cbh,040h + num shl 3 + reg endm res macro num,reg db 0cbh,080h + reg + num shl 3 endm bitx macro num,disp db 0ddh,0cbh,disp,046h+num shl 3 endm setx macro num,disp db 0ddh,0cbh,disp,0c6h+num shl 3 endm resx macro num,disp db 0ddh,0cbh,disp,086h+num shl 3 endm bity macro num,disp db 0fdh,0cbh,disp,046h+num shl 3 endm sety macro num,disp db 0fdh,0cbh,disp,0c6h+num shl 3 endm resy macro num,disp db 0fdh,0cbh,disp,086h+num shl 3 endm ldx macro reg,disp db 0ddh mov reg,m db disp endm stx macro reg,disp db 0ddh mov m,reg db disp endm ldy macro reg,disp db 0fdh mov reg,m db disp endm sty macro reg,disp db 0fdh mov m,reg db disp endm andx macro disp db 0ddh ana m db disp endm subx macro disp db 0ddh sub m db disp endm sbcx macro disp db 0ddh sbb m db disp endm cmpx macro disp db 0ddh cmp m db disp endm inrx macro disp db 0ddh inr m db disp endm xorx macro disp db 0ddh xra m db disp endm lbcd macro addr db 0edh,04bh dw addr endm sbcd macro addr db 0edh,043h dw addr endm lded macro addr db 0edh,05bh dw addr endm sded macro addr db 0edh,053h dw addr endm lspd macro addr db 0edh,07bh dw addr endm sspd macro addr db 0edh,073h dw addr endm lixd macro addr db 0ddh lhld addr endm sixd macro addr db 0ddh shld addr endm ldir macro db 0edh,0b0h endm ralr macro reg db 0cbh,010h+reg endm rarr macro reg db 0cbh,018h+reg endm slar macro reg db 0cbh,020h+reg endm srlr macro reg db 0cbh,038h+reg endm dsbc macro reg db 0edh,042h+reg shl 3 endm .list !Y2$OX\T*!4A``#1S4X&RT7*IR0A+^/-"@4&4"'>XLVR!+-L@7-YQ_E(0$`T+-L@7#0R4A MA^'-"@4&4"'>XLVR!2K8X2/1&\/J)"$N`&4N`>4AWN+-"@7-?`CE(0``TXLVR!2&`X^4AWN+-"@7-/!/- M8A_-4A;-@1D)('1O(&9I;&4@(=[BS0H%(0``S7$9(2X`S?(8S9`9S6(?(8#C MSXLT*!(A@./-6Q;-@1D%8F5G:6XA(`#-\A@A MC>+-"@4A``#-<1DA(`#-\A@A+^/-"@4A``#-<1G-D!G-8A_)PWTF_>'A?3)_ MX?WE*G_A)@#E(2``T4A2.+E(0``T1EN)@#E(0(`T4A2.+E(0``T1EN M)@#E(00`T4A1.+E*G7AT1EN)@#E(3\`T7RB9WVC M;^4A(`#1&>OA$CT1O#L"+) M*HGBY2$#`-'-3@;+1+1&>7-H2%][@%O?3*@(2J@(28` M?>X!;\M%RD,H*HGB(R*)XLDJB>+E(0``T(C; Customization equates for DOS+ system ; ; Define memory size base for DOS+ msize equ 63; kbytes RAM available. Not used in DOS+ ; ; Define memory. Max. TPA is ramlow+0100h to base+0800h ramlow equ 0; Available memory starts here base equ (msize-7)*1024; of CCP area - multiple of 256 only ; ; Define path location pathat equ 046H; Location of Path Buffer. 0 disables path ; NOTE: if non-zero coldboot must zero the byte at this address ; to prevent a random path being followed. ; ; Define timer locations and operations timeat equ 040h; Location of time buffer or routine. 0 = none tfunct equ false; true if routine, false if address acctim equ true; true enables file access time stamps ; ; Define BREAK capabilities to interrupt runaway programs. usrbrk equ true; true enables user break on 'brkchr' dciobk equ true; true enables user break on DCIO calls brkchr equ 0; The keyboard input to break (if enabled) ; debug equ false; true for copy executable under an existing ; system. false for normal system e if address acctim equ true; true enables file access time stamps ; ; Define BREAK capabilities to interrupt runaway programs. usrbrk equ true; true enables user break on 'brkchr' dciobk equ true; true enables user break on DCIO calls brkchr equ 0; The keyboard input to break (if enabled) ; debug equ false; true for copy executable under an existing ; system. false forͫCopyright (C) 1984 BORLAND IncAM-102 120/Apple CP/MP[1;1k~7#~=% o&ͦoͦܐԩͣ}!!"8~#(}:$= +*!Z!*B!!:(=2!Z: <2!!!:O::O:!*B! !45(!.+/ 0y0( d!kZ!{Z͈͈o&  :(y ͠|( *"x2y( >28!?"9!!>2 :D]SXN]D [ (!e}̈́A8Q0G: x@!\w# (   yV. V!h6# (*(.(!8}(*(̈́w#>?> w#a{ |͒}͛Ɛ'@'7||}>"C"6# ""͐ͩ*B"[R5*"^#V#^#V#N#FO/o&9O/o&9!9(> (G!9 w#E͊w}8uRB0 >R@RR!+ͨ z R!+ͨ z <!+ͨ z <!+ͨ z <!#ͨ z <!+ͨ z T]KB!z> S>))0 = |JJDMgo>jB0 7?= H\<z5+)+<z {0Gɯgo||H}||/g}/o#}o&K[xAJSJDM!b"!6J"DM'ͬͬdͬ ͬ} wͦWͧ _}8(8J`9{T]=o`9y w >uJ u` }>(; xQ }} ˸T}ٕ(0D=C ,= ( [ 0%D , 7 ͏ ?(8u x O - ; 8˸x X ,-xG}; }م 9; .>#n0[ D = - nx P ,-(-˸G,-; }ٕ? 9.>͏ 8u ?= u+-(>O 0u O 8͏ ?x P , 78ƀ8ƀ8ox٨!دoGOW_gɷɷ|لg{ً_zيWyىOxوG|ٔg{ٛ_zٚWyٙOx٘Gxٸyٹzٺ{ٻ|ټx٨ xx(ͼ ?}ٽÏ }ց; <(; 7D = |٤g{٣_z٢Wy١Ox٠GD u J }x>uu}ƀ/ƀo; -J }0W-J W,}l˸ͨ 8 ; ` x( -ͨ 8J -ͨ 8,J }l8;*!` ! >u` ` u--- J ,,,-xGg?+2n*8t z~,->uxua}.; OJ , ; !U >,k- o&0%,` }g; }؉}颋.:}8c~I$I~L*kٷx˸; }0G,͙<},-(-J ! >0 a` o8 Oþ >um.`1pF,t6|!wS<.z}[|%FXc~ur1}Oٯx(<˸ͨ 8; !~Jͨ 0O!><ͨ 8 =  7 <` O ; 7 0 W-J OT0 j oD,:j !I}袋.}8c~I$I~L!>u` ` 77 ` = O nf^VNF!DLT\I!!53!r1!\!> x #-= o˸xO(- }(x>8(C ,C `iM!>u|; |J>| )=|(DMbo˸ͦ88ͦx(0 8> Mx(>-Ͳ{(ay(Ͱͦ \z(>.Ͳ (Ͱ ~ͦ{>EͲ>+|(|Dg>-Ͳ|/ 0:p# ~# +>0w#,-  60#J˸}րogM| .(C = ~> x0w#xG%P %P ZJDM%P = _~65i+~hìx-Sx9?+{Η@}|C C gZJDM0D ,7}o˸  #yO!@9i&   # w# /w# w#!9! E9!!9~(+F͊!"9!(#>2*Ͳ"|>" :( ͆ *6#w*6#6 !\$![ (̈́( #:~CONTRMKBDLSTAUXUSR>2$*#~ Ͷ$*:> >w###6  #6++p>2S-$Ͷ:*6###ww#w$w#w: ##N#F*B> w#w#[s#r>2S$Ͷ$*6 #-Nw#Fwq#p#6#w#w#w* :( ͒: *^ F* < >26"~͟*-w#ww#͟"~ <@*Ͳ!\  <ʮ!\$> >2*|>! * \$\<(!: [1Á\!(f"> 2:!<"F( #~#6e>!["N>!~8>O6*"w (=(&("( :(N 8y(~#x+% (6*#~[*#~ *~(h#"b=  8 J= B== ͯ}8= ͵}/ͭ !*###~-_~(4Q6*>2>*##w:>*##~*#~(E[ ( ( ( !][ ( ( ((w#(6!]~-#8~>7  [>OkͼMs #rkͼpX á[ [ (( #w(q*#~[ (  *##~6͜O$*#~(08ʦ=ʦ==ʩ=ʬò+###~-_q46͡> *:4^q}Ò*|(M|( M6-#͐ͦ[R8 (G> ͒C~͒#*ͦC!h !lTRUEFALSEͦ!9^#(~#(G~͒#> ͒> Ò "F![(#RR0*4#4> RR *4 #4(>>2$*V(/˖:(#~+ x y2!͵( =( X:(R*:(###~-_-͌X> :("͟"*^˞*V˖0 SRѷR8A* N#F#s#r$ 0})jS\*###w* N#FB ͟r+s> !T]>)j)0 0= UR!#U*^#V#N#F#^#V>">!2DM"~x(L* :O(o:" C}=( ?*-N#Fp+qq#p! * F+N+++V+^Bq#p>>> SRѷR* s#r$ s#r"S"! N#FB(^x * 6#[<(H*! Kq#p##K[! *! 4 #4! x *$ *>w""{_!"*nf}(HR0nf" ^VMDnfutqp*s#r*s#r"* 5KB!>u~#fo{_"*R0RnfR0KqputsrNF( ^VNF^V*SutKqp R*R(~w~wnf ut"6# * *!""*NFy(* "*B0Cnf* [R*"*RS[s#r^#VS>O"w2x2!"" @*>2"!"""!\Ͳ*: !~6go(\R*s#r_2x( s x(T]DMR0 -a%}̈́o*!~6o&͠|ͣ}%^C User break1:% I/O% Run-time% error ͒%, PC=[R"͍% Program aborted*1!͍!(mͲÙ(!"!"! }2!*"*n&!aEo *&! N*n&! a}oEJ *!"*n&}2*!"!*" *"*"!"d!"b! }2f !gͲ!*b"`*`n&!aE(!*f&! N*`n&! a}oE!*d!"d*d*NE!+!*`n&}2f*b!"b!*b"`ì Ç!*`n&!a*`n&! a}oEʇ!!g *`n&e. !gͲ*b!"b!*b"`+!!g  !Ͳ! ï!"A*!&EN"!}2!!0!/ =!0z5!aE%"ŔFile !/ !q́ not found. Aborting͐b!0U"!!;!ͥ!*;s#r*;"!!"!*!";*!!͛E@#*;^#V!aEʛ"*;^#V"9!;!:*9";!"!@#!;!:!";!"!*!*!ͯ*!!ͯ}oE:#!7!ͥ!*7s#r*;!NE#*7";*;"9#*7*9s#r*7"9!0*9!kb*!#"!*!#"!ñ"!"!*;"!*;!aE}#*;*!+n&*As*!#"!!}2CÌ#!*As!}2C*C&P!Ͳ! R!q͐b!0Sb!b%!ͯE#No input file specified.͒#!y P!/Ͳ!0!/ =!0z5!͛EM$Can't open file !/ ͒#ŔUuencoding file !/ !qb!.e.!/ |"*!NEʧ$!/ P!Ͳ$!/ !*+5P!Ͳ644P!Ͳ!͛EL%!5zL%"*y P!Ͳ!!n&Q!0!9kE5%! P!ͲC%! P!Ͳ*#$!.e.! |!NEʂ%! .uueP!Ͳ!! <bŔ to file ! !q!.͐b!5!͛E% Can't open ! ͒##!"!"!"![́begin! ! !q! !/ !q͐b}&}2*&! NEk&![!`b|&![*&bR!.b*! >&!*+5z&"!K*n&>&*#â&![͐b!"!"*!<NE&;&!D!!H!n&! s!D!!H!n&!!H!n&! s!D!!H!n&!!H!n&! s!D!!H!n&!?|g}os!!5z'"u!K*!D*un&!?|g}o! s*#"*u#ð'**"!"*!NE(&!H*͡!}o}2!*!&}oEC(*#"*!͛EW(&*!͛Ep(;&;&s(;&![́end͐b!b!0Sb#*!&}oEʰ((Ü(D(oEst*#"*!͛Eʛ&*!͛Eʛ;&;&e(;&![́end:20E80000000000000000C311E836EB55EB7BEB5AEBC320E84600400070000000000000006F :20E820007932A8F5ED73FEF531FEF5FDE5DDE5D5DDE12118E87EE640C401EBAF32ABF532BA :20E84000ADF5676F22A9F53E26B93801792188E8CD68E83AABF5B7C47BEDDDE1FDE1ED7B42 :20E86000FEF52AA9F57D44C987856F8C95677E23666FE97B217CE8FE06D018EC8CEC79EF39 :20E8800009EC04E90EE909E903F618E9AFEAF7E8FCE800E933E924E929E91EEA42EA2EE9E8 :20E8A0001EEC2BEC85ED2AF1AEF145EC6DEC79EC3FF3A6F378F284EC91EC98EC72EF9FEC8A :20E8C0003BEFA4ECA9ECB1ECB6EC35F396F3C4ECF9EC2EEDD6E821E5E87EB92328903C2827 :20E8E0008D232318F42896F36825F56912F5D273E8D35FE9FF97ECCD15F618254BC312F6A1 :20E900004BC30FF6CD2DF618182A1AE818032A1CE87CB5C472E81809CDD7E9CD0FEAD4B008 :20E92000EAC39BEC3A030018F87B320300C9CDD7EA18EE4B1C281F1C28173A18E8E60820F8 :20E94000041C28161C792A87F5EBC495E9EBC394ECCDF2E918CBCDF2E9C8CDD7E918C2EB76 :20E9600018036F2600010A10AF2917B93802912310F7F57CB5C465E9F1C630C5D5E5CDB014 :20E98000EAE1D1C1C93E0DCD90E93E0A18023E20F5CDD7EAF14FF5DDE5FDE5C5CD0CF6C14F :20E9A000E53A18E80FDC01E9D1FDE1DDE1F1FE7FC82188F534FE20D035FE082805FE0DC0CD :20E9C00036013435C835C92188F57EB7C8CDD3E9CD8EE93E0818BE2186F57E360023B77EA5 :20E9E0003600C02109F6DDE5FDE5CD72E8FDE1DDE1C93A86F5B73EFFC0CD0AEAB7C8CDE378 :20EA0000E93287F5F6FF3286F5C92106F618D7FE0DC8FE0AC8FE09C8FE08C8FE20C91AFEA9 :20EA200024C813CD7BE918F678B7C8C5E5CDC7E9E1E57EFE20DCC7E9E1C12B05C9CD28EA12 :20EA400020FBDDE5E14E230600E5C5CDD7E9C1E1E67FFE05200CE5C5CD85E918EECD28EA4A :20EA600018E7FE0828F7FE7F28F3FE10200A3A18E8EE013218E818D1FE1528C1FE1828BD67 :20EA8000FE0D2823FE0A281F23770479B820092B053E07CD7BE918B17ECDC2EAFE037820DA :20EAA000A83DCCF9EA18A2233600DD70011E0D7BFE09C290E9CD8EE93A88F5E60720F63E3D :20EAC00009C9CD0FEAD27BE9F53E5ECD7BE9F1F5C640CD7BE9F1C9CD0AEAB72804AF3286C4 :20EAE000F5CDF2E9C83A87F5FE133EFFC0CDD7E9CDD7E9FE032802AFC93A18E8E640C818F0 :20EB0000647EE620200479FE06C8C5D5CDF2E9D1C1C83A87F52119E8BEC0D5C5119AEBCDB5 :20EB20001EEACD09ECCD18E9F5CD85E9F1C1D1E65FFE59C8182F1145F5AFCDAAEB1181EB06 :20EB4000CD1EEACD18E9E65FFE52C8FE412816FE4920EAB7C9114EF518241157F53EFFCD70 :20EB6000AAEBCDD7E93AA8F54FDDE5D1ED7BFEF52A1EE8E5210000221EE8C9115CF5AF180F :20EB8000DE0D0A4129626F7274204929676E6F7265205229657472793F240D0A526573753A :20EBA0006D652028792F4E293F244FC5D53AB1F5C641327CF5116FF5CD1EEAD1CD1EEA1145 :20EBC00060F5CD1EEA3AA8F5F5CD62E9F1C1FE0F3837FE183810FE1E280CFE21382BFE25A6 :20EBE0003804FE282023DDE5D6132007B12804CDBDEEE31167F5CD1EEAE10608CD12EC3E2C :20EC00002ECD7BE90603CD12ECCDF2E9C8CDD7E918F7237EE67FFE20C47BE910F5C93A1849 :20EC2000E8E6083E2220743E251870118000CD72EFAF32B1F56F672284F52282F5CD86ED8F :20EC40003AB2F51856CD4EEDDD7E00D63F280DDD7E0EFE3F2804DD360E003E0E3CCD39F047 :20EC60002A91F5ED5B80F5018000EDB0C9DD2AB8F5CD4EEDCD48F018E7CD4EEDCDC2F03ABF :20EC8000BAF51817CD4EEDCDE3F018F32100E818032A84F522A9F5C93AB1F532A9F5C92AF0 :20ECA00097F518F02A82F518EBCD4EEDCDF9F018CE2A93F518DE7B1C2805E61F32AFF53AF7 :20ECC000AFF518D7CD4EED01000051CDFFECCD1BF1C0CDD4EEC8CDBDEEEB210F00CD09ED49 :20ECE0007ADD962179DD9E2278DD9E23D4FFECCD48F0CDD4EE20DF18A2212000CD09EDDDED :20ED00007221DD7122DD7023C9197E210C0019577EE61FCB12CE001FCB1A4F23237E0F0F20 :20ED20000F0FF5E60347F1E6F0814FD004C97B2F5F7A2F572A84F57BA56F7AA4672284F501 :20ED4000EB2A82F57BA56F7AA4672282F5C93EFF32ABF53AB1F532B0F55FDD7E0032ACF55E :20ED6000FE3F2821E61F7B2804DD7E003DCD86ED3AAFF5DD7700C92A0BE8E93AACF5DD7759 :20ED8000003AB0F55F7BE60F47ED5B84F5B72806CB1ACB1B10FA21B1F5CB432802BEC87707 :20EDA000D54F211BF6CDE6E97CB528CB5E235623ED5389F5228BF5110600191191F5010813 :20EDC00000EDB02A93F50E0FEDB0D1CB43C02A84F5CD2FEE2284F5ED5B9EF53E03CB3ACB77 :20EDE0001B3D20F9132A97F5E53600231B7AB320F8E1ED5BA2F57323722A8BF5AF77237709 :20EE000032B2F5CDCDEE3EFFCDEFEECDD4EEC8CDBDEEFEE528F0FE2128ECB7200A237ED655 :20EE20002420043D32B2F5CDB8EFCDDBEE18D7EB2101003AB1F5B72804293D20FC7AB46794 :20EE40007BB56FC92AB5F5CB3CCB1DCB3CCB1D22B3F5EB210000ED4B99F53E11B7ED423097 :20EE600001093FCB13CB123D2804ED6A18EEE52AA6F519444D211EF6CDE6E9C1ED5B89F51C :20EE80002130F6CDE6E9444D2121F6C3E6E9DD4E203A9BF547CB3910FC2FC609473A9DF5B7 :20EEA000DDA60C0F0710FD81DDE5E10E10094F093A9FF5B75E57C8095E23562BC92A91F577 :20EEC0003AB7F5856F8C9567E5FDE17EC921FFFF22B5F5C92AB5F57CA53CC9CDE2EED81390 :20EEE000186A2A8BF5ED5BB5F57B96237A9EC94F2AB5F52322B5F5ED5BA0F5B7ED521928B9 :20EF00000230CA7D0F0F0FE66032B7F5C0C5CD44EECD85EFCD50EFCD7FEFC12AA4F5ED5B4F :20EF2000B3F5B7ED52C8D82A91F50680AF862310FC2A95F5190C200177BEC82A82F5CD2F65 :20EF4000EE2282F5ED5BA0F5132A8BF5732372C92127F6CDE6E9B7C8CD6EEF28F3C9212A0D :20EF6000F6CDE6E9B7C8CD6EEF0E0128F1C92A09E8E9ED5380F5CD7FEF2A80F5C394ECEDA2 :20EF80004B80F51804ED4B91F52124F6C3E6E97BE6073C474FCB3ACB1BCB3ACB1BCB3ACB2A :20EFA0001B2A97F5197E0710FD41C9C5CD8FEFE6FED1B30F10FD77C90E01CDBDEE1110004F :20EFC00019435E233A9FF5B75728030556237AB3280DE5C52A9EF5B7ED52D4ABEFC1E110F0 :20EFE000E1C9CDBDEEFDCB0A7E2005FDCB097EC82A0FE8E92A82F5CD2FEEED52C02A0DE8B0 :20F00000E9626B7AB3280B1BE5D5CD8FEF1F301FD1E1ED4B9EF5B7ED4209300E23D5E5EBDA :20F02000CD8FEF1F3009E1D118D97AB320D5C93717CDB3EFD1E1C93E0F32BBF53EFF32BA0F :20F04000F5DD22B8F5CDCDEEAFCDEFEECDD4EE2869ED5BB8F51AFEE52807D5CDE2EED1307A :20F0600059CDBDEEFE2128E0AF32AEF54F3ABBF547D60F3822FDCB0A7E281C7EB720183222 :20F08000AEF513230C1010CDDBEE3AB5F5E60332A9F5AF32BAF5C91AD63F2F28E279D60D1B :20F0A00028E03C1A2807AEE67F209D18D5C5AE473A9DF52FE61FA0C118EFCDCDEE3EFFC35C :20F0C0009BECCDF4EF3E0CCD39F0CDD4EEC8CDBDEECDEBEF36E50E00CDBAEFCD9BF1CD4836 :20F0E000F018E7CD18F1C0CDD4EEC8CDE2EF01100CCD83F1CD48F018EECD18F1C0CDD4EE08 :20F10000C8DDCB067E2806DD7E20FD770D01000CCD83F1CD48F018E5CDF4EF3E0CCD39F091 :20F120003AAEF5B7C832BAF51893CD4EEDDD360E00CD27F2CDD4EEC8CD47F1DD7E203CC005 :20F14000DD7E0DDD7720C9DD7E0CF5CDBDEEDDE5D1012000EDB0DDCB0EFEDD460CDD4E0FC8 :20F16000F1DD770CB828060E0030020E80DD710F3A18E8E610C8DDCB097E1E08CCE4F4D864 :20F18000C01818CDBDEEEBDDE5E1C5060009C1480600EDB0FDCB06BEFD7700CD44EE0EFFED :20F1A000CD1BEFCD85EF0E01CD5EEFC37FEFCD4EEDDDCB0E7EC0CDF4EFCD37F0CDD4EEC8E6 :20F1C000CDE2EFFDCB0BBE01100009EBDDE5E1093A9FF5B7280105CD05F2EBCD05F2EBC27C :20F1E000BDF02313CB40280323130D0D20E921ECFF19DD7E0CBE380877232323DD7E0F7752 :20F20000CDE2F418967ECB40280323B62BB7200B1A77CB40C823131A7718071A96C0B0C8D1 :20F2200023131A962B1BC9CD37F0CDD4EEC03AACF5B7C02A14E87CB5C83AB0F5477E23B7A7 :20F2400023CABAF0FE2428F13DE60FB828EB2BE5CD86EDE13AAFF5477E23FE242805A8E60B :20F260001F20D6E5CD37F0CDD4EEE128CCCDBDEE3AB1F53C32ACF5C9CD4EEDDD360E00CD16 :20F28000A1F3CDF4EFDD7E00F5DD3600E53E01CD39F0F1DD7700CDD4EEC8AFDD770DDDE53F :20F2A000E1110F00190611772310FCCDBDEEDD7E00771E02CDE4F4CDE2F41E08CDE4F401F9 :20F2C0000020CD83F1DDCB0EFEC9DDCB0E7E202CCDB1F13AA9F53CC8CD0AF338182024CD5A :20F2E00037F0CDD4EE201C3AADF5B72808CD82F2CDD4EE2011DDCB0EFEC3BAF0CD0AF33835 :20F30000F418DCCD47F1AFC39BECDD4E0CDD460ECB7037C00C79E61F4F20070478E63F4785 :20F3200037C83A9DF5A1DD7E0CDD710C4FDD7E0EDD700E47C9CD4EEDAFCD52F4C01803CD0B :20F340004EEDAF32ADF5DD7E20FE80200ECDCAF23AA9F5B72024DD77201805DDBE0F301AE7 :20F36000CD8EEE7AB32813CD7EF3CD56EECD50EF3AA8F5FE14C0DD3420C93E0118892100DD :20F38000003A9BF547CB23CB12CB1510F83A9CF5DDA620B35FC9CD4EED3EFFCD52F4C01830 :20F3A00008DDCB0EBEC9CD4EED3EFF32ADF5CDF4EFDDE5FDE1CDE5EFDD7E20FE80380CCDF4 :20F3C000CAF23AA9F5B720B2DD7720CD8EEE7AB3205AE579B728043DCDA8EECD01F0E17AB2 :20F3E000B33E02CA9BECCDA1F3733A9FF5B7280223720E023AA8F5D6282033D52A91F506EE :20F4000080772310FCCD7EF33A9CF547042FA35F0E02E5D5C5CD56EECD85EFC1C5CD5EEFC0 :20F42000C1D1E10E001C10EACD7FEFD10E00CDA1F3C5CD7EF3CD56EEC1CD5EEFDD7E20DD73 :20F44000BE0F38043CDD770F3AA8F5FE15C0DD3420C932ADF5DD7E2157CBBA17DD7E221789 :20F46000F5E61F4FF117171717E60F47DD7E231E06FE043063070707078047DD7220DD56FE :20F480000ECB72205379DDBE0C200878DDAE0EE63F283ECB7A200FD5C5CDB1F1C1D11E039A :20F4A0003AA9F53C282ECD26F3C5CD37F0C13AA9F53C201A3AADF53C2807CD26F33E0418AD :20F4C0001CCD82F21E053AA9F53C28081803CD47F1AF1809DD360EC0DDCB0EFE7B32A9F598 :20F4E000B7C91E042A91F5016000097ED621C05719D53AB7F50F0F5F0F0F835F19E5CD3474 :20F50000F5D1C1D879FE022803010400F3EDB0FBAFC9D5CD34F5D13EFF3807010400CD0CEA :20F52000F57EC39BECD5D5C1CD37F5D1D8C0EBCD09F512C90100002A16E87CB537C83A1805 :20F54000E8E680C8E94469736B20492F4F244E6F2064726976652446696C6520522F4F2467 :20F560000D0A466E3A20242046696C653A20240D0A444F532B206572726F7220003A202414 :20F580008000000000000000000000000000000000000000000000000000000000000000EB :20F5A00000000000000000000000000000000000000000000000000000000000436F7079B0 :20F5C000726967687420286329203139383620432E422E2046616C636F6E6572202832304C :20F5E0003329203238312D31343338000000000000000000000000000000000000000000F7 :00000001FF S4T'W38`+=TC MU7AM^U2ZY,X"B@(1SX@S9(8$/E#!`7(?LV2&",8]\'1 MV>'1P=G%W2K;`-7-]`\8Q\'1Q+<@'7FW^C(:Q=4.(OQR2+B`,V?&L@8Z`XB*N(`R];+7LC+ MGA@(*N(`RU;(RY;EQ1$P`!GK#AK-!0#!X1$,`!GKS04`M\G!T>U3X@#%Y%R*W/)/I'#(!;5V>'9(0``5%T^$"GK M[6KKV2G9,`0),`$3/2#OR4BX@!^Y@/*\QMXL2A,Q=4.<% M`"KB`!$,`!GK.N<`3\T%`-'!MR@0;SKG`/XB($-]/2@$_@,@/\75*N(`$2T` M&4XC1@-P*W$1V_\9<2-PT<$A@``9ZPL8L"KB`!$)`!E&*TXK*RM6*U[KM^U" MT.MQ(W#)/ID8!C[P&`(^!,,@%L'1[5/B`,7ES5(;T;?M4MH?&RKB``$(``ES M(W(!)``)>+$@&BKB``$, M``D&`(Q#[[5OB``X/S04`/"A(*N(``2$`">U+Y`!Q(W`C(^OM2^8`Q=4. M<%`.U;X@`.(+$@U2KB``$D M``GIW2KB`#[PPW^;\7R'M`"+K`-TJ[0#=;@+=9@-] MM"A([5(P#]UN`-UF`>7=(NL`W>$8XR`*W5X`W58!W>48&TU$W6X`W68!W>7= M&=UU`-UT`=UQ`MUP`]WET2KK`',C7A&2+-`"KR``$$``G= MY<$)VC4=[4O/`.U"`0``(0``VO`-^(V9O$Q,3>^;\7^LB\@`J M[0#EW>&W[ page 90 title 'DOS+ Disk Operating System 2.5' ; ver equ 5; 3 thru 15 allowable ; ; *************************************************************** ; * * ; * D O S + Z80 replacement Disk Operating System Version 2.5 * ; * * ; * Copyright (c) 1986 by * ; * C.B. Falconer, 680 Hartford Tpk., (203) 281-1438 * ; * Hamden, Conn. 06517, USA * ; * all rights reserved * ; *************************************************************** ; ; DOS+ is designed for general usage, and is an improved replacement ; for CPM 2.2. DOS+ requires a Z80 cpu. DOS+ has comprehensive ; provisions for RCPM security, especially when used with CCP+ (the ; supplied CCP), and is virtually impregnable with BYERSX. The system ; allows extension with user installable RSXs (Resident System Exten- ; sions), which are used for print spool/unspoolers, the XJOB utility, ; and others. These RSX's may be dynamically installed and removed, ; for optimum memory usage. DSKDRIVE (the foreign disk driver) and ; BYERSX (the communications system) must be installed for the target ; system before use. See below. ; ; Some of the code is quite tricky, in order to pack the features into ; the available space. The tricks are usually commented. ; ; Revisions: ; 2.5 (86/12/06) cbf. Prevented permanent lockout of random read ; files after a bad seek (can now re-seek, aborted Turbo Pascal). ; If the bios supports it (by returning an appropriate value in ; HL on console output calls) DCIO output calls (function 6) will ; return that value as the current X/Y screen position. GETINFO ; arguments 3, 4 & 5 return List, Punch, and Reader status resp- ; ectively (punch/reader only when customization addresses set). ; A special vector at offset 01Eh now controls the exit point for ; aborts, either from DOS errors, or CTL-C (breaks enabled) from ; the console. If used, the vector resets itself to a warm-boot. ; 2.4 (86/11/05) cbf. Console buffer read simplified. No CTL-R, ; rub equivalent to bs, pt) 14A TEND0\ 14B TEND1\ 14C IEI (daisy-chain int. enable) 15A EXTRQ\ 15B Clock 15C IEO (daisy-chain out) 16A +5V 16B Ground 16C Ground In essence, a subset of the CPU bus is brought out on these pins. The lines are unbuffered, and are not intended to drive long backplane lines. The pin assignments are such that for basic IO functions, only the two outer rows of the connector are used. This enables the cheaper 2-row connectors to be used. The centre row is needed only when a memory page is mapped on to an external board. The intended mating connector is the same half-DIN41612 format, with wire-wrap tails. These are soldered through the expansion board, and are plugged into J1. This technique enables several expansion boards to be stacked on each other, if required. The IEO pin is not connected on the CPU card. It is assigned for use by expansion cards, to enable the daisy-chain to be propagated through a maximum of 2 expansion cards. The method is shown below (X denotes a connector pin): Vcc | 15C Expn. board 1 15C Expn. board 2 15C < X----X-------------------X+---X----X+-------------------X----X > J1 J2 | J1 | J2 < 14C | 14C | 14C IEI +----X----X-------------------X----X----X--------------------X----X | | | | +---------------+ | | +---------------+ X-| IEO Logic IEI |-X+ X+-| IEO Logic IEI |-X +---------------+ +---------------+ Each of the IEI connections to the expansion-board logics should have a pullup resistor. Each expansion board has 2 jumpers, J1 and J2. It may be seen that by setting these jumpers as shown, a daisy-chain of up to two vectored-interrupt expansion boards is possible. The "E" clock output may be used to gate the RD\ and WR\ signals, as described for the IO combination chip. It also provides a convenient clock to control a logic analyser. For this purpose the falling edge is appropriate, and will give exactly one clock (with valid data available) per bus cycle. If a logic analyser is used, bear in mind that CPU accesses to internal chips usually do not generate external bus cycles. ^$#`75%TIV"G8#`T@`E1=&=@IV%\6`!G8&,MYM\A\A\G= MX>'E?28`(SE.@3@<=^LA``!$[4(Y^>OE`^VPZ^$K&T\#[;CK(_G=Z3X0PW'-I@17XG=X>'E?28`(SGY;R8`W>G=X2$``%0Y7DLCY1E>0R/E&>7] MX='A>9`X$#Q/Q=7E&KXH#.'1P2,-(/(A```8#B,3$.S1X<$A```YZ^U2_?G= MZ=WAS:8$3^'-IPE?X7Z3.!L,#2@7D3@2]7Z1=P8`4!E470GQ/$_ML!@"'7/= MZ=WAS:<)3]'M4^8`(0``.1KUAC@#N#@!>!+Q5UZ1."\\;WJ#.`2X?3@(>),X M)I$X(SRW*!_%U2KF`%\=%@!"&0G1U>50&>OA3^VXT<$8!7H\*!E/>)$\NS@! M>[LA`0`Y3^VP(0``5#E>$QGYW>G=X>$MPC`(;"8`W>DA`@!4 M.5X3&7XV`2-WR2$$`%0Y7DLCY1E>0R/E&>7]X='AK[@H!+D@"'BYX=']^=7I M&KX@]B,3!0T8YWRW(`-]M\`^$<-W'\W6"=`^`<-U'\U*"ACUS74/S6`*&.W9 M?;?9/@(HZ,V^"AC@V-Q@@ MS8\+/_4H$#@!V'9W>'+N+!'+"W,.PL(R7VWR-F5V3_-%@OEY>7=.=DN!=D^"`C-CPLX M`\UU"S_+%0@](`S==07=*]DMV2@./@C-3PLPWPC-=0NW&.'-3PLX!,V/"S_A MT<'+>"`%S5`+&)HL()/9Y<5XR_C9J.:`]7=(0``R>'8KV]'3U=?9\FWRQC+&MF*V5=YV8G93WC9B-E'R7S9E-EG>]F;V5]ZV9K95WG9F=E/>-F8 MV4?)>-FXV]F[V"@&S;P+ MR#_)?=F]V<"WR,./"WW6@=H["SS^*-#9Q=7E",T["P@WS40+/2#YV7S9I-EG M>]FCV5]ZV:+95WG9H=E/>-F@V4?#1`K9Q=7EV#X#PG4?S74/?<:`RR_&@&_6%/79Q=7ES;X*S=8Notes on the "first cut" BIOS: This is the first version, to get CP/M up & running on the P112 board. Support is minimal: basic devices, no interrupts or IOBYTE. The Submit file will build BIOS for its correct starting location (F600), with a loader in the 100H bytes below that. The entire .HEX file is to be read in using the Hex Upload feature of the ROM debugger. GO to locn. F500 (from the debugger), and BIOS will be installed on the correct sectors. Assuming the boot sector and CP/M itself are also installed, this is now a bootable disk. Note that the version of DISKOP (the diskette subsystem) used in BIOS has had the FORMAT command deleted. This to save memory: FORMAT is quite large, and never normally used. See the FORMAT subdirectory for formatting diskettes. The DISKOP source file is the same for BIOS and the ROM, save for the switch "incformat" - this is defined in the ROM version, and commented out in the BIOS version. This BIOS is designed so that loading will not corrupt the final 200H bytes of RAM - they are occupied by the disk sector-buffer. This is because these locations are used as workspace by the ROM. Since they are not altered, the act of loading CP/M will not interfere with ROM functionality, and an un- successful load can return to the ROM in safety. (Note that once CP/M is actually initiated, the ROM is no longer accessible). "OVERLOAD" FUNCTIONS Besides the regular BIOS functions, additional "overload" functions are defined. These are called from the cold-boot entry (which CP/M never uses after start-up). The call passes a function code in C. Currently defined are: C=0 Reset disk subsystem This will turn off all drive motors, and issue a reset to the controller hardware. It does NOT flush the CP/M blocking buffers: a call to HOME should be made first, to do this. C=1 Get boot-drive number The number of the drive from which CP/M was booted is returned in A. C=2 Assign drive type Pass D = required rive number E = required drive type (see DRVTYPE.INC for definitions) If D and E are valid, the given drive is assigned to the hardware type specified in E. This affects both the CP/M organsiation tables, and the parameter-block controlling the hardware setup. If E = -1, the assigned type is returned in E. 07 Mar 1997 Added cold-boot code to set the DOS+ "path" variable to null as a startup default. See the DOS+ documentation. MSXBRB`6.N8`MR@-S883(`@JX@`V`"-WRLA7``!)`#ML,D&!B&V$\7E!@/M6]L`$QK^("CZ&LV$!)8H"N'! M$00`&1#CM\DC$Q#KP<$:_CK`?LE#3TX`5%)-`4M"1`),4U0#0558!%534@4^ MKS+F`,WN%,TD%BKB`"-^_@8@'LZY@"W`0\!*`K5#A/-!0#1`1;QQ41'``9ZR%<``$, M`.VPX1$,`!GEZPX7S04`T3S*KA4A7``!)`#ML,D^`<,@%CZO,N8`S1<6P"K? M`'RU/B$@ZRKB`!$,`!D17``!)`#ML!%<``X/S04`/"C/(?T5$8```1H`[;`1 M``$ZY@"W(`3M6P$!,0`!PX$`_]4.<%`!%<``X4S04`T2&``!GKMRCI&&8B MX@#-PA;(/B`RV0#).MD`M\CQR=WAW>7E(;HHU'X4(\WH`1C,%?IX%BO-)0(((`@`'2B]&.\V&LGE*N(`(W[^!N') MS<(6R,U;%_X:R,75Y2KB`"-^MR`.*MT`?OX:*&@C(MT`&&(](!7-$@+U_B`X M!S5L7_B`H%OX):20F50000C307F5000D01042171F5E7CDCDF538F7FE0230F357D52189F5E7CDCDF538F7213A :20F520000B00FD2103F5FE03280B210D00FD2105F5FE0520E14E2346C5DDE121EEFD0100E5 :20F54000F6A7ED4201FF010944CB382100F6D1FD4E00FD5E013E03CF380621A1F5E71809F2 :20F56000F521B6F5E7F1C630DF21CBF5E73E01CFFF456E746572206472697665204E6F2E05 :20F58000205B302E2E335D3A00456E7465722064726976652073697A65205B332F355D3ADE :20F5A000005772697474656E207375636365737366756C6C79005772697465206661696C52 :20F5C00065643A20636F64653D20000D00D7A728FCFE1BCC3800D630D8FE0A3FF521CBF549 :20F5E000CD2000F1C900000000000000000000000000000000000000000000000000000064 :20F60000C367F9C391F6C314F7C31AF7C33EF7C367F7C356F7C349F7C382F7C3A6F7C387C9 :20F62000F7C399F7C3A1F7C3D2F7C3DEF7C361F7C39EF7000000000000000067F975F69B28 :20F64000FAE7F9000000000000000067F975F6BBFA41FA0056F94800040F01AE003F0080FD :20F660000010000100DF022502092AFF50E50F0827020363F94800040F00CA027F00C00005 :20F6800020000100DF022502121BFF6CE50F084F00318000CD8CF720623A66F9F54FCDA68B :20F6A000F7F157060BDD2ADBFA2100E00E001E02DD7E04B83016C53E02DD460405C5D5CDFA :20F6C000C5FC3837D1C1F190470C1E013E02CDC5FC3828AF32E7FA32E5FA3EC33200002120 :20F6E00003F62201003205002106E8220600018000CDA1F73A04004FC300E02103F7CD0A78 :20F70000F7F3760D0A4641494C007EA7C84FCD3EF72318F6ED38E01F9FC9E5C5210000068A :20F7200040CD14F7A7200F2B7CB520F510F3CDBDF8CD14F728FBC1E1ED38E1E67FC9ED38EF :20F74000E0CB5728F979D3E1C9ED389DCB4728F9ED3898CBBFC9ED389DCB6F28F9ED0998E0 :20F76000C9ED388D079FC9CD61F72006062810FE18F5ED098C3E0DED398E00003E0CED391A :20F780008EC9CD8CF70E007932EAFAC93AE7FAB7C83AE8FAB7C4C7F8C97932EBFAC9C5E1A4 :20F7A000C9ED43DFFAC92100007932E9FAFE02D00610ED4C2133F609E5010A00097E23668D :20F7C0006F2B462B4EED43DDFA0111000922DBFAE1C93E0132E1FA3E0232E2FA1853AF3227 :20F7E000E1FA7932E2FAFE0220173E1032E5FA3AE9FA32EFFA3AEAFA32F0FA3AEBFA32F15D :20F80000FA3AE5FAB7282A3D32E5FA2AE9FAED5BEFFAED52201B21F1FA3AEBFABE20123477 :20F820007EFE483806360021F0FA34AF32E4FA1808AF32E5FA3C32E4FAAF32E3FA3AEBFA89 :20F84000CB3FCB3F32E6FA21E7FA7E3601B7281B2AE9FCTL-U equivalent to CTL-X. No reg. save ; Improved error reports. Compatibility flag bit. Setting ; break inhibit also prevents ^C break on call 10 (cons. input) ; and when exiting from CTL-S output pause. R/O files are not ; stamped for access time. Extended calls GETINFO and TDEC. ; 2.3 (86/09/20) cbf. Flags expanded to control time access method. ; Time routine may be a pointer to storage. File timestamps for ; creation, update, and access (incompatible with CPM3). Access ; stamping controlled separately, allows for disk wrt-protect. ; Set/Get time bdos calls changed for compatibility with CPM3 ; Initial link at bdos+11, compatible with dos finder routines. ; Console input modified to make DCIO compatible with other ops. ; SYSTEM files, user 0, are visible to all users (for read). ; Removed path restriction to SYSTEM files. Applies to all read ; Paths only apply to FCBs with a default drive specification. ; User break on any DOS call available. DCIO enabled separately. ; Corrected wrt_rand_zero_fill (40) call. Corrected file system ; so SUBMIT/JOB files work. File alteration now resets the ; $ARC bit (T3) for proper operation of archiving utilities. ; The CPM3 method (via set file attributes) of recording exact ; file length in bytes is available (using F6). Wild cards ; rejected for rename, file size, set attributes. ; ; 2.1/2 Based on Mr. Ten-Brugges original P2DOS release, which made ; this development practical. Uses CCP+ for best results. ; ; New features of DOS+ (over CPM2.2) are: ; - Console status call always checks physical input, so that it is ; always possible to abort a program by the sequence CTL-S CTL-C. ; (assuming the program is making console calls other than DCIO ; and that breaks are enabled in the flag byte). ; - DCIO calls (function 6) are now compatible with all other console ; calls, so that a mixture of functions can be used. The abilities ; are such that direct bios calls are no longer needed. ; - DCIO provides the CPM3 conin_wait call (0fdh), and a "lookahead" ; call (0fch) so programs may examine input chars without using ; them. The lookahead call also returns the console column (as ; viewed by DOS, not the bios) in the h (and b) registers. This may ; not be accurate if tabs or cursor positioning sequences etc. have ; been used. If no char is ready lookahead returns 0 (which, if ; the status call (0feh) has returned true, is really a ready nul). ; The output call (any value less than 0fch in e) returns any value ; returned in hl by the bios. If implemented in the bios, this ; should describe the current row (in h) and column (in l) of the ; cursor, with an offset of 020h added. Applications can now intel- ; ligently control the cursor for windowing, status lines, etc. ; - User break on "brkchr" (except DCIO calls, enabled separately). ; This can abort a runaway program, provided it makes DOS calls. ; - Error routines are more informative, including DOS call number. ; DOS+ ERROR ON D: disk I/O ; bad drive ; file R/O ; R/O ; Fn=XXX (FILE =FILENAME.TYP) ; The option 'FILE =FILENAME.TYP' is displayed only when the DOS ; function uses a filename. After all errors a warm boot is done, ; except bad sectors, which allow retry/ignore/abort options. ; Provisions exist (separate documentation) for applications to ; intercept errors, and to detect where the DOS+ call would have ; returned if successful. ; - Search path is implemented to find files on other drives. The ; files must be specified by their exact name. This takes effect ; only after the file is not found on the current default drv/usr, ; thus there is no point to a $$ entry in the path string. If the ; FCB specifies a drive no path is searched. ; - Any file stored on USER 0 with the $SYS attribute set, is visible ; to all other users for read (but not write or erase). Such files ; can be erased from user 0, but not written into. ; - Automatic date ÊInsert system disk in drive $Enter drive from which to read System Track/s: $Enter drive to be formatted: $Insert disk to format & hit Enter: $Formatting... $Format another? [Y/N] $: and hit Enter $Invalid choice: try again! $Format successful! $ $ЇO!& ^#V6> > >I_uFatal disk error: $Recalibration error $Error from FDC chip $Sectors overrun track $DMA lost data $Operation timed out $Invalid function $Seek error $>&2     A_   : (: `8˯QC0AW* B{(xF: W>~0>FG >         F q˾#yw#w#~w#!. ;: W>* ~( ~( ~(yݾ * F!. : W>y ݾ Formatting... $Verifying... $Writing System Track/s $ * * !2 " : * : W!v \Q2 " o >R b 1q !v FM~M  : ( : Y(y(>>8w(  7I>8Ax-ͼ!x-~ !#~ #~ (&8'>  >7>78(98(8F#~ͯ!v-:w-/w{)#!$9%>9 9!9"{) !!9">9#9$9%{==ݾ0c90>ͯf !@F)T]!)&!'"-I>>ͯͼGͼ9>7x >7B>2w-G8O 9y 89~  = ~ 9>ͯ~ͯ~ˇͯ!v-:w- >ͯzͯ͊8:w-w8>7/ܥد!?o0$~#foɥMSY_{!! !!"->2-!"->2-̀-0( :-= 7x-[-x-72v-9> 9!q+89ͯ£f>91F@ͯ£f>91E@ͯ£Vͯ£>ͯzA(ͯy?ͯ͊n&)))&!'"->91>MͯzA(ͯ~ͯ~ͯ~ͯ>c90~ͯ!xf|g8:o|8888:o|>889Lo`)))) |E`and time stamp is implemented. The creation date ; is set when the function MAKE is executed. The update date and ; time is set as the file is closed (when modified). The access ; date and time is is set whenever the file is opened, UNLESS the ; file is marked R/O or the TACESS flags bit is reset. To enable ; this feature you need to have a real time clock and the correct ; DOS+ driver (or reserved memory area). You must also initialize ; directories for time stamps (every 4th entry = 021h,0,0....0), ; i.e 3,7.. (0 based). INITDIR utility performs this operation. ; - File R/O error message occurs if one of the following file types ; is active and a write is attempted: ; File R/O (T1) (also prevents erase) ; System file (T2) (erasable from base user) ; - Disk sizes up to 65536 * 16K = 1 048 576 K BYTE = 1 G BYTE. ; - File sizes up to 32 * 64 * 16K = 32 768K BYTE = 32 M BYTE. ; - CPM3 function GET TIME (105) is implemented to get the correct ; date and time. Entry DE is address to put time. The date and ; time record has the following layout: ; date: ds 2; date = 1 (Sun 1978-Jan-01) ; date = 65535 (Sun 2157-Jun-05) ; hour: ds 1; hour in BCD ; min: ds 1; minute in BCD ; Functions only if suitable bios function call is installed. ; - CPM3 function SET TIME (104) is implemented to set the correct ; date and time. Entry DE is address new time. The date and time ; layout is as above. System seconds field is zeroed. Functions ; only if suitable bios function call is installed. ; - BDOS function GETINFO (210) returns system info, on (e) value ; e = 0 Returns pointer to Serial # area (BDOS base) ; e = 1 Returns current setting of DMA ; e = 2 Returns 0, Flushes any pending console input ; e = 3 Returns list device status (ready/not ready) ; e = 4 Returns punch " " " ; e = 5 Returns reader " " " ; e = other Reserved for future. Returns 0. ; (operands 4 and 5 function only if suitable connector addresses ; !#~ (0 G:2:#0=`2`($`,,````$.AT. MAR..@(`',#U@,@(`&&``!.```)X:```````````````````````````````` F```````````````````````````````````````````````````` ` end sum -r/size 40540/203 section (from "begin" to "end") sum -r/size 8694/128 entire input file FORMAT COMGUSER UUE have been installed at offsets 01ah and 01ch respectively. Else ; these functions return 0, i.e. device not ready) ; - BDOS function TDEC (211) writes de as unsigned decimal to the ; console, with leading zero suppression. ; - Offset 01eh can be set to a trap address after any abort. ; ; Possible DOS+ Incompatibilities with CPM 2.2 ; - The IX and IY registers are used, and restored to user values ; on function exit. Bios calls from DOS+ are protected. DOS+ ; does not use the alternate register set. Interrupt systems ; that modify and do not restore IX & IY will cause failure. ; - SYS (T2) attribute automatically marks files non-writable. ; - The CTL-S pause mechanism always works. Programs that depend ; on 2 char input buffering (DOS buffer and hardware) may fail. ; - Console output chars 0fch and 0fdh are now input on function 6. ; Compatibility mode inhibits this feature. ; - Buffered console input (function 10) treats DEL/RUBOUT as BS, ; and does not implement the ^R repeat line operation. Will not ; end a line when full, refuses chars until entered. Marks ; line end with a 0 byte. Thus max length 1 less than original. ; - Version returned is 2x, where x is DOS+ revision (4 up). Values ; in hex. This allows discrimination against CPM2.2, and avoids ; confusion with CPM3. The compatibility bit forces 2.2 value. ; Note that call #210 with e = 0 will always return a non-zero ; value, so that DOS+ can be detected in compatibility mode. ; - Files written with more than 65536 records will not be legible ; to CPM2.2 systems (but will be to CPM3 systems). ; - Time stamp directory entries may appear as peculiar file names ; on user 33 to some utilities. CPM2 and 3 will not access them. ; - The date/time file stamp format is INCOMPATIBLE with CPM3. ; dates will be garbage data if read there (and vice-versa). ; This is caused by maintenance of 3 (not 2) dates with DOS+ ; NOTE: The following do not agree with CPM2.2, but DO agree with ; Digital Researchs CPM 2.2 documentation ; - Console status call returns 0ffh for ready, rather than 01 ; - SYS files on user area 0 are visible to all users ; ; Added features can be enabled/disabled by the following data: ; - Enable PATH by putting address of PATH in offset 14H. If this ; value is 0 no path is used. Suggested value 046H. ; NOTE power-on cold-boot should clear the PATH string (0 at Path^) ; - Enable DOS+ time and date stamping with a suitable (non-zero) ; data address at offset 16H. Suggested value 040h (5 bytes used). ; - Enable other features with the flag byte at offset 18h: ; MSB 76543210 LSB ; ^^^^^ ^---- 1 = Echo console to list. ^P complements ; ||||| (this locn allows applications to control) ; ||||^------- 1 = compatibility bit. Causes verno call to ; |||| return 2.2. Disables fc/fd operand on DCIO ; |||^-------- 1 = do file access time stamp (timeat <> 0) ; ||| (disable caters to wrt-protected disks) ; ||^--------- 1 = enable break on DCIO (if following bit) ; |^---------- 1 = enable user break, 0 = disable (see 19h) ; | When disabled ^C will not abort either. ; ^----------- 0 = time address is location of time array ; 1 = time address is location of routine ; (when non-0 address in offset 16h only) ; (value x10x1000b for maximum CPM2 compatibility) ; - If user breaks enabled, the char at offset 19h will break. ; - CCP+ can access wheel byte, suggested location 045h. This allows ; path/wheel to be initialized by "lxi h,0ffh; shld 45" in bios. ; ; ------------- ; ; NOTE - All features can be controlled in the file DOS.LIB ; ; Change with assembler. Allows for SLRMAC or M80. The M80 include ; statement must be changed to MACLIB for RMAC, with other changes. ; This allows for the widest range of assemblers, even ASM with manual ; macro expansion by editing. ; ; Following must be upper case for M80. ; SLRMAC can use "maclib z80" and/or dispense with Z80.LIB file INCLUDE Z80.LIB ; ; SLRMAC v1.0 bug fix - mvix/mviy operands interchanged mvix macro disp,value db 0ddh,036h,disp,value endm ; true equ -1 false equ not true empty equ 0e5h; mark for vacant directory entries tmstamp equ 021h; mark for time-stamp directory entries ; ; Following must be upper case for M80. ; Specifies base/path/ramlow/timesystem/debug INCLUDE DOS.LIB ; ; Ascii control char. definitions etx equ 03h; key to generate warm boot enq equ 05h; break line bel equ 07h; bell bs equ 08h; backspace tab equ 09h; tab lf equ 0ah; line feed cr equ 0dh; carriage return dle equ 10h; set/reset print flag dc3 equ 13h; pause console output nak equ 15h; delete line can equ 18h; delete line (backspaces) rubout equ 7fh; delete last char ; ; FCB description. Like CPM3, we reserve bits f7 and f8 for internal ; use. Caller should initialize to off, and never alter them. f.usr equ 0; usage in directory. 5 bits f.drv equ f.usr; alternate use for field in FCB f.name equ 1; 8 char field f.ifc6 equ 6; hi bit, sfattr interface control f.type equ 9; 3 char field f.ro equ f.type; hi bit f.sys equ 10; " f.arc equ 11; " f.exlo equ 12; 5 low bits f.s1 equ 13 f.exhi equ 14; 6 low bits f.clean equ f.exhi; hi bit f.rc equ 15; Records in last FCB extent f.dm equ 16; 16 bytes/8 words f.next equ 32; next recd, FCB only f.rrno equ 33; 3 bytes, FCB only ; ; Flag byte bit definitions fb.tcal equ 80h; Timer is routine, not data area fb.ubrk equ 40h; Implement console break fb.bcio equ 20h; also on DCIO calls fb.tacc equ 10h; Do file access time stamps fb.comp equ 08h; Compatibility bit fb.lflg equ 01h; Echo console output to lister ; ; bit settings via DOS.LIB tcal equ tfunct AND fb.tcal ubrk equ usrbrk AND fb.ubrk bcio equ dciobk AND fb.bcio tacc equ acctim AND fb.tacc ; ; A standard CPM 2.2 Bios arrangement ; This linkage allows debugging using pre-existing bios. ;extrn boot; 0 boot none none extrn wboot; 1 wbootP/VCAEWM!6# x!"8!U"2!9"1!$ r ͮ :]/ ̈́:5 5ڊO; Ignoring: > x xǘ x2y2.0}¦ !~=ʷ#©:5#͞ :5>2#L; No destination file specified. tK͞t:57::<!L#r L>Ͳt ,**2͗ s!͗ i_`i"|Š; Out of memory. t:#G>pͲt:q!>?!q͂ ; Wildcards not allowed. t!p: t; File is open. Use ^Z to quit. *2ͧ p*2' A; Disk is full. Deleting file. Z tʹ t|  > { :2!!U; COPYING: L r !Kp!K:; to !p::)´:Vʴ; Archived@>PPҾ !Jo ͞ ; Can't copy to same drive/user.t!q ͞ ; Duplicate!@!Kp͈(:4t@:%ʽ*"; - Verifying p t**͗ ʢ; failed! :!”; Please check your disk. t=2!pZ T; OK :2!:'ʽ* :/; - Erasing !K:u Z !q r :: :y2yL!q ~w怶w# :)::V2V:{2{Kf pf *6+"6|t   k k; User abort :G:O͕ *ɯ25!~#~#=ʑ ʑ+ͧ‘:5<25~!=##õ6#:5O!8 ~#fos#rG:5=25Ox<G~#~x<=<:5Ox:L7x#~7$gʊY~ ; - unrecognized option PM—>2%Ù/PͲ < no file < bad drive/user spec in N< invalid characters in :G:O>:͂ @=J:J~AG#a 1O#a 1W#yOO~:J#:Jyx<7~~#.ʎ*ʃ!ڳV~#.ʓ!ڳt>?…tŽ~~#.*ʷ!ڳ•>?·ó7 > { ! { !͂ ,;:='"  #>!>.>!!N ?+~ 2#=!F+NY##O>. ~# OxA y/ o0  o Ox y0 >: ɯ2"22w ұ!< can't open source *DM*2K :"/2"DM*2' Z !< Disk full. Copy deleted.:"ʶʹ !< can't close destinationu !xI ͋ ͘ I # . u !xu ͋ ͦ u :%P # R u ɯ22 ͨ *  >2! ~~w >2 :- ; R/O! f ' :+' :-' ; Exists! Z F !< directory is fullu u _  OGXY !͋ u =Շo&ͨ #*2 r "2*6#"6!͗ <=  # r !"w < < verify file open error!͋ ͦ N P B ~b #U *O! ~W$^"!!yg)җ >g>!o‹ r$s%#  ͪ ~ e e ʆ  B ® x6#= BKͪ i @ ` @ ~ ñ _  >^ @ yO# {B @ . F{@ @ > B @ > w#xM *͗ >> >k î y+~ y ͢ ͢ x͏ î > B > B ;  ʭ  ~# _; Delete? i Y7;  |$ }$ -  6 0 ; ERROR:  | >247>9~0a{_~#r { O~#ʔ ‡ x{_zW~O#ž **͗ "; PPIP, Version 1.7 USAGE: PPIP [DU:][ [DU:][]X; PPIP [[DU:]=][DU:]Xt; [ : ; options] $!; Options (default):; : ʿ; (ON) - ; (OFF) - Ðdo CRC Verificationprint the CRC valuecopy only unarchived filesdelete (Erase) R/W files without askingdelete (Wipe) R/W and R/O files without askingmove files - deletes source after copyCON:PPIP v1.7 7 SEP 87 Copyright (C) David Jewett,III - 1986 " " extrn const; 2 console status " A=0FFH ready ; =0 not ready extrn conin; 3 console input " A=console char extrn conout; 4 console output C=console char option xy posn extrn list; 5 list output C=list char " extrn punch; 6 punch output C=punch char " extrn reader; 7 reader input none A=reader char ;extrn home; 8 home disk " option sysadr. extrn seldsk; 9 select disk C=drv # (0..15) HL=^Disk table extrn settrk; 10 select track BC=track # none extrn setsec; 11 select sector BC=sector # " extrn setdma; 12 set DMA address BC=DMA address " extrn read; 13 read 128 bytes none A = 0 no error ; A <> 0 error extrn write; 14 write 128 bytes; C=0 write data A = 0 no error ; C=1 wrt dir. A <> 0 error ; C=2 wrt unalloc extrn listst; 15 list status none A = 0ffh ready ; A = 0 not ready extrn sectrn; 16 sector translate BC = sect HL = sector # ; DE = ^table ; (from select) ; XX time BC =0 get pointer only HL=pointer to time array ; BC <> 0 allows hard- HL+0^ date LSB days since ; ware to be updated HL+1^ date MSB (1=1978/1/1) ; if a routine call. HL+2^ hour (bcd) ; ignored if timead HL+3^ minute (bcd) ; is purely an address. HL+4^ seconds (bcd) ; BC^ time to set. (no secs) ; CARRY clear, NZ on exit. ; ; Start of BDOS module serial: ds 6,0; Serial number not implemented ; ; Linkage for function calls start: jmp entry; To location 11, for DOSfinders ; ; Error trap vector. Programs can alter error traps here stbdsc: dw badsec; Bad sector stsel: dw selerr; Select error stro: dw rdonly; Drive read only sfilro: dw filro; File read only ; ; Connector so DOSfinder routines work. The jump at location ; bdos+6 must be to bdos+11h. The above error vector must not ; be moved or programs that trap BDOS errors will fail. entry: jmp dos ; ; ------------------------- ; The following area is patchable. DOS.LIB sets initial values ; ; Location of external path for open file command path: dw pathat ; ; Time address. 0 disables all time operations. Array or routine timead: dw timeat; Routine addr. for time/date stamps ; ; Flags for specials flags: db tcal+ubrk+bcio+tacc brkch: db brkchr; char. for user breaks ; " " ; If non-zero, address of bios routines. (a): 0ffh=ready, 0=not ready rdrsta: dw 0; rdr status routine ptr punsta: dw 0; pun status routine ptr ; ; This specifies control transfer after fatal errors or CTL-C exits ; when breaks are enabled. CAUTION: must point to a valid connector. ; Automatically reset to ramlow if used. abtrap: dw ramlow; destination on aborts ; ; ------------------------- ; ; Entry point DOS+ function calls dos: mov a,c; function number sta funct sspd spsave; Save user SP lxi sp,stack; Switch stacks pushiy pushix; Save push d; Save parameter popix; in IX lxi h,flags mov a,m ani fb.ubrk cnz userbk; User break enabled, check it xra a sta drvflg; Reset drive select done flag sta rdwr; and read/write flag mov h,a mov l,a; lxi h,0 shld fvalue; Clear exit value (default) mvi a,maxcmd-1 cmp c jrc dos1; above command table, use last entry mov a,c; else use specified dos1: lxi h,ctable call jinx; execute ; " " ; DOS+ exit routine lda drvflg; test drive select used flag ora a cnz drvfix; restore entry drive if modified popix popiy lspd spsave; restore saved on entry lhld fvalue; Get exit code mov a,l; Copy exit code to ba mov b,h ret ; ; Jump indexed to (hl + 2 * a). Max entry a = 127 ; a,f,h,l jinx: add a; * 2, words add l mov l,a adc h sub l mov h,a; hl := hl+a ; " " ; indirect transfer to hl^ ; a,f,h,l jind: mov a,m inx h mov h,m mov l,a; hl := (hl) xpchl: pchl; implements "call hl" ; ; Function 210, Get info, e specifies details. ; This can perform anything that does not require input parameters. getinf: mov a,e lxi h,inftbl cpi maxinf rnc jr jinx ; inftbl: dw @serial; 0 pointer to serial dos+/serial # area dw rtndma; 1 current dma setting dw cflush; 2 flush console input buffers dw lsta; 3 list device status (ready/not ready) dw psta; 4 punch device status " " dw rsta; 5 reader device status " " maxinf equ ($-inftbl) /2 ; ; Main Command table. Covers the contiguous opcodes. ; DOS+ returns values in HL, with BA a copy. Thus 8 bit values are ; also returned in A. Function 0 ignores the pointer at 1, and can ; be used to force system reloading if bios unaltered. ctable: dw wboot; warm boot dw cin; console input dw coute; console output dw rin; reader input dw pout; punch output dw lout; list output dw dcio; direct console I/O dw giobyt; get I/O byte dw siobyt; set I/O byte dw mesg; print string dw rdbuf; read console buffer dw cstat; get console status dw cmnd12; get CPM version. num dw cmnd13; reset disk system dw cmnd14; select disk dw cmnd15; open file dw cmnd16; close file dw cmnd17; search for first dw cmnd18; search for next dw cmnd19; delete file dw cmnd20; read sequential dw cmnd21; write sequential dw cmnd22; make file dw cmnd23; rename file dw cmnd24; Get login vector dw cmnd25; Get current disk dw cmnd26; Set DMA address dw cmnd27; get address allocation vector dw cmnd28; write protect disk dw cmnd29; Get R/O vector dw cmnd30; Set file attributes dw cmnd31; Get addr. disk parameter header (DPH) dw cmnd32; Get/set user code dw cmnd33; Read random dw cmnd34; Write random dw cmnd35; Compute file size dw cmnd36; Set random recordd dw cmnd37; reset individual drive(s) dw other; last entry, check extensions maxcmd equ (($-ctable)/2); Number of valid DOS commands ; ; Check function in auxiliary table other: lxi h,auxtbl ; " " ; Search table hl^ up for index c. last (default) entry is 0ffh ; execute result. ; a,f,h,l + executed code tblchk: mov a,m; get id byte cmp c inx h; point to operand field jrz jind; found, hl points to exec adr. inr a jrz jind; last entry, use as default inx h inx h; skip operand jr tblchk; go check next ; ; Define table entry format dt macro op,adr db op dw adr endm ; ; Auxiliary table. 1st entry found fastest. 0ffh terminator ; This structure allows for unused opcodes. auxtbl: dt 40, cmnd40; write random w/zero fill dt 104, settim; set time dt 105, gettim; get time dt 210, getinf; return data, e specifies what dt 211, cmd211; write de in decimal, zero suppress dt 0ffh, dummy; end marker, null operation ; ; *********************** ; * * ; * Device I/O routines * ; * * ; *********************** ; ; Read reader. BDOS function 3 rin: call reader jr exit; return rdr char. to caller ; ; Write punch. BDOS function 4 pout: mov c,e jmp punch; Char. to punch device ; ; Write list. BDOS function 5 lout: mov c,e ; " " ; list from console echo mechanism listx: jmp list; Char. to list device ; ; list status lsta: call listst jr exit ; ; reader status rsta: lhld rdrsta jr biosx ; ; punch status psta: lhld punsta ; " " ; Execute routine hl^ if hl non zero, else return 0 biosx: mov a,h ora l cnz xpchl; non-zero, call it jr exit ; ; Read Char. from console and echo if in [cr, lf, tab, bs, >= blank] ; BDOS function 1 cin: call getch; get it call tstch cnc couta; echo cr, lf, tab, bs, >= blank exit: jmp rtnbyt ; ; Get I/O status byte. BDOS function 7 giobyt: lda ramlow+3 jr exit; return it to caller ; ; Set I/O status byte. BDOS function 8 siobyt: mov a,e sta ramlow+3; Save new value in RAM ret ; ; Test console status. BDOS function 11 cstat: call qwait; Get console status, check pause jr exit; and return it ; ; Direct console input/output. BDOS function 6 ; input E : 0ffh - get char or 0 if not ready ; 0feh - get console status ; 0fdh - console input, wait for it (CPM3 usage) ; 0fch - get buffered char, without flushing ; (so still available for console input) ; (DOS+ also sets b=h=column count) ; This now co-operates with the 1 char input buffering, and thus can ; be used intermixed with other console functions. Output here cannot ; be paused with CTL-S. Output via other functions will flush any ; incoming CTL-S. This status call (argument = 0feh) will not pause ; on incoming CTL-S. Note that a nul input can be detected by calling ; status (argument 0feh), and if ready then calling input (arg 0ffh) ; or input-wait (arg 0fdh) or look-ahead (arg 0fch). This allows ; discrimination between no_char ready and nul ready. However, ; console output may not track columns correctly. Compatibility bit ; disables arguments 0fch and 0fdh (become output). ; IF the bios co-operates, console output calls return an indicator ; of the x/y screen position. H describes row, L describes column. dcio: mov c,e; Possible output char. inr e jrz dcio5; 0ffh, do input inr e jrz dcio4; 0feh, get status lda flags ani fb.comp; compatibility bit jrnz dcio3; inhibits extra operations over 2.2 inr e jrz dcio6; 0fdh, console input, wait inr e dcio3: mov a,c lhld lastch; assumes status called before xchg cnz coraw; <> 0fch, output char. xchg jmp rtnwd; h is column value dcio4: call csta; Get console status jr exit; and return it to caller dcio5: call csta; Get console status rz; Exit if no char. available dcio6: call getch; else get char. jr exit; and return it to caller ; ; Call #211, write in decimal to console cmd211: xchg jr tdzs ; ; output (a) in decimal to console, leading zero suppress. Recursive ; a,f,b,c,d,e,h,l tadzs: mov l,a mvi h,0 ; " " ; output (hl) in decimal to console, leading zero suppress. Recursive ; a,f,b,c,d,e,h,l tdzs: lxi b,0100ah; c=divisor=10, b=iter cnt=16 xra a; clear tdzs1: dad h; (hl) := (hl)/10; rdr to (a) ral; shift off into (a) cmp c; test jrc tdzs2; no bit sub c; bit = 1 inx h tdzs2: djnz tdzs1; not done push psw; save output digit mov a,h ora l cnz tdzs; not left digit, recursive pop psw; last unlisted digit adi '0' ; " " ; couta, preserving bcdehl co: push b push d push h call couta pop h pop d pop b ret ; ; cr/lf to console ; a,f,b,c,d,e,h,l crlf: mvi a,cr call cout mvi a,lf jr cout ; ; Blank to console ; a,f,b,c,d,e,h,l blk: mvi a,' ' ; " " ; Console output A, no tab expansion. Preserve A. Check for pause ; However a tab records appropriate column advance here. ; Column confusion results if hi bit is set in char. or if ; cursor movement sequences are used. ; b,c,d,e,h,l cout: push psw; Save non tab call qwait; Check for user pause pop psw; Get char back ; " " ; Raw console output, attempting to track output column, and ; implementing any list echo in effect. Guard against evil bioses. ; If the bios performs, de returns indicating the current x/y posn. ; b,c,d,e,h,l coraw: mov c,a push psw pushix pushiy push b call conout; output it pop b; get char back to ck push h; save bios return (x/y posn) lda flags; Get printer echo flag rrc; test fb.lflg cc listx; bit set, output char to printer pop d; may be x/y posn popiy popix pop psw; restore char. ; " " ; Count chars. in line ; f,h,l countc: cpi rubout rz; non-print, no column update lxi h,column; Pointer inr m; advance cpi ' ' rnc; printing char, exit dcr m; control, cancel column advance cpi bs jrz count3; bs, decrement column cpi cr rnz; Not tab char, ignore for count mvi m,1; will become 0, for cr count3: inr m dcr m rz; don't reduce past zero dcr m; reduce, for bs ret ; ; Backup if column > 0. Called only from delch, thus rdbuf ; a,f,b,c,d,e,h,l (because bios) bakup: lxi h,column mov a,m ora a rz; at lh column, absorb call bakup1; write backspace (in c) call blk; write space bakup1: mvi a,bs jr coraw ; ; Get char. from console, using look ahead buffer. Wait for it ; a,f,b,c,d,e,h,l (because bios) getch: lxi h,bufull mov a,m; flag mvi m,0; Reset buffer full flag inx h; point to lastch at bufull+1 ora a mov a,m; buffer contents (lastch) mvi m,0; and reset it to nul rnz; lastch was valid ; " " ; conin protected against evil bioses ; a,f,b,c,d,e,h,l (because bios) cinx: lxi h,conin ; " " ; Guard against a bios that clobbers ix/iy (e.g. Osborne 1). ; Call (hl)^, saving and restoring ix and iy ; a,f,b,c,d,e,h,l (because bios) xbios: pushix pushiy call xpchl popiy popix ret ; ; Get console status to a and z flag, using look ahead buffer. ; When char. ready lastch buffer is loaded. ; a,f,b,c,d,e,h,l (because bios) csta: lda bufull ora a mvi a,0ffh rnz; buffer is non-empty call cstax; Physical console status ora a rz; nothing read, return 0 call cinx sta lastch; get char and save ori 0ffh; return true sta bufull; mark char in buffer ret ; ; protected const ; a,f,b,c,d,e,h,l (because bios) cstax: lxi h,const jr xbios ; ; Test character ; reset carry : cr, lf, tab, bs, OR >= space ; set carry : all others ; f tstch: cpi cr rz cpi lf rz cpi tab rz cpi bs rz cpi ' '; test >= space ret ; ; Output message. BDOS function 9 ; a,f,d,e mesg: ldax d cpi '$' rz; End of string inx d; point to next char. call co; output jr mesg; more ; ; Delete char. Called only from rdbuf ; Entry : HL = ^ last char in buffer ; B = Char. counter ; Exit : hl decremented, b decremented, z flag on b ; a,f,b,d,e,h,l delch: mov a,b ora a rz; empty, nothing to do push b push h call bakup pop h push h mov a,m cpi ' ' cc bakup; control, wipe out 2 pos'ns pop h pop b dcx h dcr b; Char counter ret ; ; Read buffer IX^. BDOS function 10 ENTRY below rdbuf0: call delch; Delete last char in line jrnz rdbuf0; more to remove ; " " rdbuf: pushix; buffer start addr. << ENTRY here pop h; to HL mov c,m; Max. line length inx h; Adv. to actual line lgh position mvi b,0; Clear line length counter rdbuf1: push h push b rdbuf2: call getch pop b pop h ani 07fh; Mask char cpi enq jrnz rdbuf5; Not CTL-E push h; SAVE push b call crlf; newln; Move cursor to next line jr rdbuf2; and get next char rdbuf4: call delch; Delete char jr rdbuf1; Get next char. rdbuf5: cpi bs jrz rdbuf4; backspace cpi rubout jrz rdbuf4; rubout cpi dle jrnz rdbuf6; not CTL-P (print enable/disable) lda flags; Complement print flag xri fb.lflg sta flags; flip fb.lflg jr rdbuf1; and get next char rdbuf6: cpi nak jrz rdbuf0; CTL-U, delete line cpi can jrz rdbuf0; CTL-X, delete line cpi cr jrz rdbufx; cr, exit cpi lf jrz rdbufx; lf, exit inx h; incr. pointer mov m,a; and save char. inr b; incr. line counter mov a,c cmp b jrnz rdbuf8 dcx h; line end, refuse char dcr b mvi a,bel call co jr rdbuf1 rdbuf8: mov a,m call outch; Echo char. cpi etx mov a,b; Get line count jrnz rdbuf1; Not CTL-C dcr a; If 1st char in line then cz abtchk; abort if breaks enabled jr rdbuf1; else just another char. rdbufx: inx h mvi m,0; mark line end for user stx b,+1; save line counter mvi e,cr; force carriage return ; " " ; Write console. BDOS function 2 coute: mov a,e; Char ; " " ; Write char A to console, expand tabs. Preserves A couta: cpi tab jnz cout; not tab couta1: call blk; expand tab to spaces, 1 or more lda column ani 7 jrnz couta1; Not done, repeat mvi a,tab; return tab ret ; ; Output char (Control char displays ^CHAR) outch: call tstch jnc co; cr,lf,tab,bs or >= space push psw mvi a,'^' call co; write '^' pop psw push psw adi 'A'-1; add offset call co; output it pop psw; restore chanr. ret ; ; ******************************* ; * * ; * ERROR ROUTINES etc. * ; * * ; ******************************* ; ; Check for user pause (CTL-S). Always uses key depression. ; Returns current console status in a and z flag qwait: call cstax; bios ora a jrz qwait1; No key, check buffer xra a sta bufull; flush buffer on physical input qwait1: call csta rz; no input lda lastch; what was it cpi dc3 mvi a,0ffh; to return status=ready rnz; not pause call getch; flush the DC3 call getch; and get the next input cpi etx jrz abtchk; reboot on CTL-C xra a; set status = not ready ret ; ; Check breaks enabled, and abort if so. Else return 0 and z flag ; a,f abtchk: lda flags ani fb.ubrk rz; breaks disabled jr abort ; ; Check for user break. At entry hl points to flags ; a,f,h,l userbk: mov a,m ani fb.bcio jrnz ubk1; enabled for DCIO mov a,c cpi 6 rz; Not for DCIO call ubk1: push b push d call csta pop d pop b rz; no input, no break lda lastch; look ahead lxi h,brkch cmp m rnz ; " " ; Check operator for abort. ; a,f,h,l qabort: push d push b lxi d,brkmsg call mesg call cflush; purge char and input buffer call cin; Get user response push psw call crlf pop psw pop b pop d ani 05fh; upshift any 'y' cpi 'Y' rz; ignore non Y jr abort; abort ; ; Bad sector error badsec: lxi d,mbadsc; bad sector message xra a; not file r/o call error; display, flush input stream retry: lxi d,qretry call mesg call cin ani 05fh cpi 'R' rz; with z flag for "retry" cpi 'A' jrz abort; else abort cpi 'I' jrnz retry ora a ret; with n/z flag for ignore ; ; Select error selerr: lxi d,msel; Select error message jr abterr; go display error & abort ; ; File read only error filro: lxi d,mfilro; File R/O message mvi a,0ffh; Set file R/O message flag ; " " ; Abort error, no option to retry abtro: call error; display error call getch; get operator response ; " " ; Errors and user breaks abort through here. ; Restore input arguments and stack for any debugger. abort: lda funct mov c,a; restore fnct pushix pop d; restore argument lspd spsave; callers stack lhld abtrap; usually 0, reboot push h lxi h,ramlow+0 shld abtrap; reset for next time ret ; ; Drive read only error rdonly: lxi d,mro; Drive R/O messaage ; " " abterr: xra a; not file r/o jr abtro ; qretry: db cr,lf,'A)bort I)gnore R)etry?$' brkmsg: db cr,lf,'Resume (y/N)?$' ; ; Display Error Message ; DOS+ error on D: ERROR MESSAGE ; FUNCTION = NN [FILE = FILENAME.TYP] error: mov c,a; Save file R/O message flag push b push d; Save error message pointer lda defdrv; get current drive adi 'A'; make Ascii sta mdrive; modify message lxi d,mberr; "DOS+ ERROR ON D:" call mesg; display message pop d; Get error message pointer call mesg; display it lxi d,mbfunc; "FUNCTION =" call mesg; display it lda funct; Get function number push psw call tadzs; display number pop psw; restore function number pop b; Get file R/O flag cpi 15; Test FCB used in command jrc cflush; no cpi 24 jrc error1; yes cpi 30 jrz error1; yes cpi 33 jrc cflush; no cpi 37 jrc error1; yes cpi 40 jrnz cflush; no error1: pushix; yes, display "FILE =" sui 19 jrnz error2; Not delete file function ora c jrz error2; not file r/o error call caldir; Get FCB from directory buffer xthl; save it error2: lxi d,mfile; " FILE =" call mesg; Display it pop h; ^FCB mvi b,8; 1st 8 chars. call filenm mvi a,'.' call co; write '.' mvi b,3; last 3 chars call filenm ; " " ; Flush any incoming console chars ; a,f,b,c,d,e,h,l (because bios) cflush: call csta rz; nothing ready call getch; purge it jr cflush ; ; Display hl^ for (b) chars, suppress blanks filenm: inx h; adv pointer mov a,m ani 07fh; remove any attributes cpi ' ' cnz co; write djnz filenm; more ret ; ; ******************************* ; * * ; * DISK FUNCTIONS * ; * * ; ******************************* ; ; Return Version Number cmnd12: lda flags ani fb.comp mvi a,22h jrnz rtnbyt; return 2.2 in compatibility mode mvi a,020h+ver; act like 2.2 compatible, not 3.0 jr rtnbyt; exit ; ; Reset disk system cmnd13: lxi d,ramlow+080h; Set default DMA address call cmnd26; SETDMA, so bios agrees xra a; Default drive 'A' sta defdrv mov l,a mov h,a; lxi h,0 shld login; All drives logged out shld dskro; " " read/write call seldk; Select drive 'A' lda subflg; return submit flag jr rtnbyt; exit ; ; Search for file cmnd17: call seldrv; from FCB ldx a,f.drv sui '?' jrz cmd17b; '?' in drv field, all entries match ldx a,f.exhi; Get system byte cpi '?' jrz cmd17a; is '?' mvix f.exhi,0; Else set it to zero cmd17a: mvi a,14; Test 1st 15 bytes in FCB cmd17b: inr a; allow for the zero from above call search; do the search. (leaves result code) ; " " cpydir: lhld @dirbuf; Copy directory buffer lded dma; To dma addr. lxi b,128; for 128 bytes ldir ret ; ; Seach for next occurence of file cmnd18: lixd dcopy; last FCB used by search call seldrv; from FCB call searcn; Search next file match jr cpydir; and copy directory to DMA addr. ; ; Delete file cmnd19: call seldrv; from FCB call delete ; " " ; Return search result (found/not found) srchcd: lda searex; Get exit byte 00=file found, 0FFH not jr rtnbyt; and exit ; ; Rename file cmnd23: call seldrv; From FCB call renam jr srchcd; and exit with code ; ; Call 212 getinfo, subcall 0. ; Return pointer to serial # area of executing system. ; (offsets from here can access configuration tables) ; In compatibility mode this non-zero value indicates DOS+ @serial: lxi h,serial jr rtnwd ; ; Return login vector cmnd24: lhld login ; " " ; Return word value HL rtnwd: shld fvalue ; " " dummy: ret; label for null operations ; ; Return current drive cmnd25: lda defdrv; Get current drive ; " " ; Return byte value A rtnbyt: sta fvalue ret ; ; Return pointer to ALV vector cmnd27: lhld @alv jr rtnwd; and exit ; ; Return disk R/O vector cmnd29: lhld dskro jr rtnwd; and exit ; ; Change status of file (attributes) cmnd30: call seldrv; from FCB call sfattr; Change status jr srchcd; and exit ; ; Return pointer to drive table cmnd31: lhld @ixp jr rtnwd; and exit ; ; Set/get user code. Return current user code cmnd32: mov a,e; argument inr e jrz cmd32a; get only, arg 0ffh ani 01fh; mask sta user cmd32a: lda user jr rtnbyt ; ; Compute file size cmnd35: call seldrv; from FCB ; " " ; Compute file size filsz: lxi b,0; Reset file size length mov d,c call ldrrc; in FCB+33,34,35 call nowild; initial search, check wild cards rnz; wild card, illegal, error set call tstfct rz; Not found, exit with search result filsz2: call caldir; Get directory entry to hl & iy xchg; copy to de lxi h,f.rc; Offset to next record call calrrc; Calculate random record count mov a,d; Test LSB < (IX+33) subx f.rrno mov a,c; Test ISB < (IX+34) sbcx f.rrno+1 mov a,b; Test MSB < (IX+35) sbcx f.rrno+2 cnc ldrrc; Write new maximum call searcn; next file call tstfct jrnz filsz2; and test it jr rtnbyt; set 0, file found ; ; Set random record count cmnd36: lxi h,f.next; pointer to next record call calrrc; calculate ; " " ; Store bcd (3 bytes) in FCB IX^ random rcd field ldrrc: stx d,f.rrno stx c,f.rrno+1 stx b,f.rrno+2 ret ; ; Calculate random record from f.rc or f.next (on entry hl) ; Entry HL = offset in FCB; DE = FCB pointer ; Exit B,C,D = random record calrrc: dad d; Point to FCB+15 or FCB+32 mov a,m lxi h,f.exlo; Offset to extent number dad d mov d,a; Save record # to use mov a,m; extent byte ani 01fh; Mask it ralr d; Shift MSB in carry aci 0; add carry rar; Shift 1 time (16 bits) rarr d mov c,a; save ISB inx h; exhi, FCB+14 inx h mov a,m; Get exhi rrc; Shift 4 times rrc rrc rrc push psw; Save ani 03h; Mask MSB mov b,a; Save pop psw; Get LSB ani 0f0h; Mask add c; Add with ISB mov c,a; Save ISB rnc; No carry, return inr b; Incr. MSB ret ; ; Reset specified drives. No files should be open cmnd37: mov a,e cma; Complement input vector mov e,a mov a,d cma mov d,a lhld login mov a,e; mask login vector ana l mov l,a mov a,d ana h mov h,a shld login; Save resultant login vector xchg; use result as mask lhld dskro; for drive R/O vector mov a,e ana l mov l,a mov a,d ana h mov h,a shld dskro; Save resultant drive R/O vector ret ; ; ******************************* ; * * ; * Subroutines and functions * ; * * ; ******************************* ; ; Select disk from FCB. Save 0th byte in FCB0 and set to current user. seldrv: mvi a,0ffh; Set disk select done flag sta drvflg lda defdrv sta drive; Save current drive mov e,a; and to (e) ldx a,f.drv; Get drive from FCB sta fcb0; save cpi '?' jrz cmnd14; '?', select drive from (e) ani 01fh; mask drive mov a,e jrz seldr0; 0=default, select drive from (e) ldx a,f.drv; else get drive from FCB dcr a; normalize to 0..maxdrv seldr0: call seldk lda user; set current user in 1st FCB byte stx a,f.usr; (for directory searches) ret ; ; select error occured slkter: lhld stsel; error message address pchl; go display error ; ; restore entry drive. Used only on exit drvfix: lda fcb0; Get FCB byte 0 stx a,f.drv; restore it in FCB lda drive; Get old drive number mov e,a ; " " ; Select disk e cmnd14: mov a,e; drive number ; " " ; select disk a seldk: ani 0fh; mask mov b,a; to b lded login ora a jrz seldk1; Drive 'A' seldk0: rarr d; Rotate login vector rarr e; until bit 0 of (e) djnz seldk0; represents current drive seldk1: lxi h,defdrv bit 0,e jrz seldk2; Not logged in cmp m rz; Already selected, no effort needed seldk2: mov m,a; save new current drive push d; save logged in flag (e) mov c,a; copy drive number lxi h,seldsk; bios select, e bit 0 specifies reset call xbios; bad bios guard mov a,h ora l jrz slkter; Error, illegal drive mov e,m; Get translation vector inx h mov d,m inx h sded @trans; and save shld @filect; save addr. temp0 lxi d,6 dad d; ignore temp1, temp2 lxi d,@dirbuf; point to dirbuf lxi b,8; copy 8 bytes ldir lhld @ixp; Get drive parameter addr. mvi c,15; copy 15 bytes ldir pop d; restore drive logged in flag bit 0,e rnz; drive was logged in, return lhld login call sdrvb; Set drive bit in login vector shld login ; " " ; Init drive. Set up ALV bit buffer for blocks assigned. SUBFLG ; indicates if drive holds any '$*.*' file on user 0. initdr: lded maxblk; Get length ALV buffer-1 (bits) mvi a,3; / 8 initd0: srlr d; to get bytes rarr e dcr a jrnz initd0 inx d; +1, so all bits are cleared lhld @alv; point to ALV buffer push h initd1: mvi m,0; clear 8 bits inx h dcx d mov a,d ora e jrnz initd1; more pop h; restore ALV pointer lded ndir0; Get 1st 2 bytes ALV buffer (directory) mov m,e inx h mov m,d; save lhld @filect; Clear number of files on this drive xra a mov m,a inx h mov m,a sta subflg; Clear submit flag (Reset disk command) call setfct; Set file count initd2: mvi a,0ffh; update directory checksum call rddir; read FCB'S from directory call tstfct rz; last FCB, exit call caldir; Point to entry point FCB, get 0th byte cpi empty jrz initd2; Empty dir entry, get next FCB cpi tmstamp jrz initd2; Time stamp entry, get next FCB ora a jrnz initd3; Not on user 0 inx h; point to filename mov a,m sui '$' jrnz initd3; 1st filename char <> '$' dcr a; i.e. 0ffh sta subflg; to SUBFLG, may be a submit file active initd3: call allocb; Set bits from FCB in ALV buffer call setlf; update last file count jr initd2; and get next FCB ; ; Set drive bit in HL for defdrv ; a,f,d,e,h,l sdrvb: xchg; de := hl lxi h,1 lda defdrv; Get current drive ora a jrz sdrvb1; Drive 'A', hl is set sdrvb0: dad h; left shift bit dcr a jrnz sdrvb0; not positioned yet sdrvb1: mov a,d; hl := hl OR de ora h mov h,a mov a,e ora l mov l,a ret ; ; Calculate and set sector/track for directory entry # filcnt ; a,f,b,c,d,e,h,l stdir: lhld filcnt; Directory FCB counter srlr h; / 4 rarr l; (4 FCB'S / sector) srlr h rarr l shld recdir; Save (used by checksum) xchg; de := hl lxi h,0; hl := 0 ; " " ; Calculate sector/track ; Entry : HL, DE = sector number (128 byte sector) ; Result set track = HL,DE / maxsec ; set sector = HL,DE MOD maxsec ; a,f,b,c,d,e,h,l calst: lbcd maxsec; sectors/track mvi a,17; init loop counter calst1: ora a; divide by maxsec. dsbc b jrnc calst2; hl >= bc dad b; hl < bc, restore hl, set carry calst2: cmc ralr e; shift left result in DE ralr d dcr a jrz calst3; divide done ; *** Undefined macro: DADC *** ; dadc h; shift next bit (left) in hl ; Intended to be ADC HL,HL - put in as code db 0edh, 06ah ; *** End of fix *** jr calst1; continue calst3: push h; Save sector num. lhld nftrk dad d; add 1st track offset mov b,h; to BC for bios mov c,l lxi h,settrk call xbios; bad bios guard pop b; sector number lded @trans; Get translation table addr. lxi h,sectrn call xbios; bad bios guard mov b,h; result to BC mov c,l lxi h,setsec jmp xbios; bad bios guard ; ; Get disk map block number for FCB f.next entry ; Exit: HL = Address of FCB DM entry ; DE = DM entry ; BC = offset in DM ; a,f,b,c,d,e,h,l getdm: ldx c,f.next; c := next record lda nblock; a := number of blocks mov b,a; to b getdm1: srlr c; shift next_record djnz getdm1; number_of_blocks times cma adi 1+8 mov b,a; B := 8-number of blocks lda nextnd; Get extent mask andx f.exlo; mask with extent rrc getdm2: rlc djnz getdm2; 8-number of blocks times add c; Add the 2 values to get entry FCB ; " " ; Get block no. for diskmap entry (a) of FCB ix^ (b=0 on entry) ; a,f,c,d,e,h,l getbk: pushix; FCB addr. pop h mvi c,f.dm; Offset 16 to point to DM dad b mov c,a; add entry FCB dad b lda maxblk+1 ora a; Test 8/16 bits FCB entry mov e,m; Get 8 bit value mov d,a; zero if 8 bits / entry rz; 8 bits per entry only dad b; add twice (16 bit values) mov e,m; load 16 bit value inx h mov d,m dcx h; restore pointer ret ; ; Calculate dirbuf entry point. Set hl and iy pointers ; Return a := directory entry user code (0th byte) ; a,f,h,l,iy caldir: lhld @dirbuf; hl := dirbuf + secpnt lda secpnt add l mov l,a adc h sub l mov h,a push h; Set iy pointer popiy mov a,m ret ; ; Init file count ; h,l setfct: lxi h,-1 shld filcnt ret ; ; Test file count = -1, z flag if so ; a,f,h,l tstfct: lhld filcnt mov a,h ana l inr a; z if -1 ret ; ; Set last file ; a,f,d,e,h,l setlf: call tstlf; Test last file rc; No, exit inx d; incr. last file jr sdem; Save it in filect ; ; Test last file ; a,f,d,e,h,l tstlf: lhld @filect; get pointer to last file lded filcnt; get file counter mov a,e; DE-(HL) sub m inx h mov a,d sbb m ret ; ; Get next FCB from drive ; Entry : A=0 Check checksum, A=0FFH update checksum ; a,f,b,c,d,e,h,l rddir: mov c,a; Save checksum flag lhld filcnt inx h; advance file counter shld filcnt lded nfiles; get max number of files ora a; clear cy dsbc d dad d; leaves dsbc flags, restore hl jrz rddir1; Not last file jrnc setfct; last file, set file count 0FFFFH rddir1: mov a,l; Get file count LSB rrc; *32, around the bend rrc rrc ani 060h; Mask sta secpnt; Save for later use rnz; Not first FCB sector push b; save checksum flag call stdir; calculate sector/track directory call dmadir; Set DMA for directory call rdrcd; Read dir. record from drive call stdma; Set DMA for user pop b; checksum flag ; " " ; Update/Check directory checksum ; Entry : C=0 Check checksum, C=0FFH update checksum ; a,f,b,c,d,e,h,l chkdir: lhld ncheck; number of checked records lded recdir; get current record ora a dsbc d; test current record rz rc; >= ncheck, exit lhld @dirbuf mvi b,128; Set up counter xra a; Clear checksum chkdr0: add m; Add checksum inx h djnz chkdr0; 128 times lhld @csv; pointer to directory checksum dad d; add current record inr c; test checksum flag jrnz chkdr2; 0, setup checksum mov m,a; 0ffh, update checksum chkdr2: cmp m; test checksum rz; ok or setting, exit ; " " ; Set write protect disk command cmnd28: lhld dskro; get disk R/O vector call sdrvb; include drive bit shld dskro lded nfiles; Get max number of files - 1 inx d lhld @filect; point to disk parameter block ; " " and set max number of files ; Store de in hl^ ; h,l sdem: mov m,e inx h mov m,d ret ; ; Read sector from drive ; a,f,b,c,d,e,h,l rdrcd: lxi h,read call xbios; guard against bad bios ora a rz call rwerr jrz rdrcd; retry if error handler returns z ret; ignore if error handler returns nz ; ; Write sector to drive ; a,f,b,c,d,e,h,l wrtrcd: lxi h,write call xbios; guard against bad bios ora a rz; no error call rwerr mvi c,1; retries must put to disk jrz wrtrcd; retry if error handler returns z ret; ignore if error handler returns nz ; ; read/write error handler rwerr: lhld stbdsc; Bad sector message pointer pchl; DOS+ Error on D: disk I/O ; ; Set DMA address command. ; a,f,b,c,d,e,h,l cmnd26: sded dma; Save DMA address call stdma ; " " ; return current dma setting rtndma: lhld dma; echo back setting jmp rtnwd ; ; Set DMA Address for user ; a,f,b,c,d,e,h,l stdma: lbcd dma jr dmaset; do bios call ; ; Set DMA Addr. for directory ; a,f,b,c,d,e,h,l dmadir: lbcd @dirbuf; Get DMA Addr. for directory ; " " ; protected setdma dmaset: lxi h,setdma jmp xbios; guard against bad bios ; ; Get bit from ALV buffer ; Entry : DE = block number ; EXIT : A = bit IN LSB (rotated, other bits meaningful) ; B = bitnumber in A ; HL = pointer in ALV buffer ; a,f,b,c,d,e,h,l getbit: mov a,e; Get bit number ani 7; mod 8 inr a; +1 mov b,a; to b mov c,a; and c srlr d; Get byte number rarr e; DE = DE/8 srlr d rarr e srlr d rarr e lhld @alv; Get start addr. ALV buffer dad d; + byte number mov a,m; Get 8 bits getbt0: rlc; select correct bit djnz getbt0 mov b,c; restore bit number ret ; ; Set/reset bit in ALV buffer ; ENTRY : DE = block number ; C = 0 reset bit, C=1 set bit ; a,f,b,c,d,e,h,l setbit: push b call getbit; Get bit ani 0feh; mask it (reset bit) pop d; Get set/reset bit ora e; set/reset bit ; " " ; position bit and save ; a,f,b bitset: rrc; rotate bit to correct position djnz bitset mov m,a; save 8 bits ret ; ; Mark allocated blocks from FCB in dirbuf allocb: mvi c,1 ; " " ; Fill bit buffer from FCB in dirbuf ; Entry : C = 0 reset bit, C=1 set bit fillbb: call caldir; Get directory entry lxi d,f.dm; offset to DM block dad d mov b,e; Get block counter fillb0: mov e,m; Get block number, 8 bits extened inx h; advance lda maxblk+1 ora a mov d,a; 0 if < 256 blocks present jrz fillb1; < 256 blocks present dcr b; Decr. block counter, 256 or more mov d,m; Get correct MSB inx h; advance fillb1: mov a,d ora e jrz fillb2; block number = 0, Get next block push h; Save pointer push b; counter and set/reset bit lhld maxblk; get max length ALV buffer ora a dsbc d cnc setbit; de <= max length, insert bit pop b; counter and set/reset bit pop h; pointer fillb2: djnz fillb0; repeat over all DM entries ret ; ; Check file R/O, get DIR entry to hl & iy chkfro: call caldir; Get DIR entry to hl & iy ; " " ; Check file iy^ for r/o ; f ckfyro: bity 7,f.sys jrnz fronly; $SYS file, error ; " " ; For erase, allows SYS files to be erased rochk: bity 7,f.ro rz; not $R/O file, ok ; " " ; File read/only error fronly: lhld sfilro; Pointer to FILE R/O error handler pchl; Error trap ; ; Check drive read only chkro: lhld dskro; Drive R/O vector call sdrvb; Set drive bit dsbc d; test extra bit added rnz; Yes, then drive not R/O lhld stro; Pointer to DRIVE R/O error handler pchl; error trap ; ; Get free block from ALV buffer ; Entry : DE = old block number ; Exit : DE = new block number (0 if no free block) ; HL counts up, DE counts down getfre: mov h,d; hl := old block mov l,e getfr0: mov a,d ora e jrz getfr1; down counter = 0 dcx d; decrement push h; Save up/down counters push d call getbit; from ALV buffer rar jrnc getfr3; 0, found empty block pop d; Get up/down counters pop h getfr1: lbcd maxblk; get max ALV length-1 to BC ora a dsbc b; Test HL >= length ALV -1 dad b; restore HL (Flags not changed) jrnc getfr2; End Buffer inx h; Incr up counter push d; Save counters push h xchg; Up counter to DE call getbit; from ALV buffer rar jrnc getfr3; 0, found empty block pop h; Get counters pop d jr getfr0; and test next block getfr2: mov a,d ora e jrnz getfr0; not last block, test next block ret; Exit (DE=0) getfr3: stc ral; Sst block number used call bitset; put bit in ALV buffer pop d; Get correct counter pop h; restore stack pointer ret; Exit (DE=block number) ; ; Search for file name, for read/directory operations srchrd: mvi a,15; bytes to match ; " " ; Search for file name ; Entry : A : number of bytes to match search: sta searnb; Save number of bytes mvi a,0ffh; Set exit code 0FFH (not found) sta searex sixd dcopy; copy FCB pointer to RAM (search next) call setfct; init. file counter ; " " ; Search next file name searcn: xra a; check checksum directory call rddir; Get FCB from directory call tstfct jrz nofile; past last entry lded dcopy; Get FCB pointer ldax d; user byte cpi empty jrz searc1; empty directory entry push d; FCB pointer call tstlf pop d jrnc nofile; last file on this drive searc1: call caldir; hl := iy := dir entry, a := 0th byte cpi tmstamp jrz searcn; time stamp, get next directory entry xra a sta wildcd; no wild card detected yet mov c,a; i.e. a zero lda searnb; get number of bytes to match (to b) mov b,a; save input (a) for search length ; " " ; If dir entry (hl=iy)^ has the sys attribute set, and is stored under ; user 0, ignore the user number during the directory search by ; advancing the indices appropriately. At entry a contains the length ; of the directory entry to be matched, and de points to the input FCB ; (i.e. the searchee name). IY^ is the candidate dir entry. sui 15; differentiate from erase searches jrc searc4; not looking for name, orig. algorithm bity 7,f.sys; test system bit jrz searc4; not (sys) file, original algorithm mov a,m ora a jrnz searc4; not on user 0, original algorithm searc2: sta wildcd; set/reset wild card found flag searc3: inx d inx h; skip over the user id inr c djnz searc4; if more bytes to match ; " " ; All bytes matched. call setlf; update last file count (empty FCB) lda filcnt; Get file counter ani 3; mask it sta fvalue; and set exit code xra a; clear exit code search sta searex ret ; ; Check for match. searc4: ldax d; Get byte from FCB sui '?' cma; If zero then a holds 0ffh jrz searc2; set wild card found, matches any mov a,c; FCB char posn sui f.s1 jrz searc3; s1 scratch, then no test inr a; cpi f.exlo; test if extent number ldax d jrz searc7; Special case if extent number xra m; compare to directory entry ani 07fh; on mask searc6: jrnz searcn; not equal on mask, get next entry jr searc3; test next byte ; ; Special handling for extent number searc7: push b; save counters xra m; test extents mov b,a lda nextnd cma; complement extent mask ani 01fh ana b; mask extents pop b; restore counters jr searc6; and test result ; nofile: call setfct; error set file counter ; " " rtnerr: mvi a,0ffh; and set return value jmp rtnbyt ; ; delete file delete: call chkro; check disk R/O mvi a,12; count of bytes to match call search; for file del0: call tstfct rz; not found, exit call caldir; get entry point directory to iy, hl call rochk; allow $SYS files to be erased. mvi m,empty; remove file mvi c,0; remove bits ALV buffer (recycle space) call fillbb call wrtdir; write dir buffer to disk call searcn; search next entry jr del0; and test it ; ; Rename file renam: call schbgn; Check disk R/O, no wild cards, etc. rnz; wild cards renam0: call tstfct; iy points to dir entry rz; Not found, exit call chkfro; Check file R/O, set iy^ dir entry lxi b,12*256+16; Copy FCB+16 to Directory+0 12 times call wrfcb; and write dir to disk call searcn; search next file jr renam0; and test it ; ; Change status file sfattr: call schbgn; Check disk R/O, no wild cards etc. rnz; wild cards sfatr1: call tstfct; iy points to dir entry rz; Not found, exit bitx 7,f.ifc6 jrz sfatr2; No byte count update requested ldx a,f.next sty a,f.s1; set byte count sfatr2: lxi b,12*256+0; Copy FCB+0 to directory+0 12 times call wrfcb; and write dir to disk call searcn; search next file jr sfatr1; and test it ; ; Set up for search on name field. From sfattr and renam ; Error if wild cards specified (nz flag) or r/o disk (abort) schbgn: call chkro; Check disk R/O ; " " ; Initial search on name field. ; nz for wild cards specified when exit errors set nowild: mvi a,12; Count of bytes to match call search; file. iy points to dir entry lda wildcd ora a rz; No wild cards found, ok sta searex; attrib & rename return this jr rtnerr; a is 0ffh ; ; Open file command cmnd15: call seldrv; from FCB mvix f.exhi,0; clear hi extent call findf; find file (using PATH name) call tstfct rz; Not found, exit call fopen ldx a,f.next inr a rnz; Not 0ffh on entry ldx a,f.s1 stx a,f.next; else return byte count ret ; ; Open file/extent, directory entry loaded fopen: ldx a,f.exlo; Get extent number from FCB push psw call caldir; Get dir entry, hl & iy pushix pop d; FCB entry to de lxi b,32; Number of bytes to move ldir; Move directory to FCB setx 7,f.clean; Set FCB/FILE not modified ldx b,f.exlo; Get extent number ldx c,f.rc; Get next record number pop psw; old extent number stx a,f.exlo; Save it cmp b jrz fopen1; old and new extent numbers same mvi c,0; Set next record count 0 jrnc fopen1; old extent >= new extent mvi c,80h; Set next record count to maximum fopen1: stx c,f.rc; Save next record count lda flags ani fb.tacc rz; access stamping disabled bitx 7,f.ro mvi e,8 cz stime; not r/o, set access time stamp rc; timer system disabled rnz; No time stamps, this disk jr wrtdir; else time stamp updated ; ; write FCB to disk directory entry ; c is offset into FCB to copy from, b is byte count to copy wrfcb: call caldir; Get dir entry to iy, hl, a := usr code xchg; in DE pushix; Save FCB entry pop h; to hl push b mvi b,0 dad b; add offset into FCB pop b mov c,b; Get number of bytes to move mvi b,0; 0 extend ldir; Move resy 7,f.ifc6; Reset any interface bit sty a,f.usr; Restore user code ; " " ; Write directory entry to drive wrtdir: call stdir; Calculate sector/track directory mvi c,0ffh; Update dir checksum call chkdir call dmadir; Set DMA for directory mvi c,1; Write directory flag call wrtrcd; write jmp stdma; Set DMA for user & exit ; ; Close file command cmnd16: call seldrv; from FCB ; " " ; close file close: bitx 7,f.clean rnz; FCB/FILE not modified, no close req'd call chkro; test disk R/O call srchrd; file, match 15 bytes call tstfct rz; file not present, exit call chkfro; Check file R/O, get directory entry resy 7,f.arc; and reset any archive bit lxi b,f.dm; Offset to DM block dad b xchg; to de pushix pop h; FCB pointer to HL dad b; Add offset lda maxblk+1 ora a jrz close0; number of blocks < 256 dcr b; Set flag close0: call copydm; Copy and test blocks xchg; exchange copy direction call copydm; Copy and test blocks xchg; Exchange copy direction jnz rtnerr; Block not the same, error inx h; incr FCB pointer inx d; incr DIR pointer bit 0,b jrz close1; number of blocks < 256 inx h; incr FCB pointer inx d; incr DIR pointer dcr c; decr counter close1: dcr c; decr counter jrnz close0; not ready lxi h,f.exlo-f.next; Add -20, point to extent no. dad d ldx a,f.exlo; Get extent number FCB cmp m; Compare with extent number DIR jrc close3; FCB < DIRECTORY THEN JUMP mov m,a; Save extent number in directory inx h; Get pointer record count inx h inx h ldx a,f.rc; Get FCB record count in case mov m,a; entry lgh changed (+ normal, - submit) close3: call updatm; set last update time jr wrtdir; Write FCB on disk ; ; Copy and test disk map ; Entry : HL : pointer to 1st FCB ; DE : pointer to 2nd FCB ; B : 000H < 256 blocks ; 0FFH >= 256 blocks ; Exit : ZERO : 1 Blocks are the same ; 0 Blocks are not the same copydm: mov a,m; Get byte 1st FCB bit 0,b jrz copyd0; number of blocks < 256 inx h; adv. pointer ora m; test byte = 0 dcx h; restore pointer copyd0: ora a; Test block number is zero jrnz copyd1; no, compare blocks ldax d; Copy block from other FCB mov m,a; in empty location bit 0,b rz; number of blocks < 256, exit inx h; incr to MSB block numbers inx d ldax d; Copy block from other FCB mov m,a; in empty location jr copyd2; JUMP TRICK TO SAVE SPACE copyd1: ldax d; Get block number 1st FCB sub m rnz; not the same ora b rz; < 256 blocks, return inx h; incr to MSB block numbers inx d copyd2: ldax d; Get block number 1st FCB sub m; test if the same dcx h; Decr. block FCB pointers dcx d ret ; ; Find file, using path. Only default and current user entries apply findf: call srchrd; for read file. Match 15 bytes call tstfct rnz; found, exit lda fcb0 ora a rnz; drive specified, ignore path lhld path; get PATH address mov a,h ora l rz; 0, no path, exit findf2: lda drive mov b,a; keep handy. 0..maxdrv mov a,m; Get 1st entry PATH name inx h; adv. pointer ora a inx h jz nofile; last entry, not found exit cpi '$' jrz findf2; current drive already searched dcr a; put in 0..maxdrv range ani 0fh cmp b jrz findf2; current drive already searched dcx h push h; Different drive, so.. call seldk; Select drive pop h; PATH pointer lda user; keep handy mov b,a mov a,m; Get user number inx h; adv. pointer cpi '$' jrz findf5; current user, ok, search xra b ani 01fh; Mask user no. area only jrnz findf2; Path entry not for this user, skip findf5: push h; path pointer call srchrd; file, match 15 bytes call tstfct pop h; path pointer jrz findf2; file not present, test next path entry call caldir; Get directory entry lda defdrv; Get now current drive inr a; in range 1.. sta fcb0; save it in exit FCB0 ret ; ; Make file command cmnd22: call seldrv; from FCB mvix f.exhi,0; Clear high extent # call fdirty; ensure archive bit reset ; " " ; Make file make: call chkro; Check drive r/o ldx a,f.usr push psw; Save user id for file mvix f.usr,empty; Set 1st byte to empty file mvi a,1; Search for 1 byte call search; for empty DIR space. Sets result code pop psw stx a,f.usr; Restore user id for file call tstfct rz; No empty entry found, return error xra a; clear last record byte count stx a,f.s1 pushix pop h; copy FCB pointer to HL lxi d,f.rc; Prepare offset dad d mvi b,17; Set loop counter make0: mov m,a; Clear rc and dm area inx h djnz make0 call caldir; Get directory entry ldx a,f.usr; Get first byte FCB & save in mov m,a; directory (write FCB needs this) mvi e,2; Set creation date call stime call updatm; Set last update date/time mvi e,8; Set last access date/time call stime lxi b,32*256+0; Copy FCB+0 to directory+0 32 times call wrfcb; write FCB to disk setx 7,f.clean; Mark FCB/FILE not modified ret ; ; Open next extent openex: bitx 7,f.clean jrnz openx5; FCB/FILE not modified (write) call close; Current FCB. Reads/loads dir entry. lda fvalue; exit code from close inr a rz; error, exit call calnex; Calculate next extent jrc openx3; error jrnz openx6; FCB present from close (wrt, dir read) openx1: call srchrd; for file, match 15 bytes call tstfct jrnz openx6; file found lda rdwr ora a jrz openx3; read flag, error (no extent) call make; new extent (is write) call tstfct jrnz openx7; successful, exit openx3: setx 7,f.clean; Set FCB/FILE not modified jmp nofile; Set exit code for error openx5: call calnex; Calculate next extent jrc openx3; error jr openx1; use same routine ; openx6: call fopen; open file openx7: xra a; and clear exit code ; " " bytrtn: jmp rtnbyt ; ; Calculate next extent ; exit: carry => overflow detectedd ; zflag => search next extent ; nzflag => next extent present in FCB (close) ; (A single directory/FCB entry can hold multiple extents) calnex: ldx c,f.exlo; Get extent number ldx b,f.exhi; Get high portion bit 6,b; Test error bit random record stc rnz; Non-zero, error exit, cy set inr c; Incr. extent number mov a,c ani 01fh; mask extent number mov c,a; to b jrnz calnx1; non-zero extent inr b; Incr. high order extent mov a,b ani 03fh; mask it (c is zero) mov b,a; Save it in c stc rz; file overflow, error flag (cy) set ; " " since c is 0 following returns z flag ; " " for "not same dir entry" calnx1: lda nextnd; Get next extent mask ana c; Test if same dir entry (close) ; " " ; Set FCB extent bytes from bc (high/low). Preserve flags. ; Return bc = old values xchext: ldx a,f.exlo stx c,f.exlo; Save extent number mov c,a ldx a,f.exhi stx b,f.exhi; and high portion mov b,a ret ; ; Read random record command cmnd33: call seldrv; from FCB xra a; set read/write flag call ldfcb; Load random record in FCB rnz; Return error jr reads; no error, go read sector ; ; Read sequential cmnd20: call seldrv; from FCB ; " " ; Read sector reads: xra a; set read/write flag sta rdwr; save it ldx a,f.next; Get record counter cpi 080h jrnz reads1; Not last rcd of this extent call openex; Open next extent lda fvalue; get exit code ora a jrnz eofull; end of file stx a,f.next; Clear record counter jr reads2 reads1: cmpx f.rc; illegal rcd ctr fields cause eof jrnc eofull; signal EOF reads2: call getdm; Get block number from DM in FCB mov a,d ora e jrz eofull; block number = 0, end file call calsec; Calculate sector number (128 bytes) call calst; Calculate sector/track number call rdrcd; Read data lda funct; Get function number cpi 20 rnz; Not read sequential, return inrx f.next; incr. next record counter ret ; ; Signal eof or full eofull: mvi a,1; Set EOF flag jr bytrtn; and return to caller ; ; Calculate sector number from start of data area in HLDE ; Entry : DE = block number from FCB ; a,f,b,d,e,h,l calsec: lxi h,0; clear MSB sector number lda nblock; get loop counter mov b,a; to b calsc1: slar e; shift L,D,E ralr d ralr l djnz calsc1; B times lda nmask; Get sector mask andx f.next; and with next record ora e; Set up LSB sector number mov e,a ret ; ; Write random sector (with zero fill command 40 done in "writes") cmnd34: cmnd40: call seldrv; from FCB mvi a,0ffh; Set read/write flag call ldfcb; Load FCB from random record rnz; return error jr writes; no error, write record ; ; Mark file modified fdirty: resx 7,f.clean; reset FCB/FILE modified ret ; ; Write sequential cmnd21: call seldrv; from FCB ; " " ; Write sector writes: mvi a,0ffh; Set read/write flag sta rdwr; and save it call chkro; Check disk R/O pushix popiy; FCB pointer to iy call ckfyro; Check file iy^ R/O ldx a,f.next; Get record count cpi 080h jrc writs0; not end of this extent call openex; open next extent lda fvalue; error code ora a jrnz eofull; error, directory full stx a,f.next; Clear record counter writs0: call getdm; Get block number from FCB mov a,d ora e jrnz writs5; Not 0, write sector push h; save pointer to block number mov a,c ora a jrz writs1; 1st block number in extent dcr a; Decr pointer to block number call getbk; Get prev. blocknumber writs1: call getfre; Get nearest free block pop h; Get pointer to block number mov a,d ora e mvi a,2 jz rtnbyt; blocknumber = 0, disk full error call fdirty; reset FCB/FILE modified mov m,e; Save blocknumber lda maxblk+1 ora a jrz writs2; blocksize < 256 inx h; adv. to MSB blocknumber mov m,d; Save MSB blocknumber writs2: mvi c,2; Set write new block flag lda funct; Get function number sui 40 jrnz writs6; Not writeranrcd with zero fill push d; save blocknumber lhld @dirbuf; use directory buffer for zero fill mvi b,128; bytes to clear writs3: mov m,a; Clear directory buffer inx h djnz writs3; more call calsec; Calculate sector number (128 bytes) lda nmask; Get sector mask mov b,a; to b inr b; Increment to get number of writes cma; Complement sector mask ana e; Mask sector number mov e,a; and save it mvi c,2; Set write new block flag writs4: push h; Save registers push d push b call calst; Calculate sector/track call dmadir; Set DMA directory buffer pop b; Get write new block flag push b; Save it again call wrtrcd; Write record to disk pop b; Restore registers pop d pop h mvi c,0; Clear write new block flag inr e; Incr. sector number djnz writs4; Write all blocks call stdma; Set user DMA address pop d; Get block number writs5: mvi c,0; Clear write new block flag writs6: call fdirty; Reset FCB/FILE unmodified flag push b call calsec; Calculate sector number (128 bytes) call calst; Calculate sector/track pop b; write new block flag call wrtrcd; Write record to disk ldx a,f.next; Get record counter cmpx f.rc; next record jrc writs7; record counter < next record inr a; incr. record count stx a,f.rc; Save on next record position writs7: lda funct; Get function number cpi 21 rnz; not write sequential, return inrx f.next; incr. record count ret ; ; Load FCB for random read/write. NZ flag for error. ; Entry a=0 for read, 0ffh for write ldfcb: sta rdwr; save read/write flag ldx a,f.rrno; Get 1st byte random record mov d,a; to d res 7,d; Rest MSB to get next record ral; Shift MSB to carry ldx a,f.rrno+1; Load next byte ral; Shift carry push psw; Save ani 01fh; Mask next extent mov c,a; Save it in C pop psw; Get byte ral; Shift 4 times ral ral ral ani 0fh; Mask mov b,a; Save FCB+14 ldx a,f.rrno+2; Get next byte random record mvi e,6; Set random record too large flag cpi 4 jrnc ldfcb7; error, random record too large rlc; address extent (actually div 16) rlc rlc rlc add b; add byte mov b,a; Save FCB+14 in B stx d,f.next; Set next record count ldx d,f.exhi; Get FCB+14 bit 6,d jrnz ldfcb7; error, earlier random record write mov a,c; Get new extent number cmpx f.exlo; Compare with FCB jrnz ldfcb1; not equal, open next extent mov a,b; Get new FCB+14 xorx f.exhi; Compare with FCB+14 ani 03fh; Mask it jrz ldfcb5; FCB at appropriate extent, return ldfcb1: bit 7,d jrnz ldfcb2; FCB not modified (not written) push d push b call close; extent pop b pop d mvi e,3; Set close error in case lda fvalue; Get exit code inr a jrz ldfcb6; close error, exit ldfcb2: call xchext; Save new extent # (bc=high/low) push b call srchrd; search file, match 15 bytes pop b; previous value for extent fields lda fvalue; Get error code inr a jrnz ldfcb4; No error, exit lda rdwr; Get read/write flag inr a jrz ldfcb3; write, go make it call xchext; read, restore the extent bytes mvi a,4; Error, reading empty record jr ldfcb9; and exit ldfcb3: call make; make new FCB mvi e,5; make error code lda fvalue; error ? inr a jrz ldfcb6; make error exit jr ldfcb5; No error exit (zero set) ldfcb4: call fopen; open file ldfcb5: xra a; Set Z flag and clear error code jr ldfcb9 ; ldfcb6: mvix f.exhi,0c0h; Set random record error ldfcb7: setx 7,f.clean; Set FCB/FILE not modified mov a,e; error code ldfcb9: sta fvalue; save error code ora a; Clear/set zero flag ret ; ; Set update time updatm: mvi e,4 ; " " ; Set time and date ; Entry : E = 2 : Set creation date ; 4 : Set last update time/date ; 8 : Set last access time/date ; Exit : cy for timer disabled ; nz for no time stamp on drive ; z and nc for directory updated stime: lhld @dirbuf; Get directory entry lxi b,060h; offset entry point time/date stamp dad b; Add offset mov a,m; Get byte sui tmstamp rnz; No time stamp present, return mov d,a; 0, clear D dad d; Add entry (create/update/access) push d; save field id lda secpnt; Get sector pointer (0, 32, 64 rrc; Divide / 4 rrc mov e,a; 0, 8, 16 rrc; divide 4 = 0, 2, 4 rrc add e; Add it (A=0,10,20) mov e,a; Save in e dad d; point to appropriate field push h call getbtm; point to system time array pop d; field pointer pop b; restore field id rc; timer system disabled mov a,c cpi 2; no carry for valid field id jrz mvdate; 2 byte field for creation ; " " ; Move 4 byte time array hl^ to de^, avoid interrupts ; b,c,d,e,h,l mvtime: lxi b,4 ; " " ; entry for 2/4 byte fields, bc = length on entry ; b,c,d,e,h,l mvdate: di ldir; store it ei xra a; z/nc for good exits ret ; ; Get time gettim: push d; Save address to put time call getbtm; get system time adr. pop d; Restore address to put time mvi a,0ffh; If disabled return error jrc getim2 lxi b,4 call mvdate; if timer enabled mov a,m; seconds field getim2: jmp rtnbyt ; ; Set time settim: push d; keep source time ptr push d pop b; if hardware must be accessed to set call btime; get system ptr pop d rc; timer system disabled rnz; Bios did it all xchg call mvtime; sets a := 0 stax d; set seconds field 0 ret ; ; Specification for any bios timer routine. Leaves carry clear, NZ flg ; Input Output (always) ; BC = 0 get pointer HL=pointer to time array ; BC <> 0 allows hard- HL+0^ date LSB days since 1977 Dec. 31 ; ware to be updated HL+1^ date MSB (1=1978/1/1) (0=nodate) ; if a routine call. HL+2^ hour (bcd) ; ignored if timead HL+3^ minute (bcd) ; is purely an address. HL+4^ seconds (bcd) ; BC^ is time to set. ; Carry and Z flags reset. ; ; Get time from bios system getbtm: lxi b,0; so hardware not updated ; " " ; Execute BIOS time routine. ; bc = 0 to get time, <> 0 to set hardware, when bc points to time ; to set. This is used only when hardware ports accessed. ; flags 80h bit = 0 for timead = address of array ; = 1 for timead = pointer to routine ; net result is to return hl pointer to array ; i.e. at exit hl always points to the system array ; The routine call allows for interrogation of hardware ports. ; The bios routine may leave interrupts disabled, they will be ; re-enabled when the time value has been copied. ; carry set on exit means timer disabled. ; Z flag set on exit if timead is a pointer only btime: lhld timead; Get address time routine mov a,h ora l; check disabled stc rz; disabled, do nothing lda flags ani fb.tcal rz; timead is address of array only pchl; is address of routine, execute ; ; Error messages mbadsc: db 'Disk I/O$' msel: db 'No drive$' mfilro: db 'File ' mro: db 'R/O$' ; mbfunc: db cr,lf,'Fn: $' mfile: db ' File: $' ; mberr: db cr,lf,'DOS+ error '; Last area checksummable mdrive: db 0,': $'; modified ; ; RAM AREA. Note mdrive above is a variable ; dma: dw 080h; DMA address dskro: dw 0; Disk R/O vector login: dw 0; Login vector ; ; Console i/o variables. Keep these 3 in this order (wired into code) bufull: db 0; Lastch contains unused char. lastch: db 0; Last console input char. column: db 0; Current console output column ; ; Copied in from Bios tables on drive selection @trans: dw 0; ^Translation vector, 0 for none @filect: dw 0; ^Number of files on drive ds 4; temp1, temp2 not used @dirbuf: dw 0; ^directory buffer @ixp: dw 0; ^Disk parameter block @csv: dw 0; ^Check sum vector @alv: dw 0; ^Allocation vector ; ; Copied in from Disk Parameter table on drive selection maxsec: dw 0; Maximum number of sectors/track nblock: db 0; Number of blocks nmask: db 0; Mask number of blocks nextnd: db 0; Extent mask maxblk: dw 0; Maximum block number -1 nfiles: dw 0; Maximum number of files - 1 ndir0: db 0,0; First two entries ALV buffer ncheck: dw 0; Number of checksum entries nftrk: dw 0; First track number ; funct: db 0; Function number fvalue: dw 0; Exit code drvflg: db 0; Drive select used flag fcb0: db 0; FCB byte 0 (save for exit) ; rdwr: db 0; Read/write flag wildcd: db 0; Search question mark used ; user: db 0; User number drive: db 0; Drive number defdrv: db 0; Default drive number subflg: db 0; Submit flag (Reset disk command) ; recdir: dw 0; Record directory (checksum) filcnt: dw 0; File counter secpnt: db 0; Sector pointer ; dcopy: dw 0; Copy address FCB searex: db 0; Exit code for search searnb: db 0; Search number of bytes ; ; 64 minimum byte stack area. Copyright re-used for stack. stktop: db 'Copyright (c) 1986 C.B. Falconer (203) 281-1438' ds 64-($-stktop) ; ; Macro for storage allocation messages only, SLRMAC specific px macro v, xmsg ; *** FIX: PRINTX requires delimiters around its string *** .printx * v&xmsg * endm ; left equ serial+0dfeh-$ if left ge 8000h; negative +++ ERROR DOS+ too big +++ px %(-left), < too many bytes used> else px %left, < bytes still available> if left gt 0 ds left; space that's left endif ; Put stack at end of segment. Error trappers expect spsave there. stack: spsave: dw 0; Entry stack pointer save at end endif ; end iters around its string *** .printx * v&xmsg * endm ; left equ serial+0dfeh-$ if left ge 8000h; negative +++ ERROR DOS+ too big +++ px %(-left), < too many bytes used> else px %left, < bytes still available> if left gt 0 ds left; space that's left endif ; Put stack at end of segment. Error trappers expect spsave there. stack: spsave: dw 0; E page 90 title BIOS Hooks ;=======================================================================; ; ; ; D-X Designs Pty. Ltd. Perth, Western Australia ; ; Project: 112 May, 1996 ; ; ; ; Copyright (C) 1996 David R. Brooks ; ; ; ; This program is free software; you can redistribute it and/or ; ; modify it under the terms of the GNU General Public License ; ; as published by the Free Software Foundation; either version 2 ; ; of the License, or (at your option) any later version. ; ; ; ; This program is distributed in the hope that it will be useful, ; ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; ; GNU General Public License for more details. ; ; ; ; You should have received a copy of the GNU General Public License ; ; along with this program; if not, write to the Free Software ; ; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ; ; ; ;=======================================================================; global BOOT, WBOOT, CONST, CONIN, CONOUT, LIST, PUNCH global READER, HOME, SELDSK, SETTRK, SETSEC, SETDMA, READ global WRITE, LISTST, SECTRN dseg ;Make it DSEG, then exclude from output file BOOT: ds 3 ;Each is length of a JP WBOOT: ds 3 CONST: ds 3 CONIN: ds 3 CONOUT: ds 3 LIST: ds 3 PUNCH: ds 3 READER: ds 3 HOME: ds 3 SELDSK: ds 3 SETTRK: ds 3 SETSEC: ds 3 SETDMA: ds 3 READ: ds 3 WRITE: ds 3 LISTST: ds 3 SECTRN: ds 3 end  global BOOT, WBOOT, CONST, CONIN, CONOUT, LIST, PUNCH global READER, HOME, SELDSK, SETTRK, SETSEC, SETDMA, READ global WRITE, LISTST, SECTRN dseg ;Make it DSEG, then exclude from output file BOOT: ds 3 ;Each is length of a JP WBOOT: ds 3 CONST: ds 3 CONIN: ds 3 CONOUT: ds 3 LIST: ds 3 PUNCH: ds 3 READER: ds 3 HOME: ds 3 SELDSK: ds 3 SETTRK: ds 3 SETSEC: ds .comment $ R O M - M O N I T O R E X T E R N A L H O O K S Definitions of code-hooks for external entry to the ROM. These are intended for use by OS boot-sectors, etc. They MUST NOT be used by BIOS and similar code, since the ROM will be disabled. The symbolic names are those used in the ROM code for these routines. $ diskop equ 8 ;JP to diskette handler dpb3 equ diskop+3 ;Ptr. to 3" D.P.B. dpb5 equ dpb3+2 ;Ptr. to 5" D.P.B. getchr equ 10h ;Read console to A (or 0) putchr equ 18h ;Output A on console putmsg equ 20h ;Output ASCIIZ (HL) on console break equ 38h ;ROM breakpoint trap ;----------------------------------------------------------------------- ill be disabled. The symbolic names are those used in the ROM code for these routines. $ diskop equ 8 ;JP to diskette handler dpb3 equ diskop+3 ;Ptr. to 3" D.P.B. dpb5 equ dpb3+2 ;Ptr. to 5" D.P.B. getchr equ 10h ;Read console to A AED5BECFAED52200921E6FA3AEE05 :20F86000FABE281E3AE8FAB7C4C7F82AE9FA22ECFA3AE6FA32EEFA3AE4FAB7C4C3F8AF32BC :20F88000E8FA3AEBFAE6032E00CB3F67CB1D11FEFD19ED5BDFFA0180003AE1FAB720063E00 :20F8A0000132E8FAEBEDB03AE2FAFE013AE3FAC0B7C0AF32E8FACDC7F83AE3FAC93E01CD0D :20F8C000C5FCC93E0218023E03DDE5F5CD4EF9DD2ADBFA21FEFD3AECFA570601F1CDC5FC43 :20F8E000DDE13802AFC93E01A732E3FAC97AFE023FD8420E10ED4C2133F609010A00097BCE :20F90000FEFF20107E23666FE5DDE1DD5EFD010F00DD09C9FE053FD8E5DDE1CB23160021C8 :20F9200032F9197E23666FB437C8DD7500DD7401A7C956F60000000075F6000079A7CAC5E0 :20F94000FC3D20043A66F9C93D37CCEDF8C92ADDFAED4BEDFAE978CB21FE093803D6090C60 :20F960003C5FC90458C900AF3203007A3204003266F9213CF92201F6CDEDF8AFCDC5FC215A :20F98000B7F9CDAAF93E08ED398E01100010FE0D20FB3E0CED398EED388DED388DAF32467D :20F9A0000021C4F9CD0AF7C3D3F63EFF06004EED0CC823EDA318F59B80980C99009B03996E :20F9C000009C03000D0A42494F53206275696C742030382D4D61722D313939370D0A000011 :20F9E000000000000000000000000000000000000000000000000000000000000000000007 :20FA00000000000000000000000000000000000000000000000000000000000000000000E6 :20FA20000000000000000000000000000000000000000000000000000000000000000000C6 :20FA40000000000000000000000000000000000000000000000000000000000000000000A6 :20FA6000000000000000000000000000000000000000000000000000000000000000000086 :20FA8000000000000000000000000000000000000000000000000000000000000000000066 :20FAA000000000000000000000000000000000000000000000000000000000000000000046 :20FAC000000000000000000000000000000000000000000000000000000000000000000026 :20FAE000000000000000000000000000000000000000C5D50100001614ED38DECB77280BC9 :20FB00000D20F610F41520F1371801AFD1C1C9CDF2FA3E053841C5D511F1FD0607CD65FBF6 :20FB2000121310F9D1C121F1FDE57EE6F8FDBE012021237EFDBE02201A237ED6002014ED88 :20FB40002826ED3827B5E13E042008AF18093E033718043E02E137C9F5ED3894CB7F28F96D :20FB6000F1ED3995C9ED3894CB7F28F9ED3895C9C546237ECD58FB10F9C1C9E521EFFD3ADE :20FB8000F0FD2FA677E1C9CDB3FDED2923ED2124ED39253EA0ED3920AFED3921ED3922C924 :20FBA000CDB3FDED2920ED2121ED39223EA0ED3923AFED3924ED3925C9FDE37B803D3DDDB5 :20FBC000BE04308A3C67FD7E00CD58FB7ACB412802CBD7CD58FB79CB3FCD58FB79E601CD29 :20FBE00058FB7BCD58FBDD7E03CD58FB7CCD58FBDD7E05CD58FB3E63ED39303EFFCD58FB29 :20FC0000CD0FFBC5F5010300FD09F1C1FDE3C9E5D5C5214000DD4603042910FD545D2100DC :20FC200000C1C51910FDED2926ED212722FCFDC1D1E1C9CDF2FA3E05D83E08CD58FBCD65E4 :20FC4000FB47CD65FBC5CB39B9C13E0737C078E6E0FE20C83E0137C9C5E542043E08871086 :20FC6000FD32F0FD47ED38924FE6FCB2F60CED399279A02016ED3892B0ED3992DD7E0A8773 :20FC800001000010FE0D20FB3D20F8DD7E0CED39973E03CD58FBDD7E00CD58FBDD7E01CBB1 :20FCA00087CD58FB21EFFD3AF0FDA620133E07CD58FB7ACD58FBCD33FC38063AF0FDB67703 :20FCC000AFA7E1C1C9FE0738043E0637C9CDD8FCF5DC4EFDF1D8AFC9E521E8FC87856F304B :20FCE00001247E23666FE3C94EFD69FDF6FCFCFC02FD08FDB3FDE52173FD1810E5218BFD42 :20FD0000180AE521A3FD1804E521B0FD22FAFDE1F53EC332F9FDE521000022FCFDE13E03F1 :20FD200032F8FDF1E5CDF9FDE13018FE022804FE07200BF5CD7BFB3AF8FD3D20E3F137119E :20FD4000F1FDC9ED5BFCFD1911F1FDC937C9E5AF32EFFDED39923E0CED39922164FDCD709F :20FD6000FBAFE1C9041300712BED3892E60FED3992AFC9CD58FCC24CFDCD87FBCD0FFC3E0F :20FD8000CDED3931CDB9FB464080C9CD58FCC24CFDCDA0FBCD0FFC3EF1ED3931CDB9FB4537 :20FDA0004080C9CD58FCC24CFDCDB9FB560000C9C34CFDE57CE6F067ED383AE6F06F7C958F :20FDC0003805ED38381811ED383A878787876F7C953E003803ED3839E1C5E54C06006F60E2 :0EFDE00029292929097CE60F45E160C1A7C940 :00000001FF 000000000000000000000000000000026 :20FAE000000000000000000000000000000000000000C5D50100001614ED38DECB77280BC9 :20FB00000D20F610F41520F1371801AFD1C1C9CDF2FA3E053841C5D511F1FD0607CD65FBF6 :20FB2000121310F9D1C121F1FDE57EE6F8FDBE012021237EFDBE02201A237ED6002014ED88 :20FB40002826ED3827B5E13E042008AF18093E033718043E02E137C9F5ED3894CB7F28F96D :20FB6000F1ED3995C9ED3894CB7F28F9ED3895C9C546237ECD58FB10F9C1C9E521EFFD3ADE :20FB8000F0FD2FA677E1C9CDB3FDED2923ED2124ED39253EA0ED3920AFED3921ED3922C924 :20FBA000CDB3FD page 90 title BIOS1 subttl 08-Mar-1997 DRB ;===============================================================; ; ; ; Z 1 8 2 C P / M B I O S - M k I ; ; ; ; "First cut" BIOS for the Z80182 CP/M board. Includes support ; ; for 3" and 5" drives. By default, Drives 0 & 1 are 3" ; ; ; ; NB If you change this, update DATECODE: to suit ; ; - at end of file ; ; ; ;===============================================================; ;=======================================================================; ; ; ; D-X Designs Pty. Ltd. Perth, Western Australia ; ; Project: 112 May, 1996 ; ; ; ; Copyright (C) 1996 David R. Brooks ; ; ; ; This program is free software; you can redistribute it and/or ; ; modify it under the terms of the GNU General Public License ; ; as published by the Free Software Foundation; either version 2 ; ; of the License, or (at your option) any later version. ; ; ; ; This program is distributed in the hope that it will be useful, ; ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; ; GNU General Public License for more details. ; ; ; ; You should have received a copy of the GNU General Public License ; ; along with this program; if not, write to the Free Software ; ; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ; ; ; ;=======================================================================; .comment $ Besides the regular BIOS functions, additional "overload" functions are defined. These are called from the cold-boot entry (which CP/M never uses after start-up). The call passes a function code in C. Currently defined are: C=0 Reset disk subsystem This will turn off all drive motors, and issue a reset to the controller hardware. It does NOT flush the CP/M blocking buffers: a call to HOME should be made first, to do this. C=1 Get boot-drive number The number of the drive from which CP/M was booted is returned in A. C=2 Assign drive type Pass D = required drive number E = required drive type (see DRVTYPE.INC for definitions) If D and E are valid, the given drive is assigned to the hardware type specified in E. This affects both the CP/M organisation tables, and the parameter-block controlling the hardware setup. If E = -1, the assigned type is returned in E. 6-May-1996 Original issue 7-Mar-1997 Fixed boot-up to exclude path for DOS+ 8-Mar-1997 Added date-stamp sign-on message $ auxio equ 0 ;Define to include AUX ports code Z80182 equ 0 include Z180.INC include DPARM.INC include FDC.INC include DRVTYPE.INC include ASCII.INC global bios extrn diskop ;The core disk driver extrn hstbuf ;512-byte host buffer ; Addresses within the CP/M load CPMSZE equ 1600h ;Length of CCP + BDOS ccp equ bios-CPMSZE ;Start of CP/M proper bdos equ ccp+806h ;Entry point within CP/M ; ; Addresses within the 1st. 100H bytes boot? equ 0 ;"jp boot" iobyte equ 3 ;Intel i/o byte cdisk equ 4 ;currently logged disk bdos? equ 5 ;"jp bdos" ; cseg ; ;BIOS standard entry points bios: jp boot ;First locn. wboote: jp wboot jp const jp conin jp conout jp list jp punch jp reader jp home ;See side effect below jp seldsk jp settrk jp setsec jp setdma jp read jp write jp listst jp sectran $eject ; D I S K O R G A N I S A T I O N T A B L E S .comment $ The 3" diskette has 18 sectors per track, while the 5" has 9. Both drives are 2-sided. This makes for a very simple dual-drive scheme: for 5" drives, the two sides are mapped into one 18-sector track, while each side is a separate track on the 3" drives. The overall organisation is then: 3" 5" ------------------------------------- Bytes / sector 512 512 Sectors / track 18 18 Tracks / disk 160 40 ------------------------------------- Bytes / disk 1,474,560 368,640 The only parameter which changes is the number of "tracks". Both drives have the sector interlace created by hard formatting. Hence there is no sector-translation table. This system is not only simpler, but is inherently transparent to disks created with different interlace strategies. $ ;Constants describing the track layout:- blksiz equ 2048 ;CP/M allocation block size hstsiz equ 512 ;host sector size hstspt equ 18 ;host sectors per track hstblk equ hstsiz/128 ;CP/M sectors per host sector cpmspt equ hstblk * hstspt ;CP/M sectors per track secmsk equ hstblk-1 ;sector mask secshf equ 2 ;log(2) hstblk ; ;BDOS write-command codes: wrall equ 0 ;write to allocated wrdir equ 1 ;write to directory wrual equ 2 ;write to unallocated ;---------------------------------------------------------------------- ; D I S K - P A R A M E T E R H E A D E R S dpbase: ;Drive Parameter headers: Drives 0 & 1 ;Drive 0: Values for a 3", 1.44MB drive dw 0 ;Skew table (none) dw 0,0,0 ;Scratch for CP/M dw dirbf ;Directory Buffer dpbptr: dw dpblk3 ;Disk Parameter Block (3") dw chk00 ;Work area (for changed diskettes) dw all00 ;Allocation vector hdrsiz equ $-dpbase ;Length of block ; ;Drive 1: Values for a 5", 360kB drive dw 0 ;Skew table (none) dw 0,0,0 ;Scratch for CP/M dw dirbf ;Directory Buffer dw dpblk3 ;Disk Parameter Block (3") dw chk01 ;Work area (for changed diskettes) dw all01 ;Allocation vector ndrives equ ($-dpbase) / hdrsiz ;No. of drives ;---------------------------------------------------------------------- ; D I S K - P A R A M E T E R B L O C K S ; ;Parameters for 5", 360kB drives ;Special parameters BEFORE label db D5_360 ;Drive type dw remap5 ;Sector mapping strategy dpblk5: dw cpmspt ;CP/M "sectors"/track db 4 ;Block shift db 15 ;Block mask db 1 ;Extent mask dw 174 ;Max. allocn. block no. dw 63 ;No. of directory entries -1 db 10000000B ;Bit-map for allocn. blocks db 00000000B ; used for directory dw 16 ;No. of bytes in dir. check buffer dw 1 ;No. of tracks before directory dpbofs equ $-dpblk5 ;Size of the preceding block ; Custom extension: controller hardware parameters ; Format is same as MS-DOS db 0dfh ;SRT=3mS, HUT=240mS db 02h ;HLT=4mS, no DMA db 25h ;5 secs. (25 index pulses) db 02h ;512 bytes/sector maxsec: db 09 ;Sectors/track db 2ah ;Gap length db 0ffh ;DTL (not used) db 50h ;Gap-3 length: Format db 0e5h ;Data fill: Format db 0fh ;Head-settle time (mS) db 8 ;Motor-on delay * 1/8 sec. db 39 ;Highest cylinder no. db 02 ;data rate (250kb/s) ;----------------------------------------------- ; The following "max." values are defined for the largest disk node equ 128 ;No. of directory entries noab equ 715 ;No. of allocation blocks ;Parameters for 3", 1.4MB drives ;Special parameters BEFORE label db D3_144 ;Drive type dw remap3 ;Sector mapping strategy dpblk3: dw cpmspt ;CP/M "sectors"/track db 4 ;Block shift db 15 ;Block mask db 0 ;Extent mask dw noab-1 ;Max. allocn. block no. dw node-1 ;No. of directory entries -1 db 11000000B ;Bit-map for allocn. blocks db 00000000B ; used for directory dw 32 ;No. of bytes in dir. check buffer dw 1 ;No. of tracks before directory ; Custom extension: controller hardware parameters ; Format is same as MS-DOS db 0dfh ;SRT=3mS, HUT=240mS db 02h ;HLT=4mS db 25h ;5 secs. (25 index pulses) db 02h ;512 bytes/sector db 18 ;Sectors/track db 1bh ;Gap length db 0ffh ;DTL (not used) db 6ch ;Gap-3 length: Format db 0e5h ;Data fill: Format db 15 ;Head-settle time (mS) db 8 ;Motor-on delay * 1/8 sec. db 79 ;Highest cylinder no. db 00 ;data rate (500kb/s) ;--------------------------------------------------------------------- bsects equ (bios-ccp)/hstsiz ;No. of warm-boot sectors to load basect equ 2 ;First CP/M sector (after boot) wboot: ld sp,80h ;warm boot: reload cp/m ;NB boot from 5" double-density drive, ; so we save time by reading physical, ; 512-byte sectors. CP/M starts at ; physical sector 1. ; call flush ;Clean up the disk system jr nz,faults ; write errors ; Re-load CP/M. This code must determine whether CP/M is entirely on ; one track, or split over the two sides of the disk. Either one or ; two reads are necessary, as the disk driver does not support multi- ; track operations. ; This code uses "physical" sector notation, so there is no need to ; call the transation function. ;Set up to re-load CP/M ld a,(bootdv) ;Boot drive push af ld c,a call seldsk ;Sets up DPH pointers, etc. pop af ld d,a ;Drive in D ld b,CPMSZE / hstsiz ;No. of sectors to load ld ix,(curdph) ld hl,ccp ;Start of load ld c,0 ;First system track ld e,2 ;After boot sector ld a,(ix+EOT) ;Final sector, this track cp b ;Is that enough? jr nc,onetrk push bc ;Save total sectors ld a,2 ;No: read an extra track ld b,(ix+EOT) ;Sectors on this track dec b ;Skipping the first push bc push de call diskop ;Read 1st track jr c,faults pop de pop bc pop af ;Total sectors reqd. (B -> A) sub b ;Less those already read ld b,a inc c ;Next track ld e,1 ;Start at the beginning onetrk: ld a,2 ;"Read" last/only track call diskop jr c,faults ; C O M M O N C O D E T O C O L D & W A R M - B O O T gocpm: xor a ld (hstact),a ;host buffer inactive ld (unacnt),a ;unalloc. ctr. = 0 ld a,0c3h ;"jp" ld (boot?),a ld hl,wboote ld (boot?+1),hl ;BIOS entry ld (bdos?),a ld hl,bdos ld (bdos?+1),hl ;BDOS entry ld bc,80h call setdma ;default buffer locn. ld a,(cdisk) ld c,a ;currently logged disk jp ccp ;then to cp/m ; faults: ld hl,emsg ;Reboot failed (this is fatal) call putmsg di halt emsg: db 0dh,0ah,'FAIL',0 ;------------------------------------------------------------ putmsg: ;Output ASCIIZ on conout ld a,(hl) ;Affects A, BC, HL and a ret z ;Zero terminates ld c,a call conout ;Display 1 char. inc hl jr putmsg ;------------------------------------------------------------ ; C O N S O L E I / O O P E R A T I O N S const: in0 a,(sccacnt) ;Console status rra ;Input-ready is Bit-0 ( -> CY) sbc a,a ;a = ff, if CY = 1 ret ; ; conin: push hl ;console input push bc ;delays for drive turn-off ld hl,0 ld b,64 ;initialise: 20 secs. approx lp: call const and a ;console ready? jr nz,ex ;yes... dec hl ld a,h or l ;inner-loop count jr nz,lp djnz lp ;outer-loop count ; call turnoff ;After 20 secs., drives off w2: call const ;then wait on... jr z,w2 ex: pop bc ;input ready pop hl in0 a,(sccad) and 7fh ;so get it ret ; conout: in0 a,(sccacnt) ;console output bit 2,a ;tx ready? jr z,conout ld a,c out (sccad),a ;send it ret ; ;------------------------------------------------------------- ; ; A U X I L I A R Y I / O F U N C T I O N S ; ;Parallel Port IO Addresses dport equ 8ch ;Data port sport equ 8dh ;Status port cport equ 8eh ;Control port reader: ifdef auxio in0 a,(_LSR) ;Line status? bit 0,a jr z,reader ;Loop till ready in0 a,(_RBR) res 7,a ;Mask bit 7 (CP/M std.) ret endif punch: ifdef auxio in0 a,(_LSR) ;Line status? bit 5,a jr z,punch ;Wait till ready out0 (_THR),c ;Send from C ret endif listst: ;List device status in0 a,(sport) ;Get status rlca ;A[7] (ready) -> CY sbc a,a ;A = -1 if CY set ret ;Returns A, & NZ if ready list: ;Output C on printer call listst ;Busy? jr nz,ls2 ;Go if ready ld b,40 ls1: djnz ls1 ;Pause, jr list ; then try again ls2: out0 (dport),c ;Latch data ld a,0dh out0 (cport),a ;STB = 1 nop nop ;Pause ld a,0ch out0 (cport),a ;STB = 0 ret ; ;---------------------------------------------------------------- ; D I S K - M A N A G E M E N T F U N C T I O N S home: call flush ;Intentional side effect ld c,0 ;use track 0 settrk: ld a,c ;use track (c) - 8 bits only ld (sektrk),a ret ;----------------------------------------------------------------- ; Clean-up the disk sub-system flush: ld a,(hstact) ;see if block needs writing out, first or a ret z ld a,(hstwrt) ;if active & written, write it back or a call nz,writehst ;Return Z if OK ret ;------------------------------------------------------------------ ; setsec: ld a,c ;use sector (c) ld (seksec),a ret ; ; sectran: ;translate sector (bc), using table at (de) push bc pop hl ;Null routine: just BC => HL ret ; ; setdma: ld (dmaadr),bc ;buffer addr. in bc ret ; ; seldsk: ld hl,0 ;select drive (c): DPH ptr. in HL ld a,c ld (sekdsk),a cp ndrives ;Valid? ret nc ;if > 1, abort ; ld b,hdrsiz ;Length of DPH entry mlt bc ;BC = offset into list ld hl,dpbase add hl,bc ;DPH ptr. in HL (wanted for BDOS) push hl ; - hence saved ld bc,dpbptr-dpbase add hl,bc ld a,(hl) inc hl ld h,(hl) ld l,a ;HL -> Drive Parameter Block dec hl ld b,(hl) dec hl ld c,(hl) ;BC -> mapping strategy ld (mapptr),bc ; Saved for disk access routines ld bc,dpbofs+2 add hl,bc ld (curdph),hl ;HL -> current hardware parameters pop hl ;Original DPH ptr. for BDOS ret ; ;----------------------------------------------------------------- ; read: ;Read one, 128-byte "sector" ld a,1 ld (readop),a ;read operation ld a,wrual ld (wrtype),a ;treat as unalloc. jr alloc ;to common code ; ; write: ;Write one, 128-byte "sector" xor a ld (readop),a ;not a read ld a,c ;write type in c (ex BDOS) ld (wrtype),a cp wrual ;write unallocated? jr nz,chkuna ;check for unalloc. ; ; write to unallocated: set parameters ld a,blksiz/128 ;next unalloc. recs. ld (unacnt),a ld a,(sekdsk) ;drive to seek ld (unadsk),a ;unadsk := sekdsk ld a,(sektrk) ld (unatrk),a ;unatrk := sektrk ld a,(seksec) ld (unasec),a ;unasec := seksec ; chkuna: ;checks for write to unallocated sectors ld a,(unacnt) or a ;any unallocated sectors remaining? jr z,alloc ;skip if not ; ; more unallocated records remain dec a ;unacnt := unacnt - 1 ld (unacnt),a ld hl,(sekdsk) ;sekdsk, sektrk ld de,(unadsk) ;unadsk, unatrk sbc hl,de ;equal? (cy=0 from "or" above) jr nz,alloc ld hl,unasec ld a,(seksec) cp (hl) ;same sector? jr nz,alloc ;skip if not same inc (hl) ;unasec := unasec + 1 ld a,(hl) ;end of track? cp cpmspt ;count cp/m sectors jr c,noovf ;skip if no oflo ; ; overflow to next track ld (hl),0 ;unasec := 0 ld hl,unatrk inc (hl) ;unatrk := unatrk + 1 ; ; match found: mark as unnecessary read noovf: xor a ld (rsflag),a jr rwoper ;to do the write ; ; not an unallocated record: requires a pre-read alloc: xor a ld (unacnt),a ;unacnt := 0 inc a ld (rsflag),a ;rsflag := 1 ; ; ; common code for read & write ; rwoper: xor a ld (erflag),a ;no errors (yet!) ld a,(seksec) ;compute host sector rept secshf srl a ;a shr 1: bring in zero endm ld (sekhst),a ;host sector to seek ; ; active host sector? ld hl,hstact ;host-active flag ld a,(hl) ld (hl),1 ;active now! or a ;was it already? jr z,filhst ;fill host if not ; ; host buffer active: same as seek buffer? ld hl,(sekdsk) ;sekdsk, sektrk ld de,(hstdsk) ;hstdsk, hsttrk sbc hl,de ;equal? (cy=0 from "or" above) jr nz,wngsec ld hl,sekhst ;use converted sector no. ld a,(hstsec) cp (hl) ;same sector too? jr z,match ; ; proper disk, but not correct sector wngsec: ld a,(hstwrt) ;host written? or a call nz,writehst ;clear host buffer ; ; may have to fill the host buffer filhst: ld hl,(sekdsk) ;sekdsk & sektrk => ld (hstdsk),hl ; hstdsk & hsttrk ld a,(sekhst) ld (hstsec),a ;sekhst => hstsec ld a,(rsflag) ;need to read? or a call nz,readhst ;yes, if 1 xor a ld (hstwrt),a ;no pending write ; match: ;copy data to/from buffer ld a,(seksec) ;mask buffer no. and secmsk ;l.s. bits ld l,0 ;bits shl 7 => hl srl a ld h,a rr l ;shift right 1, ie left 7 in next byte ld de,hstbuf add hl,de ;hl := host addr. ld de,(dmaadr) ;get/put to cp/m buffer ld bc,128 ld a,(readop) ;which way? or a jr nz,rwmove ;skip if read ; ; write operation: mark & switch direction ld a,1 ld (hstwrt),a ;hstwrt := 1 ex de,hl ;source/dest. swap rwmove: ldir ;shift across ; ; data has been moved to/from host buffer ld a,(wrtype) cp wrdir ;write to directory? ld a,(erflag) ;in case errors ret nz ;no further processing ; ; clear host buffer for directory write or a ;errors? ret nz ;skip if so xor a ld (hstwrt),a ;buffer written call writehst ld a,(erflag) ret ;--------------------------------------------------------- ; B A S I C D I S K O P E R A T I O N S turnoff: ;Turn off all drive motors ld a,1 call diskop ret readhst: ;Set up argts. for READ ld a,2 ;READ command jr common writehst: ;Set up argts. for WRITE ld a,3 ;WRITE command common: push ix ;Must not alter it, for DOS+ push af ;Save the command call mapsec ;Get track & sector in C, E ld ix,(curdph) ;Current drive parameters ld hl,hstbuf ;Always IO to this buffer ld a,(hstdsk) ;Drive no. ld d,a ld b,1 ;Always 1 sector only pop af ;Command code call diskop ;Go do it pop ix ;Unchanged jr c,flt xor a ;OK - set zero ret flt: ld a,1 ;Errors: set NZ and a ld (erflag),a ret ;---------------------------------------------------------- ; S E T U P D R I V E P A R A M E T E R S ; Routine to assign hardware type & CP/M strategies to a given ; drive. Enter with: ; D = Drive No. (0..ndrives) ; E = Drive Type (0..ntypes) ; ; If E = -1, the currently assigned type is RETURNED in E, and ; IX will point to the hardware parameter block. The BIOS tables ; are unchanged by this call. drivetype: ld a,d cp ndrives ;Drive in range? ccf ret c ;No: exit with CY=1 ld b,d ld c,hdrsiz mlt bc ld hl,dpbase add hl,bc ;HL -> reqd. DPH ld bcm80 loadbios,loadbios=loadbios m80 bios,bios=bios m80 diskopq,diskopq=diskopq m80 biostop,biostop=biostop l80 /p:F500,/d:FDEF,loadbios,bios,diskopq,biostop,bios/n:p/y/x/e ROMHOOK INCpBIOS HEX,qrsBIOS MACtuvwxyz{BIOS MAC5|}~BIOS SUB page 90 title BIOS top-of-memory ;===============================================================; ; ; ; T O P - O F - M E M O R Y M A R K F O R B I O S ; ; ; ; D-X Designs Pty. Ltd. Perth, Western Australia ; ; Project: 112 Author: D R Brooks May, 1996 ; ; ; ;===============================================================; ; Just mark the top "cseg" location used: cseg global biostop, hstbuf biostop equ $ dseg hstbuf: ds 512 ;Disk sector buffer end - O F - M E M O R Y M A R K F O R B I O S ; ; ; ; D-X Designs Pty. Ltd. Perth, Western Australia ; ; Project: 112 Author: D R Brooks May, 1996 ; ; ; ;===============================================================; ; Just mark the top "cseg" location used: cseg global biostop, hstbuf biostop equ $ dseg hstbuf: ds 51;Standard drive-parameter block ; Format is same as MS-DOS BIOS SPEC_1 equ 0 ;"Specify" byte 1 SPEC_2 equ 1 ;"Specify" byte 2 MTROFF equ 2 ;Wait before stop motor SECSZE equ 3 ;Bytes/sector (must be > 0) EOT equ 4 ;Final sector no. GPL equ 5 ;Gap length DTL equ 6 ;Data transfer length GAPFMT equ 7 ;Gap-3 length: Format DATFMT equ 8 ;Data fill: Format SETTLE equ 9 ;Head-settle time (mS) MTRON equ 10 ;Motor-start (* 1/8 sec.) MAXCYL equ 11 ;Max. cylinder no. DRATE equ 12 ;Data rate  EOT equ 4 ;Final sector no. GPL equ 5 ;Gap length DTL equ 6 ;Data transfer length GAPFMT equ 7 ;Gap-3 length: Format DATFMT equ 8 ;Data fill: Format SETTLE equ 9 ;Head-settle ; Standard drive-type identifiers ntypes equ 5 ;No. of defined types D5_360 equ 0 ;5", 360kB D5_120 equ 1 ;5", 1.2MB D3_720 equ 2 ;3", 720kB D3_144 equ 3 ;3", 1.44MB D3_288 equ 4 ;3", 2.88MB ROMHOOK INCpBIOS HEX,qrsBIOS MACtuvwxyz{BIOS MAC5|}~BIOS SUBBIOSTOP MACDPARM INCDRVTYPE INC page 90 title Basic diskette handler .comment $ ;=======================================================================; ; ; ; B A S I C D I S K - D R I V E R O U T I N E S ; ; ; ; Non-interrupt driven support routines for the SMC diskette chip. ; ; ; ;=======================================================================; ;=======================================================================; ; ; ; D-X Designs Pty. Ltd. Perth, Western Australia ; ; Project: 112 May, 1996 ; ; ; ; Copyright (C) 1996 David R. Brooks ; ; ; ; This program is free software; you can redistribute it and/or ; ; modify it under the terms of the GNU General Public License ; ; as published by the Free Software Foundation; either version 2 ; ; of the License, or (at your option) any later version. ; ; ; ; This program is distributed in the hope that it will be useful, ; ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; ; GNU General Public License for more details. ; ; ; ; You should have received a copy of the GNU General Public License ; ; along with this program; if not, write to the Free Software ; ; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ; ; ; ;=======================================================================; DISKOPQ - Version for BIOS, with FORMAT disabled to save space. This code is designed to work without interrupts (compatible with the ROM bootstrap code). Consequently, timing functions are done by polling and/or delay loops. The DMA is used for data transfer, and is polled for completion (check that the byte counter has decremented to zero). Call: A - OPCODE: 0 - Reset disk system: all drives uncalibrated 1 - Turn motors off (leave drives calibrated) 2 - Read sector/s 3 - Write sector/s 4 - Verify sector/s 5 - Format track 6 - Translate logical address to physical B - No. of sectors to read/write C - Track No. (even tracks are Side 0, odd tracks are Side 1) D - Drive No. (0..3) E - Sector No. HL - Ptr. to data buffer (logical address) IX - Ptr. to Drive Parameter Block (DPB) Return: If successful: CY = 0 A undefined HL advanced past data block If errors: CY = 1 A status (see below) HL unchanged In either case: DE -> Result vector (7 bytes) IX, IY unchanged BC trashed $ Z80182 equ 0 include Z180.INC include DPARM.INC include FDC.INC ;incformat equ 0 ;Define this to include the FORMAT cmnd. .sall dseg ;====================================================================== ; L O C A L D A T A ;Return-error status values (in A, if CY=1) calerr equ 1 ;Error in a recalibration function ioerr equ 2 ;Error posted by Result Phase: see (HL) badsect equ 3 ;Sector/Length will overrun track lostdat equ 4 ;DMA did not transfer full block timeout equ 5 ;Interrupt timed out badcmd equ 6 ;Invalid function code sekerr equ 7 ;Seek error calibd: ds 1 ;Drives "Calibrated" flags mask: ds 1 ;Bit-mask of current drive restab: ds 7 ;Buffer for result-phase data rtcnt: ds 1 ;IO command retry count (after RESTAB) switch: ds 3 ;Builds a JP instruction tries equ 3 ;No. of retries on IO errors blksze: ds 2 ;Save block size cseg ;====================================================================== ; F . D . C . C O M M A N D C O D E S cmd_recal equ 7 ;Recalibrate cmd_sense equ 8 ;Sense Interrupt cmd_seek equ 0fh ;Seek to track cmd_read equ 46h ;Read (MFM, implied seek) cmd_write equ 45h ;Write, ditto cmd_verify equ 56h ;Verify, ditto cmd_format equ 4dh ;Format a track ; D . M . A . C O M M A N D S dma_incmd equ 0cdh ;IO => MEM dma_outcmd equ 0f1h ;MEM => IO dma_run equ 63h ;Kick off Channel-0 ;====================================================================== ; U T I L I T Y S U B R O U T I N E S waitint: ;Wait for interrupt (but polled) push bc push de ld bc,0 ;Inner timeout counters ld d,20 ;Coarse timeout setting w1: in0 a,(drc) ;Get interrupt lines bit 6,a jr z,w2 ;Go if interrupt set dec c jr nz,w1 djnz w1 ;65k loops dec d jr nz,w1 ;Coarse outer loop scf jr w3 ;Exit: timed out w2: xor a ;Exit: OK w3: pop de pop bc ret ;-------------------------------- testresult: ;Check results of I/O operations ; IY -> test-block for status: ; see "launch" for details call waitint ;Wait for completion ld a,timeout jr c,exit ;Failed (CY posted to caller) ;Get 7 result bytes after read/write push bc push de ld de,restab ;Point to Result Table ld b,7 ;No. of expected bytes lc3: call getbyte ld (de),a inc de ;Post it djnz lc3 pop de pop bc ld hl,restab ;Pointer to results block push hl ld a,(hl) and 0f8h ;Kill variable bits (just errors) cp (iy+tst0) ;Check to expected value jr nz,bad inc hl ld a,(hl) cp (iy+tst1) ;Check to expected value jr nz,bad inc hl ld a,(hl) sub 0 ;No "funny" errors (ever!) jr nz,bad in0 l,(bcr0l) in0 a,(bcr0h) or l ;Check that all was transferred pop hl ld a,lostdat jr nz,bad ;Should have counted back to zero xor a ;It all succeeded! jr exit ;OK: return CY=0 (A=0) bad1: ld a,badsect ;Bad sector specification scf jr exit bad: ld a,ioerr ;Error post: see block at (HL) pop hl scf exit: ret ;CY = error ;-------------------------------- sendbyte: ;Send A to Cmnd/data port push af scb1: in0 a,(_MSR) ;Check FDC status bit 7,a ;Wait till ready jr z,scb1 pop af ;Recover the cmnd. byte out0 (_DATA),a ret ;-------------------------------- getbyte: ;Read Cmnd/data port to A in0 a,(_MSR) bit 7,a ;Ready? jr z,getbyte in0 a,(_DATA) ;Get it ret ;-------------------------------- sendcmdstrg: ;Send string of commands from HL push bc ;1st. byte is count ld b,(hl) ;Save count scs1: inc hl ld a,(hl) ;Get cmnd. byte call sendbyte ;Send it djnz scs1 ;Repeat pop bc ret ;-------------------------------- uncal: ;Force a recalibrate on this drive push hl ld hl,calibd ;First force a recalibrate ld a,(mask) cpl and (hl) ;Turn of the "calibrated" bit ld (hl),a pop hl ret ;-------------------------------- dmainput: ;Set up DMA buffers for input call absaddr ;Get physical addr. for DMA out0 (dar0l),l out0 (dar0h),h out0 (dar0b),a ;Destination pointers ld a,_DMA out0 (sar0l),a ;Source: FDC's DMA port xor a out0 (sar0h),a out0 (sar0b),a ;Controlled by /DREQ0 ret ;-------------------------------- dmaoutput: ;Set up DMA buffers for output call absaddr ;Get physical addr. for DMA out0 (sar0l),l out0 (sar0h),h out0 (sar0b),a ;Source pointers ld a,_DMA out0 (dar0l),a ;Destn.: FDC's DMA port xor a out0 (dar0h),a out0 (dar0b),a ;Controlled by /DREQ0 ret ;-------------------------------- ;Offsets for inline arguments opcode equ 0 ;Command to FDC tst0 equ 1 ;Match Status 0 tst1 equ 2 ; " " 1 skip equ 3 ;No. of bytes to skip at return launch: ;Initiate a read or write command ex (sp),iy ;Save IY, point at argts. ld a,e ;Find final sector for transfer add a,b dec a ;Last sector to do dec a ;1 under final cp (ix+EOT) ;This MUST be < true final jr nc,bad1 inc a ;True final sector ld h,a ;Save it ld a,(iy+opcode) call sendbyte ;Command code ld a,d ;Drive bit 0,c ;Odd track (ie Side 1)? jr z,lc1 set 2,a lc1: call sendbyte ;Drive & head ld a,c srl a ;Cylinder call sendbyte ld a,c and 1 call sendbyte ;Head ld a,e call sendbyte ;Sector ld a,(ix+SECSZE) call sendbyte ;Sector length (encoded) ld a,h call sendbyte ;Final sector no. ld a,(ix+GPL) call sendbyte ;Gap length ld a,dma_run ;Activate DMA Ch-0 out0 (dstat),a ld a,0ffh ;Data transfer length (default) call sendbyte ;Final byte: FDC & DMA running call testresult ;Find out what happened push bc push af ld bc,skip add iy,bc ;Jump past the inline params. pop af pop bc ex (sp),iy ;Recover IY, post link ret ;-------------------------------- transze: ;Determine buffer size (DMA count set) push hl push de push bc ld hl,64 ld b,(ix+SECSZE) ;Size N, => 128*2^N inc b tz1: add hl,hl djnz tz1 ld d,h ld e,l ;Sector size in DE ld hl,0 pop bc ;No. of sectors in B push bc tz2: add hl,de ;Form total in HL djnz tz2 out0 (bcr0l),l ;Set DMA counter out0 (bcr0h),h ld (blksze),hl ;Save block size pop bc pop de ;Restore regs. pop hl ret ;-------------------------------- endseek: ;Finish of a seek/recalibrate function call waitint ;Wait for it ld a,timeout ret c ;Timed out ld a,cmd_sense ;"Sense Interrupt" at the end call sendbyte call getbyte ld b,a ;ST0 in B call getbyte ;PCN in A push bc ;Verify correct cylinder srl c cp c ;Yes? pop bc ld a,sekerr scf ret nz ;Quit if unequal ld a,b ;Get back ST0 and 0e0h cp 20h ;Look for success ret z ld a,calerr scf ret ;CY=1 if it failed ;-------------------------------- doron equ 0ch ;Basic state: no drives, no reset, DMA setup: ;Prepare for a Read or Write operation push bc ;Save them... push hl ld b,d ;Drive no. inc b ld a,08h su1: add a,a djnz su1 ;Shift drive bit as reqd. ld (mask),a ;Save drive indicator bit ld b,a ;Local copy in0 a,(_DOR) ld c,a and 0fch ;Kill select bits or d ;Select reqd. drive or doron ;No reset, DMA out0 (_DOR),a ;Selected ld a,c and b ;Is this drive running? jr nz,su2 in0 a,(_DOR) or b ;Start it up out0 (_DOR),a ; Wait for motor to run-up. NB this delay assumes: ; 1. 16MHz CPU clock ; 2. 2 wait states per memory access ; 3. Z-80 instruction cycle-counts ld a,(ix+MTRON) ;Start delay add a,a ;Scale for inner loop ld bc,0 ;Prime for inner loop mo1: djnz mo1 ;17*256 = 4352 clocks dec c ; 6 jr nz,mo1 ; 17 ; ---- ; 4375 clocks ; x 256 ; ------- ; 1,120,000 clocks ; or, 1/16 second dec a jr nz,mo1 ;Full delay su2: ;Send the SPECIFY command (all from DPB) ld a,(ix+DRATE) out0 (_CCR),a ;Data rate as reqd. ld a,03h ;"Specify" call sendbyte ld a,(ix+SPEC_1) call sendbyte ld a,(ix+SPEC_2) res 0,a ;Be sure DMA is activated call sendbyte ld hl,calibd ld a,(mask) and (hl) ;Is this drive calibrated? jr nz,su3 ;Done if so ld a,cmd_recal call sendbyte ;Send the "recal" command ld a,d call sendbyte ;Drive no. call endseek ;Finish the operation jr c,su5 ;Jump if error ld a,(mask) or (hl) ld (hl),a ;Flag it calibrated, now su3: xor a ;Success... su5: and a ;Set the Z bit pop hl pop bc ret ;Done: Z set if OK ;====================================================================== ; C O M M A N D D E S P A T C H E R global diskop diskop: cp maxcmd jr c,do1 ld a,badcmd scf ret ;Illegal command do1: call entry ;Enter the slave routine push af ;Save exit status call c,reset ;If errors, reset the FDC pop af ret c ;If error, take exit code xor a ;If OK, return zero ret ;Back to caller entry: push hl ;Save it ld hl,dtab add a,a ;Scale opcode by 2 add a,l ld l,a ;Access the jumptable jr nc,do2 inc h ;Propagate carry do2: ld a,(hl) ;Look into the table inc hl ld h,(hl) ld l,a ex (sp),hl ;Recover HL: routine ptr. on stack ret ;Switch to routine dtab: ;Pointers to function routines dw reset dw motors dw xread ;I/O functions: call wrappers dw xwrite dw xverf dw xform dw absaddr maxcmd equ ($-dtab)/2 ;No. of valid commands ;====================================================================== ; I / O C O M M A N D W R A P P E R F U N C T I O N ; The READ, WRITE, VERIFY and FORMAT commands are essentially identical. ; The despatcher calls a stub, which sets up a common wrapper to ; run the required sub-function, and to implement re-tries in the ; event of data errors. ; Wrapper stubs. The common tail is called with the user's HL stacked, ; and HL pointing to the required sub-function. jpopc equ 0c3h ;A "JP" opcode xread: push hl ld hl,read ;Sub-function pointer jr comtail xwrite: push hl ld hl,write jr comtail xverf: push hl ld hl,verify jr comtail xform: push hl ld hl,format comtail: ;Common tail of the "wrapper" function ld (switch+1),hl ;Target for the despatcher pop hl ;Caller's value push af ld a,jpopc ld (switch),a ;Complete the "JP" instruction push hl ld hl,0 ld (blksze),hl ;Default value pop hl ld a,tries again: ld (rtcnt),a ;Retry counter pop af push hl call switch ;To the sub-function pop hl ;Save HL (no others changed) jr nc,ok ;Exit: no error cp ioerr ;Was it an IO error? jr z,more cp sekerr ;Or a seek error jr nz,fatal ;No: other errors are fatal more: push af ;Seek or IO errors: retry call uncal ;Reset the "calibrated" bit ld a,(rtcnt) dec a ;Count attempts jr nz,again ;More to go pop af ;Exhausted: get the error code fatal: scf ;Hard errors ld de,restab ;Pass the result pointer ret ok: ld de,(blksze) add hl,de ;Success: index HL past block ld de,restab ;Return DE -> status block ret ;------------------------------- fails: ;Common stub for sub-functions to exit with error scf ret ;====================================================================== ; R E S E T T H E D I S K E T T E S Y S T E M reset: push hl xor a ld (calibd),a ;All drives uncalibrated out0 (_DOR),a ;Force reset ld a,doron out0 (_DOR),a ;All drives off (DMA asserted) ld hl,configtab call sendcmdstrg ;"Configure" xor a ;Post OK pop hl ret configtab: db ecft-$-1 ;Length db 13h ;"Configure" db 00h ;Required db 71h ;No FIFO in use db 43 ;Write precomp point ecft equ $ ;====================================================================== ; T U R N O F F A L L D R I V E - M O T O R S ; This command is really only needed until interrups are supported, ; since it is then possible to automatically turn off a drive which has ; not been accessed for some time. ; This command is used by the elementary BIOS keyboard routine: the ; drives are turned off if the system has waited for keyboard input ; for too long - a simple method! motors: in0 a,(_DOR) and 0fh ;Drop motor lines: keep selection out0 (_DOR),a xor a ;"Success" ret ;====================================================================== ; R E A D O N E O R M O R E S E C T O R S read: call setup ;Drive selected & ready jp nz,fails call dmainput ;Set up DMA pointers for input call transze ;Get total buffer size ld a,dma_incmd out0 (dmode),a ;DMA set up: IO => MEM call launch ;Go fire it off db cmd_read ;Command code db 40h ;Expected ST0 db 80h ;Expected ST1 ret ;CY=fault: HL -> result phase ;====================================================================== ; W R I T E O N E O R M O R E S E C T O R S write: call setup ;Drive selected & ready jp nz,fails call dmaoutput ;Set up DMA pointers for output call transze ;Get total buffer size ld a,dma_outcmd out0 (dmode),a ;DMA set up: MEM => IO call launch ;Go fire it off db cmd_write ;Command code db 40h ;Expected ST0 db 80h ;Expected ST1 ret ;CY=fault: HL -> result phase ;====================================================================== ; V E R I F Y S E C T O R S - N O T R A N S F E R verify: call setup ;Drive selected & ready jp nz,fails call launch ;Go fire it off db cmd_verify ;Command code db 0 ;Expected ST0 db 0 ;Expected ST1 ret ;CY=fault: HL -> result phase ;====================================================================== ; F O R M A T A T R A C K O F T H E D I S K E T T E format: ifdef incformat ;Do we include FORMAT ? call setup ;Drive running, & calibrated jp nz,fails ld a,cmd_seek ;Seek to the required track call sendbyte ;We cannot use "implied seeks" here ld a,d bit 0,c jr z,fm1 set 2,a ;A = drive & head bits fm1: call sendbyte ld a,c srl a ;Cylinder no. call sendbyte call endseek ;Wait for seek to complete ret c ;Failed call dmaoutput ;DMA pointers for output push hl ld l,(ix+EOT) ;No. of sectors ld h,0 add hl,hl add hl,hl ;4 bytes/sector out0 (bcr0l),l out0 (bcr0h),h ;Set up DMA counter ld (blksze),hl pop hl ld a,dma_outcmd out0 (dmode),a ;DMA armed to output ld a,cmd_format ;Now initiate the FDC call sendbyte ld a,d bit 0,c jr z,fm2 set 2,a ;Side select fm2: call sendbyte ;Drive & side ld a,(ix+SECSZE) call sendbyte ;Sector size ld a,(ix+EOT) call sendbyte ;Final sector no. ld a,(ix+GAPFMT) call sendbyte ;Gap-3 length ld a,dma_run out0 (dstat),a ;Kick off the DMA ld a,(ix+DATFMT) call sendbyte ;Last byte: FDC running push iy ld iy,fmtres ;Expected results call testresult ;Wait for it... pop iy ret ;A and CY show result fmtres: db 0 ;Filler db 0 ;ST-0 db 0 ;ST-1 else jp fails ;No FORMAT command endif ;====================================================================== ; C O N V E R T L O G I C A L T O P H Y S I C A L A D D R E S S ; This utility converts a logical address (in HL) to a 20-bit physical ; address (in AHL). Other registers are unchanged. Absolute addresses ; are used by the Z182 DMA. ; The routine accesses the memory-mapping hardware registers, to obtain ; the current translations. ;NB This code assumes that CA1 > BA > CA0 absaddr: ;Converts HL to AHL push hl ld a,h ;First, see which logical bank and 0f0h ld h,a ;Save 4kB page in0 a,(cbar) and 0f0h ;CA1 logical base ld l,a ld a,h sub l ;Form Addr - Base jr c,not1 ;If CY: Addr < Base, so don't use in0 a,(cbr) ;It is CA1 - take base jr mod not1: in0 a,(cbar) add a,a add a,a add a,a add a,a ;BA logical base in A[7:4] ld l,a ld a,h sub l ;Form Addr - Base ld a,0 jr c,mod ;Not BA, must be CA0 in0 a,(bbr) ;Else, it is BA mod: pop hl ;Now do the adjustment push bc ;Save it push hl ;Save HL again ld c,h ld b,0 ;BC = HL >> 8 ld l,a ld h,b ;HL = physical base add hl,hl add hl,hl add hl,hl add hl,hl ;HL = physical base << 4 add hl,bc ;Top address in HL ld a,h and 0fh ;Bits 19:16 in A ld b,l ;Save bits 15:8 pop hl ld h,b ;Full address in AHL pop bc ;Restore BC and a ;CY=0 (ie no errors) ret ;Done end  ld l,a ld h,b ;HL = physical base add hl,hl add hl,hl add hl,hl add hl,hl ;HL = physical base << 4 add hl,bc ;Top address in HL ld a,h and 0fh ;Bits 19:16 in A ld b,l ;Save bits 15:8 pop hl ld h,b ;Full add; Port definitions for the FDC37C665/6 combo chips ; Prefix a "_" as some names clash with Z180 names ; Diskette controller _DOR equ 92h ;Digital Output _MSR equ 94h ;Main Status _DSR equ 94h ;Data-rate Select _DATA equ 95h ;Data & commands I/O _DIR equ 97h ;Digital Input _CCR equ 97h ;Confign. Control _DMA equ 0a0h ;Diskette DMA address ; Serial port ;RD/WR _RBR equ 98h ;R Receiver buffer _THR equ 98h ;W Transmit holding reg. _IER equ 99h ;RW Interrupt-enable reg. _IIR equ 9ah ;R Interrupt ident. reg. _FCR equ 9ah ;W FIFO control reg. _LCR equ 9bh ;RW Line control reg. _MCR equ 9ch ;RW Modem control reg. _LSR equ 9dh ;RW Line status reg. _MMSR equ 9eh ;RW Modem status reg. (name clash w. FDC) _SCR equ 9fh ;N/A Scratch reg. (not avail. in XT) _DDL equ 98h ;RW Divisor LSB | with DLAB _DLM equ 99h ;RW Divisor MSB | set high 9ah ;R Interrupt ident. reg. _FCR equ 9ah ;W FIFO control reg. _LCR equ 9bh ;RW Line control reg. _MCR equ 9ch ;RW Modem control reg. _LSR equ 9dh ;RW Line status reg. _MMSR equ 9eh ;RW Modem status reg. (name clash w. FDC) _SCR equ 9fh ;N/A Scratch reg. (not avail. in XT) _DDL page 90 title BIOS Loader ;===============================================================; ; ; ; B I O S I N S T A L L A T I O N T O D I S K ; ; ; ; D-X Designs Pty. Ltd. Perth, Western Australia ; ; Project: 112 Author: D R Brooks May, 1996 ; ; ; ;===============================================================; ;=======================================================================; ; ; ; D-X Designs Pty. Ltd. Perth, Western Australia ; ; Project: 112 May, 1996 ; ; ; ; Copyright (C) 1996 David R. Brooks ; ; ; ; This program is free software; you can redistribute it and/or ; ; modify it under the terms of the GNU General Public License ; ; as published by the Free Software Foundation; either version 2 ; ; of the License, or (at your option) any later version. ; ; ; ; This program is distributed in the hope that it will be useful, ; ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; ; GNU General Public License for more details. ; ; ; ; You should have received a copy of the GNU General Public License ; ; along with this program; if not, write to the Free Software ; ; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ; ; ; ;=======================================================================; .Comment $ This code is a "stub" which is loaded below the BIOS. It may be executed (via the debugger), and will write BIOS into the proper sectors on the disc. NB This code does NOT write CP/M on the disk. $ Z80182 equ 0 include Z180.INC include DPARM.INC include ASCII.INC include ROMHOOK.INC extrn bios, biostop ;Start & end of code load cseg entry: jp start ;Must be start of code ;------------------------------------------------------------ ; Starting positions on disk for the BIOS load: locn3: db 0, 13 ;Track, sector: 3" disks locn5: db 1, 4 ; ditto 5" disks ;============================================================ ; B I O S I N S T A L L A T I O N T O O L start: gdrv: ld hl,getdrv rst putmsg ;Drive No. call getdig ;Get it jr c,gdrv ;Repeat till good cp 2 ; & in range jr nc,gdrv ld d,a ;Drive in D push de ;Save it gtyp: ld hl,getype rst putmsg ;Drive type call getdig ;Get it jr c,gtyp ld hl,dpb3 ld iy,locn3 cp 3 ;3' drive? jr z,hdv ld hl,dpb5 ld iy,locn5 cp 5 ;Or, 5" ? jr nz,gtyp hdv: ld c,(hl) inc hl ld b,(hl) push bc pop ix ;IX -> DPB ld hl,biostop ;Compute no. of sectors to write ld bc,bios and a sbc hl,bc ;No. of code bytes ld bc,01ffh add hl,bc ;Round up ld b,h srl b ;No. of sectors in B ld hl,bios ;Load base pop de ;Drive in D ld c,(iy+0) ;Track ld e,(iy+1) ;Sector ld a,3 ;"Write" rst diskop ;Go write it jr c,fail ld hl,goodms rst putmsg jr ends fail: push af ld hl,badms rst putmsg pop af add a,'0' ;Make a digit rst putchr ;Send it ends: ld hl,nline rst putmsg ;Final newline ld a,1 ;Turn off drives rst diskop rst break ;To DEBUG when done getdrv: db 'Enter drive No. [0..3]:',0 getype: db 'Enter drive size [3/5]:',0 goodms: db 'Written successfully',0 badms: db 'Write failed: code= ',0 nline: db ascicr,0 ;------------------------------------------------------------- getdig: rst getchr ;Get something and a jr z,getdig ;Wait for it... cp asciesc call z,break ;ESC will abort anything sub '0' ;Else, must be a digit ret c cp 10 ccf push af ld hl,nline call putmsg ;Newline after pop af ret ;Back: CY=1 if invalid ;-------------------------------------------------------------- org entry+0ffh db 0 ;Align BIOS-proper correctly end ,dpbptr-dpbase add hl,bc ;HL -> DPBPTR ld a,e ;Given drive type cp -1 ;Requested? jr nz,dt1 ;This leaves CY=0 ld a,(hl) ;Yes inc hl ld h,(hl) ld l,a ;HL -> Drive Parameter Block push hl pop ix ;IX ditto ld e,(ix-3) ;Drive type ld bc,dpbofs add ix,bc ;Ptr. to hardware params. in IX ret ;Return them dt1: cp ntypes ;Set type: is it valid? ccf ret c ;Out of range push hl pop ix ;IX -> DPBPTR sla e ld d,0 ld hl,typtab add hl,de ;HL -> type ptr. ld a,(hl) inc hl ld h,(hl) ld l,a ;HL -> reqd. parameters or h ;Null pointer? scf ret z ;If so, error ld (ix),l ld (ix+1),h ;OK: set up the DPH pointer and a ret typtab: ;List of ptrs. to valid drive types dw dpblk5 ;D5_360 dw 0 ;D5_120 dw 0 ;D3_720 dw dpblk3 ;D3_144 dw 0 ;D3_288 ;---------------------------------------------------------- ; " O V E R L O A D E D " F U N C T I O N S ; The following are extensions to BIOS. They are invoked by ; calling the cold-boot entry, which has been overloaded after ; boot-up. Pass a function-code in C. ; Codes defined: ; 0 - Reset disk subsystem ; 1 - Return boot-drive no. in A ; 2 - Set Drive D to be of type E. If E = -1, this call ; returns as follows (and changes nothing in BIOS): ; E - currently set type for Drive D ; IX - points to hardware parameter table for Drive D overloads: ld a,c ;Function code in A and a jp z,diskop ;A=0: reset DISKOP dec a jr nz,ov2 ld a,(bootdv) ;A=1: return boot drive no. ret ov2: dec a scf ;Error if A != 2 call z,drivetype ;A=2: Set drive type ret ;---------------------------------------------------------- ; S E C T O R - M A P P I N G F U N C T I O N S ; The 3" drive treats each side as one track, while the 5" drive ; treats the entire "cylinder" as one track. This routine maps ; track & sector for these. ; Get logical address from (hsttrk, hstsec) ; Return physical track in C, sector in E sectrk equ hstspt/2 ;No. of sectors/track (not cyl.) mapsec: ;Generic entry: requires IX -> DPB ld hl,(mapptr) ;Point to slave routine ld bc,(hsttrk) ;C=track, B=sector jp (hl) ;Go to slave function remap5: ;Mapping for 5" disk ld a,b ;Logical sector sla c ;Cylinder => track cp sectrk ;Over 1 physical track? jr c,rm51 sub sectrk ;Yes: adjust down inc c ; & use top side rm51: inc a ;Physical sectors based 1 ld e,a ;Sector in E ret ;Returns physical track in C remap3: ;Mapping for 3" disk inc b ;Sector based 1 ld e,b ;Sector in E ret ;Track already in C $eject bootdv: ds 1 ;Boot-drive number ; not overlayed by boot-code ; localdata: ;BIOS workspace, overlaying thascicr equ 0dh ;ASCII characters ascilf equ 0ah ascibs equ 08h asciht equ 09h asciesc equ 1bh space equ ' ' ascdel equ 7fh .xlist .z80 ; Macros to define the Z-180 extended instructions. ; ; D-X Designs Pty. Ltd. 4/12/95 D. R. Brooks ; ; WARNING! These instructions are NOT supported by ; Z80MU. However the IO instructions are ; necessary to ensure correct access to ; the internal machine registers, which ; fully decode all 16 address bits. ; ; Adapted from Zilog (file 182macro.lib) ; Enhanced to provide conditional definition for the ; following chips (define the appropriate symbol) ; Z80180 Default ; Z80S180 ; Z80181 ; Z80182 ; First, check only one CPU is defined ifdef Z80180 ?test equ 0 ;These will throw a "Multiple endif ; Definition" error if 2 CPU's ifdef Z80S180 ; are defined ?test equ 1 endif ifdef Z80181 ?test equ 2 endif ifdef Z80182 ?test equ 3 endif ;========== Z180 Internal Interrupt Vectors ======== ; The following vectors are offsets from the value ; loaded in IL, the Interrupt Vector Low register. VINT1 equ 0 ;External INT-1 pin VINT2 equ 2 ;External INT-2 pin VPRT0 equ 4 ;Timer 0 VPRT1 equ 6 ;Timer 1 VDMA0 equ 8 ;DMA Ch-0 VDMA1 equ 0ah ;DMA Ch-1 VCSIO equ 0ch ;Clocked serial I/O VASC0 equ 0eh ;Asynch. comms. Ch-0 VASC1 equ 10h ;Asynch. comms. Ch-1 ;========== Z180 System Control Registers ========== ;NB These registers may be relocated to multiples of ; 40H, by setting the IO Control Register (ICR = 3FH) ; The addresses below are valid with ICR=0 (else they ; are offsets from the ICR base value). ;ASCI Registers cntla0 equ 00h ;ASCI Control Reg A Ch0 cntla1 equ 01h ;ASCI Control Reg A Ch1 cntlb0 equ 02h ;ASCI Control Reg B Ch0 cntlb1 equ 03h ;ASCI Control Reg B Ch1 stat0 equ 04h ;ASCI Status Reg Ch0 stat1 equ 05h ;ASCI Status Reg Ch1 tdr0 equ 06h ;ASCI TX Data Reg Ch0 tdr1 equ 07h ;ASCI TX Data Reg Ch1 rdr0 equ 08h ;ASCI RX Data Reg Ch0 rdr1 equ 09h ;ASCI RX Data Reg Ch1 brk0 equ 12h ;Break Control Reg Ch0 brk1 equ 13h ;Break Control reg Ch1 ;CSI/O Registers cntr equ 0ah ;CSI/O Control Reg trdr equ 0bh ;CSI/O TX/RX Data Reg ;Timer Registers tmdr0l equ 0ch ;Timer Data Reg Ch0-Low tmdr0h equ 0dh ;Timer Data Reg Ch0-High rldr0l equ 0eh ;Timer Reload Reg Ch0-Low rldr0h equ 0fh ;Timer Reload Reg Ch0-High tcr equ 10h ;Timer Control Reg tmdr1l equ 14h ;Timer Data Reg Ch1-Low tmdr1h equ 15h ;Timer Data Reg Ch1-High rldr1l equ 16h ;Timer Reload Reg Ch1-Low rldr1h equ 17h ;Timer Reload Reg Ch1-High frc equ 18h ;Free-Running Counter ifdef Z80S180 ccr equ 1fh ;CPU Control Reg endif ;DMA Registers sar0l equ 20h ;DMA Source Addr Reg Ch0-Low sar0h equ 21h ;DMA Source Addr Reg Ch0-High sar0b equ 22h ;DMA Source Addr Reg Ch0-B dar0l equ 23h ;DMA Destn Addr Reg Ch0-Low dar0h equ 24h ;DMA Destn Addr Reg Ch0-High dar0b equ 25h ;DMA Destn Addr Reg Ch0-B bcr0l equ 26h ;DMA Byte Count Reg Ch0-Low bcr0h equ 27h ;DMA Byte Count Reg Ch0-High mar1l equ 28h ;DMA Memory Addr Reg Ch1-Low mar1h equ 29h ;DMA Memory Addr Reg Ch1-High mar1b equ 2ah ;DMA Memory Addr Reg Ch1-B iar1l equ 2bh ;DMA I/O Addr Reg Ch1-Low iar1h equ 2ch ;DMA I/O Addr Reg Ch1-High bcr1l equ 2eh ;DMA Byte Count Reg Ch1-Low bcr1h equ 2fh ;DMA Byte Count Reg Ch1-High dstat equ 30h ;DMA Status Reg dmode equ 31h ;DMA Mode Reg dcntl equ 32h ;DMA/WAIT Control Reg ;System Control Registers il equ 33h ;INT Vector Low Reg itc equ 34h ;INT/TRAP Control Reg rcr equ 36h ;Refresh Control Reg cbr equ 38h ;MMU Common Base Reg bbr equ 39h ;MMU Bank Base Reg cbar equ 3ah ;MMU Common/Bank Area Reg omcr equ 3eh ;Operation Mode Control Reg icr equ 3fh ;I/O Control Reg ifdef Z80181 ;Features unique to Z80181 ;Integral PIO device p1ddr equ 0e0h ;Data Direction Reg 1 p1dp equ 0e1h ;Port 1 Data p2ddr equ 0e2h ;Data Direction Reg 2 p2dp equ 0e3h ;Port 2 Data ;Integral CTC device ctc0 equ 0e4h ;CTC Channel 0 ctc1 equ 0e5h ;CTC Channel 1 ctc2 equ 0e6h ;CTC Channel 2 ctc3 equ 0e7h ;CTC Channel 3 scccr equ 0e8h ;SCC Control Reg sccdr equ 0e9h ;SCC Data Reg ;Chip-select output pins ramubr equ 0eah ;RAM Upper Boundary ramlbr equ 0ebh ;RAM Lower Boundary rombr equ 0ech ;ROM Boundary scr equ 0edh ;System Control Reg endif ifdef Z80182 ;Features unique to Z80182 ccr equ 1fh ;CPU control reg. intype equ 0dfh ;Interrupt edge/pin mux reg. wsgcs equ 0d8h ;Wait-State Generator CS enh182 equ 0d9h ;Z80182 Enhancements Reg pinmux equ 0dfh ;Interrupt Edge/Pin Mux Reg ramubr equ 0e6h ;RAM End Boundary ramlbr equ 0e7h ;RAM Start Boundary rombr equ 0e8h ;ROM Boundary fifoctl equ 0e9h ;FIFO Control Reg rtotc equ 0eah ;RX Time-Out Time Const ttotc equ 0ebh ;TX Time-Out Time Const fcr equ 0ech ;FIFO Register scr equ 0efh ;System Pin Control rbr equ 0f0h ;MIMIC RX Buffer Reg thr equ 0f0h ;MIMIC TX Holding Reg ier equ 0f1h ;Interrupt Enable Reg lcr equ 0f3h ;Line Control Reg mcr equ 0f4h ;Modem Control Reg lsr equ 0f5h ;Line Status Reg msr equ 0f6h ;Modem Status Reg mscr equ 0f7h ;MIMIC Scratch Reg dlatl equ 0f8h ;Divisor latch LS dlatm equ 0f9h ;Divisor latch MS ttcr equ 0fah ;TX Time Constant rtcr equ 0fbh ;RX Time Constant ivec equ 0fch ;MIMIC Interrupt Vector mimie equ 0fdh ;MIMIC Interrupt Enable Reg iusip equ 0feh ;MIMIC Interrupt Under-Service Reg mmcr equ 0ffh ;MIMIC Master Control Reg ;Z80182 PIO Registers ddra equ 0edh ;Data Direction Reg A dra equ 0eeh ;Port A Data ddrb equ 0e4h ;Data Direction Reg B drb equ 0e5h ;Port B Data ddrc equ 0ddh ;Data Direction Reg C drc equ 0deh ;Port C data ;ESCC Registers sccacnt equ 0e0h ;ESCC Control Channel A sccad equ 0e1h ;ESCC Data Channel A sccbcnt equ 0e2h ;ESCC Control Channel B sccbd equ 0e3h ;ESCC Data Channel B endif ;[E]SCC Internal Register Definitions RR0 equ 00h RR1 equ 01h RR2 equ 02h RR3 equ 03h RR6 equ 06h RR7 equ 07h RR10 equ 0ah RR12 equ 0ch RR13 equ 0dh RR15 equ 0fh WR0 equ 00h WR1 equ 01h WR2 equ 02h WR3 equ 03h WR4 equ 04h WR5 equ 05h WR6 equ 06h WR7 equ 07h WR9 equ 09h WR10 equ 0ah WR11 equ 0bh WR12 equ 0ch WR13 equ 0dh WR14 equ 0eh WR15 equ 0fh ;==== Define the additional Z-180 instructions ===== ;Machine registers (internal use only) ?b equ 0 ?c equ 1 ?d equ 2 ?e equ 3 ?h equ 4 ?l equ 5 ?a equ 7 ??bc equ 0 ??de equ 1 ??hl equ 2 ??sp equ 3 slp macro db 0edh db 76h endm mlt macro ?r db 0edh db 4ch+(??&?r AND 3) SHL 4 endm in0 macro ?r, ?p db 0edh db 0+(?&?r AND 7) SHL 3 db ?p endm out0 macro ?p, ?r db 0edh db 1+(?&?r AND 7) SHL 3 db ?p endm otim macro db 0edh db 83h endm otimr macro db 0edh db 93h endm otdm macro db 0edh db 8bh endm otdmr macro db 0edh db 9bh endm tstio macro ?p db 0edh db 74h db ?p endm tst macro ?r db 0edh ifidn ,<(hl)> db 34h else ifdef ?&?r db 4+(?&?r AND 7) SHL 3 else db 64h db ?r endif endif endm .list  macro db 0edh db 9bh endm tstio macro ?p db 0edh db 74h db ?p endm tst macro ?r db 0edh ifidn ,<(hl)> db 34h else ifdef ?&?r db 4+(?&?r AND 7) SHL 3 else db 64h db ?r endif endif endm .li.xlist .z80 ; Macros to define the Z-180 extended instructions. ; ; D-X Designs Pty. Ltd. 4/12/95 D. R. Brooks ; ; WARNING! These instructions are NOT supported by ; Z80MU. However the IO instructions are ; necessary to ensure correct access to ; the internal machine registers, which ; fully decode all 16 address bits. ; ; Adapted from Zilog (file 182macro.lib) ; Enhanced to provide conditional definition for the ; following chips (define the appropriate symbol) ; Z80180 Default ; Z80S180 ; Z80181 ; Z80182 ; First, check only one CPU is defined ifdef Z80180 ?test equ 0 ;These will throw a "Multiple endif ; Definition" error if 2 CPU's ifdef Z80S180 ; are defined ?test equ 1 endif ifdef Z80181 ?test equ 2 endif ifdef Z80182 ?test equ 3 endif ;========== Z180 Internal Interrupt Vectors ======== ; The following vectors are offsets from the value ; loaded in IL, the Interrupt Vector Low register. VINT1 equ 0 ;External INT-1 pin VINT2 equ 2 ;External INT-2 pin VPRT0 equ 4 ;Timer 0 VPRT1 equ 6 ;Timer 1 VDMA0 equ 8 ;DMA Ch-0 VDMA1 equ 0ah ;DMA Ch-1 VCSIO equ 0ch ;Clocked serial I/O VASC0 equ 0eh ;Asynch. comms. Ch-0 VASC1 equ 10h ;Asynch. comms. Ch-1 ;========== Z180 System Control Registers ========== ;NB These registers may be relocated to multiples of ; 40H, by setting the IO Control Register (ICR = 3FH) ; The addresses below are valid with ICR=0 (else they ; are offsets from the ICR base value). ;ASCI Registers cntla0 equ 00h ;ASCI Control Reg A Ch0 cntla1 equ 01h ;ASCI Control Reg A Ch1 cntlb0 equ 02h ;ASCI Control Reg B Ch0 cntlb1 equ 03h ;ASCI Control Reg B Ch1 stat0 equ 04h ;ASCI Status Reg Ch0 stat1 equ 05h ;ASCI Status Reg Ch1 tdr0 equ 06h ;ASCI TX Data Reg Ch0 tdr1 equ 07h ;ASCI TX Data Reg Ch1 rdr0 equ 08h ;ASCI RX Data Reg Ch0 rdr1 equ 09h ;ASCI RX Data Reg Ch1 brk0 equ 12h ;Break Control Reg Ch0 brk1 equ 13h ;Break Control reg Ch1 ;CSI/O Registers cntr equ 0ah ;CSI/O Control Reg trdr equ 0bh ;CSI/O TX/RX Data Reg ;Timer Registers tmdr0l equ 0ch ;Timer Data Reg Ch0-Low tmdr0h equ 0dh ;Timer Data Reg Ch0-High rldr0l equ 0eh ;Timer Reload Reg Ch0-Low rldr0h equ 0fh ;Timer Reload Reg Ch0-High tcr equ 10h ;Timer Control Reg tmdr1l equ 14h ;Timer Data Reg Ch1-Low tmdr1h equ 15h ;Timer Data Reg Ch1-High rldr1l equ 16h ;Timer Reload Reg Ch1-Low rldr1h equ 17h ;Timer Reload Reg Ch1-High frc equ 18h ;Free-Running Counter ifdef Z80S180 ccr equ 1fh ;CPU Control Reg endif ;DMA Registers sar0l equ 20h ;DMA Source Addr Reg Ch0-Low sar0h equ 21h ;DMA Source Addr Reg Ch0-High sar0b equ 22h ;DMA Source Addr Reg Ch0-B dar0l equ 23h ;DMA Destn Addr Reg Ch0-Low dar0h equ 24h ;DMA Destn Addr Reg Ch0-High dar0b equ 25h ;DMA Destn Addr Reg Ch0-B bcr0l equ 26h ;DMA Byte Count Reg Ch0-Low bcr0h equ 27h ;DMA Byte Count Reg Ch0-High mar1l equ 28h ;DMA Memory Addr Reg Ch1-Low mar1h equ 29h ;DMA Memory Addr Reg Ch1-High mar1b equ 2ah ;DMA Memory Addr Reg Ch1-B iar1l equ 2bh ;DMA I/O Addr Reg Ch1-Low iar1h equ 2ch ;DMA I/O Addr Reg Ch1-High bcr1l equ 2eh ;DMA Byte Count Reg Ch1-Low bcr1h equ 2fh ;DMA Byte Count Reg Ch1-High dstat equ 30h ;DMA Status Reg dmode equ 31h ;DMA Mode Reg dcntl equ 32h ;DMA/WAIT Control Reg ;System Control Registers il equ 33h ;INT Vector Low Reg itc equ 34h ;INT/TRAP Control Reg rcr equ 36h ;Refresh Control Reg cbr equ 38h ;MMU Common Base Reg bbr equ 39h ;MMU Bank Base Reg cbar equ 3ah ;MMU Common/Bank Area Reg omcr equ 3eh ;Operation Mode Control Reg icr equ 3fh ;I/O Control Reg ifdef Z80181 ;Features unique to Z80181 ;Integral PIO device p1ddr equ 0e0h ;Data Direction Reg 1 p1dp equ 0e1h ;Port 1 Data p2ddr equ 0e2h ;Data Direction Reg 2 p2dp equ 0e3h ;Port 2 Data ;Integral CTC device ctc0 equ 0e4h ;CTC Channel 0 ctc1 equ 0e5h ;CTC Channel 1 ctc2 equ 0e6h ;CTC Channel 2 ctc3 equ 0e7h ;CTC Channel 3 scccr equ 0e8h ;SCC Control Reg sccdr equ 0e9h ;SCC Data Reg ;Chip-select output pins ramubr equ 0eah ;RAM Upper Boundary ramlbr equ 0ebh ;RAM Lower Boundary rombr equ 0ech ;ROM Boundary scr equ 0edh ;System Control Reg endif ifdef Z80182 ;Features unique to Z80182 ccr equ 1fh ;CPU control reg. intype equ 0dfh ;Interrupt edge/pin mux reg. wsgcs equ 0d8h ;Wait-State Generator CS enh182 equ 0d9h ;Z80182 Enhancements Reg pinmux equ 0dfh ;Interrupt Edge/Pin Mux Reg ramubr equ 0e6h ;RAM End Boundary ramlbr equ 0e7h ;RAM Start Boundary rombr equ 0e8h ;ROM Boundary fifoctl equ 0e9h ;FIFO Control Reg rtotc equ 0eah ;RX Time-Out Time Const ttotc equ 0ebh ;TX Time-Out Time Const fcr equ 0ech ;FIFO Register scr equ 0efh ;System Pin Control rbr equ 0f0h ;MIMIC RX Buffer Reg thr equ 0f0h ;MIMIC TX Holding Reg ier equ 0f1h ;Interrupt Enable Reg lcr equ 0f3h ;Line Control Reg mcr equ 0f4h ;Modem Control Reg lsr equ 0f5h ;Line Status Reg msr equ 0f6h ;Modem Status Reg mscr equ 0f7h ;MIMIC Scratch Reg dlatl equ 0f8h ;Divisor latch LS dlatm equ 0f9h ;Divisor latch MS ttcr equ 0fah ;TX Time Constant rtcr equ 0fbh ;RX Time Constant ivec equ 0fch ;MIMIC Interrupt Vector mimie equ 0fdh ;MIMIC Interrupt Enable Reg iusip equ 0feh ;MIMIC Interrupt Under-Service Reg mmcr equ 0ffh ;MIMIC Master Control Reg ;Z80182 PIO Registers ddra equ 0edh ;Data Direction Reg A dra equ 0eeh ;Port A Data ddrb equ 0e4h ;Data Direction Reg B drb equ 0e5h ;Port B Data ddrc equ 0ddh ;Data Direction Reg C drc equ 0deh ;Port C data ;ESCC Registers sccacnt equ 0e0h ;ESCC Control Channel A sccad equ 0e1h ;ESCC Data Channel A sccbcnt equ 0e2h ;ESCC Control Channel B sccbd equ 0e3h ;ESCC Data Channel B endif ;[E]SCC Internal Register Definitions RR0 equ 00h RR1 equ 01h RR2 equ 02h RR3 equ 03h RR6 equ 06h RR7 equ 07h RR10 equ 0ah RR12 equ 0ch RR13 equ 0dh RR15 equ 0fh WR0 equ 00h WR1 equ 01h WR2 equ 02h WR3 equ 03h WR4 equ 04h WR5 equ 05h WR6 equ 06h WR7 equ 07h WR9 equ 09h WR10 equ 0ah WR11 equ 0bh WR12 equ 0ch WR13 equ 0dh WR14 equ 0eh WR15 equ 0fh ;==== Define the additional Z-180 instructions ===== ;Machine registers (internal use only) ?b equ 0 ?c equ 1 ?d equ 2 ?e equ 3 ?h equ 4 ?l equ 5 ?a equ 7 ??bc equ 0 ??de equ 1 ??hl equ 2 ??sp equ 3 slp macro db 0edh db 76h endm mlt macro ?r db 0edh db 4ch+(??&?r AND 3) SHL 4 endm in0 macro ?r, ?p db 0edh db 0+(?&?r AND 7) SHL 3 db ?p endm out0 macro ?p, ?r db 0edh db 1+(?&?r AND 7) SHL 3 db ?p endm otim macro db 0edh db 83h endm otimr macro db 0edh db 93h endm otdm macro db 0edh db 8bh endm otdmr macro db 0edh db 9bh endm tstio macro ?p db 0edh db 74h db ?p endm tst macro ?r db 0edh ifidn ,<(hl)> db 34h else ifdef ?&?r db 4+(?&?r AND 7) SHL 3 else db 64h db ?r endif endif endm .list  macro db 0edh db 9bh endm tstio macro ?p db 0edh db 74h db ?p endm tst macro ?r db 0edh ifidn ,<(hl)> db 34h else ifdef ?&?r db 4+(?&?r AND 7) SHL 3 else db 64h db ?r endif endif endm .li;Standard drive-parameter block ; Format is same as MS-DOS BIOS SPEC_1 equ 0 ;"Specify" byte 1 SPEC_2 equ 1 ;"Specify" byte 2 MTROFF equ 2 ;Wait before stop motor SECSZE equ 3 ;Bytes/sector (must be > 0) EOT equ 4 ;Final sector no. GPL equ 5 ;Gap length DTL equ 6 ;Data transfer length GAPFMT equ 7 ;Gap-3 length: Format DATFMT equ 8 ;Data fill: Format SETTLE equ 9 ;Head-settle time (mS) MTRON equ 10 ;Motor-start (* 1/8 sec.) MAXCYL equ 11 ;Max. cylinder no. DRATE equ 12 ;Data rate  EOT equ 4 ;Final sector no. GPL equ 5 ;Gap length DTL equ 6 ;Data transfer length GAPFMT equ 7 ;Gap-3 length: Format DATFMT equ 8 ;Data fill: Format SETTLE equ 9 ;Head-settle ; Standard drive-type identifiers ntypes equ 5 ;No. of defined types D5_360 equ 0 ;5", 360kB D5_120 equ 1 ;5", 1.2MB D3_720 equ 2 ;3", 720kB D3_144 equ 3 ;3", 1.44MB D3_288 equ 4 ;3", 2.88MB ROMHOOK INCpBIOS HEX,qrsBIOS MACtuvwxyz{BIOS MAC5|}~BIOS SUBBIOSTOP MACDPARM INCDRVTYPE INCascicr equ 0dh ;ASCII characters ascilf equ 0ah ascibs equ 08h asciht equ 09h asciesc equ 1bh space equ ' ' ascdel equ 7fh .comment $ R O M - M O N I T O R E X T E R N A L H O O K S Definitions of code-hooks for external entry to the ROM. These are intended for use by OS boot-sectors, etc. They MUST NOT be used by BIOS and similar code, since the ROM will be disabled. The symbolic names are those used in the ROM code for these routines. $ diskop equ 8 ;JP to diskette handler dpb3 equ diskop+3 ;Ptr. to 3" D.P.B. dpb5 equ dpb3+2 ;Ptr. to 5" D.P.B. getchr equ 10h ;Read console to A (or 0) putchr equ 18h ;Output A on console putmsg equ 20h ;Output ASCIIZ (HL) on console break equ 38h ;ROM breakpoint trap ;----------------------------------------------------------------------- ill be disabled. The symbolic names are those used in the ROM code for these routines. $ diskop equ 8 ;JP to diskette handler dpb3 equ diskop+3 ;Ptr. to 3" D.P.B. dpb5 equ dpb3+2 ;Ptr. to 5" D.P.B. getchr equ 10h ;Read console to A :20800000CD0A8000E00F00C300F6FDE1FD4602FD6E00FD6601D50E001E02DD7E04B8301510 :20802000C53E02DD460405C5D5CFD1C1DA7780F190470C1E013E02CFF5383CF1D13EC0ED2B :20804000393A21000001401F757EBD2008EDA1EA4880C307803EC8ED393A215F80E7C9466E :2080600061696C65642074657374696E67206C6F772052414D0D00C1C1217E80E7C945725C :20808000726F722072656164696E67204F7065726174696E672053797374656D0D00000018 :2080A0000000000000000000000000000000000000000000000000000000000000000000C0 :2080C0000000000000000000000000000000000000000000000000000000000000000000A0 :2080E000000000000000000000000000000000000000000000000000000000000000000080 :2081000000000000000000000000000000000000000000000000000000000000000000005F :2081200000000000000000000000000000000000000000000000000000000000000000003F :2081400000000000000000000000000000000000000000000000000000000000000000001F :208160000000000000000000000000000000000000000000000000000000000000000000FF :208180000000000000000000000000000000000000000000000000000000000000000000DF :2081A0000000000000000000000000000000000000000000000000000000000000000000BF :2081C00000000000000000000000000000000000000000000000000000000000000000009F :2081E00000000000000000000000000000000000000000000000000000000000000000007F :20820000216482E7CDBF8238F7FE0230F357D5217C82E7CDBF8238F7210B00FE0328072124 :208220000D00FE0520E94E2346C5DDE121008001FF01AF86EDA1EA3382ED4432FF81D12112 :2082400000803E0306010E001E01CF3806219482E71809F521A982E7F1C630DF21BD82E7A8 :208260003E01CFFF456E746572206472697665204E6F2E205B302E2E335D3A00456E746551 :20828000722064726976652073697A65205B332F355D3A005772697474656E2073756363F3 :2082A00065737366756C6C79005772697465206661696C65643A20636F64653D000D00D7A1 :1782C000A728FCFE1BCC3800D630D8FE0A3FF521BD82CD2000F1C99E :00000001FF DBF8238F7210B00FE0328072124 :208220000D00FE0520E94E2346C5DDE121008001FF01AF86EDA1EA3382ED4432FF81D12112 :2082400000803E0306010E001E01CF3806219482E71809F521A982E7F1C630DF21BD82E7A8 :208260003E01CFFF456E746572206472697665204E6F2E205B302E2E335D3A00456E7465 page 90 title P112 OS Boot Sector ;===============================================================; ; ; ; B O O T - S E C T O R C O D E ; ; ; ;===============================================================; ;=======================================================================; ; ; ; D-X Designs Pty. Ltd. Perth, Western Australia ; ; Project: 112 May, 1996 ; ; ; ; Copyright (C) 1996 David R. Brooks ; ; ; ; This program is free software; you can redistribute it and/or ; ; modify it under the terms of the GNU General Public License ; ; as published by the Free Software Foundation; either version 2 ; ; of the License, or (at your option) any later version. ; ; ; ; This program is distributed in the hope that it will be useful, ; ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; ; GNU General Public License for more details. ; ; ; ; You should have received a copy of the GNU General Public License ; ; along with this program; if not, write to the Free Software ; ; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ; ; ; ;=======================================================================; .Comment $ Boot-sector code. This is loaded & executed at 8000H. The incoming machine state is: IX - Points to hardware DPB for boot drive D - Boot drive no. E - Boot-drive type-code SP - Valid stack-frame The stack is valid, however it should be used with care: being in high memory, it MAY be overwritten as CP/M loads (usually not: it is in the blank data area). This routine need not post error messages: a simple Return will generate one. Boot sectors are sumchecked. The 8-bit sum over all 512 bytes must be zero, else the ROM will not run this code. (As a test-aid, a sumcheck generator is included). The boot-drive number is passed in D as a parameter to BIOS, which should remember to re-boot from it. This code's final task before triggering BIOS, is to re-map memory, & kill the ROM. The code assumes a physical disk sector of 512 bytes. ------------------------------------------------------------------------- If the "testing" variable is defined, the code will return to the ROM after loading the OS, but before relocating it. The OS image may be examined in memory. The test-code includes a hook at Bootsec + 1F0. A jump to this will disable the ROM, and jump to BIOS (ie will complete the transfer of control to CP/M. ------------------------------------------------------------------------- Above the boot-sector code (ie 512 bytes on), is a utility (intended to be run from the ROM debugger) which will compute a correct sumcheck, then write the boot code. $ Z80182 equ 0 include Z180.INC include DPARM.INC include ASCII.INC include ROMHOOK.INC ;testing equ 0 ;Define to stop after loading OS ramon equ 0c0h ;Value to disable ROM (for MMU) ramoff equ 0c8h ;Value to restore ROM if error ;Offsets in standard header, below ldbase equ 0 ;Final OS load address nsects equ 2 ;No. of sectors to load ;======================================================================= ; ; Standard boot-sector header. This only need be changed in most cases, ; to accommodate different load configurations. ; ;======================================================================= cseg begsec: ;Start of boot-code call start ;Mark: & pass header ;Control Area: offset from IY dw 0e000h ;0 Load base dw 15 ;2 No. of sectors to load trig: jp 0f600h ;4 Jump to OS start ;======================================================================= start: ifdef testing push de ld hl,signon rst putmsg ;Sign-on msg. pop de endif pop iy ;IY -> controls, as above ld b,(iy+nsects) ;No. of 512-byte sectors reqd. ld l,(iy+ldbase) ld h,(iy+ldbase+1) ;Load addess ; Code fragment to boot in CP/M, allowing for 1 or 2 system tracks. ; On entry, D = Drive ; E = Drive-type code (for BIOS) ; B = Total sectors reqd. ; IX -> DPB ; HL -> Load-base push de ld c,0 ;First system track ld e,2 ;After boot sector ld a,(ix+EOT) ;Final sector, this track cp b ;Is that enough? jr nc,onetrk push bc ;Save total sectors ld a,2 ;No: read an extra track ld b,(ix+EOT) ;Sectors on this track dec b ;Skipping the first push bc push de rst diskop ;Read 1st track pop de pop bc jp c,flt ;Errors pop af ;Total sectors reqd. (B -> A) sub b ;Less those already read ld b,a inc c ;Next track ld e,1 ;Start at the beginning onetrk: ld a,2 ;"Read" last/only track rst diskop push af ;Keep it in balance jr c,flt ;Errors pop af pop de ;Drive & type for BIOS ;Loaded OK: Kill the ROM ld a,ramon out0 (cbar),a ;Now check we have set up the RAM ld hl,0 ld bc,8000 ts: ld (hl),l ld a,(hl) cp l ;Read it OK? jr nz,bad cpi ;HL++, BC--, set P/V jp pe,ts ifdef testing ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ld a,ramoff out0 (cbar),a ;Test: put ROM back ld hl,trapms ;Report rst putmsg ret ; & back to ROM trapms: db 'Load halted for testing',ascicr,0 signon: db 'Running boot sector',ascicr,0 endif ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< jp trig ;OK: go run the OS bad: ld a,ramoff ;RAM test failed: ROM again out0 (cbar),a ld hl,badram rst putmsg ret ;Back to ROM badram: db 'Failed testing low RAM',ascicr,0 ;------------------------------------------------------- flt: ;Load failure pop bc ;Balance stack (discard) pop bc ;Up 2 levels ld hl,ldfld rst putmsg ret ;Back to ROM ldfld: db 'Error reading Operating System',ascicr,0 ;============================================================ ifdef testing ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< org begsec+1f0h ld a,ramon out0 (cbar),a ;Kill the ROM jp trig ;Go run BIOS endif ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ;============================================================ ; B O O T - S E C T O R I N S T A L L A T I O N org begsec+200h ;Load beyond the boot sector sumloc equ begsec+1ffh ;Sumcheck locn. gdrv: ld hl,getdrv rst putmsg ;Drive No. call getdig ;Get it jr c,gdrv ;Repeat till good cp 2 ; & in range jr nc,gdrv ld d,a ;Drive in D push de ;Save it gtyp: ld hl,getype rst putmsg ;Drive type call getdig ;Get it jr c,gtyp ld hl,dpb3 cp 3 ;3' drive? jr z,hdv ld hl,dpb5 cp 5 ;Or, 5" ? jr nz,gtyp hdv: ld c,(hl) inc hl ld b,(hl) push bc pop ix ;IX -> DPB ;Compute & place sumcheck ld hl,begsec ;Sumcheck the boot sector ld bc,1ffh ;Length loaded (excl. sum) xor a slp: add a,(hl) ;Run the check cpi ;HL++, BC--, set P/V jp pe,slp ;All neg ;Negate all this ld (sumloc),a ;Place sum pop de ;Got drive back ld hl,begsec ;Set up to write ld a,3 ;"Write" ld b,1 ;1 sector ld c,0 ;Track 0 ld e,1 ;1st sector rst diskop ;Go write it jr c,fail ld hl,goodms rst putmsg jr ends fail: push af ld hl,badms rst putmsg pop af add a,'0' ;Make a digit rst putchr ;Send it ends: ld hl,nline rst putmsg ;Final newline ld a,1 ;Turn off drives rst diskop rst break ;To DEBUG when done getdrv: db 'Enter drive No. [0..3]:',0 getype: db 'Enter drive size [3/5]:',0 goodms: db 'Written successfully',0 badms: db 'Write failed: code=',0 nline: db ascicr,0 ;------------------------------------------------------------- getdig: rst getchr ;Get something and a jr z,getdig ;Wait for it... cp asciesc call z,break ;ESC will abort anything sub '0' ;Else, must be a digit ret c cp 10 ccf push af ld hl,nline call putmsg ;Newline after pop af ret ;Back: CY=1 if invalid end m80 bootsec,bootsec=bootsec l80 /p:8000,/d:8400,bootsec,bootsec/n:p/y/x/e README TXTASCII INCZ180 INCEZ180 INCEDPARM INCDRVTYPE INCASCII INCROMHOOK INCBOOTSEC HEXBOOTSEC MAC@BOOTSEC SUB CP/M boot sector for the P112 boards. This code is loaded on Track 0, Sector 1 of a bootable disk. It is loaded by the ROM at locn. 8000H (the lowest RAM location accessible from the ROM). This code will load CP/M and BIOS from the remainder of the system track. The code is very short: all IO is handled by ROM services. The BIOS code is designed not to overload the top 200H RAM locations, which are used by the ROM code. This ensures that the ROM remains usable after CP/M is loaded, and can resume control if errors occur in the loading. Once CP/M is successfully loaded, the Z80182 memory map is altered to disable the ROM, and substitute the lower 32kB of RAM. The entire 64kB logical space is now filled with RAM. From this point on, ROM services are unavailable. Following the boot-sector code itself, is a self-loader. If the entire .HEX file is loaded into RAM using the ROM's "hex upload" function, a GO to locn. 8200H will execute this loader, which will copy the boot-sector code onto a disk. ered to disable the ROM, and substitute the lower 32kB of RAM. The entire 64kB logical space is now filled with RAM. From this point on, ROM services are unavailable. Following the boot-sector code itself, is a self-loader. If the entire .HEX file is loaded into RAM using the ROM's "hex upload" function, a GO to locn. 8200H will execute this loader, which will copy the .xlist .sall ; ; Macros for CCP+, DOS+. Intel mnemnonics, z80 opcodes ; Needed with M80, not necessary with SLRMAC. Allows slight ; source revision to assemble with MAC and RMAC also. a equ 7 b equ 0 c equ 1 d equ 2 e equ 3 h equ 4 l equ 5 m equ 6 ; pushix macro db 0ddh,0e5h endm popix macro db 0ddh,0e1h endm pushiy macro db 0fdh,0e5h endm popiy macro db 0fdh,0e1h endm inxix macro db 0ddh,023h endm dcxix macro db 0ddh,02bh endm jrc macro where db 038h db where-$-1 endm jr macro where db 018h db where-$-1 endm jrz macro where db 028h db where-$-1 endm jrnc macro where db 030h db where-$-1 endm jrnz macro where db 020h db where-$-1 endm djnz macro where db 010h db where-$-1 endm bit macro num,reg db 0cbh,040h + num shl 3 + reg endm res macro num,reg db 0cbh,080h + reg + num shl 3 endm bitx macro num,disp db 0ddh,0cbh,disp,046h+num shl 3 endm setx macro num,disp db 0ddh,0cbh,disp,0c6h+num shl 3 endm resx macro num,disp db 0ddh,0cbh,disp,086h+num shl 3 endm bity macro num,disp db 0fdh,0cbh,disp,046h+num shl 3 endm sety macro num,disp db 0fdh,0cbh,disp,0c6h+num shl 3 endm resy macro num,disp db 0fdh,0cbh,disp,086h+num shl 3 endm ldx macro reg,disp db 0ddh mov reg,m db disp endm stx macro reg,disp db 0ddh mov m,reg db disp endm ldy macro reg,disp db 0fdh mov reg,m db disp endm sty macro reg,disp db 0fdh mov m,reg db disp endm andx macro disp db 0ddh ana m db disp endm subx macro disp db 0ddh sub m db disp endm sbcx macro disp db 0ddh sbb m db disp endm cmpx macro disp db 0ddh cmp m db disp endm inrx macro disp db 0ddh inr m db disp endm xorx macro disp db 0ddh xra m db disp endm lbcd macro addr db 0edh,04bh dw addr endm sbcd macro addr db 0edh,043h dw addr endm lded macro addr db 0edh,05bh dw addr endm sded macro addr db 0edh,053h dw addr endm lspd macro addr db 0edh,07bh dw addr endm sspd macro addr db 0edh,073h dw addr endm lixd macro addr db 0ddh lhld addr endm sixd macro addr db 0ddh shld addr endm ldir macro db 0edh,0b0h endm ralr macro reg db 0cbh,010h+reg endm rarr macro reg db 0cbh,018h+reg endm slar macro reg db 0cbh,020h+reg endm srlr macro reg db 0cbh,038h+reg endm dsbc macro reg db 0edh,042h+reg shl 3 endm .list  page 90 title CCP+ v2.2 (c) by C.B Falconer (1986 Oct. 27) ; ; Z80 cpu required. Use CCPLUS 1.7 for 8080/8085 ; ; SEE CCP+.DOC for features, etc. Assembles as is with M80 or SLRMAC. ; For M80 Z80.LIB must be available and must rename source 'CCPLUS'. ; ; 2.2 86/10/27. Search suppression for DOS+ use. Added KILL command ; to abort submit/job operations. CCP+ knows how executed. cbf ; 2.1 86/10/11 Fixed so "-b:xyz name" executes name in b:xyz.lbr ; (with CCPXTEND mounted). Was aborting. Added non-wheel drive ; access checks. Commands suppressed under wheel now search for ; transients, and transient execution is non-suppressable. Now a ; du consisting of ":" alone specifies default. Fixed REN. cbf ; 2.0 86/10/2 Preliminary beta test release. Complete rewrite of 1.7 ; cseg ccpver equ 22; UPDATE with each revision true equ -1 false equ not true debug equ false; true allows linking to existing code cr equ 0dh lf equ 0ah tab equ 09h eof equ 01ah ; ; User configurable values. See patch area at end. doupsft equ true; FALSE for NO command line upshift ; at initialization. subuser equ 0; User # for $$$.sub files maxuser equ 31; Max user when wheel set whluser equ 13; Max user when wheel not set dcols equ 5; columns for directory display ; END user options ; ; For M80 the following must be upper case. INCLUDE Z80.LIB ; ; CPM/DOS+ syscall values @cin equ 1 @cout equ 2 @instg equ 10 @csta equ 11 @rsdsk equ 13 @seldk equ 14 @fopen equ 15 @fclose equ 16 @srch1 equ 17 @srchn equ 18 @fpurg equ 19 @rdseq equ 20 @wtseq equ 21 @fnew equ 22 @frenm equ 23 @curdk equ 25 @stdma equ 26 @usrcd equ 32 ; ; CPM/DOS+ definitions reboot equ 0 iobyte equ reboot+3 defdu equ reboot+4; user/drive fields if debug; link separately extrn sysfnc else sysfnc equ reboot+5; connector to BDOS system endif defcbk equ reboot+05ch defdma equ reboot+080h tpa equ reboot+100h ; ; Macros tdig macro rlc rlc rlc rlc endm ; ; --------- Start ---------- ; ; Standard entry points. The "cold" entry is auto-patched to "both" ; at initial execution, for single sign-on and to cater to peculiar ; Osborne 1 peculiar cold boot mechanism. begin: jmp cold; execute command jmp warm; clear command line ; ; This MUST start at begin+6 for compatability. ibfsiz: db 126; size of input buffer. space for eol mark. ; 127 can cause obscure problems. ; set the following byte 0 for no cold start default command ibflen: db 0; patch command length for cold execution ; and install command below, 0 terminator ; ; For Osborne 1, do not modify. Result won't boot iobuff: dw 0,0,0,0,0,0,0; needed for OS1 autoboot. Why? db ' CCP+ v', ccpver/10 + '0', '.', ccpver MOD 10 + '0' db ' (C) 1986, C.B. Falconer,' db ' Tel. (203) 281-1438,' db ' 680 Hartford Tpk., Hamden, CT., USA' ds 136-($-begin),0; must have 2 spare bytes here. ; nofmsg: db 'No File',0 fulmsg: db 'No room',0 allmsg: db 'All (y/N)?',0 foldms: db 'File exists',0 dnmsg: db 'No ' upmsg: db 'UPSHIFT',0 ; ; Check for valid drive access. Carry if drive (a) invalid. ; entry (a) = 0 is default, always valid, 1, 2.. for A, B.. ; a,f,h,l drvchk: lhld whlmsk ; " " ; Entry here can check against mask hl (usually drvmsk) ; a,f,h,l drvckw: ora a rz dcr a ; " " ; move bit (a) of hl to carry. 0 is lsb, 15 is msb ; a,f,h,l bitmsk: sui 16 bitm1: dad h; left shift 16-n times inr a jrnz bitm1 ret ; ; Upshift (a) if lower case alpha. ; a,f upshft: cpi 'a' rc cpi 'z'+1 rnc ani 05fh ret ; ; Check (a) valid digit, carry if not ; f qnum: cpi '0' rc cpi '9'+1 cmc ret ; ; crlf to console ; a,f crlf: mvi a,cr call couta mvi a,lf ; " " ; console output from (a) ; a,f couta: push d mov e,a mvi a,@cout call bdos pop d ret ; ; Numeric 1..99 to console. Convert to Ascii, zero suppress ; a,f putnum: cpi 10 jrc pn2; 1 digit only push b mvi c,'0'-1 pn1: inr c adi -10 jrc pn1 adi 10 push psw mov a,c call couta pop psw pop b pn2: adi '0' jr couta ; ; Test for any console character ready. If so purge it and ; return nz flag. Else return z flag. Nulls absorbed ; a,f qbreak: mvi a,@csta call bdos rz mvi a,@cin jr bdos ; ; called from xcom and xtyp. If disk is default then search system ; disk on failure. z flag indicates failure ; a,f,d,e fopenf: xra a sta frecd lxi d,fcbdrv lda cmdmsk+1; (get high byte) ral jrc fopen; search disabled ldax d ora a jrnz fopen; not default, restrict search call fopen rnz; success on default drive inr a; i.e. disk a stax d; now try the system drive call fopen rnz; success stax d; restore default drive id for ccpxtd ret ; ; open file (de)^. z flag for failure ; a,f fopen: mvi a,@fopen ; " " ; execute functions, Z flag for 0ffh, increment return value ; a,f sfncr: call bdos inr a ret ; ; close file (de)^. Z flag for failure ; a,f fclose: mvi a,@fclose jr sfncr ; ; search next on (de)^. Z flag for failure, exit (a) incremented ; a,f srchn: mvi a,@srchn jr sfncr ; ; search for file fcbdrv. Z flag for failure, exit (a) incremented. ; a,f,d,e ffind: lxi d,fcbdrv mvi a,@srch1 jr sfncr ; ; purge file (de)^, z flag for failure ; a,f fpurge: mvi a,@fpurg jr sfncr ; ; read from file fcbdrv. z flag for success ; a,f,d,e freadf: lxi d,fcbdrv ; " " ; read from file (de)^. z flag for success ; a,f,d,e rdseq: mvi a,@rdseq jr bdos ; ; write to file (de)^. z flag for success ; a,f fwrite: mvi a,@wtseq jr bdos ; ; create file (de)^; z flag for success ; a,f create: mvi a,@fnew jr sfncr ; ; set dma access to defdma area ; a,f,d,e sdma80: lxi d,defdma ; " " ; set dma access to (de)^ ; a,f setdma: mvi a,@stdma jr bdos ; ; Find current logged disk qdisk: mvi a,@curdk jr bdos ; ; Set user to absolute value in fcbusr and select on BDOS. ; Do not modify or select drive. Leave drv/usr in bc ; Update fcbusr to absolute value ; a,f,b,c,e setusr: lbcd fcbusr; c := user, b := drive mov a,c ora a cm quser; default, get current user mov c,a; now an absolute value sbcd fcbusr ; " " ; set user to a ; a,f,e susera: mov e,a jr suser ; ; find current user code ; a,f,e quser: mvi e,0ffh ; " " ; set user (e) ; a,f suser: mvi a,@usrcd jr bdos ; ; reset disk system ; a,f rsdisk: mvi a,@rsdsk ; " " ; execute bdos call, return (a), set flags. Preserve other registers ; This is the sole connection to the outside world. ; a,f bdos: push h push d push b pushix mov c,a call sysfnc ora a; set flags on return value popix pop b pop d pop h ret ; ; Get a line from $$$.SUB file, and reduce the file size. ; If anything fails, purge $$$.SUB and reset subflg ; Line is placed in ' call couta; finish the prompt lda subflg ora a lxi h,iobuff jnz tstr; a subfile line loaded, echo & exit ; " " ; Input line from console. Add line end mark. Return de^ to ibflen ; a,f,d,e,h,l getln: lxi d,ibfsiz mvi a,@instg call bdos; else read from console & exit inx d; to ibflen ldax d mov l,a xra a mov h,a dad d; point to line end inx h mov m,a; and mark it ret ; ; Parse the next field from the command line (IX^) into fcbdrv. Any ; drive/user specifications are recorded in fcbdrv and fcbusr ; (which default to 0 and -1 respectively). name and type are parsed ; into fname and ftype, blank padded, with any '*'s expanded into ; '?'s, and the fields are blank padded. At exit IX points to the ; field terminating delimiter char and lastwd points to the 1st char. ; a contains a count of '?' characters in fname & ftype fields, with ; flags set on it. Illegal chars. cause abort. ; a,f,b,c,d,e,h,l,ix parse: xra a ; " " ; Entry to parse 2nd drive spec. for xcom, when a = 010h parsef: lxi h,fcbusr call index; select fcb or alternate fcb call skipbk; skip any leading blanks sixd lastwd; save marker for errors call getdu; c := user, b := drv mov m,c; set fcbusr inx h mov m,b; set fcbdrv, set up for ldfld call lastch cpi ':' cz nextch; Absorb any du terminating ':' mvi b,8 push h call ldfld; fill the name field call lastch cpi '.' cz nextch; Absorb any name terminating '.' mvi b,3; (else terminator blank fills) call ldfld; fill the type field mvi b,3 parse1: inx h mvi m,0 djnz parse1; zero ex, s2, s1 fields lxi b,11 shl 8; b := 11, c := 0 pop h mvi a,'?' parse2: inx h cmp m jrnz parse3 inr c parse3: djnz parse2; count the '?'s in fname/ftype mov a,c ora a; z flag for no wild cards ret ; ; load up to (b) chars from (ix)^ up to (hl)^ up. ; skip to delimiter. Implement any wild cards on "*" ; blank fill if less than (b) chars available. ; Upshift any lower case characters. ; a,f,b,h,l,ix ldfld: call lastch; on (ix)^ and load it jrz ldfld4; delimiter inx h cpi '*' jrnz ldfld1 mvi m,'?'; expand '*' jr ldfld2; dont skip past it ldfld1: call upshft; upshift any lower case mov m,a call nextch ldfld2: djnz ldfld call lastch; on (de)^ and load it rz; a delimiter ldfld3: call nextch; else skip to a delimiter rz jr ldfld3 ldfld4: inx h mvi m,' '; blank fill djnz ldfld4 ret ; ; getdu returns any "du" spec. in b and c, with c = user, b = drv ; The default user is signified by a -1 value, default drive by 0 ; At entry, IX points to the start of the field to be parsed. At ; exit, either IX is unchanged (no du found), or points to ':' ; a,f,b,c,d,e,ix getdu: lxi b,0ffh; set defaults pushix pop d; pre-scan for valid du field ldax d call upshft; 2.1 - No ':' abort here call qnum jrnc getdu1; 1st char digit, no d cpi '@' rc; < '@', no du spec cpi 'P'+1 rnc; > P, no du spec inx d ldax d cpi ':' jrz getdu2; d spec only call qnum rc; no 'du' spec getdu1: inx d ldax d cpi ':' jrz getdu2; du spec found call qnum rc; no du spec inx d ldax d cpi ':' rnz; not terminal ':', no du spec ; " " ; prescan found a valid du format, now load it getdu2: call lastch call qnum jrnc getdu3; digit, no d portion call upshft sui '@' mov b,a; save d portion call nextch getdu3: cpi ':' rz; no 'u' portion ani 0fh mov c,a call nextch rz; ':', 1 digit only call dstep; incorporate call nextch; and advance to the (known) ':' lda maxusr cmp c jrc badcmd; User # too large ret ; ; Decimal input step. Carry for overflow. c is accumulator, a digit ; a,f,c,d dstep: ani 0fh mov d,a mov a,c cpi 26 cmc rc; overflow add a add a add c; 5* add a; 10* add d mov c,a; result ret; cy for overflow ; ; Get next character from line. Z flag for a delimiter, ; and abort if the character is illegal. Do not advance past eoln. ; Return char in a and leave IX pointing to it. cy for eoln ; a,f,ix nextch: ldx a,+0 ora a jrz lastch; don't advance past eol inxix ; " " ; Return last character, as above. Abort if invalid, cy for eoln ; a,f lastch: ldx a,+0 ora a stc rz; null is a delimiter cpi '='; and all these rz cpi '_' rz cpi '.' rz cpi ':' rz cpi ';' rz cpi '<' rz cpi '>'; Redirection chars rz cpi ','; Operand separator rz cpi '|'; Piping separator rz; ; " " ; Check white space, abort on illegal chars. z flag for white qwhite: cpi tab rz; white space is a delimiter cpi ' ' jrc badcmd; abort on illegals ret ; ; skip blanks and tabs in input line. Abort on illegal chars. ; return the 1st non-blank char. found. ; a,f,ix skipbk: call lastch rc; eoln skip1: call qwhite rnz; not white space ; " " ; Effectively "call nextch ! call skipbk" next: call nextch jrnc skip1 ret; eoln ; ; Parse a filename, abort if wild cards specified pfwild: call parse rz ; " " ; Badcmd is a command aborter. It shows the portion of the ; current line from lastwd^ thru ix, with a '?', kills any ; submit job in progress, and returns to the command loop. badcmd: call crlf lhld lastwd pushix pop d inx d mov a,e sub l mov b,a; char count for the field badcd1: mov a,m call couta inx h djnz badcd1; display the field mvi a,'?' call couta call killsub jr cmdone; go mark line empty ; ; **************************** ; The 'cold' entry should be at the magic 035Ch from begin ; to function with the peculiar Osborne 1 bootstrap loader. spare equ 035ch - ($-begin); available for patching if spare AND 08000h; i.e. negative +++ Code entry point wrong for Osborne 1 +++ else if spare NE 0 ds spare,0; null fill it endif endif ; ; ------- Outer Block -------- ; ; cold entry and sign-on. This is only used on initial entry, and is ; automatically patched out. If "cold" and "both" are not on the ; same page the relocation mechanism in RELOCCP will have problems. cold: jmp signon ; ; at entry (c) specifies default user/drive warm: xra a sta ibflen; kill prestored command ; " " ; Initialization. Entry here executes pre-stored command. c = usr/drv both: lxi sp,stktop lxi h,both; Automatic no sign-on patch. shld begin+1; also allows for Osborne 1 peculiarity xra a sta defdu; Until input (c) found valid call rsdisk; true if any '$*.*' file exists sta subflg mov a,c call dvalid; So defdu is A0: if invalid ; " " ; Main loop of the command processor. cmdlp: lxi sp,stktop; in case aborted call preset; Set default drv/user/dma call crlf lda ibflen ora a cz getcmd; No prestored, get new lda subflg; (sub breaks checked before and ora a; after echo, to ease operation) cnz qbreak; If console break on sub job jrz cmdlp1 call killsub; then abort sub in progress jr cmdone cmdlp1: lxi h,iobuff; init cursor to buffer start shld lastwd push h popix mov a,m cpi '*' jrz cmdone; initial '*' is also a comment for now sui ';' jrz cmdone; an initial ';' marks a comment line inr a; i.e. cpi ':' jrz cmdone; and ':' is a label for submit, ignore lda ibflen ora a cnz parse; next item into fcbdrv lda ibflen ora a cnz exec; execute the non-null command ; " " ; Exit point from commands cmdone: xra a; badcmd re-enters here sta ibflen jr cmdlp; Until a .COM file reboots ; ; hl := hl + a ; a,f,h,l index: add l mov l,a rnc inr h ret ; ; ------- The rest is execution features ------- ; ; The abilities of CCP+ can be modified fairly freely in the following ; code, without affecting the main parsing and submit execution. ; ; ----------------------------------------------- ; ; Check wheel permission for command # (a). At entry, ; a = 0 1 2 3 4 5 6 7 8 9 (= maxcmd+1) ; for login, dir, era, type, save, ren, caps, go, kill, xcom ; Values 10, 11, 12 for du check on login, dir, xcom respectively ; Returns carry for controlled command ; a,f,h,l whlchk: lhld @wheel mov a,m ora a rnz; wheel set lhld cmdmsk jmp bitmsk; put controlling bit in carry ; ; Login to drive/user specified by fcbusr, fcbdrv. ; a,f,b,c,e login: call skipbk jrnc cmdbad; more in line mvi a,maxcmd+2; for logins call chkdu; check validity while defaults marked mov a,c; chkdu set c := user, b := drv inr a ora b rz; drv/user default, null command call setusr; update to abs usr, call bdos mov a,c tdig ani 0f0h mov c,a mov a,b dcr a jp login1; not default drive lda defdu login1: ani 0fh ora c mov c,a; new defdu value, if valid ; " " ; validate drive selection before defdu update ; a,f,e dvalid: call seldka; so BDOS aborts if invalid mov a,c sta defdu; outer block does actual selection ret ; ; Exec receives the initial command line field parsed into fcbdrv, ; and is responsible for whatever is done with it. IX has been advanced ; to the delimiter past this first field. exec: lda ftype sui ' ' sta flag; if good, a default 0 jrnz cmdbad; No type allowed on initial field lda fname sui ' ' jrz login; A login command only lbcd fcbusr; Something other than a login command inr c mov a,c ora b mvi a,maxcmd cz lookup; No drv nor user spec, check built-ins lxi h,xfrtbl; (otherwise a file is specified) add a call index mov a,m inx h mov h,m mov l,a pchl; transfer via hl, returns to main ; ; Check validity of du under wheel reset conditions ; Abort to badcmd if illegal du. Returns b := drv, c := user ; Used for login, dir, and execution of transient commands, ; for which a = 10, 11 or 12 on entry respectively. ; a,f,b,c,h,l chkdu: lbcd fcbusr call whlchk; Wheel for command access? rnc; not controlled ; " " ; Validate against system values, abort if illegal inr c; so default is 0 lda whlusr; max ALLOWED inr a cmp c dcr c; restore c mov a,b cnc drvchk; if u ok check drive rnc; drive ok ; " " ; linkage to badcmd cmdbad: jmp badcmd ; ; search for valid command. Checks (fname) against internal list ; Returns a := index of command, maxcmd if not found (i.e. xcom) ; A suppressed command (via wheel/cmdmsk) returns maxcmd ; a,f,b,c,d,e,h,l lookup: lxi h,cmdtbl mvi c,0 jr look4; to loop entry look1: inx h djnz look1; skip over command table to next look2: inr c; advance index, test next entry mov a,c cpi maxcmd rnc; not in command table - exit look4: lxi d,fname mvi b,4; length of command strings look5: ldax d cmp m jrnz look1; not this one inx d inx h djnz look5; more chars to check ldax d cpi ' ' jrnz look2; Not terminated, not command mov a,c; found inr a; because 0 describes login call whlchk; is command suppressed? mov a,c rnc mvi a,maxcmd; yes, look for transient ret; found ; ; Set drv/user from fcbusr/fcbdrv. Expected to be restored. ; This is used only by the built-in and transient commands. ; Revise fcbusr/drv to specify absolute values. ; a,f,b,c,e setdu: call setusr; b := drv; c := usr mov a,b dcr a; put in range 0..15 jp setdu1; not default lda defdu; else get default setting setdu1: ani 0fh mov b,a; now drv/user are absolute values call seldka; aborts on invalid inr b; non-default, defeat any paths sbcd fcbusr; update fcb ret ; ; DIR command ; a,f,b,c,d,e,h,l,ix xdir: call skipbk xra a sta flag call parse call skipbk; so ix^ is at any options (O, S) jrc xdir3; end of line, no options call upshft cpi 'S'; system also jrz xdir1 cpi 'O'; only system jrnz xdir2; go check separator xdir1: sta flag cz nextch; position past any flag found call skipbk jrc xdir3; eol, no more xdir2: cpi ';' jrnz cmdbad; should have line end now xdir3: call nextch; absorb separator mvi a,maxcmd+3 call chkdu call setdu; now bc is abs drv/usr lxi h,fname mov a,m cpi ' ' jrnz dir; something specified mvi b,11; set *.* default xdir4: mvi m,'?'; with 11 "?"s inx h djnz xdir4 ; " " ; Parameters set up. List all matching entries dir: call ffind; return (a) := dir ptr + 1 jrz dirx mvi e,1; so first item causes new line dir1: dcr a; regain dir block pointer rrc rrc rrc ani 060h; mov c,a; form dir entry pointer call qlist jrc dir9; suppress this entry dcr e jrnz dir2; not new line needed lda cols mov e,a call crlf call qdisk adi 'A' call couta lda fcbusr ora a cnz putnum; show user if non-zero jr dir3 dir2: mvi a,' ' call couta dir3: mvi a,':' call couta mvi b,1; point to 1st char. in fname dir4: mvi a,' ' call couta dir5: mov a,b call idxac ani 07fh; remove any attribute bit call couta inr b; count position in name mov a,b cpi 9 jrz dir4; after fn, insert blank cpi 12 jrc dir5; not done, continue dir9: call qbreak; check for interruption rnz; user break call srchn jrnz dir1; with (a) := dir entry id dirx: call skipbk rc; end of command line, EXIT call crlf call setdud; restore defaults and jmp xdir; repeat for next field ; ; Check whether entry should be listed. defdma holds the ; directory field, c holds the field index, and flags any ; command input flag (0 if none, ystem ; Set carry if listing to be suppressed ; a,f,b,h,l qlist: mvi a,10 call idxac mov b,a; get system bit lda flag ora a jrnz qlist1; a flag mov a,b ral ret; with carry for system file qlist1: cpi 'S' rz; (S)ystem also, list this one mov a,b; must be (O)nly system cma ral ret; carry for non-system ; ; load (a+c)th char from defdma array ; a,f,h,l idxac: lxi h,defdma add c call index mov a,m ret ; ; TYPE command execution xtype: call pfwild; aborts if wild cards call setusr; but not drive, allow paths call fopenf jrz getn6; badcmd call crlf mvi b,128 xtype1: mov a,b cpi 128 jrc xtype2; disk read not needed call freadf rnz; eof mov b,a; a zero xtype2: inr b lxi h,defdma call index mov a,m cpi eof rz call couta call qbreak jrz xtype1; no interruption ret ; ; Get number from command line. ; Optional final "+" which sets 'flag' getnum: call pfwild; forbids wild cards lda fcbdrv ora a jrnz getn6; badcmd; starts with "d:" lxi h,fname lxi b,11 shl 8; c := 0, b := 11 getn1: mov a,m cpi ' ' jrz getn5; done cpi '+' jrz getn4; done, with + flag inx h call qnum cnc dstep; incorporate jrc getn6; badcmd overflow djnz getn1 getn3: mov a,c ret getn4: sta flag; i.e. "+" terminator getn5: inx h dcr b jrz getn3 mov a,m; test for excess garbage cpi ' ' jrz getn5 getn6: jmp badcmd ; ; SAVE command execution xsave: call getnum push psw call pfwild; aborts if wildcards call setdu; no paths, absolute drive lxi d,fname ldax d dcx d; to fcbdrv cpi ' ' jrz getn6; badcmd; no name specified call fpurge call create jrz xsave3; fullup xra a sta frecd pop psw mov l,a mvi h,0 dad h; convert pages to records lxi d,tpa lda flag ora a jrz xsave1 inx h; extra record to save xsave1: mov a,h ora l jrz xsave2 dcx h push h lxi h,128; advance to next record dad d push h; save next, d is present call setdma lxi d,fcbdrv call fwrite pop d; get back next pointer pop h; and record counter jrz xsave1; write succeeded jr fullup; write failure xsave2: lxi d,fcbdrv; done call fclose rnz; close succeeded push h; so we can arrive with xsave3: pop h; junk on the stack ; " " ; NO ROOM message and return fullup: lxi h,fulmsg jr xcaps1; tstrc ; ; CAPS command execution xcaps: lxi h,lcuc mov a,m cma mov m,a ora a lxi h,dnmsg jrz xcaps1 lxi h,upmsg xcaps1: jr tstrc; exit with message ; ; ERA command execution xera: call parse cpi 11 jrnz xera1; not *.* specification lxi h,allmsg call tstrc call getln xchg; hl points to ibflen dcr m rnz; not 1 char reply. jr byte saver inx h mov a,m ani 05fh; upshift, only interested in 'Y' cpi 'Y' rnz; not confirmed xera1: call setdu lxi d,fcbdrv call fpurge rnz; ok ; " " ; crlf,"NO FILE" message ; a,f,h,l nofile: lxi h,nofmsg ; " " ; crlf, then tstr ; a,f,h,l tstrc: call crlf ; " " ; string (hl) to console until 0 byte ; a,f,h,l tstr: mov a,m ora a rz inx h call couta jr tstr ; ; REN command execution xren: call pfwild; aborts if wild cards call setdu push b call ffind jrnz xren2; new name pre-exists lxi h,fcbdrv lxi d,filedn lxi b,16 ldir call skipbk cpi '=' jrz xren1 cpi '_' jrnz xren3; badcmd; invalid assignment operator. xren1: call nextch call pfwild; aborts on wild card call skipbk jrnc xren3; badcmd; extra garbage on line lhld fcbusr mov a,l inr a ora h jrnz xren3; badcmd; 2nd spec has a d/u pop h; du from 1st spec, absolute shld fcbusr; make them match call setdu call ffind; (sets de := fcbdrv) jrz nofile; cant find file to rename mvi a,@frenm jmp bdos; rename and EXIT xren2: pop psw lxi h,foldms jr tstrc; and EXIT with message xren3: jmp badcmd; LINKAGE ; ; COM/CCPXTEND.SYS file not found. (flag specifies which). ; Recycle the loader to load CCPXTEND or abort. ; This transient receives the complete command line, and can control ; any access rights, search libraries, execute interpreters, etc. ccpxtd: lda fcbdrv; no ccp extension when disk specified lxi h,flag; nor if already tried ora m jrnz xren3; badcmd dcr a mov m,a; set flag to prevent re-execution etc. lxi b,13; user, drive, name, type lxi d,fcbusr; Now try for ccp extension lxi h,xtndf jr xcom1; load extension and execute ; ; anything other than built-ins. look for a com file first, ; If this fails, pass the complete command line to CCPXTEND.SYS xcom: mvi a,maxcmd+4; for execution call chkdu; allows access restriction lxi h,com lxi d,ftype lxi b,3 xcom1: ldir; set file type to ".COM" call setusr; leave drive default, for paths call fopenf jrz ccpxtd; not found, exit lxi h,tpa-128 xcom2: lxi d,128; advance store ptr. dad d lxi d,begin mov a,l sub e mov a,h sbb d jnc fullup; prevent overwriting ccp on load xchg call setdma xchg call freadf; load the COM file jrz xcom2; not eof yet ; " " ; Execute loaded program after parsing command tail into page 0. xgo: call parse; 1st passed fcb call next; past closing delimiter. nextch/skipbk mvi a,010h call parsef; 2nd passed fcb xra a sta frecd sta frecnt lxi d,defcbk lxi h,fcbdrv lxi b,33; set default fcbs for execution ldir lxi h,iobuff lda flag ora a jrnz xgo2; keep everything on CCPXTEND xgo1: mov a,m ora a jrz xgo2 cpi ' ' jrz xgo2; skip the command name inx h jr xgo1 xgo2: mvi b,0 lxi d,defdma+1 xgo3: lda lcuc ora a mov a,m; set the passed command line cnz upshft; upshifting in effect stax d ora a jrz xgo4 inr b; count chars passed inx h inx d jr xgo3 xgo4: mov a,b sta defdma; set cmd line lgh for execution call crlf call preset; preset drive/user/dma jmp tpa; EXECUTE. Return to cmdlp on TOS ; xfrtbl: dw xdir, xera dw xtype, xsave dw xren, xcaps dw xgo, killsub dw xcom; xcom must be last entry maxcmd equ ($-xfrtbl)/2-1 ; ; Resident commands cmdtbl: db 'DIR ' db 'ERA ' db 'TYPE' db 'SAVE' db 'REN ' db 'CAPS' db 'GO ' db 'KILL' ; ; Check overall size if ($-begin) GT 1896 +++ CCP+ too large +++ else; enough room ; ; This space is re-used as execution time stack space. ; ; cold entry and sign-on. This is only used on initial entry. ; If "cold" and "both" are not on the same page the relocation ; mechanism in RELOCCP will have problems. signon: lxi sp,stktop lxi h,vermsg call tstrc jmp both ; ; Do not lengthen this message, else signon stack use clobbers it. vermsg: db 'CCP+ Ver. ' db ccpver/10 + '0','.',ccpver MOD 10 + '0' db 0 ds 1944-($-begin),0; working stack space available stktop: ds 0 endif; Too large check ; ; Data area. Starts at 0798h (from begin) ; ; SUBMIT control block. (34 bytes) subusr: db subuser subfcb: db 1,'$$$ SUB'; drv A, user 0 subex: db 0 subs1: db 0 subs2: db 0 subrc: ds 1,0 subdn: ds 16,0 subrcd: ds 1,0 subflg: ds 1,0; zero prevents sub file searches ; ; NOTE: the ",0" in ds statements ensures the areas are 0 filled ; ; File control block and receiver of parse fields (34 bytes) fcbusr: ds 1,0 fcbdrv: ds 1,0 fname: ds 8,0 ftype: ds 3,0 ds 3,0 frecnt: ds 1,0 filedn: ds 16,0; map or altfcb image frecd: ds 1,0 ; ; Parsing (3 bytes) lastwd: ds 2,0; start of current word in iobuff flag: ds 1,0; Command options. Multiple uses ; ; The rest can be re-configured. Placed at the end so location ; will not change with revisions. 16 bytes for this group com: db 'COM'; file type for transients ; ; The following file is loaded, passed the complete command line as ; entered by the user, and executed whenever a transient command is ; not found. Distributed CCPXTEND.SYS checks user 0, then looks in ; COMMAND.LBR on default and A drives, current user and user 0, and ; if that fails attempts to execute RUNPCD Pascal interpreter. You ; are perfectly free to install whatever CCPXTEND file you prefer. ; By installing different ones on various drv/user areas you can ; alter the system characteristics dependent on login area. If you ; are using normal CPM2.2 installation of the CPMFIX patch will make ; files on user area 0 with the SYSTEM attribute visible everywhere, ; and thus a single CCPXTEND.SYS can serve all areas by default. ; DOS+ requires no such patch, and implements paths. xtndf: db 0,0,'CCPXTENDSYS'; ccp extension usr/drv/filename ; ; Configuration constants for customization. Patchable. ; These ALWAYS appear in the last 16 bytes of the CCP area. cols: db dcols; columns to use for directory lcuc: db doupsft; zero to prevent command line upshift ; CAPS command modifies at run time. maxusr: db maxuser; Limit for parsing. Login max = 15 whlusr: db whluser; Highest user allowed when @wheel^ = 0 @wheel: dw reboot + 0; Location of wheel byte. +0 = none. ; (reboot always holds 0c3h=jmp) ; ; This mask specifies which commands are wheel controlled. ; bit (lsb) 0 1 2 3 4 5 6 7 8 9 ; for login, dir, era, type, save, ren, caps, go, kill, trans ; AND ; bit 10 11 12 cause du checks (wheel off) on ; for login dir transients (i.e. running .COM files) ; AND ; bit 15 (msb) disables A: search for transients & type command. This ; is normally disabled for DOS+, since DOS+ provides the search. ; ; (The ordering is dependent on the command table) ; running transients cannot be disabled, bit 9 is ignored ; Set to enable search for .COM files for CPM use. cmdmsk: dw 0; (use 8000h for DOS+) Mask for wheel controlled cmds ; ; These masks specify drives that may NOT be accessed. The lsb (of ; the word, weight 1) specifies A:, the msb (bit 15, weight 8000h) ; specifies P:. DRVMSK can prevent logins causing BDOS SELECT errors ; by specifying all drives not physically present in the system. ; WHLMSK is used for security purposes. ; CAUTION: do not disable drive A on most systems drvmsk: dw 0; Mask for invalid drives, wheel set whlmsk: dw 0; Mask for bad drives when @wheel^ = 0 db 0,0,0,0; Spares for future use ; (last word is available for ccitcrc) ; ; Check for relocator problem if ((both-begin) SHR 8) NE ((cold-begin) SHR 8) +++ Relocator problems, cold/warm/both pages +++ endif; relocation problem ; end drives not physically present in the system. ; WHLMSK is used for security purposes. ; CAUTION: do not disable drive A on most systems drvmsk: dw 0; Mask for invalid drives, wheel set whlmsk: dw 0; Mask for bad drives when @wheel^ = 0 db 0,0,0,0; Spares for future use ; (last word is available for ccitcrc) ; ; Check for relocator problem if ((both-begin) SHR 8) NE (:20E00000C35CE3C35FE37E00000000000000000000000000000020204343502B2076322E44 :20E02000322028432920313938362C20432E422E2046616C636F6E65722C2054656C2E20CC :20E040002832303329203238312D313433382C203638302048617274666F72642054706B8F :20E060002E2C2048616D64656E2C2043542E2C205553410000000000000000000000000093 :20E0800000000000000000004E6F2046696C65004E6F20726F6F6D00416C6C2028792F4E32 :20E0A000293F0046696C6520657869737473004E6F2055505348494654002AFAE7B7C83DF1 :20E0C000D610293C20FCC9FE61D8FE7BD0E65FC9FE30D8FE3A3FC93E0DCDDEE03E0AD55FEA :20E0E0003E02CD74E1D1C9FE0A3811C50E2F0CC6F638FBC60AF579CDDEE0F1C1C63018DE6F :20E100003E0BCD74E1C83E01186AAF32DCE711BCE73AF7E71738101AB7200CCD27E1C03C6E :20E1200012CD27E1C012C93E0FCD74E13CC93E1018F73E1218F311BCE73E1118EC3E1318C1 :20E14000E811BCE73E14182C3E1518283E1618D91180003E1A181D3E191819ED4BBBE779BC :20E16000B7FC6CE14FED43BBE75F18021EFF3E2018023E0DE5D5C5DDE54FCD0500B7DDE14E :20E18000C1D1E1C93A98E7CD69E11199E7CD27E12827D53AA8E73D32B9E71107E0CD53E118 :20E1A000D1CD44E120133286E021A7E7772335CD2EE12805CD00E128103A98E7CD69E11183 :20E1C00099E7CD3DE1AF32BAE7CD50E13A0400F507070707E60FCD69E1F1E60F5FE52AF8AD :20E1E000E7CDC0E0E1DA3DE33E0E18883ABAE7B7C484E13A0400F5E60FC641CDDEE0F10797 :20E20000070707E60FC4E7E03E3ECDDEE03ABAE7B72108E0C23EE61106E03E0ACD74E1136D :20E220001A6FAF67192377C9AF21BBE7CDC1E3CD2BE3DD22DDE7CD95E2712370CD02E3FE4A :20E240003ACCFAE20608E5CD6EE2CD02E3FE2ECCFAE20603CD6EE2060323360010FB0100B2 :20E260000BE13E3F23BE20010C10F979B7C9CD02E3281C23FE2A2004363F1807CDC7E07741 :20E28000CDFAE210E9CD02E3C8CDFAE2C818FA23362010FBC901FF00DDE5D11ACDC7E0CDA4 :20E2A000D0E03010FE40D8FE51D0131AFE3A2813CDD0E0D8131AFE3A2809CDD0E0D8131A2C :20E2C000FE3AC0CD02E3CDD0E03009CDC7E0D64047CDFAE2FE3AC8E60F4FCDFAE2C8CDEBF7 :20E2E000E2CDFAE23AF2E7B93853C9E60F5779FE1A3FD887878187824FC9DD7E00B7280293 :20E30000DD23DD7E00B737C8FE3DC8FE5FC8FE2EC8FE3AC8FE3BC8FE3CC8FE3EC8FE2CC8D7 :20E32000FE7CC8FE09C8FE203813C9CD02E3D8CD23E3C0CDFAE230F7C9CD28E2C8CDD7E0C1 :20E340002ADDE7DDE5D1137B95477ECDDEE02310F93E3FCDDEE0CDB9E1186000C365E7AFF8 :20E360003207E03198E72163E32201E0AF320400CD72E132BAE779CDF7E33198E7CDC9E14B :20E38000CDD7E03A07E0B7CCECE13ABAE7B7C400E12805CDB9E118232108E022DDE7E5DDD1 :20E3A000E17EFE2A2815D63B28113C280E3A07E0B7C428E23A07E0B7C4FFE3AF3207E018D9 :20E3C000B9856FD024C92AF4E77EB7C02AF6E7C3C0E0CD2BE330653E0ACD28E4793CB0C8B1 :20E3E000CD5BE17907070707E6F04F783DF2F3E33A0400E60FB14FCDDAE179320400C93A70 :20E40000C5E7D62032DFE720333ABDE7D62028C2ED4BBBE70C79B03E08CC3FE42133E7874B :20E42000CDC1E37E23666FE9ED4BBBE7CDC6E3D00C3AF3E73CB90D78D4BAE0D0C33DE32110 :20E4400045E70E0018082310FD0C79FE08D011BDE706041ABE20EF132310F81AFE2020E9B2 :20E46000793CCDC6E379D03E08C9CD5BE1783DF275E43A0400E60F47CDDAE104ED43BBE738 :20E48000C9CD2BE3AF32DFE7CD28E2CD2BE3381ACDC7E0FE532804FE4F200B32DFE7CCFA06 :20E4A000E2CD2BE33804FE3B2092CDFAE23E0BCD28E4CD6AE421BDE77EFE202007060B36C3 :20E4C0003F2310FBCD36E128561E013D0F0F0FE6604FCD2CE5383F1D20183AF0E75FCDD791 :20E4E000E0CD57E1C641CDDEE03ABBE7B7C4E7E018053E20CDDEE03E3ACDDEE006013E2019 :20E50000CDDEE078CD42E5E67FCDDEE00478FE0928ECFE0C38EDCD00E1C0CD32E120ACCD67 :20E520002BE3D8CDD7E0CDCCE1C381E43E0ACD42E5473ADFE7B720037817C9FE53C8782F5A :20E5400017C921800081CDC1E37EC9CD39E3CD5BE1CD0AE12854CDD7E0068078FE8038059E :20E56000CD41E1C04704218000CDC1E37EFE1AC8CDDEE0CD00E128E3C9CD39E33ABCE7B7A7 :20E58000202821BDE701000B7EFE202814FE2B280D23CDD0E0D4EBE2381010EC79C932DF54 :20E5A000E7230528F77EFE2028F7C33DE3CD79E5F5CD39E3CD6AE411BDE71A1BFE2028EA51 :20E5C000CD3DE1CD4CE12835AF32DCE7F16F2600291100013ADFE7B72801237CB528162BF7 :20E5E000E521800019E5CD53E111BCE7CD48E1D1E128E8180911BCE7CD2EE1C0E5E1219042 :20E60000E0180F21F1E77E2F77B721AFE0280321B2E01827CD28E2FE0B20132198E0CD3B9E :20E62000E6CD17E2EB35C0237EE65FFE59C0CD6AE411BCE7CD3DE1C02188E0CDD7E07EB795 :20E64000C823CDDEE018F7CD39E3CD6AE4C5CD36E1203A21BCE711CCE7011000EDB0CD2B00 :20E66000E3FE3D2804FE5F202ACDFAE2CD39E3CD2BE3301F2ABBE77D3CB42017E122BBE7D8 :20E68000CD6AE4CD36E128B03E17C374E1F121A3E018A8C33DE33ABCE721DFE7B620F43D33 :20E6A00077010D0011BBE721E3E7180E3E0CCD28E421E0E711C5E7010300EDB0CD5BE1CDD2 :20E6C0000AE128D2218000118000191100E07D937C9AD2FEE5EBCD53E1EBCD41E128E8CD9B :20E6E00028E2CD33E33E10CD29E2AF32DCE732CBE7115C0021BCE7012100EDB02108E03A4C :20E70000DFE7B7200B7EB72807FE2028032318F506001181003AF1E7B77EC4C7E012B72839 :20E720000504231318EF78328000CDD7E0CDC9E1C3000181E414E64BE5ADE547E603E6DF94 :20E74000E6B9E1ACE64449522045524120545950455341564552454E2043415053474F205D :20E76000204B494C4C3198E72171E7CD3BE6C363E34343502B205665722E20322E320000FF :20E780000000000000000000000000000000000000000000000000000001242424202020AC :20E7A00020205355420000000000000000000000000000000000000000000000000000002F :20E7C000000000000000000000000000000000000000000000000000000000000000000039 :20E7E000434F4D00004343505854454E4453595305FF1F0D000000000000000000000000B2 :00000001FF 1ACE64449522045524120545950455341564552454E2043415053474F205D :20E76000204B494C4C3198E72171E7CD3BE6C363E34343502B205665722E2032.xlist .z80 ; Macros to define the Z-180 extended instructions. ; ; D-X Designs Pty. Ltd. 4/12/95 D. R. Brooks ; ; WARNING! These instructions are NOT supported by ; Z80MU. However the IO instructions are ; necessary to ensure correct access to ; the internal machine registers, which ; fully decode all 16 address bits. ; ; Adapted from Zilog (file 182macro.lib) ; Enhanced to provide conditional definition for the ; following chips (define the appropriate symbol) ; Z80180 Default ; Z80S180 ; Z80181 ; Z80182 ; First, check only one CPU is defined ifdef Z80180 ?test equ 0 ;These will throw a "Multiple endif ; Definition" error if 2 CPU's ifdef Z80S180 ; are defined ?test equ 1 endif ifdef Z80181 ?test equ 2 endif ifdef Z80182 ?test equ 3 endif ;========== Z180 Internal Interrupt Vectors ======== ; The following vectors are offsets from the value ; loaded in IL, the Interrupt Vector Low register. VINT1 equ 0 ;External INT-1 pin VINT2 equ 2 ;External INT-2 pin VPRT0 equ 4 ;Timer 0 VPRT1 equ 6 ;Timer 1 VDMA0 equ 8 ;DMA Ch-0 VDMA1 equ 0ah ;DMA Ch-1 VCSIO equ 0ch ;Clocked serial I/O VASC0 equ 0eh ;Asynch. comms. Ch-0 VASC1 equ 10h ;Asynch. comms. Ch-1 ;========== Z180 System Control Registers ========== ;NB These registers may be relocated to multiples of ; 40H, by setting the IO Control Register (ICR = 3FH) ; The addresses below are valid with ICR=0 (else they ; are offsets from the ICR base value). ;ASCI Registers cntla0 equ 00h ;ASCI Control Reg A Ch0 cntla1 equ 01h ;ASCI Control Reg A Ch1 cntlb0 equ 02h ;ASCI Control Reg B Ch0 cntlb1 equ 03h ;ASCI Control Reg B Ch1 stat0 equ 04h ;ASCI Status Reg Ch0 stat1 equ 05h ;ASCI Status Reg Ch1 tdr0 equ 06h ;ASCI TX Data Reg Ch0 tdr1 equ 07h ;ASCI TX Data Reg Ch1 rdr0 equ 08h ;ASCI RX Data Reg Ch0 rdr1 equ 09h ;ASCI RX Data Reg Ch1 brk0 equ 12h ;Break Control Reg Ch0 brk1 equ 13h ;Break Control reg Ch1 ;CSI/O Registers cntr equ 0ah ;CSI/O Control Reg trdr equ 0bh ;CSI/O TX/RX Data Reg ;Timer Registers tmdr0l equ 0ch ;Timer Data Reg Ch0-Low tmdr0h equ 0dh ;Timer Data Reg Ch0-High rldr0l equ 0eh ;Timer Reload Reg Ch0-Low rldr0h equ 0fh ;Timer Reload Reg Ch0-High tcr equ 10h ;Timer Control Reg tmdr1l equ 14h ;Timer Data Reg Ch1-Low tmdr1h equ 15h ;Timer Data Reg Ch1-High rldr1l equ 16h ;Timer Reload Reg Ch1-Low rldr1h equ 17h ;Timer Reload Reg Ch1-High frc equ 18h ;Free-Running Counter ifdef Z80S180 ccr equ 1fh ;CPU Control Reg endif ;DMA Registers sar0l equ 20h ;DMA Source Addr Reg Ch0-Low sar0h equ 21h ;DMA Source Addr Reg Ch0-High sar0b equ 22h ;DMA Source Addr Reg Ch0-B dar0l equ 23h ;DMA Destn Addr Reg Ch0-Low dar0h equ 24h ;DMA Destn Addr Reg Ch0-High dar0b equ 25h ;DMA Destn Addr Reg Ch0-B bcr0l equ 26h ;DMA Byte Count Reg Ch0-Low bcr0h equ 27h ;DMA Byte Count Reg Ch0-High mar1l equ 28h ;DMA Memory Addr Reg Ch1-Low mar1h equ 29h ;DMA Memory Addr Reg Ch1-High mar1b equ 2ah ;DMA Memory Addr Reg Ch1-B iar1l equ 2bh ;DMA I/O Addr Reg Ch1-Low iar1h equ 2ch ;DMA I/O Addr Reg Ch1-High bcr1l equ 2eh ;DMA Byte Count Reg Ch1-Low bcr1h equ 2fh ;DMA Byte Count Reg Ch1-High dstat equ 30h ;DMA Status Reg dmode equ 31h ;DMA Mode Reg dcntl equ 32h ;DMA/WAIT Control Reg ;System Control Registers il equ 33h ;INT Vector Low Reg itc equ 34h ;INT/TRAP Control Reg rcr equ 36h ;Refresh Control Reg cbr equ 38h ;MMU Common Base Reg bbr equ 39h ;MMU Bank Base Reg cbar equ 3ah ;MMU Common/Bank Area Reg omcr equ 3eh ;Operation Mode Control Reg icr equ 3fh ;I/O Control Reg ifdef Z80181 ;Features unique to Z80181 ;Integral PIO device p1ddr equ 0e0h ;Data Direction Reg 1 p1dp equ 0e1h ;Port 1 Data p2ddr equ 0e2h ;Data Direction Reg 2 p2dp equ 0e3h ;Port 2 Data ;Integral CTC device ctc0 equ 0e4h ;CTC Channel 0 ctc1 equ 0e5h ;CTC Channel 1 ctc2 equ 0e6h ;CTC Channel 2 ctc3 equ 0e7h ;CTC Channel 3 scccr equ 0e8h ;SCC Control Reg sccdr equ 0e9h ;SCC Data Reg ;Chip-select output pins ramubr equ 0eah ;RAM Upper Boundary ramlbr equ 0ebh ;RAM Lower Boundary rombr equ 0ech ;ROM Boundary scr equ 0edh ;System Control Reg endif ifdef Z80182 ;Features unique to Z80182 ccr equ 1fh ;CPU control reg. intype equ 0dfh ;Interrupt edge/pin mux reg. wsgcs equ 0d8h ;Wait-State Generator CS enh182 equ 0d9h ;Z80182 Enhancements Reg pinmux equ 0dfh ;Interrupt Edge/Pin Mux Reg ramubr equ 0e6h ;RAM End Boundary ramlbr equ 0e7h ;RAM Start Boundary rombr equ 0e8h ;ROM Boundary fifoctl equ 0e9h ;FIFO Control Reg rtotc equ 0eah ;RX Time-Out Time Const ttotc equ 0ebh ;TX Time-Out Time Const fcr equ 0ech ;FIFO Register scr equ 0efh ;System Pin Control rbr equ 0f0h ;MIMIC RX Buffer Reg thr equ 0f0h ;MIMIC TX Holding Reg ier equ 0f1h ;Interrupt Enable Reg lcr equ 0f3h ;Line Control Reg mcr equ 0f4h ;Modem Control Reg lsr equ 0f5h ;Line Status Reg msr equ 0f6h ;Modem Status Reg mscr equ 0f7h ;MIMIC Scratch Reg dlatl equ 0f8h ;Divisor latch LS dlatm equ 0f9h ;Divisor latch MS ttcr equ 0fah ;TX Time Constant rtcr equ 0fbh ;RX Time Constant ivec equ 0fch ;MIMIC Interrupt Vector mimie equ 0fdh ;MIMIC Interrupt Enable Reg iusip equ 0feh ;MIMIC Interrupt Under-Service Reg mmcr equ 0ffh ;MIMIC Master Control Reg ;Z80182 PIO Registers ddra equ 0edh ;Data Direction Reg A dra equ 0eeh ;Port A Data ddrb equ 0e4h ;Data Direction Reg B drb equ 0e5h ;Port B Data ddrc equ 0ddh ;Data Direction Reg C drc equ 0deh ;Port C data ;ESCC Registers sccacnt equ 0e0h ;ESCC Control Channel A sccad equ 0e1h ;ESCC Data Channel A sccbcnt equ 0e2h ;ESCC Control Channel B sccbd equ 0e3h ;ESCC Data Channel B endif ;[E]SCC Internal Register Definitions RR0 equ 00h RR1 equ 01h RR2 equ 02h RR3 equ 03h RR6 equ 06h RR7 equ 07h RR10 equ 0ah RR12 equ 0ch RR13 equ 0dh RR15 equ 0fh WR0 equ 00h WR1 equ 01h WR2 equ 02h WR3 equ 03h WR4 equ 04h WR5 equ 05h WR6 equ 06h WR7 equ 07h WR9 equ 09h WR10 equ 0ah WR11 equ 0bh WR12 equ 0ch WR13 equ 0dh WR14 equ 0eh WR15 equ 0fh ;==== Define the additional Z-180 instructions ===== ;Machine registers (internal use only) ?b equ 0 ?c equ 1 ?d equ 2 ?e equ 3 ?h equ 4 ?l equ 5 ?a equ 7 ??bc equ 0 ??de equ 1 ??hl equ 2 ??sp equ 3 slp macro db 0edh db 76h endm mlt macro ?r db 0edh db 4ch+(??&?r AND 3) SHL 4 endm in0 macro ?r, ?p db 0edh db 0+(?&?r AND 7) SHL 3 db ?p endm out0 macro ?p, ?r db 0edh db 1+(?&?r AND 7) SHL 3 db ?p endm otim macro db 0edh db 83h endm otimr macro db 0edh db 93h endm otdm macro db 0edh db 8bh endm otdmr macro db 0edh db 9bh endm tstio macro ?p db 0edh db 74h db ?p endm tst macro ?r db 0edh ifidn ,<(hl)> db 34h else ifdef ?&?r db 4+(?&?r AND 7) SHL 3 else db 64h db ?r endif endif endm .list  macro db 0edh db 9bh endm tstio macro ?p db 0edh db 74h db ?p endm tst macro ?r db 0edh ifidn ,<(hl)> db 34h else ifdef ?&?r db 4+(?&?r AND 7) SHL 3 else db 64h db ?r endif endif endm .li;Standard drive-parameter block ; Format is same as MS-DOS BIOS SPEC_1 equ 0 ;"Specify" byte 1 SPEC_2 equ 1 ;"Specify" byte 2 MTROFF equ 2 ;Wait before stop motor SECSZE equ 3 ;Bytes/sector (must be > 0) EOT equ 4 ;Final sector no. GPL equ 5 ;Gap length DTL equ 6 ;Data transfer length GAPFMT equ 7 ;Gap-3 length: Format DATFMT equ 8 ;Data fill: Format SETTLE equ 9 ;Head-settle time (mS) MTRON equ 10 ;Motor-start (* 1/8 sec.) MAXCYL equ 11 ;Max. cylinder no. DRATE equ 12 ;Data rate  EOT equ 4 ;Final sector no. GPL equ 5 ;Gap length DTL equ 6 ;Data transfer length GAPFMT equ 7 ;Gap-3 length: Format DATFMT equ 8 ;Data fill: Format SETTLE equ 9 ;Head-settle ascicr equ 0dh ;ASCII characters ascilf equ 0ah ascibs equ 08h asciht equ 09h asciesc equ 1bh space equ ' ' ascdel equ 7fh  page 90 title Basic diskette handler .comment $ ;=======================================================================; ; ; ; B A S I C D I S K - D R I V E R O U T I N E S ; ; ; ; Non-interrupt driven support routines for the SMC diskette chip. ; ; ; ;=======================================================================; ;=======================================================================; ; ; ; D-X Designs Pty. Ltd. Perth, Western Australia ; ; Project: 112 May, 1996 ; ; ; ; Copyright (C) 1996 David R. Brooks ; ; ; ; This program is free software; you can redistribute it and/or ; ; modify it under the terms of the GNU General Public License ; ; as published by the Free Software Foundation; either version 2 ; ; of the License, or (at your option) any later version. ; ; ; ; This program is distributed in the hope that it will be useful, ; ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; ; GNU General Public License for more details. ; ; ; ; You should have received a copy of the GNU General Public License ; ; along with this program; if not, write to the Free Software ; ; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ; ; ; ;=======================================================================; This code is designed to work without interrupts (compatible with the ROM bootstrap code). Consequently, timing functions are done by polling and/or delay loops. The DMA is used for data transfer, and is polled for completion (check that the byte counter has decremented to zero). Call: A - OPCODE: 0 - Reset disk system: all drives uncalibrated 1 - Turn motors off (leave drives calibrated) 2 - Read sector/s 3 - Write sector/s 4 - Verify sector/s 5 - Format track 6 - Translate logical address to physical B - No. of sectors to read/write C - Track No. (even tracks are Side 0, odd tracks are Side 1) D - Drive No. (0..3) E - Sector No. HL - Ptr. to data buffer (logical address) IX - Ptr. to Drive Parameter Block (DPB) Return: If successful: CY = 0 A undefined HL advanced past data block If errors: CY = 1 A status (see below) HL unchanged In either case: DE -> Result vector (7 bytes) IX, IY unchanged BC trashed $ Z80182 equ 0 include Z180.INC include DPARM.INC include FDC.INC incformat equ 0 ;Define this to include the FORMAT cmnd. .sall dseg ;====================================================================== ; L O C A L D A T A ;Return-error status values (in A, if CY=1) calerr equ 1 ;Error in a recalibration function ioerr equ 2 ;Error posted by Result Phase: see (HL) badsect equ 3 ;Sector/Length will overrun track lostdat equ 4 ;DMA did not transfer full block timeout equ 5 ;Interrupt timed out badcmd equ 6 ;Invalid function code sekerr equ 7 ;Seek error calibd: ds 1 ;Drives "Calibrated" flags mask: ds 1 ;Bit-mask of current drive restab: ds 7 ;Buffer for result-phase data rtcnt: ds 1 ;IO command retry count (after RESTAB) switch: ds 3 ;Builds a JP instruction tries equ 3 ;No. of retries on IO errors blksze: ds 2 ;Save block size cseg ;====================================================================== ; F . D . C . C O M M A N D C O D E S cmd_recal equ 7 ;Recalibrate cmd_sense equ 8 ;Sense Interrupt cmd_seek equ 0fh ;Seek to track cmd_read equ 46h ;Read (MFM, implied seek) cmd_write equ 45h ;Write, ditto cmd_verify equ 56h ;Verify, ditto cmd_format equ 4dh ;Format a track ; D . M . A . C O M M A N D S dma_incmd equ 0cdh ;IO => MEM dma_outcmd equ 0f1h ;MEM => IO dma_run equ 63h ;Kick off Channel-0 ;====================================================================== ; U T I L I T Y S U B R O U T I N E S waitint: ;Wait for interrupt (but polled) push bc push de ld bc,0 ;Inner timeout counters ld d,20 ;Coarse timeout setting w1: in0 a,(drc) ;Get interrupt lines bit 6,a jr z,w2 ;Go if interrupt set dec c jr nz,w1 djnz w1 ;65k loops dec d jr nz,w1 ;Coarse outer loop scf jr w3 ;Exit: timed out w2: xor a ;Exit: OK w3: pop de pop bc ret ;-------------------------------- testresult: ;Check results of I/O operations ; IY -> test-block for status: ; see "launch" for details call waitint ;Wait for completion ld a,timeout jr c,exit ;Failed (CY posted to caller) ;Get 7 result bytes after read/write push bc push de ld de,restab ;Point to Result Table ld b,7 ;No. of expected bytes lc3: call getbyte ld (de),a inc de ;Post it djnz lc3 pop de pop bc ld hl,restab ;Pointer to results block push hl ld a,(hl) and 0f8h ;Kill variable bits (just errors) cp (iy+tst0) ;Check to expected value jr nz,bad inc hl ld a,(hl) cp (iy+tst1) ;Check to expected value jr nz,bad inc hl ld a,(hl) sub 0 ;No "funny" errors (ever!) jr nz,bad in0 l,(bcr0l) in0 a,(bcr0h) or l ;Check that all was transferred pop hl ld a,lostdat jr nz,bad ;Should have counted back to zero xor a ;It all succeeded! jr exit ;OK: return CY=0 (A=0) bad1: ld a,badsect ;Bad sector specification scf jr exit bad: ld a,ioerr ;Error post: see block at (HL) pop hl scf exit: ret ;CY = error ;-------------------------------- sendbyte: ;Send A to Cmnd/data port push af scb1: in0 a,(_MSR) ;Check FDC status bit 7,a ;Wait till ready jr z,scb1 pop af ;Recover the cmnd. byte out0 (_DATA),a ret ;-------------------------------- getbyte: ;Read Cmnd/data port to A in0 a,(_MSR) bit 7,a ;Ready? jr z,getbyte in0 a,(_DATA) ;Get it ret ;-------------------------------- sendcmdstrg: ;Send string of commands from HL push bc ;1st. byte is count ld b,(hl) ;Save count scs1: inc hl ld a,(hl) ;Get cmnd. byte call sendbyte ;Send it djnz scs1 ;Repeat pop bc ret ;-------------------------------- uncal: ;Force a recalibrate on this drive push hl ld hl,calibd ;First force a recalibrate ld a,(mask) cpl and (hl) ;Turn of the "calibrated" bit ld (hl),a pop hl ret ;-------------------------------- dmainput: ;Set up DMA buffers for input call absaddr ;Get physical addr. for DMA out0 (dar0l),l out0 (dar0h),h out0 (dar0b),a ;Destination pointers ld a,_DMA out0 (sar0l),a ;Source: FDC's DMA port xor a out0 (sar0h),a out0 (sar0b),a ;Controlled by /DREQ0 ret ;-------------------------------- dmaoutput: ;Set up DMA buffers for output call absaddr ;Get physical addr. for DMA out0 (sar0l),l out0 (sar0h),h out0 (sar0b),a ;Source pointers ld a,_DMA out0 (dar0l),a ;Destn.: FDC's DMA port xor a out0 (dar0h),a out0 (dar0b),a ;Controlled by /DREQ0 ret ;-------------------------------- ;Offsets for inline arguments opcode equ 0 ;Command to FDC tst0 equ 1 ;Match Status 0 tst1 equ 2 ; " " 1 skip equ 3 ;No. of bytes to skip at return launch: ;Initiate a read or write command ex (sp),iy ;Save IY, point at argts. ld a,e ;Find final sector for transfer add a,b dec a ;Last sector to do dec a ;1 under final cp (ix+EOT) ;This MUST be < true final jr nc,bad1 inc a ;True final sector ld h,a ;Save it ld a,(iy+opcode) call sendbyte ;Command code ld a,d ;Drive bit 0,c ;Odd track (ie Side 1)? jr z,lc1 set 2,a lc1: call sendbyte ;Drive & head ld a,c srl a ;Cylinder call sendbyte ld a,c and 1 call sendbyte ;Head ld a,e call sendbyte ;Sector ld a,(ix+SECSZE) call sendbyte ;Sector length (encoded) ld a,h call sendbyte ;Final sector no. ld a,(ix+GPL) call sendbyte ;Gap length ld a,dma_run ;Activate DMA Ch-0 out0 (dstat),a ld a,0ffh ;Data transfer length (default) call sendbyte ;Final byte: FDC & DMA running call testresult ;Find out what happened push bc push af ld bc,skip add iy,bc ;Jump past the inline params. pop af pop bc ex (sp),iy ;Recover IY, post link ret ;-------------------------------- transze: ;Determine buffer size (DMA count set) push hl push de push bc ld hl,64 ld b,(ix+SECSZE) ;Size N, => 128*2^N inc b tz1: add hl,hl djnz tz1 ld d,h ld e,l ;Sector size in DE ld hl,0 pop bc ;No. of sectors in B push bc tz2: add hl,de ;Form total in HL djnz tz2 out0 (bcr0l),l ;Set DMA counter out0 (bcr0h),h ld (blksze),hl ;Save block size pop bc pop de ;Restore regs. pop hl ret ;-------------------------------- endseek: ;Finish of a seek/recalibrate function call waitint ;Wait for it ld a,timeout ret c ;Timed out ld a,cmd_sense ;"Sense Interrupt" at the end call sendbyte call getbyte ld b,a ;ST0 in B call getbyte ;PCN in A push bc ;Verify correct cylinder srl c cp c ;Yes? pop bc ld a,sekerr scf ret nz ;Quit if unequal ld a,b ;Get back ST0 and 0e0h cp 20h ;Look for success ret z ld a,calerr scf ret ;CY=1 if it failed ;-------------------------------- doron equ 0ch ;Basic state: no drives, no reset, DMA setup: ;Prepare for a Read or Write operation push bc ;Save them... push hl ld b,d ;Drive no. inc b ld a,08h su1: add a,a djnz su1 ;Shift drive bit as reqd. ld (mask),a ;Save drive indicator bit ld b,a ;Local copy in0 a,(_DOR) ld c,a and 0fch ;Kill select bits or d ;Select reqd. drive or doron ;No reset, DMA out0 (_DOR),a ;Selected ld a,c and b ;Is this drive running? jr nz,su2 in0 a,(_DOR) or b ;Start it up out0 (_DOR),a ; Wait for motor to run-up. NB this delay assumes: ; 1. 16MHz CPU clock ; 2. 2 wait states per memory access ; 3. Z-80 instruction cycle-counts ld a,(ix+MTRON) ;Start delay add a,a ;Scale for inner loop ld bc,0 ;Prime for inner loop mo1: djnz mo1 ;17*256 = 4352 clocks dec c ; 6 jr nz,mo1 ; 17 ; ---- ; 4375 clocks ; x 256 ; ------- ; 1,120,000 clocks ; or, 1/16 second dec a jr nz,mo1 ;Full delay su2: ;Send the SPECIFY command (all from DPB) ld a,(ix+DRATE) out0 (_CCR),a ;Data rate as reqd. ld a,03h ;"Specify" call sendbyte ld a,(ix+SPEC_1) call sendbyte ld a,(ix+SPEC_2) res 0,a ;Be sure DMA is activated call sendbyte ld hl,calibd ld a,(mask) and (hl) ;Is this drive calibrated? jr nz,su3 ;Done if so ld a,cmd_recal call sendbyte ;Send the "recal" command ld a,d call sendbyte ;Drive no. call endseek ;Finish the operation jr c,su5 ;Jump if error ld a,(mask) or (hl) ld (hl),a ;Flag it calibrated, now su3: xor a ;Success... su5: and a ;Set the Z bit pop hl pop bc ret ;Done: Z set if OK ;====================================================================== ; C O M M A N D D E S P A T C H E R global diskop diskop: cp maxcmd jr c,do1 ld a,badcmd scf ret ;Illegal command do1: call entry ;Enter the slave routine push af ;Save exit status call c,reset ;If errors, reset the FDC pop af ret c ;If error, take exit code xor a ;If OK, return zero ret ;Back to caller entry: push hl ;Save it ld hl,dtab add a,a ;Scale opcode by 2 add a,l ld l,a ;Access the jumptable jr nc,do2 inc h ;Propagate carry do2: ld a,(hl) ;Look into the table inc hl ld h,(hl) ld l,a ex (sp),hl ;Recover HL: routine ptr. on stack ret ;Switch to routine dtab: ;Pointers to function routines dw reset dw motors dw xread ;I/O functions: call wrappers dw xwrite dw xverf dw xform dw absaddr maxcmd equ ($-dtab)/2 ;No. of valid commands ;====================================================================== ; I / O C O M M A N D W R A P P E R F U N C T I O N ; The READ, WRITE, VERIFY and FORMAT commands are essentially identical. ; The despatcher calls a stub, which sets up a common wrapper to ; run the required sub-function, and to implement re-tries in the ; event of data errors. ; Wrapper stubs. The common tail is called with the user's HL stacked, ; and HL pointing to the required sub-function. jpopc equ 0c3h ;A "JP" opcode xread: push hl ld hl,read ;Sub-function pointer jr comtail xwrite: push hl ld hl,write jr comtail xverf: push hl ld hl,verify jr comtail xform: push hl ld hl,format comtail: ;Common tail of the "wrapper" function ld (switch+1),hl ;Target for the despatcher pop hl ;Caller's value push af ld a,jpopc ld (switch),a ;Complete the "JP" instruction push hl ld hl,0 ld (blksze),hl ;Default value pop hl ld a,tries again: ld (rtcnt),a ;Retry counter pop af push hl call switch ;To the sub-function pop hl ;Save HL (no others changed) jr nc,ok ;Exit: no error cp ioerr ;Was it an IO error? jr z,more cp sekerr ;Or a seek error jr nz,fatal ;No: other errors are fatal more: push af ;Seek or IO errors: retry call uncal ;Reset the "calibrated" bit ld a,(rtcnt) dec a ;Count attempts jr nz,again ;More to go pop af ;Exhausted: get the error code fatal: scf ;Hard errors ld de,restab ;Pass the result pointer ret ok: ld de,(blksze) add hl,de ;Success: index HL past block ld de,restab ;Return DE -> status block ret ;------------------------------- fails: ;Common stub for sub-functions to exit with error scf ret ;====================================================================== ; R E S E T T H E D I S K E T T E S Y S T E M reset: push hl xor a ld (calibd),a ;All drives uncalibrated out0 (_DOR),a ;Force reset ld a,doron out0 (_DOR),a ;All drives off (DMA asserted) ld hl,configtab call sendcmdstrg ;"Configure" xor a ;Post OK pop hl ret configtab: db ecft-$-1 ;Length db 13h ;"Configure" db 00h ;Required db 71h ;No FIFO in use db 43 ;Write precomp point ecft equ $ ;====================================================================== ; T U R N O F F A L L D R I V E - M O T O R S ; This command is really only needed until interrups are supported, ; since it is then possible to automatically turn off a drive which has ; not been accessed for some time. ; This command is used by the elementary BIOS keyboard routine: the ; drives are turned off if the system has waited for keyboard input ; for too long - a simple method! motors: in0 a,(_DOR) and 0fh ;Drop motor lines: keep selection out0 (_DOR),a xor a ;"Success" ret ;====================================================================== ; R E A D O N E O R M O R E S E C T O R S read: call setup ;Drive selected & ready jp nz,fails call dmainput ;Set up DMA pointers for input call transze ;Get total buffer size ld a,dma_incmd out0 (dmode),a ;DMA set up: IO => MEM call launch ;Go fire it off db cmd_read ;Command code db 40h ;Expected ST0 db 80h ;Expected ST1 ret ;CY=fault: HL -> result phase ;====================================================================== ; W R I T E O N E O R M O R E S E C T O R S write: call setup ;Drive selected & ready jp nz,fails call dmaoutput ;Set up DMA pointers for output call transze ;Get total buffer size ld a,dma_outcmd out0 (dmode),a ;DMA set up: MEM => IO call launch ;Go fire it off db cmd_write ;Command code db 40h ;Expected ST0 db 80h ;Expected ST1 ret ;CY=fault: HL -> result phase ;====================================================================== ; V E R I F Y S E C T O R S - N O T R A N S F E R verify: call setup ;Drive selected & ready jp nz,fails call launch ;Go fire it off db cmd_verify ;Command code db 0 ;Expected ST0 db 0 ;Expected ST1 ret ;CY=fault: HL -> result phase ;====================================================================== ; F O R M A T A T R A C K O F T H E D I S K E T T E format: ifdef incformat ;Do we include FORMAT ? call setup ;Drive running, & calibrated jp nz,fails ld a,cmd_seek ;Seek to the required track call sendbyte ;We cannot use "implied seeks" here ld a,d bit 0,c jr z,fm1 set 2,a ;A = drive & head bits fm1: call sendbyte ld a,c srl a ;Cylinder no. call sendbyte call endseek ;Wait for seek to complete ret c ;Failed call dmaoutput ;DMA pointers for output push hl ld l,(ix+EOT) ;No. of sectors ld h,0 add hl,hl add hl,hl ;4 bytes/sector out0 (bcr0l),l out0 (bcr0h),h ;Set up DMA counter ld (blksze),hl pop hl ld a,dma_outcmd out0 (dmode),a ;DMA armed to output ld a,cmd_format ;Now initiate the FDC call sendbyte ld a,d bit 0,c jr z,fm2 set 2,a ;Side select fm2: call sendbyte ;Drive & side ld a,(ix+SECSZE) call sendbyte ;Sector size ld a,(ix+EOT) call sendbyte ;Final sector no. ld a,(ix+GAPFMT) call sendbyte ;Gap-3 length ld a,dma_run out0 (dstat),a ;Kick off the DMA ld a,(ix+DATFMT) call sendbyte ;Last byte: FDC running push iy ld iy,fmtres ;Expected results call testresult ;Wait for it... pop iy ret ;A and CY show result fmtres: db 0 ;Filler db 0 ;ST-0 db 0 ;ST-1 else jp fails ;No FORMAT command endif ;====================================================================== ; C O N V E R T L O G I C A L T O P H Y S I C A L A D D R E S S ; This utility converts a logical address (in HL) to a 20-bit physical ; address (in AHL). Other registers are unchanged. Absolute addresses ; are used by the Z182 DMA. ; The routine accesses the memory-mapping hardware registers, to obtain ; the current translations. ;NB This code assumes that CA1 > BA > CA0 absaddr: ;Converts HL to AHL push hl ld a,h ;First, see which logical bank and 0f0h ld h,a ;Save 4kB page in0 a,(cbar) and 0f0h ;CA1 logical base ld l,a ld a,h sub l ;Form Addr - Base jr c,not1 ;If CY: Addr < Base, so don't use in0 a,(cbr) ;It is CA1 - take base jr mod not1: in0 a,(cbar) add a,a add a,a add a,a add a,a ;BA logical base in A[7:4] ld l,a ld a,h sub l ;Form Addr - Base ld a,0 jr c,mod ;Not BA, must be CA0 in0 a,(bbr) ;Else, it is BA mod: pop hl ;Now do the adjustment push bc ;Save it push hl ;Save HL again ld c,h ld b,0 ;BC = HL >> 8 ld l,a ld h,b ;HL = physical base add hl,hl add hl,hl add hl,hl add hl,hl ;HL = physical base << 4 add hl,bc ;Top address in HL ld a,h and 0fh ;Bits 19:16 in A ld b,l ;Save bits 15:8 pop hl ld h,b ;Full address in AHL pop bc ;Restore BC and a ;CY=0 (ie no errors) ret ;Done end d hl,hl add hl,hl add hl,hl add hl,hl ;HL = physical base << 4 add hl,bc ;Top address in HL ld a,h and 0fh ;Bits 19:16 in A ld b,l ;Save bits 15:8 pop hl ld h,b ;Full address in AHL pop bc ;Restore BC and a ;CY=0 (ie no erro:20010000C38A04E9496E736572742073797374656D206469736B20696E206472697665204F :2001200024456E7465722064726976652066726F6D20776869636820746F2072656164207D :2001400053797374656D20547261636B2F733A2024456E74657220647269766520746F208A :20016000626520666F726D61747465643A2024496E73657274206469736B20746F20666F1C :20018000726D617420262068697420456E7465723A2024466F726D617474696E672E2E2EBF :2001A0000D0A24466F726D617420616E6F746865723F205B592F4E5D20243A20616E6420AC :2001C00068697420456E7465722024496E76616C69642063686F6963653A207472792061EC :2001E0006761696E210D0A24466F726D6174207375636365737366756C210D0A240D0A24A4 :20020000CD1C07D0874F0600212602095E2356D51136023E09CD0500D13E09CD05003E00BA :20022000CD1C070E00C3050049025F0275028D029D02B302C602466174616C206469736B77 :20024000206572726F723A2024526563616C6962726174696F6E206572726F720D0A2445CD :2002600072726F722066726F6D2046444320636869700D0A24536563746F7273206F7665AC :200280007272756E20747261636B0D0A24444D41206C6F737420646174610D0A244F70655A :2002A000726174696F6E2074696D6564206F75740D0A24496E76616C69642066756E6374C4 :2002C000696F6E0D0A245365656B206572726F720D0A243E263206091106090E0ACD0500E1 :2002E00011FD010E09CD0500C9F50E09CD0500F1C6415F0E02CD050011BA010E09CD050071 :20030000CDD302C9D511CB010E09CD0500D1D50E09CD0500CDD3023A0709A7D128E63A0894 :2003200009FE603802CBAFFE510E00CC0500FE4330D2D641D5571EFF2A010001FDFF090E92 :2003400002CD0301427BD1FEFF28B978C9DD46043A0309571E013E03CD0002C90E001E0134 :20036000DD7E04B83013C53E02DD4604C5D5CD0002D1C1F190470C1E013E02CD0002C90130 :200380001202030405060708090A0B0C0D0E0F1011010A020B030C040D050E060F07100834 :2003A000110912010902030405060708070809010203040506010602070308040905DD4667 :2003C00004C5E5CB0971CBBE237907E60177231A771323DD7E03772310EBE1C1C9C5212E44 :2003E00009CDBE033A0309571E013E05CD0002C1C9DD2A04090E00DD7E04117F03FE1228C2 :200400000311A303CDDD030CDD7E04119103FE12280311AC03CDDD030CDD7E04119103FEAF :2004200012280311B503CDDD03D879DDBE0B20E8C9DD2A0409DD46040E00C5212E093A039E :2004400009571E013E04CD0002C1790CDDBE0B20E9C9466F726D617474696E672E2E2E0D9C :200460000A24566572696679696E672E2E2E0D0A2457726974696E672053797374656D202D :20048000547261636B2F730D0A240E0DCD05002A010001150009CD03012A010001FDFF0951 :2004A0000E00CD0301112101CD0E03320009DD2201091104013A0009CDE902DD2A01093AAC :2004C0000009570612217609CD5C03115101CD0E03320309DD220409116F010E09CD0500E3 :2004E000CDD3023E00CD00021152040E09CD0500CDF1031162040E09CD0500CD3104117158 :20050000040E09CD0500217609DD46040E00CD4D03DD7E04FE120E01C44D0311E8010E0959 :20052000CD050011A3010E09CD0500CDD3023A0709A7280B3A0809FE59289DFE7928993EA8 :2005400000CD00023E00C30500C5D50100001614ED38DECB77280B0D20F610F41520F13705 :200560001801AFD1C1C9CD49053E053841C5D511782D0607CDBC05121310F9D1C121782D10 :20058000E57EE6F8FDBE012021237EFDBE02201A237ED6002014ED2826ED3827B5E13E047B :2005A0002008AF18093E033718043E02E137C9F5ED3894CB7F28F9F1ED3995C9ED3894CB7C :2005C0007F28F9ED3895C9C546237ECDAF0510F9C1C9E521762D3A772D2FA677E1C9CD7B73 :2005E00008ED2923ED2124ED39253EA0ED3920AFED3921ED3922C9CD7B08ED2920ED21215D :20060000ED39223EA0ED3923AFED3924ED3925C9FDE37B803D3DDDBE04308A3C67FD7E0092 :20062000CDAF057ACB412802CBD7CDAF0579CB3FCDAF0579E601CDAF057BCDAF05DD7E0327 :20064000CDAF057CCDAF05DD7E05CDAF053E63ED39303EFFCDAF05CD6605C5F5010300FD93 :2006600009F1C1FDE3C9E5D5C5214000DD4603042910FD545D210000C1C51910FDED29261C :20068000ED212722832DC1D1E1C9CD49053E05D83E08CDAF05CDBC0547CDBC05C5CB39B935 :2006A000C13E0737C078E6E0FE20C83E0137C9C5E542043E088710FD32772D47ED38924FED :2006C000E6FCB2F60CED399279A02016ED3892B0ED3992DD7E0A8701000010FE0D20FB3DFE :2006E00020F8DD7E0CED39973E03CDAF05DD7E00CDAF05DD7E01CB87CDAF0521762D3A777C :200700002DA620133E07CDAF057ACDAF05CD8A0638063A772DB677AFA7E1C1C9FE0738046A :200720003E0637C9CD2F07F5DCA507F1D8AFC9E5213F0787856F3001247E23666FE3C9A5D1 :2007400007C0074D07530759075F077B08E521CA071810E521E207180AE521FA071804E5BC :2007600021070822812DE1F53EC332802DE521000022832DE13E03327F2DF1E5CD802DE1BA :200780003018FE022804FE07200BF5CDD2053A7F2D3D20E3F13711782DC9ED5B832D19112D :2007A000782DC937C9E5AF32762DED39923E0CED399221BB07CDC705AFE1C9041300712B20 :2007C000ED3892E60FED3992AFC9CDAF06C2A307CDDE05CD66063ECDED3931CD100646409B :2007E00080C9CDAF06C2A307CDF705CD66063EF1ED3931CD1006454080C9CDAF06C2A3079B :20080000CD1006560000C9CDAF06C2A3073E0FCDAF057ACB412802CBD7CDAF0579CB3FCDF7 :20082000AF05CD8A06D8CDF705E5DD6E0426002929ED2926ED212722832DE13EF1ED3931B0 :200840003E4DCDAF057ACB412802CBD7CDAF05DD7E03CDAF05DD7E04CDAF05DD7E07CDAF1C :20086000053E63ED3930DD7E08CDAF05FDE5FD217808CD6605FDE1C9000000E57CE6F0679B :20088000ED383AE6F06F7C953805ED38381811ED383A878787876F7C953E003803ED38390E :1608A000E1C5E54C06006F6029292929097CE60F45E160C1A7C9C1 :00000001FF DAF057ACB412802CBD7CDAF0579CB3FCDF7 :20082000AF05CD8A06D8CDF705E5DD6E0426002929ED2926ED212722832DE13EF1ED3931B0 :200840003E4DCDAF057ACB412802CBD7CDAF05DD7E03CDAF05DD7E04CDAF05DD7E07CDAF1C :20086000053E63ED3930DD7E08CDAF05FDE5FD217808CD6605FDE1C9000000E5 page 90 title Format Program ;===============================================================; ; ; ; D I S K E T T E F O R M A T P R O G R A M ; ; ; ;===============================================================; ;=======================================================================; ; ; ; D-X Designs Pty. Ltd. Perth, Western Australia ; ; Project: 112 May, 1996 ; ; ; ; Copyright (C) 1996 David R. Brooks ; ; ; ; This program is free software; you can redistribute it and/or ; ; modify it under the terms of the GNU General Public License ; ; as published by the Free Software Foundation; either version 2 ; ; of the License, or (at your option) any later version. ; ; ; ; This program is distributed in the hope that it will be useful, ; ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; ; GNU General Public License for more details. ; ; ; ; You should have received a copy of the GNU General Public License ; ; along with this program; if not, write to the Free Software ; ; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ; ; ; ;=======================================================================; Z80182 equ 0 include Z180.INC include DPARM.INC include ASCII.INC .radix 10 extrn diskop ;Disk subsystem BIOS equ 0 ;Pointers to CP/M services BDOS equ 5 cseg jp start dseg sysdrv: ds 1 ;Drive to read system tracks systab: ds 2 ;Ptr. to its hardware params. fmtdrv: ds 1 ;Drive to format (may be the same) fmttab: ds 2 ;Ptr. to its hardware params. reply: ds 40 ;User-reply buffer srp equ $-reply-2 ;Useful length fbuf: ds 4*18 ;Format table buffer sysbuf: ds 18*512 ;Buffer for system track/s cseg jphl: jp (hl) ;Just a routine hook sysdsk: db 'Insert system disk in drive $' sysmsg: db 'Enter drive from which to read System Track/s: $' fdmsg: db 'Enter drive to be formatted: $' reqmsg: db 'Insert disk to format & hit Enter: $' formsg: db 'Formatting...', ascicr, ascilf, '$' mormsg: db 'Format another? [Y/N] $' endst: db ': and hit Enter $' ermsg: db 'Invalid choice: try again!', ascicr, ascilf, '$' suxes: db 'Format successful!', ascicr, ascilf, '$' nline: db ascicr,ascilf,'$' ;================================================================== disk: ;Disk function, & trap errors call diskop ret nc ;Back if OK add a,a ;Error code ld c,a ld b,0 ld hl,etab-2 add hl,bc ;Point into table ld e,(hl) inc hl ld d,(hl) push de ld de,ec0 ld a,9 call BDOS ;Message preamble pop de ld a,9 call BDOS ;Display error ld a,0 call diskop ;Reset disks ld c,0 jp BDOS ;Escape to CP/M etab: dw ec1 dw ec2 dw ec3 dw ec4 dw ec5 dw ec6 dw ec7 ec0: db 'Fatal disk error: $' ec1: db 'Recalibration error', ascicr,ascilf,'$' ec2: db 'Error from FDC chip', ascicr,ascilf,'$' ec3: db 'Sectors overrun track', ascicr,ascilf,'$' ec4: db 'DMA lost data', ascicr,ascilf,'$' ec5: db 'Operation timed out', ascicr,ascilf,'$' ec6: db 'Invalid function', ascicr,ascilf,'$' ec7: db 'Seek error', ascicr,ascilf,'$' ;-------------------------------- input: ;Get a reply from user ld a,srp ld (reply),a ld de,reply ld c,0ah call BDOS ;Read to buffer ld de,nline ld c,9 ;Newline after call BDOS ret ;-------------------------------- diskin: ;Call user to insert disk push af ld c,9 call BDOS ;Send 1st msg (DE^) pop af add a,'A' ;Drive letter ld e,a ld c,2 call BDOS ;Output it ld de,endst ld c,9 call BDOS call input ;Pause for reply ret ;-------------------------------- repeat: ;Internal label: repeat query push de ld de,ermsg ld c,9 call BDOS pop de getdrv: ;Call for user's drive selection push de ld c,9 call BDOS ;Display prompt call input ld a,(reply+1) ;Reply may not be null and a pop de jr z,repeat ;Retry if bad ld a,(reply+2) cp 60h jr c,gd1 res 5,a ;Fold case gd1: cp 'Q' ld c,0 call z,BDOS ;"Q" exits cp 'C' ;Highest drive currently jr nc,repeat sub 'A' ;Drive no. push de ld d,a ld e,-1 ;Request drive type ld hl,(BIOS+1) ld bc,-3 ;Point at overload entry add hl,bc ld c,2 call jphl ;To BIOS (special entry) ld b,d ;Save drive no. ld a,e ;Drive type pop de cp -1 ;Invalid drive? jr z,repeat ld a,b ret ;Back: see A & IX ;-------------------------------- wstk: ;Write one System Track (in C) ld b,(ix+EOT) ;All sectors ld a,(fmtdrv) ld d,a ;Drive ld e,1 ;From Sector 1 ld a,3 ;Write call disk ret ;-------------------------------- ; Code fragment to boot in CP/M, allowing for 1 or 2 system tracks. ; Lifted from the Boot Sector code ; On entry, D = Drive ; E = Drive-type code (for BIOS) ; B = Total sectors reqd. ; IX -> DPB ; HL -> Load-base systrk: ld c,0 ;First system track ld e,1 ;Including boot sector ld a,(ix+EOT) ;Final sector, this track cp b ;Is that enough? jr nc,onetrk push bc ;Save total sectors ld a,2 ;No: read an extra track ld b,(ix+EOT) ;Sectors on this track push bc push de call disk ;Read 1st track pop de ;HL is updated pop bc pop af ;Total sectors reqd. (B -> A) sub b ;Less those already read ld b,a inc c ;Next track ld e,1 ;Start at the beginning onetrk: ld a,2 ;"Read" last/only track call disk ret ;============================================================= ; F O R M A T - E N G I N E P R O P E R ;Sector interlace tables t0_18: db 1, 18, 2, 3, 4, 5, 6, 7, 8 ;System track (18 sectors) db 9, 10, 11, 12, 13, 14, 15, 16, 17 ;Special skew tn_18: db 1, 10, 2, 11, 3, 12, 4, 13, 5 ;Data tracks db 14, 6, 15, 7, 16, 8, 17, 9, 18 ;Skewed 2:1 t0_9: db 1, 9, 2, 3, 4, 5, 6, 7, 8 ;System Tk-0 (9 sectors) t1_9: db 7, 8, 9, 1, 2, 3, 4, 5, 6 ;System Tk-1 tn_9: db 1, 6, 2, 7, 3, 8, 4, 9, 5 ;data tracks maktab: ;Build the sector initialisation table ;DE -> table, HL -> buffer, C = track ld b,(ix+EOT) ;Final sector push bc push hl rrc c ;Track => Cyl., Side mt1: ld (hl),c res 7,(hl) ;Cylinder inc hl ld a,c rlca and 1 ld (hl),a ;Side inc hl ld a,(de) ld (hl),a ;Sector inc de inc hl ld a,(ix+SECSZE) ld (hl),a ;Sector size inc hl djnz mt1 pop hl pop bc ret fortrk: ;Format this track push bc ;Track in C, DE -> table ld hl,fbuf call maktab ld a,(fmtdrv) ld d,a ;Drive no. ld e,1 ;Start at Sector 1 ld a,5 ;"Format" call disk pop bc ret format: ld ix,(fmttab) ld c,0 ;Track 0 ld a,(ix+EOT) ld de,t0_18 cp 12h ;18-sector track? jr z,dot0 ld de,t0_9 ;Else, 9-sector dot0: call fortrk inc c ;Track 1 ld a,(ix+EOT) ld de,tn_18 ;18-sectors (as data)? cp 12h jr z,dot1 ld de,t1_9 ;Else 9-sector Tk-1 dot1: call fortrk fm1: inc c ;All other tracks ld a,(ix+EOT) ld de,tn_18 ;Try 18 sectors cp 12h jr z,dotn ld de,tn_9 ;Else 9 sectors dotn: call fortrk ret c ld a,c cp (ix+MAXCYL) ;Do the lot... jr nz,fm1 ret verify: ld ix,(fmttab) ld b,(ix+EOT) ld c,0 vl1: push bc ld hl,fbuf ld a,(fmtdrv) ld d,a ;Drive no. ld e,1 ;From Sector 1 ld a,4 ;"Verify" call disk pop bc ld a,c inc c cp (ix+MAXCYL) jr nz,vl1 ret fmtmsg: db 'Formatting...',ascicr,ascilf,'$' vermsg: db 'Verifying...',ascicr,ascilf,'$' wrmsg: db 'Writing System Track/s',ascicr,ascilf,'$' ;============================================================= start: ld c,0dh call BDOS ;Reset BDOS ld hl,(BIOS+1) ;Addr. of warm boot ld bc,15h ;Offset to Home/Flush add hl,bc call jphl ;Flush BIOS sector buffer ld hl,(BIOS+1) ld bc,-3 add hl,bc ;Point to "overloaded" entry ld c,0 call jphl ;Hard disk-subsystem reset ld de,sysmsg call getdrv ;System-tracks drive ld (sysdrv),a ;Save the details ld (systab),ix ld de,sysdsk ld a,(sysdrv) call diskin ;Request to load System disk ld ix,(systab) ;Parameter ptr. ld a,(sysdrv) ld d,a ;Drive ld b,18 ;Read all sectors ld hl,sysbuf call systrk ;Read system tracks ld de,fdmsg call getdrv ld (fmtdrv),a ld (fmttab),ix ;Save details for Format drive NFORM: ;Entry to format another disk ld de,reqmsg ld c,9 call BDOS ;"Insert disk..." call input ld a,0 call disk ;Force recalibrate ld de,fmtmsg ld c,9 call BDOS call format ;Do the format ld de,vermsg ld c,9 call BDOS call verify ;Verify ld de,wrmsg ld c,9 call BDOS ;Writing system tracks ld hl,sysbuf ld b,(ix+EOT) ;No. of sectors ld c,0 call wstk ;Write 1 track ld a,(ix+EOT) cp 12h ;Was that all? ld c,1 ;No, need Track 1 also call nz,wstk ld de,suxes ;OK! ld c,9 call BDOS ld de,mormsg ;More? ld c,9 call BDOS call input ld a,(reply+1) ;Get reply and a jr z,xit ;Null: quit ld a,(reply+2) ;Else, 1st. char. cp 'Y' jr z,NFORM ;Yes - repeat cp 'y' jr z,NFORM xit: ld a,0 call disk ;Done: clear disk subsystem ld a,0 jp BDOS ;Then back to CP/M end lso call nz,wstk ld de,suxes ;OK! ld c,9 call BDOS ld de,mormsg ;More? ld c,9 call BDOS call input ld a,m80 format,format=format m80 diskop,diskop=diskop l80 /p:100,/d:900,format,diskop,format/n:p/y/x/e PPIP18 LBRUUDECODEBAKAUUDECODEPASKUSER MACPPPIP18 LBRSSTAT COM#TUVRECEIVE UUE_;OQRSWREADME TXTxyFORMAT SUBzFORMAT $$$RECEIVE UUE_.xlist .z80 ; Macros to define the Z-180 extended instructions. ; ; D-X Designs Pty. Ltd. 4/12/95 D. R. Brooks ; ; WARNING! These instructions are NOT supported by ; Z80MU. However the IO instructions are ; necessary to ensure correct access to ; the internal machine registers, which ; fully decode all 16 address bits. ; ; Adapted from Zilog (file 182macro.lib) ; Enhanced to provide conditional definition for the ; following chips (define the appropriate symbol) ; Z80180 Default ; Z80S180 ; Z80181 ; Z80182 ; First, check only one CPU is defined ifdef Z80180 ?test equ 0 ;These will throw a "Multiple endif ; Definition" error if 2 CPU's ifdef Z80S180 ; are defined ?test equ 1 endif ifdef Z80181 ?test equ 2 endif ifdef Z80182 ?test equ 3 endif ;========== Z180 Internal Interrupt Vectors ======== ; The following vectors are offsets from the value ; loaded in IL, the Interrupt Vector Low register. VINT1 equ 0 ;External INT-1 pin VINT2 equ 2 ;External INT-2 pin VPRT0 equ 4 ;Timer 0 VPRT1 equ 6 ;Timer 1 VDMA0 equ 8 ;DMA Ch-0 VDMA1 equ 0ah ;DMA Ch-1 VCSIO equ 0ch ;Clocked serial I/O VASC0 equ 0eh ;Asynch. comms. Ch-0 VASC1 equ 10h ;Asynch. comms. Ch-1 ;========== Z180 System Control Registers ========== ;NB These registers may be relocated to multiples of ; 40H, by setting the IO Control Register (ICR = 3FH) ; The addresses below are valid with ICR=0 (else they ; are offsets from the ICR base value). ;ASCI Registers cntla0 equ 00h ;ASCI Control Reg A Ch0 cntla1 equ 01h ;ASCI Control Reg A Ch1 cntlb0 equ 02h ;ASCI Control Reg B Ch0 cntlb1 equ 03h ;ASCI Control Reg B Ch1 stat0 equ 04h ;ASCI Status Reg Ch0 stat1 equ 05h ;ASCI Status Reg Ch1 tdr0 equ 06h ;ASCI TX Data Reg Ch0 tdr1 equ 07h ;ASCI TX Data Reg Ch1 rdr0 equ 08h ;ASCI RX Data Reg Ch0 rdr1 equ 09h ;ASCI RX Data Reg Ch1 brk0 equ 12h ;Break Control Reg Ch0 brk1 equ 13h ;Break Control reg Ch1 ;CSI/O Registers cntr equ 0ah ;CSI/O Control Reg trdr equ 0bh ;CSI/O TX/RX Data Reg ;Timer Registers tmdr0l equ 0ch ;Timer Data Reg Ch0-Low tmdr0h equ 0dh ;Timer Data Reg Ch0-High rldr0l equ 0eh ;Timer Reload Reg Ch0-Low rldr0h equ 0fh ;Timer Reload Reg Ch0-High tcr equ 10h ;Timer Control Reg tmdr1l equ 14h ;Timer Data Reg Ch1-Low tmdr1h equ 15h ;Timer Data Reg Ch1-High rldr1l equ 16h ;Timer Reload Reg Ch1-Low rldr1h equ 17h ;Timer Reload Reg Ch1-High frc equ 18h ;Free-Running Counter ifdef Z80S180 ccr equ 1fh ;CPU Control Reg endif ;DMA Registers sar0l equ 20h ;DMA Source Addr Reg Ch0-Low sar0h equ 21h ;DMA Source Addr Reg Ch0-High sar0b equ 22h ;DMA Source Addr Reg Ch0-B dar0l equ 23h ;DMA Destn Addr Reg Ch0-Low dar0h equ 24h ;DMA Destn Addr Reg Ch0-High dar0b equ 25h ;DMA Destn Addr Reg Ch0-B bcr0l equ 26h ;DMA Byte Count Reg Ch0-Low bcr0h equ 27h ;DMA Byte Count Reg Ch0-High mar1l equ 28h ;DMA Memory Addr Reg Ch1-Low mar1h equ 29h ;DMA Memory Addr Reg Ch1-High mar1b equ 2ah ;DMA Memory Addr Reg Ch1-B iar1l equ 2bh ;DMA I/O Addr Reg Ch1-Low iar1h equ 2ch ;DMA I/O Addr Reg Ch1-High bcr1l equ 2eh ;DMA Byte Count Reg Ch1-Low bcr1h equ 2fh ;DMA Byte Count Reg Ch1-High dstat equ 30h ;DMA Status Reg dmode equ 31h ;DMA Mode Reg dcntl equ 32h ;DMA/WAIT Control Reg ;System Control Registers il equ 33h ;INT Vector Low Reg itc equ 34h ;INT/TRAP Control Reg rcr equ 36h ;Refresh Control Reg cbr equ 38h ;MMU Common Base Reg bbr equ 39h ;MMU Bank Base Reg cbar equ 3ah ;MMU Common/Bank Area Reg omcr equ 3eh ;Operation Mode Control Reg icr equ 3fh ;I/O Control Reg ifdef Z80181 ;Features unique to Z80181 ;Integral PIO device p1ddr equ 0e0h ;Data Direction Reg 1 p1dp equ 0e1h ;Port 1 Data p2ddr equ 0e2h ;Data Direction Reg 2 p2dp equ 0e3h ;Port 2 Data ;Integral CTC device ctc0 equ 0e4h ;CTC Channel 0 ctc1 equ 0e5h ;CTC Channel 1 ctc2 equ 0e6h ;CTC Channel 2 ctc3 equ 0e7h ;CTC Channel 3 scccr equ 0e8h ;SCC Control Reg sccdr equ 0e9h ;SCC Data Reg ;Chip-select output pins ramubr equ 0eah ;RAM Upper Boundary ramlbr equ 0ebh ;RAM Lower Boundary rombr equ 0ech ;ROM Boundary scr equ 0edh ;System Control Reg endif ifdef Z80182 ;Features unique to Z80182 ccr equ 1fh ;CPU control reg. intype equ 0dfh ;Interrupt edge/pin mux reg. wsgcs equ 0d8h ;Wait-State Generator CS enh182 equ 0d9h ;Z80182 Enhancements Reg pinmux equ 0dfh ;Interrupt Edge/Pin Mux Reg ramubr equ 0e6h ;RAM End Boundary ramlbr equ 0e7h ;RAM Start Boundary rombr equ 0e8h ;ROM Boundary fifoctl equ 0e9h ;FIFO Control Reg rtotc equ 0eah ;RX Time-Out Time Const ttotc equ 0ebh ;TX Time-Out Time Const fcr equ 0ech ;FIFO Register scr equ 0efh ;System Pin Control rbr equ 0f0h ;MIMIC RX Buffer Reg thr equ 0f0h ;MIMIC TX Holding Reg ier equ 0f1h ;Interrupt Enable Reg lcr equ 0f3h ;Line Control Reg mcr equ 0f4h ;Modem Control Reg lsr equ 0f5h ;Line Status Reg msr equ 0f6h ;Modem Status Reg mscr equ 0f7h ;MIMIC Scratch Reg dlatl equ 0f8h ;Divisor latch LS dlatm equ 0f9h ;Divisor latch MS ttcr equ 0fah ;TX Time Constant rtcr equ 0fbh ;RX Time Constant ivec equ 0fch ;MIMIC Interrupt Vector mimie equ 0fdh ;MIMIC Interrupt Enable Reg iusip equ 0feh ;MIMIC Interrupt Under-Service Reg mmcr equ 0ffh ;MIMIC Master Control Reg ;Z80182 PIO Registers ddra equ 0edh ;Data Direction Reg A dra equ 0eeh ;Port A Data ddrb equ 0e4h ;Data Direction Reg B drb equ 0e5h ;Port B Data ddrc equ 0ddh ;Data Direction Reg C drc equ 0deh ;Port C data ;ESCC Registers sccacnt equ 0e0h ;ESCC Control Channel A sccad equ 0e1h ;ESCC Data Channel A sccbcnt equ 0e2h ;ESCC Control Channel B sccbd equ 0e3h ;ESCC Data Channel B endif ;[E]SCC Internal Register Definitions RR0 equ 00h RR1 equ 01h RR2 equ 02h RR3 equ 03h RR6 equ 06h RR7 equ 07h RR10 equ 0ah RR12 equ 0ch RR13 equ 0dh RR15 equ 0fh WR0 equ 00h WR1 equ 01h WR2 equ 02h WR3 equ 03h WR4 equ 04h WR5 equ 05h WR6 equ 06h WR7 equ 07h WR9 equ 09h WR10 equ 0ah WR11 equ 0bh WR12 equ 0ch WR13 equ 0dh WR14 equ 0eh WR15 equ 0fh ;==== Define the additional Z-180 instructions ===== ;Machine registers (internal use only) ?b equ 0 ?c equ 1 ?d equ 2 ?e equ 3 ?h equ 4 ?l equ 5 ?a equ 7 ??bc equ 0 ??de equ 1 ??hl equ 2 ??sp equ 3 slp macro db 0edh db 76h endm mlt macro ?r db 0edh db 4ch+(??&?r AND 3) SHL 4 endm in0 macro ?r, ?p db 0edh db 0+(?&?r AND 7) SHL 3 db ?p endm out0 macro ?p, ?r db 0edh db 1+(?&?r AND 7) SHL 3 db ?p endm otim macro db 0edh db 83h endm otimr macro db 0edh db 93h endm otdm macro db 0edh db 8bh endm otdmr macro db 0edh db 9bh endm tstio macro ?p db 0edh db 74h db ?p endm tst macro ?r db 0edh ifidn ,<(hl)> db 34h else ifdef ?&?r db 4+(?&?r AND 7) SHL 3 else db 64h db ?r endif endif endm .list  macro db 0edh db 9bh endm tstio macro ?p db 0edh db 74h db ?p endm tst macro ?r db 0edh ifidn ,<(hl)> db 34h else ifdef ?&?r db 4+(?&?r AND 7) SHL 3 else db 64h db ?r endif endif endm .li page 90 title Basic diskette handler .comment $ ;=======================================================================; ; ; ; B A S I C D I S K - D R I V E R O U T I N E S ; ; ; ; Non-interrupt driven support routines for the SMC diskette chip. ; ; ; ;=======================================================================; ;=======================================================================; ; ; ; D-X Designs Pty. Ltd. Perth, Western Australia ; ; Project: 112 May, 1996 ; ; ; ; Copyright (C) 1996 David R. Brooks ; ; ; ; This program is free software; you can redistribute it and/or ; ; modify it under the terms of the GNU General Public License ; ; as published by the Free Software Foundation; either version 2 ; ; of the License, or (at your option) any later version. ; ; ; ; This program is distributed in the hope that it will be useful, ; ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; ; GNU General Public License for more details. ; ; ; ; You should have received a copy of the GNU General Public License ; ; along with this program; if not, write to the Free Software ; ; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ; ; ; ;=======================================================================; This code is designed to work without interrupts (compatible with the ROM bootstrap code). Consequently, timing functions are done by polling and/or delay loops. The DMA is used for data transfer, and is polled for completion (check that the byte counter has decremented to zero). Call: A - OPCODE: 0 - Reset disk system: all drives uncalibrated 1 - Turn motors off (leave drives calibrated) 2 - Read sector/s 3 - Write sector/s 4 - Verify sector/s 5 - Format track 6 - Translate logical address to physical B - No. of sectors to read/write C - Track No. (even tracks are Side 0, odd tracks are Side 1) D - Drive No. (0..3) E - Sector No. HL - Ptr. to data buffer (logical address) IX - Ptr. to Drive Parameter Block (DPB) Return: If successful: CY = 0 A undefined HL advanced past data block If errors: CY = 1 A status (see below) HL unchanged In either case: DE -> Result vector (7 bytes) IX, IY unchanged BC trashed $ Z80182 equ 0 include Z180.INC include DPARM.INC include FDC.INC incformat equ 0 ;Define this to include the FORMAT cmnd. .sall dseg ;====================================================================== ; L O C A L D A T A ;Return-error status values (in A, if CY=1) calerr equ 1 ;Error in a recalibration function ioerr equ 2 ;Error posted by Result Phase: see (HL) badsect equ 3 ;Sector/Length will overrun track lostdat equ 4 ;DMA did not transfer full block timeout equ 5 ;Interrupt timed out badcmd equ 6 ;Invalid function code sekerr equ 7 ;Seek error calibd: ds 1 ;Drives "Calibrated" flags mask: ds 1 ;Bit-mask of current drive restab: ds 7 ;Buffer for result-phase data rtcnt: ds 1 ;IO command retry count (after RESTAB) switch: ds 3 ;Builds a JP instruction tries equ 3 ;No. of retries on IO errors blksze: ds 2 ;Save block size cseg ;====================================================================== ; F . D . C . C O M M A N D C O D E S cmd_recal equ 7 ;Recalibrate cmd_sense equ 8 ;Sense Interrupt cmd_seek equ 0fh ;Seek to track cmd_read equ 46h ;Read (MFM, implied seek) cmd_write equ 45h ;Write, ditto cmd_verify equ 56h ;Verify, ditto cmd_format equ 4dh ;Format a track ; D . M . A . C O M M A N D S dma_incmd equ 0cdh ;IO => MEM dma_outcmd equ 0f1h ;MEM => IO dma_run equ 63h ;Kick off Channel-0 ;====================================================================== ; U T I L I T Y S U B R O U T I N E S waitint: ;Wait for interrupt (but polled) push bc push de ld bc,0 ;Inner timeout counters ld d,20 ;Coarse timeout setting w1: in0 a,(drc) ;Get interrupt lines bit 6,a jr z,w2 ;Go if interrupt set dec c jr nz,w1 djnz w1 ;65k loops dec d jr nz,w1 ;Coarse outer loop scf jr w3 ;Exit: timed out w2: xor a ;Exit: OK w3: pop de pop bc ret ;-------------------------------- testresult: ;Check results of I/O operations ; IY -> test-block for status: ; see "launch" for details call waitint ;Wait for completion ld a,timeout jr c,exit ;Failed (CY posted to caller) ;Get 7 result bytes after read/write push bc push de ld de,restab ;Point to Result Table ld b,7 ;No. of expected bytes lc3: call getbyte ld (de),a inc de ;Post it djnz lc3 pop de pop bc ld hl,restab ;Pointer to results block push hl ld a,(hl) and 0f8h ;Kill variable bits (just errors) cp (iy+tst0) ;Check to expected value jr nz,bad inc hl ld a,(hl) cp (iy+tst1) ;Check to expected value jr nz,bad inc hl ld a,(hl) sub 0 ;No "funny" errors (ever!) jr nz,bad in0 l,(bcr0l) in0 a,(bcr0h) or l ;Check that all was transferred pop hl ld a,lostdat jr nz,bad ;Should have counted back to zero xor a ;It all succeeded! jr exit ;OK: return CY=0 (A=0) bad1: ld a,badsect ;Bad sector specification scf jr exit bad: ld a,ioerr ;Error post: see block at (HL) pop hl scf exit: ret ;CY = error ;-------------------------------- sendbyte: ;Send A to Cmnd/data port push af scb1: in0 a,(_MSR) ;Check FDC status bit 7,a ;Wait till ready jr z,scb1 pop af ;Recover the cmnd. byte out0 (_DATA),a ret ;-------------------------------- getbyte: ;Read Cmnd/data port to A in0 a,(_MSR) bit 7,a ;Ready? jr z,getbyte in0 a,(_DATA) ;Get it ret ;-------------------------------- sendcmdstrg: ;Send string of commands from HL push bc ;1st. byte is count ld b,(hl) ;Save count scs1: inc hl ld a,(hl) ;Get cmnd. byte call sendbyte ;Send it djnz scs1 ;Repeat pop bc ret ;-------------------------------- uncal: ;Force a recalibrate on this drive push hl ld hl,calibd ;First force a recalibrate ld a,(mask) cpl and (hl) ;Turn of the "calibrated" bit ld (hl),a pop hl ret ;-------------------------------- dmainput: ;Set up DMA buffers for input call absaddr ;Get physical addr. for DMA out0 (dar0l),l out0 (dar0h),h out0 (dar0b),a ;Destination pointers ld a,_DMA out0 (sar0l),a ;Source: FDC's DMA port xor a out0 (sar0h),a out0 (sar0b),a ;Controlled by /DREQ0 ret ;-------------------------------- dmaoutput: ;Set up DMA buffers for output call absaddr ;Get physical addr. for DMA out0 (sar0l),l out0 (sar0h),h out0 (sar0b),a ;Source pointers ld a,_DMA out0 (dar0l),a ;Destn.: FDC's DMA port xor a out0 (dar0h),a out0 (dar0b),a ;Controlled by /DREQ0 ret ;-------------------------------- ;Offsets for inline arguments opcode equ 0 ;Command to FDC tst0 equ 1 ;Match Status 0 tst1 equ 2 ; " " 1 skip equ 3 ;No. of bytes to skip at return launch: ;Initiate a read or write command ex (sp),iy ;Save IY, point at argts. ld a,e ;Find final sector for transfer add a,b dec a ;Last sector to do dec a ;1 under final cp (ix+EOT) ;This MUST be < true final jr nc,bad1 inc a ;True final sector ld h,a ;Save it ld a,(iy+opcode) call sendbyte ;Command code ld a,d ;Drive bit 0,c ;Odd track (ie Side 1)? jr z,lc1 set 2,a lc1: call sendbyte ;Drive & head ld a,c srl a ;Cylinder call sendbyte ld a,c and 1 call sendbyte ;Head ld a,e call sendbyte ;Sector ld a,(ix+SECSZE) call sendbyte ;Sector length (encoded) ld a,h call sendbyte ;Final sector no. ld a,(ix+GPL) call sendbyte ;Gap length ld a,dma_run ;Activate DMA Ch-0 out0 (dstat),a ld a,0ffh ;Data transfer length (default) call sendbyte ;Final byte: FDC & DMA running call testresult ;Find out what happened push bc push af ld bc,skip add iy,bc ;Jump past the inline params. pop af pop bc ex (sp),iy ;Recover IY, post link ret ;-------------------------------- transze: ;Determine buffer size (DMA count set) push hl push de push bc ld hl,64 ld b,(ix+SECSZE) ;Size N, => 128*2^N inc b tz1: add hl,hl djnz tz1 ld d,h ld e,l ;Sector size in DE ld hl,0 pop bc ;No. of sectors in B push bc tz2: add hl,de ;Form total in HL djnz tz2 out0 (bcr0l),l ;Set DMA counter out0 (bcr0h),h ld (blksze),hl ;Save block size pop bc pop de ;Restore regs. pop hl ret ;-------------------------------- endseek: ;Finish of a seek/recalibrate function call waitint ;Wait for it ld a,timeout ret c ;Timed out ld a,cmd_sense ;"Sense Interrupt" at the end call sendbyte call getbyte ld b,a ;ST0 in B call getbyte ;PCN in A push bc ;Verify correct cylinder srl c cp c ;Yes? pop bc ld a,sekerr scf ret nz ;Quit if unequal ld a,b ;Get back ST0 and 0e0h cp 20h ;Look for success ret z ld a,calerr scf ret ;CY=1 if it failed ;-------------------------------- doron equ 0ch ;Basic state: no drives, no reset, DMA setup: ;Prepare for a Read or Write operation push bc ;Save them... push hl ld b,d ;Drive no. inc b ld a,08h su1: add a,a djnz su1 ;Shift drive bit as reqd. ld (mask),a ;Save drive indicator bit ld b,a ;Local copy in0 a,(_DOR) ld c,a and 0fch ;Kill select bits or d ;Select reqd. drive or doron ;No reset, DMA out0 (_DOR),a ;Selected ld a,c and b ;Is this drive running? jr nz,su2 in0 a,(_DOR) or b ;Start it up out0 (_DOR),a ; Wait for motor to run-up. NB this delay assumes: ; 1. 16MHz CPU clock ; 2. 2 wait states per memory access ; 3. Z-80 instruction cycle-counts ld a,(ix+MTRON) ;Start delay add a,a ;Scale for inner loop ld bc,0 ;Prime for inner loop mo1: djnz mo1 ;17*256 = 4352 clocks dec c ; 6 jr nz,mo1 ; 17 ; ---- ; 4375 clocks ; x 256 ; ------- ; 1,120,000 clocks ; or, 1/16 second dec a jr nz,mo1 ;Full delay su2: ;Send the SPECIFY command (all from DPB) ld a,(ix+DRATE) out0 (_CCR),a ;Data rate as reqd. ld a,03h ;"Specify" call sendbyte ld a,(ix+SPEC_1) call sendbyte ld a,(ix+SPEC_2) res 0,a ;Be sure DMA is activated call sendbyte ld hl,calibd ld a,(mask) and (hl) ;Is this drive calibrated? jr nz,su3 ;Done if so ld a,cmd_recal call sendbyte ;Send the "recal" command ld a,d call sendbyte ;Drive no. call endseek ;Finish the operation jr c,su5 ;Jump if error ld a,(mask) or (hl) ld (hl),a ;Flag it calibrated, now su3: xor a ;Success... su5: and a ;Set the Z bit pop hl pop bc ret ;Done: Z set if OK ;====================================================================== ; C O M M A N D D E S P A T C H E R global diskop diskop: cp maxcmd jr c,do1 ld a,badcmd scf ret ;Illegal command do1: call entry ;Enter the slave routine push af ;Save exit status call c,reset ;If errors, reset the FDC pop af ret c ;If error, take exit code xor a ;If OK, return zero ret ;Back to caller entry: push hl ;Save it ld hl,dtab add a,a ;Scale opcode by 2 add a,l ld l,a ;Access the jumptable jr nc,do2 inc h ;Propagate carry do2: ld a,(hl) ;Look into the table inc hl ld h,(hl) ld l,a ex (sp),hl ;Recover HL: routine ptr. on stack ret ;Switch to routine dtab: ;Pointers to function routines dw reset dw motors dw xread ;I/O functions: call wrappers dw xwrite dw xverf dw xform dw absaddr maxcmd equ ($-dtab)/2 ;No. of valid commands ;====================================================================== ; I / O C O M M A N D W R A P P E R F U N C T I O N ; The READ, WRITE, VERIFY and FORMAT commands are essentially identical. ; The despatcher calls a stub, which sets up a common wrapper to ; run the required sub-function, and to implement re-tries in the ; event of data errors. ; Wrapper stubs. The common tail is called with the user's HL stacked, ; and HL pointing to the required sub-function. jpopc equ 0c3h ;A "JP" opcode xread: push hl ld hl,read ;Sub-function pointer jr comtail xwrite: push hl ld hl,write jr comtail xverf: push hl ld hl,verify jr comtail xform: push hl ld hl,format comtail: ;Common tail of the "wrapper" function ld (switch+1),hl ;Target for the despatcher pop hl ;Caller's value push af ld a,jpopc ld (switch),a ;Complete the "JP" instruction push hl ld hl,0 ld (blksze),hl ;Default value pop hl ld a,tries again: ld (rtcnt),a ;Retry counter pop af push hl call switch ;To the sub-function pop hl ;Save HL (no others changed) jr nc,ok ;Exit: no error cp ioerr ;Was it an IO error? jr z,more cp sekerr ;Or a seek error jr nz,fatal ;No: other errors are fatal more: push af ;Seek or IO errors: retry call uncal ;Reset the "calibrated" bit ld a,(rtcnt) dec a ;Count attempts jr nz,again ;More to go pop af ;Exhausted: get the error code fatal: scf ;Hard errors ld de,restab ;Pass the result pointer ret ok: ld de,(blksze) add hl,de ;Success: index HL past block ld de,restab ;Return DE -> status block ret ;------------------------------- fails: ;Common stub for sub-functions to exit with error scf ret ;====================================================================== ; R E S E T T H E D I S K E T T E S Y S T E M reset: push hl xor a ld (calibd),a ;All drives uncalibrated out0 (_DOR),a ;Force reset ld a,doron out0 (_DOR),a ;All drives off (DMA asserted) ld hl,configtab call sendcmdstrg ;"Configure" xor a ;Post OK pop hl ret configtab: db ecft-$-1 ;Length db 13h ;"Configure" db 00h ;Required db 71h ;No FIFO in use db 43 ;Write precomp point ecft equ $ ;====================================================================== ; T U R N O F F A L L D R I V E - M O T O R S ; This command is really only needed until interrups are supported, ; since it is then possible to automatically turn off a drive which has ; not been accessed for some time. ; This command is used by the elementary BIOS keyboard routine: the ; drives are turned off if the system has waited for keyboard input ; for too long - a simple method! motors: in0 a,(_DOR) and 0fh ;Drop motor lines: keep selection out0 (_DOR),a xor a ;"Success" ret ;====================================================================== ; R E A D O N E O R M O R E S E C T O R S read: call setup ;Drive selected & ready jp nz,fails call dmainput ;Set up DMA pointers for input call transze ;Get total buffer size ld a,dma_incmd out0 (dmode),a ;DMA set up: IO => MEM call launch ;Go fire it off db cmd_read ;Command code db 40h ;Expected ST0 db 80h ;Expected ST1 ret ;CY=fault: HL -> result phase ;====================================================================== ; W R I T E O N E O R M O R E S E C T O R S write: call setup ;Drive selected & ready jp nz,fails call dmaoutput ;Set up DMA pointers for output call transze ;Get total buffer size ld a,dma_outcmd out0 (dmode),a ;DMA set up: MEM => IO call launch ;Go fire it off db cmd_write ;Command code db 40h ;Expected ST0 db 80h ;Expected ST1 ret ;CY=fault: HL -> result phase ;====================================================================== ; V E R I F Y S E C T O R S - N O T R A N S F E R verify: call setup ;Drive selected & ready jp nz,fails call launch ;Go fire it off db cmd_verify ;Command code db 0 ;Expected ST0 db 0 ;Expected ST1 ret ;CY=fault: HL -> result phase ;====================================================================== ; F O R M A T A T R A C K O F T H E D I S K E T T E format: ifdef incformat ;Do we include FORMAT ? call setup ;Drive running, & calibrated jp nz,fails ld a,cmd_seek ;Seek to the required track call sendbyte ;We cannot use "implied seeks" here ld a,d bit 0,c jr z,fm1 set 2,a ;A = drive & head bits fm1: call sendbyte ld a,c srl a ;Cylinder no. call sendbyte call endseek ;Wait for seek to complete ret c ;Failed call dmaoutput ;DMA pointers for output push hl ld l,(ix+EOT) ;No. of sectors ld h,0 add hl,hl add hl,hl ;4 bytes/sector out0 (bcr0l),l out0 (bcr0h),h ;Set up DMA counter ld (blksze),hl pop hl ld a,dma_outcmd out0 (dmode),a ;DMA armed to output ld a,cmd_format ;Now initiate the FDC call sendbyte ld a,d bit 0,c jr z,fm2 set 2,a ;Side select fm2: call sendbyte ;Drive & side ld a,(ix+SECSZE) call sendbyte ;Sector size ld a,(ix+EOT) call sendbyte ;Final sector no. ld a,(ix+GAPFMT) call sendbyte ;Gap-3 length ld a,dma_run out0 (dstat),a ;Kick off the DMA ld a,(ix+DATFMT) call sendbyte ;Last byte: FDC running push iy ld iy,fmtres ;Expected results call testresult ;Wait for it... pop iy ret ;A and CY show result fmtres: db 0 ;Filler db 0 ;ST-0 db 0 ;ST-1 else jp fails ;No FORMAT command endif ;====================================================================== ; C O N V E R T L O G I C A L T O P H Y S I C A L A D D R E S S ; This utility converts a logical address (in HL) to a 20-bit physical ; address (in AHL). Other registers are unchanged. Absolute addresses ; are used by the Z182 DMA. ; The routine accesses the memory-mapping hardware registers, to obtain ; the current translations. ;NB This code assumes that CA1 > BA > CA0 absaddr: ;Converts HL to AHL push hl ld a,h ;First, see which logical bank and 0f0h ld h,a ;Save 4kB page in0 a,(cbar) and 0f0h ;CA1 logical base ld l,a ld a,h sub l ;Form Addr - Base jr c,not1 ;If CY: Addr < Base, so don't use in0 a,(cbr) ;It is CA1 - take base jr mod not1: in0 a,(cbar) add a,a add a,a add a,a add a,a ;BA logical base in A[7:4] ld l,a ld a,h sub l ;Form Addr - Base ld a,0 jr c,mod ;Not BA, must be CA0 in0 a,(bbr) ;Else, it is BA mod: pop hl ;Now do the adjustment push bc ;Save it push hl ;Save HL again ld c,h ld b,0 ;BC = HL >> 8 ld l,a ld h,b ;HL = physical base add hl,hl add hl,hl add hl,hl add hl,hl ;HL = physical base << 4 add hl,bc ;Top address in HL ld a,h and 0fh ;Bits 19:16 in A ld b,l ;Save bits 15:8 pop hl ld h,b ;Full address in AHL pop bc ;Restore BC and a ;CY=0 (ie no errors) ret ;Done end d hl,hl add hl,hl add hl,hl add hl,hl ;HL = physical base << 4 add hl,bc ;Top address in HL ld a,h and 0fh ;Bits 19:16 in A ld b,l ;Save bits 15:8 pop hl ld h,b ;Full address in AHL pop bc ;Restore BC and a ;CY=0 (ie no erro;Standard drive-parameter block ; Format is same as MS-DOS BIOS SPEC_1 equ 0 ;"Specify" byte 1 SPEC_2 equ 1 ;"Specify" byte 2 MTROFF equ 2 ;Wait before stop motor SECSZE equ 3 ;Bytes/sector (must be > 0) EOT equ 4 ;Final sector no. GPL equ 5 ;Gap length DTL equ 6 ;Data transfer length GAPFMT equ 7 ;Gap-3 length: Format DATFMT equ 8 ;Data fill: Format SETTLE equ 9 ;Head-settle time (mS) MTRON equ 10 ;Motor-start (* 1/8 sec.) MAXCYL equ 11 ;Max. cylinder no. DRATE equ 12 ;Data rate  EOT equ 4 ;Final sector no. GPL equ 5 ;Gap length DTL equ 6 ;Data transfer length GAPFMT equ 7 ;Gap-3 length: Format DATFMT equ 8 ;Data fill: Format SETTLE equ 9 ;Head-settle ; Standard drive-type identifiers ntypes equ 5 ;No. of defined types D5_360 equ 0 ;5", 360kB D5_120 equ 1 ;5", 1.2MB D3_720 equ 2 ;3", 720kB D3_144 equ 3 ;3", 1.44MB D3_288 equ 4 ;3", 2.88MB ROMHOOK INCpBIOS HEX,qrsBIOS MACtuvwxyz{BIOS MAC5|}~BIOS SUBBIOSTOP MACDPARM INCDRVTYPE INC; Port definitions for the FDC37C665/6 combo chips ; Prefix a "_" as some names clash with Z180 names ; Diskette controller _DOR equ 92h ;Digital Output _MSR equ 94h ;Main Status _DSR equ 94h ;Data-rate Select _DATA equ 95h ;Data & commands I/O _DIR equ 97h ;Digital Input _CCR equ 97h ;Confign. Control _DMA equ 0a0h ;Diskette DMA address ; Serial port ;RD/WR _RBR equ 98h ;R Receiver buffer _THR equ 98h ;W Transmit holding reg. _IER equ 99h ;RW Interrupt-enable reg. _IIR equ 9ah ;R Interrupt ident. reg. _FCR equ 9ah ;W FIFO control reg. _LCR equ 9bh ;RW Line control reg. _MCR equ 9ch ;RW Modem control reg. _LSR equ 9dh ;RW Line status reg. _MMSR equ 9eh ;RW Modem status reg. (name clash w. FDC) _SCR equ 9fh ;N/A Scratch reg. (not avail. in XT) _DDL equ 98h ;RW Divisor LSB | with DLAB _DLM equ 99h ;RW Divisor MSB | set high 9ah ;R Interrupt ident. reg. _FCR equ 9ah ;W FIFO control reg. _LCR equ 9bh ;RW Line control reg. _MCR equ 9ch ;RW Modem control reg. _LSR equ 9dh ;RW Line status reg. _MMSR equ 9eh ;RW Modem status reg. (name clash w. FDC) _SCR equ 9fh ;N/A Scratch reg. (not avail. in XT) _DDL ascicr equ 0dh ;ASCII characters ascilf equ 0ah ascibs equ 08h asciht equ 09h asciesc equ 1bh space equ ' ' ascdel equ 7fh .comment $ R O M - M O N I T O R E X T E R N A L H O O K S Definitions of code-hooks for external entry to the ROM. These are intended for use by OS boot-sectors, etc. They MUST NOT be used by BIOS and similar code, since the ROM will be disabled. The symbolic names are those used in the ROM code for these routines. $ diskop equ 8 ;JP to diskette handler dpb3 equ diskop+3 ;Ptr. to 3" D.P.B. dpb5 equ dpb3+2 ;Ptr. to 5" D.P.B. getchr equ 10h ;Read console to A (or 0) putchr equ 18h ;Output A on console putmsg equ 20h ;Output ASCIIZ (HL) on console break equ 38h ;ROM breakpoint trap ;----------------------------------------------------------------------- ill be disabled. The symbolic names are those used in the ROM code for these routines. $ diskop equ 8 ;JP to diskette handler dpb3 equ diskop+3 ;Ptr. to 3" D.P.B. dpb5 equ dpb3+2 ;Ptr. to 5" D.P.B. getchr equ 10h ;Read console to A ; Macros to provide "subroutines" without a stack xcall macro link,tgt local next ld link,next jp tgt next equ $ endm xretn macro link jp (link) endm  page 90 title Cold-Start Functions ;===============================================================; ; ; ; C O L D - S T A R T F U N C T I O N S ; ; ; ;===============================================================; ;=======================================================================; ; ; ; D-X Designs Pty. Ltd. Perth, Western Australia ; ; Project: 112 May, 1996 ; ; ; ; Copyright (C) 1996, 1997 David R. Brooks ; ; ; ; This program is free software; you can redistribute it and/or ; ; modify it under the terms of the GNU General Public License ; ; as published by the Free Software Foundation; either version 2 ; ; of the License, or (at your option) any later version. ; ; ; ; This program is distributed in the hope that it will be useful, ; ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; ; GNU General Public License for more details. ; ; ; ; You should have received a copy of the GNU General Public License ; ; along with this program; if not, write to the Free Software ; ; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ; ; ; ;=======================================================================; ; Basic hardware initialisations for the Z80182 CP/M board. ; Determine hardware configuration, and make optimal hardware ; setups. Link with the standard D-X Designs debugger. ;----------------------------------------------------------------------- ; R E V I S I O N H I S T O R Y ; See DEBUG.MAC for version numbers ; 20-05-96 Initial issue ; 07-07-96 Display version number ; 22-08-96 Date changed to agree with fix to DEBUG ; 06-02-97 Report 1MB RAM size correctly ; Add IO waits for 24.576MHz ; 08-03-97 Correct wait-state contols: multiple speeds & phantom ROM ;---------------------------------------------------------------------- ;lanalyse equ 0 ;Define to setup the CPU for a ; logic analyser (extra outputs) Z80182 equ 0 ;Define the CPU variant in use .sall include Z180.INC ;Standard definitions include ASCII.INC include FDC.INC include MACROS.INC extrn rst38 extrn debug extrn memsetup ;Code to locate RAM chips extrn diskop ;DIskette handler extrn dpb3i, dpb5i ;Diskette parameter blocks ;Debugger routines used here... extrn putmsg ;Display ASCIIZ string at HL extrn decout ;Display HL in decimal extrn puta ;Convert A to hex. at [DE] ;------------------------------------------------------------------ ; H O O K S F O R B O O T - S E C T O R S , E T C . aseg ;Service functions, accessed by RSTs org 0 jp begin ;Cold-start entry today: db 97H, 03H, 08H ;Date code: YYMMDD (see also "isdate") org 08h jp diskop ;Hook to disk routine for boot-loader dw dpb3i ;Pointers to standard DPB's dw dpb5i org 10h jp getchr ;Get keyboard to A (or Z) org 18h jp putchr ;Send A to display org 20h jp putmsg ;Display ASCIIZ string ;------------------------------------------------------------------ org 38h jp rst38 ;Trap for debugger ;------------------------------------------------------------------ dseg global ivpage ivpage: ds 40h ;Interrupt vectors (start of dseg load) ;------------------------------------------------------------------ cseg ;Signature in the ROM code (see also "today") isdate: db 'ROM-code built: ' db '08 Mar. 1997',0 db 'D-X Designs Pty Ltd, Perth Australia',0 ;================================================================== ; CTC INTERRUPT-SOURCE ROUTINES (for the Debugger) ; ; The name is a misnomer. These routines are usually supported by ; a Z80-CTC device, however the Z182 does not have one. They are ; therefore supported by Channel-0 of the Programmable Reload Timer ;================================================================== global getvect global armctc global stopctc getvect: ;Return addr. of CTC interrupt vector ld a,i ld h,a ;MSB - Interrupt page in0 a,(il) add a,VPRT0 ;Offset for timer ld l,a ;HL -> Vector locn. ld a,h or l ;Z set if none. (May corrupt A) ret ;Return CTC interrupt vector armctc: ;Trigger an interrupt ASAP di ld hl,1 ;A very short time out0 (rldr0h),h out0 (rldr0l),l ;Reload reg. out0 (tmdr0h),h out0 (tmdr0l),l ;Down counter in0 a,(tcr) or 11h ;Set timer & interrupt out0 (tcr),a ;Trigger the timer ret ;Return with ints. disabled stopctc: ;Acknowledge & cancel interrupt ;To stop the timer safely, do these EXACTLY ; as given!! in0 a,(tcr) ;Read status first and 0a2h ;Kill Ch-0, don't touch Ch-1 out0 (tcr),a ;Stop it running nop in0 a,(tcr) ;Acknowledge the interrupt in0 l,(tmdr0l) ;Must read these, to clear ints. in0 h,(tmdr0h) ; (they are discarded) ei ret ;Don't use RETI for internals ctcsetup: ;Basic CTC interrupt initialisation ret ;Nothing needed for timer ;================================================================== ; BASIC INITIALISATIONS ;================================================================== global hwmsg hwmsg: db 'Special P112 version: interrupts supported',ascicr,0 begin: ld hl,inztab ;Basic setups xcall ix,ioiz2 ld hl,itab ;Set up the Z182 serial port ld b,(hl) iz1: inc hl ;Can't use OTIR: high addr. bits! ld a,(hl) out0 (sccacnt),a ;Send it djnz iz1 xcall iy,memsetup ;Set up the RAM, define stack ld a,high ivpage ld i,a ;Set interrupt page-base im 2 ;Interrupt hardware operating mode ld hl,0ffffh ;Clear out RAM first xor a clp: ld (hl),a dec hl bit 7,h jr nz,clp ;Down to 8000H ld sp,0ffffh ;Put stack at the top call clockspd db 0 ;Setup clock, no output yet call ctcsetup ;Setup interrupt for debugger ld hl,nline call putmsg ;Blank line at the start call smcsetup ;Initialise the SMC chip xor a ;Be sure timer is stopped out0 (tcr),a ld hl,isdate call putmsg ;ROM date code ld hl,sepr call putmsg call clockspd ;Report system-clock speed db 1 call tellmem ;Report available RAM jp debug ;To the internal debugger nline: db ascicr,0 sepr: db ' ',0 ;=========================================================== ; Routine to output a block of initialisation data. Table is ; Port, then Data. A port-value of 0 terminates. ;Pass block addr. in HL (port, data) ;Advances HL to end of table ioinz: push af ;Save regs. push bc push ix ld ix,iiz2 jr ioiz2 ;Run the "inner shell" iiz2: pop ix pop bc ;Get them back pop af ret ioiz2: ;This inner segment can be called without use if the stack, ; by passing a "link" in IX. Used at the very start of ; things, before the stack is set up ;This version corrupts AF, BC ld a,0ffh ilp: ld b,0 ;MS address bits ld c,(hl) ;Output port tst c ;Zero will halt jr z,xt ;Found end marker inc hl ;Else, point to data outi ;Sent, alters B jr ilp xt: jp (ix) ;"Return" ;================================================================== ; PRIMARY I/O PORT ROUTINES ;================================================================== global getchr ;Input 1 char. to A global putchr ;Output 1 char. from A putchr: ;Output A on ESCC port push af outax: in0 a,(sccacnt) bit 2,a ;Port ready? jr z,outax ;Loop till it is pop af out0 (sccad),a ;Send char. ret getchr: ;Get char. from ESCC to A (Z if none) in0 a,(sccacnt) and 01h ;Take only RX-ready ret z ;If none, exit with Z (& A=0) in0 a,(sccad) ;Else, pull the char. ret ;================================================================== ; SMC CHIP SETUP ROUTINE ;================================================================== ; NB This code is written for the FDC37C665 series parts. ; Although the hardware can run other parts, this code will ; need altering. .radix 16 cfcntl equ 90 ;Configuration control port cfdata equ 91 ;Configuration data port ;Confign. registers: see SMC data-sheet for details CR0 equ 0 ;Power-save controls CR1 equ 1 ;Serial/parallel port addresses CR2 equ 2 ;UART setups CR3 equ 3 ;FDC setups CR4 equ 4 ;Parallel port setups CR5 equ 5 ;FDC/IDE setups CR6 equ 6 ;Floppy drive types CR7 equ 7 ;Boot floppy drive, Media ID polarity CR8 equ 8 ;ADRx lower address bits CR9 equ 9 ;ADRx upper address bits CRA equ 0a ;ECP FIFO threshold CRB equ 0b ;Reserved CRC equ 0c ;Reserved CRD equ 0d ;Part sub-type: "65" or "66" CRE equ 0e ;Chip revision: "GT"=02, "IR"=82 CRF equ 0f ;Reads as zero config macro ?port, ?data db cfcntl, ?port db cfdata, ?data endm entercfg: ;Enter Configuration Mode db cfcntl, 55 ;Special sequence to enter mode db cfcntl, 55 ;NB different for the '666 series db 0 exitcfg: ;Exit Configuration Mode db cfcntl, 0aa db 0 cfg665: ;Config. for FDC37C665GT, -IR cfg666: ;Ditto FDC37C666xx config CR0, 38 ;IDE disabled, FDC enabled config CR1, 85 ;Basic bi-di printer port config CR2, 1c ;UART 1 at primary addr., UART 2 off config CR3, 78 ;Diskette: normal XT mode config CR4, 00 ;No ECP/EPP parallel port modes config CR5, 24 ;Swap drive 0,1 lines db 0 smcsetup: ;Configure the SMC multi-IO chip ld hl,entercfg call ioinz ;Put it into Config. mode ld a,CRF call getone ;CRF must = 0 and a jr nz,badchip ld a,CRD call getone ld ix,cfg665 cp 65 ;Must be '665 or '666 jr z,check1 ld ix,cfg666 cp 66 jr nz,badchip check1: ld b,a ;Saved chip ID ld a,CRE call getone ld c,a ;Save subtype res 7,a cp 2 ;Must be correct jr nz,badchip ;Found a good chip: say so push bc ld hl,chipm1 call putmsg pop bc ld hl,chipm5 ld a,b cp 66 jr nz,cf2 ld hl,chipm6 cf2: push bc call putmsg pop bc ld hl,chipm2 bit 7,c jr z,cf3 ld hl,chipm3 cf3: call putmsg ld hl,chipm4 call putmsg push ix pop hl call ioinz ;Do the configuration jr cfdone badchip: ld hl,chipm9 call putmsg ;Unrecognised chip cfdone: ld hl,exitcfg ;Exit config. mode call ioinz ret ;Done chipm1: db ascicr,'SMC IO chip identified (FDC37C66',0 chipm2: db 'GT)',0 chipm3: db 'IR)',0 chipm4: db ': configuring',ascicr,0 chipm5: db '5',0 chipm6: db '6',0 chipm9: db ascicr,'Unrecognised IO chip: not configured',ascicr,0 getone: ;Read config. register given in A out0 (cfcntl),a ;Point to the reg. in0 a,(cfdata) ;Get value ret ;================================================================== hexa: ;Output A in hexadecimal push de push hl ;Save regs. ld hl,0 push hl push hl ;Local space: 4 bytes add hl,sp ;SP -> HL ld e,l ld d,h ;Copy in DE call puta ;A-> hex. on stack dec de xor a ld (de),a ;Terminator call putmsg ;Display it (from HL) pop hl pop hl ;Discard temp. space pop hl ;Restore saved regs. pop de ret ;================================================================== ;Measure the system-clock speed. ; Measurement is done by setting the 2ary serial port to ; 1200bps, and outputting a 10-bit character (actually NUL). ; This interval equates to a frequency of 1200/10 = 120Hz. ;This period is measured using the Z180 system timer, which ; counts CLK/20. The final value will then be ; SYSCLK / (20 * 120). This will be a 65k complement, as the ; timer counts down. The measurement will be subject to some ; error, but near enough to identify the standard crystals: ; 12.288MHz, 16.0MHz, 18.432MHz, and 24.576MHz. ; ; The estimated speed is reported on the monitor, and the ; Timer-1 reload register is set up to yield a "tick" rate ; of 25Hz. The "tick" is NOT actually initiated. clockspd: in0 a,(_LSR) ;First, be sure it's empty bit 6,a jr z,clockspd ld hl,tminz ;Ready to run it call ioinz ;Kick off SIO & timer clkw: in0 a,(_LSR) ;Now wait till it's gone bit 6,a jr z,clkw in0 l,(tmdr1l) ;Get residual timer into HL in0 h,(tmdr1h) xor a ;Then kill the timer (at startup, out0 (tcr),a ; we know it's not shared) in0 a,(_RBR) ;Clear the looped char. inc h ;Round HL in top 7 bits res 0,h ;Further rounding ld b,tcnt ;No. of table items ld a,h ld hl,trtab ld de,ltab tr1: cp (hl) ;Matched? jr z,tr2 add hl,de ;No: next djnz tr1 ld hl,nomat ;No match... call putmsg ld hl,oddone-1 ;Offset for INC below tr2: inc hl ;Point at the timer value ld a,(hl) out0 (rldr1l),a inc hl ld a,(hl) out0 (rldr1h),a ;Set-up the timer inc hl ld a,WR12 out0 (sccacnt),a ld a,(hl) out0 (sccacnt),a inc hl ld a,WR13 out0 (sccacnt),a ld a,(hl) out0 (sccacnt),a ;Set a correct baud-rate inc hl in0 a,(scr) ;Is the ROM phantomed? bit 3,a ld a,(hl) ;Value for phantom inc hl jr nz,nph ld a,(hl) ;Value if not phantomed nph: out0 (dcntl),a ;Define memory & IO waits inc hl ld a,(hl) inc hl ld h,(hl) ld l,a ;Msg. pointer in hl or h ;Zero if none ret z pop de ld a,(de) ;In-line flag inc de push de ;Replace link and a ;If zero, no messages ret z push hl ;Else, output reports ld hl,xtms1 call putmsg pop hl call putmsg ;The observed frequency ld hl,xtms2 call putmsg ret ;Then done xtms1: db 'CPU clock: ',0 xtms2: db 'MHz',ascicr,0 .radix 10 trtab: db 0ech ;Translation table for results dw 24576 ;Timer value dw 38 ;Baud-rate value (9600bps) db 20h ;Wait states: ROM phantomed db 20h ; ditto: physical ROM dw ms12 ;Ptr. to message ltab equ $-trtab db 0e6h dw 32000 dw 50 db 20h db 20h dw ms16 db 0e2h dw 36864 dw 58 db 60h db 0a0h dw ms18 db 0d8h dw 49152 dw 78 db 70h db 0f0h dw ms24 tcnt equ ($-trtab)/ltab ;No. of entries oddone: dw 34000 ;Default timer for odd crystals dw 50 db 70h ;Use the slowest values db 0f0h dw 0 ;No message here .radix 16 ms12: db '12.288',0 ms16: db '16.0',0 ms18: db '18.432',0 ms24: db '24.576',0 nomat: db 'Non-standard CPU clock crystal: timer will' db ' be inaccurate',ascicr,0 tminz: db _LCR, 80 ;DLAB=1 db _DDL, 60 ;96D, divisor for 1200bps db _DLM, 0 db _LCR, 03 ;DLAB=0, 8 bits, no parity db _MCR, 10 ;Loopback, so nothing is output db tmdr1l, 0 db tmdr1h, 0 ;Timer-1: preset to zero db rldr1l, 0 db rldr1h, 0 db tcr, 02 ;Kick off the timer db _THR, 0 ;Send the byte db 0 ;Stop flag ;================================================================== tellmem: ;Report amount of RAM available in0 a,(ramubr) ;Upper bound add a,1 ;To 1st invalid page (set CY) rra ;Scale & keep CY in0 l,(ramlbr) ;Lower bound srl l ;Scale similarly sub l ;Available RAM / 8kB ld l,a ld h,8 mlt hl ;HL = size * 1kB push hl ld hl,rams1 ;Now output report call putmsg pop hl call decout ld hl,rams2 call putmsg in0 a,(ramlbr) call hexa ;Lower bound ld hl,rams3 call putmsg in0 a,(ramubr) call hexa ld hl,rams4 call putmsg in0 a,(scr) bit 3,a ;ROM shadowed? ld hl,rams5 call nz,putmsg ;Say so ld hl,nline call putmsg ret rams1: db 'RAM available: ',0 rams2: db 'kB. From ',0 rams3: db '000 to ',0 rams4: db 'FFF',0 rams5: db ', ROM shadowed into 1st 32kB',0 ;================================================================== .radix 16 ;Initialisation tables inztab: db rcr, 00 ;No refresh (all static) db omcr, 00 ;Timings as Z80 db il, 00 ;Local interrupts vector base ; db wsgcs, 9b ;CS waits don't work?? db dcntl, 70 ;Wait states: mem 1 (for ROM) ; IO 4 (for SMC) db bbr, 00 db cbr, 0fc ;Wrap CA1 over BA, at 08000 db cbar, 0c8 ;Memory mapping: ;Common 0: 0000-7FFF: 00000-07FFF ;Bank: 8000-BFFF: 08000-0BFFF ;Common 1: C000-FFFF: 08000-0BFFF db ramlbr, 08 ;RAM starts above ROM db ramubr, 0ff ;RAM to the top, for now db rombr, 07 ;ROM in 1st 32kB db intype, 5c ;INT1,2 level: MRD/WR, IOCS db ccr, 80 ;Full clock speed (16MHz) ifdef lanalyse db scr, 70 ;Logic analyser support else db scr, 60 ;No unnecessary outputs endif ; db itc, 39 ;Block SMC interrupts, yet db dra, 0a0 ;Initial values: Vpp off db ddra, 41 ;PA6 & 0 are in, others out db 0 ;End mark .radix 10 itab: ;ESCC serial channel db itabend-$-1 ;Length of table db WR4, 01000100b ;x16, 1 stop bit, no parity db WR1, 00000100b ;Parity is special RX condition db WR3, 11000000b ;RX 8 bits/char db WR5, 01100000b ;TX 8 bits/char db WR9, 00000001b ;Status affects int. vector db WR11, 01010110b ;RX & TX <- BRG, RTxC <- BRG db WR12, 50 ;Baud rate divisor LSB: 9600bps db WR13, 0 ;Ditto, MSB db WR14, 01100010b ;BRG source (internal) DPLL off db WR14, 00000011b ;BRG enabled db WR1, 00000100b ;Enable ints. here, if reqd. db WR15, 00000000b ;No "advanced" features db WR0, 00010000b ;Reset pending external ints. db WR0, 00010000b ;Repeat, to be sure of it db WR3, 11000001b ;RX enabled db WR5, 01101010b ;TX enabled, RTS active itabend equ $ end  ;Skip display/set until matched push ix push iy ;Display/change this register call uplvl ;Save environment while displaying rg5a: ld de,conbuf ;Here to re-display on error push ix pop hl ld a,c ld bc,3 ldir ;Register name + space ld c,a ;Restore C bit wrdreg,c ;1 or 2-byte? jr z,oneb ld l,(iy) ld h,(iy+1) call puthl ;2-byte jr rg5 oneb: ld a,(iy) call puta ;1-byte rg5: call outbuf ;Output current value ld hl,conbuf push hl ld (hl),space ;Be sure there's a space at start inc hl push bc ;Save flags in C ld b,szbuf-1 call get ;Reply line pop bc pop hl call getch ;Test reply jr z,rg6 ;Null: next reg. cp 'Q' jr nz,rg7 call dnlvl ;"Q" - Quit pop iy pop ix ;Balance stack xor a ret ;Done rg7: call getn2 ;Form new value in DE cp ascicr ;Must be valid jr z,rg8 ld hl,mbdn call pcr jr rg5a rg8: push de pop ix ;Save result call dnlvl pop iy ex (sp),ix ;Restore IX pop hl ;New value in HL, other regs. restored ld (iy),l bit wrdreg,c jr z,rg4 ld (iy+1),h ;MSB page 90 title Z-80 Resident Debugger subttl DEBUG data space ;=======================================================================; ; ; ; D-X Designs Pty. Ltd. Perth, Western Australia ; ; Project: 112 May, 1996 ; ; ; ; Copyright (C) 1996, 1997 David R. Brooks ; ; ; ; This program is free software; you can redistribute it and/or ; ; modify it under the terms of the GNU General Public License ; ; as published by the Free Software Foundation; either version 2 ; ; of the License, or (at your option) any later version. ; ; ; ; This program is distributed in the hope that it will be useful, ; ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; ; GNU General Public License for more details. ; ; ; ; You should have received a copy of the GNU General Public License ; ; along with this program; if not, write to the Free Software ; ; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ; ; ; ;=======================================================================; .Comment $ Skeleton ROM-resident debugger. Adapted from ancient code (1978) D-X Designs Pty Ltd December 1995 D. R. Brooks Revision history: V1.00 Dec. 1995 Initial version V1.02 Mar. 1996 Added hooks to I/O functions Added display of current instruction V1.03 Apr. 1996 Added IN, OUT & BOOT Commands V1.04 May 1996 Special extensible version for P112 V1.05 Aug. 1996 Fixed bug in DECOUT routine V1.06 Feb. 1997 Fixed size report for 1MB RAM Extra IO wait state at 24.576MHz This is the generic core of the Z80/Z180 debug module. All hardware dependent functions have been exported. These functions are called by the following External declarations. $ cseg ;Standard sign-on message & version bgnmg1: db ascicr db 'Z80 Series ROM-Resident Debugger V1.06: ' db 'D-X Designs Pty Ltd 1997',ascicr,0 endlin: db 'Type "?" for help',ascicr,ascicr,0 dseg .z80 ;Generic CPU: any Z80 derivative global debug ;Primary entry point global rst38 ;Entry from RST-38 instruction extrn getvect ;Get int. vector addr., or zero extrn armctc ;Trigger an interrupt extrn stopctc ;Deactivate it, & EI extrn getchr ;Get 1 char. to A, no editing extrn putchr ;Output 1 char. from A extrn hwmsg ;Hardware-dependent sign-on message extrn excom ;Hook for extension commands: ;Call with HL -> input buffer, or 0 for help ;Returns CY if unsuccessful ;Basic IO functions: exported for plug-in modules (V1.02) global get ;Input line to HL, until B chars. or CR global putmsg ;Output ASCIIZ string global decout ;Decimal output function global puta ;A converted to hex. at [DE] global getnum ;Get next number from input dseg dbdat: ds 64 ;DEBUG stack stack equ $ ;User-environment register-save area SP_: ds 2 PC_: ds 2 IY_: ds 2 IX_: ds 2 HL?_: ds 2 DE?_: ds 2 BC?_: ds 2 AF?_: ds 2 HL_: ds 2 DE_: ds 2 BC_: ds 2 AF_: ds 2 regend equ $-1 ;Final byte of saved regs. spva: ds 2 ;Saved debug-level SP bpadr: ds 2 ;Breakpoint address inst: ds 1 ;Instr. replaced by breakpoint bpcnt: ds 1 ;Count breaks before trapping nxcnt: ds 1 ;Count NEXT operations before halting eiadr: ds 2 ;Addr. of extra EI instr. eiopc: ds 1 ;Opcode replaced by EI instr. inptr: ds 2 ;Input-buffer ptr. hexlin: ds 2 ;Line-count of hex. input file errlin: ds 2 ;Line-number of last error seen (or 0) ;Input-queue controls qsbit equ 6 ;Queue-size mask bit qiptr equ 0 ;Offset of input ptr. qoptr equ 1 ;Offset of output ptr. qbuff equ 2 ;Offset of buffer qspace: ds qbuff + (1 shl qsbit) ;Queue space conbuf: ds 81 ;Standard console I/O buffer szbuf equ $-conbuf sysflg: ds 1 ;DEBUG status flag ;Bits in sysflg: atbrk equ 0 ;RST-38 was the set breakpoint ;Intel hex-format errors: ifhex equ 5 ;Bad hex. digit ifadr equ 6 ;Address out of range ifsum equ 7 ;Bad sumcheck montop equ $ ;End of monitor's RAM org dbdat+256 ;Force to a page, for int. vectors subttl Basic IO Functions page cseg ;====== BASIC CHARACTER I/O FUNCTIONS ======================== .Comment $ The fundamental functions are external, as they are hardware dependent. The design enables the CP/M calls 02 and 06 to serve, in a test environment. These external calls (getchr/putchr) should preserve registers. $ include ASCII.INC ;Control chars. ;Queue-driver routines. Input is buffered to obviate ; overflow problems when loading hex. files into RAM toque: ;Push char. to input queue push ix push bc ld ix,qspace ld b,a ;Save the char. ld a,(ix+qiptr) inc a ;Check there is room res qsbit,a ;Increment modulo-N cp (ix+qoptr) jr z,qout ;Jump if no room ld a,b ld c,(ix+qiptr) ld b,0 inc (ix+qiptr) ;QIPTR++ (Modulo-N) res qsbit,(ix+qiptr) add ix,bc ;Point into buffer ld (ix+qbuff),a ;Save char. qout: pop bc pop ix ret fmque: ;Pull char. from queue push ix push bc ld ix,qspace ld a,(ix+qiptr) ;Queue empty? sub (ix+qoptr) ; ie QIPTR == QOPTR jr z,qout ;If so, return zero ld c,(ix+qoptr) ld b,0 inc (ix+qoptr) ;QOPTR++ (Modulo-N) res qsbit,(ix+qoptr) add ix,bc ;Point into buffer ld a,(ix+qbuff) ;Pull the char. and a jr qout ;-------------------------------------------------------------- inpoll: ;Poll input for char., & queue it call getchr ;Next from input stream (if any) and a call nz,toque ;If any, push it to queue ret get: ;Input to (HL), until B=0 or CR ld c,0 ;Column count gt1: call inpoll ;Put anything new on queue call fmque ;Pull from tail jr z,gt1 ;Wait for something cp ascibs jr nz,gt2 ld a,c ;Backspace: =NOP at 1st. col. and a jr z,gt1 ld a,ascibs call putchr ld a,space call putchr ;Destructive BS: BS-SP-BS ld a,ascibs call putchr dec c ;Back-up pointers: col. count dec hl ; buffer ptr. inc b ; counter jr gt1 gt2: cp asciht jr nz,gt3 gt2b: ld a,space call putchr ld (hl),a ;TAB - fill out spaces inc hl inc c djnz gt2a ret ;Done if buffer full gt2a: ld a,c and 7 ;Tab-out to 8th column jr nz,gt2b jr gt1 gt3: cp ascicr jr z,gt4 ;CR - the only other legal control cp space jr c,gt1 ;Ignore the others cp ascdel jr nc,gt1 cp 'a' ;Force uppercase jr c,gt4 sub 'a'-'A' gt4: call putchri ;Echo the transformed char. ld (hl),a ;Accept it inc hl inc c dec b ;Count up buffer ret z cp ascicr ret z ;Stop at CR jr gt1 ;Else, go for more ;---------------------------------------------------------- pcr: ld a,(hl) ;Output until CR call putchri ;Sent 1 (preserves A) inc hl cp ascicr ;Until CR ret z jr pcr ;---------------------------------------------------------- putmsg: ld a,(hl) ;Output ASCIIZ string inc hl and a ret z ;Back at the end call putchri ;Send 1 jr putmsg ;---------------------------------------------------------- putdis: ld a,(hl) ;Output B chars. from HL call putchri ;Sent 1 inc hl djnz putdis ret ;---------------------------------------------------------- putchri: ;Output 1 char. & add LF to CR call putchr cp ascicr ret nz ld a,ascilf ;Add the LF call putchr ld a,ascicr ;Don't alter A ret subttl General Utilities page ;Register save/restore Functions ;Up 1 level (std. saves) uplvl: ex (sp),hl push af push bc push de jp (hl) ;"Return" ;Down 1 level (std. restore) dnlvl: pop hl pop de pop bc pop af ex (sp),hl ret ;---------------------------------------------------------------- .Comment $ Routine to format 16 bytes for display. It is suitable for re-entrant use. On entry, HL holds addr of 1st byte for display, DE points at output buffer. All main registers are destroyed. A CR is placed after the last char. generated. $ bytesln equ 16 ;No. of bytes displayed per line txtcol equ 54 ;Locn. on line for text display txtbgn equ '>' ;Opening "quote" for text txtend equ '<' ;Closing ditto disply: push ix push hl push de pop ix ld bc,txtcol add ix,bc ;IX -> char. display area on line ld (ix-1),txtbgn page 90 title Drive Hardware Parameters ;===============================================================; ; ; ; D R I V E H A R D W A R E P A R A M E T E R S ; ; ; ;===============================================================; ;=======================================================================; ; ; ; D-X Designs Pty. Ltd. Perth, Western Australia ; ; Project: 112 May, 1996 ; ; ; ; Copyright (C) 1996 David R. Brooks ; ; ; ; This program is free software; you can redistribute it and/or ; ; modify it under the terms of the GNU General Public License ; ; as published by the Free Software Foundation; either version 2 ; ; of the License, or (at your option) any later version. ; ; ; ; This program is distributed in the hope that it will be useful, ; ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; ; GNU General Public License for more details. ; ; ; ; You should have received a copy of the GNU General Public License ; ; along with this program; if not, write to the Free Software ; ; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ; ; ; ;=======================================================================; ;Standard drive parameters: globally available global dpb3i, dpb5i dpb3i: ;Drive parameters for 3" disks db 0dfh ;SRT=3mS, HUT=240mS db 02h ;HLT=4mS db 25h ;5 secs. (25 index pulses) db 02h ;512 bytes/sector db 18 ;Sectors/track db 1bh ;Gap length db 0ffh ;DTL (not used) db 6ch ;Gap-3 length: Format db 0e5h ;Data fill: Format (CP/M) db 15 ;Head-settle time (mS) db 8 ;Motor-on delay * 1/8 sec. db 79 ;Highest cylinder no. db 00 ;data rate (500kb/s) dpb5i: ;Drive parameters for 5" disks db 0dfh ;SRT=3mS, HUT=240mS db 02h ;HLT=4mS db 25h ;5 secs. (25 index pulses) db 02h ;512 bytes/sector db 09 ;Sectors/track db 2ah ;Gap length db 0ffh ;DTL (not used) db 50h ;Gap-3 length: Format db 0e5h ;Data fill: Format (CP/M) db 0fh ;Head-settle time (mS) db 8 ;Motor-on delay * 1/8 sec. db 39 ;Highest cylinder no. db 02 ;data rate (250kb/s) end  ;512 bytes/sector db 09 ;Sectors/track db 2ah ;Gap length db 0ffh ;DTL (not used) db 50h ;Gap-3 length: Format db 0e5h ;Data fill: Format (CP/M) db 0fh pop hl call puthl ;Post address ld b,bytesln disp_1: ld a,(hl) call puta ;Display in hex. ld a,(hl) cp space ;Non-printing? jr c,disp_2 cp ascdel ;DEL does not print jr c,disp_3 disp_2: ld a,'.' ;Non-printing substitute disp_3: ld (ix),a inc hl inc ix djnz disp_1 ;Do the whole line ld (ix),txtend ld (ix+1),ascicr ;End of line pop ix ret ;---------------------------------------------------------------- ;Get to start of next blank-delimited field crt: cp ascicr ;Not space, try CR ret z inc hl ;Not CR either: skip it getch: ld a,(hl) ;Or accept it cp space jr nz,crt plblk: inc hl ;Strip off blanks ld a,(hl) cp space jr z,plblk cp ascicr ret ;Back: Z indicates CR ;---------------------------------------------------------------- getlin: ;Input a line to conbuf ld hl,conbuf ld b,szbuf-1 ld (inptr),hl ;Initialise pointer push hl ld (hl),space ;Ensure a space at start, for getch inc hl call get pop hl ;Ptr. to start of conbuf call getch ;Return 1st. char. to user ret ;---------------------------------------------------------------- dspac: ex de,hl ;Post a space at (DE) ld (hl),space inc hl ex de,hl ret ;------ Hexadecimal <-> Binary Conversions ---------------------- getnum: ;Convert chars at (HL) to hex. no. in (DE) ;Destroys A, DE. Advances HL past no. call getch getn2: ld de,0 ex de,hl push bc ;Preserve it ld b,0 ;Flag: nothing seen yet push hl add hl,sp ;HL points at zero-ed workspace (on stack) dlp: call gethex ;Convert 1 char. to hex. jr c,notdig set 7,b ;Flag: something was seen rld ;Roll digit into number inc hl rld dec hl jr dlp notdig: dec de ld a,(de) ;Get back terminal char. pop hl ;Scrap workspace rl b ;B[7] -> CY (set if something seen) pop bc ;Recovered BC ex de,hl ;Exit: result in DE, ptr. in HL ret ;Terminal char. in A ;-------------------------------------------------------------- gethex: call inpoll ld a,(de) ;Convert byte [DE] to hex. inc de sub '0' ;Return CY if bad ret c cp 10 jr c,dig ;Digit 0-9 sub 7 ;Block special chars. ret c cp 16 ccf ret c dig: and a ;Good: CY=0 ret ;---------------------------------------------------------------- getbyte: ;Convert 2 chars. to byte in A push bc ;Return CY if error call gethex ;1 byte jr c,bad add a,a add a,a ;Shift left 4 places add a,a add a,a ld b,a ;Save it call gethex ;2nd. byte jr c,bad or b ;OK: form byte & CY=0 bad: pop bc ret ;---------------------------------------------------------------- getsum: ;Get a byte, & keep sumcheck in C call getbyte ;Source ptr. in DE push af add a,c ;Sumcheck ld c,a pop af ret ;Back: CY=1 if error ;---------------------------------------------------------------- puthl: ld a,h ;Convert HL to 4 hex. chars. from (DE) call puta dec de ld a,l puta: push af ;Convert A to 2 hex. chars. at (DE) rra rra rra rra call nibble ;Bits 4-7 pop af call nibble ;Bits 0-3 ld a,space ld (de),a ;Blank after inc de ret ;---------------------------------------------------------------- nibble: ;Output A[3:0] as hex. char. or 0f0h ;Top bits =1, flags H, N =0 daa add a,0a0h adc a,40h ;Convert to ASCII ld (de),a inc de ret ;---------------------------------------------------------------- tenpwr: dw 10000 dw 1000 dw 100 dw 10 decout: ;Output HL in decimal - direct output push ix push de push bc ld ix,tenpwr ld b,4 ld c,'0' ;Leading-zero flag dc2: ld e,(ix) inc ix ;Power of 10 in DE ld d,(ix) inc ix ld a,'0'-1 and a ;CY=0 dc1: inc a sbc hl,de ;Trial subtraction jr nc,dc1 add hl,de ;Restore cp c ;(Leading) zero? jr z,dc3 call putchr ;No, display ld c,-1 ;Clear LZ flag dc3: djnz dc2 ld a,l ;Get the last bit add a,'0' call putchr pop de pop bc pop ix ret ;--------------------------------------------------------- ; Check the given address points into User Area userarea: push de ;Save the address push hl bit 7,d ;Can't be in ROM jr z,uaerr and a ;Dummy for now jr uaexit uaerr: scf ;Not allowed: set flag uaexit: pop hl pop de ret subttl DEBUG mainline page debug: ;Primary entry point ld hl,dbdat ;Clear out workspace ld b,montop-dbdat xor a clp: ld (hl),a inc hl djnz clp ld sp,stack ;Initialise SP ld hl,bgnmg1 call putmsg ;Sign-on message ld hl,hwmsg call putmsg ;Indicate hardware variant ld hl,endlin call putmsg ;Final CR dbglin: ;Get & process next user command ld sp,stack ;Forced reset ld hl,prompt call putmsg ;Prompt first call getlin ;Input response jr z,dbglin ;Skip null line inc hl ld (inptr),hl ;Points after the command-code ld hl,comlis ld bc,ncoms dbcomd: cpi ;Match command letter to table ld e,(hl) inc hl ld d,(hl) ;Routine address in DE inc hl jr z,comok call intelerr ;Report any outstanding errors jp pe,dbcomd ld hl,(inptr) ;Try for external commands dec hl ;Point HL at command code call excom jr nc,endcom ;Done if OK (else flag error) invcom: ld a,badcom cmderr: ld hl,emtab ;List of error messages ld e,a ;Offset ld d,0 add hl,de call pcr ;Output the message (CR ends it) endcom: jr dbglin comok: ld hl,endcom ;Push return-link for command processor push hl push de ;Push address of processing routine ld hl,(inptr) ;Point to 2nd. char. of command ret ;Go to command routine ;---------------------------------------------------------------- prompt: db '=',0 ;Standard DEBUG prompt comlis: db ':' ;Table of DEBUG commands dw hexformat ;This cmnd. must be first db 'B' dw break db 'D' ;Key letter dw display ;Routine pointer db 'G' dw goget db 'I' dw inport db 'N' dw next db 'O' dw outport db 'R' dw regs db '?' dw showhelp ncoms equ ($-comlis)/3 ;No. of table entries ;DEBUG error messages emtab: badcom equ $-emtab db 'Invalid command code',ascicr badnum equ $-emtab mbdn: db 'Invalid hexadecimal digit',ascicr badreg equ $-emtab db 'Invalid register name',ascicr invbrk equ $-emtab db 'Cannot set breakpoint in this area',ascicr runrom equ $-emtab db 'Cannot single-step in this area',ascicr nocnge equ $-emtab xadr: db 'Cannot edit memory in this area',ascicr noints equ $-emtab db 'Function requires interrupt hardware',ascicr badchk equ $-emtab xchk: db 'Bad checksum',ascicr noport equ $-emtab db 'Required argument missing',ascicr subttl Read Intel-hex. Format Data page imsg: db 'Errors in Intel-hex file: last bad line: ',0 igap: db ' ',0 emask equ (1 shl ifhex) + (1 shl ifadr) + (1 shl ifsum) intelerr: ;Log errors & reset indicators call uplvl ;Save everything ld ix,sysflg ld a,emask and (ix) ;Any errors? jr z,noer ld hl,imsg call putmsg ;Message stub ld hl,(errlin) call decout ;Line No. in decimal ld hl,igap call putmsg bit ifhex,(ix) ld hl,mbdn call nz,pcr ;Bad hex. digit res ifhex,(ix) bit ifadr,(ix) ld hl,xadr call nz,pcr ;Bad address res ifadr,(ix) bit ifsum,(ix) ld hl,xchk call nz,pcr ;Bad checksum res ifsum,(ix) noer: ld ix,0 ld (hexlin),ix ;Reset hex-file line counter ld (errlin),ix ;Reset error-line ptr. call dnlvl ;Restore caller's regs. ret hexformat: ;Read a line of Intel-hex. format ex de,hl ;Buffer ptr. in DE ld ix,sysflg ld hl,(hexlin) inc hl ;Bump line counter ld (hexlin),hl ld c,0 ;Preset the checksum call getsum jr c,badhex ld b,a ;Data counter call getsum jr c,badhex ld h,a ;Address call getsum jr c,badhex ld l,a call getsum jr c,badhex cp 0 ;Record type jr z,nbt ;Data cp 1 ;If the end, call z,intelerr ; ,report any outstanding errors ret nbt: and a ;Data: CY=0 push hl push de ld de,dbdat ;Check address in range sbc hl,de pop de pop hl jr nc,badadr call getsum ;Data byte jr c,badhex ld (hl),a ;Place data inc hl djnz nbt ;All data bytes call getsum jr c,badhex ;Sumcheck ld a,c and a ret z ;OK: done set ifsum,(ix) ;Bad sumcheck jr ifend badhex: set ifhex,(ix) ;Bad hex. digit jr ifend badadr: set ifadr,(ix) ;Bad address ifend: ld hl,(hexlin) ld (errlin),hl ;Last failed line ret ;Delay errors till end of file subttl Help Command (list commands) page hlpmsg: db ascicr db ' C O M M A N D H E L P',ascicr db ascicr db 'Separate all fields by one or more blanks',ascicr db ascicr db 'Commands Available:',ascicr db ': Input line of Intel hex-format data',ascicr db '? Display this help',ascicr db 'B [addr [count]] Set/clear breakpoint',ascicr db 'D addr [length] Display/change memory',ascicr db 'G [addr] Go run program (from addr)',ascicr db 'I port Input & display byte from port',ascicr db 'N [count] Run (next N) instructions',ascicr db 'O port data Output data byte at port',ascicr db 'R [register name] Display/change user registers' endhlp: db ascicr, 0 showhelp: ld hl,hlpmsg call putmsg ;Just display the message ld hl,0 :20000000C3E8009703080000C327098E049B0400C372010000000000C36501000000000010 :20002000C3D20B000000000000000000000000000000000000000000C385140000000000C4 :20004000524F4D2D636F6465206275696C743A203038204D61722E203139393700442D58B7 :200060002044657369676E7320507479204C74642C205065727468204175737472616C693E :200080006100ED5767ED3833C6046F7CB5C9F3210100ED210FED290EED210DED290CED3811 :2000A00010F611ED3910C9ED3810E6A2ED391000ED3810ED280CED200DFBC9C953706563AF :2000C00069616C20503131322076657273696F6E3A20696E7465727275707473207375708E :2000E000706F727465640D00214E04DD21F200C35501216D0446237EED39E010F9FD21043F :2001000001C3A8043EFEED47ED5E21FFFFAF772BCB7C20FA31FFFFCD900200CDBB0021416B :2001200001CDD20BCD9D01AFED3910214000CDD20B214301CDD20BCD900201CDBF03C31CDC :200140000D0D00202000F5C5DDE5DD2150011805DDE1C1F1C93EFF06004EED0C280523ED5D :20016000A318F4DDE9F5ED38E0CB5728F9F1ED39E1C9ED38E0E601C8ED38E1C990559055BF :200180000090AA0090009138900191859002911C90039178900491009005912400217C013D :2001A000CD46013E0FCD7102A720553E0DCD7102DD218401FE652808DD218401FE6620409A :2001C000473E0ECD71024FCBBFFE022033C5210D02CDD20BC121460278FE662003214802ED :2001E000C5CDD20BC1212F02CB792803213302CDD20B213702CDD20BDDE5E1CD4601180635 :20020000214A02CDD20B218101CD4601C90D534D4320494F2063686970206964656E74693E :2002200066696564202846444333374336360047542900495229003A20636F6E666967752B :2002400072696E670D00350036000D556E7265636F676E6973656420494F20636869703ACD :20026000206E6F7420636F6E666967757265640D00ED3990ED3891C9D5E5210000E5E539A7 :200280005D54CDB80C1BAF12CDD20BE1E1E1D1C9ED389DCB7728F921A803CD4601ED389D92 :2002A000CB7728F9ED2814ED2015AFED3910ED389824CB8406047C212803110900BE280C9D :2002C0001910FA216E03CDD20B214B03237EED3916237EED3917233E0CED39E07EED39E09E :2002E000233E0DED39E07EED39E023ED38EFCB5F7E2320017EED3932237E23666FB4C8D127 :200300001A13D5A7C8E5211703CDD20BE1CDD20B212303CDD20BC943505520636C6F636B49 :200320003A20004D487A0D00EC0060260020205403E6007D320020205B03E200903A0060FF :20034000A06003D800C04E0070F06703D084320070F0000031322E3238380031362E30000C :2003600031382E3433320032342E353736004E6F6E2D7374616E64617264204350552063E3 :200380006C6F636B206372797374616C3A2074696D65722077696C6C20626520696E61639D :2003A0006375726174650D009B80986099009B039C1014001500160017001002980000EDC9 :2003C00038E6C6011FED28E7CB3D956F2608ED6CE5210B04CDD20BE1CDDB0C211B04CDD257 :2003E0000BED38E7CD7802212504CDD20BED38E6CD7802212D04CDD20BED38EFCB5F2131CD :2004000004C4D20B214101CDD20BC952414D20617661696C61626C653A20006B422E204625 :20042000726F6D200030303020746F2000464646002C20524F4D20736861646F7765642000 :20044000696E746F203173742033326B420036003E0033003270390038FC3AC8E708E6FFEC :20046000E807DF5C1F80EF60EEA0ED4100200444010403C0056009010B560C320D000E62ED :200480000E0301040F000010001003C1056ADF022502121BFF6CE50F084F00DF02250209E8 :2004A0002AFF50E50F082702AFED39E73EFFED39E61100003EF0DD21BD04C3480520021E4B :2004C000F03E08DD21CA04C34805200216087AB32001767AA720017BD608ED3939082100E3 :2004E00082F9EB21450501B700EDB0210000010080AF86EDA1EAF204CD0082ED11E7ED1957 :20050000E6ED38E7A72017ED38EFCB5F20100640ED38E680ED39E6ED38E780ED39E70E0019 :20052000ED00E7ED38E690FE0830020E087891ED08EFCB592802C608ED3938ED39393EC832 :20054000ED393AFDE9C31F82D9472100C0D60CED39383E5577BE20032F77BE78D9DDE9004A :20056000082080FFF5FDE5ED38EFCBDFED39EFFD211A82FD7E00FD23FEFF200176DD213F04 :2005800082C3038220EDFDE1575FD60CED39382100C036553E08835F3816DD215C82C3032C :2005A00082200D36007AD60CED39387EFE5528E41DED38EFCB9FED39EFDDE17AA720387B5D :2005C00092FE3F3832DDE5D50100802100001600ED18EFCB9BED19EF7ECBDBED19EF778232 :2005E00057EDA1EA8E82DDE1F1DDE5BA2808ED38EFCB9FED39EFD108ED3939C9C3FF05C3A3 :2006000002067CB5200C218106CD2000210000C34F077EFE53C24F07CD5F0C7BFE043012C8 :20062000F5CD5F0CF1577BA7280AFE032806FE05280A37C91E03DD210B0018061E00DD2129 :200640000D00DD4E00DD4601C5DDE1D521008006010E001E013E02CFD121FA06381921009E :2006600080010002AF86EDA1EA6506211507A72006CC0080213207CD20003E01CD0800A787 :20068000C953205B64726976655D205B747970655D2020426F6F742073797374656D206693 :2006A000726F6D2064726976650D2020202020202020202020202020202020203C647269EA :2006C00076653E203D20302E2E330D2020202020202020202020202020202020203C74794F :2006E00070653E20203D20223322206F7220223522202873697A65290D004572726F7220D6 :2007000072656164696E6720626F6F7420736563746F720D00426F6F7420736563746F722A :20072000206661696C65642073756D636865636B0D004572726F722066726F6D20626F6F76 :20074000742D736563746F7220636F64650D007CB5C837C9C5D50100001614ED38DECB779D :20076000280B0D20F610F41520F1371801AFD1C1C9CD54073E053841C5D51142FE0607CDF6 :20078000C707121310F9D1C12142FEE57EE6F8FDBE012021237EFDBE02201A237ED60020FD :2007A00014ED2826ED3827B5E13E042008AF18093E033718043E02E137C9F5ED3894CB7F21 :2007C00028F9F1ED3995C9ED3894CB7F28F9ED3895C9C546237ECDBA0710F9C1C9E52140C9 :2007E000FE3A41FE2FA677E1C9CD860AED2923ED2124ED39253EA0ED3920AFED3921ED3939 :2008000022C9CD860AED2920ED2121ED39223EA0ED3923AFED3924ED3925C9FDE37B803D97 :200820003DDDBE04308A3C67FD7E00CDBA077ACB412802CBD7CDBA0779CB3FCDBA0779E626 :2008400001CDBA077BCDBA07DD7E03CDBA077CCDBA07DD7E05CDBA073E63ED39303EFFCD1B :20086000BA07CD7107C5F5010300FD09F1C1FDE3C9E5D5C5214000DD4603042910FD545D62 :20088000210000C1C51910FDED2926ED2127224DFEC1D1E1C9CD54073E05D83E08CDBA075A :2008A000CDC70747CDC707C5CB39B9C13E0737C078E6E0FE20C83E0137C9C5E542043E08A3 :2008C0008710FD3241FE47ED38924FE6FCB2F60CED399279A02016ED3892B0ED3992DD7EAF :2008E0000A8701000010FE0D20FB3D20F8DD7E0CED39973E03CDBA07DD7E00CDBA07DD7EA4 :2009000001CB87CDBA072140FE3A41FEA620133E07CDBA077ACDBA07CD950838063A41FE49 :20092000B677AFA7E1C1C9FE0738043E0637C9CD3A09F5DCB009F1D8AFC9E5214A09878504 :200940006F3001247E23666FE3C9B009CB0958095E0964096A09860AE521D5091810E521DA :20096000ED09180AE521050A1804E521120A224BFEE1F53EC3324AFEE5210000224DFEE1FC :200980003E033249FEF1E5CD4AFEE13018FE022804FE07200BF5CDDD073A49FE3D20E3F1D5 :2009A000371142FEC9ED5B4DFE191142FEC937C9E5AF3240FEED39923E0CED399221C60972 :2009C000CDD207AFE1C9041300712BED3892E60FED3992AFC9CDBA08C2AE09CDE907CD7186 :2009E000083ECDED3931CD1B08464080C9CDBA08C2AE09CD0208CD71083EF1ED3931CD1B3B :200A000008454080C9CDBA08C2AE09CD1B08560000C9CDBA08C2AE093E0FCDBA077ACB4180 :200A20002802CBD7CDBA0779CB3FCDBA07CD9508D8CD0208E5DD6E0426002929ED2926ED5D :200A40002127224DFEE13EF1ED39313E4DCDBA077ACB412802CBD7CDBA07DD7E03CDBA0795 :200A6000DD7E04CDBA07DD7E07CDBA073E63ED3930DD7E08CDBA07FDE5FD21830ACD7107DF :200A8000FDE1C9000000E57CE6F067ED383AE6F06F7C953805ED38381811ED383A878787A5 :200AA000876F7C953E003803ED3839E1C5E54C06006F6029292929097CE60F45E160C1A7A0 :200AC000C90D5A38302053657269657320524F4D2D5265736964656E74204465627567670C :200AE00065722056312E30363A20442D582044657369676E7320507479204C7464202031C2 :200B00003939370D005479706520223F2220666F722068656C700D0D00DDE5C5DD21B7FE56 :200B200047DD7E003CCBB7DDBE01281278DD4E000600DD3400DDCB00B6DD09DD7702C1DD8D :200B4000E1C9DDE5C5DD21B7FEDD7E00DD960128EDDD4E010600DD3401DDCB01B6DD09DD67 :200B60007E02A718D9CD7201A7C4190BC90E00CD650BCD420B28F8FE08201879A728F03E8C :200B800008CD65013E20CD65013E08CD65010D2B0418DCFE0920123E20CD650177230C1060 :200BA00001C979E60720F018C6FE0D280EFE2038BEFE7F30BAFE613802D620CDE30B772377 :200BC0000C05C8FE0DC818A77ECDE30B23FE0DC818F67E23A7C8CDE30B18F77ECDE30B2337 :200BE00010F9C9CD6501FE0DC03E0ACD65013E0DC9E3F5C5D5E9E1D1C1F1E3C9DDE5E5D5AF :200C0000DDE1013600DD09DD36FF3EE1CDB20C06107ECDB80C7EFE203804FE7F38023E2E1D :200C2000DD770023DD2310E9DD36003CDD36010DDDE1C9FE0DC8237EFE2020F7237EFE20E5 :200C400028FAFE0DC921F9FE065022B1FEE5362023CD6D0BE1CD370CC9EB362023EBC9CD1D :200C6000370C110000EBC50600E539CD820C380ACBF8ED6F23ED6F2B18F11B1AE1CB10C12B :200C8000EBC9CD650B1A13D630D8FE0A3807D607D8FE103FD8A7C9C5CD820C380B878787CF :200CA0008747CD820C3801B0C1C9CD970CF5814FF1C97CCDB80C1B7DF51F1F1F1FCDC90CF1 :200CC000F1CDC90C3E201213C9F6F027C6A0CE401213C91027E80364000A00DDE5D5C5DDFD :200CE00021D30C06040E30DD5E00DD23DD5600DD233E2FA73CED5230FB19B92805CD650152 :200D00000EFF10E37DC630CD6501D1C1DDE1C9D5E5CB7A2803A7180137E1D1C9214FFE0604 :200D2000FCAF772310FC318FFE21C10ACDD20B21BC00CDD20B21050BCDD20B318FFE21814C :200D40000DCDD20BCD450C28F22322B1FE21830D010900EDA15E235623281DCDC00EEA5350 :200D60000D2AB1FE2BCDFC05300C3E00219E0D5F160019CDC80B18C321760DE5D52AB1FE0E :200D8000C93D003A1A0F429C1344371347C314497B114EF2144F9A1152AF113F6811496EA9 :200DA00076616C696420636F6D6D616E6420636F64650D496E76616C69642068657861646B :200DC0006563696D616C2064696769740D496E76616C6964207265676973746572206E612F :200DE0006D650D43616E6E6F742073657420627265616B706F696E7420696E207468697327 :200E000020617265610D43616E6E6F742073696E676C652D7374657020696E20746869734F :200E200020617265610D43616E6E6F742065646974206D656D6F727920696E20746869733B :200E400020617265610D46756E6374696F6E20726571756972657320696E7465727275705D :200E6000742068617264776172650D42616420636865636B73756D0D5265717569726564BB :200E800020617267756D656E74206D697373696E670D4572726F727320696E20496E746584 :200EA0006C2D6865782066696C653A206C61737420626164206C696E653A200020202000BD :200EC000CDF10BDD214AFF3EE0DDA600283C21920ECDD20B2AB5FECDDB0C21BC0ECDD20B6C :200EE000DDCB006E21B30DC4C80BDDCB00AEDDCB007621260EC4C80BDDCB00B6DDCB007E80 :200F0000216B0EC4C80BDDCB00BEDD210000DD22B3FEDD22B5FECDF60BC9EBDD214AFF2AE7 :200F2000B3FE2322B3FE0E00CDAA0C383F47CDAA0C383967CDAA0C38336FCDAA0C382DFE1D :200F4000002806FE01CCC00EC9A7E5D5114FFEED52D1E1301DCDAA0C3812772310EBCDAA2B :200F60000C380979A7C8DDCB00FE180ADDCB00EE1804DDCB00F62AB3FE22B5FEC90D20205E :200F80002043204F204D204D2041204E2044202020482045204C20500D0D53657061726113 :200FA000746520616C6C206669656C6473206279206F6E65206F72206D6F726520626C61E8 :200FC0006E6B730D0D436F6D6D616E647320417661696C61626C653A0D3A203C496E74656B :200FE0006C206865782E3E20202020496E707574206C696E65206F6620496E74656C2068C3 :2010000065782D666F726D617420646174610D3F2020202020202020202020202020202037 :2010200020446973706C617920746869732068656C700D42205B61646472205B636F756E84 :20104000745D5D20205365742F636C65617220627265616B706F696E740D44206164647265 :20106000205B6C656E6774685D202020446973706C61792F6368616E6765206D656D6F720B :20108000790D47205B616464725D20202020202020202020476F2072756E2070726F67725B :2010A000616D202866726F6D2061646472290D4920706F72742020202020202020202020E7 :2010C00020496E707574202620646973706C617920627974652066726F6D20706F72740DEA :2010E0004E205B636F756E745D20202020202020202052756E20286E657874204E29206925 :201100006E737472756374696F6E730D4F20706F72742064617461202020202020204F7564 :20112000747075742064617461206279746520617420706F72740D52205B72656769737412 :201140006572206E616D655D20446973706C61792F6368616E6765207573657220726567D2 :201160006973746572730D00217D0FCDD20B210000CDFC05216611CDD20BC9CD5F0CD5C1A9 :20118000ED7821F9FE060636202310FBEBCDB80C3E0D1221F9FECDC80BC9CD5F0C3EDAD2C6 :2011A0006C0DD5CD5F0CC13EDAD26C0DED59C921F9FECD370CFE52C2C412CD370CCAC412B6 :2011C00056235E3E0DBB20021E20010014DD218012FD21A6FE78FE053004CBC9FD2BDD6EB5 :2011E00001DD6600A7ED522002CBC1CB41CA6112DDE5FDE5CDF10B11F9FEDDE5E179010339 :2012000000EDB04FCB49280BFD6E00FD6601CDB20C1806FD7E00CDB80CCD291321F9FEE511 :20122000362023C50650CD6D0BC1E1CD370C2847FE512009CDF60BFDE1DDE1AFC9CD620C1F :20124000FE0D280821B30DCDC80B18ABD5DDE1CDF60BFDE1DDE3E1FD7500CB492803FD740D :2012600001FD2BDD23DD23DD231009AFCB41C03E2FC36C0DC3D511CDF60BFDE1DDE118E1FC :201280004120204620204220204320204420204520204820204C20204127204627204227A7 :2012A000204327204427204527204827204C27204958204959205043205350203C496E73EC :2012C00074722E3E21801211F9FE013000EDB03E04CD590C0E03EDB0CD590C3D20F321BCB2 :2012E00012010800EDB03E0D1221F9FECDC80B11F9FEDD21A6FE0610DD7E00CDB80CDD2B6D :2013000010F60604DD6600DD6EFFCDB20CDD2BDD2B10F1DD2A91FE0603DD7E00DD23CDB815 :201320000C10F63E0D1213121321F9FEEBA7ED52EB43CDDB0BAFC9CD5F0CD5CD5F0C7AB352 :201340002828D521000039ED6F23ED6FC179E6F0280104E111F9FEC5CDFC0BE521F9FECDAA :20136000C80BE1C110EEC91213D5D1D5CD0F0D3E88DA6C0DE111F9FEE5CDFC0B21F9FE06CF :2013800008CDDB0BCD450CD128DEFE51C8D5CD620CFE0D7BD128D03E15C36C0D2AA9FE7C4B :2013A000B5280A3AABFE7721000022A9FE2AB1FECD5F0C7AB3C8CD0F0D3E45DA6C0DD5CD9B :2013C0005F0C7AB33E012809CD82003EA8CA6C0D7B32ACFEE17E32ABFE36FF22A9FEC9ED48 :2013E0005B91FECD0F0D3E68DA6C0DEBED4BA9FEA7ED422009214AFFCBC63AABFE022A91BD :20140000FE2B7E32B0FE36FB2291FE22AEFECD8200115D14732372CD8E00ED73A7FE319398 :20142000FEFDE1DDE1E1D1C1F108D9E1D1C1F1ED7B8FFEE52A91FEE3C9FD2293FEFDE1DDBF :201440002295FEDDE1DD2291FEED738FFEF331A7FEF5C5D5E508D9F5C5D5E5FDE9CD39140C :20146000ED7BA7FECDA7002AAEFE3AB0FE77214AFFCB46CB86C82AA9FE36FFC942726561D9 :201480006B20617420CD3914318FFEFB2A91FE2BED5BA9FEEBA7ED5221ACFE2007ED539192 :2014A000FE35204111F9FE3601217C14010900EDB02A91FECDB20CEB360D21F9FECDC80BD7 :2014C000C3760D2AB1FECD5F0C7AB32004ED5B91FE2AA9FEA7ED522011CD82003EA8CA6C3A :2014E0000DED5391FECDDF131804ED5391FEF3C31A14CD82003EA8CA6C0D2AB1FECD5F0CF9 :171500007AB37B20023E0132ADFECDDF13CDAF1121ADFE3520F4C9C4 :00000001FF 9140C :20146000ED7BA7FECDA7002AAEFE3AB0FE77214AFFCB46CB86C82AA9FE36FFC942726561D9 :201480006B20617420CD3914318FFEFB2A91FE2BED5BA9FEEBA7ED5221ACFE2007ED539192 :2014A000FE35204111F9FE3601217C14010900EDB02A91FECDB20CEB360D21F9FECDC80BD7 :2014C000C3760D2ABm80 startup,startup=startup m80 memsetup,memsetup=memsetup m80 debug,debug=debug m80 sysboot,sysboot=sysboot m80 diskop,diskop=diskop m80 drivparm,drivparm=drivparm l80 /P:40,/D:fe00,startup,drivparm,memsetup,sysboot,diskop,debug,rom/n:p/y/x/e DRIVPARMMACMEMSETUPMACa   ROM HEXe  ROM SUB call excom ;Show any additional stuff ld hl,endhlp call putmsg ;One extra line at end ret subttl In & Out Commands page ; Read & write 1 byte from the IO space. ; Port addresses are full 16 bits inport: ;Read & display port contents call getnum ;Port to read (even zero!) push de pop bc ;16-bit port in BC in a,(c) ;Read to A ld hl,conbuf ld b,6 ip1: ld (hl),' ' inc hl djnz ip1 ex de,hl ;Ptr. in DE call puta ld a,ascicr ld (de),a ;Terminator ld hl,conbuf ;Start of buffer call pcr ;Display ret outport: ;Write data to port call getnum ld a,noport jp nc,cmderr ;Must give a port push de ;Port address call getnum ;Data in E pop bc ;Port in BC ld a,noport jp nc,cmderr out (c),e ;That's all... ret subttl Register Display/Set Command page ; This block is rather awful spaghetti: being original legacy code ; from 1978! "If it ain't broke, don't fix it." ;Bit-flags in Reg. C usereg equ 0 ;Accept this reg. for processing wrdreg equ 1 ;This is a 16-bit reg. regs: ld hl,conbuf call getch ;Command type? cp 'R' jp nz,disall call getch ;Z is set if end of line jp z,disall ;If not 'R' + suffix, display all ; else display & set selectively ld d,(hl) ;1st. char. of reg-name inc hl ld e,(hl) ld a,ascicr cp e ;No 2nd char? jr nz,rg1 ld e,space ;No, use space ; ;Now set-up for scan rg1: ld bc,nregs shl 8 ;Count & flags, 0-Display, 1/2-Byte ld ix,mhdr ;Text ptr. ld iy,regend ;Store ptr. rg2: ld a,b ;Entry to process next register cp 5 ;2-byte registers? jr nc,rg2a set wrdreg,c ;Yes dec iy ;Step twice rg2a: ld l,(ix+1) ld h,(ix) ;Reg-name (NB byte order!) and a sbc hl,de ;As input? jr nz,rg3 set usereg,c ;Flag: use regs from here rg3: bit usereg,c ;Bit stays set on subsequent passes jp z,rg4 ;Skip display/set until matched push ix push iy ;Display/change this register call uplvl ;Save environment while displaying rg5a: ld de,conbuf ;Here to re-display on error push ix pop hl ld a,c ld bc,3 ldir ;Register name + space ld c,a ;Restore C bit wrdreg,c ;1 or 2-byte? jr z,oneb ld l,(iy) ld h,(iy+1) call puthl ;2-byte jr rg5 oneb: ld a,(iy) call puta ;1-byte rg5: call outbuf ;Output current value ld hl,conbuf push hl ld (hl),space ;Be sure there's a space at start inc hl push bc ;Save flags in C ld b,szbuf-1 call get ;Reply line pop bc pop hl call getch ;Test reply jr z,rg6 ;Null: next reg. cp 'Q' jr nz,rg7 call dnlvl ;"Q" - Quit pop iy pop ix ;Balance stack xor a ret ;Done rg7: call getn2 ;Form new value in DE cp ascicr ;Must be valid jr z,rg8 ld hl,mbdn call pcr jr rg5a rg8: push de pop ix ;Save result call dnlvl pop iy ex (sp),ix ;Restore IX pop hl ;New value in HL, other regs. restored ld (iy),l bit wrdreg,c jr z,rg4 ld (iy+1),h ;MSB if 2-byte rg4: ;Now, wind-up pointers dec iy inc ix inc ix inc ix ;Next register name djnz rg2b ;To a "JP", as rg2 is too far away xor a bit usereg,c ;Did we process a register? ret nz ;OK if match succeeded ld a,badreg jp cmderr ;Or error rg2b: jp rg2 rg6: call dnlvl ;Skip this register pop iy pop ix jr rg4 ;Then do next ;---------------------------------------------------------------- mhdr: db "A F B C D E H L A' F' B' C' D' E' H' L' " szmhdr equ $-mhdr db "IX IY PC SP " ;MUST follow immediately after mhdr htail: db "" lht equ $-htail nregs equ 20 ;Total no. of registers disall: ;Display all registers ld hl,mhdr ld de,conbuf ;First, build header ld bc,szmhdr ldir ;Names of 1-byte regs. ld a,4 ;Count of 2-byte regs. ds1: call dspac ld c,3 ldir ;2-byte reg. name call dspac ; & 2 extra spaces dec a jr nz,ds1 ld hl,htail ld bc,lht ldir ;Final part of legend ld a,ascicr ld (de),a ;End of Line-1 ld hl,conbuf call pcr ;Output 1st. line ld de,conbuf ;Restart output buffer ld ix,regend ;Do 1-byte values ld b,szmhdr/3 ds2: ld a,(ix) call puta dec ix djnz ds2 ld b,4 ;& 2-byte values ds3: ld h,(ix) ld l,(ix-1) call puthl dec ix dec ix djnz ds3 ld ix,(PC_) ;Display part of instr. ld b,3 ds4: ld a,(ix) inc ix call puta djnz ds4 ld a,ascicr ld (de),a ;Final CR inc de ld (de),a ;Double-line after inc de outbuf: ld hl,conbuf ;Output message: don't alter C ex de,hl and a sbc hl,de ex de,hl ;Addr. in HL ld b,e ;Length in B call putdis xor a ret ;Return, successful subttl Display/Set Memory Command page display: ;Display memory command call getnum ;Get starting address push de ;Save it call getnum ;Get length (if any) ld a,d or e ;If zero, display/test 1 only jr z,dp1 push de ld hl,0 add hl,sp ;HL points at DE on stack rld ;Roll-up LSB, don't care bits in 0-3 inc hl rld ;Rolled up 4 bits, so that pop bc ; [DE]/16 now in B, modulo-4095 ld a,c ;LS 4 original bits in C[4-7] and 0f0h ; ie remainder modulo-16 jr z,dp5 ;If non-zero, round up no. of lines inc b dp5: pop hl ;Start addr in HL, no. of lines in B dp2: ld de,conbuf push bc call disply ;Format 1 line for output push hl ;Save address ld hl,conbuf call pcr ;Send line pop hl pop bc djnz dp2 ;All lines ret ;Then done dp3: ld (de),a ;Place data dp4: inc de ;Next locn. push de dp1: pop de push de ;Copy addr.into DE call userarea ;OK to edit this area? ld a,nocnge jp c,cmderr ;No... pop hl ;Display/update 1 byte ld de,conbuf push hl call disply ;Build address & data ld hl,conbuf ld b,8 call putdis ;Send data & await reply call getlin ;Get any reply pop de ;Save address in DE jr z,dp4 ;Null - display next cp 'Q' ret z ;Quit push de call getn2 ;Get substitute value cp ascicr ;Which must end with CR ld a,e ;Substitute byte pop de ;Balance the stack jr z,dp3 ld a,badnum jp cmderr ;Error in reply subttl Set Breakpoint Command page .8080 ;Op-codes allowed as data only in 8080 mode ;Instructions placed by code brkins equ rst 7 ;Note the 8080 notation here: = RST 38H einst equ ei .z80 ;Normal assembly mode break: ;Set-Break command ld hl,(bpadr) ;Addr. of any existing breakpoint ld a,h or l ;Any set? jr z,bk1 ld a,(inst) ;Re-instate any displaced instr. ld (hl),a ld hl,0 ld (bpadr),hl ;Now, no breakpoint set bk1: ld hl,(inptr) call getnum ;Get new break address ld a,d or e ret z ;If zero, no new break call userarea ;Else, may not be in privileged area ld a,invbrk jp c,cmderr push de ;Save BP address call getnum ;Breakpoint count, or zero, in DE ld a,d or e ld a,1 ;Default jr z,onebk call getvect ;To use a count, we need interrupts ld a,noints ; If Z, no interrupts available jp z,cmderr ;So this command fails ld a,e onebk: ld (bpcnt),a ;Set the count pop hl ;BP addr. in HL ld a,(hl) ld (inst),a ;Save the displaced instr. ld (hl),brkins ;Set new breakpoint ld (bpadr),hl ret subttl User/Debug Environment Transfers page .Comment $ USER ENVIRONMENT The following code administers transfer from DEBUG to User Environment, which implies reloading all the user's register values. A utility routine will reload these registers, execute a single (user) instruction, then escape (via a CTC interrupt), and switch back to the DEBUG environment. Repeated calls to this routine will hence step through the user's program. An alternate entry point will restore the user-environment, without arming the CTC interrupt, and hence allows the user to run free. Breakpoints transfer from the user to this package, which switches to the DEBUG environment, and displays appropriate messages. Two types of breakpoint exist, viz. 1. An executed 0FFH (RST 38H) instruction, which is the type set by the BREAK command in DEBUG. 2. Single-stepping over instructions, which is done by setting a CTC channel to interrupt after the user instruction. This function requires suitable external hardware & CTC drivers. $ run1: ;Entry to run 1 instruction, & regain control ld de,(PC_) call userarea ;Check we're not in privileged area ld a,runrom jp c,cmderr ex de,hl ;User-PC in HL ld bc,(bpadr) ;Running from the set breakpoint? and a sbc hl,bc jr nz,claims ld hl,sysflg set atbrk,(hl) ;Note the fact, for later ld a,(inst) ld (bc),a ;Replace the real instr. claims: ld hl,(PC_) dec hl ;Locn. before the live instr. ld a,(hl) ld (eiopc),a ;Save that byte ld (hl),einst ;Replace it with EI ld (PC_),hl ;This is the locn. we shall run from ld (eiadr),hl ;It is also the locn. of the EI call getvect ;Vector address ld de,rentry ld (hl),e ;Set up vector inc hl ld (hl),d call armctc ;Set up for 1 interrupt after runfree: ;Entry to run the user, without regaining control ld (spva),sp ;Save DEBUG-level SP ld sp,IY_ pop iy ;Get back user registers pop ix pop hl pop de pop bc pop af ;Alternate regs. ex af,af' exx pop hl pop de pop bc pop af ;Main registers ld sp,(SP_) ;User's SP push hl ld hl,(PC_) ;User's PC ex (sp),hl ;Now on user's stack ret ;Despatch to user: INTERRUPTS DISABLED ;--------------------------------------------------------------------- dbgenv: ;Routine to switch to DEBUG environment ;Enter with return-link on (user) stack, ; & user-link below it ld (IY_),iy pop iy ;Link into dbgenv in IY ld (IX_),ix pop ix ;User link in IX ld (PC_),ix ld (SP_),sp di ;Don't interrupt: SP is invalid ld sp,AF_+2 push af ;Save main registers push bc push de push hl ex af,af' ;Save alternate registers exx push af push bc push de push hl jp (iy) ;Exit via 1st-level link ;------------------------------------------------------------------ rentry: ;CTC will interrupt to here, 1 instr. later call dbgenv ;Switch back to DEBUG environment ld sp,(spva) ;SP for call into run1 call stopctc ;Cancel the interrupt ld hl,(eiadr) ld a,(eiopc) ld (hl),a ;Restore the instr. displaced by EI ld hl,sysflg bit atbrk,(hl) ;Test & reset the at-breakpoint flag res atbrk,(hl) ret z ;If not at breakpoint, all done ld hl,(bpadr) ld (hl),brkins ;Re-instate the break-instruction also ret ;---------------------------------------------------------------- bkms: db "Break at " lbkms equ $-bkms rst38: ;RST 38H despatches here call dbgenv ;To DEBUG environment ld sp,stack ;Initialise DEBUG stack ei ld hl,(PC_) ;From the real breakpoint? dec hl ld de,(bpadr) ex de,hl and a sbc hl,de ld hl,bpcnt jr nz,bkmsg ld (PC_),de ;Yes, back up dec (hl) ;Count occurrences jr nz,runagn bkmsg: ld de,conbuf ;Display message ld (hl),1 ;Default counter in case a repeat ld hl,bkms ld bc,lbkms ldir ld hl,(PC_) ;Locn. of breakpoint call puthl ;Build the message ex de,hl ld (hl),ascicr ld hl,conbuf call pcr jp endcom ;Go & input a command subttl GO Command (run program) page goget: ld hl,(inptr) call getnum ;Get address (if any) ld a,d or e ;If zero, use current PC jr nz,gg2 ld de,(PC_) ;DE = address to run from gg2: ld hl,(bpadr) ;Run from live breakpoint? and a sbc hl,de jr nz,newpt call getvect ;Yes: this requires hardware support ld a,noints jp z,cmderr ; and we don't have it ld (PC_),de ;OK to run runagn: call run1 ;Run once, then replace breakpoint jr runs newpt: ld (PC_),de ;Set new PC runs: di jp runfree ; and run it subttl NEXT Command page next: call getvect ;This command requires hardware support ld a,noints jp z,cmderr ; and we don't have it ld hl,(inptr) call getnum ;Get count (if any) ld a,d or e ld a,e jr nz,nx1 ld a,1 ;Default =1 nx1: ld (nxcnt),a ;Set count onerun: call run1 ;Run a single instruction call regs ;Display registers, if provided ld hl,nxcnt dec (hl) ;Count steps jr nz,onerun ret ;End of count: next command end  ld a,d or e ld a,e jr nz,nx1 ld a,1 ;Default =1 nx1: ld (nxcnt),a ;Set count onerun: call run1 ;Run a single instruction call regs ;Display registers, if provided ld hl,nxcnt dec (hl) ;Count steps jr nz in0 a,(scr) bit 3,a ;ROM shadowed? ld hl,rams5 call nz,putmsg ;Say so ld hl,nline call putmsg ret rams1: db 'RAM available: ',0 rams2: db 'kB. From ',0 rams3: db '000 to ',0 rams4: db 'FFF',0 rams5: db 'ROM shadowed into 1st 32kB',0 ;================================================================== .radix 16 ;Initialisation tables inztab: db rcr, 00 ;No refresh (all static) db omcr, 00 ;Timings as Z80 db il, 00 ;Local interrupts vector base ; db wsgcs, 9b ;CS waits don't work?? db dcntl, 60 ;Wait states: mem 1 (for ROM) ; IO 2 (for SMC) db bbr, 00 db cbr, 0fc ;Wrap CA1 over BA, at 08000 db cbar, 0c8 ;Memory mapping: page 90 ;===============================================================; ; ; ; M E M O R Y - C H I P L O C A T I O N F U N C T I O N ; ; ; ;===============================================================; ;=======================================================================; ; ; ; D-X Designs Pty. Ltd. Perth, Western Australia ; ; Project: 112 May, 1996 ; ; ; ; Copyright (C) 1996 David R. Brooks ; ; ; ; This program is free software; you can redistribute it and/or ; ; modify it under the terms of the GNU General Public License ; ; as published by the Free Software Foundation; either version 2 ; ; of the License, or (at your option) any later version. ; ; ; ; This program is distributed in the hope that it will be useful, ; ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; ; GNU General Public License for more details. ; ; ; ; You should have received a copy of the GNU General Public License ; ; along with this program; if not, write to the Free Software ; ; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ; ; ; ;=======================================================================; .comment $ Determine memory size page 90 title Command Extensions ;===============================================================; ; ; ; D E B U G - C O M M A N D E X T E N S I O N S ; ; ; ;===============================================================; ;=======================================================================; ; ; ; D-X Designs Pty. Ltd. Perth, Western Australia ; ; Project: 112 May, 1996 ; ; ; ; Copyright (C) 1996 David R. Brooks ; ; ; ; This program is free software; you can redistribute it and/or ; ; modify it under the terms of the GNU General Public License ; ; as published by the Free Software Foundation; either version 2 ; ; of the License, or (at your option) any later version. ; ; ; ; This program is distributed in the hope that it will be useful, ; ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; ; GNU General Public License for more details. ; ; ; ; You should have received a copy of the GNU General Public License ; ; along with this program; if not, write to the Free Software ; ; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ; ; ; ;=======================================================================; .comment $ Skeleton for DEBUG extension functions These will typically include system bootstrap, and (eventually) Flash-ROM programming functions. On entry, HL is a "function" code: If non-zero, it points at the command key-letter in the input line. Subfunctions should identify their letter, and branch forward if no match. Finally, return with CY set if error. If HL=0, each sub-function should display its help message before passing control to its successor. The last should clear CY and return. $ .radix 10 .z80 cseg include ASCII.INC include DRVTYPE.INC include ROMHOOK.INC extrn getnum ;Numerical input, from ROM global excom ;Hook from debugger excom: jp flash ;Try the flash commands ;-------------------------------------------------- ; FLASH-ROM PROGRAMMING (not yet implemented) ; Functions: 1. Move ROM code to high RAM ; 2. Burn ROM from RAM data flash: ;Nothing defined, yet jp sysboot ;Try for OS bootstrap ;-------------------------------------------------- ; SYSTEM BOOTSTRAP FUNCTION .comment $ When this command is executed, the memory is set up thus: 0000-7FFF ROM 8000-FFFF RAM This means we cannot load the boot sector at low RAM, so we load it at 8000H. It will then (typically) load CP/M at high RAM, before killing the ROM and jumping to the BIOS start-point. As a safety feature, the boot-sector is sumchecked. Once it is successfully read, the checksum is verified, to be sure it really is boot code, before jumping to it. $ bootad equ 8000h ;Boot-load point sysboot: ld a,h or l ;HL null? jr nz,tboot ld hl,bthelp call putmsg ;Yes: display the help ld hl,0 jp next ;To successor tboot: ld a,(hl) cp 'S' ;Was it a boot command? jp nz,next ;No: leave it to the next ;This command is for me... call getnum ;Try for drive ld a,e cp 4 ;If present, must be valid jr nc,no push af ;Save drive call getnum pop af ld d,a ;Drive in D, type in E ld a,e and a ;No type given? jr z,use3 ;Default? cp 3 ;Or specifically 3" ? jr z,use3 cp 5 jr z,use5 ;Else, only 5" no: scf ;Invalid... ret use3: ld e,D3_144 ;Drive: 3", 1.44MB ld ix,dpb3 jr use use5: ld e,D5_360 ;Drive: 5", 360kB ld ix,dpb5 ; jr use use: ;Load it: IX => DPB ptr. ld c,(ix) ld b,(ix+1) ;BC -> DPB proper push bc pop ix ;IX set up push de ;Save drive & type ld hl,bootad ;HL => read buffer ld b,1 ;No. of sectors ld c,0 ;Track ld e,1 ;1st. sector ld a,2 ;"Read" rst diskop ;Do the read (IX unchanged) pop de ;Get the drive ld hl,btfail ;Error pointer jr c,failbt ;Go if errors ld hl,bootad ;Sumcheck the boot sector ld bc,200h ;Length loaded xor a slp: add a,(hl) ;Run the check cpi ;HL++, BC--, set P/V jp pe,slp ;All ld hl,smfail and a ;Sumcheck to zero? jr nz,failbt call z,bootad ;Yes: go run it ;NB IX -> DPB ; DE = Boot Drive & Type ; Stack is valid ld hl,secfl ;If it returns: it's an error failbt: call putmsg ;Display error message ld a,1 call diskop ;Drive motor/s off and a ;No msgs. from DEBUG ret bthelp: db 'S [drive] [type] Boot system from drive', ascicr db ' = 0..3', ascicr db ' = "3" or "5" (size)', ascicr, 0 btfail: db 'Error reading boot sector', ascicr, 0 smfail: db 'Boot sector failed sumcheck', ascicr, 0 secfl: db 'Error from boot-sector code', ascicr, 0 ;--------------------------------------------------- next: ;Next function (actually the end) ld a,h ;Finish: just a HELP ? or l ret z ;If so, return success scf ;Else: fail (no-one took it) ret end ng boot sector', ascicr, 0 smfail: db 'Boot sector failed sumcheck', ascicr, 0 secfl: db 'Error from boot-sector code', ascicr, 0 ;--------------------------------------------------- next: ;Next function (actually the end) ld a,h ;Finish: jus page 90 ; Real-time clock drivers - DS1202 part ;===============================================================; ; ; ; D S 1 2 0 2 C L O C K - C H I P D R I V E R ; ; ; ;===============================================================; ;=======================================================================; ; ; ; D-X Designs Pty. Ltd. Perth, Western Australia ; ; Project: 112 May, 1996 ; ; ; ; Copyright (C) 1996 David R. Brooks ; ; ; ; This program is free software; you can redistribute it and/or ; ; modify it under the terms of the GNU General Public License ; ; as published by the Free Software Foundation; either version 2 ; ; of the License, or (at your option) any later version. ; ; ; ; This program is distributed in the hope that it will be useful, ; ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; ; GNU General Public License for more details. ; ; ; ; You should have received a copy of the GNU General Public License ; ; along with this program; if not, write to the Free Software ; ; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ; ; ; ;=======================================================================; .sall Z80182 equ 0 ;Define the CPU variant in use include Z180.INC ;Standard definitions extrn suparm, sutime ;Standard RTC fields global NVRAM ;Despatcher extrn getspd ;Baud-rate finder ; Command codes: ; 10 - Read time/date to RAM ; 11 - Write " " to chip ; 12 - Read setup params. to RAM ; 13 - Write " " to chip ; 14 - Get ROM date code, YYMMDD to AHL ; 15 - Get setup params. address in HL ; 16 - Get date/time address in HL ; 17 - Get baud-rate divisors in HL, DE NVRAM: ;Common entry point and 0fh ;Commands jr z,NVRDate ;Read clock dec a jr z,NVWDate ;Write clock dec a jr z,NVRSetup ;Read RAM dec a jr z,NVWSetup ;Write RAM dec a jr z,datecd ;ROM date-stamp dec a jr z,gsu ;Addr. of setup params. dec a jr z,gsc ;Addr. of clock vector dec a jp z,getspd ;Get baud factors scf ret ;Undefined op-code datecd: ;Get date-code from ROM ld hl,(4) ;MM in L, DD in H ld a,h ld h,l ld l,a ;Swap: MM in H, DD in L ld a,(3) ;YY in A and a ;CY=0 ret gsu: ;Get setup params. addr. ld hl,suparm and a ret gsc: ;Get clock address in HL ld hl,sutime and a ret ;--------------------------------------------------------- ; R . T . C . C H I P S E R V I C E S NVRDate: ;Read date from RTC to RAM ld a,0bfh ld b,8 ;Length of time/date block ld hl,sutime lr1: push af call RTC_open pop af call RTC_write_byte ;Burst read command lr2: call RTC_read_byte ;Read one ld (hl),a inc hl djnz lr2 call RTC_close and a ;CY=0 ret NVRSetup: ;Read the Setup parameters from RTC to RAM ld a,0ffh ld b,18h ;Length of setup block ld hl,suparm jr lr1 NVWDate: ;Write time/date from RAM to RTC ld hl,sutime res 7,(hl) ;Clock-halt off ld b,8 ld c,0beh lw1: call RTC_open ld a,8eh call RTC_write_byte ;Write-protect off ld a,0 call RTC_write_byte call RTC_close ;Must clear-down call RTC_open ;Before starting new op. ld a,c ;Write clock/setup call RTC_write_byte lw2: ld a,(hl) call RTC_write_byte inc hl djnz lw2 call RTC_close and a ;CY=0 ret NVWSetup: ;Write the Setup params. to chip ld hl,suparm ld b,18h ;Length of setup block ld c,0feh jr lw1 ;Bits in Parallel Port A rtcrst equ 2 ;Reset: active low rtcclk equ 1 ;Clock rtcdat equ 0 ;Data - bidirectional RTC_open: ;Activate the RTC: call before operations in0 a,(ddra) set rtcdat,a ;data line IN out0 (ddra),a in0 a,(dra) res rtcclk,a out0 (dra),a ;Clock must be LO at start set rtcrst,a out0 (dra),a ;Then RST\ HI ret ;-------------------------------- RTC_close: ;Deactivate RTC after access in0 a,(ddra) set rtcdat,a ;Data line IN out0 (ddra),a in0 a,(dra) set rtcclk,a out0 (dra),a ;CLK HI res rtcrst,a out0 (dra),a ;RST\ LO ret ;-------------------------------- RTC_read_byte: ;Get next byte to A push bc ld b,8 ;Bit counter lr: in0 a,(dra) res rtcclk,a out0 (dra),a ;Clock falls nop ;Data setup time in0 a,(dra) ;Get data rrca rr c ;Data => C[7] rlca set rtcclk,a out0 (dra),a ;Clock rises djnz lr ld a,c ;Data byte pop bc ret ;-------------------------------- RTC_write_byte: ;Send A to the RTC push bc ld c,a ld b,8 in0 a,(ddra) res rtcdat,a ;Data line OUT out0 (ddra),a lw: in0 a,(dra) res rtcclk,a out0 (dra),a ;Clock falls srl a rrc c rla ;Data => A[0] out0 (dra),a set rtcclk,a out0 (dra),a ;Clock rises djnz lw in0 a,(ddra) set rtcdat,a out0 (ddra),a ;Data IN pop bc ret end tcdat,a ;Data line OUT out0 (ddra),a lw: in0 a,(dra) res rtcclk,a out0 (dra),a ;Clock falls srl a rrc c rla ;Data => A[0] out0 ; Port definitions for the FDC37C665/6 combo chips ; Prefix a "_" as some names clash with Z180 names ; Diskette controller _DOR equ 92h ;Digital Output _MSR equ 94h ;Main Status _DSR equ 94h ;Data-rate Select _DATA equ 95h ;Data & commands I/O _DIR equ 97h ;Digital Input _CCR equ 97h ;Confign. Control _DMA equ 0a0h ;Diskette DMA address ; Serial port ;RD/WR _RBR equ 98h ;R Receiver buffer _THR equ 98h ;W Transmit holding reg. _IER equ 99h ;RW Interrupt-enable reg. _IIR equ 9ah ;R Interrupt ident. reg. _FCR equ 9ah ;W FIFO control reg. _LCR equ 9bh ;RW Line control reg. _MCR equ 9ch ;RW Modem control reg. _LSR equ 9dh ;RW Line status reg. _MMSR equ 9eh ;RW Modem status reg. (name clash w. FDC) _SCR equ 9fh ;N/A Scratch reg. (not avail. in XT) _DDL equ 98h ;RW Divisor LSB | with DLAB _DLM equ 99h ;RW Divisor MSB | set high 9ah ;R Interrupt ident. reg. _FCR equ 9ah ;W FIFO control reg. _LCR equ 9bh ;RW Line control reg. _MCR equ 9ch ;RW Modem control reg. _LSR equ 9dh ;RW Line status reg. _MMSR equ 9eh ;RW Modem status reg. (name clash w. FDC) _SCR equ 9fh ;N/A Scratch reg. (not avail. in XT) _DDL !2@%KQ(3$/SML,$^()"1*`9'KQ(3$/S=Z=WA(>#_.?D&(*]W(Q#\W>G=X47- MB@6V=]WIW>'1?9,X]SQ/0\V*!5]!K[/+(S`&MG%X(0``1#E.Y0DC7B-6&-S=X>MH)@!$.>VP M(2``.?G=Z=WA(2``.5XC5F@F`$0Y[;`A(@`8Y]WAZW@O;R;_.?EP(T@&`.OM ML-WIM^U2&=@^D,-U'[?M4K?M0C`#"1G)/I$8[K?M4NL3ZD`&\!@!^!$``,G5 MZ[?M4NOA&.NW[5(A`0#(*\G-J`L8]@D8 M\,T\!R$!`-`KR@D8[\T\!R$` M`,C8(\G-.xlist .z80 ; Macros to define the Z-180 extended instructions. ; ; D-X Designs Pty. Ltd. 4/12/95 D. R. Brooks ; ; WARNING! These instructions are NOT supported by ; Z80MU. However the IO instructions are ; necessary to ensure correct access to ; the internal machine registers, which ; fully decode all 16 address bits. ; ; Adapted from Zilog (file 182macro.lib) ; Enhanced to provide conditional definition for the ; following chips (define the appropriate symbol) ; Z80180 Default ; Z80S180 ; Z80181 ; Z80182 ; First, check only one CPU is defined ifdef Z80180 ?test equ 0 ;These will throw a "Multiple endif ; Definition" error if 2 CPU's ifdef Z80S180 ; are defined ?test equ 1 endif ifdef Z80181 ?test equ 2 endif ifdef Z80182 ?test equ 3 endif ;========== Z180 Internal Interrupt Vectors ======== ; The following vectors are offsets from the value ; loaded in IL, the Interrupt Vector Low register. VINT1 equ 0 ;External INT-1 pin VINT2 equ 2 ;External INT-2 pin VPRT0 equ 4 ;Timer 0 VPRT1 equ 6 ;Timer 1 VDMA0 equ 8 ;DMA Ch-0 VDMA1 equ 0ah ;DMA Ch-1 VCSIO equ 0ch ;Clocked serial I/O VASC0 equ 0eh ;Asynch. comms. Ch-0 VASC1 equ 10h ;Asynch. comms. Ch-1 ;========== Z180 System Control Registers ========== ;NB These registers may be relocated to multiples of ; 40H, by setting the IO Control Register (ICR = 3FH) ; The addresses below are valid with ICR=0 (else they ; are offsets from the ICR base value). ;ASCI Registers cntla0 equ 00h ;ASCI Control Reg A Ch0 cntla1 equ 01h ;ASCI Control Reg A Ch1 cntlb0 equ 02h ;ASCI Control Reg B Ch0 cntlb1 equ 03h ;ASCI Control Reg B Ch1 stat0 equ 04h ;ASCI Status Reg Ch0 stat1 equ 05h ;ASCI Status Reg Ch1 tdr0 equ 06h ;ASCI TX Data Reg Ch0 tdr1 equ 07h ;ASCI TX Data Reg Ch1 rdr0 equ 08h ;ASCI RX Data Reg Ch0 rdr1 equ 09h ;ASCI RX Data Reg Ch1 brk0 equ 12h ;Break Control Reg Ch0 brk1 equ 13h ;Break Control reg Ch1 ;CSI/O Registers cntr equ 0ah ;CSI/O Control Reg trdr equ 0bh ;CSI/O TX/RX Data Reg ;Timer Registers tmdr0l equ 0ch ;Timer Data Reg Ch0-Low tmdr0h equ 0dh ;Timer Data Reg Ch0-High rldr0l equ 0eh ;Timer Reload Reg Ch0-Low rldr0h equ 0fh ;Timer Reload Reg Ch0-High tcr equ 10h ;Timer Control Reg tmdr1l equ 14h ;Timer Data Reg Ch1-Low tmdr1h equ 15h ;Timer Data Reg Ch1-High rldr1l equ 16h ;Timer Reload Reg Ch1-Low rldr1h equ 17h ;Timer Reload Reg Ch1-High frc equ 18h ;Free-Running Counter ifdef Z80S180 ccr equ 1fh ;CPU Control Reg endif ;DMA Registers sar0l equ 20h ;DMA Source Addr Reg Ch0-Low sar0h equ 21h ;DMA Source Addr Reg Ch0-High sar0b equ 22h ;DMA Source Addr Reg Ch0-B dar0l equ 23h ;DMA Destn Addr Reg Ch0-Low dar0h equ 24h ;DMA Destn Addr Reg Ch0-High dar0b equ 25h ;DMA Destn Addr Reg Ch0-B bcr0l equ 26h ;DMA Byte Count Reg Ch0-Low bcr0h equ 27h ;DMA Byte Count Reg Ch0-High mar1l equ 28h ;DMA Memory Addr Reg Ch1-Low mar1h equ 29h ;DMA Memory Addr Reg Ch1-High mar1b equ 2ah ;DMA Memory Addr Reg Ch1-B iar1l equ 2bh ;DMA I/O Addr Reg Ch1-Low iar1h equ 2ch ;DMA I/O Addr Reg Ch1-High bcr1l equ 2eh ;DMA Byte Count Reg Ch1-Low bcr1h equ 2fh ;DMA Byte Count Reg Ch1-High dstat equ 30h ;DMA Status Reg dmode equ 31h ;DMA Mode Reg dcntl equ 32h ;DMA/WAIT Control Reg ;System Control Registers il equ 33h ;INT Vector Low Reg itc equ 34h ;INT/TRAP Control Reg rcr equ 36h ;Refresh Control Reg cbr equ 38h ;MMU Common Base Reg bbr equ 39h ;MMU Bank Base Reg cbar equ 3ah ;MMU Common/Bank Area Reg omcr equ 3eh ;Operation Mode Control Reg icr equ 3fh ;I/O Control Reg ifdef Z80181 ;Features unique to Z80181 ;Integral PIO device p1ddr equ 0e0h ;Data Direction Reg 1 p1dp equ 0e1h ;Port 1 Data p2ddr equ 0e2h ;Data Direction Reg 2 p2dp equ 0e3h ;Port 2 Data ;Integral CTC device ctc0 equ 0e4h ;CTC Channel 0 ctc1 equ 0e5h ;CTC Channel 1 ctc2 equ 0e6h ;CTC Channel 2 ctc3 equ 0e7h ;CTC Channel 3 scccr equ 0e8h ;SCC Control Reg sccdr equ 0e9h ;SCC Data Reg ;Chip-select output pins ramubr equ 0eah ;RAM Upper Boundary ramlbr equ 0ebh ;RAM Lower Boundary rombr equ 0ech ;ROM Boundary scr equ 0edh ;System Control Reg endif ifdef Z80182 ;Features unique to Z80182 ccr equ 1fh ;CPU control reg. intype equ 0dfh ;Interrupt edge/pin mux reg. wsgcs equ 0d8h ;Wait-State Generator CS enh182 equ 0d9h ;Z80182 Enhancements Reg pinmux equ 0dfh ;Interrupt Edge/Pin Mux Reg ramubr equ 0e6h ;RAM End Boundary ramlbr equ 0e7h ;RAM Start Boundary rombr equ 0e8h ;ROM Boundary fifoctl equ 0e9h ;FIFO Control Reg rtotc equ 0eah ;RX Time-Out Time Const ttotc equ 0ebh ;TX Time-Out Time Const fcr equ 0ech ;FIFO Register scr equ 0efh ;System Pin Control rbr equ 0f0h ;MIMIC RX Buffer Reg thr equ 0f0h ;MIMIC TX Holding Reg ier equ 0f1h ;Interrupt Enable Reg lcr equ 0f3h ;Line Control Reg mcr equ 0f4h ;Modem Control Reg lsr equ 0f5h ;Line Status Reg msr equ 0f6h ;Modem Status Reg mscr equ 0f7h ;MIMIC Scratch Reg dlatl equ 0f8h ;Divisor latch LS dlatm equ 0f9h ;Divisor latch MS ttcr equ 0fah ;TX Time Constant rtcr equ 0fbh ;RX Time Constant ivec equ 0fch ;MIMIC Interrupt Vector mimie equ 0fdh ;MIMIC Interrupt Enable Reg iusip equ 0feh ;MIMIC Interrupt Under-Service Reg mmcr equ 0ffh ;MIMIC Master Control Reg ;Z80182 PIO Registers ddra equ 0edh ;Data Direction Reg A dra equ 0eeh ;Port A Data ddrb equ 0e4h ;Data Direction Reg B drb equ 0e5h ;Port B Data ddrc equ 0ddh ;Data Direction Reg C drc equ 0deh ;Port C data ;ESCC Registers sccacnt equ 0e0h ;ESCC Control Channel A sccad equ 0e1h ;ESCC Data Channel A sccbcnt equ 0e2h ;ESCC Control Channel B sccbd equ 0e3h ;ESCC Data Channel B endif ;[E]SCC Internal Register Definitions RR0 equ 00h RR1 equ 01h RR2 equ 02h RR3 equ 03h RR6 equ 06h RR7 equ 07h RR10 equ 0ah RR12 equ 0ch RR13 equ 0dh RR15 equ 0fh WR0 equ 00h WR1 equ 01h WR2 equ 02h WR3 equ 03h WR4 equ 04h WR5 equ 05h WR6 equ 06h WR7 equ 07h WR9 equ 09h WR10 equ 0ah WR11 equ 0bh WR12 equ 0ch WR13 equ 0dh WR14 equ 0eh WR15 equ 0fh ;==== Define the additional Z-180 instructions ===== ;Machine registers (internal use only) ?b equ 0 ?c equ 1 ?d equ 2 ?e equ 3 ?h equ 4 ?l equ 5 ?a equ 7 ??bc equ 0 ??de equ 1 ??hl equ 2 ??sp equ 3 slp macro db 0edh db 76h endm mlt macro ?r db 0edh db 4ch+(??&?r AND 3) SHL 4 endm in0 macro ?r, ?p db 0edh db 0+(?&?r AND 7) SHL 3 db ?p endm out0 macro ?p, ?r db 0edh db 1+(?&?r AND 7) SHL 3 db ?p endm otim macro db 0edh db 83h endm otimr macro db 0edh db 93h endm otdm macro db 0edh db 8bh endm otdmr macro db 0edh db 9bh endm tstio macro ?p db 0edh db 74h db ?p endm tst macro ?r db 0edh ifidn ,<(hl)> db 34h else ifdef ?&?r db 4+(?&?r AND 7) SHL 3 else db 64h db ?r endif endif endm .list  macro db 0edh db 9bh endm tstio macro ?p db 0edh db 74h db ?p endm tst macro ?r db 0edh ifidn ,<(hl)> db 34h else ifdef ?&?r db 4+(?&?r AND 7) SHL 3 else db 64h db ?r endif endif endm .liX&RT7*!2#-4A8A+@#-\AC-8A\^!>TYX#YH M[3G@R7-!P@& M>"&3X\VR!2J/X^4A`0#1&2*/XR&``.4JC^/1&2*1X\/7("&3X\T*!TYX#YJ[3G@P\4?0U(@=&\@96YDS9`9 MS6(?(9/CY?@ABCDCCPLUS PRNEFGHIJKLCCPLUS PRNMNOPRSTUCCPLUS PRNVWTEST HEX'XYZTEST SYM[DISKOPQ PRNXYZ[\]^_DISKOPQ RELbDISKOPQ PRN`acdefghDISKOPQ PRNijklmnop ; For M80 Z80.LIB must be available and must rename source 'CCPLUS'. ; ; 2.2 86/10/27. Search suppression for DOS+ use. Added KILL command ; to abort submit/job operations. CCP+ knows how executed. cbf ; 2.1 86/10/11 Fixed so "-b:xyz name" executes name in b:xyz.lbr ; (with CCPXTEND mounted). Was aborting. Added non-wheel drive ; access checks. Commands suppressed under wheel now search for ; transients, and transient execution is non-suppressable. Now a ; du consisting of ":" alone specifies default. Fixed REN. cbf ; 2.0 86/10/2 Preliminary beta test release. Complete rewrite of 1.7 ; 0000' cseg 0016 ccpver equ 22; UPDATE with each revision FFFF true equ -1 0000 false equ not true 0000 debug equ false; true allows linking to existing code 000D cr equ 0dh 000A lf equ 0ah 0009 tab equ 09h 001A eof equ 01ah ; D O S + system documentation 86/12/07 by C.B. Falconer DOS+ is a complete replacement system for CPM2.2 (Copyright Digital Research). DOS+ provides many CPM3 features, and several unique capabilities. It also supplies many ZCPR features, without requiring any extra memory assignments. DOS+ operates on Z80 CPUs only. DOS+, CCP+, DDTZ, INITDIR, FDATE, MOVDOS+, SETFLAGS, XJOB, TIME and their associated documentation are Copyright (c) 1986 by: C.B. Falconer, 680 Hartford Tpk, Hamden CT 06517, Tel (203) 281-1438. all rights reserved. They may be freely copied and distributed provided no charges are made, and that they are not included with other items for sale. For commercial per- mission contact C.B. Falconer. Contributions are solicited. All contributions of $20 or over will receive notices of available updates and/or revisions. $50 or over is considered registration, and major revisions (on Kaypro 4 or IBMPC format disks, as desired) will be made for 1 year, with source code. ------------------------------ This file is the header of DOSPLUS.DOC in DOSPLS25.LBR (or .ARC) object distribution file. That file contains the ready-to-run object code and further documentation. I have added the source (and object) of SYSGEN, for those who had problems with initial loads. Since virtually no-one has contributed any funds for this development, and it has been almost 6 months since the last, I have decided to release the source to the public domain for non-profit use. I still retain all commer- cial rights. Contributions remain welcome, however. The contents have been repackaged in an ARC file, and the embedded file names altered (to eliminate the "+" character, which gives MSDOS fits). cbf 88/01/13 begin 644 ROM.COM MP\D?S:M#;W!Y5^S0`"X?$]R!CS MS24"#0H`R<75Y=WE_>7U;R8`Y7-HP!]&-GE(08"&`3E(0`"(C@"X>/UQ=5^(['A^/CX^/%`=($P3T@]"L8Z,W0`=@JS@$8W_7%U>4A MJ`'-6@(AH@'-T`$JN@'40@+AT<'QR?7%U>4AM`$8Z?7%U>4AK@$8X/4ZO`*W M*!#%U>4],KP"(<@!S5H"X='!\4A MO`$8V_7%U>7E$?``(8L!`1``[;#1.IX!3SJ<`8+5S0`#T3J?`4\ZG0&#S0`# M(?``S=`!*J`!S4("X='!\4ZX0"W*!]Y_@T@&M7%S:``?+4H M#\T2`OX3(`C-$@+^`\K%'\'1*@$`&>DBVP#5>#+A`'FW*`L^PS(X`"$_'R(Y M`"')`Q&@``$8`.VP(>$#$;@``1(`[;#A`0,`[;`^?S+:`*_#(!;#.@/#1`/# M70/#4P/#6`/#3@/#70/#1`,#```#`0`!`@`"`P`#!``#!0`._Q@,#@#M6]L` M$QK^("CZ(64`!@/-?00:S80$_D$X$OY1,`Y'$QK^.B`&>-9`$Q@"&Z\A7`!W M(PP-*`P:_AH@!P8+S7D$&!`&",U6!!K^+B`&$P8#S58$(6@`!A@V`",0^\D: M#`TH!/XJ*!G^+B@:_B$X%OY]*!+^*B@.S80$=R,3$-_)$SX_&`(^('(U8C3B-&XL:3P8`+V\F_SGYZP/ML-WIT1I/!@`O;R;_.?GK`^VPZ=WAZR'@_SGYZ\4$ M!2@%KQ(3$/SML,$^()"1*`9'KQ(3$/S=Z=WA(>#_.?D&(*]W(Q#\W>G=X47- MB@6V=]WIW>'1?9,X]SQ/0\V*!5]!K[/+(S`&MG%X(0``1#E.Y0DC7B-6&-S=X>MH)@!$.>VP M(2``.?G=Z=WA(2``.5XC5F@F`$0Y[;`A(@`8Y]WAZW@O;R;_.?EP(T@&`.OM ML-WIM^U2&=@^D,-U'[?M4K?M0C`#"1G)/I$8[K?M4NL3ZD`&\!@!^!$``,G5 MZ[?M4NOA&.NW[5(A`0#(*\G-J`L8]@D8 M\,T\!R$!`-`KR@D8[\T\!R$` M`,C8(\G-J`L8],UZ"1COS3P'(0$`V"O)S:@+&/7->@D8\%1=2T+K(0``>K<^ M$"`#4SX(*>LIZS`!"3T@]LE\JO7-2@?KS4H'ZT1-KV=O/A'M:NU",`()-S_+ M$\L2/2#PZ_'P&$CES5P'RSS+'='KS=X&Z\MZR!@US2L'R"D0_MZMR`(>_X0,`-'M\FO9V_)ZWRJ?/I(![K`?;O)%\G+?,A\+V=]+V\C MR7WF`6\F`,GM2],`[5O1`,75>$%*4QX`'\L8RQG+&LL;X1GKX>U*1$TAZ6(9 M(M$`ZR$9-NU*(M,`1$W)!@`1$"?-K`<1Z`/-K`<19`#-K`<>"LVL!WT8#:\\ M[5(P^QD$/2`"!'E?28`(SE.@3@<=^LA``!$[4(Y^>OE`^VPZ^$K&T\#[;CK(_G=Z3X0PW'-I@17XG=X>'E?28`(SGY;R8`W>G=X2$``%0Y7DLCY1E>0R/E&>7] MX='A>9`X$#Q/Q=7E&KXH#.'1P2,-(/(A```8#B,3$.S1X<$A```YZ^U2_?G= MZ=WAS:8$3^'-IPE?X7Z3.!L,#2@7D3@2]7Z1=P8`4!E470GQ/$_ML!@"'7/= MZ=WAS:<)3]'M4^8`(0``.1KUAC@#N#@!>!+Q5UZ1."\\;WJ#.`2X?3@(>),X M)I$X(SRW*!_%U2KF`%\=%@!"&0G1U>50&>OA3^VXT<$8!7H\*!E/>)$\NS@! M>[LA`0`Y3^VP(0``5#E>$QGYW>G=X>$MPC`(;"8`W>DA`@!4 M.5X3&7XV`2-WR2$$`%0Y7DLCY1E>0R/E&>7]X='AK[@H!+D@"'BYX=']^=7I M&KX@]B,3!0T8YWRW(`-]M\`^$<-W'\W6"=`^`<-U'\U*"ACUS74/S6`*&.W9 M?;?9/@(HZ,V^"AC@V-Q@@ MS8\+/_4H$#@!V'9W>'+N+!'+"W,.PL(R7VWR-F5V3_-%@OEY>7=.=DN!=D^"`C-CPLX M`\UU"S_+%0@](`S==07=*]DMV2@./@C-3PLPWPC-=0NW&.'-3PLX!,V/"S_A MT<'+>"`%S5`+&)HL()/9Y<5XR_C9J.:`]7=(0``R>'8KV]'3U=?9\FWRQC+&MF*V5=YV8G93WC9B-E'R7S9E-EG>]F;V5]ZV9K95WG9F=E/>-F8 MV4?)>-FXV]F[V"@&S;P+ MR#_)?=F]V<"WR,./"WW6@=H["SS^*-#9Q=7E",T["P@WS40+/2#YV7S9I-EG M>]FCV5]ZV:+95WG9H=E/>-F@V4?#1`K9Q=7EV#X#PG4?S74/?<:`RR_&@&_6%/79Q=7ES;X*S=8)+<75Y"@#S=8)V2W9S:@+]3@#S4H*V2W9S:@+.`79+,U*"GW^;#@[V0&J*A&JJB%_ MJLU@"MWEW2'0##X%S?T.W>'-=0_-8`K-8`K%U>79S74/+2W9+\X=`W0``W0>HB(B(@(?JNJJJJJ M+"T^!,IU'\MXPG4?V7=(54-/@;-_0[=X2S9S6L/+=G-U@GQQ=7E;R8`,`$ES=$/V2S-8`K9 MX='!S=8)??YGVCL+R7V*G=B)'7WIHHLN.GV.XSB.8WY)DB1)$G[-S,S,3'^K MJJJJ*MG-:P_9M\MX]4LS9D/Y'Q,`KUV'+3\C+^,E_Y\_,$U1_]O2B,`E_ M:L&1"@:`M9Z*;T2`@BPZS1.`:L&1"@:!``````"`(:+:#TE]Z**++KI]CN,X MCF-^29(D29)^S7US74/S6`*\7--P_-U@G9X='!V79X='!R-G-3P\H`LOX+-D6!R@!%)(P`:_^"3@"/@D\5]79_2%= M`-WES;@0W>'13WH\RWL@$('R.!#]-@``&`O^##@"/@O5S4T1T2@%S;`0&`?-IA`-\EP0>K!\?'Q_F#\8P_7<`_2-XY@]'Q=7ERR7-4`O+ M)/M2D1-X')_>7A7Q8`&7XV`/XU MV!WZ:1$K?CQW_CK8-@`8\38Q(S8`#,G9`0``VL1V-G+X-TCW7X`_BLH!OXM(`3+Z-TCS0,2/]A/W2/-`Q(P"MTC5WF'AX&' M@D_+:"@$>>U$3]G9><:`_EK8_J8_V,7=Y7G-#1+=X=G!V8#*`CUS8`2\3T@ M^/&W\F`*V<.^"H$``````(X```!`')L``""\/J@`$*74:+8$O\D;#L.LQ>MX M+=#-SAO"4][Y>#D_`>LKJ*W%'?C)>\Z70'VWR,OXQ=5\S4,+S4,+A&?C[5KK MX>/M2D1-X3`&S40++#?(?<8#;\NXR0X!&`(.`,T,$QJ^(`@C$Q#X>>X!3R%` M`#GY:28`W>D.`1@"#@#-#!,-(`'K#@`:MKX@XB,3$/<.`1C:S0P3&K9W(Q,0 M^>OYW>G-#!,:+Z9W(Q,0^!COS0P3&J9W(Q,0^1CC_>'=X2$``#GK(2``13G] MZ=WA(2$`.7ZW*`.O&`8K1LV*!:8A(@`Y^2$``"@!(]WI/J\RY@#]X2K;``80 MS;(%KQ+A(N(`_>5\MSXBRB`6.N8`MR@-S883(`@JX@`V`"-WRLA7``!)`#ML,D&!B&V$\7E!@/M6]L`$QK^("CZ&LV$!)8H"N'! M$00`&1#CM\DC$Q#KP<$:_CK`?LE#3TX`5%)-`4M"1`),4U0#0558!%534@4^ MKS+F`,WN%,TD%BKB`"-^_@8@'LZY@"W`0\!*`K5#A/-!0#1`1;QQ41'``9ZR%<``$, M`.VPX1$,`!GEZPX7S04`T3S*KA4A7``!)`#ML,D^`<,@%CZO,N8`S1<6P"K? M`'RU/B$@ZRKB`!$,`!D17``!)`#ML!%<``X/S04`/"C/(?T5$8```1H`[;`1 M``$ZY@"W(`3M6P$!,0`!PX$`_]4.<%`!%<``X4S04`T2&``!GKMRCI&&8B MX@#-PA;(/B`RV0#).MD`M\CQR=WAW>7E(;HHU'X4(\WH`1C,%?IX%BO-)0(((`@`'2B]&.\V&LGE*N(`(W[^!N') MS<(6R,U;%_X:R,75Y2KB`"-^MR`.*MT`?OX:*&@C(MT`&&(](!7-$@+U_B`X M!S5L7_B`H%OX)*!+^#2@4_AHH$'7-(R,CY7[&+5\6`!EQX33P-@`.%7AM^U2ZY,X"B@(1SX@S9(8$/E#!`7(?LV2&",8]\'1 MV>'1P=G%W2K;`-7-]`\8Q\'1Q+<@'7FW^C(:Q=4.(OQR2+B`,V?&L@8Z`XB*N(`R];+7LC+ MGA@(*N(`RU;(RY;EQ1$P`!GK#AK-!0#!X1$,`!GKS04`M\G!T>U3X@#%Y%R*W/)/I'#(!;5V>'9(0``5%T^$"GK M[6KKV2G9,`0),`$3/2#OR4BX@!^Y@/*\QMXL2A,Q=4.<% M`"KB`!$,`!GK.N<`3\T%`-'!MR@0;SKG`/XB($-]/2@$_@,@/\75*N(`$2T` M&4XC1@-P*W$1V_\9<2-PT<$A@``9ZPL8L"KB`!$)`!E&*TXK*RM6*U[KM^U" MT.MQ(W#)/ID8!C[P&`(^!,,@%L'1[5/B`,7ES5(;T;?M4MH?&RKB``$(``ES M(W(!)``)>+$@&BKB``$, M``D&`(Q#[[5OB``X/S04`/"A(*N(``2$`">U+Y`!Q(W`C(^OM2^8`Q=4. M<%`.U;X@`.(+$@U2KB``$D M``GIW2KB`#[PPW^;\7R'M`"+K`-TJ[0#=;@+=9@-] MM"A([5(P#]UN`-UF`>7=(NL`W>$8XR`*W5X`W58!W>48&TU$W6X`W68!W>7= M&=UU`-UT`=UQ`MUP`]WET2KK`',C7A&2+-`"KR``$$``G= MY<$)VC4=[4O/`.U"`0``(0``VO`-^(V9O$Q,3>^;\7^LB\@`J M[0#EW>&W[5(P4MUN`-UF`>6W[5(P!-WA&/#AU?WA[4OR`/UQ`OUP`_UU`/UT M`=US`-UR`=WEX=U.`MU&`\W$'2@)W5X`W58!U=WAW>7AW4X"W48#W5X`W58! M&!LJ[0#M4^T`U=WAW74`W70![4OR`-UQ`MUP`^L)M^U2P-7]X2K-`+?M4B@; M_7X`W7<`_7X!W77A(LT`!@0V`",0^\G-"QXJ M]@#)S0L>*O@`R2$``"+V`"+X`-TJ[0#=3@+=1@-YL"@>*O8`"2+V`"KX`+?M M0C`$[4/X`-UN`-UF`>7=X1C8*L\``?O_">U;S0"W[5+8ZRKV`!DB]@`J^`"W M[5+0[5/X`,GM6\T`H>(N(` MX2+D`.$,#2`%S?88&`/-0!DJY`#I/J\RZ@`BY@`AZAXBX@#A(N0`X2+H`"%< M``8>S;(%KQ(JZ``ZZ@"W(`7-[A<8`\T2&"'9`'XV`+=G;R@(W>7A$5P`[5+K M*N8`'!X7BQ*`MS"WBQ*`5471/ML-WI1$W=X='A MM^U2&3#P"PGK">L#[;C=Z='!U2UA)DAV0!^-@!O M)@#)S:``?+7(S:,`??X#P-WAS24"7D,-"E5S97(@8G)E86L`&#$ZV0"WR-WA M]'-)0(-"E)U;BUT:6UE`,TE`B!E7A[5O5`+?M4A$5`!DBUP#-C03-)0(-"E!R;V=R86T@86)O0O$9WB`0``S;($PZ'A?3*)X_WE M*HGC)@`1,``!"@"W[5*W[4+2&"`JB>,F`.4A,`#1Z[?M4B**X\-T(!D)$4$` M`08`M^U2M^U"TD,@*HGC)@#E(4$`T>NW[5+E(0H`T1DBBN/#="`9"1%A``$& M`+?M4K?M0M)N("J)XR8`Y2%A`-'KM^U2Y2$*`-$9(HKCPW0@(?__(HKC*HKC MR?WAX2*"X_WE(4'DY2J"X]$9;B8`YN,J?./E*GKCT7RR9WVS;^4A`(#1?*)G?:-OY2$``-'-80;+1'A?3)J MX_WE(0``?3)KXR$``.4A_W_1S34&>K/*12/5(F#C*FKC)@#+1R(JNN3E*F#CT1EN)@!],E_C*E_C)@#E(?\`T MXR$!`.4A"@#1S34&>K/*WB+5(F+C*F+C(]$;P\PB(0``Y2'``.7-.`!],E[C M(0$`Y2$&`-'--09ZL\H*(]4B8N,J8N,CT1O#^"(J8./E(?__Y(RI@XR/1&\-.(B$` M`.4A``#ES3@`?3)>XR$!`'TR:^/#9B/APULCX<,\(RIKXR8`R2$``'TR7>,A M``!],ECC(0``Y2'_?]'--09ZL\JS(]4B5N,J6.,F`.4J5N/E(?__YK/*GR35(E3C(0``Y2$@`.7-.`!],ECC M(0``Y2$@`.7-.`!],ECC(3(`S4("(0``Y2'_?]'--09ZL\I])-4B5N,J5N/E M(:``Y/#HB0J5.,CT1O#XR/#JB3APY\DX<.6)"I=XR8` MR?WAX2)0X_WE*E#CY2$`@-%\HF=]HV_E(0``T/)PW,AD>/-G1E][@%ORT7* MTR8AD>/-.!8A0>0&>,TN&,U?&,UB'R%!Y.4A`0#1&6XF`.4A.@#1S6$&RT7* MPB7-,"4A``!],D'C(0(`(D+C(0$`Y2$"`.7->"#E(04`T1G1S34&>K/*%2;5 M(D3C*D'C)@#E*D+CY"#E(0@`T"`B1.,J1./E(0``T"#KX7,J1N/E(0$`T1DB1N,J0N/E(0(`T1DB0N,J1./E(0$`T>NW[5(B M1./#@B;#@R7-4A;-@1D24')O9W)A;6UI;F<@9G)O;3H@S6(?*H_CY'!X?,^R.TY.GF@ M_O\@!6XF`!@!<3[`[3DZ^_WI_>'A(A7C_>4B.0`^PS(X`,DJ%^/)(?\`?3() MXRJ/X^4JC>/1S34&>K/*C"?5(@KC*@GC)@#E*@KCY2'__^7-.`#1?*)G?:-O M?3()XRH*XR/1&\->)RH)XR8`Y2'_`-'-3@9],A#C*A#C)@#)(0``Y2$=`-'- M-09ZL\K9)]4B&>,A&^/E*AGCT1GE(1DGY2H9X]$9;B8`Z^%S*AGC(]$;PZXG M(1OCY(JNN3E*OGB MT1GE(?\`Z^%S*OGB(]$;PU`HS2TES5(6S8$9'4-H96-K:6YG(&5X:7-T:6YG M(%)/32!C;VYT96YTS9`9S6(?S5(6S9`9S6(?S4PGRT7*,2G-4A;-@1DX5&AI M2!B;&%N:R!2 M3TT@87)E82[-D!G-8A_-4A;-@1DE17AI2!I;G1E6]U7-T96T@:6YO<&5R86)L92[-D!G-8A\A`0!] M,HSCS5(6S9`9S6(?S5(6S8$9-$%R92!Y;W4@04)33TQ55$5,62!355)%('EO M=2!W86YT('1O(&-O;G1I;G5E("A9+TXI.B#-8A\A_N+-*Q8&"LTN&,U?&,UB M'R'^XN4A`0#1&6XF`,TH'^4A60#1S6$&RT7*G"K-Q1_-4A;-@1DJ0V]M;65N M8VEN9R!P(A`0`B[^(A(`!],NSB(8``Y2KOXM$9(NWB*NWB;B8`Y2$``-'-80;+1+E(0$` MT1DB\>(J[>)N)@!],NSB*N_BY2$!`-$9(N_B(8``Y2KOXM$9(NWBPPTM*O'B M(O?B*O?BR?WAX2+)XOWE(0``(J'B(0$`(I_B(2``?3*CXLT=!0`&("&DXLVR M!2&``.4JG^+1&2*=XBJ=XFXF`.4A``#1S6$&RT7*+RXJH^(F`.4A(`#1S4X& MY2J=XFXF`.4A(`#1S6$&T7VC;\M%R@HN*J'BY2$!`-$9(J'B*J'BY2K)XM'- M3@;+1+# MLRW#CBXJG>)N)@#E(0``T)N)@#E(2``T7-!P@&("&DXLVR!2J?XN4A`0#1&2*?XB&``.4JG^+1 M&2*=XL,R+B&DXLT*!08@($AR^+-"@7]Y7-T96TM4D]-(')E<')O9W)A;6UE"X@9FEL92!N86UE/LV0&"%!Y,VR!2$N`&4N`>4A0>3-"@7-?`CE(0``T"%!Y,VR!2&1X^4A0>3-"@7-/!/-8A\A MD>/-SQ/-8A_-4A;-@1D?4F5A9&EN9R`F('9E6EN9R!D871A(&9I;&4Z M("%!Y,T*!2$``,UQ&3- 1"@7-'04$+DA%6,T'"`9X(4$` ` end ͏ ?x P , 78ƀ8ƀ8ox٨!دoGOW_gɷɷ|لg{ً_zيWyىOxوG|ٔg{ٛ_zٚWyٙOx٘Gxٸyٹzٺ{ٻ|ټx٨ xx(ͼ ?}ٽÏ }ց; <(; 7D = |٤g{٣_z٢Wy١Ox٠GD u J }x>uu}ƀ/ƀo; -J }0W-J W,}l˸ͨ 8 ; ` x( -ͨ 8J -ͨ 8,J }l8;*!` ! >u` ` u--- J ,,,-xGg?+2n*8t z~,->uxua}.; OJ , ; !U >,k- o&0%,` }g; }؉}颋.:}8c~I$I~L*kٷx˸; }0G,͙<},-(-J ! >0 a` o8 Oþ >um.`1pF,t6|!wS<.z}[|%FXc~ur1}Oٯx(<˸ͨ 8; !~Jͨ 0O!><ͨ 8 =  7 <` O ; 7 0 W-J OT0 j oD,:j !I}袋.}8c~I$I~L!>u` ` 77 ` = O nf^VNF!DLT\I!!53!r1!\!> x #-= o˸xO(- }(x>8(C ,C `iM!>u|; |J>| )=|(DMbo˸ͦ88ͦx(0 8> Mx(>-Ͳ{(ay(Ͱͦ \z(>.Ͳ (Ͱ ~ͦ{>EͲ>+|(|Dg>-Ͳ|/ 0:p# ~# +>0w#,-  60#J˸}րogM| .e cold-boot code dirbf: ds 128 ;directory buffer all00: ds (noab/8)+1 ;Allocation vectors all01: ds (noab/8)+1 ; enough for 3" drives chk00: ds (node)/4 ;Directory check areas chk01: ds (node)/4 ; enough for 3" drives ; curdph: ds 2 ;Ptr. to selected DPH mapptr: ds 2 ;Ptr. to current mappin strategy dmaadr: ds 2 ;user "dma" addr. readop: ds 1 ;1 if read operation wrtype: ds 1 ;write operation type erflag: ds 1 ;error reporting / retry counter rsflag: ds 1 ;read sector flag unacnt: ds 1 ;unalloc. record count ; sekhst: ds 1 ;seek shr secshf hstact: ds 1 ;host active flag hstwrt: ds 1 ;host written flag ; ; following "triads" are order-sensitive sekdsk: ds 1 ;seek disk no. sektrk: ds 1 ;seek track no. seksec: ds 1 ;seek sector no. ; hstdsk: ds 1 ;host disk no. hsttrk: ds 1 ;host track no. hstsec: ds 1 ;host sector no. ; unadsk: ds 1 ;last unalloc. disk unatrk: ds 1 ;last unalloc. track unasec: ds 1 ;last unalloc. sector endlocaldata equ $ ;-------------------------------------------------------------- ; Cold-boot code, overlayed by local workspace above org localdata ; B O O T S T R A P F U N C T I O N S ; On entry, DE = boot drive & type ; boot: xor a ;cold start ld (iobyte),a ld a,d ld (cdisk),a ;Start from the boot disk ld (bootdv),a ;Save boot-drive number ld hl,overloads ;Cold-boot entry no longer used, so ld (wboote-2),hl ; "overload" it for extensions cͫCopyright (C) 1984 BORLAND IncAM-102 120/Apple CP/MP[1;1k~7#~=% o&ͦoͦܐԩͣ}!!"8~#(}:$= +*!Z!*B!!:(=2!Z: <2!!!:O::O:!*B! !45(!.+/ 0y0( d!kZ!{Z͈͈o&  :(y ͠|( *"x2y( >28!?"9!!>2 :D]SXN]D [ (!e}̈́A8Q0G: x@!\w# (   yV. V!h6# (*(.(!8}(*(̈́w#>?> w#a{ |͒}͛Ɛ'@'7||}>"C"6# ""͐ͩ*B"[R5*"^#V#^#V#N#FO/o&9O/o&9!9(> (G!9 w#E͊w}8uRB0 >R@RR!+ͨ z R!+ͨ z <!+ͨ z <!+ͨ z <!#ͨ z <!+ͨ z T]KB!z> S>))0 = |JJDMgo>jB0 7?= H\<z5+)+<z {0Gɯgo||H}||/g}/o#}o&K[xAJSJDM!b"!6J"DM'ͬͬdͬ ͬ} wͦWͧ _}8(8J`9{T]=o`9y w >uJ u` }>(; xQ }} ˸T}ٕ(0D=C ,= ( [ 0%D , 7 ͏ ?(8u x O - ; 8˸x X ,-xG}; }م 9; .>#n0[ D = - nx P ,-(-˸G,-; }ٕ? 9.>͏ 8u ?= u+-(>O 0u O 8͏ ?x P , 78ƀ8ƀ8ox٨!دoGOW_gɷɷ|لg{ً_zيWyىOxوG|ٔg{ٛ_zٚWyٙOx٘Gxٸyٹzٺ{ٻ|ټx٨ xx(ͼ ?}ٽÏ }ց; <(; 7D = |٤g{٣_z٢Wy١Ox٠GD u J }x>uu}ƀ/ƀo; -J }0W-J W,}l˸ͨ 8 ; ` x( -ͨ 8J -ͨ 8,J }l8;*!` ! >u` ` u--- J ,,,-xGg?+2n*8t z~,->uxua}.; OJ , ; !U >,k- o&0%,` }g; }؉}颋.:}8c~I$I~L*kٷx˸; }0G,͙<},-(-J ! >0 a` o8 Oþ >um.`1pF,t6|!wS<.z}[|%FXc~ur1}Oٯx(<˸ͨ 8; !~Jͨ 0O!><ͨ 8 =  7 <` O ; 7 0 W-J OT0 j oD,:j !I}袋.}8c~I$I~L!>u` ` 77 ` = O nf^VNF!DLT\I!!53!r1!\!> x #-= o˸xO(- }(x>8(C ,C `iM!>u|; |J>| )=|(DMbo˸ͦ88ͦx(0 8> Mx(>-Ͳ{(ay(Ͱͦ \z(>.Ͳ (Ͱ ~ͦ{>EͲ>+|(|Dg>-Ͳ|/ 0:p# ~# +>0w#,-  60#J˸}րogM| .(C = ~> x0w#xG%P %P ZJDM%P = _~65i+~hìx-Sx9?+{Η@}|C C gZJDM0D ,7}o˸  #yO!@9i&   # w# /w# w#!9! E9!!9~(+F͊!"9!(#>2*Ͳ"|>" :( ͆ *6#w*6#6 !\$![ (̈́( #:~CONTRMKBDLSTAUXUSR>2$*#~ Ͷ$*:> >w###6  #6++p>2S-$Ͷ:*6###ww#w$w#w: ##N#F*B> w#w#[s#r>2S$Ͷ$*6 #-Nw#Fwq#p#6#w#w#w* :( ͒: *^ F* < >26"~͟*-w#ww#͟"~ <@*Ͳ!\  <ʮ!\$> >2*|>! * \$\<(!: [1Á\!(f"> 2:!<"F( #~#6e>!["N>!~8>O6*"w (=(&("( :(N 8y(~#x+% (6*#~[*#~ *~(h#"b=  8 J= B== ͯ}8= ͵}/ͭ !*###~-_~(4Q6*>2>*##w:>*##~*#~(E[ ( ( ( !][ ( ( ((w#(6!]~-#8~>7  [>OkͼMs #rkͼpX á[ [ (( #w(q*#~[ (  *##~6͜O$*#~(08ʦ=ʦ==ʩ=ʬò+###~-_q46͡> *:4^q}Ò*|(M|( M6-#͐ͦ[R8 (G> ͒C~͒#*ͦC!h !lTRUEFALSEͦ!9^#(~#(G~͒#> ͒> Ò "F![(#RR0*4#4> RR *4 #4(>>2$*V(/˖:(#~+ x y2!͵( =( X:(R*:(###~-_-͌X> :("͟"*^˞*V˖0 SRѷR8A* N#F#s#r$ 0})jS\*###w* N#FB ͟r+s> !T]>)j)0 0= UR!#U*^#V#N#F#^#V>">!2DM"~x(L* :O(o:" C}=( ?*-N#Fp+qq#p! * F+N+++V+^Bq#p>>> SRѷR* s#r$ s#r"S"! N#FB(^x * 6#[<(H*! Kq#p##K[! *! 4 #4! x *$ *>w""{_!"*nf}(HR0nf" ^VMDnfutqp*s#r*s#r"* 5KB!>u~#fo{_"*R0RnfR0KqputsrNF( ^VNF^V*SutKqp R*R(~w~wnf ut"6# * *!""*NFy(* "*B0Cnf* [R*"*RS[s#r^#VS>O"w2x2!"" @*>2"!"""!\Ͳ*: !~6go(\R*s#r_2x( s x(T]DMR0 -a%}̈́o*!~6o&͠|ͣ}%^C User break1:% I/O% Run-time% error ͒%, PC=[R"͍% Program aborted*1!͍!K"ͲÐ "*&}oE R!b!}2>9>j9x*Ͳ!.o&}2*&! aEs *&! aEs * *&e.x*Ͳ*&! NE& >9>h9Ŕ1File Download Receiver: D-X Designs Pty Ltd, 1996͐b!}2!"x!Ͳ!*"*n&!aE"! ! <b! bŔReady to receive ! !q́ type ESC/CR to end͐b!!!n&!aE5"!!n&! aE+"! [! !q͐b!!! b>9>j9CR to end͐b!!!n&!aEʰs!! sum -r/size 4560/8576 entire input file er different DOS+ "users". Think of those users as MS-DOS subdirectories. I have not included source files that are generally available on the Internet: only for code I myself wrote or altered. In general, the code is suitable for processing with M80/L80, and Turbo Pascal. Generally, each "user" repesents a separate project. Each user therefore includes (unless it's a trivial matter) a .SUB file to assemble & link it. The more complex projects also include a README.TXT file. The DOS+ and CCP+ modules are by C B Falconer (see his notices in !!READ.ME and the source files). I have made minor changes to assemble with M80 (documented in the files), but have not changed the "sense" of the code. The disk layout is: User 0, "system" files (accessible from any user): 1. PPIP.COM A shareware replacement for CP/M's PIP 2. UUENCODE.COM and UUDECODE.COM The standard binary/ASCII converters 3. FORMAT.COM Formats 3" and 5" disks for the P112 system 4. USER.COM Change user numbers under DOS+. Same as CP/M (ie "USER n"), but 0 <= n <= 9. 5. RECEIVE.COM Receives and files ASCII text. Enter "RECEIVE ", and enter ESC/CR to quit. Because these are "system" files, they will not show up on a DIR listing. User 0, non-system files (visible on DIR): 1. README.TXT This file 2. HARDWARE.TXT Explanations of how the hardware works, detailed pin-outs of connectors, etc. 3. LICENSE.TXT The GNU General Public License User all drivetype ;Set up drive & type xor a call diskop ;Reset the (newly loaded) disk driver ld hl,auxinz call setup ;Port setups: aux. port ld a,8 ;Set up parallel (printer) port out0 (cport),a ;INIT\ low ld bc,0010h iz1: djnz iz1 dec c ;Long pause jr nz,iz1 ld a,0ch out0 (cport),a ;INIT\ high in0 a,(sport) ;Not sure why the PC reads twice, in0 a,(sport) ; if in doubt, do the same :-) xor a ld (46h),a ;For DOS+, no path ld hl,DATECODE ;Sign-on message call putmsg jp gocpm ;To common boot-code ;---------------------------------- setup: ;Output a block to ports ld a,0ffh ilp: ld b,0 ;MS address bits ld c,(hl) ;Output port tst c ;Zero will halt (A & C) ret z inc hl ;Else, point to data outi ;Sent, alters B jr ilp auxinz: ;Setup table for aux. port db _LCR, 80h ;Select divisor db _DDL, 0ch ;9600 bps db _DLM, 0 ;Divisor MSB db _LCR, 03h ;8 bits, 1 stop, no parity db _IER, 0 ;No interrupts db _MCR, 03h ;DTR, RTS active db 0 ;End ;---------------------------------------------------------- DATECODE: db ascicr,ascilf,'BIOS built 08-Mar-1997' db ascicr,ascilf,0 org endlocaldata end isor MSB db _LCR, 03h ;8 bits, 1 stop, no parity db _IER, 0 ;No interrupts db, & make setups Memory chips may be fitted in several combinations. The only rule is that if 2 RAMs are used, both must be of the same size. The code will attempt to "phantom" the ROM into low RAM. This requires: 1. RAM is available at physical address 00000 2. Not less than 256kB of RAM are fitted The setup follows this decision table: Chips fitted Address responses RAM valid at RAM Bounds U2 U3 A19 A18 A17 A16 A15 F0000 08000 Low High -------------------------------------------------------------------- -- -- x x x x x N N No RAM: Halt 32kB -- x x x x 0 Y N 00 07 -- 32kB x x x x 1 N Y 08 0F 32kB 32kB x x x x - Y Y 00 0F 128kB -- x x 0 - - N Y 00 1F -- 128kB x x 1 - - Y N 20 3F 128kB 128kB x x - - - Y Y 00 3F 512kB -- 0 - - - - N Y 00 7F -- 512kB 1 - - - - Y N 80 FF 512kB 512kB - - - - - Y Y 00 FF ROM (32kB) 0 0 0 0 0 (selected by ROMBR decoder) where "x" = address-bit not decoded (addresses will wrap) and "-" = a fully decoded address bit. The test starts by marking all addresses as valid-RAM (the ROM will override in its area). Then test for RAM at 2 addresses (see above): F0000 and 08000. This indicates if any RAM is present at all (!), and whether it extends down to address 00000. The detailed test is then copied into RAM (since we now know the address of at least 1 block), and executed there, with the ROM disabled. The lowest and highest valid RAM addresses are determined, and set up in the CPU's hardware decoder. Finally, if RAM extends over at least 00000-7FFFF, the ROM is copied to low RAM, and "phantom-ed" there, to speed up processing (since RAM is faster). As this routine starts, there is no memory set up, so no stack. Map registers affected:- Register Locn Start value Exit value CBAR 3A C8 88 BBR 39 00 Point into RAM as found CBR 38 00 ditto RAMLBR E7 00 Low RAM bound RAMUBR E6 FF High RAM bound SCR EF 60 (typ.) Bit-3 set if ROM shadowed Finally, the RAM will be relocated up the 1MB space, if 1. Physical RAM base = 00000, and 2. The ROM is NOT shadowed. This renders accessible the 32kB of RAM that was previously hidden under the ROM, increasing total capacity. Call this routine using the XCALL IY,MEMSETUP macro, since no stack is available at the time of the call (this routine will define one). The final setup will (assuming 64kB or more RAM) put the 3 areas thus: CA0 Logical 0000-7FFF ROM BA Logical 8000-BFFF RAM: base+(8000-BFFF) CA1 Logical C000-FFFF RAM: base+(C000-FFFF) This setup is "MP/M ready", in that it is only necessary to change CBAR from C8 (the value set by MEMSETUP), to C0, in order to replace the ROM (or its phantom equivalent) by user RAM space. To select different user areas, just change BBR to point to another 48kB "page", anywhere in RAM above the 64kB base-user area. So BBR = CBR, or >= CBR+10H. ----------------------------------------------------------------------- R E V I S I O N H I S T O R Y 17-05-96 Initial version 07-07-96 Correct handling of phantom-ROM setups 08-03-97 Don't speed-up CPU for phantoms (leave to clock-test later) $ Z80182 equ 0 include Z180.INC include MACROS.INC .radix 16 .sall cseg global memsetup reloc macro reg ;Adjust CPU reg.: incr. in B in0 a,(reg) add a,b out0 (reg),a endm relocn equ 40 ;RAM relocation factor (* 4kB) memsetup: xor a out0 (ramlbr),a ld a,-1 out0 (ramubr),a ;Be sure RAM is valid everywhere ld de,0 ld a,0F0 xcall ix,xismem ;See if this is RAM jr nz,mx1 ld e,0F0 ;Yes... mx1: ld a,8 xcall ix,xismem jr nz,mx2 ld d,8 mx2: ld a,d or e ;One must have worked jr nz,mx3 halt ;No RAM in the system! mx3: ld a,d and a ;Is D valid jr nz,mx4 ld a,e ;Then E is mx4: sub 8 ;Adjust for bank base =8000 out0 (bbr),a ;Bank: 8000 logical -> 08000/F0000 ex af,af' ;Save BBR for later ld hl,memrtn ;Clear of the bottom, in new space ld sp,hl ;Define a stack ex de,hl ld hl,xmbase ld bc,memrsze ldir ;Copy slave routine into RAM ld hl,0 ld bc,8000 ;Compute ROM checksum xor a mx5: add a,(hl) cpi ;HL++, BC--, set P/V jp pe,mx5 call memrtn ;Go run it (checksum in A) ; Now assign the RAM bounds as determined by the call. ;They must not be set earlier, as this may (temporarily) ;render the RAM inaccessible (the ROM overlays). If this ;happens while we are executing from RAM: disaster! out0 (ramlbr),d out0 (ramubr),e ;Physical RAM extent in0 a,(ramlbr) and a ;RAM present from zero? jr nz,mx6 ;No relocn. otherwise in0 a,(scr) bit 3,a ;Nor if ROM is shadowed jr nz,mx6 ld b,relocn ;OK: relocate the RAM reloprogram ROM_burner; { ;=======================================================================; ; ; ; D-X Designs Pty. Ltd. Perth, Western Australia ; ; Project: 112 May, 1996 ; ; ; ; Copyright (C) 1996 David R. Brooks ; ; ; ; This program is free software; you can redistribute it and/or ; ; modify it under the terms of the GNU General Public License ; ; as published by the Free Software Foundation; either version 2 ; ; of the License, or (at your option) any later version. ; ; ; ; This program is distributed in the hope that it will be useful, ; ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; ; GNU General Public License for more details. ; ; ; ; You should have received a copy of the GNU General Public License ; ; along with this program; if not, write to the Free Software ; ; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ; ; ; ;=======================================================================; This program will read an Intel hex-format file, and program the system ROM at U4. IF YOU MIS-PROGRAM THIS PART, YOUR SYSTEM MAY BECOME UNUSABLE! The program operates by momentarily re-enabling the ROM, baking an access, and disabling ROM again. The ROM code must therefore lie above 8000H, so as no to be itself overlaid by the ROM. In Turbo-Pascal, the only way to guarantee this is to copy the code onto the Stack, and run there. Program for use with Intel 28F256A Flash ROMs ONLY. --------------------------------------------------- } type cblock = array[0..29] of byte; rombuf = array[0..32767] of byte; rbp = ^rombuf; var rbptr : rbp; buff : string[120]; {Input-line buffer} inf : text; {The data file} lobound, hibound : integer; {Programming span} neederase : boolean; {ROM must be erased} {=========== I/O HELPER FUNCTIONS ===================} function hexdig(x :char) :integer; {ASCII -> hex.} begin case x of '0'..'9' : hexdig:= ord(x) - ord('0'); 'A'..'F' : hexdig:= ord(x) - ord('A') +10; 'a'..'f' : hexdig:= ord(x) - ord('a') +10; else hexdig:= -1; end end; function hexbyte(ptr :integer) :byte; {ASCII to byte} var a , b :integer; begin a:=hexdig(buff[ptr]); b:=hexdig(buff[ptr+1]); if ((a or b) and $8000) <> 0 then begin writeln('Bad hex. value in line:'); writeln(buff); writeln('Aborting'); halt; end else hexbyte:= (a*16 + b) and $FF; end; procedure hexout(x :integer); {Output X in hex.} {NB the 8-bit version of Turbo is not properly recursive. The classical recursive radix converter does not work...} const xchr : string[16] = '0123456789ABCDEF'; begin write(xchr[(x div $1000)+1]); x:= x mod $1000; write(xchr[(x div $100)+1]); x:= x mod $100; write(xchr[(x div $10)+1]); x:= x mod $10; write(xchr[x+1]); end; {=============== PROGRAMMING SWITCH ===================} procedure vppon; {Turn on 12V programming voltage} begin inline ($F3); {DI} inline ($ED); inline ($38); inline ($EE); {IN0 A,(EE)} inline ($CB); inline ($AF); {RES 5,A} inline ($ED); inline ($39); inline ($EE); {OUT0 (EE),A} inline ($FB); {EI} delay(100); {Pause for Vpp to build up} end; procedure vppoff; {Turn off programming voltage} begin inline ($F3); {DI} inline ($ED); inline ($38); inline ($EE); {IN0 A,(EE)} inline ($CB); inline ($EF); {SET 5,A} inline ($ED); inline ($39); inline ($EE); {OUT0 (EE),A} inline ($FB); {EI} end; {========== INTEL PROGRAMMING ALGORITHMS ===================} function rom(addr, outval :integer) :byte; external $38; function QuickPulse (zero :boolean) :boolean; {Programming function: does every thing necessary. ZERO, if true, forces it to program $00, else data from buffer. Data bytes of $FF are skipped: this is the erased value} var plscnt, {Retry count} wait, {For time delays} ptr : integer; {Address pointer} idata, data : byte; label OK, QUIT; begin QuickPulse:= false; for ptr:= 0 to 32767 do begin if zero then idata:= 0 else idata:= rbptr^[ptr]; if idata <> $FF then begin for plscnt:= 0 to 25 do begin data:= ROM(0,$40); {"Setup program"} data:= ROM(ptr,idata); {Program data} for wait:= 1 to 10 do ; {Pause 10uS nominal} data:= ROM(0,$C0); {"Program Verify"} for wait:= 1 to 6 do ; {Pause 6uS nominal} data:= ROM(ptr,-1); {Read data} if data = idata then goto OK; end; goto QUIT; {Retries exhausted: exit FALSE} end; OK: end; data:= ROM(0, 0); {Normal read mode} QuickPulse:= true; {Successful} QUIT: end; {End of QuickPulse} function QuickErase :boolean; {Erase algorithm} var data : byte; ptr, plscnt, wait : integer; label NEXT, QUIT; begin QuickErase:= false; data:= 0; for ptr:= 0 to 32767 do data:= data or ROM(ptr,-1); if data<>0 then begin {Must start all zeros} if not QuickPulse(true) then goto QUIT; end; for plscnt:= 0 to 1000 do begin data:= ROM(0,$20); {Erase setup} data:= ROM(0,$20); {Erase command} delay(50); {10mS at 16MHz} for ptr:= 0 to 32767 do begin data:= ROM(ptr,$A0); {Erase verify} for wait:= 1 to 6 do ; {Pause 6uS} data:= ROM(ptr, -1); {Read back} if data<>$FF then goto NEXT; end; data:= ROM(0,0); {All OK: set to READ} QuickErase:= true; goto QUIT; NEXT: end; {Next retry attempt} QUIT: end; {End of QuickErase} {================ DATA-FILE MANAGEMENT =====================} procedure limits(addr :integer); {Set up address limits} begin if (addr and $8000) <> 0 then begin writeln('Address out of range: > 8000H'); halt; end; if lobound > addr then lobound:= addr; if hibound < addr then hibound:= addr; end; procedure checkfile; {Test the data file} var addr, ctr, ptr : integer; sum : byte; procedure fatal; begin writeln('Bad format in data line: aborting'); writeln(buff); halt; end; begin lobound:= $7FFF; hibound:= 0; while not eof(inf) do begin readln(inf,buff); if buff[1] <> ':' then fatal; sum := 0; ptr:= 2; for ctr:= 1 to hexbyte(2)+5 do begin sum := sum + hexbyte(ptr); ptr:= ptr+2; end; if sum <> 0 then fatal; addr:= (hexbyte(4) shl 8) + hexbyte(6); if hexbyte(8) = 0 then begin limits(addr); limits(addr+hexbyte(2)); ptr:= 10; ctr:= hexbyte(2); while ctr > 0 do begin rbptr^[addr]:= hexbyte(ptr); addr:= addr+1; ptr:= ptr+2; ctr:= ctr-1; end end end; write('Programming from: '); hexout(lobound); write(' to: '); hexout(hibound); writeln; end; {================= PROGRAMMING FUNCTIONS PROPER ==============} procedure doit; {Must put in here, so variables are stacked} {Routine which MUST be executed in high memory: moved up} const romhook : cblock = ( $FD, $E1, {POP IY} $C1, {POP BC} $E1, {POP HL} $F3, {DI} $3E, $C8, {LD A,C8 - ROM on} $ED, $39, $3A, {OUT0 (3A),A} $79, {LD A,C} $A0, {AND B} $FE, $FF, {CP FF} $20, $05, {JP NZ,POKE} $6E, {LD L,(HL)} $26, $00, {LD H,0} $18, $01, {JR EXIT} {POKE:} $71, {LD (HL),C} {EXIT:} $3E, $C0, {LD A,C0 - ROM off} $ED, $39, $3A, {OUT0 (3A),A} $FB, {EI} $FD, $E9 ); {JP (IY)} var romfunc : cblock; ct : integer; function fixhook(var code :cblock) :integer; {Sets up jump vector} begin inline ($22); inline ($39); inline ($00); {LD (39),HL} inline ($3E); inline ($C3); {LD A,C3} inline ($32); inline ($38); inline ($00); {LD (38),A} inline ($C9); {RET} end; {Returns relocation addr. as integer} function checkrom : boolean; {ROM blank in this area?} var adr : integer; test : byte; begin test:= $ff; for adr:= lobound to hibound do test:= test and rom(adr, -1); checkrom:= test = $ff; end; var ibf : string[10]; scrap, mfr, part : byte; temp : integer; begin {Code -> high memory} for ct:= 0 to 29 do romfunc[ct]:= romhook[ct]; temp:= fixhook(romfunc); {Set up 38H as despatcher} { writeln('Hook addr '); hexout((temp shr 8) and 255); hexout(temp and 255); writeln; } if (temp and $8000) = 0 then begin writeln('Unable to relocate code above 8000H: aborting'); halt; end; new(rbptr); {Allocate buffer for new data} for temp:= 0 to 32767 do rbptr^[temp]:= $ff; {Clear it} checkfile; {Read & check data file} writeln('Checking existing ROM content'); writeln; if checkrom then begin writeln('This data will be written to a currently blank ROM area.'); writeln('Existing ROM data will not be erased.'); neederase:= false; end else begin writeln('WARNING! WARNING! WARNING!'); writeln; writeln('The System ROM is about to be erased and re-programmed.'); writeln('Any interruption of this process, or use of invalid data,'); writeln(' will render your system inoperable.'); neederase:= true; end; writeln; write('Are you ABSOLUTELY SURE you want to continue (Y/N): '); readln(ibf); if upcase(ibf[1]) <> 'Y' then halt; writeln('Commencing programming - DO NOT INTERRUPT!'); writeln; vppon; writeln('Vpp generator enabled'); scrap := rom(0, $90); {Command: read part ID} mfr := rom(0, -1); part := rom(1, -1); scrap := rom(0, 0); {Normal read mode} if ((mfr = $89) and (part = $B9)) then begin writeln('Intel 28F256A part identified'); end else writeln('Incorrect ROM part: cannot program'); if neederase then begin writeln('Erasing ROM...'); if not QuickErase then begin writeln('ROM faulty: could not erase'); halt; end else writeln('ROM erased successfully'); end; writeln('Programming ROM...'); if not QuickPulse(false) then begin writeln('ROM faulty: could not program'); halt; end else writeln('ROM programmed successfully'); vppoff; writeln('Vpp generator disabled'); { dispose(rbptr); } end; {End of DOIT} {============== MAINLINE & HELPERS =================} const cmtail = $80; type argt = string[32]; function paramcount : integer; var ct, ctr : integer; cmd : ^char; last : char; begin ct := 0; ctr := 1; last := ' '; cmd := ptr(cmtail+ctr); while ord(cmd^) <> 0 do begin if ((last = ' ') and (cmd^ <> ' ')) then ct:= ct+1; last := cmd^; ctr := ctr+1; cmd := ptr(cmtail+ctr); end; paramcount := ct; end; function paramstr(i : integer) : argt; var local : argt; last : char; ct, ctr : integer; cmd : ^char; label got, exit; begin ct := 0; ctr:= 1; last := ' '; local := ''; cmd:= ptr(cmtail+ctr); while ord(cmd^) <> 0 do begin if ((last = ' ') and (cmd^ <> ' ')) then begin ct:= ct+1; if ct = i then goto got; end; last := cmd^; ctr:= ctr+1; cmd:= ptr(cmtail+ctr); end; goto exit; got: while ((ord(cmd^) <> 0) and (cmd^ <> ' ')) do begin local := local + cmd^; ctr:= ctr+1; cmd:= ptr(cmtail+ctr); end; exit: paramstr:= local; end; begin writeln('P112 System-ROM reprogrammer'); writeln('For Intel 28F256A parts ONLY!'); writeln; if paramcount <> 1 then begin writeln('Usage: ROM '); halt; end; buff := paramstr(1); if pos('.',buff) = 0 then buff:= buff + '.HEX'; assign(inf,buff); reset(inf); {Ready to read data file} writeln('Reading & verifying data file: ',buff); doit; {Inner routine: make sure everything's stacked} close(inf); end. ONLY!'); writeln; if paramcount <> 1 then begin writeln('Usage: ROM '); halt; end;ͫCopyright (C) 1984 BORLAND IncAM-102 120/Apple CP/MP[1;1k~7#~=% o&ͦoͦܐԩͣ}!!"8~#(}:$= +*!Z!*B!!:(=2!Z: <2!!!:O::O:!*B! !45(!.+/ 0y0( d!kZ!{Z͈͈o&  :(y ͠|( *"x2y( >28!?"9!!>2 :D]SXN]D [ (!e}̈́A8Q0G: x@!\w# (   yV. V!h6# (*(.(!8}(*(̈́w#>?> w#a{ |͒}͛Ɛ'@'7||}>"C"6# ""͐ͩ*B"[R5*"^#V#^#V#N#FO/o&9O/o&9!9(> (G!9 w#E͊w}8uRB0 >R@RR!+ͨ z R!+ͨ z <!+ͨ z <!+ͨ z <!#ͨ z <!+ͨ z T]KB!z> S>))0 = |JJDMgo>jB0 7?= H\<z5+)+<z {0Gɯgo||H}||/g}/o#}o&K[xAJSJDM!b"!6J"DM'ͬͬdͬ ͬ} wͦWͧ _}8(8J`9{T]=o`9y w >uJ u` }>(; xQ }} ˸T}ٕ(0D=C ,= ( [ 0%D , 7 ͏ ?(8u x O - ; 8˸x X ,-xG}; }م 9; .>#n0[ D = - nx P ,-(-˸G,-; }ٕ? 9.>͏ 8u ?= u+-(>O 0u O 8͏ ?x P , 78ƀ8ƀ8ox٨!دoGOW_gɷɷ|لg{ً_zيWyىOxوG|ٔg{ٛ_zٚWyٙOx٘Gxٸyٹzٺ{ٻ|ټx٨ xx(ͼ ?}ٽÏ }ց; <(; 7D = |٤g{٣_z٢Wy١Ox٠GD u J }x>uu}ƀ/ƀo; -J }0W-J W,}l˸ͨ 8 ; ` x( -ͨ 8J -ͨ 8,J }l8;*!` ! >u` ` u--- J ,,,-xGg?+2n*8t z~,->uxua}.; OJ , ; !U >,k- o&0%,` }g; }؉}颋.:}8c~I$I~L*kٷx˸; }0G,͙<},-(-J ! >0 a` o8 Oþ >um.`1pF,t6|!wS<.z}[|%FXc~ur1}Oٯx(<˸ͨ 8; !~Jͨ 0O!><ͨ 8 =  7 <` O ; 7 0 W-J OT0 j oD,:j !I}袋.}8c~I$I~L!>u` ` 77 ` = O nf^VNF!DLT\I!!53!r1!\!> x #-= o˸xO(- }(x>8(C ,C `iM!>u|; |J>| )=|(DMbo˸ͦ88ͦx(0 8> Mx(>-Ͳ{(ay(Ͱͦ \z(>.Ͳ (Ͱ ~ͦ{>EͲ>+|(|Dg>-Ͳ|/ 0:p# ~# +>0w#,-  60#J˸}րogM| .(C = ~> x0w#xG%P %P ZJDM%P = _~65i+~hìx-Sx9?+{Η@}|C C gZJDM0D ,7}o˸  #yO!@9i&   # w# /w# w#!9! E9!!9~(+F͊!"9!(#>2*Ͳ"|>" :( ͆ *6#w*6#6 !\$![ (̈́( #:~CONTRMKBDLSTAUXUSR>2$*#~ Ͷ$*:> >w###6  #6++p>2S-$Ͷ:*6###ww#w$w#w: ##N#F*B> w#w#[s#r>2S$Ͷ$*6 #-Nw#Fwq#p#6#w#w#w* :( ͒: *^ F* < >26"~͟*-w#ww#͟"~ <@*Ͳ!\  <ʮ!\$> >2*|>! * \$\<(!: [1Á\!(f"> 2:!<"F( #~#6e>!["N>!~8>O6*"w (=(&("( :(N 8y(~#x+% (6*#~[*#~ *~(h#"b=  8 J= B== ͯ}8= ͵}/ͭ !*###~-_~(4Q6*>2>*##w:>*##~*#~(E[ ( ( ( !][ ( ( ((w#(6!]~-#8~>7  [>OkͼMs #rkͼpX á[ [ (( #w(q*#~[ (  *##~6͜O$*#~(08ʦ=ʦ==ʩ=ʬò+###~-_q46͡> *:4^q}Ò*|(M|( M6-#͐ͦ[R8 (G> ͒C~͒#*ͦC!h !lTRUEFALSEͦ!9^#(~#(G~͒#> ͒> Ò "F![(#RR0*4#4> RR *4 #4(>>2$*V(/˖:(#~+ x y2!͵( =( X:(R*:(###~-_-͌X> :("͟"*^˞*V˖0 SRѷR8A* N#F#s#r$ 0})jS\*###w* N#FB ͟r+s> !T]>)j)0 0= UR!#U*^#V#N#F#^#V>">!2DM"~x(L* :O(o:" C}=( ?*-N#Fp+qq#p! * F+N+++V+^Bq#p>>> SRѷR* s#r$ s#r"S"! N#FB(^x * 6#[<(H*! Kq#p##K[! *! 4 #4! x *$ *>w""{_!"*nf}(HR0nf" ^VMDnfutqp*s#r*s#r"* 5KB!>u~#fo{_"*R0RnfR0KqputsrNF( ^VNF^V*SutKqp R*R(~w~wnf ut"6# * *!""*NFy(* "*B0Cnf* [R*"*RS[s#r^#VS>O"w2x2!"" @*>2"!"""!\Ͳ*: !~6go(\R*s#r_2x( s x(T]DMR0 -a%}̈́o*!~6o&͠|ͣ}%^C User break1:% I/O% Run-time% error ͒%, PC=[R"͍% Program aborted*1!͍!/Ͳç.}2*&0 RB *&!0R"t  ARBC *&!AR! "t  aRBn *&!aR! "t !"*"!A*n&"|!A*!n&"z*|*z|g}o!|g}o!aE&!ŔBad hex. value in line:͐b!A R!q͐bŔAborting͐bF!*|!*z!|g}o}2*&`!0123456789ABCDEF"x!O!*x!!n&Rb*x!"x!O!*x!!n&Rb*x!"x!O!*x!!n&Rb*x!"x!O!*x!n&Rb8˯9!dB89}2j!}2k!!5zE#"`*j&Ek"!}2_{"**`n&}2_*_&!aE<#!!5z9#"d!!@8}2^*`*_&8}2^!! 5z""b*b#"!!8}2^!!5z #"b*b#"*`!8}2^*^&*_&NE0#b#*d#Ø"^#*`#N"!!8}2^!}2kf#[#<#*k&!}2]!}2X!!5zʳ#"V*X&*V!8|g}o}2X*V#Å#*X&!aE#!3"}oE#ß$!!5zʟ$"T!! 8}2X!! 8}2X!2B!!5z}$"V*V!8}2X!!5zP$"R*R#>$*V!8}2X*X&!aEt$æ$*V#$!!8}2X!}2]â$*T##ê$ß$Ö$*]&"P*P!|g}o!aE%ŔAddress out of range: > 8000H͐b**P͛E%*P"**PͯE,%*P"w%Ŕ!Bad format in data line: aborting͐b!A R!q͐b!"!"!͝}oE&!8!Ax._b!A!n&!:aE%0%!}2A!"B!!x !5z&"D*A&*Bx }2A*B!"B*D#%*A&!aE*&0%!x !!x "F!x !NE&*FͰ$*F!x Ͱ$! "B!x "D*D!͛E&**F*Bx s*F!"F*B!"B*D!R"DÂ&Ã%ŔProgramming from: b*L!Ŕ to: b*L!R͐bã'>9:y n&q>9:""9>28*!}2 **5zʌ'" * &* !8|g}o}2 * #^'* &!N}2*&!!5z'"!*!'*n&s*#î'!7'"*!|g}o!NE;(Ŕ-Unable to relocate code above 8000H: aborting͐b!!ͥ!!5zr("**!s*#P(-%ŔChecking existing ROM content͐bR͐bL'E1)Ŕ8This data will be written to a currently blank ROM area.͐bŔ%Existing ROM data will not be erased.͐b!}2%*ŔWARNING! WARNING! WARNING!͐bR͐bŔ7The System ROM is about to be erased and re-programmed.͐bŔ9Any interruption of this process, or use of invalid data,͐bŔ$ will render your system inoperable.͐b!}2R͐bŔ4Are you ABSOLUTELY SURE you want to continue (Y/N): b!+ ._b!!n&(!YaEʜ*Ŕ*Commencing programming - DO NOT INTERRUPT!͐bR͐b"ŔVpp generator enabled͐b!!8}2!!8}2!!8}2!!8}2*&!N*&!N}oEʎ+ŔIntel 28F256A part identified͐bý+Ŕ"Incorrect ROM part: cannot program͐b*&E@,ŔErasing ROM...͐bl#}oE,ŔROM faulty: could not erase͐b@,ŔROM erased successfully͐bŔProgramming ROM...͐b!3"}oEʟ,ŔROM faulty: could not program͐b,ŔROM programmed successfully͐b("ŔVpp generator disabled͐b!"!"! }2!*"*n&!aEv-*&! N*n&! a}oEQ-*!"*n&}2*!"!*" -*"*"!"!"! }2 !Ͳ!*"*n&!aE/.*&! N*n&! a}oE .*!"**NE .2.*n&}2*!"!*"ó-Î.*n&!a*n&! a}oEʎ.! *n&e. !Ͳ*!"!*"2.!  !Ͳ! ŔP112 System-ROM reprogrammer͐bŔFor Intel 28F256A parts ONLY!͐bR͐b,!aE?/ŔUsage: ROM ͐b!̀-x!AͲ!.e.!A |!NEʄ/!A .HEXx!AͲ!!A <b!bŔReading & verifying data file: !A !q͐b'!bNEN!A .HEXx!ANE .2.*n&}2*!"!*"ó-Î.*n&!a*n&! a}oEʎ.! *n&e. !Ͳ*!"!*"2.!  !Ͳ! ŔP112 System-ROM reprogrammer͐bŔFor Intel 28F256A parts ONLY!͐bR͐c ramubr reloc ramlbr ; Now, set the base of CA1 for the RAM. If 64kB or more, set up logical ;addr. 0000 -> CA1. If only 32kB, set logical 8000 -> CA1, since ROM ;cannot run otherwise. BA is set similarly. mx6: ld c,0 ;Adjustment in0 b,(ramlbr) in0 a,(ramubr) sub b ;RAM range available cp 8 ;More than 32kB? jr nc,mx7 ld c,8 mx7: ld a,b ;ie RAMLBR sub c ;Adjust base if only 32kB in0 c,(scr) ;Is the ROM shadowed to 1st 32kB of RAM? bit 3,c jr z,mx8 add a,8 ;If so, locate user RAM above it mx8: out0 (cbr),a ;CA1 base value out0 (bbr),a ;Bank Area ditto ld a,0C8h ;0000-7FFF = CA0: ROM out0 (cbar),a ;8000-BFFF = BA: RAM ;C000-FFFF = CA1: RAM xretn iy ;Back (called without stack) ;----------------------------------------------------------- xmbase equ $ ;Base of moving code xismem equ $+3 ;Addr. of ISMEM, locally .phase 8200 memrtn: jp mstart ;Hook the main routine ismem: exx ld b,a ;Save A (without stack) ld hl,0C000 sub 0c ;Adjust for CB1 base out0 (cbr),a ld a,55 ld (hl),a ;Write to "RAM" cp (hl) ;Correct? jr nz,ism1 cpl ld (hl),a ;Try a new pattern cp (hl) ism1: ld a,b ;Recover A, leave F exx xretn ix mbase: db 00, 08, 20, 80 ,-1 ;Putative base addresses mstart: push af ;Save ROM checksum push iy ;Save IY (incoming "link") in0 a,(scr) set 3,a out0 (scr),a ;ROM turned off ld iy,mbase ms2: ld a,(iy) inc iy cp -1 jr nz,ms1 halt ;Unable to locate RAM base ;Scan memory, looking for an address "wrap-around", as ; we hit the un-decoded high address bits. ms1: xcall ix,ismem jr nz,ms2 ;Physical base pop iy ;Restore IY (main "link") ld d,a ;Make 2 copies: fixed base ld e,a ; moving ptr. sub 0C ;Offset adjust out0 (cbr),a ld hl,0C000 ;Base of CA1 ld (hl),55 ;Test pattern at base ms4: ld a,8 add a,e ;Next 32kB block ld e,a jr c,ms3 ;Oflo from top of 1MB xcall ix,ismem ;Is there RAM here? jr nz,ms3 ;Out if not, else... ld (hl),0 ;Try to overwrite the base ld a,d sub 0C ;To fixed base out0 (cbr),a ld a,(hl) cp 55 ;Signature still there? jr z,ms4 ;Yes: repeat ms3: dec e ;E points at last good block in0 a,(scr) res 3,a out0 (scr),a ;ROM active again pop ix ;Balance stack in case we jump to MS6 ld a,d and a ;RAM from 00000 (underlays ROM)? jr nz,ms6 ;No: can't shadow ROM ld a,e sub d ;Amount of RAM present cp 3f jr c,ms6 ;Don't shadow if < 256kB of RAM push ix ;Put AF back on stack: this branch ;Copy the ROM into RAM, and finally disable it push de ;Save RAM bounds ld bc,8000 ;Length of ROM block ld hl,0 ;Start address ld d,0 ;Sumcheck for later in0 e,(scr) ms5: res 3,e out0 (scr),e ;ROM active ld a,(hl) ;Get 1 byte set 3,e out0 (scr),e ;RAM on, now ld (hl),a ;Copy out add a,d ld d,a ;Accumulate checksum cpi ;HL++, BC--, set P/V bit jp pe,ms5 ;Loop until BC=0 pop ix ;Save DE (stacked above it) pop af ;Original ROM checksum push ix ;Put DE back cp d ;Match? jr z,ms6a in0 a,(scr) res 3,a ;No: we must have the original ROM out0 (scr),a ms6a: pop de ;Return RAM bounds in DE ms6: ex af,af' ;Get the original BBR out0 (bbr),a ;Be sure we're in the original stack! ret memrsze equ $-memrtn ;Length to move into RAM .dephase ;Normal addressing, now end  push ix ;Put DE back cp d ;Match? jr z,ms6a in0 a,(scr) 76 halt ;No RAM in the system! 002B' 7A mx3: ld a,d 002C' A7 and a ;Is D valid 002D' 20 01 jr nz,mx4 002F' 7B ld a,e ;Then E is 0030' D6 08 mx4: sub 8 ;Adjust for bank base =8000 + out0 (bbr),a ;Bank: 8000 logical -> 08000/F0000 0035' 08 ex af,af' ;Save BBR for later 0036' 21 8200 ld hl,memrtn ;Clear of the bottom, in new space 0039' F9 ld sp,hl ;Define a stack 003A' EB ex de,hl 003B' 21 00A9' ld hl,xmbase 003E' 01 00B3 ld bc,memrsze MACRO-80 3.44 09-Dec-81 PAGE 1-2 0041' ED B0 Welcome to the D-X Designs P112 8-bit CPU board! David R. Brooks, daveb@iinet.net.au Disk Build: 3 June 1996, and updates If you are reading this, you have got your board running! This file contains general notes on various topics. Copyrights & copylefts ---------------------- The intellectual property in this project falls into 3 groups: 1. The hardware design and the PCB artwork. I retain copyright on these, including commercial rights. 2. Software written by me, and supplied herewith. This is supplied under the terms of the GNU General Public License (see LICENSE.TXT on this disk). Source files so covered are identified by a header block at the start. Minor "include" files have not been marked individually, and follow the source files which include them. 3. Shareware components downloaded from the Net, and included herewith. These components are: 1. CCP+ and DOS+, by C B Falconer, and placed in the public domain. See the file !!READ.ME in the group USER.2 on this disk 2. PPIP by David Jewett 3. UUEN/DECODE by Ross Alford, adapted by me These are included FREE OF CHARGE in this distribution. What does this software do? --------------------------- There's a shareware equivalent of CP/M, with some basic utilities to help get things going. One caution: if you attempt to read from a non-existent file, CP/M will report an error to the program: DOS+ kills you! Specifically, it posts an error message like: DOS+ Error F: No Drive Fn: 15 File: This precludes use of the standard Turbo-Pascal trick of making a test read to see if a file exists. In the present case, I have had to patch this test out of UUENCODE & UUDECODE to make them work with DOS+. If they decode to an existing file, that file will be over- written, WITH NO WARNING! What are the capabilities of this BIOS? --------------------------------------- The present BIOS is very primitive: it supports the console, reader/ punch and printer, as basic devices. Both serial devices are set up as 9600bps, 8 bits, no parity, 1 stop bit. The IOBYTE is not implemented. The parallel port has been tested on a H-P LaserJet 4L. Support is provided for 2 disk drives only, both 3". Either can be redefined as 5", by calling the "overload" BIOS functions. (See the BIOS source code for this). Enhanced ROM and BIOS code (by Hal Bower) is available for download from my Web page. What's on this disk, & where is it? ----------------------------------- To keep things in order, I have filed everything under different DOS+ "users". Think of those users as MS-DOS subdirectories. I have not included source files that are generally available on the Internet: only for code I myself wrote or altered. In general, the code is suitable for processing with M80/L80, and Turbo Pascal. Generally, each "user" repesents a separate project. Each user therefore includes (unless it's a trivial matter) a .SUB file to assemble & link it. The more complex projects also include a README.TXT file. The DOS+ and CCP+ modules are by C B Falconer (see his notices in !!READ.ME and the source files). I have made minor changes to assemble with M80 (documented in the files), but have not changed the "sense" of the code. The disk layout is: User 0, "system" files (accessible from any user): 1. PPIP.COM A shareware replacement for CP/M's PIP 2. UUENCODE.COM and UUDECODE.COM The standard binary/ASCII converters 3. FORMAT.COM Formats 3" and 5" disks for the P112 system 4. USER.COM Change user numbers under DOS+. Same as CP/M (ie "USER n"), but 0 <= n <= 9. 5. RECEIVE.COM Receives and files ASCII text. Enter "RECEIVE ", and enter ESC/CR to quit. Because these are "system" files, they will not show up on a DIR listing. User 0, non-system files (visible on DIR): 1. README.TXT This file 2. HARDWARE.TXT Explanations of how the hardware works, detailed pin-outs of connectors, etc. 3. LICENSE.TXT The GNU General Public License User 1, Miscellaneous utilities: 1. USER.MAC Switch users under DOS+ 2. RECEIVE.PAS Download ASCII files 3. UUENCODE.PAS Binary -> ASCII (modified) 4. UUDECODE.PAS ASCII -> Binary (modified) 5. ROM.PAS In-system ROM reprogrammer 6. ROM.COM Executable of ROM.PAS User 2, DOS+ 1. BIOSHOOK.MAC Define BIOS entry locns. 2. DOS.LIB Standard definitions 3. DOSPLUS.MAC Main code, altered for M80 4. DOSPLUS.HEX Object file 5. Z80.LIB Z80 opcodes as macros 6. DOSPLUS.SUB Batch file to build it 7. !!READ.ME C B Falconer's notices User 3, BIOS 1. ASCII.INC Standard characters 2. BIOS.HEX Object file 3. BIOS.MAC Main source file 4. BIOS.SUB Batch file to build it 5. BIOSTOP.MAC End-of-code markers 6. DISKOPQ.MAC Shortened version of DISKOP (see below) 7. DPARM.INC Define hardware parameters 8. DRVTYPE.INC Define known drive types 9. FDC.INC Disk-controller IO ports 10. LOADBIOS.MAC Utility to "jumpstart" BIOS onto the disk 11. README.TXT Documentation 12. ROMHOOK.INC Defines ROM-resident services 13. Z180.INC Z80182 features User 4, Boot Sector 1. ASCII.INC Standard characters 2. BOOTSEC.HEX Object file 3. BOOTSEC.MAC Source 4. BOOTSEC.SUB Batch file 5. DPARM.INC Hardware parameters 6. DRVTYPE.INC Drive types 7. README.TXT Documentation 8. ROMHOOK.INC ROM services 9. Z180.INC Z80182 features User 5, CCP+ 1. CCPLUS.HEX Object file 2. CCPLUS.MAC Source 3. Z80.LIB Z80 features 4. CCPLUS.SUB Batch file to build it User 6, FORMAT 1. ASCII.INC Standard characters 2. DISKOP.MAC Relocatable of DISKOP (see ROM) 3. DPARM.INC Hardware parameters 4. FORMAT.HEX Object file 5. FORMAT.MAC Source code 6. FORMAT.SUB Batch file 7. Z180.INC Z80182 features 8. FDC.INC Port addresses for SMC chip User 7, ROM Code 1. ASCII.INC Standard characters 2. DEBUG.MAC ROM-resident debugger 3. DISKOP.MAC Diskette subsystem 4. DPARM.INC Hardware parameters 5. DRIVPARM.MAC Standard hardware setups 6. DRVTYPE.INC Standard drive types 7. FDC.INC Port addresses for SMC chip 8. MACROS.INC Macro library 9. MEMSETUP.MAC RAM chip detector 10. ROM.HEX Object file 11. ROM.SUB Batch file 12. ROMHOOK.INC Define ROM services 13. STARTUP.MAC Cold-start functions 14. SYSBOOT.MAC Boot operating system 15. Z180.INC Z80182 features User 8, Odds & Ends 1. RTC.MAC Demonstration of the RTC chip 2. DISKCOPY.MAC Source for a diskette duplicator program 3. DISKCOPY.COM Executable ditto 4. DISKCOMP.MAC Source to check 2 disks are identical 5. DISKCOMP.COM Executable ditto ========================================================== Bootstrapping code into a new system ------------------------------------ Of course, you don't have to: I've done it already. But for those who are interested, here's how it was done. I bootstrapped most of the system using the hex-download feature of the ROM monitor. Having assembled a program to a .HEX file, the "send ASCII" feature of my terminal program will copy that file to the ROM, which "understands" Intel hex. notation, and loads the code in RAM. Normal Debugger functions then run that code. Remember that the full ROM services (including the full version of the diskette driver) are accessible - see ROMHOOK.INC for details. This is how most of the ROM itself was checked out: the debugger was the first piece in, and everything else built on that. Each module was first loaded into RAM and tested there, before being included in the next cut of the ROM. The development ROMs were not programmed on this board: with a suitable programmer already avail- able, I could cut that corner. With the ROM up and running, the kernel of the present FORMAT program was run via the debugger, to build the first formatted disks. The system tracks were written by downloading BIOS into RAM, and entering a short scrap of code: RST 08H ;Call to DISKOP RST 38H ;Break to Debugger With the registers manually set up, executing this will trigger a call to the DISKOP service, which can do anything necessary on the disk drive. In this case, manually writing BIOS, etc. at the proper sectors. The boot-loader and BIOS programs now include short stubs, which assemble the necessary instructions automatically. A debug jump to these stubs will copy the code to the disk. To install DOS+ and CCP+ on a disk, download DOSPLUS.HEX and CCPLUS.HEX into RAM (the debugger will read them directly). They now occupy the correct locations of E000..F600. Now manually set the main registers as follows: A 03 ;"Write" command B 0B ;No. of sectors to write C 00 ;Track no. D 00 ;Drive no. E 02 ;Starting at sector HL E000 ;Start of the code load IX 044F ;Address in ROM of the 3" hardware table PC 8000 ;Point to the RST 08 / RST 38 code and type G . The code stub above will call the disk subsystem, which will write DOS+ and CCP+ in the proper locations on Drive 0. Remember that, for CP/M (and DOS+), unused disk sectors must be filled with E5, not the F6 used by MS-DOS. The FORMAT program supplied does this automatically. At this point, DOS+ should come up. Here I "cheated", by incuding drivers for that old 5", 360kB format. I had an old CP/M system using those disks, and could pull loads of code straight off it. As the system now stands, the key tools are RECEIVE and UUDECODE. RECEIVE will accept and store ASCII text, which of course includes UUENCODEd binaries. The UUDECODE program will restore the binary. A word of warning: MS-DOS records the length of a file, to the last byte, while CP/M only works to the nearest 128 bytes. So don't expect to UUENCODE a file on your PC, download it, decode and re-encode it, and upload it again to the PC, and have the two files compare. Chances are, they will be different lengths. Because RECEIVE has no handshaking ability, you will probably need to set a delay in your sending program at the end of each line, to enable DOS+ to write to the disk. I have found 2 seconds per line reliable (but very slow!). The 3" diskettes are readable (at the BIOS level) on a PC, so the option exists to write a file-transfer utility to use those disks directly (I haven't done so yet). Making new disks ---------------- The FORMAT program will take standard 3" diskettes (whether or not MS-DOS formatted) and re-format them for this system. Once formatted, they are immediately ready for use, with the system tracks installed. The DISKCOPY program requires a formatted target disk (ie it does not format while copying). Although it will copy to a MS-DOS formatted diskette, the result will run very slowly, as the sector interlace will be wrong. BASIC MEMORY LAYOUT ------------------- Here's the memory layout, once DOS+ has loaded: 0000-00FF DOS+ data areas 0100-DFFF User area (TPA) E000-E7FF CCP+ E800-F5FF DOS+ F600-FFFF BIOS ed target disk (ie it does not format while copying). Although it will copy to a MS-DOS formatted diskette, the result will ru page 90 title Disk-Compare Utility: P112 subttl 2-June-1996 DRB ;===============================================================; ; ; ; D I S K - C O M P A R E U T I L I T Y - P 1 1 2 ; ; ; ; ; ;===============================================================; ;=======================================================================; ; ; ; D-X Designs Pty. Ltd. Perth, Western Australia ; ; Project: 112 May, 1996 ; ; ; ; Copyright (C) 1996 David R. Brooks ; ; ; ; This program is free software; you can redistribute it and/or ; ; modify it under the terms of the GNU General Public License ; ; as published by the Free Software Foundation; either version 2 ; ; of the License, or (at your option) any later version. ; ; ; ; This program is distributed in the hope that it will be useful, ; ; but WITHOUT ANY WARRANTY; without even the implied warranty of ; ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ; ; GNU General Public License for more details. ; ; ; ; You should have received a copy of the GNU General Public License ; ; along with this program; if not, write to the Free Software ; ; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ; ; ; ;=======================================================================; .COMMENT $ This program runs under DOS+, but uses ROM functions. It is relocated to high memory to run. $ Z80182 equ $ include Z180.INC include DPARM.INC include ROMHOOK.INC include ASCII.INC aseg org 100h jp begin runat equ 8000h begin: ld hl,reloc ld de,runat ld bc,size ldir ;Copy it up jp start ;Then run it sdv equ 5ch tdv equ 6ch ;Drive nos. from CCP+ exit equ 0 bios equ 1 ;Points to BIOS+3 bdos equ 5 ;------------------------------- reloc equ $ .phase runat ;Moved code testdv: ;Validate drive, passed in A and a scf ret z ;Zero from CCP+ if invalid dec a ;ROM is based-zero ld d,a ;Drive ld c,2 ;Call code ld e,-1 ;get type ld hl,(bios) dec hl dec hl dec hl ;Point at "overload" entry call jphl ret ;Back: CY, E, IX jphl: jp (hl) ;------------------------------- spars: ;Set up parameters for drive function ; Pass drive no. in A (as from CCP+) ld ix,(hwp) ld e,1 ;Start at Sector 1 dec a ;Drives based zero ld d,a ld a,(ctrack) ld c,a ld b,(ix+EOT) ;No. of sectors ret ;------------------------------- dodv: ;Basic drive function push de push af ld a,0c8h out0 (cbar),a ;ROM on pop af rst diskop ;ROM to do it push af ld a,0c0h out0 (cbar),a ;ROM off pop af pop de ret nc ;Back if OK push af push de ld de,fatal ld c,9 call bdos ;Error message pop af ;D => A add a,'A' ld e,a ld c,2 call bdos ld de,fatal3 ld c,9 call bdos pop af ;Get error code add a,'0' ld e,a ld c,2 call bdos ld de,fatal2 jp exms ;Quit fatal: db 'Fatal error on Drive $' fatal2: db ': Exiting',ascicr,ascilf,'$' fatal3: db ': Code $' ;------------------------------- tksize: ;Get track length for this drive push bc ld b,(ix+SECSZE) ;L= 128*2^B inc b ;Scale by 2 ld hl,80H ts1: add hl,hl djnz ts1 ;Secsize*2 (all in H) ld l,(ix+EOT) ;No. of sectors mlt hl ;Track *2 in L (/100) ld h,l ld l,0 ;Track*2 in HL srl h rr l ;Correct length in HL pop bc ret ;------------------------------- tenpwr: dw 10000 dw 1000 dw 100 dw 10 decaout: ;Output A in decimal push hl ld l,a ld h,0 call decout pop hl ret decout: ;Output HL in decimal - direct output push ix push de push bc ld ix,tenpwr ld b,4 dc2: ld e,(ix) inc ix ;Power of 10 in DE ld d,(ix) inc ix ld a,'0'-1 and a ;CY=0 dc1: inc a sbc hl,de ;Trial subtraction jr nc,dc1 add hl,de ;Restore cp '0' ;Kill leading zeros call nz,puta djnz dc2 ld a,l ;Get the last bit add a,'0' call puta pop de pop bc pop ix ret puta: ;Output A to screen push bc push de push hl ld e,a ld c,2 call bdos pop hl pop de pop bc ret ;------------------------------- start: ld sp,lstak ;Stack in safe area ld a,(sdv) ;Source drive ld hl,tdv cp (hl) ;Drives must be different ld de,samedv jr z,fail call testdv ;Check source ld de,baddv jr c,fail ld (hwp),ix ;Save hardware ptr. ld a,(tdv) call testdv ;Check target ld de,baddv jr c,fail push ix pop hl ld bc,(hwp) ;Must be same h'ware type sbc hl,bc ld de,mixed jp z,ok fail: ld c,9 ;Report command errors call bdos ld de,usage exms: ld c,9 ;Final message call bdos ld de,sysbak call dskchg ;Be sure the right disk is in ld c,0 ;Finally, force a recalibrate ld hl,(bios) ; on BIOS dec hl dec hl dec hl ;Point at "overload" entry call jphl jp exit sysbak: db 'Replace system disk if necessary, & hit Return$' usage: db 'Usage: DISKCOMP ',ascicr,ascilf db 'Source & target may not be the same drive,',ascicr,ascilf db ' but must be the same type',ascicr,ascilf,ascicr,ascilf db ' eg DISKCOMP A: B:',ascicr,ascilf,ascicr,ascilf,'$' mixed: db 'Drives must be the same type',ascicr,ascilf,'$' samedv: db 'Cannot compare on same drive',ascicr,ascilf,'$' baddv: db 'Absent or invalid drive spec.',ascicr,ascilf,'$' prompt: db 'Load disks & hit Return$' newline: db ascilf,'$' dskchg: ;Request reload disks ld c,9 call bdos ;Output prompt ld hl,xbuff ld (hl),80 ;Buffer length ex de,hl ld c,0ah call bdos ;Wait for reply ld de,newline ld c,9 call bdos ;Final linefeed ret ok: ld c,0dh ;BDOS: disks are changing! call bdos ld de,prompt ;User: change disks call dskchg ld a,(sdv) call spars ld a,0 ;Using ROM driver call dodv ;Must recalibrate first xor a ;Start at track 0 ld (ctrack),a nrd: ld a,(sdv) call spars ld hl,xbuff ld a,2 call dodv ;Read 1 track from 1st drive ld a,(tdv) call spars ld hl,ybuff ld a,2 call dodv ;Read 1 track from 2nd drive ; jp xx call tksize ;Compare them... push hl pop bc ;Length in BC ld hl,xbuff ld de,ybuff cp1: ld a,(de) inc de cpi jr nz,differs jp pe,cp1 ;Test all ld hl,ctrack inc (hl) ;Next track ld a,(hl) srl a ;Cylinder cp (ix+MAXCYL) jr c,nrd jr z,nrd ;More xx: ld de,suxes jp exms ;Done differs: ;Errors! ld de,flms1 ld c,9 call bdos ;Report it ld a,(ctrack) srl a call decaout ;Cylinder no. ld de,flms2 ld c,9 call bdos ld a,(ctrack) and 1 ;Side call decaout ld de,sx2 jp exms ;Quit suxes: db 'Identical!' sx2: db ascicr,ascilf,'$' ;MUST follow "suxes" flms1: db 'Different data on Cyl. $' flms2: db ' Side $' size equ $-runat hwp: ds 2 ctrack: ds 1 ds 256 ;Stack space lstak equ $ xbuff equ $ ;Track buffer ybuff equ xbuff+(18*512) ;2nd ditto .dephase end  call decaout ld de,sx2 jp exms ;Quit suxes: db 'Identical!' sx2: db ascicr,ascilf,'$' ;MUST follow "suxes" flms1: db 'Different data on Cyl. $' flms2: db ' Side $' size equ $-runat hwp: ds 2 ctrack: ds 1 ds 256 ;Stack space lstak equ M```````````````````````````````````````````````````````````` M```````````````````````````````````````````````````````````` ;```````````````````````````````````` ` end sum -r/size 36591/1617 section (from "begin" to "end") sum -r/size 33998/1152 entire input file `` M```````````````````````````````````````````````````````````` M````````````````````````````````````````````````````````````!Ts7=W*+++*T!W=W:VOF>9:>9: QA_gðFatal error on Drive $: Exiting $1W:\!l(&8"T:l8KTBq  Replace system disk if necessary, & hit Return$Usage: DISKCOPY Source & target may not be the same drive, but must be the same type eg DISKCOPY A: B: $Drives must be the same type $Cannot copy to the same drive $Absent or invalid drive spec. $Load disks & hit Return$ $ !W6P   Ёꁯ2V:\>':l>':l>'!V4~?ݾ 8(GðCompleted! $ $Drives must be the same type $Cannot copy to the same drive $Absent or invalid drive spec. $Load disks & hit Return$ $  regend equ $-1 ;Final byte of saved regs. 0058" spva: ds 2 ;Saved debug-level SP 005A" bpadr: ds 2 ;Breakpoint address 005C" inst: ds 1 ;Instr. replaced by breakpoint 005D" bpcnt: ds 1 ;Count breaks before trapping 005E" nxcnt: ds 1 ;Count NEXT operations before halting 005F" eiadr: ds 2 ;Addr. of extra EI instr. 0061" eiopc: ds 1 ;Opcode replaced by EI instr. 0062" inptr: ds 2 ;Input-buffer ptr. 0064" hexlin: ds 2 !:7=W*+++*:=W:9:>9:` A_ 0_v-Fatal error on Drive $: Exiting $: Code $F!)nle.<'d o&ʹ!^#V#>/ Source & target may not be the same drive, but must be the same type eg DISKCOMP A: B: $Drives must be the same type $Cannot compare on same drive $Absent or invalid drive spec. $Load disks & hit Return$ $ !=6P o  Wq:\>$2<:\!=>$:l!=>$͊!== ˂!<4~?ݾ 8(- :3n04V 7H| fܰO.`8c?s@8_?85 Dw5SFcNf ͤ@"0ͻ k| f05zZ Eq[W+U Ktl8Y ?3o |.n6 n nY/k F~q >HU,lXf`Kl ,lP09f)vnx0 ,f@M0l?C;X;%͸ #ZCٷpX0Y,۬@,6ϯP|>fЀ'6 % H& 3 nZV膉#n ^;JCe0bR3iEpZVYPS#w E!g#?9C@DB3h3h m6l #f  @ xFV걠B+f`!E2͠!9ZUPu BI6KPzAn;M o6L& o2Aql4)d2& @d4'@i$v0 &Ag4ΆSa6A3 o:fSr2MgytMsNFS4a7An3 әpMsNFS4a7Ai: SiyMsNFS4u7Άy@r2N 4Sp: a9A# @c4Lf )N'SIdNFsn: n3H#sMIe6 MSi6GBat&An2@f} 0P<6mf`m`6mn bPp,na `bPp,n bPp,n@27DYM@Y.} Em8ٷp37oHZ 2TVG;JM:ͽ #FuoHyS0 n=YE @C4@AA@HD@ )NeMe6b@o7Do9D#ak9A3ya7b i6LF(: &㡔 4O@ M@l4y@I7 x#i 2Nh@ @ @D4 @t4NbAp rf].3)^c6L'!e0I " &C!@[6Ms aCr=CW>M0M0M0UM0M0M0M0U M0 M0 M0 M0U M0000U0a000100000 0 0 0 ]0 ]0]0T]10000U0 0 0 0U 0 00000@0IA@@-PPQPp@ @ 0 0 001q<# R%]0^``"@PN@O 8T`3@ X@ X@ ApApCS /@PP P PPAS@ @ @ @@@ @A@@*@@@ AA@@@ @ ^A* @@ PP@@ @@lACAQPPPQW@@@Uk`k`k`(QkQP8P8P8P~@HPHP  iP`a```8`qP`K0}P}P P0G`k`k`QpaG@KC PPPPPP`P\pPRPQ*@*@*@`a*`*`*`*`*`*` *` *` *` s` s`s`sc \p3`3`PPP _` _` K` K` K`K`c`0P`c `` aP aP aPTaQWpyPyPyPCQQ``U````U ` ` ` `U ````u`*c  aP)QPPP W *p*p *pU *p p p ppJp KpqppK23Op`5``L wpU gpgpgpgp   *?p ?p?q1DppZP+B?p?p?p?p?p *?p ?p qhppS #pp2p2p @pZ/(p    )w5Wc W/MUTEj"P/ߌ597N8B0 .NG._Ͷ1212!12.^GFFE\ڳ{* ffYi5944,a@º.iHmⅪsL;588 %B͠`Ӆu2sGݳ}þчĐG.\3333ks4 4r7ݼING[T)\ZC5aqTg5A-._uܰR333#.3b.p۶?|)_hsKvEejeee+Cr=C>I0I0I0I0I0I0I0 I0 I0 I0 I0 9090909090*a00010U0000U 0 0 0 ]0 ]0]0]100000 0 0 0 0 000040Dp`A0)0-P+@9Pp[@ 0 0U 0 001q<# R]0^``"@PN@ 8T`3@ P P xApApC /PP P PrPAS@U @ @ @@@@@TA@@@@E@ AA@@@ @ A* { 0U P P@@_@@lACAQC@C@C@Q@@@k`*k`k`(Qk*8P58P8P~"HPHPP iPR`a```8PqP`KԷP}P}P PTPC`k`k`QpaG@KC UPPPP5PP@`PS4`PPQ*@*@*@`Tao`o`o`o`Uo`o` o` o`U o` o` o`o`=sc P3`U3`PPPU _` _` K` K` K`K`Uc`0P`cW `` aP aP aPaQ[pjyPyPyP&QQ`````` ` ` ` ` `````.*c  aPQPPP5p *p*p *p *p p p ppqJ@pzppiqpp2@3%POp```Lwp gpgpgpgpp S/p p pe?q1 p ZP+BUCpCpCpCpUCp Cp Cp qhY p e p2p2p pQO8 e  U    U    U    U Ym@%PimT0uuuuUuu u uU u u uu'`PJ p`ррUррррUр р р рU р рррS8P   U    U U   (4Ӗ90z [ ypM(= rZ984^SUPPLY SYSTEMZtR} ;׫%(4Dw$;0T9-9` +'9VYevԖ888V] 1[Ϧudz쭛85tO1 +5ͨӸ((%HR1F10ȡ10sV\أ}wI%bCuCヽܠӮG}EHŽ;1@15M5q ͑͡22 +937ElI͎\JIIHRݠmѥüwҥIC2Y\LKKJݨݸݠ-a;zd}p]36ZӠWEDDC^= 򷯰s9355OTBAA@]9( •~AZ{ݎZkQ}(<\MAp1zy sF ; E=c&^=$$2 *!vF/NN8o4_8n n n n~~D uZ  [A,G!}̬^=򚙙?ț9308NGAIN OP AMPT@??>8z}G33S u ?HXi_?y  K08ANS㐸REC/ISIOrW`)<1;=G\ !$aaMa%P4 4 U4 4 4 4 4 4 4 PW \ \ \ U\ \ \! @*x x x x pppJppqp p ! !qC#qB#qA#q@#q?J3q>Cr=CW>909090U90909090U )0 )0 )0 )0U )0)0)0)0U)0a000100000 0 0 0 ]0 ]0]0T]10000U0 0 0 0U 0 00000.zPv2@-PPl9Pp@ @U @ 0 00]1q<# R]0^``"@PN@ 8T`3@ @ @ ApApC / @@ @ @@ASU@ @ @ @@@@R@A@@@@@ AA@U@@ @ A/* @@PW P P@}@@@lACAQl@l@l@Q@@@k`k`k`(QkԱ 8P8P8P~@HPHPP J``a``M`85 qP`SK@}P}P PS@G`k`k`IQ`aG@KCW PPPPPPL`P) PPQ*@*@*@R`ao`o`o`Uo`o`o` o`U o` o` o` o`o`sc T) 3`3`PPUP _` _` K` K` K`K`Wc`0P`]c `|`U |` |` |`aQ[pyPyPyPrQQ`````` ` ` ` ` `````*c  |`QPPP5p *p*p *p *p p p ppJnPpzppqpp2nP35 Op```L60wp *gpgpgpgppO /p ?p ?p?q1.pUB0+BW?p?p?pU?p?p ?p ?pe qhJp Vp2p2p ެ " &G^% %&k{Fui"_L. x" 0WBBBU3`3`3` 3`U 3` 3` 3` 3`U3`PPCa_/BBUBBBBU B B B BM B@U M ) Ӏ001 " .xS y] }` U U    M am@8888@O-(CUU5UU0Z&0b0R1P J ͑);`" W,PM]P  S _<@  U U   U    ]B+:#O*3pk kU k k kkUkkkkS = Ap&GARۂAHApף]Pp-R9͚è$4DTdtݔݤݴ$4DTdt$4DTdt,0PPS PPPUPPPP5P P PPU P PPPMP 0PPUP P P PU P PPPUPPpppqppppp p pi@j@\`\`\`\`\`\`\`\` \` \` \` \` \`\`\`da qCb#qBb#qq*q?b#q>b#r==b#>{U0`U````U` ` ` `U ` ```5``| 9pU9p9p9p9pU9p9p9p 9pU 9p 9p 9p 9pE9pEqxxxUxx x xU x x xxxxxc U0ur~0j$P@ pU p p p ppr?%H[`R%&xK>90M8 p̞p侊p#$0YY [~25GnnHPzzzzzzzz z z z z zzzzzzIPƀƀƀƀ΁4%E0FP nnnnnnnnn n n n n nn~?3 .=| | 0Z0Ds 2/ ~@  %%%%%%%% % % % % %%%%%%%% 1-@@ TA@ @ @ @U@@@@5@@ &UU U UUUU N0(U@@@@S UU U 0ððOϰPװװװװװװװװ װ װ װ װ װװP;K[k{ˍۍ +;K[k{˝۝ +;K[k{˭ۭ +;K[k{˽۽ ǿpsLb Gb R^)7߽w\#wF&G  << +pLpT T T F 8zpqq(q@Zxz0&E e 0p˚pR)@n&D:p0 0*2C++(00K(0,0M } .&Bk  @Pj! ! !,P1111(P2A)TPTTTTUTTZ$Prrrrrr r r r r rr*rr/`S @5@U@K#U## #RURRR !U!!!!!rr/? L 0$0}/ TU@\ \ \ \ y\ 60> f$0jy %A@  j \ \ A@60=^7 $0!H H # #? #< q15@ ? ? ?I0XXXXXXXXX X X X X XXXXcMMM RewPU U UxPɰɰ@H `ڰڰ *ڰ ڰ ڰ 3a`@ dCMM$M4MDMTMdMtMMMMMMMMM]]$]4]D]T]d]t]]]]]]]]]mm$m4mDmTmdmtmmmmmmmmm}}$}4}D}T}d}t}}}}}}}ysrRL G$$i]!Q!7TVJ---- - - - - Z--_d40]] r~m5 mm I}}}eU+YYY*YYY}U}}} }U } } } }}}}}  ـJـᝎ. ...TqKSrJR$ j  N0sss 'MЇ ــ*ـــ݁ـUــ ـ ـ ـ ـ ـ.|?Q! J !- U    U  UU U    @! ?P |B} } } } } f h &  O& M   } } } } J} !     T    U    U U    M B08!NTTjTTTg0g0 Aqs0JI000001W 0 0 0 0 00M;qqqqqMoooo o o o o oRRRRRRm0@@@@@@@@ @ @ @ @ @@@@@@@@TTTTTTT T T AQaq--!-1-A-Q-a-q---------==!=1=A=Q=a=q=========MM!M1MAMQMaMqMFU T TTq``q"CMo pTPUU    `EEEE E E E E EEEi*uu+𪁀JAM      J)..>...... . .>  0eGGGGGGGGG G G G G GGGGc#<<dHHHHHHHH H H TwTxxxxU x x x xU xxxxxxxx怸'H  * Z  sJ@H@IXdB#f 8 3m]M=- gK.cUqq^K8%ۊdW3prProgIDqccXdkff$B( Bx\A,@ su?RAPT20M_45BNR\?{n?dQ8??U __U TMQaqѝ!1AQaqѭ!1AQaqѽ!1AQaq͑͡ͱ!1AQaqݑݡݱ!1AQaq!1AQaqW"QLJK gQpx  U   U U       yTUUUUUUUUUU U U U UU UUUUUUUUUMUzUU U U{TUU    U y<]3S <\dS'p@x\x=[pp?P  ʭ=ZS 7ΐ ΐΑi Pސސ:0 H0(eQpYN 0xx [R''''''TCCCCUCCCC C KXS|tttttt$T5p-%H`ͤ`T`ȡWTݠݠ ݠ ݠU ݠ ݠ ݠݠUݠU U U?V%J+FUFFF FU F F F F5F dPv5 vv rPU :::: -p p p Jp z ưư%ưư+-U:::: : : :9 :::::: 033  * AQaq--!-1-A-Q-a-q---------==!=1=A=Q=a=q=========MM!M1MAMQMaMqMMMC0 s TR''%`^$##!VTC=ks$9 <9=j{JUJJ J JU J J JJUJJJ M Т U y=i `  Tuh [𡠘TT\\\\\0`t1T`|||ppppʸpsgrf:SgeUSS  U   U T !O`O` O` O`U O` O` O`O`UO`O`O`O`UO`4-=pi Mi .u u Uu u UOeϐT TUTTTT%T!X@ U    !Z  J  dq=Pc5~0U000050030U30303030U303030 30U 30 30 30 30U30303030U30303030S000U0000U0 0 0 0U 0 000U0000500ƒ3589 [0U @@@@@@ ;@ ;@;@;@D T d t $4DTdt--$-4-D-T-d-t---------==$=4=D=T=d=t======= %E6*I|UU U    UUS}mmmUmmmmUm m m mU m mmmUmmmmUmpppUppppUpp p p p p ` ` ` ``````IC-ADJUSTABLE REGSBAA@920?d)\@<@dE@,o(?{THu?oLM7131BCNi2YHIGH SPEED OP AMPZF;3f8%@ff6)\?M]d0pѐ2NDIFFERENTIAL COMPARATOR\.ͻl@\"FR#АH3۝t1U8Q@ףF\Նd09pAK^R@ SFG!L9񡧭b($AzFף\ѭ09AA1YIAA'7675T1BPOWERO@??>u83`8 CwQuq=&\6365qA思PV.̈{>uff\{3644;)(FffԽD3622^n;(ŢFzd\ͤ3611͆?aMq{SM#-W@ffRuT\2ӌBUHǛffHBβ4d3136/mC]@%Cdlz\瓵29N6~AMOTIONRNTROLLfo=u8e{;Z uz"ד182I\[ACURK BACK[DCCB:3&\.@R†;%181^hxsAv/;010U000q0 0 0 0 0 000000000gP]] `iiiiiigP ^P^P^P^P^P^P^P^P^P ^P ^P ^P8CTAVOLTAG( +18VW?ӏ?6\]|p}d815Cb5#3CS812fp2@= 6 q?  ( 8 H X h x  q}'}7}G}W}g}w}}}}}}}vN@bqOSaqMS`', `@@K;@KA;@;@U;@;@(@(@ (@ 4A` ` ` `````Y\@\@\@\@\@\@\@\@ \@ \@ \@ \@ \@\@\@\@*\@qsO]P@ VPPP\P@@@/@@PP[@@?0@ Qΰ0 P `PPPPPPPPZS P4P 4P4Q  DPDP:PP H XP(a`cYN \QZ@@ [8`ʵ`PPPPPP PPPPPPPP P ~QX@PPPPPP$H`PPPPP%P` P P`&`&`&`&`.aW@C`C` C` C` C` C` C`C`C`PPPPPP P P P P PP P P=2V%J@`U``` `U ` ` ` ``_`d ` `` r`` `` Ԙ```` Ԕ` p p p /Wpp qz%p,p,p,p\,p U+``U````Qq```` ` ` ` Tq`````` Upp p pU p p p pU @ @@@@``T0` ` ```R E5m   5P5 555555f UUUUUUUU U U U U UUUUUUg  ppp0'` j 05 g$(8HXhč f:g@h5͐͐*44 4 L4U 4 44< R @|`  U   UMApQQQQQ-4 @ii. uUuuu lPUlPlPlPlP=lSe5PU U&/`X@X@X@X@JX@X@ Ρ@@U@@@ CdP3= =0=@=P=`=p=========MM M0M@MPM`MpMMMMMMMMM]] ]0]@]P]`]p]]]]]]]]]mm m0m@mPm`mpmmmmmmmmm}} }0}@}P}`}p}}}}}}}}B s NJOM>$#I~gver\sG:\EXCELA.EXE5VQ 3InprocHandl1 Ole2.dll3WV rProgID3ebaTR>bX>dy&>T%> S=Z[BC5502NTRANSISTORH>==<7UcRG@@ i & & & & & :hB 400 \U\\\\51'|U||x3ઐqQﳶƝ֝&6FVfvƭ֭&6FVfvƽֽ&6FVfv͖͆ͦͶ&6FVfv݆ݖݦݶ&6FVfv&6FVfv^BMR0@  U    U U    5  0MUMMMMUMMM MU M M M MUMMMMMM0UU U T0U   !!~!t6,@66 6 6 6 6 66666666-Prrrrrrrr r r rCPȠ0 Ɍ0~s& 1IP }P EP77777777P[[*[PPopUpp p pU '''5'''`0r @}P}P}P}P}P }P }P }PMܠܠq9Pؠ*ؠؠؠؠ 1p ұ`P @ @ ؠ ؠ ؠ ؠ `0o 5P? ?RR@j`ؠؠ.v`7n OUO  Ԡؠtt0m @|ءؠؠl M`5PP PU0k)sz ?M ?'d`X` T`U (@ (@ (@(@AOj{TTUT T T TU T TTTTT| L[S 0 U V! '' ' '& ' 'J''&`*+;&`&`&`&`&`&`RIYiy --)-9-I-Y-i-y--------- ==)=9=I=Y=i=y======:stPW0N0}P'$GQTH"6o_N-T`[BODDUDDD n?MPeZ@m @@y;b Re&WЎUyy%T@ U UUUU ~6 ; ;;;;;;\]@PPPPPPPP P P P P PPjPPP]]@< }%QPU   '`@J;;;;;U;;;; ; ;S3{A@J J `o o *ooZ!0pn 5n n y+`~ U~ ~ ~ !z V!V V V V V !QPPPJP7?Z U Щ~ ~ ~ ~ ~ ~ #y00Z00(0(040 jXP XPXP@H0H0H0H0H0T1C#x&@0000 /IP0000777777*7 7 7 1ZЩ!Z Z Z Z ZZ wU40404040S `@ @ @U@@@@U@@ 0 0 0 0 ,RvK r rrr c_@H0H0po@!iii&iB b!B =b# U    U U   U  gggo# Q QTQQQQ !     Q0Q0Q0Q0 Q0 Q0 Q0 Q0 Q0Q0Q0Q0Q0~001~00000000 0 0 0 0 000000Q0Q0Q0A JM1A"""""" " " " " "*"""[AU U ǣ', G` eQVz`   ϬP ~w@! ! Z! ! @@B!> B F# > > > > > > > > > <> V @ U )!> > d!н &TO   U   !       !JS !  y>!" h h  K' \v  K Q[Uj0j0  L1   L3 * * z)F T,@* * * U* * * * U* * * * U * * * * Q11! ! ! U ))FV[   @5@Ǜj z *:JZjz --*-:-J-Z-j-z--------- ==*=:=J=Z=j=z========= J^! I`\B v)I .m4TIt[|@0QQ >B4 9 jQ&r r[P~ c–p JoPoP5oPoPɖpUU U    ?!`?U=@=@=@=@oPoPsQoPoPoPoPoP* `5 ˢpUU @ PPO@ܐܐܐ @@@&@P  PU P=P=P@AO- ----@S ykJ JJS{? ?C????*?=@=@=A=@]=C J JJ@ 6 iV@WBP@@@@ {?A &J ] Mܐp@@ZAPQPS  @ܠܠܠܣ@@@@R@A@ @ @S{@   O@ T_UPPPP-PPTQPPP1A*PP P SM.Hdtčԍ$4DTdtĝԝ$4DTdtĭԭ$4DTdtĽԽs`rq (T2P    M )_P!!U!!!!U!! ! !U ! ! !!U!!!!M!*_PqqUqqqqUqq q qU q q q       iiiiiiiPm'>p@P  &@ m 1.P%   J  hh5hh̖pN UN N N V!+k :us LR^MX q  sssssssss s s ! 5@ 5@  R 7XXXUXXhh]Q1 RCXXdXXXX(P`RaaaaaUaaa aU a a a aUaaaaUaUU U A:JZjz͚͊ͪ *:JZjz݊ݚݪ *:JZjz *:JZjzJa`K?'ECzQ(*(t[qT'O;`JJJa.Z:-pkO9 g k p8gg k k kk7 ' > R t0vt| Go6 =| Z9~` * W5<(`   j߀ ߀ ߀ sq`<uP@yPO4.PQ zI3 QQHjaaa ߲b/2z}vy1 w@@ 0P͐͐ ِ jb/+P@Tu`&&&&U & & &&5&&u`RURRRRUR R R RU R RRRRR@@T3 UM.     &&&& & &&RR q_-)qq5qq+r0U0000U000 0U 0 0 0 0DOd@ll l l l l lllllPypꜰ ,^+,LipհPݰݰݰݰApʍڍ *:JZjzʝڝ *:JZjzʭڭ *:JZjzʽڽKPPiiUiiiiUi i iъ cp $s d_8]8[,n=$zERG9+ wi[K4 lU>(3PesqX@(apf_hd)\@2{X(BB߮GB23ߘBY ף0?2?d>>h33A= @d@,y@{?jow͇'7GWgw݇ݗݧݷ'7GWgw'7GWgwpP*0!@jA:@ @P%$0@@ ֳ@ `wb#SFO PPPPAW`W`W`W` W` W` W` W` cc"3P`"P<"PP! P 3PU 3P 3P 3P3P' 0`SPSPP odP& pPpPpPpPKPKPKPKPKPKPQ m`P i1a0PP% PpPpPpPpPpPpPpPpPpP pP pP JpP tQ`PPMPp```` a+"`:u`*`L7MT6`3P3P3P3PGQ3PqkV`V`pb`b`b`b`b`b`b`b` b` b` ja P` @ @ @````PPP`0appppp p p p p ppppppp@@ɑp p p```````4q(```e 3•pappipipipipipipipip ip ip ip ip ipipipipipipppppppppp p p p p pqb0PT+2W[29Wm`aJS@MM MM M aaS mmmUmmmmUm m m u_I"aaYasaaUaa aaea ΀ jրOPOP۵0 1 H T0/ ///S 0C CCUCCW0@__lsE 0?`&$Ap/D s 0  C _BB7KgA . (( h<< @ QQQT0aaa050072?@}}}}} } } } } }}}}}}::~Ρ> b۠۠۠۠f00}}=aa a 0 J00 H     H< M          9B; laEp B: >9Sk Q@] 8ӰӰ ۳J"L\l|Colrr~~ ~ ~ ~̍܍ ,<L\l|̝ܝ ,<L\l|̭ܭ ,<L\l|x̽ܽ0s^`c0a0o a?y"yWL1*RePFNNNNNN N fNej /U0\z*QAOT3 LP ~*P)0!0T UU }wZaONM M M M MMMMMMJM ~ j~ ~~ *WN)UePQP  4OPOP @SeF F F UF }b!M)U   P         *   !% !^pu f#LPUPPP@U@@@~0j80 > > *H0~~U   uf#K#s!     *  !oq00U0000U0000U00~CRA Q a qzUzzzz*y z ~>& & & ӄ $4DTdt--$-4-D-T-d-t---------==$=4=D=T=d=t========~ԯAPPP>dbEtIx6*GX. @, , ,,,,,eLLLLL L L L LLJL`@ U o@gU U W R_@T@ p p p pU p p p pS)))M)`==U====U== = E?V3 6nUnnnn_7UU U US8ҐҐҐUҐҐҐҐU Ґ Ґ Ґ ҐU ҐҐҐҐUҐU10 0 0 0 0 00[J[[cppUp p p pzz0UUU U UPPPUPPPPPQA Ts J A`@SP(((U((((U((((SPXXXUXXX`_S zzaA@ @@ @ @ @ @ *@@@(U ( ( ( (Dt=MM'M7MGMWMgMwMMMMMME#3CScsÝӝ#3CScsíӭ#3CScsýӽp"slLec>Al-0[Q4w%^**@6{g]" GG$P@[[[[[[[[ [ [ [ [ [[[[[[666666666 ~\mVЪ nj 4Ъjjjjjjjj*j j j ?[4ۇpQY TFPaaaaMazVy yU y y y yUyyyyS{ TPMPUU  U   OZ> ^>P& & U & & & & & & _ZPjR)PkR R R UR R R R UR R R R U R R R R 5R R l U    U   U U    UU5Ъ   iY0S D#0 #0 #0U#0#0#0#05#0#0 DK0U K0 K0K0K0UK0K0K0GGs1{0{0{0{0{0{0p0;0000000 0 0 0 1uaa Ja a a&>+;K[@@R` dtxK[k{ --+-;-K-[-k-{--------- ==+=;=K=[=k={========@= MM+M;MKMUpэq .gdWg.=9{if :*{{3 ?G>OOOOOO O O O JO wie p#P T T pd 4ɀ iрjррр7*ic 37 w@U eJ\&ibU U ʰ ia3|+5``;G"xNЬi`&8+dBRB͐͐͐͐ ͐ ͐ ͐ ͐ ͐͐͐͐͐ Ҕ _+i+ff.Rr:>> >U > > > >U>>>>SUU U U͐͐͐%) 6 6 6 6R6656>>>>>> N ^ n ~ ʍڍ *:JZjzʝڝ *:JZjzʭڭ *:JZjzʽڽ )9s jhGX6>!jrUDr) >)>`e@Z_Pi"p?? `pppp`G`W *W W^_P_P) jp m`WVX]`` Z??U Ϩp ;C&C`OO)O$ͨp``U ` ` ` `U `````6`j `  U   )"`````R5   U  U C CCCJA![P[PU[P@@ @U @ @ Aڈm m m! `     33\pp q~ ) U U  M ]p  ) * ! Ow@80J8081-9H0H0eH0H0p\0ppd0)-4I`}0J`00QL<0 3 0 0U 0 01,50000H0H0H0H0H0H0H0H0*H0 H0 H0 159>=> F V f v &6FVfv--&-6-F-V-f-v---------==&=6=F=V=f=v====P===; p qz`z`z` 2ppqGe\3,y,b &GnzE=Mo`I]]]$]%Meeeeeeeעz ,By ]'@'@'@ '@ '@ '@-v,BxIUII I I I ߁] ] ]]]] <w@=@U==EM*I߁1r#A@U@]]]]]]*]] ] v*E<@DU5 ٟ_U u @ @ << Փt@@@@@ @ J@ @<<<< <9ՑՓs P?T`eeq"Axh@@B`Z ۖ1jp 꽐Փr_`ՠ o`n`n`xxxx x x x *x xx ; 4,Bqׁ@S @ƀƀƀobiX=VVVT U5 5 5 5 55hW$Pe~@=@ V VVRѵU 9`9`9`9`9`ffgXՠ@@@@V*VVVVUV V V @J ᵐ9`U9`9` 9` 9` 9` 9`ffU "n`n` ZVTuU U j Qp9 s 4 fg],$[4ZMOJ4nXB,B`}iS>(P>/ Ole2.dll=3pW`~rProgIDqeh]b@Y@ZR\{A2AdeBpBdppB, `.BH?u?MC68HC705C8CS 2YIC-MCU 8K OTP[NMML?20?33;: " Po$4j>N^ FNSM~`POON@w(33ff1w1F111DG 8-BIT CMOS CPU`LKKJ>\D( #A"-2-B!EG(!2NX-h-zR)\ף!--#0(0--ffAq/=AdU0-=M#0{2*22;[JIIH=9Q8q=_=o=A"A160=:{,4s@'^`*@*@ *A@@ a@ @ @ @epepepepepRU}p}p}pU}p}p}p }p }p }p Az` Tq ѪIIIp\p&P+epep*u@@+T@@@@U@@@@U @ @ @ @U @@@@U@}p}pATIIIIUI I I I I KQp p p q3oPP4ep)̰PPPPPP P P PPP@@@@@@@@@ @ @ @ @ @Qq0p 0p 0p 0ppppoPoPoPoPoP oP oP oP oPoPoPoPaC1U epUa']` ]` ]` ]` ]`]`]`]`j]`]`]`(ʍ```a``` ` ` ` ` ``````PP P PPPa{Tp pppUoPoP oPsS~ UIIIIS2p2pee>q}pQp p pppp|  \Fep p pp.C{ ԰ lqe e e e qJ$ mk7UN JQMZbQFCKO #pXXUXXXXX J܀xST G Lp"ᰩ U 3Pɀvwk@ڀū ր ր ր*րր} `S~@UU   U   {LdPP|XXUXXX XU X X X XXXXAëPPPPPP P P PPPPPXXTh U ^A2w@ XR{4?CC BOSxxxS dPg gggggT@? ]CМU Uށڀڀڀڀڀڀ ڀ ڀ ڀ ڀ ރ!m# jnp!!!! 555 *5 5 5 5ր5րրx}PaUaaaaA1<_~~~~ ~ *~ ~ ~ U 55U555U ʱ *̓UeuōՍ%5EUeuŝ՝%5EUeuŭխ%5EUeuŽսxT|xxxxUxx x xU x x xxuxnsLpfBu<m( d'LABBWNNNUNNNN5N N pv5 v vq257pKr0;5KILUU/@U_ 8U 1 1  K 6IIAZZ" IjjH5%@pDppQ/zAg zza<A дU 5O5 &- ?fA R     kQR  - Ce05 E EpN ~Kr Pc c c c QOw w ts> > > > > > > > c c c c c c c c c *c c !K: : : > A ZN N N .P 0 0 0 0 0 0( LN20 2:0 :0 A6CDI,R0_ J0J0N0N0N1N0N0N0 0 0 0b3:0:0:0 :0je6(F0X? Y 0 0 0< 0A305 0 V tp00A4>Z> >g;@@ lC@@ @ @ @*@*@*@:@:@:@:@:@:@:@:@ :@ :@ :@ :@ :@:@:@:@:@;@@@@@@@@@ @ @ @ @ @@@Ap@A4K @ @* @ @ @ A @)A````|T;@PPPPUPPPPU P P P PU PPPP5PP};@_PU_P_P_P_PU_P_P_P _P _P _P wQ@@ @1@:KOPjPPP:PPPPPPPP P P P P zPQPUPPPPU P P P PU PPPPPPU<`<`<`<`U<`<`<`<`U <` <` <` <`U <`<`<`<`<`<`<`۞ PPPN`*```13OO``'ipp``M` `` `U`````JpJsS s[p``U`` ` `A'k8p 8p 8p½HpT1``` `S 0dpdpdpdpdpdpT=`ppppUppppU p p p pU ppppUpPPPA8p8p Kr`Qij~Y,*_Q^ zm`SF9,vi\OB5(reXK>1$ Xz??du?r@?dQB= ~B \wBK{wqB2jB^͂G@ffw@dK`@? z4@̵\ a? MJE13007"2NTRANSISTOR,POWERTDCCB:20j͂HJw? 5* DISC OFFER BUV46 *2N.`_^^]I?Z͂\6AрAdphu?d802ST2ERP@??>9J\͂"ff;k?423SEMD} ?RA@@?Ia͂ff33pףup/_?035DARLINGTONWBAA]@i!w]G_͂{ GE䤉&1bU 823q=ףu?A/Ga۝J2955. {(a25fn~rTGG TYp{ { { {^V*{{û@vp bºsѽ ùU U  >иѩѩ aJ=÷ UoU#Ɨp@S10qquHpU U @@@0qЛPqUqq q qU q q qqqqE Hp]]J]]yE j000]R]U U qzqӳ" p  J Hp]0U0 0 0 0U 0 000U00UU U ? K 000<S PPQ*Hp AO@ttUO Hp s si A` J%1 s@rqkMP     N;@55555555 5 5 5 5 55555O;@}}}}oSP jT;@  Xe Ag`TЪ                Uddddd3@|AOp5НT-~ cO  Z  ?,pQ["  z  Wi        z A A A A!||b b b M!+ p fp D JK ALl0 P  U      K0SY  AϨր  3 4 05P0 P000Aͫ     i:`K0K04-5-4S@l0l0l0``A)Љ001 U    U | | | | | 5  0U b b b b Ub b b A =Q# #@U@@@@U@@   $O Pe-P@"X@ *  /A3rx@A[k\kA [ [ [_[A}L-Ю@~9ж@@U@@@@U@@ @ @U @ @ @@@A3 {@|EPUPPPPU P P P PU PPPPA@@@@@@ @ @ @@@@@PRPQ@ @ @U @ @ @@9@AсЩ TP@@Q@@@:@S  B P !   92`2`2`:a p p pTkgggggAkkkkkk k k k k C!m` ` ` ` ``````n```` U``` ` ` R` a[[[UssswssA1U>>>>U>>> >U > > > >U>>>>SLUU U U  U   ֡?1 iU 5 U    U   U /? ? ???????gggggggg g g g g ggg{     R б'ST3 Va ,!       |))T`5555UUE ]ܳddUd d d dU d dddxd   +;K[k{ --+-;-K-[-k-{--------- ==+=;=K=[=k={========3ppq ?p:'E?XEc]DS:: :y :20SSSS2ykJJ{{1/ ʔє{Tl`TϠUU U e:5hDDLUeVpm m yyyyy hSs  U  H@H@UH@H@H@HAIzŰ   M   yS۠_zs; ; ; ; ; ҀҀҀҀ|c c c c c c c c c c c c h W; ; ; iII I*  _!  H@ ZH@ H@23Q@00 0 0   j ~|\A0S*r0Sz0z0z0Uz0 z0 z0 1%`0 000000]&ҀҀ_!ҀҀҀ H@ iC`0 0Q@00   <ˀ@H@ M ] m } -=M]m} ----=-M-]-m-}--------- ==-===M=]=m=}=========f nmF/]j+raP?.m|1^O@"}zm`SF9,PP@0 ffAAdHrA\?+>Űu?MSM6389RS2YIC-VOICE DATA REGISTER\FEED;20?iƍ֍JJSM _k{$;Q*(0@~8GSV1K_RECORD ICaLKKJ>$(N*둙2X42BRSA!2NCMOS RTC WIT?H XTAL_QB,*33$GS1K-_>_QPPO@{$ff@+@p2'9EAL TIME CLOCK_HGGF<ɣRC *ϡ٭𪠽b\dH&$)\ *RAQ58332dz2NuZmc= {B+HBYMM p p% p ќpqpUppp`U`````M@M@M@M@M@ M@U````Ia-a S OPOPOP_  U} pppjpp p  j@&&Ё```PPq 5@ 5@ 5@```UkRoa@M@ M@M@UM@M@M@P)A` ` `W|p|p|p|p |p q`R`ў`` qTU ````U```a```c+@q =` =` 5aPPM TQ` ` ` `OPOPOPT@uu}k BW\p\p\p`qp4qppH@eᚒ``PP& h +PP h4ip}6U    U i++U!N X|@5WhhhUhh h hU h h hhUhhhU IPG@ z xsk4?Us];$8@11119pEE x|QQQQQM@PQAxPP PU P P P PPay`y`y`y`y`y` y` y` }c" KP KP KP KP KPKPKPKP4F@ R`TY@Y@Y@QY@@""R&3`2222P MPPPs s s s sssjsss   q`/@# 5  j6T96@!<=p=`2@ @  $!g0 0 0 0 L!]@]@ ]@ ]@ *]@ ]@ ]@eA]@]@]@a`ў`a````22@kkk @ *   WQOPU OPOPOPOP& & &*&&& Aq*PPPoP P C!7:@K0K0K08TEp[0[0[0`s0s0 s0 `@0 0 000000wwwwww ` ` ` SY@Y@Y@Y@Y@ Y@ Y@ *Y@ Y@ p1y`Uy`y`y`y`S'P@@```aWWWWUWW8p I mPUA  %!pp5P/@@  0@P`p-- -0-@-P-`-p---------== =0=@=P=`=p=========MM L lT@  U    Smp---U----SnpMMMUMMMMUM M M MU M MMMUMMMMSopS TЭ USp̀̀̀Ù̀̀̀Ù ̀ ̀ ̀U ̀ ̀̀̀Ù̀̀̀SpU_ b==5==c-pQUQQQQUQQQ QU Q Q Q QUQQQQ5QQd-pv൐A@ŐŐŐBT@ՐՐՐՐUՐՐՐՐU Ր Ր Ր ՐU ՐՐՐՐՐՐՐCT@%%%%U%%%%U % % % %U %1VХΐe@mmmmmmR}CЍI @n K"r7:a4ǠǠǠǠ+-P=nvU111iP      R`R`Ra8+' F E E E EEEEEETy@@@@@ @ @ @ @ @@j@@@@ f` baPP'0 @ P ` p  p p MMMMMMMM]].]>]N]^]n]~]]]]]]]]]mm.m>mNm^mnm~mmmmmmmmm}}.}>}N}^}n}~}}}}}}}W8s(''''''''''|'&&&&%(#####{#""""!_!ڠ#!^UU^A e eU eeee}eU U TW"> U U UM Uj SUj U aaa ".ReйS...U... .U . . . .U....M.9rrUrrrrUrr r rU r r rrUrrrrS9u!qyڠ # !r          > O ǰ [ *[ [ [ [ ڠUqqUqqO1 Ш     T    U  !!       y0 00000j000z00000000%D0D0D0_-mX0X0X0X0ڠrqqqqq~q}Zq|z{UqyqxUqwqv qu ١#/T ed t } W W W!A[ o# +;K[k{ --+-;-K-[-k-{--------- ==+=;=K=[=k={=======1s. s 9 *9 9 9 9999- Je-uu5uu AU Taaaa m m Jm m ́ U U     jQQQQQQQQ Q Q Q Q QQQQQmMX7228KNŕ2NIC-8-BIT DACPDCCB:20?ZQ3BףBd{A,)\ BuS? 6˔$՝[S0zB574cAJ̐{/125oADCQdHA= wAdLA t36AJHԥ/RMS TO DC CONVERTERZ' ﷭ǭסD80?f= fB(EB \,B28F40?00PC12/4MB MEMORY\ONNMu?kGew?$ʗ7L512QC15-15/SM-K CMOS PROMaMLLK>fz|RRף4D DT#E-\2jw)\B= "p+DC;20-20`Ǽ{Z5 P`7OL256 B_B&6iRvM0 0@uƭ^ג_̸{{7CL1 1tɴՄpQJY ݛ7C92YLKKJ6г\j ;;^n~䧲~䴵kݭq=^G1~D08vӤpW)\'3CSxn2!srJ ' Yz J r- -U - - -----TUUUUUUUUUU U U U UU UUUUMUњUU U ԒWUU U TAAAAUAAAAU A A A AU AAAA5AAUU U    USUU   U  5 U    U    U     U    Se e e Ue e e e Ue e e e U e e e e e e e T    U    M   U    U  U  U    S%0%0%0U%0%0%0%0U%0 %0 %0 %0U %0 %0%0%05%0%0m0Um0m0m0m0Um0m0m0 m0U m0 m0 m0 m0Um0m0m0m0S000U0000U0 0 0 0U 0 000000T@@@@ua Jsz(y\N0o2070FD-72WGFFE;cףsf/fA @9MIA15NF@VֽYIHHG<C(AĄ@pMMF010;65 T-651eMuC{@ף@̎MM Q20NCPrP]Ibvff}Aף΄@= N]^] QER|%WXHGGFXw s33yGz]]R2tVP7`/ZFmHB@m#mF?001BXTEa-aY FLASHcǶ`mpmmhBjqmmG{pytm+543nsFҡO}_}542˒r|}r:K  U      U1111U1111U 1 1 1 1U 11111112_UU U UM撀UU U US璀---U----U- - - -U - ------TyyyyUyyyyU y y y yU yyyyyyyTɐɐɐɐUɐɐɐɐU ɐ ɐ ɐ ɐU ɐɐɐɐ5ɐɐꒀUU U    UM뒀aaUaaaaS .&}}}U}}}}S/UU U U0 U U}UU U    UMiiUiiiiUii i iU i i iiUiiiiSUU U TUU    U 5MUMMMMUMMM MU M M M MUMMMMMMUU U USUU U T1111U1111U 1 1 1 1U 1111511}U}}}}U}}} }U } } } }U}}}}Ѝ}ЃS6r CPU[FEcEDpBVB@-{}tAC80C188XL8`!|P8_KJJI=]z̤r#12+8 tAQjvB%Зltb6'416`= RIpף㠒N\vD {IpJ)))))))) ) ) ) ) ))))j)))?Jyyyyyyyy y y y y yyyyjyyy@Jɠɠɠɠɠɠɠɠ ɠ ɠ ɠ ɠ ɠɠɠɠjɠɠɠAJ     jBJiiiiiiii i i i i iiiijiiiCJ jDJ        j   X@Y@MMMMMMMcjnqqqq q q q q qqjqqq^ ^ j^99999999 9 9 9 9 9999^}}}}}}}} } } } } }}}}^ ^     ^MMMMMMMM M M M M MMMMM^ ^ ^!!!!!!!! ! ! ! ! !!j!!!^iiiiiiii i i i i iiiiB,p`)\=2C122YCALIBRATION CHARGEN<;;:6200s7v6R @P`   E EJ%%%%%%%% % % % % %%%%%%%FJuuuuuuuu u u u u uuuuuuuGJ HJ     IJeeeeeeee e e e e eeeeeeeJJ     KJ                   LJU U U U U U U U U U U U U U U U U U U MJ              NJ              OJE0E0E0E0E0E0E0E0 E0 E0 E0 E0 E0E0E0E0E0jE0E0E0PJ0000000M MJ@0 0 0 0 000000@00000000 0 0 0 0 000j000@9@9@9@9@9@9@9@9@ 9@ 9@ 9@ 9@ 9@9@9@9@9@9@@@@@@@@@@ @ @ @ @ @@@@@@@@@@@Ad @(?@\@E5090N T2NIC-ADDRESSABLE RELAY DRIVER]BAA@923aTB= Bd\AףAi]PV81RvPRFSK MODEM)PCE2QW7VdA]YRRQ^]nVSP\TRANSMITTERZ7VcRRA_@d@Bw ׫@HM P44R;`RPROGRAMM%RE[NCPRY7VZRQ?q=7?dKPW?za_GT4558PbRDUAL OP AwMPP\R>`wף@zBu?OSDP706Bd2NRISTOR,MOSFET TO-220U0?gdF`{ @xmm`A2N*as DISC OFFER 707314 at*];::9!rem>}N|5c5}tp^e0?%_M0 0U 0 0 0 0U0000000QT====U====U = = = =U ====U====SR>UU U UMS>UU 倕 V     jjMMMMMMMM M M M M MMMMMMMMij –𪭐 fjŐŐŐŐŐŐŐŐ Ő Ő Ő Ő ŐŐJŐŐ U U}99@s`U.Bff6"b*(fe5539QnRHIGH FREQUW`YdWbibff@D\Tf7q7SS`'PAND HWOLDaXv_ib?6(8H@̍܍ ߱x ޱwv u t sq_= =@IivQQQQQ Q Q Q Q uj}}kj/ 9:}U}}}  )@@ @$(Yp37400DUDDP@XXXX X X Xxxxxx x x x x xx*xxxx_JL܁M ݑ й  ; "R)7A"""K@46666<=CG__\k= @{ {{{{{{222ϓ'S Fд U uGUR@U U UXXthч@<}DD'85UUUU9ii xuuuuuy@ Z2Ъ $sos2 TA)))))))) ) ) ) ) )))))))UAyyyyyyyy y y y y yyyyyyyVA WA     XAiiiiiiii i i i i iiiiiiiYA     ZA              [AY Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y \A              ]A              ^AI0I0I0I0I0I0I0I0 I0 I0 I0 I0 I0I0I0I0I0I0I0_A00000000 0 0 0 0 0000000`A00000000 0 0 0 0 0000000aA9@9@9@9@9@9@9@9@ 9@ 9@ 9@ 9@ 9@9@9@9@9@9@9@bA@@@@@@@@ @ @ @ @ @@@@@@@cA@@@@@@@@ @ @ @ @ @@@@@@QTr)P )P)P)PU)P)P)P)PM)PϊQPQPUQPQPQPQPQP]QVuPuPuPuP uP uP uP uP uPuPuPuPuPuPuPuPuPъPPPPPPPP P P P P PPPPPPPʽPQҎ`L^`ջ%`%`%`%`%`T=`=`=`=`U=`=`=`=`U =` =` =` =`U =`=`=`=`U=`=`=`=`M=`׊``U````U`` ` `U ` ` ``U```````T````U````U ` ` ` `U ````U````M`يEpEpUEpEpEpEpUEpEp Ep EpU Ep Ep EpEpUEpEpEpEpEpEpEpTppppUppppU p p p pU ppppUpppqwBl8QP QP QP QP QP QPQPQPQPQPQPQPQP*uPuPuPQ``a```` ` ` ` ` ```````````````` ` ` ` ` ``T!a````5``ԊUU U UUU%`%`%`%`U%`%`%`%`U%` %` %` %`U %` %`%`5apۊ T SERIAL EEPROM[DCCB:eףKdw33#N\\fM24C02Ny2K-BIȖpB z|B_Bã3g2DDhDU#TRANSCEIVERUR ?A9AL\2CQǤQUADA {q=ʠnCtuX ׷wףy ʠǣ>N@??>8ZEtBd)\XK1608ݳOCTO ISOLATORP^q33GAd#hн601\74BUSTw̠R*600PէMͥdBJM4200D2Y6ANALOGUE MULTIPLIERZ:Ȗczڐבd151[V/F, F/V CONTERYȖor&qxH29EE{01A03CF--SM-1MB 5V MEM.eTSSRA׮GEpxS8SF04015,-24!Ef洺H FX781A5000 GATE FPGAYEDDC1(X :E6MIXER FM IF S?YSTEMU%wGڐHJ\212Ax^VHF /OSCILYv3ѓ둤(TfffN04_LOW POW[qQx6_  U Sd@%%%U%%%%U% % % %U % %%%%%%eT@qqqqUqqqqU q q q qU qqqqUqqqqSf@UU  z    * Q7C256L56K CMOS ~’^LKKJ>g7yl,ISN2\Ñ]qofⓏS10Q#fhff{;I=ɧ128Qz)+#28dB-V!{J]-m-}#$--J-Z--'NO4-\ =Ѹ'= F{˧/ &4Ql1Ap=z===3ND:8-fkEL33= M2(D2KÑ\qlD/\dMtM02&$* OBEθOFFQ00115F1 *PbuiEҍ-=-010V6YS0&Ñ_q ,XBH6]F]VR&T+-0V̞]]T\X'-]]]m j$Ec;mKmGffrmm}mVRNXamjѓq=ڐR{=8 88ĝ8ڐzd;}K}t3n}~z1             T U5gUU U UhTUU    U USiUUUUUUUUUU U U UU U UUUUUUUUMUjUU U U5kUU U UlTQQQQUQQQQU Q Q Q QU QQQQUQQQQSmUU U UMnc93C+(8HXhx,mm@16hVt0bs16}iRU`wpe@HB3}C}Stftj}zzT: X     Y!!!! ! ! ! ! !!!!!!!Z\aaaaaaaa a a a a aaaaaaa[\ీ 0000000r# )599ȊEEEE,BUAL MICROPOWER OP_ AMP[5?3wQ8U`ffRĤr%?'>uU2OP213FP2YY,PRECISIONk-oZs^OB{U`)/\@dY@t ԩ0G0baPT@??>8xwGU`-r0\LOW f֗g4 @]`CuX 177GSԤ0bSM-ULTRAPȗo]seíӤ=0bl {U`q=>@33 A/7FZРIYwXOB(TU`= @\)tϥ1@^0bQUAD´N5p07D_0bOFFSET-D4=; w33S@P7DN0bƙERAT̐^o\5aOBG4(l,ͮ7Cdڠ#1nPW53U4)\= ?CPió22w4\b_ҁ'u݅Њs̓4 ׋7CC5SOB)\gU`(@#tX5ҩ0bóI5cOBp42t㩓H?N3040U0bHALL EFFECT SWITCHYDCCB2G4q=zrI303@a ~H8?O302Xl|pNsv?9 5  UU U    MsUUUUUUUUUU U UU U U UUUUUUU5UUt怩UU U UuTUU U USvQQQUQQQQUQ Q Q QU Q QQQUQQQQMQw急UU  U   U5xUU _ - ! ! U ! ! ! ! ! ! .UE E E E UE E E E Q E ߨV5]OBGH4Q6B3?!LmSwzL#VHڦ,!  ( 8 H Xx01 10~3}3Z|3z0{3Uy3x3Uw3v3U u3 t3 s30q3z=@ =A I@SiRQ@Q@Q@UQ@Q@ Q@ Q@ Q@ Q@ uAjk}@}@kF@@A 9R:)0@@@*@}@}@}@0  @_)@@U@@@@_@@_@@U@@@@}@  P0$(@ 0Pj0P0P0P@DPDPDPPQT PXPXPXPXP XP XP XPWxPxPxPUxPxP xP xPU xP xP xPxPUxPxPxPxP0JPPP P 2QґPP܁PP5PP ݑPP P P0 @@a;A0~` `")P7"`"`"`RP4v@6`6`6`y6`0<)0e=I0W`궀_`_`k`=@` P{` {`{`{`{`{`{`2`2`>2``0O' FP` `U ` ``````GW````a P```` ` ` ` ` `````JXPXPtQhQmP&&pС̝%z4"p0,#(w̬p}!7F3F9IZԲ33}"V649"P9g,~D;9 Q˽۽DڥPOWE+R ]e!1AMICRO\P[_"ͻD 3y͜71^FASTaUd"QD%k7pѾNOISEaZ2܆DR zP`70FY{݋7 B “6P8-b$DҦt`4FZJFETLX2 n3~gHݞD g )|2_7q= hs((21HX~scv>-0          j   )0UU#aa a a a a aaaam&TX` U5'l`S V`5W@UU U P     j`UUUUUUUU T]uuuuuu-nQDCCB:s{uҐ _?`վ$A603AXCURRENT FEEDBACK ;3337!O12E DInhDc"6#-`41o31PA&2Y},n-INPUY^;sf" 0<--404K2C\ÚRhHZ A31t2,QNhpU=e=2v3P1=,A43ŰX-`665024A"DUAL-PWYi,wffDphy=-2604CEBa"UDIOf'r#1D\wMM2%CJT-L*‡MM21112gSG׺Mr# Q”G]W]2107CRG='wR^(d)\C}S}hPAMup}|H9 * MT==U====U== = =U = = ==U====M=U xW UyWрррUррррUр р рUSX>@8F001BX-T1501MBFLASH`ONNMu?sjAdwA LУA"Xͫ)T 12(26FVfv)B4)ѝ񗑙c ^cB q{ ~B>3{135ġ2NMODULE, THYRISTOR BRIDGET<;;:6swff {`R(8ds W񁀳UU~}|z{yxwv u t rsq= =IiQQQQQ Q Q Q Q uj}}k/ 90:V}U}}}  ) $( U0000SDDDХPXXXX X X Xbxxxxx x x x x xxxxxxJU e *jj * U ;ij ")Щ7Ҁ"""4v6666==<74'.=qPף)I--2!2--:%`){17RM-MF51220(3R0K MEMORYVHGGF"a=q==63==1{7Q==2WCMGb)ff1H᝞76MFMF A4D'qCXJIIH3"MMMG`TMG8#q=0wR7M]SA r0XY/&_4JB!=j]F0207(20-70b2 {qCUGFwFE;7q=^PG9R]]QP(VVV&(17pZ],mF010;65d-65RzqCTVlDP;7= |mma0*** OBSOLETE OPRpcC **2N.ba``_"SmmmqphruT< Pw33 zF}V}udrWm lCSV   U  U  U  UUMU}ҀMMUMMMMUMM M MU M M MMUMMMM5MM~ҀUU U UT#UU U T#EEEE5EE aUaaaa-ae-fU .TZ A51hAPERIPHERAL INTERFACEYBAA@9IA |G i]AqRޭ|U82542TIMER/COU(8-1 .PTU M yz UUUDDDI5Q򃌳U񁤳Uȳ}Գ|Vz{UyxUwv Uu t sqss =TiIaQQUQQQ QU Q Q Q ujk :PUЮʅ"S -U,,,M,%UU з$(A @0000T*DDDPtUttt8J4 4 4UU U xxxx  ݔ I ;^ Mw7F""U" F 6666W<=zpW__\kA 222sKM' U UU$$$$$ $ $ $ $ *ppthљ<D\D)'eUUUU9Tii uUuuuuSyU U S2 +ruv<  U  U    S11======= = =KeeLqqqqqqqq q q q q qqqqqqqTEE E E E ]EEEEEEEF FIIIIIIII I I I I IIIIIIfIFЪ     ҡs 7C748EBPNgB8-BIT$#CPU[Fg9#8 0= ?Bdl`')Bs5Q#|R+ OTP]6#Q_ 0* 330-@-C5!4S&"a-u Y6#wq=F 0q=* )\-C52xS&2MCU-u*e#Ѽ {* Q\- =2FCFA~8+=;0'i"B_3 C&@* Ba=q=0R'3t-q$_8ّfhd;zHZM]49H2N}pUPDpRD!pwP\:W9988RbDFPQDLR*R]b]48HS9PU-1Kt! PROMX4VL3\fFP@z$]C55A:bʖ[F#= FPQff&m*m P>c4-2r " NTROLYF1s{FPp@d%@@ms B715trBUS EXTENDERUFEED;ّaޒz Kybmt 910`qrGPIB TALK#L;ISpERW4V#H"A}Q}74r2MULTIPTOCOL dLERY>==<7ّpr0 [ d111111 1 1 1 1 11115     F F jxAAAAAAAA A A A A AAAAAAAAx TG~B`D@@` ׽b(@{AL20L8BgCNSrOCtp5 V (8H8zUt\-k1 Uܡܠܠܠ*UU U , , ,U,,,U@U0000SDDDS hXXEXX򃌳Va񁤳U񀰳U~ȳ}Գ|z{yxwvR t sqss R=ٶIaQUQQQQU Q Q Q Q uk  i:F<" -UT U5 О$( @0000TDDRDPpppХt84 4 T4U U UxxxxЮ LIM й I ; w7TƐ"""U F 666y6<= W__\kA 222sO' U UU     *ppthљ<}D\D-'eUUUU9T:ii UuuuuSyrU U S2 sOv3s j   t) ) )I999IIƐUUUUUUUU U U U U UUUUUUƐR0U T /U    U      099  + ; LT px - # ŠW UUIIIIUIIIIUI I I IU I IIII2O 6 [ [ [ [ [ -qѭ!1AQaqѽ!1AQaq́͑͡ͱ!1AQaq݁ݑݡݱ!1AQaq!1AQaq($r p _Y 2G;$/$#$$ $#E zm`SF9,vi\OB5$  {naTG:- eגwHߐ= Ww{qBYR1645ۅ2NDIODE, SCHOTTKY 16A 45V[DCCB:Ґdהߐ(<\뒏?Ǎ"$S 0F F F V VUWbb bU b b b b3bp Vp.n@PP P‘!ё#--$-4-D-T-d-t---------==$=4=D=T=d=t=========MM$M4MDMTMdMtMMMMMMMMM]]$]4]D]T]d]t]]]]]]]]]mm$m4mDmTmdmtmmmmmmmmm}}$}4}D}T}d}t}}}}}}}{lus p+Bl3rY&&&%(Sj[*\EXCE3S1R R R5RRAbj2\ŀ Ѓ1 wŠN^i0\w/IЬ. L k   ) ) *Xc(0 0 0 0 0=y( oQU00U00HHHHz' L U    -'0* O& 0 U  U00DOOWWWW[[[[[p%9`R UUCj   IC * 2 : :::::B5 P P lc5cc`sUssssUsss {_A ::U:cccU c c ccyc@ѐ ѐQcȓ?  Q`Pr> h@ +HE7I? TrG GGGnr= h@E*d GGlu< @ @z; [@[@@@@ J@ @    :LbߠC k9M@ ccȑȓ8U @ k7Ga[ :3n?vMv@GTWGGGGGG W6?? )ϰϱ!۰5VP߳=MM"M2MBMRMbMrMMMMMMMMM]]"]2]B]R]b]r]]]]]]]]]mm"m2mBmRmbmrmmmmmmmmm}}"}2}B}R}b}r}}}}}}}} sVvhl"    111111 J1 9UU a i ii,y :;ހ_<  U UK?րBڀU  LހUU !!!! !!!A A A A AYYހ怩iiiJ7@ SAꀒ K性U  eU e e e eU eeeeUiiiumII<IH:  e 񹐪# # # # j# # # C C C C C C C C yyy y y y y yyyyjy           &  IWG8 ERѩ000005F4040404040404040 40 40 40 40 40*404040p11S>00EUE EEEE1000v0F00 ŀŀ ɀIF8S000S0 00U0000K00@@5@@ŀ5ŀ ɀ 9@U 9@ 9@ 9@9@U9@9@9@9@M9@e@e@KDހu@u@SEꀁ@@@U@@@@@ A@@@yyD@ @ @ @ @@@ WPPPP(8HXhxȝ؝(8HXhxȭح(8HXhxȽؽ?eL k2f5- zmPE9.$ ;wgWG7'qaQtf\Q=){d\eWwC?d?aףekHZA2Ad#A,݂ A'>bu?ʁPIC16C55XTS9OIK! U      TpU  a|| --,-<-L-\-l-|--------- ==,=<=L=\=l=|========= MM,M20mAq=^AdKA,;A'>u?PIC16C62020SO+-20?/SO2YIܣ㩿cPOON?l\U C4&P8PGwz4)\)\@l'04604DT0i-{\B{9 꺻_d"BBdB( B]˭1JW/JWŰZIHHG0O1Q6SM1Q6SL/L`L` L` L` L` L`a`p0*`0`0`0l1B UB V V 1*Z Z Z 10U0 0 0 0U 00`0U 0 0 0 0U 0000U00001000>1K*CQ?PU?P?P?P?P KP KP i0IA 1ACTPM@M@ @@U@@@@QA@ @ @ @=`@J@P"QPQ\p-PJKPKQT Y@@@U@@ @ uAP P P P P @@@@"P@@HAAPP&`I]/3H: @ AA@ oP oP oP oP SPSPSPSPPsPsPsPsPsP sP sP sPppp p p p p ppppp٠٠```````` ` ` ` ` ``PPPPP`` pG8Sp,` H`H`U. . . . UX0X0X0X0UX0X0t`d`Ud`d`d`d`Ud`d`d` d`U d` d` d` d`Ud`d`d`a=y`>}```J`` a```a0``` 0 0W 000 apap ep F8S:ppppU=p =p =p=pU!p!p!p!pS UpEpEpEpEpU pp p pU p p p pUppipip5ipipp-p0DPppqpppppp*pp qPpUppPP0/0/06I=%Hs=r9vbN:&r^J6"cHandler'Ole2.dll3W0ProgkIDrbTbaTo3{D@P֥p)ff@m`w@O@6O@ף0rSffHuscA T   ,` ,` ,`f!ST04 4 4 4 4 SK. RT"@U U U@U@@@ @U @@@@@@OQ@ R@ %A@`[`0v v v v v v v }}* !/3-+-;-K-[-k-{--------- ==+=;=K=[=k={========= MM+M;MKM[MkM{MMMMMMMMM ]]+];]K][]k]{]]]]]]]]] mm+m;mKm[mkm{mmmmmmmmm }}+};}K}[}k}{}}}}}}}^r4snM/0  Kji' H=11 ?EӹE ETΐQ U y y y y yyyyyyХ *M 5UU U S- )).2y9AKаM MUMMMMSi i i iiiTЅ U    UsйZj {  2ʰ ˘   cx/bSRSS ax/_x/^Ev̰̰ \; *u u RU   =!!!!!! ! ! !!!AAAAAEEEE EEEE6W7 0 0 0-1DUU ۢ[x/Zx/Yx/X4S0 0 0 0 0-0-0-0-0-0*-0-0 1R0U0 0 0 0 Wx/V$ Ͱ0001Ph @ @QTΐ@@@@U@@@@U @ @ @ @U @@@@U@@00QgAHDDDuDHU %젨@&@ O@д@ A,U ,:::U: :::5::a@U@@A `P&6FۢRbrҝ"2BRbr­ҭ"2BRbr½xҽN HXRpI   U   U U    U    SP]]]U]]]]U] ] ] ]U ] ]]]U]]]]M]PUU U UUI      11-20J2YIC-SM-256K MICRO SUPPORT_GFFE;20?iApAd= A,(A'>~sPu?PSD3111 5J-.>NG BRa{gw3E00IgS{#Đ BbНQ8o3C94V2NTWISTED PAIR TRANSCEIVER]BAA@9NeS\[HaG9AQ2AdETHERNETu[DCCB:^SĐp_3AB:\5BR023ġ%ͣNCODER/DUE7TZ[c19 I M7628HP1e8-BIT DACP?[ Đza ׫c{54ݲ12QĐ;a33ͽw5455FPd"׵3ക꽟NQݔ[zXaH ss5dOfS,@@244CMULTIPLYING\\zĐP333)-x226SڛNw)\[Ua'Q,͞2Iܹ([a}G GퟶcS-6a({1012edCOMPENSAmOP AMPYff":W"иLUS16L87NdOCTALpLTHGGF=~N9X?>>=7N\r5a9~=4245=5R ONTROLLERRA@@S?8Waw9z|=ʧ33 eMEMORY I/O, TIMER A@YY5]9[mO33@@M2àHDd_R2"Z6d3z4[P"3ɢMGBME14 6dP[B<9T]E0~R>=4PERIPԠ8i-3!Z@??>BX%[Q\Naף<9-0CQ+NffR8]]0!*K6pFs"mu?ާQS338\c10uBUS SWITCHZ=cmsmm83c3DîaE[XC( GEdXVff6"fsfmm245a|YqQUICKc `JR\}+};}K}bqd}t}%X:_  } UU     WMQQUQQQQU Q Q QQUQQQQ]Q ; ?Q CVU U U5钀U U USꒀU  U   U  PRECISN0_ REFYVa#B @R"\)\؜>EF01Ci^d+10VhWwwQG"'051НԸUP(P"~bu?CV420KPtURRENT LOjoR?ѥ?d^?Xo4558{ܢRDU8P[7[(8HrZh gYuX46WU Rΰΰ ΰ Rΰ ΰWuOV$ P  Q:     *ΰΰgSoUooooUU5%&M O> B TK M ðo oU o o o o{fS. RBjF F FT&VV V V5VVvUvv v vЕ v vъ}[ð  ?> RuQ0 ~# QR777M7!!)!! ! !ѦM Jo oooo,9:UU  =fP "JS& QTЫ! OuMuL/5 5 5 5 5 QQRQ]33 7 7 qKKK} TБ Kð U US:"svA&*  M Q L`%d-5ASdIIIUIIIIUI I IIUIIIISdU U USdU U 4dZ4%% zt1U1111S{IIIUI I I IMI~m m5 mmɒUU U    UMʒU̚JU ) pFET[JIIHu=!j#B̌q=*pR@^pQ?{J#FD10P03LSMn(2@ANSISW0,,# DPAK`3&33ff&p .Q"{Y,Ki+n&-/ WFEED;HQ]#Bp;XpG!t50Z93R5)SQAH.UP g[R)W,=43G11Q2.J=8_#B\2pz ==25>10R=gEFU[6c ׮!wApף==25DVCRSMtMsX[<@K `p9MIM1922B2YEVOLTApԑ`2(D!0C`MM12>1PR1.2U6U[񕁳ZuYX54DU!!!!U---ʱ*--- ްUΰΰ ΰ ΰ ΰWV$ JP  U[[[[U[[[[U[ [ [ [U [ [KKUKKKΰEΰg9999oUѤi% OR  U U++++@T R c9 9 ) j) ) )OS. RF FU FrrrUr V VVUVvvUv v v ve vю[Xjk k kkkkk J R] Q0   ]I# U iuuUuuuycc!S RS !Ѿ U oooMoUU < =n PS "gUU SSU OWMWL/EE E E E EaQJQQ]33 G G qKJKK}U ) ) )M)l lU l l l lUllllUlUslvJE3)7%%IѠѠѠUѠѠ ѠѠѠ;;Ta a a aUaGGdAj]j`- y y y yyyyyyyy}}}}}}}} } } } } }}}}J}!!Sv- M tAAUA A ပ     ő=p1Oq=:Q"!Oi$P45Epp]K P@|!p1M!5$2Y&w3g2{m0w33s0"tt!!FP3 " # TO_-220]f2wףm0!s0HAAO?-"5%T'\Fct "-3D-',3LEa7 =YHGGF<e%DCp[?A?E3 ̬R=FP10;!2u:LOGICr$[ q33pʘ1dm #" A@-0,BE-b#wRpףpwR~")\'HZ$-*C52B=6]Y&#pQpzd"A1MP1A53Bu==RIp33SeB."5Q!yMAf1UVMM_&ךB8p9"QF]VSBSg]w],0b#pq=jp]@]5&c]]kWBwHp0w̧2ffff=$bi2e5m6aJIIH=\q#ffr!pranm~m :"cMU-R_B0pzdjףAm`N1SZrmEm,03` ("9}DKL1N21s}$3950_z!~:i       j======== = = = = ===j===kઉJ{ХU U 5<UU  .%%L)99U 9 9 9 9U 9999599 mUmmmmUmmm mU m m m mUmmmmYmUU U eUU U UAAAAUAAAAU A A A AU AAAAeAAUU U UY٠٠U٠٠٠٠U٠٠ ٠ ٠U ٠ ٠ ٠٠U٠٠٠٠V%%%U%%%%U% % % %U % %%%%%%UqqqqUqqqqU q q q qU qqqqqqUU U UV   U    U U  % __KjKKKRТcg))))oUK%4[Ш O   ++++Tq2@T )   c     S.S RF F FUrrrrХ vvv v v v vJ"["5 U kkUkkU5U Щ R Q0 I# iGuuuuyR! !Ѫ oooo <42 ={ P "OЪ SS */UOMWL/E5 5 5 5 5TaQQQ]33 G RG qKKK} " *cHs ?3''' &P#X4zm`SF9,v 6wgWG7'G=qa! x 0Dl>T%> ^WBq= H zGrAR&oURG30602NDIODE,ULp-FASTTvbYch W1 1 1U 1 MQQ76QQg\ed* €z΀ ƀ @ڀ !F 2кi|th i|{Ъ  6 ˔   czF1b`Id7 7 aF1՗_F1^Gk`\; J  SwС   U   U   UM  U   -  6"QQYQj&|-190U3 3 3 3 3 3 3 >[qZqYqXj40 0 0 0 0-0-0-0-0-0-0-0 T1kkk k k kWqV$ L0*001PX @U @KKKUKKKKUKK K K K KJZjz͚ͪͺ *:JZjzݚݪݺ *:JZjz *:JZjz` נ  j   ;P!!W111U1111ShQQQUQQQQUQ Q Q QU Q Qai@ `#ڀ OP6ـ ـ ـ ـ ــــــ$` f>p   gF999 9 9l@QQQQQQQ Q Q Q Q QQQQQQQd@ J.P U i`` (2   >Qp @ @PPPPDD*DDD>P\U\\\l xxxx x xR>RP pSm=ck& 0ՠU ՠ ՠ ՠ ١Q jp j00     jP@PW]|@>Rjl4@'`'` @eՠUՠՠՠՠUՠՠQ Q np d!@Up@ΰαi>g@QQJQQizzSmRMp5MpMp pUUMR1p p pUpk@k@k@[`@l@eReeeeeU e e e eU eeeeeeed@'pE p&>Rh$0@QP)Sppqk@Uk@k@ k@ k@k@( 8@@@ * `p-- -0-@-P-`-p---------== =0=@=P=`=p=======2#sPv.UTpttUttttUt t t tU ttttU x x x.`RU U U TP UMyUU PQP*PP>PUU U UyA* : J Z j z  kn0U ) )``a@@@/a0@P`pЭ 0@P`pн 0@P`p͐͠Ͱ 0@P`pݐݠݰ 0@P`p 0@P`pdW4   Sv %  ! !f0Uz0z0Mz0bррՁр р р рmmyــp g@*g@g@g@Ap U p p p  U  DQuIP )y ) 1j111y fEMU UU U U U U UU*UUU!   kPp6 @}PU pp p p RÑӐ Ӑ ӐU    kPo#--!-1-A-Q-a-q---------==!=1=A=Q=a=q=========MM!M1MAMQMaMqMMMMMMMMM]]!]1]A]Q]a]q]]]]]]]]]mm!m1mAmQmamqmmmmmmmmm}}!}1}A}Q}a}q}}}}}}}| s̠̠''{'ui&]&H<&{%Dȿ{m_QClH5'x`<T0$  m[I7%g=Y/K!bAW{?d?VBףBdkB33#@Au?SC32YCALIBRATION CHARk/r2U2222U   S]ZZZUZZ Z Z Z Z f $kqq̣Н 0@P`pЭ 0@P`pн 0@P`p̀͐͠ 0@P`p݀ݐݠ 0@P`p 0@P`p \b  z! 5  0%5 % %055!   P P PTaPPU p}p`k@k@k@k@@ j f0 ~y @)^ b!f)IP111 1 1 *1 1 Mș UUu *T i iiuIޡ }* U  P  PȐpААА А А А А ААTБMt`0Txt`,kPw8 e9999TPMMMMSPaaaUaaaaUa a a a a }P 0 F& jGy ݠݠݠݠݠݠݠݠ jݠ ݠ ݠ YP  kPv*fTs00U0000U0000U 0 0 0 0 0: @jjpvva0a0a0А*АА }}}*} } } }kPuuoQ#s waw`w`w`w`w` 0 0 003r)-=M]m}    Ԯp|||T  H!--"-2-B-R-b-r---------=="=2=B=R=b=r=========MM"M2MBMRMbMrMMMMMN^R`` _j0j0r1j0  J !  U@@@@Q90!0  0 03q--!-1-A-Q-a-q---------==!=1=A=Q=a=q=========@s?P'1lG&\PkD8}qe[G3 ~rh\L<, {vZhqg[N@2 ] ׫@ @2@dPG@\AA fq=B RmB2HNB,@u?=PH-ZP"2U MBPHHUHHH HU H H H X P     PQS}< dh &&&&&& & & J&&%!mmUmmm mml|̭ܭ ,<L\l|̽ܽ ,<L\l|͌ͬ͜ͼ ,<L\l|݌ݜݬݼ ,<L\l| ,<L\l|XSp''&&&&&&&&&&YM%"## #"m!{JuX!`!` TpN N NN{ #r4  k $0sss'0,  j-`jp v x ǀǀǀǀǀey 00 Ҷ  J   5   +++!` Sрp=p;PVLʳP1P\NPd!`T pwPDT } }}a rzs'!p5pΐw0`֐ 820?[PpA& wAd& A,59S#-*b""GAz*"0 @7-G#L6601CDP#/C/DP3NIC-IF/AF CIRCUITXHGGFu;!e""Rz* w\*0 --440#0'HIGH LEVEL MIXER[&g""%* @dq=-=274x0"2!CO` OLLED PRE-AMP]:<1* ;R0ffX=F$$5630'300MHZ LOW NOISE 1FEED:!]:$"* ףR0t=F$$490!E@/B5a"MITTERSEDDCu9!Z""33#* wQR0­&M6M86HB86/NIA54PAiBf""ׅL2R0R閃MF$>E43AHB43/FZERO VOLTAGE SWITCH\Fi""\B{0 R6-h<164bQ7MODULAh /DEyTR_&!#{b7PzB!AC]S]612fT1-2'RFAQ&|#wz* (0 = ]F$KRC0$d2NSNUBBER NETWORK,SINGLEXBAA@iBhD3WCs@DC2{0CmG#dKT92B16Eg2N" yRE THYRf"^!iii i i i i iiijiii‪     >IPHERMUZ = ?: TE5189YW b$&-6-F-V ĺ!b-Sd)= W! , P`0V1q "qc3qc38 0000“00000000 0 0 0 0 000000000000000 0 0 0 0 0000000<@<@<@ JL@ L@պX@ֺQn kv@v@00@m@U@@@0 :@@@w@@ @s O@mC A&@@@ @0H@S@@P = 126PUPP P PMPB P2P2PU2P2P2P 2PU 2P 2P 2P BQGP^P ^P ^P ^P ^P^P^P^P^P PPPPPPPP P P P P PPPP*P P P Q Sqc3}< P_ PPPPU````U` ` ` ``aP;`;`;`;` ;`;`;`;`;`Pc`c`c`c`c`c`c` *c` c` ga P`5`` P`U````U ` ` ` ``aSP`q;P`0|0 PM P `PPUPPPPPa``` ` ```;`;`;`;` ;` ;` ;` ;`c` c` c`c`c`c`c`c``lplpjlplp`wPppppʟ```0{ s␩p@TT@pp p p qSPp qTWPp^P^P^P^PLo8---     aaaaaaaa a a a a aaaaa
 =@ iiiiTm;0;0 ;0 ;0U ;0 ;0 ;0;0U;0;0;0;0S=@}}}U}}}}U} } } }U } }}}}}Atףe=MR12DM-1.2V P ISIONp FV>==<7'RFB Bd̟Нu?~P8680BH/B/DGELECTAB DIVID$Rnt ˝ C720AP<&PROTbARRAYU3]䚙6tq=ͨ$mLBC176P BUS s#\JIwIH='Qnd5CV%v1--gAQa q#۳-]$P˽v8z8C #^ )\R^!ͨ-u4068zTRI +i'{15ALS193J _7B2Y"z#]7ڥ)⩀Y"2]$G̘-M&47A3Gợx#SHj}/Ő&6F2J2@Rb%E1J1azdŐQݙ>6E^ľISTORʣWz&HJŒ]6DU PE )]z&vs~v60        =@AAAAAAAA A eW m m mUmmmm}mUU U UMޒUU U UQ@) ) ))))))j@MMMMMMMM M M M M MMMMMMj@J n U   Tj@UA ɐÑM#T24C04B1\5&4K USEEMj Hڒ ?-)-C02AMl=$!2Y2KS,jl-|--&<% 1P'U[#`dC .B?0B-=0%30S1p5?2NTHYRtq0A 1200VZcB L0LR=b=r00X5= 60Yb,(T= Ad\-MS?M2220P6EMATCHEDrt^ ף,㠗zҹM)M221ALANC@_[L 7G]W] PT]&YbBG!33Őz]]2135 S,`AUDIO OP AMPXӝ] mmc13T`SOWiuƢGc\zݐRR@ff+۔1F018T=Bb"VOLTAGE CONTOROLL@J`_)\g(@lmmaPYt}s\CBBA#=3q= 㠚;Ő ד;}K}`7d7Ac-J`LIFIERZ71B U    U   U U    SBUUUUUUUUUU U U UU U UUU5UUBUU U UU   !A A AAAAAAB     jBaaaaaaaa a a a a aaaaaaB B  MCU!OTP`MLLK>w]̈/rL5r/b($wi0$62T10M6HWD[벶 8-BIT_LKcKJ$#/7 =M]B6SeB6/͠{~ $ 2 U1?U??դ??8?2TBUU U TBUU U B<<< L LXYQV vmv|`mU :w ~ Om  HS c 12 j B Ъ22222 2 2 2 J2 BѲG^ ^U ^ ^ ^^^^^E  ІUU U U   ?}< +/    J;;U;; ;;;;;TccccUccc c c g Џ П ʟS; |0   RU  U;;;;U ; ; ; ;Uc c ccUccccSlll5lwЄU { s T J S W^^z^^ s}ov* j怪99999999 9 9 9 9 9qqqq jj T   UMEEUEEEEUEE E EU E E EEUEEEESU õeDa`Q`bGQ0$9040KITUK-/UK2N- STARTER PACK`=WczbW65B#M6\'s+-3\45(ף`b`tbzd@G-W*ˠ&ݫ{(_&WcQ@m`)\Kb{>-W(0c&11p--c-q==&:%1--&lCpB:ߟ"t4V45Qe#1sCMOS CP ^ult2-B-25d egA٢qx} 4b36MFMVMfBdsBp|IC^MMMf@˧;Q٭頌C ]]*]:RGIPpT]0C]ppe}RDb)\7]]HakFawMM]]]mFaM0mJmZmjm`=X֭]mmmm~h]\}?h= #rqn0wRN2@7}VhHqmb죒G}O299999T!!!!U!!!!U ! ! ! !U !!!!M!iiUiiiiUii i iU i i iiiiiT怱UU U M=UU U REEEUEE E EU E E EEEEETUU U U}}}U}}}}U}} } } } }z$@d?]JVD17N0e #2NTRANSISTOR,@FET D-PAK[DCCB:?g`2`@d0( c$5L1A]'E?e`2 S])\ziyAQE]Э12&VEH:] H5EUR :Q@)GU"ɽt333]= 33!0ٽQ3Yף@i3C66B1r`BSERIAL 3&F?%]H?d%h3C56AMWup \& 5EU erpF3[32С/ףt46CY"?51m^%݀!Ċer9[JnSff]ff!/u0#?52`J\̬/К6X56I*# WC/ BaB|8T40ZC(̾e|16 rU6?sbzxW U  AAAAAAAA A A A A AAAAAjAAAuuuuuuuu u u u u uuuuuuuu J_:===5: j% % % %%%%%%MMMMMMY Wmmm m m m STW80 *^<;;:OSh0;in0H]RH75&>TO-3Pⷻw»h0= n0;6N1C00A%Q_`2w( h0G'ף4-6#Q-U,.h0n2C$--60E 2^q 0qU3q3qU3q3qU3q3qդ3q38K 2005000U0000U000 0U 0 0 0 0U00005000U0000U000 0U 0 0 0 0U0000500<@5<@<@ &L@} L@X@Y@Q _v@v@kp"0|m@U@@@0 :@@@w@@ @O@mC LA@"@ @0H@S@@P { 12^PPP P PPB P2P2P2P2P2P 2P 2P 2P 2P RBQGP^P ^P ^PU ^P ^P^P^P^P^P UPPPPUPPPPU P P P PU PPPPUP P P Q Sq3}< P PPPP````` ` ` *``aP;`U;`;`;` ;`U;`;`;`;`SPc`c`c`Uc`c`c`c`U c` c` ga Pj``` P````` ` ` ` *``aSP`;P`0|0 P P `PPPPPJPPa``U` ` ``U`;`;`;`U;` ;` ;` ;`U ;`c` c` c`Uc`c`c`c`Mc``lplplplp`TwPpppp```0{ s p@T@pp *p p qSPp qWPp^P^P^P^P-29U US)))U))))U) ) ) )U ) )))U))))M)}}U}}}}U}} } }U } } }}U}}}}5}}рUррррUррр рU р р р рUрррррррT=@%%%%U%%%%U % % % %U %%%%U%%%%S=@yyyUyyyyUy y y y y ym Rmmmmmm UՐՐՐՐUՐՐՐՐU Ր Ր ]@ʍ @BvAq U   ̄\GNʠ-OP2N8H -a#220YBAA@9c$W Rx2N66׏;E7A2]a$\-1Y?O#ók'kԐY"ۭM1hLF (ѽISOL.aJIIH=gףp5 33ऽ)&N*a`\2 f;f \ݯSV82a&W@??>8§g - = V[ta&d`q= *--9id#Z ,sv4KyUyyyyMy=@%%U%%%%U%% % %U % % %%U%%%%5%%=@yUyyyyUyyy yU y y y yUyyyy5yy=@UU U U5=@UU U    A#PU UUUUUUj@uuuuuuuu u u u u uuuuuuPѐ  !!!!!!!!! ! ! ! !-$ 4 D T d t  ,<L0!q3q'3qJ33q?3rK3UqW3qc3Uqo3q{3UqSqSO8@00U0000U0000U0000U 0 0 0 0U 0000U0008@U8@8@8@8@U8@8@8@8@U 8@ 8@ 8@ 8@U 8@8@8@00000<@<@<@ 4L@ L@ސX@ސyQvC @v@v@@i@@@Upʖ@@@ _:@@M@w@@ @A@mC TA@@@ @ Hj@pppPPS2.P.P.P` ` ``VP*VPVPVPZQVPU FP FP FP FP BQp p p p p pppppPPPPPPPPP P P P P PPPP*P P P Q Sq3}< PU ppppp7a(p(p(p(p(p (p *(p (p(pa[`U[`[`[`[`U K`K`K`K`K`hpahphphphphp*hp hp hp gapUppp`U````` ` a` *``a```` |0 P PbpRp q p```a(p(p(p ` ```K`K`K`K` K` K` K` K`hp hp hphpc`c`c`c`|plplplplp`pppppʻ``` {S sp@pUpp p p q`p qTWPpPPPPA~> N 'H     (p========Paaaapuuuuuuuu u u u u ujuuup WPjppq`ODE SCHOTTKY 30A 35V^HGGF< ) "(8HXdt ~'}ΐw֐ < ސfU}  a  j p"""" a a a a aPprpp # @U @ @ @ @u@@OM @UΐUΐΐΐΐUΐ֐֐֐Sx@ӠӠӠӠӠۡ3- ==-===M=]=m=}========= MM-M=MMM]MmM}MMMMMMMMM ]]-]=]M]]]m]}]]]]]]]]] mm-m=mMm]mmm}mmmmmmmmm }}-}=}M}]}m}}}}}}}}}s sG% s+fu"pZD/kUjT>?()xbr\FyLc6M 17 ! RjA)\@dTN+a+ppAd]A,MA$ @u?HM^a@U@d{>@GQQ8@mSTTA806yD* x~Ӡ ;Lqd VT wDj} }}GpБ   f WХqϝߝ/?O_oϭ߭/?O_oϽ߽/?O_o͏ͯ͟Ϳ/?O_oݏݟݯݿ/?O_o/?O_oJ` F0K.PP 5U555WPj%%% $`5 5 55%pII==,`]]] ] ]]] -P} } j} }}x`` p Ҭ``` ` ` ``p J3P!!U!!! !U ! ! !! ep `^ ^PPnnnR ,7  qpjUjjjjjj j j j jjjjnnnnnnnnn n n n ۑ / !oPU  x   _SPUUB F!B B B iPu up 00ʠʠPWPڠڠڠ U U U jU UU3P 7U " " " " U" " 2!#`P;;T֡֠ ڠ ڠ ڠSp[[[[[ _UJUUuuuuu T` %U   `ϰϰϰ ϰ Zϰ ϰPRW4 %% 5U555UU]]]y] ] ]]R]}}}v3PTy3P;; Tpp Ù̀ WP```` ;K[k{ --+-;-K-[-k-{--------- ==+=;=K=[=k={========= MM+M;MKM[EsHv  *     M (\--U - - - -U ----Q` PA AAq@yyyyyyyyyyyy@ j ˠ p 29P`^`[UP*KڠڠSxSp???M̀3P 㵫IPC; ;SPKK[[[ _̀ ` a! IJ@K Q )R }D}}}_ S  U    # Їಫ"     kkk2kkZU@s!Ѓ            !  R L!*  SP  P0 0 0 0000p%0 %0 %0B%0!#Essђs !WPZ0000U VV U Z0 Z0U Z0 Z0Z0Z0Z0j10000j3 [!Z0Z0JZ0Z01%0%0U%0%0%0%0U%0 %0 %0 %0U%0%0    #1 Ԁ TPI@I@I@I@Sp]@]@]@U]@]@]@]@U]@ ]@ ]@ ]@U ]@ ]@]@]@M]@p@@U@@@@U@@ @ @U @ @ @@U@@Z01\Z0 3" Q Q@!I!1AQaqѝ!1AQaqѭ!1AQaqѽ> 7 EZ7J? 4DTdtbah‹AףhAdGA,{?zҀu?̀IDT7201LA35J2YIC-512X9w Cefff\2ĀffA''  J%q9p2+bbr--"-2-B-R-b-r---------=="=2=B=R=b=r=========MM"M2MBMRMbMrMMMMMMMMM]]"]2]B]R]b]r]]]]]]]]]mm"m2mBmRmbmrmmmmmmmmm}}"}2}B}R}b}r}}}}}}}{sMk       (|)--j---/|0IIIIII I IIII1yyyyyyyy y y y y yyy}3CR|DUU    U 55S  ?U???„) pWW? ' @B B?N N N NxhfJн, <;ss -Ґ̠̠̠̠T{{{ { { { {{J U  (  Jмk; \ < < < U+|,jkZX 5r|sЪh h h h h h h h jh h h w|9 9 !YSs   pppp     Ϊ    i00HW54 \\\T=0L L 6}U0 U0 a0a0999TU YYYY%YSSsi%%*00U   0Jй4 \=0 =0=0 @JL L!v"@ a0 i1O6@6@0 3K{ |p!AFHҷ &6F KKOOIISSQH|%%1%@1euŝ՝%5EUeuŭխ%5EUeuŽսpͻPb  4PFG;%]zBverづG:\EXCELA.EXE5VQ 3InprocHandl1Ole2.dll3WVProgID3ebaTR {d HAA2] dDQ,R@d耞@ף?c33@q=:33#@,IѾ{:;*U***2ss sNNN=bmm} ----=-M-]-m-}--------- ==-===M=]=m=}========= MM-M=MMM]MmM}MMMMMMMMM ]]-]=]M]]]m]}]]]]]]]]] mm-m=mMm]mmm}mmmmmmmmm }}-}=}M}]}m}}}}}}}}}#sA44      ))))) IAMXXU X X XXMXl?iiUiiiQa a aU aaaaUa T UU - -- -y^y*  _PMQ ((M 88#@ W ) ))5)) ee A J  HH@ 78٠ o... . Ö48U   U  U ;TE" " " " U" " 8HHHH ԞR R R Tb b b b Ub b b 둪 J !o  !U !J <Sߒ৐ L R 10DDבk k kkkkkkkK$ ! U    U  100000000 R1Хk k k88@?*** * * * * *T:ssss s sANN N N NNb b b  Q@ Q@ Q@ 'e@e@e@e@( y@y@y@y@y@ Z@@@@ J SSU S S  U    % Ѫ %5EN^ e@ @ |A@FPU FP FP FP FP An~Νޝ.>N^n~έޭ.>N^n~஽ν޽Z%4'6*&u1mUI1|naRD5& |n`RC4ft Ў3PProgIDgbσ?dayA B A@2zjBZq=*?Ā@_̬u?|TePg V@)% $/CCScs--#-3-C-S-c-s---------==#=3=C=S=c=s=========MM#M3MCMSMcMsMMMMMMMMM]]#]3]C]S]c]s]]]]]]]]]mm#m3mCmSmcmsmmmmmmmmm}}#}3}C}S}c}s}}}}}}}zW$sA#  R6:Sj%%%ZLAIIUIIIIUI I IIK .3y yUyyyyS4 5uvԻMMM4U Sûѳ  ΐ %5555 5 5 555Rbf999U9999U9 9 9 95 9 9qSfyyS/ y*L L LM~T e #xGЩ fI )       *" ipp ߡ<6 e 7Џwk5Tٰaaa aU a a@@U@@ @ @ ɜ e#3 s젴 M o S   U   5  5  0U0000U000 0U 0 1U#ꁺ#չ#ꁶ#g1m0m0T }   100 0 0 02yyy G2  e '01M'0U48FVfvƝ֝&6FVfvƭ֭&6FVfvƽֽ&6FVfv͆ͦͶ%RBU S`U    9 9 9 9900 P PPPPlmq q q q q qqqqn jŀŀ ŀ ŀ ŀ ŀ ŀ!J !U5)U))))MEE?'К?̬@пu?_'TIP137n2NTRANSISTOR,DARLINGTONU@??>820_( @z?ďQ(Yi6͓z?l5,ٝQ8G!@d@ 328H R vi1꣗ǭ׭k0IwE q= hg,<12s2yd0b?ף fffQ= Ґô XBAA@:< hs = 7 h= Q#Tͣ127͸ ffhQ122pӽף@%t5 wR µiy݉Ґ?ݳp- 33 { ݣN2TM )\h ף2i1s1bw C h 1q1R. $吢*"H*} q;= ON1R0ksCz^p PI@    *0010Umm m mU m m mmUmmmqUqqqqq} ŀŀŀŀR ) ) ) =)) 0* A16 6 <7Z0 )\| \:ci31CL?POWERPwR A ғd7GBXhK+ ; JA#Xû]Џ• ;E ҸGL -ERN>==?= '䲦=-M-30Q0W: ( p "{H-'"0 -*\K:,nF1+d'51i1=ERR.923'$33]Ld+6 -D "1u=u-) w ==29Q@=-" QqMG!w@t=(=l ;Uh\2nA `K`629k2AM9hpmPnj66ot}hRY^ ]]166\E]RnB5h(!m]}]5N5]33@SfR,l]]14s4m {hG*m:m14Ғ4tbmm |mCf14mmmmCf45] }5ğ¨hq=G}W}14b4]}T }JL WU  -AA A *A A AMI5I I G6MyyU ) 9i ހ*R   U    U       T*U  4ATDCCB23^B)\"lFʪLLȿgmVm!)* 0U I3 muƆ~   ް ް ްް  )*Pn$$$Q4>4ް#e?  *]]]]Wqq }U }}}}M}S S 78 |R L8-  ; ......<3NNN ^^^  nnnnjnnn  ʎ  !   T* -VZ W  Ц'' k3 3333333$ G#UU SWи3 3 3ްް곿?; <  z5U 5 5 55?BQM Q  ] ]9 ]'!qqqq(TM  ,#-2K^% U _ #sLLj$_P/l zm`SF9,vi\OB5(reXK>1$ ֿdAbBGKB A;B26BdpF0Bף"Bu6968942YT`Bff^"?d[$\(C0"(?,% ^---===rMMM M M jMMMAruuuuuuuu u u u u u>ir I/ְ  x U f*" ~ΰ.  ́  #wOи5:]]] ] ] ] Ryy g# sr) qq ְ      j vj   00000000 0 0 1ֲqLFVfvƽֽ&6FVfv͆ͦͶ&6FVfv݆ݦݶ&6FVfv&6FVfvKD@L0EMeuuUM @11U 1 1 1 1U 1111M1aaUaaaaU a a a aUaaaaSU@@@@@ .Ԟ0ɀ ɀɀKـ ! հ@@–0L0     [004041     ڛ 24S40```U` ` ` `M `b@Sc0Uie@j0Uq0@0ܐ@ 0Ԫ0(7/ C +P5K U@=IS0QQQU Q Q Q QU QQQ-ــ 0 ̾@͖0 0ɠɠɠ ɠ ɠɠ( ,zL3:@" M@  N@ O0  Q@**W0666J6>Z0NN-N \@^@b3_򀐐d@rfzg0iR0w@ 5 0U /ԐԐUԐؐؐؐUؐؐؐ ؐe 0ް2UL3L3uL32 %e % )%`IIIII===== = = = = ===MM M JMU0 U U1Y}@* ! M 0 @W ܐ70L3;$4DTdtT ̑Lѧ~0 01 0@ --$-4-D-T-d-t---------==$=4=D=T=d=t=======6 sDv@T FFF9Up pN .P JP V@=ZW``IJ/aWP[P``KsP9и U    MT@ U Q/U ԐԐ TԑԐ ؐ ؐ ؐUؐؐؐJ G(IC-SM-QUAD CMOS UART\HGGF<20?hzA;Ad@A,?Su?MTL16C550ANh2N# WITH _FIFO^-\7w(L?Ez@L\C450q|RFEED;2a7ݍ?\VEKFFNS2Y#W-c7q=@ff?dG?- #c084CNSGS$|BIFET OP AMPYEDDC1[7pd @dp"p}x-)-T$QBAA@9W'---4CCDK4@%9Y6#d \Nj •.=$؈&G2CP4-8`7p?*2k!==0" @(DU+AL$V5[#=q!{n=8Q2m@p@%"Bf=v9Qd w)\j ffLM\M813@=8#w0)\j ףMM@"+PLM7^M` p-@]@Q2P@%:YT<a-f]?<7&Q--3==]#Va=,G= m0mVQ1a|^=tKP33S`G( mZAHd pQgcRDCCB!:7=Mmv\73eq|Mfh==P}`uIbxM$M }L2 #U8 8 8 8`4--%9 9 9 %%+UɁH4U€mSVuuNU^^b j j jj`TU UzzhRАKr   Й]IR,c7705B1Y@"POWER SUPPLY MON_ITOR]lR^R&`8c?OACP"-A|n~bKJWJI>!gTjPwף0`q=R_Đ՝y3‘Q0@%AM!^v2Ęӝj]_L\@Pѱ裭2eQPp`zdR50L05CL_7|VOLTAGE REG+5V[JIIH=2bP(`{tdc497 rJCONVERTERX'vKPH*`ף|͌9 MOT|zWMTROLLERW%?3EP%`= {-SCHEDD]hfdb= pPd?d31CZ|ADJUSTABLE SoHUNTV.Zhfga@ԽP̌ݶд0)wRECISIONX@hfÖyq 1<¨['vfXpQdlGl| Q0eV\hfwffP931AY\'v633pPj\7GW۱^^'vd sMv?5  U  %-U99993&aN 9U9 9 9 9SRQQ[Tmm*  ɀg рـ ـ vF w2* .M  U      B1߭^RC27LmBX@*cWpuQ" ܭI279!Qgp}` ܀`Hsᒚ2771p#pw%0 -2Fc{#8,M-]-m-c#jpZD;  ( 8 HT` p 01 132 @ @ @ '@j'@'@'@ ;@;@;@;@ ;@ ;@ ;@ ;@ j;@;@;@0k@ k@ k@k@:@ @ @@@@@Y@}@ >@ @   UB2]3;@AT 1 0 0 0;@U;@;@;@k@k@{Ak@ k@ k@ k@k@k@ J  5  PtPP|P|PҊ/΀PP 3Rj>P PQf@~B@ڀFڀ55 5 50 xK P eO PPS )` ` `U````QQ ތ01` 9`0  ,w50(@^`^` ^` ^` ^`jv`v`v` v` v`v`u 2` ɜ` `0# sP` `oTހ` @@@U@@@@@ @ A@    pppppppp p p q23333gZpppp`ڀ``` q0Tp p p pS22PPP Gj`P*.۟0pyP0 p p pK7 001'@'@ '@ '@'@ 0Kڀ--- - - - - -------Lڀiii i i ii*  ΀UUL ̈@ŀŀ5ŀŀg0ـUــــUــ ـ ـUــــMـg0U  u pEOA-%E2682IDW^h-"uYHGGF%ӎNUAY?301INEh|u\L= )\t-Q752~#%d8-BIT DACR[X}Р{>֠]Q556d~pTIMERQ^M]m}^ܢhrTL= 'wf y5": +;ࣗZ#Q'y49I>15ADCPW(]p:Q393"MG-#OMPARATOR`q=)j!d-=͡3}$‰(jVtS(<+dм372P(((*€*ӽ݇370tX|Ue¸d̕W ד`ζR33 6G̲ca!wR.-27M~%-|\+ C\{GuT|f- 7L~%^f(8HX^!izp\|Ds00zn'b'V'J'P$$$#?v4 D T d t s=о2kq=RH^33@QMS27C128/20JL-4K#EPROMaONNM?j>ҸUq= 15\`NMMLB6kBB7ͣ=04019-44MBvuhԺQ0y2604`J   0+![/ F`+K`̠N`P'@'@0Q Q Q Q Q Q Q Q Q Q P*PPPeEJ ррUـ ـ ـ ݁  PQԃ` 0q3:0)`MT@ 0 0J0J0 O`0 0 Q4*0*0WS060U606060>1b0b0N0N0 \v0v00c`dr0000 0000 0 0 0000  1O00Bq CqCqC2 @ @ TA@M M UM M M g@Ug@g@g@g@U g@ g@ g@ PU PPPPUP P PQ@ @ @ @@@@@P@PPJ`aj @ @ `@ @n Rq.Cs;@A U   ;@U;@;@;@{@{@{A{@ {@ {@ {@{@{@)\P\P\P\P\PLPLPLPLP LP LP jLP LP LP5PtP|P|P} /30PP p jj P PLQ@~n `pЇ` pW0P P P@`Ͽ `KG E { N PP p p p ppppp00 e 001` `9`` 5 ,: A wO5@@r`r`U^` ^` ^` ^`U``z`z`U z` z`z`p30` ``y `:p# supP` `oS0` @``````` ` TA`Uppppp3qppp p p q)"q[s˪qgsq#q#gkpppp`O0!`!`!` Tqpp p pM p20PPMP G`PƠ@ 00pP  P@p p pw 6p'Fqrf#!6  . \@,2U!#W08 6b @U @ @@@5@@7@`U```` ^0 ^0^0p@ sO0z 0|T@@@Q000@1Pqp ĀĀā`ԀԀԁ#;@@@8@#@#@#@#@#@ 2M I!|P 5b  @@RT0----U6060 b0 n0 n0 n1n0n0eS0aPP yj q qqqq@ @ F@O0a0@@APʱ`ݿ0ᔀ@Ő Ő Ő #: PP 8P@'@0 J00&1b1vPZ0qW0@j& & &O0T6 U `U`` -` -`S j n @@5@0 U@@ @ @ @@p p pŐ Ő ŐŐѓ߫!@ tP p"0ߠߠߠߠߠߠ88 888I$W0@ TPPk@##qR0r@333SO0CC] #W)P@QR +A8PtPtPUtPtPtPiW0 S0 *ı. ԰԰QPPPP@`a0 ܧ\@0Q %0J 0 )a00S+@A԰pUpppp8 aj0`R@bn 0p@. 7@ӡ@U@@@@A,@ P aaeaaaa a a a a aRCn M D0  U    [`0R7p7q```U``` `]}4    % (qqqn0*n0n0n0]n0%n0aeaUPPPPQ/ 00R@PPP QP P P PPPPPP  Q  #2-B-R-b-r---------=="=2=B=R=b=r=======4!sE>;wA8PU8P8P TI) )555= TUTVUUU ]V@i i i REYV}}} } 2 2 *2e]@Uqq y yUyyaaMt```66J66+i ` ! 1 A Q a q  0@P`pЭ 0@P`pн 0@P`p̀͐͠Ͱ 0@P`p݀ݐݠݰ 0@P`p 0@P`p^~#ݐUh0h0U@ @ @)*%Xe`E E E2PT Uip a a%aQpqppp[   Pــ4  pTe`  p 6 6 p((((`<<<<<< < < < < <<<<< 큮 6`ݓݓk8@*@It1  e  ё p e`7i` T=EEEEUp Up2P2P2P2Pipip*ip ip ip 5q@UpppuALN!@ N` #ap` )[ uuu6`#w7pPP PGT` ep xp0000" qy@ aNq` J  !b"w<`S # ##_  3 U U@ U@ U@00#0Sp06 Lp N 5  `6`_37_ Q`u0 U@)p)p)p)p)pP[  J5p9q5p5pU5p5p5p5p5p 1qSu`pphP`T`pPP PK p[ N 6`*(VpHp=pj=pEE ae`*p p p pUp30 30 30U 30 30sPj S0^p  Ѯ Zp--*_[|`ap000 &P^^00 0 0 0 j00=9Vp * љNUC0C0C0S0S1S0S0ـ, Ӥ@ q!p^^ A@ A@ A@ A@ 'ITe`3 3 )piAqp up P }F! P!d  m``^p 0H`#R0!00᪉pp ` ` ` ``p*p p pQ U    U }@}@}@C06`0@ T! % !0jѪY@ Y@|||/0/0/0/0/0/0/0J/0/0 Q/0 /0% /0 e ^ U ^ ^ ^ U}@C0C0 C0 C0C0сـ6`^_0sIv?>U` U吕  * 9ЩA   R ; I 0 Z00U000010      kw}@U }@ }@ }@ }@U}@C0C0 C0E C0 C1S0 S0 S0 ы!u?pUC3844N92NIC-PWM CONTROLLERSBAA@920h{@q@di>@,5ף0@)\O?,<A?AFADVANCED ~L^DCCB:`]eym(SOWER FpP8Z fc1@w{7@33_=BQPz 9Y-=4_Ca]W==N^xMM%:#s=Hx7  5  J57b))EYmZm m \]rMMMMYe>ay>z怪m m m2怍 і ހLbU   MbU U MJUU J V\@??>8E@?2Hf0= {bmoF5404e2NDI@,ST-`OPY 3A 400(6<)\:f2P`e32qz 3A@,z  U! ! ! )!). 9 9 9!  ) ) ) )M^be m m m  !#w  D> GNI ax   €m r  j   J001~""w  #0 #0#0  30"r2?0 j?0EEk^TS1Lbw00 Հe Ձ怏0ހ% !7? . 5 ?0O0000PTJ0000U0000U 0 0 0 0U 0000SQJ$@$@$@U$@$@$@$@$@ $@SfԖP@P@P@hT`@`Aibj>Zp@ p@ pJʗ0 0 *00(^H2W@XJ@S aP@ P@ P@i XAl@l@r怪@ @ @ @RAs@@@U@U S>P P Q0b-P-P~"*[U^#RPRP &^P^P   R59^PPPU P P P QPPPހPPPPQ ,  !P^P^P'r+ ` ` `@@@J@@ 'aa a a 0_TrG` a aU P P@0 QŒ002 r3#0U  RPRPS$€`agr` `@ `@ `@ `@`@l@l@ jl@ l@p@vr````` ppܲP 0 T2 )p )p )p PU;0;0 QRjQ3Qp|@|@M|@qJepepUepepepepUepep ep ep ep ep eq w0 p pp000RpqPP PU PPP ƫ0fD> ! 05 ^!K*€.--U- a a a U a a   0Ca000 [m mJmIIIIUIIe!bNp *l@ a~NpU }!r0P o` o` o`o`o`o`o`o`s` %:%%(8HXdtȫ38 --,-<-L-\%@@@@ Zr mmRmmd%e e e 5l-|!r@ IҀ`a 09P9P9P9S--------=='=7=G=W=g=w=========MM'M7MGMWMgMwMMMMMMMMM]]']7]G]W]g]w]]]]]]]]]mm'm7mGmWmgmwmmmmmmmmm}}'}7}G}W}g}w}}}}}}}vs{ϫë'/L8o DzmrasG:\EXCELA.EXE5pVQ 3InprocHandle2Ole2.dlKl3pWV^ProgID3h42Q=%T4>>d>> >]4l@\"@d>?,a({vHgH{ѐՑ%$^^^^R^f^^ ^Е ^ ^ H<<< <NqɫƝ֝&6FVfvƭ֭&6FVfvƽֽ&6FVfv͆ͦͶ&6FVfv݆ݦݶ&6FVfv&6FVfvp 0''&&:i#""9h>a;4<<<HHTT T 2dd=>tt ttt M+1HHPHUHH H H H H H 70ɀMɀqppUppppUp B     CAAAAIm3+^buffffffff f f f f ffff2~ciҀU U MuUU ⑩F3) 1 F@7577 J@GUGGGOZL@L@T@Vpkkkk@@@@@= = = = = = = TU!-P -P -P -PU-P-P-P5QW9Ϋ39]ͫ3:@@L@g U@  kkkTw@ @@@M@Y`PPUPP K`@d$`p pU` ` ` `U```@`@U`@l@@AJP P QPPAzrpİİVU Ђ"9̫359ū3=+. 3CScs_ mmmpύߍ/?O_oϝߝ/?O_oϭ߭/?O_oϽ߽n"sJ~4.l  ժ)p)p -@5PPL`EER`0Uhhl @ @ @@*@ @@I!]Np % % JG`muuyu@@a@AU U U U @J-P-P5Q-P-P1Q `  0cp=?= @zu?0UPD75P008CUK2NIC-4-BIT CMOS MCU-OTP_JIIH=20?d(F1084""CLOCK GENERATOR/DRIVER_FEED;')\7{pm- 59C1L2-1y0al8259__KJJI}f5ff)->C95$0#e45 &\ 6k='=78C9 ^0*$@ DISC O@ R TMP82?C54P2 $A$@a?>>=}H#ff6(\==CF_7TIMER/COU![==gMwM051P71[=517av==MMAFM=w0?lzwzdM~-70116HM/BU8C8>Db@?G@D'Q)RfG]]RCm8$f-8a16gPU 8MHZ[j[I$Q]=ѳW02"a9c0gADCQ&SQ`byNUlm>F43256BCZ85Lh-`a`KkSRAMbQPPO@G`f33_mme70i[p2Y}MaPOONrg= 33Ǒ)\3}>Kv~ 00C7v9cMX1 Dp-70NS]LKKJRKC8J9JE88U SI1115HHNUU U U UUU  *  d)*l==QQQiiT IcuuU u u}}U }}M y T UVN66AFD4}1ANSIS0,mFET TO-220ZBAA@9!]P u@S!^<<]HFVN4) L2CETS]3fף )\o@{.< N2410MVN17(8HXhxą܍ +;K[k{<=.3 %&UU  U  !(6*yj99 9+yIIII eOnQa\ii w2nyTU U ƤY8%%*%% % " 2 R7nJ J JULLLUL h hJ y ѦᰭѬJ*#w0D GO i e6xin׭౰G GGGGGc-"w    "n2 6ykR5}}My3 䪲7 "' ]]]]]PAAAAAAAA A A A A AAAAaaRaeaaaUaa aU ij p VsDvW?U 777GGGGGGG G G G TEO _U  TP PPPUPhllUllU |*| ||ۡİ԰! ))aam`b=AK30ݓ C"XK22P0POu AbVe1NVpW]UgQ? Bd95J0402MFHYRIK]~`PZ$;2A$sHQ q=W ÏAp$p:u"WD37C65/PL00Z$Ca!r)@ p&]Vc1 P7 ROB>-FYZ 3C93Ba$&lrSCSI BUSz(bv---'JM'51#MA,L' Qp̬?= CvU#10G?C OBSOLETE-D646726>D2N.\[ZZY6`gLJ33\|233=U#08G12NBRIDGE RECTIFI1@1.5A 800VV<;;;:8zr{|2q==46@6MF6 M5^z|2uXJM44@4fMF4Miff k;nR|2ף0M4%2@2MF2Miw\\w+G|2l' ] 41@1&]FpBX~b/]<|2" j]405@P]E50VW>== 4U4444$+ =UU?aaaaaaaa a a a a aaaaa } 7 U;<e UU U U U 7" *M*366M6=FFd.(=__boooojb 2     .' J>4       4  _v@ @ @ @ ."    T0! }       W U [        * 2*R! 66666Ԩ  !&0&0 &0 &0 &0 &0 &0&0CW6 6 6 6 c1F F 4 4 4 J0J0J0 b"UYY]>00=0000000000鴒00u+@ @ P!P" ;m@< @@+%@%@PO _ o  /?O_o--/-?-O-_-o----------==/=?=O=_=o=======x==9_dh~B'E;. $Tp1111U 1 1``}` PUPPPPU P P P P PQPPPPP LLL&@ҀҀҀҀҀJqAM"g@Y YU Y Y YYYYQ@r6`** UPPPPUPP P S Rg2ooooo3U`M`\@ U 1 1 L LU LLLLđpR""""U`***#. *@LLLLLLL RL ̑%@ppMpQPOGk@] `  p & * * * * ****2 4Zr`r`*r`r`r` p ¡%` %` %` %` %`%`  z =Rp gO@  ``@@# +. pDT@888 8U 8 8 8 8U88\N@hhh####UVА+ + + + +3 C ̑ 4@ /p /p /p lq/q/pU/p/p/p/pU8888 `4MDMTMdMtEЍ 0@P`pН 0@P`pЭ 0@P`pнͼ 0s c}0zG kYYD?4B@::R  O j: ::CGj`;;>@\D4OOMOac A;;; R; /!`!`ssqpFU@@@QTpppP`Lg`@;E; )Qw`T!a*p:: : 2: Wc_QPUP R@ A@;"!` !` !` !` J!`!`v`sUs4ccc w wwwjww K p pppss fd`a P@m m m m m m m m m m Rm !ppp4Qp     R!BIP J I q &@Pa !YUYY@ 1` ` ` ` ``r`ak U   |1 J%@#1#0#0U#0#0 K1 j &0z *:JZjz --*-:-J-Z-j-z--------- ==*=:=J=Z=j=z=======6FVfv11| $RttY$rrWF3#+c`< \c`"Rnp*yQ Q QUQQQDS uq qqҊL v 4!yD D DDy΀ꕀ *MMQaD5DD@U    U};?dGGGKSY@PPuPUPg@Q F osʑO"SO OMO 4o U @IQ@ A@@U@5t3U3333U3333ue@1JOO O p@ @g P0@33 3 3 3 3 333; OOO G͠͠͠Q@FFF @PIAAP   e@ e@ e@ e@ je@ e@c9 Q_FE@|QCP RAUPPPIe@ae@cL \ l =MA6 *;DD D DCGTPJZjzʍڍ *:JZjzʝڝ *:JZjzʭڭ *:JZjzʽڽs@*T@N%xBdC,Tp== = ={kb+S @ZZZӅPвpjjj=====MwWUx*jjjjjjjj j j j *j jj@U U )P8 p====== = = = = ===j===>ƈ(3S x5еU    U MUU    U 5% U% % % % U% % % % U % % % % % % -!O'*ssUssssUsss s w P P jPPP 4@    f@        !& bp00 R0 ! y%@D0 D0 D0X0X0X0T`1SIP|0|0|0J00Rkg@0 B B}$pa P00 4P000j000>Ъ00000BB 3'T d t $4DTdt--$-4-D-T-d-t---------==$=4=D=T=d=t=======x==MbZoN%EeDsL; U6@6@ 6@ 6@6@6@T4UbbtJn?:2{S]Tb-ku9 3 KĀk̀Ù̀``S8}- QpkM3QIM7Z AQ 6 :)pĀ ĀĀ n5 _JqB O4 %p U xpUxpBBqB3 BB$  2k6@lp'''''*''3g@KUKKK KU K K K _ ␿1 LRН} U U 0 ĀĀĀ   /M===KKKKlP{@&.lPlPTpQlPlPlPlPUlPlP lP lPU lP lP cs ssssss-U = = =)2⑪ssss s ,8 H QQ;AQanm}͍ݍ -=M]m}͝ݝ -=M]m}ͭݭ -=M]m}HͽݽQPQUQh h hU h h hhhhhsTr8Լ@        W@AAAAAAAA A A A A AAAAAAW@ W@ jW@%%%%%%%% % % -S@cvb\b0@B~`~`E~` awb bU b b b bUbbbbUbb@@@CAT[`Х^6@6@ u  f @22222 2 2 2 2 22222RUe!wЪu u u u u u u 0@?cU kkk * !` 0@> ` j T6@ 6@ 6@~`U~`kkkuu #= hpU hp hphphphqboo o o o o Tou u u u Sxpt0t0W<     ;@13ccc5d00 R`000000*6@ooo(8HXhxͨ͘͸(8HXhxݘݨݸ(8HXhx(8HXhxw(Xp.u@p;G;"`T!#XyV@5@[ tPe2PVP^^Pj*jjjj5@ZNSuPVVVU V V V V ^ ^ ^ ^ ^^^^^~Y _xf0 j P*j~X DePyGMP)RRR*"W5@OV *==5==+@jUjjjjUjj j j3BU i& ǐ5@WT % %%U%%%%UUU SMRTP====U====U = = ==5==PyS jjnQ sPv|P = =jjjP  J  סU OSzP   S Ӫp  U Uǐǐˑǐǐǐ 4`\ \ \&\Ppp5@WN ` ` `U ` `UOK W0n5@J MP*PP ױ`@I Q` fT!l0l0#H R 9P PEo@o@@@ \@5@G ;@_@_@_@rc@ TXQP PPP]SF00 0 0 0pD'@a`@@ @ <@5@E EP   P PjD ;@ 0 bbjC 5T66660c@Yiy --)-9-I-Y-i-y--------- ==)=9=I=Y=i=y=======<sJrqWV S` Ñ &IIIIIIII I I I I IIIIII& ))))))))) ) ) ) ) ))))"`)E PP`pН 0@P`pЭ 0@P`pн 0@P`p̀͐͠ 0@P`p݀ݐݠ 0@P`p 0@P`p \MM"{b1 c: IePu z@G G Gu0WWW W W WWWWWW _tIU ЀЀЀJЀ y ePsQ`R` < ePr/PF UU   U  UU  qW;PאЀЀЀ   Lgp U 耥 3l qpY YYYYYr9puu}k+ y Oj g pUSh @Ji %pܠ`Ӡp0x3h  Ӡx i0%j%%%99ePgTJ JJJJUJ J J JU J JJZӠ Ӡ Ӡ Ӡ ӠӠ%ePOf0U U UEӠӡӠӠӠӠӠT   eT@0J      mpt΍ލ.>N^n~Νޝ.>N^n~έޭ.>N^n~ν޽#s 24 4 |M2CEIzm`SF9,vi\OB5(reXK>1$ {naTG:fYp@2= WeLB̔BT\?Q?dp}? )\O?߈VMu?[pZTX9512NTRANSISTORJ@??>82w0ף7R869k#338ףqV]X857wH㣰 GNV7A3#3= -j -3PU-i4p4vV33z+V2V-TX792A4)LBAA@9'zO!w(VG!=J1030=,202=B=R= 48920s=Ѓ3A!?!aD1= 558C""2BRbrtUtttt5tt L@ePdp@Щ@@@uDAc@@@@@p P@ p@ @@@@@@@ @ @ @ @"P"P"P"P6PePOb6@CPCP CP CP CP e p[P[P[Pp@@pzP{P R`t`P P PUP@@@Pam`C_PPPP@@QQl@l@l@l@l@l@Q`PPPP P P P P PPPPP%b=`=`=`=`Q`Q`Q`Q`Q`~Ya_ w pr`r`r`r`fr`x`W*``aX@PQ=`=`=` N"V!Nb<f-F{; oЪ< < < <TDN NNNЕNXlll|</1?2ЍM 6SP Q*P Q^ీ AЃqAAݬ΀΀Sڀ ڀ jڀ ڀ ڀ6@f@@*P P\`< PPSmP+p~k? @ xaac :Ъ\ \PPPPPPP @@@T@@@@{2@͐͐ ͐ R PPPU @@@o@K 꽀-@222aPBBBBRᑀ RVa6`6`6`U6`6`6`6`U6` @@||Π& Lڠڠ<ϒmaP T@ MP 2 mPTuP#PPUPPP7Π f< DP@R/l| @ @ x?ckPP2PJ 롪++pp>pxŰ<@AA*T@ްްްްUްްް ް@ p p Rp @8CÍӍ#3CScsÝӝ#3CScsíӭ#3CScsýӽ#/ bsHrqV`  Wp-------- - - - - -------Xp}}}}}}}} } } } } }}}ҹtT`UU U  ty`!:QP++++RuP????? l@W W W WWWWWWRk@Syo@Azy     { j< 5@@ U   *P I?`Ѫ* C S 0@P`p݀ݐݠݰ 0@P`p 0@P`p@JZj k0U k0 k0k0k0k0pm` m` Zm` m`Upup!yp@P@@@PPxQqS:QUp@@@@R`@@@@@ J0 J0 J0 J0 J0J0TN1J0J0J0Q5P5P5PypPIPzPQPQPQPQPQPQP QP QP QP QP QPQPQPQPQPQPQP{@PP j@PPtk0k0k0``J``a``U ` ` ` `U ````Q2ypK` ` b$S * 3` 3` 3` 3` @G` T`O`ZZ0 0 10 0 0000j000(p*``a[0`5``'JP` ` ` *cp` ` `Tpa a a a Ua a a a a a````` ` ` ` ` `````z$qE[2+ o* Ep Ep Ep EpRMq6 ]p]p]p]paqx`upjupupuppppp p pMpAp pppppppBpp0p@@AZ6O=Z:,m BAt$eVE04 rA"~p_Nw<-cNbsM06Laff B BQ[@ף@dG@fZoaCd?dAX9t?oC?u?/0781344T00 19w |ňɠżN^n~--.->-N-^-n-~---------==.=>=N=^=n=~=========MM.M>MNM^MnM~MMMMMMMMM]].]>]N]^]n]~]]]]]]]]]mm.m>mNm^mnm~mmmmmmmmm}}.}>}N}^}n}~}}}`}}}}qE֠֠֠ ֠> Ckk ```Fp N x x xxxxx>&S НU UU U U_  U    U    _ *FFԁSVVzrOz_U `5 ` `n> 7)/ 2п  RD+      7 7777(пAFFFF~@!#3Y Y Y Y Y Y u }             ! <>0 . U   U    5]] l'0U 0 0 00U00000.1J0J0J0J0J0 b0b0b0b0b0~0~0~0~0~0~0~0~0 ~0 1 WW/000&i*0ޡ>$ W W W W*WWW10 0 '7GWgw--'-7-G-W-g-w---------=='=7=G=W=g=w=======P==F0p 0p 0pU 0p0p0p0p50p0p/pUpp Dp DpUDpDpDp PU P P PPPPPo@G^M4' {ZkZEk&`O6) }\m\G>\T[`wwwwwޜq ” YW@Uର }]`[a .]+/w-]+ഀ│  uрр ă ߔt]I-p>\N- hUzY " {mpSx> S SG i}}PQБd~x<Нx qЪr h*xU U x 0U` ,00 00000;`L *L L L LxO$@iiy1i R 0U0 0 0 0Х @ы0dd \J" }YH0Y@]@ j @0######## + # # # #####- w$@$@О vp> hD0 > | Kp    U !\s _    _ _ R1fpo M  _ U c k J < |#w! sCrq<P>             ?PYYYYYYYY YG`jHP RUU 0 u]ҿ @y@-†"ɲ@993!3m7P0A7 R~0c3Ta@x33J9p4`5H@- 0Ғ"STY@xxU     k-0 xxxޤp- 080  \ K p05 5  3 p W5 5 E 3r` - 0 x x xx-0gsp 3 PT0@ - 5† 5 R5 ! u-# !J1lllll l3 5 3M QMpJ0 t¯}}[1t 3 p$@p[  ]B xxUxxll110 0 0 0 00003 xx x |  z`0 0009A  ! T]@(@(@(@(@S-<@<@<@0013K  1   AH@@@A   !5 =11T @@)05 t3 zлzp+Ap@aA7`tv@" @U   !Ԁ!@- 0 !#x0#=100x1\`~P~P h` * <pqt!*=15 U5 5 A/ IzgyS(pPPJ0UJ0 0 0} PU P P P PUPPPPP5 Attttt `V` -pԣ}` P H   999 9 9 99R9a0)-uV UV V V V u V uS qa5×V V %PPrPP%aU % %%%% -S:qPPat  <!52AB  % %^k %I-5 12&&XW&}hSBtcF-AB6"h+տw63;  *K0V;ѿ": SgOU  Ѡ Ѡ39 YLPhۀ38 *J+KkS e 3 uo7 L )&6  UbbӀӀJӀv`ۀۀ=߃5$}U}}}}U}}}}U } } } }U }}}))d j4Ъ *432 8TI@ U 00I!T10000U0 0 0 0 0 0I#1 ( ([IС }` }`8 8@@@@ HRT٠ ٠ ٠٠٠30``.@@ R R R RRRR_RR } /``UCR8<88 8U 8R Q% kkkkk٠٠٠٠٠ . zР )L@ A٠٠٠٠- 2ݰݰݰ3= )  \3<  XJsYsÓ; l| yЍ 0@P`pН 0@P`pЭ 0@P`pнຈ00^  s!}dOG}l[:Y(8.ЂW MMuYYYYYYYY Y Y Y Y YYYY T@ 2y0|WMMuJMMMMUMM M OpHH PaHXhx݈ݘݸ(8HXhx(8HXhx@,PPAc1&Q>b+xpy```C* A\0<@T!p pr)t0`C(#@QPP`C'#@#@)e @&0&0@O&qPPA.C% PAC$y`yay`QPPQ71LP@A@@h`ydar# aRPrA`ppMppb"```[P!mQ t&0@S 1~ PbPr`T] wPgW34 5pqp /Sqa```d wPwPpJp p qp p qp/S *wPwPwPQhppQ` /SKp qHA\ #`g pR#04`4``# `4`4`D`gP` vAAKpup /S wPU wP wPwPp]/Sp @  `g pR` ` `p PC J4` 4`ahphp`pPC )a#`#`qd!pppp:p r 4`g/ 0 QD0Ip} r갊ZpZqʹpPg pMPMP0`` UwPwPwPwP p p0qp p p p pppps wPwP wP Q@ $/  +dG iPu$DfMrjW0"V 0_Vzttttttt|Ug@0  ɁvgpT *0&U& ݀ ݀ ݀SpCCC CRWI\ƺ~QCul PCC O%2Уv&N݀]SM C SWL C C^I6w{<H s 88  ##= @ @ @ Z00J___^__ _ _ LQBJJJ Jt~euōՍ%5EUeuŝ՝%5EUeuŭխ%5EUeuŽսsErqČ@     k@555lEjEEEm|`YYYYYYYY Y Y Y Y YYYYYYn|` o|`r@+0 JJB ) `&& 0 3fjPP <@ .& & &efpdddCu xx(ڈ d x,TP c *0 @Kp|`UU   bb JPb/3     #a<@etF'pڈ0_` U<@X ` ʲ d d _ )) *0 0 0l!0]3^ !] PPPPPC`0 0\d Rd )10 0 3[ ! d d d d -1ZbZw0w0k n0n0n0n3Y d d d k k k ă1kkkXU _\ \ Uw0w0w0w0I{1d d Ud d d 1JJ$4DTdẗ͔́ͤʹ$4DTdt݄ݔݤݴ$4DTdt$4DTdtVP ISyP U  i,!`55555555 5 5 5 5 5555j555-!` .!`̀̀̀̀̀̀̀̀ ̀ ̀ ̀ ̀ ̀̀̀̀̀̀̀/!`7@;@/ / / ///R/U    U U  U    5  +OP!Z  PBOn58PĐĐUĐĐĐĐUĐĐ Đ ĐU Đ Đ ĐĐUĐĐĐĐS9P5:P(U((((U((( (U ( ( ( (U2p p p!p p p p p p p w@ *w@ Cm@Ol5>UU U M6UU 頕 '@        *   ]@{ Bk@R 5sPU±oj t*pӰ\ yi p%r2p|wp  *T@ UM( 00U000    #hU   U&&&&UU     J@J@Cg@B@GGGGG -=M]m} ----=-M-]-m-}--------- ==-===M=]=m=}========= Dsg-],_: J%g2?vertG:\EXCELA.EXE5pVQ 3InprocHandl1 Ole2.dll3pWV^ProgID3eTߎCd\@^gQS ?d>$bR?aD_B`E?? d@0 ^ @o$/////p@GGG////TK////.>^nvΝޝ.>N^n~έޭ.>N^n~ν޽.>N^n~͎ͮ͞;.>N^n~ݎݞݮݾ.>N^n~.>N^n~ '!{BC@+?H}H)OgZ0>>->l0oPRU R RRR5RRprUrrr%_~ @P @P ` `UaA8`?0;pQ[lp꼒}HbRZ0̀̀̀̀̀̀*̀̀ ؁ U I` C|Ā>>tPEiPU U U U U UUU){ G G G TDRRRR @ zj `ېېېې ې ې ې ې ېېېېې@@@@@ y0 y3y @@@@  #x$!kmm"Z0y #0 ʁ ]>0TEP EבU U ې@@@@:v1y0 y3u$S;RZ0UU   U  U//31$ ae33B?Pף?2zjBPu?` >2= W>d>'=gPBZX8B  33CScs݃ݓݣݳ#3CScs#3CScs߽d0000 g0 g0 *g0 g0p0W@Op P0#@#@U#@#@#@pqppph0O@5@W@W@W@HV`gA0 Ro7g0Tk1g0g0g0g0USd0@@@U@@@@U@ @ @ @U @ @@@QA`Q`P`P`PU `P `P `P `PU `P`P`P`PU`P`Pe`e`Ue`e`e`e`5e`e`+M aZ` ` PROn58P]P]PU]P]P]P]PU]P]P ]P ]PU ]P ]P ]P]PU]P]P]P]PS9PPPP5PP: PUPPPPUPPP PU P P P PU`L`L`LaL`L`L`L`L`L` L` ) ) d#mq3l5          R 7A#@#@#@U#@#@#@#@U#@ #@ #@ #@ a,0```` ` ` ` ` ``````d0```*``av@+#k 1LQUSs ;p;p;p;p;p;q1A^Cj ¦p`@lp+#i arpupwԺppp # *Tfp pppUppppM0Ǹppppp ppp& O@+TRP *`HHHXXXXll l l l l l3YUU U UUHHHlË"Tm T0U    U MYVVUVVVVUV ll= -qp0U000~h0*ȑhpUhphphpW@5W@p P ` `xpt)Pj   (0J!br)))ÇK p #!  e&0' J' 0n--W 0 00U000g@Mg@pTQTSW 80@̠ ̠)P. 0 *001ud0)U))))U))) )U ) ) ) )U))))Svd0qqqUqqqqUq q q q }ꥰ y o00ʰ 0p -ÂDQEolBHUHHHHH H HG JLPTdllk{ˍۍ +;K[k{˝۝ +;K[k{˭ۭ +;K[k{x˽۽sQrqh  iUUU    !P"@APQ QQQQQQB!Pqqqqy Tp}UU SޢUU U 5ߢUU   pLjLLLp`x@ 3ƫ     !?aL0bd0M`0M0 7 `d`````d3<0    j d0                m % ^ ^ ^ &d0n n        `^3*U    !<0 R ! е 1PTP#0#0#0#0#0#0+1Od0H0H0UH0H0H0H0UH0H0 H0 H0 H0pp &`00 00000J0!0 3W00 0U 0 0 0 1s@1p0 0 0@ 00R01000U00 0 3W 0 0 0008A0300000 0 <0WP v@- v@E WpppЗ RpU`pp{PSwTI0MMMMUMM{PuuUuuquq  J]U q qqq=u mMM -UUU`U`0ճW 001x0aѽًq(" UppUp0((00:80@2Z Up000U00(x0ձճS&   RQw`UU U U100000000 @; ;<; 3PUP v` v` v`ű;GMyyy $@ z!sVrq=R 6!  U  U^ U^ ^ ^ ^ U^ ^ ^ ^ U ^ ^ ^ ^ ^ ] z L!z 40b)5 6 !R A,|`\ku?CP82C542NIC-CMOS TIMER/COUNTERWBAA@923]|B{AdQclq0A5-5UARTSGFFE;d{JBdHc!{37A>%DMA CONTROLLERZDCCB:e@@d̻@dk{OP87N&8-BIT MCU-OTP[FEED 0?p#Au@ G-- 1% 0--$wR. G-- 0%r0=)=?f ݭ HᐾzxcT=u?$M 017P6LOW POWER3r\& #̚ wwG-=7163<@BAUD RATE GENEQ@Oe&E ף (O=~{MP05GPD2YHIGH-sSP [ MPAZC0?c@ ;( p~MM01CBP1PRECISIONHYFiD ;y?M{LC440AJPbVD@D VOLT FBK OP-AMP_&u` $  ׋M]V3gURB100MHuZTV< {ByE]]V28hT/bBDU'AL,VPZ&0SWffrBd0m]4261eaB1NOISEWZg^mnm~m*c51ead-b,yPGAINrOa]&C rB ]]V07hTcrBPROG rBU R!Y\3}C}V]0erS1]"\C eU e e e eUeeeeMe55U5555U55 5 5U 5 5 55555T}}}}U}}}}U } } U MŀŀUŀŀŀŀUŀ ŀ ŀ ŀU ŀ ŀŀŀŀŀŀ\1i;B&f8TH'0J/a 0GGUGGGGMG ϰg#5 #ְ{Юж C 2bTQ еNNd: kJ|.? #U # # ##e#oӲl 3, j, ,,UjO I I3.:U:Vӭ dd^TѨӬ tdd*~~~~JO 7577U]]J CR2 `mz 1111 ^ð-S_k1111 1 ç(n񳻰zU zkkk: cð sL**CS<seDS6.E _: ð9 9 9 99j999䞐]]]]]]]] j] ] q 0E48 U !WUU U "T    U        ": D D %PPBPP::qvƝ֝&6FVfvƭ֭&6FVfvƽֽ&6FVfv͖͆ͦͶ&6FVfv݆ݖݦݶ&6FVfv&6FVfv@@aTG:+qaTD4&xk_RA6'{iWF5'sfYJ6"`_K<-ْrggfu\]^]VY͂P%̓ravrmfwf\Y[Z̅׍Z^_ZX̅lYV̅*\]X\̅ y UX^ZW]T PZV_ʀVX]V[YSƐ}ʐVWYRƐYhX]bsx]Yfw{oQƐ Y^X^{ijPƐ Y][XVYYYO \^X[YY[NV\YYVWMƒY[_VvVVXWVXLƐYZ\FV[X\^HK ZXWVSJ8Y^\gBW[VYI YZ^BVVHƐ uWVsWF^GƐuVZZW^BvF8Xw_\s{XEƐXZkåfDƐYW^Y}X[oo{iw[VoCWWV\^dX]ޠB8V[_}{WV[AV]FZ@ XvdWY^Yl?ƐXpYZY_>F_^1=ڒZY<Ɛ d\[;7](:l\V]$VWZ9X[bsgWV8X[WVW[`f7Ɛ XZmbW\a s6Z^^X[l5VW\l4͢XҠ]Y[YVXXX3[\Y2X[[[W1lXV`hWX_d0"VYWG/XW\Zl].DVLXu]-FV^]x,h#Y]/+`\*FWvvYo[[) Wl4(W_[B^'_X͐[X{&V]WY֐%VXY7V$lW^-V#]Y[o["\iXda!ƐЧ [\XՐ\_^[XWW_ڒWVZ_]X[V\~LZ[jZƐ\\m[mXggWvDX]YWX]#;ƒWXV\XuXXYlaaa~LWdgXLWWZ[\VX] gfdZW_YWmVvbXXo_V\ZWX!{XZ`X^ä!\3 ]2 Zo^V]V ƒV_Y^Xvt XVVYXV *̐ZYI䭠t^l;X )eࢠ\^ZY\ ujLXYYbWVYl`wVVk V[^VW]V]FVH'^]ԏ (Y; ~YY~bC /WYX`sv`lvY eo^YyVZWX djvbe GvX[}Zhmdow \]V Wlbd]Z`b[ZWfVژfq\5S0 U  S)))U))) )M ]MM5MM@aaaa#TPu u u uU uuuuMu$w`UU U i%` pp $0      aaaaa7hpy8$0     9$0     :$0                 ;$0Y Y Y Y Y Y Y i!U} } } } U } } } } U} } } } _  U    U  U     T    U    33GB,A)\@u?&0D8751HA31NIC-8-BIT HMOS CPUQ@??>820?_=1AAd AL%=5<49F102N7]0-2K EPROMUa6hk2{ݲs0= y0ym==48H*A OBSOLETE OFFER UP4 A2N.^]\\[e2Km0ws0Hy01=53<4088cBM815MHZO_>==<7f1\k23CC QtC$GM53paC7B2|A CO-0CE_SSORRFZk8w{y0(FMVD^F6RM216sJPL)\_s0;(4y0{"MVD<3469ADJrT2QUAD DRIVERPBAA@923[k4s2my04zUT0\B5<327128A2U2P4QDCCB:f1kC3vs0)\x1q=]VD<2CYPALC16L825WC'k2OCTAL CY1)`aPOON@f1ak2RpBףHBd6@+$4m!e7C3S441cb-?bYO0NbEPLDWKJWJI=f1dTs02 mmcPhPhOTP `Zfgk2i`o`Bxumm`225Jd52`JcSMMct]lq}C/RxSC5q5DA}Q|HaxHmugw <M&~r%< KNEcg^55U5555U 5 5 5 5U 5555555T6UU U JV݀݀}݀U )   28FP8DACRFEED;!wwi`GEo`$=eT<3AC8222FPrbDUAL,12Q 2Y13]7]k2zR.q"o`Ue8212EHz1S.S7is=4i`\ ! 6%t%0Z::">JJJJ J J J J3n 0Ɋ v v v v vvvvvRvv;!!!!!!))Vנi6ߠߠf      n .'' ' ' ' ' ''''''     cWOЮv./ 1> aB ɰUɰɰɰɰ5ɰɰbZ 5 R MZ Uu[/O-NUB2VV bbpnqvvvvvvvv v v v v vvjvvvr򀦾s ~b j %fjVŰV r + + + + + +++j+++[S#tttеtt ?aL"b*L 7[Щ_[[[[[_3B j *     !%ĠYYY&*iiQ.uuuuu  J =o̠UѪ J B ^bbtŰZ &*CCCCCCCC C jC Cw8{ ST̠ᡵФ  L0 xs=1v'y&s\#d;z̗1j111EEEEEEEE E E E E EEEEEER{UU U 5wU     ǒNNNNNNb(Tnn n nK YV Z UU    Ee p.ݫ% R1f  U!Y^j   n# # # # # # # # j# # #  W W W ~_!/Dp p p      L   J ! U  5 #S 4 U     W W x$0 V10 11Z=0qE0 ګ101010R51j0 j0 j0Uj0j0j0j0Uj0M0M0M01   Q3 F0Ġƀ01(RbbFQ1! S S 1D1FF Q1Q3ק `@ @ H!A1!d1@1@1@ 1@ 1@^ h*5A£^@ ^@Qj@j@ . R@RAR@65@:Tb@ @ @ @U @ @@@@Aư@O%a00U0000U000 0 0 Aߠߠ ߠ@@@*@))-)5))P8PU v@ v@v@v@Uv@v@v@I@IC$)T)$ ) ) )e %4Q)7PPPPJP! P PU PPPPU #nUnnnQ37GWgwǭ׭'7GWgwǽ׽'$\o4s` 9cvZHKЪ)VVVS===j= = = Fiք`]] `-uU5`HKQf€s P@aR`ՀՀՀUՀՀՀ ՀY Հ`@Un?G[N sPp~`[bZbbPÖٚe"1=V=wث]b{ 3rern} 2#M+``Ȫ'ɯ`#3`7 ]Pk@gaO`S`ŐŐk@ѐѐ Zѐ ѐ^dUq\}H4p j p    5LHpM6VsXVZUs os)WYsӥsYӡsVvvY  s 6 Rs^ӡ sjU_ s_5oY6ogWYYYWpoKYgX[\iYWW gYZ]al+[W)>[P YbY[[ d 8[\! '8HSGFFE820s.? r`mb'xN$|R(V,Z0^4 b8f<dravrmfwfrggfu\Z\]X\d%dh \_]VY[1b q]^xѐ \Y[Z¬ o ^_ZX΢YV¢5,q  y UeX^ZW%]ZV_ I V[]8I +VܨZW^Q-a*]y-WZY'-VZ\ dV_;_^ - 8/^_^W|P-2;[sK=1mdvXVVI |@me]XZ{VZIFdjvbgb}X]b]V{b;U~smovo^Xb[YXuvmfmwWW^V`bp;T i~msjbW]bZXX[kr}gio!a7msWad1<}g`oX^gVWV7Psa=Qm}*Sug[pmbeswpf`ufvweK_`e`sT tX.\2`6 d:h>lBpFpUkaxzZs3~k]OXW\^1WWZ__y>LnWV[j6[G2V`WoV][\ӈ Oe\[YYK!`e PЀBWkZ][W\ yeW_YYFOܝ[p94V\\\t#$X:[G?Qc0jX\Sim#oY t "Ti`d]XX\l˦}~dvws;[p%hoo[\\v,djugsZU@Vyh]]^Zf]Y]Gsk-yh\]W7cGM V'PIs "=yhY^\-VWyi[X^4|]V' bn]yiWYn' ]^\I wxjAGݲ]FfG]yh ZA6 I *6@W[~ԽZEZ sxi0Vsݮ[_A60/rH]YV͒ ^X}3&J W\ǫ [A6sf puaM9%qbN:&rcTE''x1Q=)wcO?/o_OF:.q_O?/V ^ VVZWXY[W k}XXj W WX WW VX,W V[VVVX Y[[[e(nH X[̢ː ZW}[ʐ| _\[X X.VVޒ WX_oYZ aYW]\\ 83"Wh /p*^_W\V]>(\3L$X8^()l(W!\(p\&W \=##[*'!$\Y[^W[L$#X*V)V^&Y^Y8PL V_Z\]_o\XXu0>2h0^^V\_[Q3]^_]VYZ[_ f8WZ\Z y9V^Zx0OP\_0 51iD0 9YW!f3Z[1Y^^R=3\]OXYVl0 4h4eJVZt0uJ[V@.GDiY_t0P4XC]P4Z]W.0\Y\0 DCX_\0JWX0H[@01I@@ H5@VtAHp^@@ ZX^\V_ "YYZZY SQX0#WX 2XVY#WW_wZ PYY PX[^#TX_0_TRP?1P5^İWu@vy3SM@ӰWUq0uZZ0_X[_M@XP0ZwXY__EX0X/p2XwZW\s@\PQW[X]]CPh ^`?1WP@[Zax0RbP[YPdTaW;hV`?1iVAdX`0Q3V]^^M@ D`X`jW _0 jakPTtZ_u@{W]2t0 w@WW%B:xWA0 gXqY_1 bx$YU0 ` aW X?g`~ g \_yǷY_Y˨] ]t +vk`SH6$)o^M<+ ;tfXJ<. ugWG7'yiYI9) yiYI9) yiYI9) N{iu[WWo^k7m"]I L`6Z&XQ&0&\"VwZ VY Vh[V0 &[7p0]\[Z;Y &Z&^&]5'\VZVY]VWVY ^ ]q 0Z P9IVX] Z)VV2VI VL`4WP_pà0[ ZWP iW XW V^W^X A\u\`Y ũVW LP  ;XZ V b81b$~# ~0~x!pbőVbbA@ Y!a]P ky$Ň # 0 H E@Б_PPv `_V`b]a_XȱVZ^W[V\I [Y^|d0[Y`Z@PZX]0 WpV_\S aY՚`_J@`[yP`4`#petԙ0W0ԾN\V|]@X VZ\VX VYN`^W=] _0 p18 ?[#HN] V[_\|S d0Xd0-V[s v [s&O`@ hO$ Z@XZ^^ŚqZa0]X{ ]W    L%s|i\OB5(3reXK>1$ M{naTG:-e{k[L=.铀qcUG,ucQ@/ ߀l_RD1$~Y[W^9 WP'ypVsfvưc V0 ~]@00V L `V Y&q L  ZYYc]\0]]@|\Y]Z^[P\\Y1\WY[b^{wa\XYZWHFbWY`0* Wv[!w p^\ " Y[YW \0@Y^v`lZ A$\I# X@ ac&o%Zvi`&}&[''Y'` }&2̰&!c$ Q% '& B! [Vboppu`jm s2<2`% U-1԰48P57VP5c1 U/0_m7]Pm6 m5[]Z-p1]_^`s>J!\4\6 0b$R%&03 < 1P:Gp\JqFq[@ G F2I EY4Ah9@ V3$NCXIXGpX@$V& XQ@ DFFF`F!%F`FzF^FWFOEWB0 4WP4V@ 4VBZ` [W{4V4VBW4Vz4VBWS4V#P4VҹW$__W PV^]gXgPVZ` +gA+gV<43ŰV` ?Y`$`If6 gpgӠg԰8gᰓgXgxgfW_gw^g]g\ggM WYIwCIwSPIw_" u_2zYz^2zCzY{#u tcRA0%% ycTD4' QvgXIo+ zo]QE9#~odXE3 whYJ;,{ocQ?0 lh@XYYY3 V^~bp X! uj\* I\$p,I[$0 ,X@O RP I X" \.0!gv@,^\@!XPZȩ엫! TɑW7Z\\ UHU U# Uɑ UAJ[#ɑN@XxY 4u `Clf01 ?XI!avSNnDŽ[$@/ ^Zk&#Azzu9kVRuX3ЕXޱ@0BT \^\S n]V 2]2g`\f{l<l &iZ`pXP0! \V\"fueȅuƃI Dž ǒư TTITޱ Tg1 ֒ ޱ g1 $ g1 4Xb@52y ]_P  1XX_@,'1(q1pXV_YZ cbSbYfx  b fD^ fsbbb(Ts@A߻3|Spo vwWYWPތ_^\_Y$d0P.[\YZ_y @XZx PX0 P ^ Q3W_lI!\pCZ" P N Y X_[[l ` YX5vY sth^K<+ {k[9-WOp_N=, j zk\M>/ {l]N?1# ߀zm`SF90 Y`\  _c Ngp p +p3 @N"g@]"P3 ]ћ+p*  "  u1 \ )0YV[% $\O]_  YO@\ Ԅ2!Z]|#;'YY^;'X`Z( ;'WO[_w();;&^'Z( 'YY) '!;&|p'c!%!)@;&[\^ "1!+7!:90;&Z! +6ZBc! g9$Pg7 +6%YS1 +5xt,%ޫ1]8\q99p9Y9@79\ 9[99a9KP0S@_[YsA°ZE°2b@XP2 YΦZW\PGp@ZAFa ."_@Ws+QCo^g[ADPY᫠fD3$ XQZh` ZPI ZP ZPXX'YR$nYgaZd Z ZlpPvj?djmoR`R ipd7p`#PgcgVg<`$_ZZ^`2O``_ZYR`l~Z:pifua]_\^=X[ca b[Ra`Cdb Xpd AR\^cbJ`S[nHg[VYVZ_ *b[p Z^_<aZpSYZ\0tYdY |x |wm vZXZ |vl YY  ~o`QD5&qX?&?wUPA2#~o`QB3$paRC1"whYJ;,ÿxiZOB5( oX`dWWz)x\^+`\( @A\0"Y TZe-Zp }rPMVV[QtgtVZ#V\RVѰk㒉[ZNR 얽P`7R 77qk0Wŀ^w Yw`Y`\ dloZd Y0J"za ^TW[ XcY^ SahcƠ,2/!]_VV&+ <#[zr0 j`vX[_!s8^?8D 0N^V>Nq1{`l1 N!8 l1? l v !q1l"H>Ƿ/ǀ1>R/^l[v >42 WT@Ǟ1 $>a21>8s0lXٯPLl1.ׄY6 VtWV^Z`P ]Vb`ZA&V \YX Y]`,bp[bg ~ԑ\+f`áZw{QР`XVZg1cYtYh,VVXg *6c O РVYYHpx-#YPr0,$[Y Xf YBWlbB# ]/!WC!0"h$W3T@;$W0T0Z.+4WYYv +0%`[.p@,$E;MҰ 4x>Z\ OZZ zU Y]'@Z^ }p sy zk\M>/ +9sdUJ=0# teVG8,|ybUH;.!~o`QB3$ufVA2 ymc;' `ZP@K`[V mw aI a[@@`z [_ZZY[Vp<*p8 <<Zw|@ZkvZ =_[qRpq99fbZI rZ%^*J^PDarZ]afb$~v_\pBv[^% E@WWX\_\ᴒBZD@RZ]` \`K`Zn m]*Z\"`. V#bBb&sB. `Z[MY\p`JZ_V[pEB`` '*·)0'1`&'D%+7076_ 7б5YXq0WqM8ِ M7#M6Ps`ZYha`ar{is) #YWF#YW86_$)6PZP f1[]@3°E0DnG[GZ; GYGGP@2%b$qxqxFG2 . ?p GXX"4XXp0$XW)BEWF"F0F 2 G* ]0gX{F(Eb$XpRW,bRWMQRVZ\Q "W^WMQWRVY\Q WIW,aWMQWx. SX !2ZW\WZ ` `fK@ ?W\G 4QgIQf"$) ~g Ҩ ZWX]\Cqu)У`Wd$`*Tf1ap:b+HGbpasRmsZW^VW|$ x$ v+x$+x3 vXx]QXxِ vX_ v^ p]V_dV^[vu$`_^ c xiZK<-`/yj[L>1$M{naTg:- ~i]N?0 n]L=.zk\M>/ T825AE-2322YSJ1`\I[a Zt  p  б  U߱ ӊmv$vб v޲+w\߱ v ЗЗ)vXRvZ)JXvv(UVWP:V70ɑJ \Z w\вvsG{WX$u{"gҸƧ_XXYƧWK@9ƦʐX 󧔡 W[Y Ʀ4`/ߡ/ƥZ^С:{ZY Ơ\YKQ[&|V p␰_X[[ZV\\n \^ S]tjPIзW\sYxVWpߡ ,Ğ"P,[WsY[W D3[V?\]Z$й\ذ X [\'` Z]CA ֨ r@ v\0ָpY[_[w]YקW JZW[ ZZY1 Y+wVXY`1B4N'W煡WpX#{ᔡСI'粡K@u煡 欐 `$甡 С'I* K@ B88*VK@G]\ [X ēVWBޏsq_yj[L=.zk\M?/ ]l]N?0!}|m^O@1"|kYG0׀xn^N.?Qu?pWX_ຳU _],W_+&+pVpa[w;dppT=` g$s6 |u q6 uV^k][t][sI-u`[bQXY\oG 'b: _A!1 F 7>7W&k7$[7&Z*9%Z .)^_ !$WPP 7Y] 9\{ 9[ #8 IYI$IW!I`H@ZIN`ZI]ZI\ZI["[H(IYIҠI`IpHF I^ I0I0I[IZIpIxIIPH`W6W]V]+ WWIW&W5 WD WS Wb 15B]+i +iEBZXiXi5BiUph`i^i] i\ i[ iZ i;i)iGthF*y^*ypK*y*y[*yZ*y+hdP8yܐyV+hPI Q Q p |fP:$5~qdUF7* vgXI:+ whYJ;,cSD5&~o`Q@/ taS@- h\.Aq=7 X\ u!jFPY6!W1 k\^Y^dY]g _u?dX[g.\^>\]^#o ]^6o]\XV[Vbos9z- raP?. vj^RF:." ̀j݂/^fffA^eY[W^"U-h]{$BW(WȠ]o|[ @dQ B]P_Q] 0 ZX{]^ "8P@\J&H @%0 @ B@?&=(PW&[f][VfoVvdɬu \_ZP& @>$X[\\|e"Z^_eP%W___\m#Wz (0P&W) 'W]ZsP)X08 =9Y` O9 P(|%X\Z_%V@ 'V`{'00'V1^)`8W[:09W38А7 8\Y\Y98X 8: ,$ HZ_@ 7a@!u P %PFP"oVY*][8  !YVX@93A@Y_ pQ A]XWsv VsPXvD&P{zr| RW]?b{KQV;QSUZ:PgPPr!WXsmvzV  ^vmv=kP USW\SP!SmvTVuh\9@VI@ X^ P4QWNP?RzEPRS]XUe\`b< \˰ (9e[B`X H`r!s|bXY8S_b-Ykgcd! k`!awbk`?o|VZБ^bg|fpAc baXZo i!iWXo iёnbZZ\ s\Z0V Dxmwu`vrpjbbmf`pfu 8D#w`B\kvӢdmaH s Wo{3wupA&wsp\)Bt^fZrTv_!d faK5 ߧ5WC/K߅q]Y9,iywWF5$~m\K:)pn]L;*o^M<+p @XX5[V2څZCt;U\@YZX `)w])\)'[) T* ~X~c[ \0Y U`~Z~l (M((~hAZ:`mW}W}P?ఫ}@9@YPW Y@݁9ZSZXD X2A*Q A f ,P9 ZɲXѸʰZ% #/Z%"ZZc__kY_ ]UWUXawWD ]# ZJ " 30vB` VſW_o 7WWYo Ƒ % W |4P^V[bhk_`a F8֊E JضE J<4SxҜۀ4 H'xHS9Xu^^aa7KXuH0][\Z Z] 0Z0XlEJ֯XuY_ XKXZ e lW[ WVZRYfQIE rW]` "YY" W " M ]]Y\~] _Vw 9b̼9"^]sep xgVE4#'tcRA09xhXH8(U_vi8 }vbN;'יs_K7#鵀q]I5! ]̬@4P_`zd`_] >K*^Yw=W\[A "XZ 6Z"W@P`PprpX9@PYX.PxYX0p@'H$(\?'@ L(p$(Y$(i\L'[ $'WW#j(5`(`(XjD(i(E L 0vP!L'/q$';8C#Y# (8@fa;8O8;8#X9 ;8iXL r@%^kqpp^C!gal3W0؀P߀Z|Wowufs?lwv D@M!@%E;2MB%@ A,}iUA-{yg9C1 nZF2 ~jXF:&pC?d?VZXYXކc7@텕W_ 0_ VY"01j`6YX\Z]^P_PkW_\]"L^X`!^XŔ@Ϝ㝬녇b"bP3ɒϘv[Aϐ+1 ϘQ! $ϐ6XGa@E2QWVVa00B0ڂX`nyzK!AϕNҶW޼ P #޸Y MV˅\=.Ѐ`ϐjNAH`Z_Xv@b_VWW[VXZ| 1WڂWd`\]\#fŷ`6kAP2PYNXڂV[E՘ Rۤ eYV>VPݏPXp=VWYs_ ;\UYD[ZЬ_WWZVV3@> pqb3PB3r9paH`J [ " # ` pwrm0P]1R @ \] Z5 X6L)\%\[\Y\ \}P/#^b s]  t]I5! /mYE3!nZF2wcO;'s_K7#o[G3 kWC/@2pkQkXEY1=W^[[݀ bPU ^ ^+Z ;;D+0 pY 0 XǑ) $+ I 4,H-* 0W{#H(Є,- p)),$,+ p))I$<<+0`]e_ Qk{1X^3!Ћ6 Q8{ ҂2945\.PYWqt5`q7V]X3TL`qHZ D(L"`qH02WE*`qdE[]0PryLap LMaqIX!P @Fa Mp @JVs`blQGbpLW2P 3]a` +V_*Rvs[p0!Rn0Tp_Ad%q*`+^^,],\{+]]-t9 x?Vds(02 8a p u pX@(qVVYD9\ \W^$[_z)% Z$Y0D&Z'Q'V}6%YV{ m(z 1d#w}({)z )u)r)h !awl)a b%u m(r m(hm % m(a m&X_^Q&X\{&X\ f8u;e9ht0#tn0 e9at0Z5u Z5hq e8718a75Y`(%XY7Z6W^@yD%#G]0HY 0FV[XJXUa^_V{ \^XY kD=J YWQ(BJ]PLJ? IJJ*J;FGBYV^Y .Z].Z\YI .ZS .ZA.ZOYY.Z@ ݁X^ހ_Vw7 i W\@Dp R}`ꅿQV@Z\W<@YpYVP Z0 $ZDp V@WQVHa Fb:Q aj]QajA ajPaja`mBp w@c^-@E@aeaVpj\[{jZ[jY[jAfD)wEZAEKqTz@Tz? TzTz2Tz* Uy;xJ` A ?dt teUE6&!)5dTD5&k H1|Z8*ֿ~qdWJ=0 ֭{naTG- 5pwj]PC3$cP6+ְ!WXgpmVW__W_]*>[JYJPJ@ J ~<`J\_ oИJ[]Y@JZ_;]@TQ)>Y_;4]4T4f@ 4V9 hw] h[ hoPhPh^_]` 04+A kO]_h+Y(W*77W[*Wirg!W_S0'x@ ]e\O7}|go}W\,ǴWаP<`ٰݶбX4 ٰQV{YVbm +${ rgyzZ]VVxg@Vxvs.oYV|@ 'IJ2ƲoXV|!p Gkz(ųw{vvZu]o`P۳|]oP\vYuY vYYYwXuX X^zW" Vo!Vu pd1o szb gs z| ]|VXkCVmfwjm "l\`Qdm s ab_Vbm;`Whuv@ "Sfvګbm_z-4_^>,'_@ȭ4!AWZ1k_.~cV^o` k^ )"] k  ""[R *Z0 8D""j"Zi@QYvj?VYfNJ$JPR 2Y tXVX_ _ " Y\GM@\p:#s~qaQA1$reZM@3C zm`SF9,zjsM@5({yk]OA3%zjZJ*xk^N>.8069;X.^# KI\ # Z# XZ`s1XZ XX X<`X@X Xnp? |!0VfkVZfNXOWf^P|X[VE^!(&&J((7(F G)`7 o|>NWZXku#ܲa'W&W_C'bp&:@kP|XV ~bT3 p%DZ@#\PUI5[p6[J &[?q&YmU%Y 6Vy (YX >{ijwX\Z@W@=0߅xu]hWvzt_`zW]l䭐W /5 7`7 6=0n5Z9 -Gl#NBNA&gIS!gHFKW%ZM-FZGxG2-F`-F-FGGTF!pGYG`FXr&W&W&WoP&WPF gWgW`@gWڠgWF W WW,HE)0Y9PTK@WֱVbV g[!f Pnީ3 UX_g_f[iyg^yg@ygyg"pygpyg$ygXpgEaY^aiE`g"g.x&>ywNkw^lvkw\q kwkwZ kwp1w[wYZ%sui^SD6' yhWF8*rcTE5& laWA+mWL@0"}o^M<. |ZI8-17IJII\Y 2X\V1 ٕzu`\s\` H~'[`'Z`HY`{GX`XW`X)VC,WV:`@w\]0`޾X\4\\Z0([^Y] XW[&H[RWU0࿰Y*0俕Y jN`j0 n`;s#[^\0d@[bagz(%+0 Ƞ1?[Yo2l`Q ȡ0 BߢPw[WV b acM%ߢƱ[}0W[ oZl^FWWZSZ_@4w-~^%U0Y`طY0aj˰1j[WY+FWW\7W\SmVSn]17`ُp03Z] S#n²v @NX v\VY \_ jP 4 ^h` }\_X 0ȣ1ԡ004Y\YZ 6Y7\V_@O3֘A[gqAZ@ AЃPoX "P]Y YV^;[P 9Е ѡZu VX֐В_6`&2 eY]~0t3IP=$Y\Z$֐U0B` : D DYVn0@&:QZ@x0\zEZ @xEU0wU\Yc@ 5W]^i+`Wb0JPY80(1x000P3!|1X@Z_Vdfhwjs{vcsYz~[Z[n[z~ P%OD fstߧgYH7&~s5[N?0 q`OA3#|n`RD6( ~pbS<u\C/ugX:+}3vbW[o4yVo `\^v`XXPouj`W& ub1mۓL`T bPwua^XYl_\^֍[\Z]r`l`lV1u ooujphvs`ppfu oi]Z]o\Y[`G #0"   szb gs w ]|VV\2+lA$ I-kA$b 1mfw }#bw 1mPSclY`W|#kv {dpP[VVj?v|'찪$-a"-`>V-Q(V][ 2 bwt \Ei1bwg!O4atQ qat&xk7Pk0%`oAMXC20i01_` _Yb_WasP__]D\j_pڔ_XzP30P $7P6Z 6Qkpq_ 6#X_dP?G?Gpj2Wc5.A^shvIЇA]YWFVAFX0^G^AGw^`FSGGBGB@AMLP3^\P4(^CQMXMP#S[p bVV_ ]K].{d]p2g\{fY_AD` ah" `z Pd wd aEIw wU \+qT]̰Xߡ]q@ u@!]X\uqa0MP0%a ]̤u[ZYiqh$\ZWXA @~#r_  yk\MC5'+r]G2{jYH7g}hTF8*sTF8*wlaRG8( ˿@vgYK=/!ADZqqD X@\0Z\WVf "1Ẩ20|Xn01@slP8|X`@oea;[Z̰ 2w}agpm]E=+`ձb2pɐ0@6I bvӑZ ̒YҒ 4YXVW?auVj+ dVmr%H$03\+LZ̒ 7q[P WVZ_e] [duU W!^˷_-@1C\ K GZ \ܰETMSUOI`b`D$?scFpt` Ѹ9PѸ\ Ѹ@ѸtѸYѸXѸ1@  cMPDrBa w GdDWc Xmjwamxfgr`ou___`dP2W^\P .]_\` f_XWBd P7W] VÀ`Z[mx]XXлX\21R&`W_]y1;\2G R`Fpyo2vתİ0RGAR`WbVrPF[H½Pdjmo  "}|g]o}j,yo}V^Z+#+W\4"!}VAJ&!}\4xgY[zY[w{mYvW\z'W\o!w{vv -XX!' 0"&!7 ws0E`O4@Ew^vz\uzZu]ozo Ggt 2t!vb^jX|XVgFvbC bR oYYo} n"sprcTE6# }l[J9(KwfN4eߗwqYK?/}teVG)̩ybTF+wk`N<*osdg[PpW`ba WXf X j $0 __3~r_^] v b}_ YVpX{W_[ u^\q^[WXH^ݠ_X>9~G^Y\^y7W^]tq_Y vbgn2\VW gff]Zqrs]Yvmb]Yx K]Xqr"Wq3%Vqrء]\VXd[r@젻V X^XXS#K_ u` "XPQ3!&W*Q54$ 'p i"aVFV #\l P$jp]r%Z%iP ̑\[_ {b1ud%8hp%8a<Ր%8`o%0"[^%0\[Zࠄ0(-e\X% 2W'4^]`6]% "RW\_WY-@ l\n t 6[]\5_[krW[Y]_D]R@s[[XV D[WX鼣[WYZg`UF XU@[ Z 4[ݠVWx0C^\!o_`X[-kF@X@Y`G@@EFY@X0z![X]Wr Bdw$@WZAvp5wBWZL@Y[+gg V UWY[A^P(PX[G=UX@] §!8(PQ\ |X@rP|PvB\\@p @T[&@[ @;BZ ע3Q3PZ ov3PYV #CWX_WP@Stq d@qV'f7gp7dZ_VXadZ[WsrWT^q)@ZR^0e_AgYYWXgXs gv@iXh4!f^af_A}wYYYwRa#xPv]a AwZ!AwX $Awa nxP vX 'YwqwiqIwaxPp^Z[\L]^!Z젉0@_^}dL45yk]OA3 GvWVF6&߶kvfVF6&ߓ6xi]L@1%|p d`edDff@d33@dG@z$R??u?OIRF530IR2NTRANSISTOR,HEXFET TO-220ZBAA@:20?ʃ(Ӏp-ߍ520ST` MOS*q=ӂ-CScLXhx[CBBA;23ʃR݆Ӏף Ha2ќ'h@Ӏ\{G{@M[FI7ISOLATED {^DCCB]ӀQ(قǀppc V{ V_ #5@#]#ڿ#w[#Z#Y#ڷ`#q#0#`PP QN(@! ՉpC@91dPwV_ duBvW $X_$']V .[\.Z_ .`*.^0fZ.Y\_ z3Wulj\0!Wshvb3W\w YVsvm w`dmwd+y"uPg%sWoW[`GeS@ X`!W`9A@\`RJV`j$QV 9 W 0x@2`vg? q&#]VsrueUE5%-p`P@0 p`P0 p`P;+ {k[K;+ wk]F5*xgVE4#ق\bbaYlj`V__f{ ^i W[f !Ym V^*Xb TV_i j`Y^XV`P Ez)`y] 0[0!YYaur4#YX!Y4@PҐ#YWI"4`<0i!Y\^@<;PR!Y^^0a ov\TYX_ !Xd^{$Xd\Z$Zqe$ !@_~:!9)\ި*[;)Zq*0*W*V):^:]:\)PH:pH:wYH:X H:H:V ) :^ ::\;:[:)@ :p:`:W I)xP)/)?]J] ]J\ ]J[ ]JZNIYNIX]JW]JV Ұ[4\#7Q: Z\ Zp%R=Z=Z`=Z`=Z#`=Y8Ya Z]Z\Z[ ZZ ZzpZНZW ZY-j^-j]-j\K-jZP-jY-j`-j Y Y/ j^ j] j\ j j jpj j j0 Pҵ @ P ɨ }z\ }z UzwYzXz #g|N7  |ocWI:+ vaN-fP:$dP<(B \XuXXYl_`a GۆW^Zl^aaU [X-VZ 5) =XlaۅaXXX݂W`Z]Wk`wVV_kV-YY-XX嚰p݂VWuVV[{bum`aljw Yy߀ XV[gpm~[tZY @@+^] Eإ\ ZM9V ^  \[ڢZZXf xlc O+{sФ}@݁VbvpgZVoi~YXȱͻXDzͻWDzͰV0 HW˰V@V/ dZ?lPlPlPlPlP | W[^ wf\ufd@huffp{p܁mxfm`blZV F Y5,NXZN؃Ъ4xY Y3 Ny X[i-݀7xs/ wvjdjmo]Wv`  uosh 쾽shgDkvdt dti[iZiYi܀WdpVV][V`]v| 5"dyp? ibWw`X`Ya $^q;Rāfo ^x FAgJPi%@ipskt`L8$v`J4 ~jVB.:}s_N=,{ncQ? 塀|pe[J3"ugWI9._.#EC ][YXT qe^KX_]@Y[ Y W -06)UZ0 6Z2 6Acڢ\r\qe\jq[mfwb%@4[z`tr/ pzPVVos/#"X[NV0l^\V[ o`[pkף[@G~X[WW\?!oXJ 9e[qZs1Z\GX}`" P }}Zz`U"f `"Wvb "W4] _Z`*0,O ,ZP,W)V! ,@,[ ,Y,3 U"W Z" \ eZY=rt538Y" u2M! 0306@4Xxu]_p3XtXPXWY^| }XYWZ# آ3@ / FA! G@AG4A_@܁X/Z[ `@eX W̲mB`pwEVof3W?v jDVsva@p[ #G9P @t"+]e\@@܃bh"tyC8AEVRXđ8/ZF(SFW8XD8WX8X2d X2tT\8ZVR Z%VR\8WP[aPZ~[Pe!gbZ]YUl7jXEd 7hKYYDfdiZe yh 䁈d7h 7h4jDe jZe ܅^\J]z sKZ]s9z 툴Xa8YYsHna8 uz` q qyYs yx{k[K;+ pcVF7(}5;߿AteGG8})M UymgQD8m wg[M3'wh\M>0#ymaP?u?MIRFI9530GIRY[X^VX0 OY[Y@ RC,/NtYZ[_SOY\\@^V} Y0wC{g@3YX]]~YN wq@\ q@8@X`͗ZWyr20VY\X^kBYV\\YK}J8 iȗ.QVYG_. 3YݠVW\]Ln[hrmVh]\ Y_Y]\^WҢ\V/_WV_@  蠀Ai 9 Q 0)0X0,W]@W^[_x(Xg:iXgGfƖ1i3f@^v^Y ]lu`os6gru~^^UP^_y^[]W \\Z]YY^+X 젻^ [44>4XX_ aJ4WV ! Z ٽ %YQk׉i!Y\JYk ^[WXkWH]v y FZY _b0A4 Wn@nXYx }^۠| m^^8@Z\x 0yXW^|m&]\]x}]\\m]\[ 8Z8ՠ88WX(#@r| (Z }n] &\\"|0?E e[ &[CsthUH:,%zk\M>.O~n^N>.}ow~n^N>.ߛl`TE5˹vfVL?2% _z6 bSD5& 38EeW0AV_]WMZV^_\Z'\s ;(X 1@1QZVY0QJZVXYC4aXe vPjB{:^@gP\;i *vumjdGa`vEl!R! j@] 5Q2*32b0Yu#vNp & 'p &Wu I 1Zp_2I O S \][W_Vw T$\[Wt&V@!e#Y[(!ⱚ!'~" AVA0BYvb[ Y^|XZg#WX|_XVg  oojpvxm`wfdujphvs`ppfu ?YhXZ[v 10oBY=h0[o20Q_s\rO_Qso0M0_tN4b0 d6d4^Yذ2@J]VoY u"Y]E,c@0C#Y\]\Z80:\:[w9Z:wY:X:W:9lxKJUKJ]LI\{J7{JZq{J{JX {J\o{JV {IW8J@J]JאJ[JZJYJX8J@JV{I/t9 Z] Z.Z[ ZZYZʐZWZ0i-1cW :gX2@:g :fgXgg`:fLX,hfNXgafWDa:f:fnXi:` f(e) w@ vA'px[ȑ PDz?! 1h}Z{|@}[ }({|'P }zmQ3& +reXK=1$ rdVH:,a yl_QB5&reXK>1$ {n`RE8+ykVJ>2~R[j@ua$pq0=!%[+s`}ZvbV^a`uZ? rZcd~gY^[ñP\h``1a0[ȗ̠՘ZY]g0Zm^ \[ 2ZZpfpѬtV\V\Uhx@i2p@@@ @@ ݧ@ݧPݧ(Pݧ8PݧHPݧXPݧhPݧ@ݧP `0l0l0llZ lBVFB 2³ lXvbYVd ʵW[wd ׹`׷VWd^׵bfXLD#XapsX[Y||m9b5m>%¿[YvMo;YmYA¥X&vZ f0 tXXY? F!XWs`x\al[aZaYaXaWa,AWs I  W[pbufdVream`blo[WpR -WY0Мp$l0ב`օ0t@^p3 0Xd`0\WXV9 sfm Yfv|o|mYbV^[@J0Z f' tW9nm-}VWv/0mYmX'gWvVX\Y($4>B4Y>0X`Qy#y0W`s||pdXL?2% |obUH;.!xk_S@-ko\I6#xSF9,vi\OB5(ƐۈreXK1$p?_2 v y08X U`Z`0EXuFW_V_^PyPyPyPyPyPyPy`y`y(`_6`q]\P_dqt=&I']I'pI'pI'Zn0=&Yz0=&?pI'F`I%V`bM_f%e&0'V&'^'] '\ ''( "VVW\ @]p__ϐCrX7 e=Bx=WW;X' =б=`=`;= =5MX#MW6^V^_2IMYJLĐoM@K1\K1MMW K1\KMY]]F`@^vr^vZLP^YQ_Pl@Up[T`rV WPW`W`W(`rVW]W\W[rVApTVeX_7`g^g]g\g@gY@gOg\NfivgvvfgАgvd] qDfUPgYgXgge^`w^Cvu[ ; \m 0\m\# Ev EulEuqi[\^Zp]\^Y6\YR p0w#0wpxr ^Y)wpO02 ~qWJ=0# zm`SF9,vi\OB5(yreXK>1$ {naTG:- wj]PC6)sfYL?2$Q@p]V~],,b0,,,@,ڠ,\` (5BO9 } S ` m z     NV w^]ܽ[YXW=V|E  b0 x X_ Aw^ A] Aw\A[AwYAXA0Ap^]\w{[wZY@W V } 8^ 8]8\8`8UP8`8`(8dz[ǥ@ĭl@zƯWV ^ ] \ [ ZY3@Ǜ0VtE }^}w]}\}[y~O0P@1  XerZYXF@xuҐߐ쐁9 Jw -:z 爠濰DDDDɠD֠DDD 8fp]Npp s_%5EUeuwgYL>1nW@n_RC7*ѫB3WA-[VV`gBQ^: YXvi "6-2X[; ?P[s`?OV;?uW\;\V# ?xp 0`Y X HcN ?5 ? | _{ijwfWY`}'am`bl'"-'WW!%` \D*9$` D(V!$\`r*9# - oeS @ePWyz!Wy& ( !VZ_XA&+VX0061vXdPwrua\!12 -5YfpF0 ~/3X[Vg90.4F7F4bf Y1D5 :3_]1` ->` N7V 6`7w^7]7w\7[7Z7֠77H7-EGfpEGEGNpEG[q EGpEGY EGX EGPEG `EF G%`G2`G?`GL`GY`Gf`Gs`F /W`/VIW`IW`IW IW[ IWZ IWYIWXIWWIWV/VZw_W^Ww]W\W[WZVYgpgWgfY_ Mg^ Mg] Mg\ Mg[MgZMgMgMgMgpf@gͰgڰgfwwww (w5v QwOQw\QwiQwvQwQwQwQwQwVvAw^, { ǿ|m\K:- Ak\M@1"̿ercTE3!}oU9+rcVI3$ɀ{pcVI</"ylE8+oSISXW̰s] \  LL LA sss,s9sFsSs`smszLV_PP `Z6 6 "3Vs/$ " ] ]'WXwjwXWZc 8GW 0YcƩWƩVXc󩦰z'㐂"㐷CkV¢X_V78PС} FP}YQ pӹ}zVnW\@ D" u V[oZb`hfdpxwvOXVWhuroofwljw <- { rg2bg&uvW&j~`rxj`!Vdm s ab "pbp}q_ S`JIad`a,FЛ`a>a Q5p~oa 3^\[F/`99вAAהfҪ nFPnβЌШ^g@aLMpѡA`eA \Ap3}AⴠI0IТggI`e}֑3ZYX0N $VYdAY!!:XEP q XK q𐴠@8@弐[I@bMi\i6 FPβ0'0sip!~qdWJ=03yc?7  YpZD.~hR<&uj\N@#qbTE6' 們PsfYK=/!\{0@`[vfa&V1[[^X^XHw "" ,2[[Yz}@ ^ ,! 8^ZVq KiZq SxZW_MigWPoʐVo^Y X&pI y ʐ oP@ yo\\@o[!oPw YZwc 2 !9"2&?Y][w A&YA&A&V+P2  YZ UZ&X!'W!92&w }$z (Zw %Yw((ҕz'א(Ww8A$YX{ij 9YW"D1I0`` Z2hX0vp[\Zsplo{5Y{iw3^7Xzm47Wamx3ܪ6VNp36[^r57]u927\aJ5 7[04 6%Z8 ?G8 ?G8 6Y8GHTG3H6X8G8G8G8G8{4W_}cfm41W82VH]WH]W3H]UZ_[G WY4HV^W7 V]X V06]PR[_1fDV0*6$g]-\Vsui \Vmo fw+f\VbrsM \9WZ$ 0\]+\p-p N[ ^\V\lmVZ{{aZq܁YVV_X  _zX^א ]yګVdV\VN[ZӗWX\>\VZ_\X\ duZ\s =܁ 1@va - @iWa }Yx }\3V_lD\ZZVs\]9P. ZVզVߣ^!ߢ آoYWVR֤!^)\)Y)QZ^Y\iYi)\X\bX[<@@#CT``D ηZ OCٳ봅W^Gb[1=˶=ɥ`J c˶=XI˶o˶WpyW)z {axmaWswXdP[ooofwujb"X3mmhl\_[a`p}r# ___[_cX PY:pj[ }h[_ \b^[JxiY`jpvA~bDҥ |1ZYНX[EW0XZ]VX]`+-ѝVt `;(0WY`*V&XX1ZdR\21`~s?W^`h,Wxg` h>4N;0G`;, W ]i0Q*\^^Z_VZZY]VZ \"Y\[;X]\4Ȑ|D[Y_]Z^0U[X_^Vo]Ww]Xw\XwWY^]U@ ZYXV[Y\_^Uso_#!ziXG6%3jYH7*KiZK<( |eXK>/ yߙ{]C)wfVF6) ym]PB4' wp@dbk\i Ogu^V帣 guqKguq!K gm\Vevp0\gZZp$q~K ~]r~bwt8V ~$bsm p ~_Z/ RN^\\W X (\^[^X Y ^/{%(,3*j03 ^_]YV9f^4"\^WZWHC]H֣3\WDp #'[WXҩ(Zᡩ ܀[^whX Xs"x-cXVe-"W[- 3 =!`@Z]_OL7Z6UXpY7WY6\c1 7r1 7W9W Y6@X; Y6ZZ]pY6WYY_h6WW[,8>h6VYjsY6VD@Y0[WZXK[VZ L9F\8@`\[WWZW] o\?^s8BXBkYto_i@⇑[ xDA]M\MV[$M/MUM @EZ,MA\XW aeYYV]X 1Z30P 8W@ 8WZ4P fŠfQ-Q^WW kUZVYz{PX^_t^]XkzXXZZEZ=U P!X^[[XY f1Ys |{PEW{2pW`_q\#W` up2U0 gDPT `W3Vbt*d5kZ5f[j O,^d[{hkYii2j` dW iW^^hi+`k0 j҄jI{[={ZNz؊g9vd]Y]YYe]=!YXoid W!00{w\00$sE1{ z1{ 00R2 p $"vaRC5'whZK=. t_Y6"o[J9(teVK?0$ sgXL=1"sdUF"u?^]Y[l0}0\]bXY>H_m ]_i Wu6o[B$]W_8f{Z2]W^XP Pn]yH9@Py[JyZ y!Y f 0l\ Z yX*!E XETW\ E[8TNETT`ET2`y}q:W\̦ۦ[̦ۦ{ ̦ۦyq9VpV[V] pzVX_PV9х Q0x]"v@s]Op! ZW(P0YQ a P0V_Q^N5^0Q&ȗB}|gZ]o} t+wLVo}0Y\LjTsPa\UAxhX[yQ \T\\lAhs0 \|^|K[Y C|Z1z+"xgW\xv XV|Y pBw{vvRV ^Veok#YYө #0Po8XEX #{#аUA|0З9WDYW #ا 0O@#vzY?uYoH4?XuXo$vh\^o W R ?3XlŐgo 8v b\u [IeZussbCs3WO[o?U`s`$ ^ sM`uj`P ! * 0P_ovS0og`V [ $U[Z\ kBjn\xov[R\Y[] 1d Z[xx&qoix]mfw bwa[Pq|ssp%#~o^M@*|iWD4Ezm`SF9,gu_TF:/$vTC2!ziYH7&рyh}W݀5$7YT`U!^XopLWT``U0"]"Y;"X"0uVVY xWa _ M0^: iK2 WXr] pY[Z]]Z[]C_cAca%) 5 q *$^$(Xca.@^XZYY4Rm!Xat't ZX0 5 Y[{bB$0Pbpq U #~ &:  P^ 3XΊ@#Z+吿% *^ ;@(*@A:wPq %0[\0*_c6Vm1;%[V]OZ L%b4\~ 85%@_ 71?6XV_$P p^bPx!u )C[ P^ FQ^WY{ij3eR9@ ^bZ]Zl`wVVkNF_pZDbHPpElCN`XՐF@j!V^mV`šR^V`F^אD`AcCWa`n b^AC lu#PB VYd WZ WY Wj Vu MW^MW] T_?Z\vU>0PI!-`pR^Y[PqQ ^QR`Xxpp]a.^`!g{XXdWW/Poojpvxm`wfdujphvs`ppfu }d1`̰[]b ĿaV\__@4aa Hj ]__ @d^Y`a!a\9p`pp7 \?Pz Po\B]Vpla[__pq][ҡovwaW[ WXvw[_V^Od\ {c[[ ` b`p`btdrՐ`laZvf'ZB9"]~``[\4a DY[*S`kpa `pWV vdb\^p{`B[w$@xv"R>xMp&y&${n`RD7( teVG8)|k[UI:/$ wwi]QE9-! sXK:(|m^O@2$vdR@.u?L7924$_VsV],_0 ;0.Q QՐ!D0 ]rPPX @ͰIТ RV;[_Qr YVia -_{__183/ {l]N?0!]W5mBX W \YCX ;;&kK h []KPI@0 X Y"10/w1@).`)JP' I)=PI)ېI)wZّ wZ!)X)')Y(@)JТ&"&9X] 7W7G9YjH8@%]Y Y 9 19`9@9.`9JP7z 9\6uXP IY9.96" EI\s6 [ F frI=PEIEGS!]I\ rGXp IJI|Is`IĚ5X W\ EQp&YZ&YР5QYwSW qY &WAYqY"qY10$`wRAi @X SVB"Y&VlBiZiYWBS!Ci`@gAKafpi Ci5OY^i F i*gʑ iې8iiV ` ^YYuX4M x]/[\XTы:yC?UqM?\q o{ ?[_ J?Y ql (kR@(& lYF3  xiZH9'OI[L:(o`@1 paRC4%qbSD߀~<- H00702H>6X][/][VoӢ\Y=[ 4p  Y)Y][ Y%DJ )k J XwJ )Qɰ Ww _X07[|2A))낛!Z{8AL@{BzPA^LS@-c ^z`@XWb!q!wЋVVX覀VeC ! !b!?? ^!AzB@oa"0 VW\U|K%7YW%{ظذ     | W_Z^y %-!% >F-q%ѳ >ȇ-ґ%ڑ -W\`n\Y^5zDŽ 0ùش%ذ4XF gZ5-YWfh$ȇȖȢȨȹFW\ȓ 5 ȘX԰^W(}.б±_ fӷFƴ Ѵ&&蹐$^ېؘ5q Ì}@_c}@`"X^VW=p Npp pY =X\3[FZYVW\[MxpV_x$@#sWn@)'wwhJ;,Q`-zm`S@.ygTB/ g{hVF3 }s@/ w_P- ߫ˀoaSE7) M13700ANo[VV\ rS[ Zt`Z`]#9W_@YV]AZ^a VZ]e k[e kYekZ aPZ64 Y`apVa WoY_\f4F  L)Ҳ $=()H+ % =(+()fӣ()&2!D+&2+ @#D -8 N9Ҳ ?8 -8S9#?8$-89ɒ95&葚 9 + Y]XlFґB@;B" Iϔ0BH! I CҲhIDFS$IeCI 3IHG I Z5@FFJCCF[Vl/!EV_E#iEoPF FoP" yPWҲyYIYS yYYYfY yPWUZXTfPCb[avo OdX^05CZU`[eAYgnxf:fpt`da bvYV`Yeai=gW`ܤeaWiVfpyW ypwa FyiFyV a:]8qLqXyVvX]s ZyXy *(}naRC4%qb?G6*zk]OA4&cyj[C*tdTG7' bSD5& yncXMB, Z15AA2NfV_W[fV` dV^\S[YX :V:a gaWV\v ]\ fg[v0gZv spfXv\ sӠfWv sg`C`Eav ggck`Y ϒ`WdZu^wuWjhdT `h"jVlA2O, k_Ymowtgdp[VYu 4Cm\W^c CaXK~Ρש נ-ץZ"  Ѣ  QIנoojpvxm`wfdujphvs`ppfu BbfW H䢳g ܰjbo`vwfubdurosmxo˳`mװp`wvrxubfdju/_@l1^W\gxvfb`uuj[!'0q?W^_ _]OG^WWL^!irmd06Ca\Xs` Yp ~\Wo2}\W`X}ƉhX1k![0dd ׀ svsZJQ[IZY _#Vw"Py\2~Y[W\Ƞs`wYX(Ѳ`Yfp`POX[`OVwZ^\ wʃ\Y'NƁJp`#uǼª[\Yqp\>W\``4ҭ `ց0VW U`ѩe0 eX | ZZ_ufdowuamxfNW_}fmmr{+԰a^0; X  z\Vuweq:iC8X^Vu e zp`C ]VVuv"p^XXxg[Vz9w{mXuXoV[sXlY`W \n)0[ZTXS:X Vz0YXWX B xmCW@<_7\ 6W A[ Xvsmjwgr`}oouX__u d{`}s`blXTWW:vvY%^tPR""]p[[>st-+sgXH5")wdXI=.=GMlJ* }qcUH.qym^SG8,|aRE6&n]R?1&R??dk?,YZ9& Y YW{ijWY8[68]YrZ Z 1fNp[YVlp[Y[ = ?VXVsJ:ޠJd`  y!p^\atW\ZJpsC# mE hpN&۰Z%oЃN%PZ W[[W  WVZm W[C# B"C0N%"sZ%PN%-Z%X\I!Z Q"&[I!&[&c"&Z ("8%W"% Z%W2 Z6 f6H"! Z6f6c" Z6`îriubW"B"V^IHu3u5"qkQA FX'FW]@"WqBG\@B"#Vq^H>@ { rgyJ{ gzׁz\^VxgަVo|u@oX[|sDZ]G@oXXAFYYG@A_FFoXV|"!0FJpEs@!0@`SG@Qo;YVA "uO#ViaLqP ^&_u}V!0P^]]_^9 QCPn أP\R; #V\]P \\ZXLPV&G#fTV N c#*fN \Uc0 [W_I0CK^fZgY`b}#*`d`\R N p$*b#N$ QeZV q)xUZeБb#e6e#eeX" e-3ovޠN T8񸐌 @=t=bS3 ezb0N "p.,wfUD3  xgUC1 ߻[saP>+uuP>,qbD5&)~oC4%wݼпxlaTH<2!H@n`hY_db ӴWaX_d^sO#]+\4P5][d f9 N,s 5\ow 2#\^YP Z%vWUf]]WpSZ^\(;hWʗXYʐ !\Z `K\Zy ʖeZgw 1YKذ!!7iP\Y\W\YX`H!XQX' -\XLPYlaaga YPsW[:Wʕn0,槸p! ݠ "VY!9t@YJʕ7 ^^őy\\W#0\T w >𭸙) * .\u&?3lP@^+Ǣ3Z+Zu]MZlPP](S{Z+Yu|YlY qY=@u+6XljXu=0u}+Wu[ 쎳4 Wl[s +@l +ۏ[u@Nj u+ZNVls= Pu+γ\ . [g5p_xp2;1 b0 j:` Z  `a VaQVAPaq[1avB![^pʔVrƐ XY*[M` 3[AP q  5C[.r. q T20Pғf/!H'1TBTdwud:X?Z[qC50]5] q Psv /-tcRA05k_SG;/# }pWVH9]ctfXJ=0"rRB4*sN<*weR@. @,2W0A p!C H0 PL3L B  Xl B&JRW 80 '\XRl9^^l vWKI ;+ Br ;+&҉L ;+RBV@`00ҳ0DAW W [GZ 09W ?60 ` PR7W _5YY_:1 o:.o6A(04Xp` 5W\X:195V^92:K6W]:1:0$1)CBDwXdPRBvoZ]oH8EYYoEFXXoEFWVoGbvjdjmoOvh@AW8Dh\AFW[o @rBh,QE`xB ~E`\^@I8D`\A @CB@\Qobv7*mbwbfwvW\v38CRP TV^vW`|PQfw Sbwtcb ka]cdP?jWjWjPQRZX Y`2VbV_`YXipCܧPQT[bVQѡU[RP~S[VX_ PQ S[c_>6_pd}`f^f]f\ f[ `D_WY]p_`Xwrrm c_W˰e`bV_q e,f] f\fffǐff吏f p` hb1|stY$q xڲx xQ_?[\\ "2gq` opq^__}d^_^v]s p`q#^^.\^J v \ǡY0l0.n\I7%n\J8%wl`PC6o}m^S>)gU>- ymZH6#p^K9'3{D@ȑ $I Ko'l8ёvD [ 8 lC#Lɛ!W[[[Zf$1[Z@ TbrxY@ X ]ZZ\`$1ZX{ijVֺ_\0WXP"ƧZѩޠZ`hY_db wWa X_dIYw0U;|21_mv`aBWYZXVYW[wp^YX}oYEx 0yVXy W\z VZz} z WV0VZzX["WPWX7^hWRQ _C\WX0:u1 n!0uk<`f]U[T`u$1WZ\p`CWYUWYufWWW`vrWd3,0MV`VXAË`^R+ठ $Y0@PgbWV\wgRS#Ҫ# M`#Pk An 0+p ir@~r` @b-6p[_7 ?ru^X0\^[\0^ ^ ^`*^R\ \*\% *p|] R[u\ 3[la[\~*[\ RZu]+ Z* RYu_ [l_S!_2?x0u I4F R  sjW 1/ |eTC2$*hCB6( |jWE3!_wjF4#wiZLC%~\K:)n]L;*d\c2AנYCЊ \* P ~[qT` Qfb.`9W`J^G P]`l\[J[gPD rPlYg[l|2T`l`)Q lVhyJ9V |A` W"Y(6*\0ޞ*[Y )VZYt`)Y *` luXxB RXY_h . R2VP/`_{ZpBW_WhcZ<2 G0~<2V\Yd6fd6˰ G0`y 7o7p7G0W@ 3Z^] 245p0^ 1I9&+^vcE(DF4JB 3@LE13J jK EJ $WJC3JK"IEJ3 WJE3JXKkEJ|DKE@ZG3J"3@3W[אi[ W[\lDZ W[\'l[U 3@j0@ ][]H` t ]_Wpn]M{]l1zUgV[U`ndZ%{jh jh I Uf g5 gεg٠U`u\" m &qb1xA+\Y[_Y8MTuYZq;B${IdB  zb 20xgVE4#y/WF5$& ziXG6%{iYH7&|kVA, ɥqYAiwQApG@\UpXV*`ـ[~ [][Tq^؆WY^偷rpנ:ՃX\wq: YVZ(2XY]VZ\3u@WLaVtpK dHrc wp\L50E[K50Y Xc50 ږG7#X1v >Le v0~X~ΠpO0%ZW 0VW^/ W,.&%[x#WJ$`ig!dix!Vj 1j!$X]ПX0N\W IWYWS W1 [ڀ[qX^ DyŴV^HEʹZp$Y^$##/™@Qdxdx Fؒxڗx1ȇ %Ș R`'W   "d[`tI "a"Z!Bd $1 ;"1;0 ; ed e $eee1Ie T sp31{nP2tgXI:'|SVD1 gs`Nw  qdWJ=0# yk]O3% ѿ}oaSE7) 33 ^1[[FR0W20XW00}Z_\2/^Z 2]02\V 2[_= 2Z] 2)2 2Wc2VS0Y_YxѾ]V[\ZZ{a'XV'<`'V|0&X_V J'O^_ J'v  \`$`2X uZYZ#Xξ0R%+ ޝ$Y%W_'Z%1 &E &\c & &z &YY&FYFW'NH6\@ C]Y V]vi[A |]Y ]k]ti[]Z ]@0]m&iP ր{X\)c[z7fE`XYup )cV\OaHEe.E`X8uApw!V =)bW_W^%Ed`@a"W\aVvXWWpWoWiW`[` xmdX` mfW` p<}s\` }wV` pV`ss3"V_qցf`cctttI@t;vˠ@PtЮpV5 4Dq2`v10tcɀ42vVE8+ x5VE/ }pcSI</"iyj\o@3& iO5eK1{G-peY/C؂&>@YvfujfvXfva[@oog[VpgUY X 4~`gsD @@ "BO Н^ti (dBJ` R(RB_h`sRԫBDšR—dܚ"<(",fI[F D^JA^F$DYB;@!]Zgp #]Yo| a`>A]Y XZ]]]\v ¶#\Z\P|%F\ ^] qڱX[zg]VVxgX[xvsZMoXV|z [oowe .\YF\W] A__{^]z\Yy[`^sW`p53|l\L<,%tdL<1'A}ϐжWYB1 Ӡt_J5 ̑xcN9$|gR=(kVA,_րf`]YC!B  gV K Y W[X W.W[V' DP HAImQCQ ,QW X\_W_V>\ZVWYXV. ݯ(Y_P]{ Y[W%1e )X` ?,nW?,YX)`@@)!`,x .P,W]-W)Vf\_ @,Y_ 9,Y=!U,W 1 ;=YP=W (ZVA 4|;4==YY+=A =HA=Q ;[40PfLQ J"LZA7MQLMQ"G[@VW WawboZw`bi ڲHgov^Ysg@`CA@BG@XV^"BusR"NpVq ePnt|2Y{1TX\VWPWXB|QXky W`YWY^ 6`vp`08.SV^ V@P`YgWAV8UpV]~RV|P!`QV`Y / րYW uB0cWXZ?[\9`,g,QfV]4a9fjaFgajptbf \ EhMмhM0j+j gP@Щgpgj[Fi0jzjWeYz[Yzn`YzXYzpDVZ0F`t9`Ղ_^WPRZ PՅ{ cU64 mXC.q\G2lWwF3] cubO<)~hR@. ~pbYF5%hXH8_(pAZV2a\*VV`ЇZۆF`݄cӁ[]B5` c< %Z5`w7W EkZZ 6Y_5`Fy,@W[%q㐙VpV\5`П@ZbW^V 2RZ\[OU=WQ `8 aVᔆ@E& р)`qWFpQP]\]B]M0]0]1BiQ\ @1`SX5ktZ^YpM]n`'˻&`P  ݀3F< h(l0݌0/  \\^V_W_ܸ_ _+ XSW_ 4[IV ^>\^L\^YƝ\^z$dW011Z1 EYP$.oA1 $sy75pfO8! }pcWH9,=yfS@-jWzj^NB6gsznbVI7+si]QE9-!﯀o]J6#ÿ(@{֠Z^P^Wl5Vl`]~`pX[l80 l7T$eVu \XlJ D\#oئPPRZ]_@P@80v]@BP%Z_%Pu$B2%W2%P2 PZ]Ѡ\_ݐ2$\ l%\Ll%[^ l%Zl%0l%Kl%l%2$[_802 pZ[^v`a!$obr4#%][_`$\P%[# 2 [[ ~PZu@[ZZ@)t$0O5X`[XYhuf} RZDeZ^Z\qp3p[_]_v 'uYsr1%`bh]c$P:G X'v]`. uA[ VB!%  A%b0L'p )Y &W\ )P '"Z@B ]^6\\6[Hp606P6OX_6605Y__j6=Pbo0^]Sv6+@6] pv6\[6\Y{v6[W v6Yqv6Y^ 7V5X\ v0"Y %R@o@aF PP%YWpv6v5X_\LF^ZLF]\[BlAXiLF LF[_v0MEZ]LF@`bLFX"pLFP2$3XV05XVpGʲ0@!VXW_W]q;vF[WY0u\ "P'"W_7YEW^CVy]`CV\^ CV[\ CVZZ= CVYX W?05WX CVW_=CVV]@VVit2$V0EV^_@Wf00"@%$@f,B%kPV _\? _X{ g8evuV^

21>) > 3> v >'!]]ov 3]c01|ҥYVs`G`*Wɕb @FXW0.][\Z hXp@ y\~ t\~d/WģͦV_Ţ0͠[gpWWUAx^^GZyW@ 7 ![Z\p`[YkXt[P td9~  Z`l! 00!~#00"ٶ( `ٵX"͒ٵ $$,BٰZWʵcڴck,BkyZ~  0xYYPh0YZ  !YYdؕrd`oX{Sij/W7 <Y@M'yX\g ȘgТ'!XY CXWhWF0Z rՒ ՠPX CdT`d]W\Z[[][fW00 r$XP+p_QXsFEW TyhzWcivmjdfv{jwbidsdwi!Wҳ"yĉ mdi0c0:`6:R"]"+AY>p20r WhWV  $slM0;9q^K6' }n_PA2#ߍyW] qziXG6%{jY7&⭀zPEw6'ŀ uhWF5$l@\"@dR?,\V]YYQ V_aNJQ10W"@"0"' \c0x~%"\0YcY]bY\|Z|MPbP \; Z  b hVpr)|aWpX űp1V^0Y u \ 0c@FVFd3p@$YFG!R%ZM!g(a"lA#W;@g'V `pR%!C 3P Z^WXZ\ %p+P+W)W@ ;[ ;I@;W%X+p)^2VLPh:9h:0j8Xh:Qh:S0xi4-@Z $J1Vb@ :l :["52Q: 8XW@Hb0@}5HV^Y4I_V\YgJZ@PgJ*0B}|gZ]o}0W + rBVo}+p\ GYYC@G @^ GV@ @CAl@p[zxg xvsoYV|. $S-WLRoX[?QDPAw{vvYYoB!UmQABzXQbRzPTVoSzPQwXwPRvhZu]oW1PP=>vhXX.VWVoPRbu\^o Vf2QgqPgQ}gW[ofK\u `fR`jRbQfYu*`i jf)afXuPi jfQfWuH`q ``o jfGaje`u`I1uj`^#"e\g`ͱ`;`Zqov~og`\Y]qǂr)po\Y$; doi]P2s'q szb gs z| ]q \#mfw 2ksg@Q`gupdguq`g2puq"p+sbrptz>p | <:sgZ5&%zf `SF;.!G~p`P@0 p`PF/ocWK?3'sg[OB5vfV@* M7818C{TL2XWaZ^WXh%-vWXoY[iD;PXiw\owpHbiqpa_^V`~\U ~Z ~X poa;`U ~W VpX_xwh V_w\mCÀ0ZU0|/WWm"^ov; r\_]@0?S@H@Uu@`X``Z^ HZ] \[𐦚𐦱𐐦pHx ` @Y 0`B0vI``_V^svmodms]\^bA;C@MP!]ʠMA@}PM\[Fʴ@P4pA@S0 ZF @P L 4pA@ s\Wo[^[]{ijE[Wo`Y^iREqr wX^hWaQBeXjcXJw\ZA"W լ 0״@o5!B05VX=f? o0ZxgWgg0Z\Z0Z;=sN!fkP_ p=Q. =\X YZ((pVuvf=Vl\@V`v~aRfzNmsm^ V"Y[[xS@Zwp!s{=;jUH;." 'ߤv?R=G {naTG:-m}yl_RE8+uh[NA4 ui]NՀ6*t^TA1!?FO^\[+AN°*p[Y19r^'  ]}fvaZ]YoogZYpgMXX #M0XaQ@*X w`Uam ws]`V[_h-^hzq]__X '$P#&Vy # ]_\_r9A X #%0 V&V# f]_[o|K$t#%Ԡ#%4n$^]D br]^[]_&\H&&@&@&& a$Z7 6^^6]@606t 6@P 6Y䱰6XHp6W[ 65Y_]{6^[6i666R66XL6X`545X_Z F^X F F $ FGp F F( FP Fp FVW^5W+ Fz`F]^FO\\F\0BZ[YxfhoovwaCORA0FYа_EX_VW]VUV__ 'V^]E 'V]'V 'VҀ 'Vp'VY^[T]Zw { ^q!\vfa! r][1s*Ͱrk]ZsTZWw { QP]mY<[ =@VUZQ XWQ P>>!XWZ``&p]W]VW\drlWV@@W\^$3W[_]_djld:a @-b[_\*5`j9b @Qc@fZ`ufKpP`qSaZVeamxQ@>!WYZrwb wF]W7W|h:a;bW`!Q`𑹫Sm#`sXdV[il)s\1.q+0dcXgVW_ CtXW_fk8"VP+K#$#VWQo=ntXntv0p>!A4 uдvVp ptA pr}><vhZL>0tfX?0!|m^O@1"w~o`SF5( ߛzm@SF9,~qdWJ=0# vjRF:."UO0YO0''Y'0'i0chcucXtc \ c `^Z\^ p`@VoE)r@+ MAаIq@@\ @ $ P P  `^Xp "qU zYWёMMؐ5W!W_ѱ   @X`! p%^7 &0&*0I&70&D0&&ְY_& v@Y)^0 t^  8̹y0̹Z̹$k0 &x0 &ۑ锢 &]0 t]_XU\ɕ\@\lp\^\w\[ @*ЧCß0@Ʋ)@I& MZW ШZ'`:}Z\Z Zٿ\_DZ\80.Y [H'`{`P|` amllW_ozLWS\^yhD0JoY;Xf΋Z>VoowPw3`bW)*`nVMS'W jb@Y悡%V@5W0hlWVUV@c!@Pϓ8!`9Vb򑠙ۑb<2b[Z<>&/\[@AW^@A ss?= {ocWK?3'/o]K9-wfUD4#eK?.fR:cIр1Հi\OB5(K@,nq _^\o@P=@ [+ I @ @ [\<H!$@ PP#PZ0Pd=PJPWPdPQ0$~P> _@ac`J P_]]`mo6_]U@W"$ n* `_S`Y[xolafWW}w"!V B"vH#WqP -`V VYWB"gf P {`r!X}^B!$afXX`P r!WA%U@ @P =pBp!!\@[r_\ P&gV ![_Q#^v`a!$obr![{\ZA!` xSONA1V@o` `'062[_24 P B4{^V1zvS7{]]1af P LP`E1\Zs3} P 6!![X p uM`Д346p.yr_[QVW0!Z" !!Z_* 2"J$Z2 02\! ې`XYW.p EXj "Y^p6$Y[^UPVOpjFp#9KbpJDRI[^qJDRIZ4qJDRIYqJDRFBV\IEIY@R@ AgY]z CWX[WX'BDV\X[@@`_JcP_A,@R[BW1X]B1X\R,@VZupP!!q McOpXww>W`C|3TaPPKB-@Qs@X\f}VZd WXbPsv 4uiXde``ac_a}SfP3 b\Z`X[_ s 'iV4` 8iW3a8eW]*Td\f\0dnjEaniVb8eVAel8`n^Y1 Rʼ`[! ]\ؾ="^\^dpqPbWo|qPё+Вr c] vc;sw[DvZDvp\phvpvZ vY vX vW ZZud0@>~qd!J=0# zm`SFG,]vi\OB5(ypaVF:, seXJ=/#pV<.!reXK=0?{pYlpYV[[i* 2 888W*P]` 8s l\` l[` zlZ`zz }{Z^Zl?Y\_`zsl`zVWVh{W6-C]W06w?o|YX]q6! oma}`om-Xmlas6\ Z X 6H̥a^Vu*ڦ\\@l(ࠄڦZڦX覔ۥWR`XRR`oW\wW \@WX)C{RlVZ=WVZWƵYzҴ?P$PfWVd[zGdrrm}"d`'$P-Vab Xbu[w_am\Y˪Ral\(Y] `*v` c_S__*$_0ИИИX ,* _w_WA_X_X&Q հC"h" "O[] "֭ "֒ "ֶ0 "T"CV֒8@p$֔p_l ՆT֓^z ]_ 撺 p p "Y殠Y^"]ЎXppYЫX WyP}]_] Bp 4q|p [V Z^EY0A\$+hEIR zls*A?yl_RE8+reXK9'yl_RE8+Ѕuh[N</"xj]PC6)seSF9-߫pbTF8*AMP^FEED;20?c vbZS ]R %M\R"V4@;QBWO`vbYw%`} lY^lO _"-`XZWXl]Wlu Oal OW`W](p ]`QO VY]`l VY\lO! p_<"W^  ]Z &'P&&??5="F!V5`@'N&$\^ZW_m%]=m%\|p'@m%[Z>m%Z'Z+n$Y'&&p&X^%Xq%W0 6& #70#7%V_w -\V]W7Y`J6[_s7XCJ61ؔ0]`p[P$[v7Z75@5]]W4[p7@5ZpFpqG}pG@% 0Fp F#A HGWF5Y0oGXoGðoGoFͰ5X5WGYNGXG0Fh0F<EV^N W] VXp%WwX %WW %W" VY^ DZu_0 fWXfW `fWfV2WlfU4ZZIfUPAVW@WWS`iRYLgJ`gP`ifbP eWXE@@Eg`-v e mg$mgpduYg[g `g@efyfVf2`,e2`w#.wW vX'v QA?wpv YwYwZYwY(Ywe[v[eZIvwJ *v*8%uB@ uh[NA4' yk]OB4& [hQ:# }bS9~qfZK@4% |hT@,xdP<(@d@,pYVV\sVV] }Pܱ)W[ Sy@eqyQ,X%Xɝ?ݝF0W W -qAȠIUF0iQ= [`@mz  Fpa vaҦ`R ȡX|`|i@գ~J [x ;p@9^W $-P " g`kkk YX?]ZVV\ C᱗0x0ƹXǸtZsYV X[zе z\Vuwe i~WWu +iV,Z" …u\4uvwZ~P bsX/9 G uvfxX xa[}4œ@[ooa{YW^puU\^^ VVkd[WY@.X~X||sZ W^90>Y'0W] V@W[K UYKUJUx`hV^Z9lXvl_ZWҮV^< J[UP / lZX_m Zt dXEXP~XQ@VWY`J=`l]W0mJWPuPKV[X  vkkY0/p = " :0kW^Xm W }p@|PP;h;p;0d^tdXn%dWZ 19@$ @dWlA\#s]pCAt`L8$znbWLAM &t[B6sbVJ2뙀bE' z]р"rU"[_}7 Y %h 9V|ZY\u^{ {ufvjvwrup'^u3qFVO _(Zku]3BZ]O_Z]l }YkuY3BYYO_YY}XkuX3BXl:, -)XO_*O]}Wu[3B&3 )l3 j)[O_W[- )!=B63]_VuZ O8VuX:, BVuiWnB )W^63am`bl0hYw`P;1bm?` HYD)@2Z;M7$p>;i9Y<M7p>;9=<9Y<M0ס\Z{ijs\b0^%\%E@`E.Q7 -WwPl[W^ `V`huffp_SFW``oae1i@oE>_@ufdi@y[zW EWJIp @N` V V VZ\סZ?[ojmE,PZVbmf}`f0 0P'S% -ৱwZ\q@ (32YVgװs]wW{Xt^`y3N]^QW\Jf]ZRVX{W`Y]Tt`]VX`PN=UVV V !13#XbX*rpFWM `mmXnP[XQW|QIkYP^2mN~Q HmX`VP8.h%e Aaff~Q moe `R `aWIM0 dW `WW[svXYw?aYV eY ee{VlsZ{agcpCFvFpbp BP `,'5 D''h <\^O\^$)\^5tFD~cH!sg[OC7+?tgXI:+ yhkH9+Ul\L@2&qUF;/# jU+u?LTC1483CN8XXZk>f - 8}qsf- B(@XXYV]guwL;[*W\@`EB|YRVQ\@07 ђWmf ¹W@р2RisrYl\0ZXe?VYl_'r'GAd}ХPXV\b[bZ{Yi{Йd@ FWdgZg`֏{Р!`w1SГ!xЙ__\C__[ Z Z  ^o[#_[p`Z!_X1[3_W1z~GA_Za \ [ ' \WHx*G41V]G 10Z:"G=x*H" @ OZW Z; bshGEmXC8+}raPE:7r^J6"snZF2 {iWE3!zk\M>̀t`L8$\{A,p@{?_\s k X/@  ;P %A9Aq O0@M԰u;PI @ 96_AX ߱  &0S V_> 35%p+' +'0+'?+'Z*>+'Y>+'+'+ 0X^k2]# 3#]PpX\_P***B ,*poFC #].1$\VA K]7]>Is\Aq]\BMq ]]]> o@+~(Ó\U&!&\# ~+[b)ca2` [`a}W?a?f aN`*b`2`[^^蟠mcѓ[__&+!/\)Z^`PbX@` Z%fV !0swY]^0^YdYV\a! 6t TX[os ])AXCpFp.NFfE|Z}(V*E|Q$}(?r }( &_HFt`L$p\H4  lXD0_ g~jVB.1`zfR>*ƹvbWG7'рsiI6#p AtrVVv˂`Ӂ؆rу؀ 7vWW# Ԁ ؆WW؀ɀW_|XVozjp}mw`sBpΥ"wTvXdPSppvgmfw lu`os`lfsuros`blgru~r`F"l'd`P6F.g.ZՐ(ɖBՙ`D@Рı‚{ 5PYdXw6! !ǭ5ۭE!Qcp?Sg1\}4[4CZ9mYW@߽̽!X]̈́˼ $/W@HWE I Q˼p͒R0A '!!_0  5[7 R11d1EY6!v1m܇2mܖQ ݚ1 1ݾ1 !T!E[ Iq DPqc!] 3Q" 1 Qr!]Q2M.1a@1uQ!r99 seIGyj^RF%zgTB4%9?xeR?,|hT?@,k{uaM9% ygUC1 6@d33#WV5X0.iYų0" > / CBb"]Yg1]¡ f!01fAWA YW#}#bYVvfaĐv4BYVL0VVX"X-@W'-pP:,!&,VA:,&, & -?-Sv-: @`YV^\]V] "]\Y\qOb"Vq0"H<,=?=S; ۱'c 묲!SgǽAXX_\Pxp OKXW f V^at`hW_d_bbX$W !$W_ 1o`А :$fGs]X ]W}XXX̒m A ͩ%8';ñVPذcHO cOt݋1c1cV[}V`  V\]'# Zk )P-MQ`_RusR:R`"W'5` @ ps>@ QB B6r\9Y 9B$1ҡ D1Xlq` IWV^ sf_KI zk\M>/ +vbN7&r^J6"|iVC0 ti^>- ̕}hT?+r^I5  WeLB̔B M^\g7Ew &${{ Ww r# 6w"66VYw K_ t# WVvw"A _Pw`$-o -6,-I A-JU-j-#^[8vgu/$ ?6q^ pK]Z;|WR&&R##Q(rRI :P "]I`R.4[ 䎫&M3V4\]V06q\\X S*QHƓ26Q7Ҿ7X9X0U\[8aP`Ad0Kap7J^ap 7qap) 7a0 H0 7a0 CH`0CHra0)7a 0|H` 0|H 0|HL` 0A`d2V0ف\XhУLR Mz!M#I[6\57]J\_]s]B6]_#\ֱ#V߇]6 ]]#\6 m'mф\Omcm6 $wmJm##P{26А 5ag! ig i i75Аy@w:ywXy8XyL0d2WV0{2KR![ZpRsX^ Pupȑ[K!Z^] tZzKeLJ߰hVD2%1^J6"nZF2 ~jVB.nXB0~rdYMA5)p]N>.2B ǑZXJMƒY9L "(sA#!NՒZJ$0W^K[z~j Zh\\@+dN;3͐(m7;B͐WXh?ozuİ䨕KJ ZV^VJא8~ NH61 [ԒW"V"\[#ZV[~jb/ӓZ0FJW ]I3l3;ZVpTX`pZEV:CóLJ}}4uiX\|X^[|WۢW]_[WV]\|W]|_ZX^/] 9\Y[ 젷sbamxfK/_!;IYM@ |F|ܳZk˽߼Q#߼C#aẀkͯa߶Gp ˜$̃$ݯ` F[ݿ1G1ݯ` W $5$ݯ`Yk# FcQwa%\iy 9‚Y 3Z '"U@R U PU PCgD F" p"VsuMK paTF7* xiVF47}k[K:(Uan[PE9* {l]N?!}n_P2#ܿudSB3$̔⁗p]p)6Z][9` 7p;9`7!1Y9 p7W[``w9w8`9 0A_ %XZW7Y,7W` %VJAr6 Gq 0ԑY_)00m5B])phLsW ]YY}bA.Wߒb@["~E^D[YE EukEu.{EX DGBE3Q[ E#kE#.{EC)8WBXQ}Q,{@TB}^W\|SDQC DQ U.{DPD $WWB}MXrW][^YP[f[ڐ+maFCeBW ]XW__ d^gXgg\^\5 ^\ gI g g ޛc\\f[_a !+pِ f[p +]w]w]w]wJ`cW_ fW^w] a`_-NLߪre[PB4& +~obUH;,SsfY_@, imqvj^RG<1"reQ=)zcXK>1$ wlaE7-EED;20?bh@Aϡi![^Wv`a!&obr 3QA5[ Q@<[\]WУgV_ q]y Q\ZY\\4Z[~$g[oow?]]^ 2ɐjD@ Е[`ޕ\]\ꗣ ZYkYĔY\8Zp!PZ~$[Z]]pg@猓Z[ a[ZVvAಐ@ƭڭᲬ2@-*ē3XЈ3b`_+ l^YX{vp\`Б0БgX]··'V °QXPYXp rt) 3OWbW2[0)ŧ^P^W JW'Kł0d!¿q\jt H@nWQA-n<1[V7bK @:QŒJ [`^V^{O [V\}\r f , aЗ‡\ '[* @g[4IZpDNA`}fq oRq oףq oVYqoցPЫ^wqoI*SYPװЗ P0qH(pYqVJIXPSqSVBզ<tGԦn$ W4}Seuz3hKZu1`*Z`t!`wY@_\`moZYXJWe_,_Z^mY  /Z^% _e=p1]R _KA]PGV`2~A]c@vu~v\^WgVӠ Y[p^:p sl OMt`R@6* 7}hT>)Pu`J5  qbV8+paRC4%qbSD5&߀̿rcT6' pAX743CPg\V\YX ~\VQNP!`Y2uM3@A0A@Af!nATY X W]Jp\Z`XW] Z⚰Se0)Z)̰'e"@)80@)X[ &V_v \|)H|)b`|)Y|'^0)Z#)wP|'ZmA" Vp'0 909P'Y0 m'Y0 ?9@m'W]9!pO^8[1`^8({9;{7V99[P89LQ Z.@yC^[ GCI0JpI0X^^5@bG!`WAV"p_G1mImI;$\ F\0P[`AP5C XE C@}|gZ]o}V\m+EVo}9à,&VXXRu"P(TQ"WP  PQVQ@"PzVxgY[xvsRooX[|Zj@Rw{vvZu]oXBɋRPQ pPVPM\ XkYYSXYYT- XXXSX,Q1R P:QdPXWVSXWQ\RA PeQ\dPsRTov] `g`\Yo ǂfL`g`V_`o\S d[oiܟab Boi[RZ`ca (gLbJp`^mfw]`v`)[`@[__>Voo p'6B_XRP{a}[u|ա}}u|%}i!Rr uPN o[G7'wgWG7+A{m_QB& {m_QC5' qcUG9+p]J7$퀰{]N?0!B 33@^X[?YYZpXX[Z ^,[ ,1JZ 1oyA\Y^Z@ou]} VV3 nXذ R4\i} C[__pХB͐A ٖ 뗗P&Y]&iuQ,ؗJ eؗ)pL pi p Ԑ lؐ\[@wwqV0 @ےZi6[Y4psE^ P&FP*PWlPV` P PXX` H I`PƐI>>ǁƐ1 FAZl\ PCZ\pg ZW 1}1 ssAZUYFAY^y 0Y\{ij JY Z]\YYUXX %W՗X0Zיh ƐXwuw ׍j@vv rٓ 1 XY s\W\^Z0WrK["@J `Y`u\^&P4P4 `~5[Gu\lE@5Pl0u]Vl@5YuSYl@Y 4Xu`XWl@ 4WuV[ JV 4 @VqA vr:qH0\WVWXat}3^C\]p E\a\G]0 Y Z0W.sw_QOteV8) uf;H9* reVL>0 }l]N?0"|m^O?/!|m^O@4%rcVH:,@d@,]SAY!Bt],H v,ْ]e0ʰ'Z 'Y:q]Y_>`RV_= _^Drp_Z_IP_[_0_]B 4PJ!YZ~WbW' H_@F _F@]X PB' _P5! <'<'YLZ)Z<'!%dQ]4.H_4'q%h@J1%X "&E(0 @]@W@z~a |`~jb П`k~~da2V_%3p,0P<.#fPXXkK7W[zZ8qK5ZY x9x7 9JPx7!x7x788d9YK0/2eY%3,0VX$P1 #AI,G!,G,GBYH/2X%3 EWEG!K5A -DW ,E!.G'GEHIZԳ@/2W%3 EXZ|I 2 }{4w[[o" D\owʰ vow _Ua_^V` mV\wPU mVZwP mVXwPqqR`mVUWwPWVwPT_am`df;_P[[F!XWi [$W!&g'WI&gEWbhqhip`:G iYg iYg iYg yZ g6 %y%xa Cy`7^Y=yczcu}1}DpF!Z][x d!*"v RPyj[L=.Ԕ@s9[L=.vk_SF;.gxiZK;)kp_N=B ƹq`>- aRF@ף^X]ye5PV]0 '$ ^ )W3\^VV\X!Y^0VP\_`_z_}1`V__ _V_^У[0 }`kWZL DH,AXMӐMN }`kMī\ī[ī2`ī0TĪ? +Y- raP?k sbQ@3udZI8" }pǀSC6*׀݀|qeSG9+p}pgwm\^^V V $  z!gwYY`bH06vi_{*g`|fw m_@UPoҠ@l @!@$ bpTP(^\# XY^0bui_V@-Qb S*DRa`}LpuWTQaVW` `hXPTQ`h # 0)!VVoP#&YP0&X[ ;!#&WP# 0c!Qj#r1 UP__ViP9{_^d Y_]^| \u|rX"nP_\_WVw0| [\XwwqVf #L#["ZV` " Y3 ![% !Z"% 5P!+YZ$64X lpGwb5n164EWj55Y1n15.{5z"V0<'!V^к2/V5 2`p!!7 #d44 @!_|,_XWZ3D0>IVOJ\[OJZ^OJZ?E^7AJ&IVJ JZY DJ H 0.ET Zm@ Z[ Y~@=ZY=V\Y_YVR pZ# pZ[I$pZH pZ =U!WJ ESVtZ; [VYCV^% kJ j\<+k jZMkV jJokV1UF+d jZ` }4^v_XdP_^9b[ ;@3x^][Ű.^]ZŰ*]Zg^]WŰuWg*!uVŰuV= ]` ^\v|XcqPwasW\ epVis_sd*ftdnqps}p,prd|Hp\!' ` [`^^  pTRn_P2#7yl_PC6)E tb]>,zjZJ:* ڍzjJ:2jWD1 sfPC6_) d?pB,9ɲWJղV_э&$@ Y] YZo Y\ 'ԯ|=V@9JW/7\XY`W cdSN ZV ZX_^r mz :Y\U[]˓U\˓[˓WZX Y X ZZUW DV DY_ bW^X@2~\[[Z>!`HrZ z@u\Z]xgYZzY[w{mZu]or9 ZVooaMZc\5@l`W{`}bruf] VD Zx`]{`WkR*h;7f7 7`7Vkxhb VXt Xb p- k׺wh׺f׺b׺Z ׹w|Z =D0 07  Wp@CwgY߱+`sExhT$˗I"RȗƷ ˗ N HƯ@ ۗ rN V`u$OۅOۗON![؅I ۗ N va\`$"Ќъ:" Z 0I CAc6`W[aYs`x\a[fZafYa{fXafWfasb$o|I7pWlY`W olW\wQ >\ W X A .Q =@P. hXb]obXXZw{p]Ykq_bsxw]ZfkqtCp!W"T``\suVW[fq_Yoq"sv pUS zl^B4& uUK=0% saO=+gqcXK>1#o_TG<1"p`QF6&~mbTA.$ )\B{_Vv_qO`^_\\o[Vbmxk! au.[@`v! l`V]]{0oP!0\~cYo[]_[0k]­c!ZV\_@ [YwXl]m@ 9\}A i0 ^XP @VXZ/Z ) WO\ [XN(0T $m(m(!m'"]'-"3$[[ DZ[j0Tq!Z^ &YYUZY{~~dgpm{ BZ  [P Y]Y;191j YS21\7l8l8"\7"9DX;\X\6`7W\87 h08Z;70XY[Z$%@Y+FU+@ P4X[ p W}Y\ua_j cxDQ dK0MLQMZ怽Ll`@xAp~A@tEpB [0 \:[@ <\Z<\pHhj~A XhBeZB0\[@\Z\Щ@ Wz WZZqSV 44W YhCW X *`Wq@zxgo|uoY;[|ODd0\Nf0oX[qbf @Nf@za\b`|fwWV>auba`  FCVa egePDV]Ӡ byt\x>0w0A36q0=wh0KxZ4RqX0pYWʂuVuW_ KP]\[q0YBiXTthYMA5%k]OD7)ugYKc1$teZG:,xdP(yeQ=)uaM9?%p|3WW- nQ@;uDXX$`p sW\^V Z]Ye1(:]WPO;0yIvpVX^̋~NApbPVSW[W Ɯ:ANWVYPSH b zPڂZX"Hƕ Ŭa!٭AŪ 5! b9Q*WpP>@ Ց $Q Q9I Ab ݽd@*bDWoVmm; g61 'WV_?Wo^^Z}qW *`ځ a{|TVV[10&c0pYDpWiY>aw]{Vsimۀ~5\WV]=030UY { rg ys{ 'gDuDW,P+@- AFmi1Tg1FiguVr\Hp~y ~=0fawАQPfsԉ!fuђVֈ y $=0 ֐Q P Z`]fsvqsC@Jdpiph`SZKW[e od oV][f odm s ab sdjmFqVbstmRf 1`W"V_bYoY^\Z k*_ҠVg Q_p@%^.]b_W\OK /!/Z N.Y @ Wz0r @V\p3A4X]-{pY*4@Vz4@&sY)W xeXK>/=eXH8* |ocdE:+ Ϳum[J9+wj]N:&cO@1"?du?@?dDQB= ~B \wqB2zjB^G@ff@dp`@4@_\ aMJE13007"2NTRANSISTOR,POWERTDCCB:20jHJ{ף?g 5* DISC OFFER BUV46 *2N.`/_^^]I? \6AAdphu?dSRYhX]bsx]Yfw{oQ Y^X^{ijP Y][X:0Y}O#\^X[Y`N$V\WMY[_VvLYZ\A[X\1K2#Z0W J<# g[bI#YZPH y WVsK^Gy ZW^vF<#X_\s$XE XZk%fDYW^Y}XAoo{iw[VoC#WZ\^dX] B<#V[_}H[A4V"]B@"XvdWY^Yl?XpYZY_>J3_^5 =X^ZZY< h0\["e;;3]dc:p3\V]( q9"X[bs,8"X[^[`f!7 XZmbW\a s63Z^ ^X[l%54pp!4"pX]Y[YV33 [\Y23X[[Ű1p3XfhWX_dC0&Da@d@/"8p!Zl].HDiR@Xu]-3V^hV,FlDY] `P+d3r*J2WvvY[7[)"Wl!]("W_[['C_X&&DV]W%"@@V5Xp$p2W^11@V#C]Y[o["C\iXda!P` C[op[Y\_^C[XWpd2z`CZ_]T\U[UpPSZ[jZ`P`@m_AmXgWv塹0"@Xa Yp2WX]' ?P<"\Xv`YlaaaPSWdgXP"[\VX] g_fdZSW0C_qC0qQCVvbXXoSV\ZWXQ2%dXq CPRp%dA\ٰ Ci#M CZ^V]V@ <"Vo_Y^PXx0 d{pl T"Z|pYMad8h^p2?`X0 pd ^c\A\ ujpP"\`YYbl`wVVk"V[^pV]J2V{pL+s`^]0,rY?b 5@~bRppWYX`sv`lvYRp ipdo^YM}sVZARp%tdjvbrggfumoY_Ypuxravrmfwft\_]|9tj&mcL@2$vk`QD, G{`R@/uhWF5$~qdWJ=0# oW?'rbRB2" bmV_\`fog0'БX/g/WROgV og / [W?`fKᔒObV V blv`zX`[lhuffm ΒW^Uՙ͐\@Fՙ֘E\ՙe@חZL͐n uv[_ NV{Z_Y]ܧ\ܧ[ܧZܧX ޥW X_ 7BpX\ =R[RQk ͐V\a|Z]ZlzrF0 lrF0Mlꅰ[Xl{߹WlN@l︐q#" wkcbbjwhvvq fshvw #ppU@mjp s̓]l ͂ ͂WV lmrhƊ{jfwid bjWsl~oWh}jwr_`CXXvbuf{vgfbj{h@ 3Dd wa wВivsvidobbi!dС m̐ijso`vwpbros`bwum`ay`]zi`Y e1biXYwfqW[`WYZ]`X70NV;gsWV 0 ygmvMOY X X忠XgVQH! M|cG7 bG M#dm0q1bfmZ\]X Xl`fmfbwurpjbwrrmordxmf!bffX|_Wv]~i[\vY@f>0\sdf]WW+/Y]f|y?EX{v[[|W\[waWl\^u /X['o Eg|`/Wx EW[E0V_o EV٠Ewf>r@`q`0durolrd`l p syYUyjZOC7( |o_O?*Gzpa_Hc% sdUw;* paRC4%˿zl^SH=2$ɂufWI;,MP76 `ZUQ X8  A  /`ss<-[t-u[ Ds6GY]vDY]sbX[vDX[sbWDW6VpqZX\rp \Z_J`. \Z^Wa(\Yu[#Xv}W!"[b,#a;5%`5 +[_$[__M7[^ !| [\pY%E[ -"E[X[Z]!&\P'! &P~'CA &=`X &Y%_D@ 7!7@7`q&@X+?7ZD@?7!?7`q&W!{7!{7!J@/ Y{wZo_\v$.P.6$`w#` 0+Z_pvw1[[]V2Z|0 2u@=@GVI@"!ZZ)1Y806Cf0YBFUPgYQG`0 AYhao arO{Cv@lzBGazB @"!Y_ Y^`BZ`B'@+Xz`dY )Ai0Ho@X\`DF!AːZX.`X!RW P R%qt0`[Y}@W>@NPQVP A5\@IzlP P!}R@ RUX`0WYQ5WWQV`d0PkQ0\g`]`i[ ][Z@im`P(̠`{RW#Q`T;WWp`UDaW`P1sP^PZWooi`mgifjhiwaf~81Wk?ZWh`?YZh ,q`VXh`W_@W^Zph|L2W^Xa`0W][XoZ[]\7EW\p>@C h eHPV@1M rpa&!c0p" mWazQWYVPqtYX_rPz)BW@ CWV Nvq @ZrspPWY3c0q:pqVuV q}?qPdiZX[L=.7vaL7+uM`UkWCa{gS?+wcO;"xmXC.mXE:)fu?ZYVXV[X\AZhRY@pn n" Ps,+0VZVʡQ8PV\` pFV?[]VMRKiW'p[Wk!o>3E悙W Pw?ȑozu4 %[AFQ%` P5EYˠ 1p 0 0u0AE*-02Wp˰g%y oy-pZ0ɭyҒsmДs -QYWs`dvW|WX|woۊV_nYy%+Xn=gWP<d;PPذ <ġQUP^nX6 u ͉s $,P@;P̯ h>@ |,105um͝s̜;P̯òDݥ!ƑV nԵxv+YVV12̊#`oY[yYKPx0xժ;P xa np|pxHZ c*QI9aN#e `2+`pz1p排 Q^}T #]]7Z13D]!_  6  p   _9a9xp  0$f% fa f# npZ r#  s]_[Yr^J6! )ߎyd?:%K}hS>)islW_B-[F9,}{]N? ń[F1AdHrA\H"OqZP@ 'FP]QG71! ! =3Q",RR  3 ґ] @tOrqbY\W^c%rƠ)`[mm#gb  ґP4"2!`;'q$;'U ;'q ;'; YP Y]C]_uP'qY,e\ -,j &YE%X0E"!Xv`a!3obr X@).LM5:Y UpI=WL^=]8X @a 5p0< <,|p9X[D" 9W _P p7t 46^ L<^k /M^ DM]2 YM* nMQ M\AZGJTM !M[ M$M^]Y!=Yk+] @\YA b8aR!Rj]_q]^ ]*A ]?A]TA*]^A][qI/V_] k2p'm 9aomV lm=l]XUl[ql[;`W Ay/qZ^$/q7}Y0K{?]s}[\ 63 `ae5ur p]\\p. g\ZsaL7%#w'+wk]/A33 7tdQ@1 W[ }qeZG<*0weSB/ ЩvdRA)?MSM82?C51ARS݀*ZX\2Vs%q T"   W}Y\{_pe 4!@W\QvQV^?x`? ua: Qᐱ!_НX t Z uQ1p:Qp&KA_RtRvZvT /h:RhK _ ϬZ R~W_ ][~`~bgpm+4ZWXs/TWs^ 2V~l~dWlkvzUjvzivzUhvzgvzUfvzdvzbv{avz`vZW`   /ǠD _ƻ<2 Ѡ`?V\sҐ[s:#4BPǠV;0'Wx~/\[[Zö49l[Y\nZH3 NgI v^ ,AjIԵ^  U3#s0Z YX׽TPX.Y/X-/E.P_WV[tZΐuOttdp1`nW](P+3+=H@0D+9jN`+з su][vi\J8&-|qbSH1ExcN9*vk^SG;/# {naT:.#zgTA.|obUH;.!TOR,MO7[WX (!!RW_^U^Q]9(\X(@(Z1(Y] (X[ ( (VYu`2j( . "a`_[ (V^ U@S[^ЎY V[ UXW0.&p.&qV\XVzZ]xg o|uZ]oXV|r[Vw{?vvZu]oq%YuYo)XuX ` &p#W!Y)WV"\ Va*~!`0V_V_^:9PV_]?46JU@46[146Zf46Ys46X402[!4Z`2op4Y3Ww5Wk6_4^6]66 6Z6 6X6]6`5}9*va 0 ~! -eE$rDYW]o_]]] E\=0(3@@m[_YW[^@Eja EX_ b@E0EW]P0@fA[@@ TV@@CPS\D(q,W;]bГB.0U|0@ E|0""4`S`#V\`RVYVP*ŒT3aVbulKVVRQPN[ PZCI cI`~bh0eAZ+!rCFar@NpPZU]:Pc]b8oÇ``ddg`\ZAM=b\YdeKX^g`B\"Cnp`Lw$LwdZ[]@1JtV_ZZjesYoopCaZkCOdp$C.pqdd)YQeuW>qdvx`x ^\|n`RB7) whYJ;,- Sl`O>-] ogXI:+  ߛl]N?0!~pbF:w&q]I5 IODE, \V\|R}[oaA$s"(X~06XX%@JI6rJ,(^f@\VwZ\^}kZ]ȖYY9ȖiYȖYV1ȐWXC^_\VVp\P @5XA~ OYOXO+ AO$#і|addBv ҧ#*Ve`]ᨒJ0K$ c#LQ;3q;A`0{ rg ymuJ0gmufqmJ0 $ʵ$ ʵ ʵ:Й __Poo _]s3dC bޱYF;r@'M'Q'rȒe`r rJ0$6'$ȰЮѮ: 6^__g~[\}Y\ua|m/vom\u 3YfA>q#PS>q|`tv!$t KaP#Z7Ù# ңҹ|`[^XX HsC[]][olj֭ZiYXo1W3V\_3F^3 F]3 弣EĄтa $J0 KaPI#蹰a;~Z Yh rZ XVh# rƤrt` op_[YAXI3XN5 [~/p7Ml v3i0?iP[]#^A Y][ [Y0hs[__]tL8$p]I5! mYE1 }iUA-ɝyeQ=)q]I5! ۀmYE1 D?dׅ?_+Z Y c X W P YY '5F0B[ oX=0nX@XH10 Y m   W^YZW^U@nWE[7-P6-[P$^--I - -T@-_A^XW i s"XK^n 4\2 ) =e`*<[*<&;oaf=I z=@ = ` m+䂃Vp*]Vwd PFvݡt]{bh0(_ZL P\]L P6]^v`a !NobrU X XW[\ZZ*[*/3 -Z^f~~bZ=Z`_~ U_} WMaY[k~~dgpmMd Yk'Y x}3 x @x"p'\Zb ƤX\X@'X"äXˤӤXYoYXoUWb0VbP 㥶CEsZ| Y|X*| W| E \W_\ 1LbǴOӻҼW3`ҼV^ ͗ QҰƲpͱõp߲tUgXU`GUhͱUh߲B  PW_faeӤWd  W '!WV+ 4tӇ3 Z ݫ܀a  1ܼaCV0ݦ %blJ$tmق?TdTZ`ujP@T;ЂTUڒg+aRaBm!M!@a bb@=AW an!s^ a_veTC2 nF6 ubO<.#eJ0 th\KA5)o[G3 kˀC/2pAq^W\swDoZ pA XDnC@60D1XQ @6QBXeBXAAAQl ZM0&ڐ ,Q ,rH-q ,r$p-@- Pð{^WXl]\к@Q^VZ`iБo^VXW N# "Ww$Wl&k3&p#吱 !mF^O\[[ؐPE?{ ^a#2O0]IV5\a6pa0xgW\zW\w{mZ]oV _Z`A]]WbZ]]Z [5 10.]\W [spr~W XZz`b]1<Z^_[0V~ Y1dbmC]\1@^D@|1?~3 X WWV10:B[_ZBC[IE01ZYXZ<@ ]ZWvfvyBoo2ZWA @p]Zs~f]D@GY?Zo o@U @ @@@@YZ@p@@@@1YY ` C01YVA @M`?@V/[ufW`,TUZ4T yK2Wb }~B__i_.\J2_\02_ӠR_W]{i:2_V|9P9PԳ \ް0_VVvC}C^w[[oP >B^bh0^_^{ijа]{wZoW_ZY\˱г^_X*˱ HW˱ а!_*0;Z^^[ d^ +>#^Y`sªP H^^ Vr˱а!]^sW]xYPj^jź!{ \\0^[Vb&a0[\`3^[])0ծSa0\)d ka 0[t @չP![*0 .0[rjop.W^S"#Z*0@L@4-`YAӽƕ2^ !Y$X@!Y "cfnb= I` [Z I,P=VI;1fC`:s0*r NX`@ns @E ]"d ?SI0 C!0XV"k!"sr ca{iWH=.})/o^M<+ s_NB]mr^A/ ˓yhW5$ϹziXJ<,ۀsfVI</"=@ ף=i WX[\ yZZ P:`pE^V] `vW_0W^_`]]`\[{`[Y`ZWaD $ӠpFWLTV_jV^]O\>pVt0~Pװв."1аƐ]\VX]fvG&VVQ!W%[O#V&TPQ!g&ZO#V&Q!g&YZP" V&YZa"g&X\ZP" V&X\a"'RO# '`#g&W# V& Q!7# $"7#"7O#U8a"V VumfNёP_gt1P^Wh@3p5]_6^鰘@0ØёP8PXW X[mpgW#V|`1 0 C23W/\ XV102p[4YC 0 AB av1EY)B@2 +BDY&DKG&@RXC_@3WC KF@WD_FWBFWE CG@XCEV_C KEQWDF_EV_B@2VOqF#` C VDPWD V]1 EV] CWXjRLWyPXC_@2S]?p%^x 5T 0,!V?"E$V[Z][Wl;DRVfX[WYi{ZXmYhPj\bj[PjjXPPRYV}Tu`{|guhhx`Bu`al{hafW]Wx 8#P `mdVV&DNVhh&%%gڰp1 7@2cXmg dq [Yp|CKp%QqVvZ[OshwNthVvPrVvV]OsqVp NpW^ еw_+p \z dbvk[K9'saO=?QqcT) kq[N@{Չ|obUH;.!xk^QD7*tgZM@{3` ][0 ][{@ b\'^    %C2?հI{i{v{2{|IӠR 6 YI   R Z3WY}2X_Ȅ\দGZ\YZ $ ڰ 0U WW ^0r],\]C[[0YW%4V\w`V\V\L{@,!] ffE#v 0\ZZ{@A\4XgG"\X[omZBVbﰖ1 F#\W\WX,![s{v_o [  {@?0V__bIV*P ^[X^>%V{{@z1[3]ZWACZ_ 2˰uÝ !< A~ZV\_qZHVYZXIy2  0U%%%%Е%%%AYvjVYf૳HѵPH!Y_Z^  pYXY Ԉ^Y&Z1YZMdvad1Y_^@p y EsZd ۥY\@ P]_i]`}]ZhVW^^ Y XR ji9W[7jPx7jSp7iWWgjwp7ij`7hP^Xl^p*cAd]]@ ]^f][He fR@ f fY^e fWZeMJ\@^v^v]X_u^v[D^vZv^vC`%\_vs`v3_Y jt  fdxbN.?mbTE=0߫_maRC7+ qudSB1&g[OC6)LRC5&p_Sΰ1% 2= W>d>=aWYaX{ijwf Vam`bl/>Xa\ L L`W[Rðh h hU h h hh@WYuT"hhhh1hY_LY]a\aIH >X\A Ұ𘰠@?,B(1BWXu T2KKKKUK K K K KhClu`os;gru~PGXb4pc W\ ^8q`¤@ pWX_ZsbXc` %Xp>V[^(K  pڰ \20Z0[`gXg @:T*^8ڕ`}|g}Vq,o}m@N0 }V?0ra:\YF BqOl\Vae!񥱈eyO1 0slge ~hR<&{iUA-?s^I4a {wbN:tZM@3& }pcVI</"ymYA6"%vaWXwUV[wQ"Wv`dx/X[`'"<bh'2W`adaX^aW[ =W`9 _L_ _^@@c_}@r]w^# W<]w@Z]wcP[ 8b P9%CA%Z@)&^Y)&]@)&@I )& )&K )&c )&X0)&`4)&%Y_&`&P& $&&&S`%Y6^6V\%X@ -6Q-6]\ -6\Z -6-6-6}-6-6VY%x636]YB6\DP `0 KKK1\ljwXgK6Wg)@\VA@@ JEpV@,FϰV}5B'@ADGA@@RI!BZOLY6AIPJ{^BdK@@L!B POK@7AOKs^BdK$@@L!B ]BOKh^BdKDP@@6\0@`]RK`^BdKPAOK`!BD]6A@>G4C 'FDXB!B'F 3D k*!B'FX1F .k!B'@\50[&60 ]dZhkh` ]`^VqP#Xe`7`+ifYadj3phga `\`@8 m`ʠg[`dh`{q)wYb?} r)wXggutqeb,h``L\i[o# uVz hӺqrq pȐR {hf_g{m[I>- !ߡ-k[K;+ C}ncSC3#ufWJ<0$ vdRD8*zn_SG:-! _[I7%CMOS YX:_9^0Z0RpYJIʋ "a ⰊWx0܌]\qZ'Y YVv`a"|br ((0Y+WHF`o !@_@}oh[M t] G[ Ј@Z ɤY[ZէՠX0 ǥ^9 ե] @ W? w_[5@=VWZWJQưYX__P e\_Xd{tWht[_\i Zb Xk tYX0_ ӶC߷gX߰X\po ]s \X\[ /73X[^ FXX-_,EW`b1 acV\, HX#_ߴ# dRXv`jV,YYF" !2/4X`mo Vf~~d ga \ u 9'd 0o [GWam`bl6W]) qwdza z\)0ԡdΪa0,W[{ij {[r)dWaZ)GdpY)ӹz@dHa#zҧ [ձVy`u|Bp st by p)0:rXVZpYa pfX9\\VdZ Z W [Y`7`V\[ZY7XB H,l `8aV2 + d Q0b2X \d o \2`XZ^p ʲXҰ Z^wXZwsv_ igp^L0" '5m_Q@6*xj\N@2$߇wgG7's`M:/ qcXA+ zocWL<, u?[WX_Z^` W R [Vi tr[V_v %r[VZvP<YUEXvPVv&`W Xa[`]=Bxib0@ `rZ@)ߍ~oQB3#znbVJ>2&|p`P@0 •?>\V_b3`" bh\V^bHP0 -'0\V]vJ 2\VZl4Y-b X-B VF0<L P JG_{G^H>`Y`o\d.p(𔷠WpPC7X77G[w]^W]W^[[`;VZYW^Z\ ֘\С ٠G\Yv\ߐ0pl[H`ڣ'qa/q0 P\!N@z<\zGZX@JlD`_$\pĶVV "Ѳ׹.0Ѳ ׹K@"Ѳ ׷г ͶI  @@ɲ װYY˲c x1Ɇ1$Ț5D$ؒ5 $ O$ Oؚ o5 oEYШ"   bc[b c[#0k;FXZ %X <(0(wZ SY 0p<pؓX:P Y拠(`05q@0@0ߐPR[ 0W]_+ ^[W\v9 \|g  62 3V4I9}P&  Yӡjҡ4 o i  s_ki}{WE3!%-~n^RD7, SwgWK?3' yw\NA1%cWK;+ %paRC4%wh\QD7* OP AMP P  ]XZ [_i_]P tt+]Zߐ]! PXd)!$skPP][IDA Is` jg]XVZ2]kpIUp`1XW"U\f'!I'''\ I-]Vi [VX)`]jqr| q^b1]VX` X[` e \|Y`Ra2\v{8S\vQVpP&Y!)@ " s` !s! @\fwbYYXcZfy 3WY#1i `^P n1>0X D6D0!^^_ufd D0 `3huffp D5 \^VEP3^`'B\n tбCaE4ա `]D0!\\`_s 1O#\C -R ϔ@[1 4 @0[Zf|wu`\Z_0@;`2CYzc;@`5@4Z^Whu}Q"[@԰m3Z1 ;E\`XzIE00CZ D4Z7PF`F4D0Z.7CGH461BX0 QVX9TFP,V- E76JSITWdX6LBpEV V@VV`pDY6A ;DPE@IDP40R^0SPSPR]0U]@P1Y] 3S1 UB U0N}`C&[gkhJTYQUPP$Nb7[eGgIh6!YтZp;`ЭeCYhp@2$ rbRB2"rbRB2">8?20?]R1^~iddyҝbdad`d}h~k OgdOK g[gȐўidKf[ fkϙ;Kd[dkdQlpb[)bk a[ ak`B[p^4bI"s^Yp^X[({)!^XZ])Y"٠\A^l2^ hӠP:"^V[h0ʡVD(eBM^ +q 7w] 7[ 7Y 75P+s]s#s@+VY+Pp!"I!ʰ^`WW[XbxUT]bh'_]#I!L^U]4Π`L[a"5_Z ̠ H H\@H[]HZ[HYYH$HHPгXaVYY;!w#ZZvi$ZZX0kA]g^  y[@ZXR?  40 Y_0^O^] ^[^B@^1^u^J^X ^W@^QX@0"sm mkp`P@% -rbO?/ ascS@0  gWG7'q^N. ӂo_L<, ~n^N>T'>+ZK I + JZ+jz++Z!Z^Y^~l~kgpm)29bkkkZk j(jkj *9(iiHZ(jEh 9(Bʐ("ڑ( d 9 6lGb9(J rZR3b(j(za" 9( Un8` Y7$!+1W!I8! 8jH 8ڑ8$8Z 8z8) 0X %B8pBb 9%@$H$!H4!$HD$ HW!Hg!I Hw$H! HMi G$H&jG!H$) H Hg\QHR$HڑHfz1$H4 H H61 ;5aG0HV4DHZ %@4 HzH1 H4$HH19 p^YW v #]eV][a `ʡǤYqfVc Ӡll=yK I $!my ]y2K D W!yw O!| nl   p`PD9-! IymaUI=1%aߎtuZM{"ufWH9*wgWG8) ߔy`RD6(%?֠_Yj DYDki_W  _X #_XV MxI * Hy2 yV]VV\[Z `,R_WS:Oa p:kP T! DiP JTdP Ti1 DbPTDaRP TA D`PTiW\v #^WW fWjrWz ˲$ &* &I DR'2&R biVFLt°| 0 * [!X~ǵ ĸb2 ӷ b gXVVV[Wg{W[^$_XW\B;[GZGYwA;XnWWnWCw[ZY `na^^a\QYaXaWaVa~]_az*]a*R*7 *Z$* ** *֜a\\7bI %[&>Й7\ϰ]^g:b,(sr+8q$Hqmphr$$! +q p!rW! +qIq!+iIpbpp + $! ]p  S?A+gpp+ OA +somtfWH9* +{k[K;+ o_SC3 }xk^QD*tgZM@3& ɀ}pdрK?3'߀xj\N@2)k`bϰ aY_ s!X-8-yW-wXWW-^asYsW-`WXup[Ja.WX`bWW s6_XC2*pD_]`<g |pi_V_&w^&]&w\ &[pVZg &YD$^\]]}_$\Qj&[WYj&Z|k%Y.&X &C&%b &^\ &]Z &\X &&Z_&Y]&b&j&o%Z_[G6^G6]G6\V{H5[^{6Z{6YZ={6XX{6ް {6 {5Y_X 6^6]_{ 6\]6[[6ZYE6YT6ϰ6OW^6{5X_VKF^^{0 ^VZ**YfEYo@ s@iz@e^` FW@a!@ \[V_^]fZ _?\eh!\Y@@'_[W5aR SD(ZpPi[nBpDERpDZ_MiZ[vS 3RY}TSQ [1TTPa hlPCRn LTY[=9DSbTQ*xq Xk`XqXi`XaX'aXXb`X Xa$XߡXaT=YǑiYXvk rYzN$`ggIh0gǑg֑g i\ i[ iZi8ib#|` [\Z_[[XawZawY_ awX] aw aw _] ^[{]Yy\l$Wl* pn}~up^UI=4 /yeQ>*O[`euw}hS>)lB- ]J7$~kXE% P80312N*\VYWbiaɐk!W_SLQ \Q$aRH2oQE?2$xQ k?2ߠQ?2VT@V^_$Ėf Ės bQ2?[Pcv$]?  _[`^[~  ) )0 ;WX\vA W]`ԱW r`_WW`MVZ/ypX5f^XZn%;TP nX ¸% ׹; ׹P $·c%I@;@PnW`uvfvmg  !`w0c`0գV[\ZY<p 60 00 ^OO#Ѫa vbrwbiw`sf X[oo|\\o.O_W_dl|Xd0Дfbթa#3faaIaa"`@[\`WV`aZ`5Y'?XR'>W\Y}|gXXVVo}X+ı@Wp*A\VoohWW0 _!bruf] V \ *[z\`xgY[xvs oXX|{w27[rsr\, 6o !lY`Wug:lpg`fWVd[l z oX[Vu znWlC zl zu nlzd[sy_qo߅xkQD7*~kXE2 EtaSG;/lbVJ}3( {qcO;' xj\M?1#ŀwi[M=-ST MSM82~_W_Y _W\]^ A[ZfvhZ%i 儣pI( WY# ]WHtHQsZ HZpVZ( duZ|H&*V4:V* HVpVadVqr?poH`YpK&WpX%]__pf&w0e'( W&[UVU`V0&)0&p&p'Z'@' L#HH^_ X VWW [5W 0 (:WV71(0`PpסC 6\pt6Zqt6 t6X t6W t5"p 6Y6b 6"` 5`0ApL[] *[ E#pEb סqh4[1 8Eb p[pZ^10?p !)3`G m@ZpSP `+BќGc Hf EʳHAIGBJEWC@סZpUh4Z"p(U p 5a Z@P"E^( VRWaXBP tZaXv ZWaX Z?e](ZWZWPX/ hv$XUXXj `Y[ YYYY0f1p`4BnfD4BhA@X_\eX^Zf]f} f[_fZ]f`XXY KvKv>bDeT eW^ ]\^)  Z@OYXàw rp\N@2$*@}m]PC4& uh\M?2$ Pmxk^QD7*~o`SF5%wk`UJ4% xfTC2!zpAdRRA \P]Z[W] {Z].XX W YZZVZ X AW W_Vgf^BpuRuWoIu%pŗPŗΏX u{g gyȣ{ ruw[[oUX cvpCv,@,Up'P#p,סv,%0(N,VdpV`GIv რmr dm s abkCabp)v;`W٠zuv۠mq# "&ܠbmۡ`W5X_^togiPXZ]i\Vrv\"iOWiuZ\V^vr]goԷZ}__v ܛs__], ^[]Y\W[VZJY\IX~pXX\Z^XdYAd0VX\V\`pƈ0 :QI\"!dì` "` } H[d ac_[*` [:e4j;z0>@8 d] Upr} #P}r/P%/PWHZ!dZ'! Yr } Y]7Y]s YZ$rI%IWUHYdY Yr})pXIŹ@_H`X#rX3: W+HXQdp] - rp߱XX*X$ !!Vmp']-5! IC"4_XE7(0ssqW}jWG4!whYJ;,!߃via>/ pdXL@4( ʝzjZJ@0 znbNC1ym[I7%VXX \&Vu;C`p\__zNh$[6h$k0`ڎ[W`1mq@a0[`1Ws/ghsz[VXZV`b3TCiU`f:pX541i0W_o)2W_\bB] 0j1W_ Pu2U @[&Y[&`[&L [&P[ .p; W]W[[[01W49qK\pV1V Ѣ!4'``' op' 'XX\ Z[#Y^# $$>0" G7" G72IG72G7'2G5MY#6"7"7272\7'2"Y!^ 5o  R!XW [$X31!F!F!FuO"EQ@ޤ!XVZ CdBX l@3!wX70Ԍ`XpeVWW0A@!Wː]_ \^CWVy $ba@Bߐ3AnpG4G[ X`G GRCV!bWP[VUZ@*cVZbdUV@}U#Y\8V}U WYWmfLRV@  V VV^ WZwFVYPhVVPZ C'2"}!VC1IPdA=)fQ7gQ 5GgYAFh7g5Q )fDQ7`Vb`amfo`ssfuQh_Wq u_p ŕ_^]Wae,p"X]bmuug[hupjXufd iYVu`fcY^WcDzrDz.rDzrDw]Otzrz.rfqrŕ^][z B s trwfUF7('{l]L9G߿SrdTF7(yi[M=- wi[K=.}o_Q5%}hW> 62ANDS775120t\R`~ ` +m}Z]WlzbJVl[UXXQUNPlwQU '0 `W2 ӟQVzPМV r[Vo`oJ༒[VgFJ*[sǕ[ DѐՕЍ rӉX 𼒫\ǕX > \Օ Y\ Y\ Z_QrɢWlYZ Ǖ[@>Օ X[oW춥XVo*'𔡢lX!Ǖ5\ Օ5 XKZo& Jwg&A H‘VRБ dޓ\WA lW"ǕW_ HՕζڣ%Wζ޶‘ Б ޓY uoJ@l*xY\u `VV[\s [ =iZ__=YZlCJ5 2ŒF B [Vvo,Ѡപ,s4s,Ь Ɗ~$YY 0FX$t )A$Rr" 顎$F$YP^pQIY h 蒈粓T $Wc %Wr "ǐEIgA $ s"vI $ Bzǐs^5 usjQ8$ znbSC. Oߊue @+ mquwhY_J;,vdR1"׵rcTE6' teVG8)0R16452NDIODYVWv?`a!obr\`f _5^Q\^@%[\%Z]@˘D%Y_@RYI_aYB@RXN%>%W^'Xw@@%V{ij"0^ H/>M(tz $2(#'P(A#'p&w@n(n(@~@DQcY d(c!A>&Q'Q Uc"A(1'5Q c!DQ /ha]\Vp /9WP?Po@fbpejVe`/ha`ar{[i)-[p]\$ '|X$>{ @Z}>pzW }<zV3t~0 +Lt~0 +tvtm[I=1!|m^O@/ ~m^OQ/ q`QB1"yj[H5&yj[L=.|oaU9+Co|B }8P Y 0  mfw_pi X,vY_W\U\V \\W\~PY\\Vf`p-`X\Y[X]Gғ& ۘV!Uὖw*Ȑ5̖[֑ɶ#O[ޓQ%[]ۖܡwὖ אWޓ͠a]ۖCY]vukQos)3%s.QBN/ZȐ-̖YZאW~G[f~ٱ1[B]ۖB o񽖒bWq Ȑ ̖XT`ܕ얏[]#ۖ /ȫ["v.V5X[@HX ֑9 W[f瑯>$M Ȩ- <א ӦTm]ۖm瑝 kW."lqbSD5&rcTE6'P,A'̰ZWZ R"Y YX_^VР#\#0###|Y#^_}w^}\} }Z}}0#Y@^ XPY\ [@)\@)ZWA(Ym)m' PY(L )[ )[Y)Y)R`͠`͠@\{%W`x@ݰZmݲcPVX\_76W\D01[]o2c}|gZ]Vo}WX[X\ ,>Rh1a}N=Y x0|2 ~1p@8@086 808X8E68Z 8YA8P80z`Vxg\YxvsKAoYV| ZPECl0NFkA[A` cE,qOE,qo+X[~AcEX%OEAoXX~Ac@pGAPMGBoY[^@m c@w{vvZu]o1p9qC@PKc3SVoq3 @EYuUYCHY2P\X,pR%XXu-XCGXqPIQUdYXPVN0@%AWCyXWV"C%Xa2@s24Q Q XcV1hH@hhVVNhy NhX pNh %owHƕ2lmXA0jvPk1k:1mXm2$kk?}R}X,}4oҕ2 1xX!x91 1xX &x xvyj[L=./{l]N?0!ShYJ;,]exiZ?K<-qGyk\M/!zmcWK?3'|iVC0P2NIC-8-BIT_$Z]bW^ZW_W< \^_P  X) VV ,!]``yPZ\{ij73\p Z\C[pjs ![[JړZ0ٔ5Y\;OppV`А Z~jb73Z^ +0jXrb +09ZZVVY=X^"e0WVH PWĎ0\A W P ,3XSZX?Wrr+0D_@ ( +h@+ ZWI [_p +0W]^WV  @sipyw߾|;uT1GWyk]OB6+gugY=/!]OA3% }oaSE, paR4'?0P{XD1]a-1[}Rs?vf  'VL@#l@1\}~0[XVO2^0N}R1# ]@d&YWKU]:'@vB[Vb`amfofwfu k\R[@^0    *[ _@W2 _Y}a0o <W]Wu263"Z~2YG!YO'p\(\&aN&1x(XCx(\&:qN&Mq(P(`(` \$}2 ()(̠(@&a .8P.8X.87P&:q f8pf8pf8pf8WY|c8)8`7vP6b6r8p8)p6:r6Mr*Hbp*HupHp4{"4iAY@pHSpH%pFaHYHfHaPpF::qHZHHH0u\W3u#PJsq4S Ta tX'tX>) +s_K?3' CÿOykSQC7']ÿ0]M:*vaTG:- wj]PC6)zj\P%j ]YVv&]!'R]X aL k55Vwd/ P4!]r L]Vndc}a7U]Y   Z^0:PV]_^{]9\\ \['^ ']'\(''@Yz8X& eq'Q@d'0d&y''@'0'qPd&W_'\'Z'@'W 'd& 7^ 7\ 7[d |]֙\]kzT7\c0P\bh'R\^]~m~dY\- 5J55=55U 5 5 5|0]^k~~dgpm33bS 04g47^0b 6f47@b 7`471@@4: ^g_kY@Y@*Y@Y@Y@Y@\\VwbfZ\[_~?f`d[BbkdhG`@@&P܀^DG FFY|@@\[]VYhDA\_@@޳B\\E\X@BZ2̰ED_)63S\:P6'SW\0V[:P>VZ:PLV 0P1bR0TAW1A0נ\۩I[G]PAYg .UXbPAXV]RCX$eZdW`I/\W[ald;r:lWLmI `mt`\\ rBW`PB*gCafY`Q h5fW`hwX dV__` h`xBN|0U:c3ws1c0tAY[YXk c[ffw [_o Ɣ2  b b b b bԡbuqۅZ`cZ䀝yY_ z: zyyt o |ztaQA1%r7O<)UiV;( lSF9,ދ}gXI+ paR4%xiZK<-(^Y`^$0 !i #0=V_^X^)U\@)[0))YY^)X4)W@^X{Xp+2V@ hX  Wҷ ^|P4yQ_YZ\@4Y_!jpX@iNW[[a!lڕ`>INi#0 NݒW$1 N@ Qi  Y_@TpX64맍NL^oV[\ 1c^`^p>^j7bš[[ЩmgmIV_ضض|ٵشg˴gJ T&ƺ&_R ~Wor XZVz`p]AWYVKÏ`TBVZJvPrXcvBiYQ1@[0Xa__ X[1q[\qs`R000]^YCB1 UX VspV~ ~P`bdbem2]o52DI@2IEV*!B fb4VדА@F1EVDB |fZ][.Z[@Z[63Ԇ835EAV01E<*DBY6Vr5<@fEI 1E DBPWd ]bN4Z¶`GZ ZYTS$RT.RY VԠU0fdDB fY!XLaӈ"50ӟӈ֔i`st}{yj[L=.wfUC9* E}l[J9[{naTq8*zo`P@2{hTA.Àˀu`J3u?\uYovog`VZP@ VXX -V\Y `@Ǖ[B\Y9!@PiW] Ps[[\WiXZv xW\v@pWp b^ ]!P[@mu\WaWe1mp z1mbw\rgHatfv[__^^o`\`!^XYKx` 0(Ca 0 P \xaWXo&Z_V^;"&Y_YV( ph'][^m%b\`{, 0&Ob#(` !#sWYYXWviFH` ޿2&p Cf`WAWbm`a`` $P`0Wr`|0@b{tVZPas2t F/6W90 =0t@agjgff0vz1O =0_2ig3`t2\}4ZV}4'p}0`ӱ$}4}4}0M@v, _Z_@%7̲_ }P r001YVv[&3XZB{_X[ EW# G^ G]g\ @1W\- 4W\@ NF 0 AP]] iF\vG[[) v@1V `_VVW bDK]K\ K[ JP J#XOY\ ~YZ7[YA7[7[07Y]`D"_V Z] Z`wpm BV?vdf3QpS]#PrpR#4V]԰W\QQW3X԰V{sP1V  sdWX]dv8R^`fbHeYw ren%`gؠ`a@f[X*Y]VZI wxǐ wՑ u$Hw fw fw+xfwII x fwgHwvxؠ pe~|{eP:%p`P@-GQtbQ?. m\J6#`n[H jWI;- wdQ?݀ ;p,@Pm X I2`؆`` W&X W 0W_>[v,>WvSւQ\@'QPRYZ 2 ȃ&P!a[XXQUX+TPXwW ׀0Vu1 1XVwu~(WZku(AYZV^`I\Y`WG[`WHYW{lX`-mW`Bd\`WX{WV`l]` { C`Ih "cˠn1 50P xX"f{"$Ǵ/Ѽ q vfujfvX A]X^bX?[o ?OæB ZL`T>[`e}L\S ZƘf l\v}ƻfZSZf lZBv }fÏYSQZ$flYv5 }Y@T"faRvZdZZXVSщÙv؇TZWXS$v؇ZmfzfmZP3Y==#{WZ|0[pxwdwv\WVphuf}lzam`bl"w/vZ\w@wvYB3`&W^p` ,Z-@<FP0w7[[o px21vzWnVHvo@GhWYYШ)hP0v``ިJ$su_} qbUF7')/}m^N?/ r`N<*ubP>.pwjL=3$߁rfyj[L>0"A׀x0ю]ViKguy000`EW0}0<`H}00}0$y0t0t0I t` fC `  t0Hgp {f* d ?buub_&w^(](\ ! ~bssE$* a q}%@Qx&XR@'q$_c đ 'ӑ _oV] '@ " Y[ 8@ !:PaHPđ97ӑZw^R a] o0o0o0w\]bf U"0,0w[V040s0#1[*0ྡp0@` Z_V[[m8Y (:8V0 ::k 0Zp+GVX7B0AZQ^WWO^l,EXA[^@UbJZ^@bJX^@ bGZmC+FAAJAOGYZD HbG@oA JA J"A bG5@oAG5@AZAbGG@oAGG@A_ZAh0Xm|oY\VXzVbqU]0V3QPS[QU[VZQVZ&VoVUVVXQRVXVWQV%WTU23q`RC1ygӑX23I gC1 gӑfW^P W^5` e]]b fPfޱ Oc\PpCQ TCPwKWY$('rXRTRQ 3uP!,PWVa`Pt23pC1wӑZRTÐQ! TÐx"Pׁݏx z_~sfZL>0"|;`UB. ua}Maizj_O?/rbRB2"odYNC8) zk\M/ CE AqDqL:E0PrR` R2]21z At:Ib:&IbpW\_Oq@w]Z(0p\B ҒҐ ڗ"& ڗ"[][\0[0Z0Wc0\!.bV  En]| lYE0lB0U!WZwgwpgȠZ\w ]ZYZf#}桗'難|ZYV"fl&w I ? /'?⨠ l 0H#0WY|*0XzgȤ%XĠРȠ_X[` Ӳ ܹܶWf : ɦ  'D ɨ0\Xdm^wH|nˆwXgz'wYWlXv2WW\C Wuơrǰr VРȠ/WV^od_zYaf)@`%)к0k[V~tf_;]CוN[CN_V7Yv}G )yR% )Y )T5:YCNоVXt]VEW % EW )5:EWCNR@!WFт[pw0sd =X h i!WWYXLp!V}wYXPXXXhWYX0p{ Vzvx $V`'`xQ !` ; k`a^!sx_ }rg\QB4' T 5}iYI;-MxhXH8(~o`QB3$ yncYK=/!seWI;-}n_PB4& F0YXP(|[_XX^]XW"XY$/Yհp@LL 42YX{ijwƅ00ɠ|bmf`uam`bl дW^Y%_^A Q]@i]^W_Px]\}(&V[_[[\E%[x!R @p yc$@'o(#{) [˓7%( ܡ *-AYvfujfvX XbwV-]Ю%\,7[5a!L7 06080X_ Xo^_X^P.[5] ˓X@6r6^7p77I5r67 7X67! 7q 0I1] t1p{1 4p‰ G1 $ G G GI G  G1 G0|X\C0I1[ @@ʷ@@A Z I1YP4WZ7@AVisl]VR1bB[PX 0Y[%ZY%Z6%XX@ UZ[ UZY; UZX %P,Ab[VbPVVY[P XXQPS1Vb\WY_ R^CWCVJVm>aw\Z\p xRґ[]Zp ܚdޗYdZWp} ܘZWdY ܐ,2`d>YIMIMϔ,ps ܗ,d\!>2?i@k!kvk k>S0Y2{^ x]U Е !\ VY[wTPPNbYM[= 0v#@ZXpY YZWhf #ZVZYZY ZYv`a YYobr pXX H @WJu |kZI8'3seVH9* qbSD5&߭}teVG8@ ueUG9+~oŀQB3$rdUG9* aRiYWp\{|Xp'Vp4X^&X]p$Byn落nVsnYO^pQ 4X> Bppp]{$!  [[ /(8/( /()W Y_H(0%X{(k' 4W> (dS "rV4%V'0'>4g^\vOb,1^g^ZYvC6WM1R6X]M1b7\2R0)2]Z0045]">B5֐M1R0g搪7R5[K35[0b4056X|,0)2Y^0045l!B0260056"500 4G FX00FB0 CǑ%EK0E2X[]`/5,00 $5, G1 G>i GǑ5W_G|F^]JF]."W1 5(F\]OWhE AmWW`00 40VȑB58AHV@00VC%EV ?A}ELV\ WA@Vl VXA@VX.V|JVW VǑ}E%VA45`f1nf>`fjAoeaeV00fǑ``bwz4w2>bȑigY]]Ay>ByHg, Gy> GyǑ g ^zy1Jzx[ qzxl`$23. xhXH8) odw^y wLlT\S,]>$5בE>5撓fu!$u> u?6Z[Iƙt!ךƘ6WQ5Z! V_5.2<M$ =][ MM=\}"uX%_ [[ ͹[dxu   > ȥ ȳ @M+!$M> M }u I }MY"u j QAM[ ]s Zs=Ws+=Z[=؃!m^s }ds % s mXd X\s =ذ! dX!Yd*W0=V!P)8k&^QKk&Bo$砑 X( 'Z0q46s $刱 Q> W!! =/d &yӑณ`$ѡ> Q8IxYso~o`Q$pbTF8*GUtfXJ<.!0PwfUD3"xgWF5$ziXI:+ i\-pRHRP860][PWVXY\ cWa   ))))))EVV W V E E EEEEFy([[@]ac&\g Y^WW_` ^f} V^l쀣VW_kr^O0V^kGr]0X^\K (Vkk %\^Yh])&X` X^hG(]lV*\aV*[fV*ZiV*YmV&pZ& F%!X0(a*Zf*Xg *W*Vg )X_h ":^iq *2]":y\"@":[g":Zk&XYwl7]_WK:Vh9V3Wi{9Vm7?^_^mE&1 :[ks9Zy`o6\\^\н!I[h 1I]Vd1I[ 1@ "VV0X\XX fGWqAWXyKWBy@WZWYfg@K|?@X]kFN7dgBWm@7|||Ay@[vfujfvX JZ|WVZL?|[PXYXX X!VXPSXY;SXX V}XY}XX T{#RXYXXXW'KU\QVjQXXXWIVQ VQ%hwY%hX%hWPrm\VWZ`!dbVlhOP{iV l`@mz &mzog ʶgZK`(mz5жfp"h!Dh `c `cǰfd/x!fd9fd`cW! \wkvV w! wшwO@dX^y`%0]pj`PF<.9qcUG9+OrdVH:,t^H2uYC-seW;-!vk\M>/ a1 \_~V_w^]Z Y +v@+]lv@ jKMW tBM@a]R\\VXRd~W wYXW[sw`b Xlbs X\Y[WY]@YYv@2W"\X`al@V_a[WO őX[s~W0 _;[[^P(Z^[Z 6Z^ ('^(V]^[o ~fXkV@k o[RyocZj oUZyYj oUYyXjoUXyWj oWyo_Z]V ZG^^uR 0!\u p}M3 T`T3[%0zh*a0Z$%6Y%ñȰ3X%߽Mqh󽬲W%$5@ Kͬ ˳7WW\&zU[ Z UY X %W 3]>ǽl Aw$Q@P`P\QjQQL`QH`CQ֔Q؇X{Z`CsmV]iYXW[itVZ[)Y[CY v@ Wt \Q4Y 4 @4豐 Q l78l@lWCŐ[ffw N ^ZZݐᐶL^V$[]sm[bv y0g UYXXA]sY]3\ 3[ZkBPb[T3v@EEEEEIE E ruv+e ^EY  DP>sspzh\D8,~ndXL<0 Qo\J;*{m_QC5' ӇqbX@`@4(eB2"xi^J?4߀_XWVp[{A_WoV>~@ kZklWl Y #`]V\i !Q,VYZ]!VPo;k;O+GPr^vuzbɮib V[  Ő^^]ss3] \_U[kVY\hto@%XZ 1 P: M: F F QF  F F U F F F F R$@ : : : : : : : P^W{ijWs!s$ ) s?zB^X@#Y( !V! "[bzVZp 2Ys5Xs5W 5Vsw]_2PVoR]_Yl@^6W^QWm6xz8Z{7Xm6@8Z`78`8,`5XW P 8P7x HHP790H[0HV7h101_A] jI\ yK0yK`yEV=_W[ItAAKKPPIV@+y@FVAPYay@R2YW?]_ .R03P f ;W\^G`IP:X0 \Y0_ IY@XPDn[0 IP+SzR 7PU00]]sVW[h`>đ]]fm\0 zS[l\s]*Xc$][Pb][Y0]PQ%ZpQYF5 +cX +!}qeYNB3 zhVD2 jL:(tj\H<)pZV~~dgpm B#\gXt r`.VWvXVoViX.p _`*41Xť'0K0ѧ!'0f0a}4Vo:A d['0 LXQW ֒[\YWVl XX^Zdz@j@哙hXgWi֒Fg0`D;ZO WZlW_f30\,1s@Fa0xзX0XԡX`g80WWXZWZiX`1Y1@k= 1W_^fZ V5 U^]lyWm U]^m9EWlvw0&l 2bA`ޡV^\۠, ۤVXQ?0^[ VZx *;UX ^נ9ӓDqa`zp``[Xrv@:?0V_-qi?aW-q=^_]Wwݡ\[tepuq^\!@1ZJ^bruf_] V`a!^W X{f|grud "xiuXXVv*0nFн4]w S`*0 ` `) `mX^$]m #l@W hX^bo[X3Phb `` *_ "Ө Ч_d`H#__f_^^q_zR!F F F F F a!^XVXX\Y 4V]D\PD[PDZPDYP Ds^Џk * @\@q\P[U0:p"[@U0)2kP,V@ه3u`~b_X[sZ  נ VX7WZXX k:W^Z]]\ `sx _{pX!1' p]Q;9-"AufWH9* swym\@2%rg\N;+ נּrcU>*ɀn^N>,?AX ^oi0]QYo[U0p!W\n+Y]bX   XX[k^V~af D.X[D`ZV\1Q^8@D~LXWY[YXkP-V_D~L`Xv`hޥXV[x,g0g3  { \o bj WVxiV][`+^Wvp!`@q^Wulj 0ޠH!fN 0W`g2Sa#cAl%VV@l ,s^s;@0sp&wY&X b!_xP'L0 E!^Y_2D"] `W]V[X@p!Vv03W`|W\Vj!9,10W W N0[B X+1258\Wb1 DL1 #x0#V[50b!VVx\ "^\PUJWV{ rg ym{ gzvz^Vwlhq @ju>VvtVZI@P "E-GY@P shu@[0Ì{jvgTKBb[|] ljwS D[BF[XB V`v2xm"V__FE[-pÞa˵QDF[zPY[ D^YX\ ` &UWW[# 5WX5WWAa@r!;0,]^^@xRYp[]Y%rzPXs3IQ%pRUT0T\V`%"V\QLI301[POTP 2^(A,Zu`յZ&fYQ*ZZ>`Jlr3Pak]g20;0Mdi]gdga*]g`g7?OIkE dVegsE Mbj5`LZQWZE@Te ]dge{wze ${we{we {we {we r0uq)݈ yncSC3i[MC, Yk`QF7( udQ?0! ߆|lL< ugZM9, |g^I4 ףBdkL@]VZ_\X/!]VVb2 gZoi~(p.V!`jpP.\d|YYZY\\\bh(\-`]P x0av]Yq\\~jb{v\[~ޠ\Z] vvc@mS\Z "\Z- ޔYڐ - ސYڬXb\WҴ \?[[,[ v`"\4= y@Zh C"[igu-Ch7@p[ P#hZ!_#h $7@ [ pZ!u pb s P [\Vp<"0p79 ]*  .[op@04 2/3:pI XI *WPs   ^fV`mo2p 2qҐphTޱfPZoa m"Z^#ZISZ[W  0^20L@2t!e.ZZZeX8ZXl[e`PVW92”^pPɳ \VV( p`_WVXYYp\ ZpZ0}WXhz@6P>WYVNYp dLZ@ mЃVVzd{WayDA I0DԚ pV°Zq;Lpϼ]\Z\[Yp@n@ 2Z[B @Wղ,"Y2"z<"3'?pw^^4!\G l^])[ ^&Րp< HE@ҐX<ғ`Y tRsҐXn@nAE[oV^c@eJZc6!6E1Ay L@^^_U@V^R@#WG K)VG K&[]V m)K$W]] )[ +z*[] +W@+0*Y]++W*(;`(;W'\eL\:epl6W[f0X};x@l0,]gbYS@Zzg]d4 4b40^ V]] 5_Pw0P7^ 0$]f1[w`LGXE)%@l]`WK]Zq$ZI%DZA0F %@YiPW\_WUGZ@IV@- HV^@ IA @1Y^1@D[W BAU\ IZ H&;Q YA YQF1HWW\DqXYZ.qXYqXX}`YdQYuQJXVWQSXcRYuQYqXR$idQiuQEuXADX^W):uН ]X\1`Fe_`Xa ghWxiZqxia;ifVa@Ɛ][XY8XdYJÑ`]bՐ]WVfҐ1m[Dm0\D@AyyxPHy9u.R\F!G {srD$ ryyщxSru!qn{iZK.p]L9(AKߊzjWJ:* yjYIy(yj[=.udVA,seVJ:* H? u__?18ZG QpU]g&C`zFAWamx_TV}fmk `d8FR^p( [[^XZY[ŝⰜX   M qVYWPPNbpYX@\w?âxiu;{DQxwt]wtV^xFРwrvX^X`5 Cn;"vX[Ƥ Auav[\Xl[ JZ] oWlXX WXYWl *V5 99uaY\5_gX]5fHl sg`W4ooujphvs`ppfu2m}4m-h}2hΑg[fwfW\7d[fVu'zS Z!%Y%(ŮuX2wl%ȼJWȊfWsWB2렷1 %__VWY7 Xb_[> !Џpv| <rɀ8:XW! ' .XwY`mo{r_Xп`_WoUP22_W_("VWv27XBнe[d Y .X RIJ ]eWS ՚2/ BY)Ѐ/lV\uwVZa `(!!GL dWlWH{kyh Y [ %hsu{jY?5teVG2P9=|m^O@1& rg]RH:/$ q\G8-"paRC4( whYՀ;,u?fQBWW_W`[@ /WLz@s)VH70 7\UP7AA7UWV]ufd`aWX'iuZh{YV|9vTXYo`UvtVZG0`RFgX|8fq  #{EUd#0$b#0$Ea#0$@M 0$bpVʠ rr"TQ{( { p!JtD{$ (ʡ(eQ{ ][YXoPp]Y[$X;A O57@0F!Д! 7\g_[(56gX\OP56eW?6I7Z\)I7ZI0F `q7ca8 8ʠ8Q8Q0!o#[^C]Ep@U[Zr[`![@q "Z} ?DY]VYoa|#YQ\0 bBY[` YXi `i!azPv! 4AȘQH0qX] 3Xe@UX/B`XYi nXZ E4@Fr"`4r -X 7$Rʠ -X1` -X010"T*`F(|DW[|q@Rp,!RRX'DWɠ CWkU@`UI@ __Y1 q eF T" 4$/PCh{$/7dCgPag2h1h1h1DhPha{ tdDVl/8!'9`gCzAV]]^tIw]\@W{\ Wvp zxVY[ {W z@ p X^zZq  }n_PA6)r7XK8%AIOUhT],mkXNA4)tdTD4$ {mYE1 zjZ:*p=B R_YXZYYX,kYXYW_Z ]^ڟ 'ZX@t9P^ 'Pg[ 'WZpA n nXA@hP XY^g ]YWXYQ0<'WYʐΕiI AʐƔ%W ƔۓV[_ dΐvYT0o1!Xb b&2X]{Xx0 jpds\^_\VZ }[UZYk\X[Xdp 'k[֋Z^{ ZXY\]V?^Z H\^s[X{ZZ!pAp!p aW!П ZK V@pYbds av{jwbiyRXX_[`am`blwrpfub`uw8@BX@2X XW~|_@ԡlg R V^l$[AkG@lr ZW_`usX #X:0O`XS XHXNvXvP [ $wh ťW`X`aX^dW[ ɦaW`W`aXi.P AaQU1W^E AW۠U iP }PAݲv_] ց_\ FsW\WpX1HW[`anVoas\'Y^ [ې %p[>NEYE 0F %l{`3"!0pc`F@!]` p`vCC;Y@vFZYB PsqMa 5=A L{`I L!0L`LVPLPL`p` EvS$S\b b [,-c sppo]G4 yk[C9'Uuj\N_5*emvu\QD7! vR@.~\K:,xgWH߀) [gZX_\Yb {k`[0Xp^DBG]e[VZ{ZZYp_*i (Zka 5W$qSp'Y{Y *Yka T5z X 'P5W{W  ka5* Fs _F})$]Sp ';&\\WI)Z"pI&gk)U!k)f!I%YZ>e b p[WW]Zd'Z @*([f*][i'YT Yh+Xk'@Ѱ; :X\k@:[m/8Rf9[_Zhu:^_`09f#k`WZi0` ^ _\oforu}d arrl ,_Zdp/`\WP%6a*3 %4W21 8Z^v`a!&Cobr VAZ^6Z]\]_uk@B]@B\4Z[mZ}XdApL)p@AA[Z[Y[@ޠ'AZҢP9%CO^@@ZPVP RAG`@'AX`mo R }ZXY I@RI@ApDp@;W@AATRP "T"TV&CpV@qAVvsY\GTV^^uX@1T\\urvwX@XP!X@AVRX@&W k= X@mb\\a sW:dZBbH`]P`D`XeVaaH`Y_^[])pvc]y][YelV 9Y^PI %fC2 %ད]XSdR SeU SxSwR cwIJ{=X@[b9 upYupX{w@ǐH T:%BYhP[ hPUwW f{|qfYN9.# ~lZH=+wf[PE7(rcWK=1&ֿ|oaTE6' ufWG7'iR;&Sb]P[]<1 0\b; I$)h?G?갿\bh&\_`2\0 [K0 ?B\]ndB\]i\\up䫖aVY^aȖXcחaחn\[^V\WO_ 9b [dhQ[\A[ZSZ[aSГSנ '@NZ୑Z ZГZX%[ إW_ إW\ⴑ #bY[bd \YYpJFT*0]YY^ %Yߓxb@"xHGR|r\W,A1C\UW9A>C\ p\Wa0vOWV!a :WDW\V]s\V_IZ] R{[<Y倲U@_nYuYJ\[YXJ1 N5P>PXbkYXv`lX/ˏ@ lnW\@:>2.SupPI?VX_%Bo[ v5`vPvvF v]Vk $ [l sj~iT>(xcM7! Q_bY9% y}n_PA5)ui]Q9-!o]OA(߀zmWA+B 33'@^lbJA^Z dlZtd p YXW* VF ]@ gB~@tF WGX+"X8 .NX@ \uXZdW` V(4@!И0& < ^PĠRf5*]/)b"Bh ?y#Hm]t ]__Y ² &p '@U]+B1C]8B>@!^^M$^ %p %@$\z_@6X5$@5\25\@25[p5ub6@5z6z6U@5`q 25*!6W 25P 6*P625`A66@25V`@ F FU@20L@]\@7P )ʢ4B =HA=HA=HA=D[ECyHEQyHSQyH@=@@]Z`8P/"]Z Ő@!Y_XsG]R P! $ASmP`bvpg^oi~g ubU[V!Q&PXZ!Q&[ZZ5R &[YX!Q &[UX5R ;[W!Q &[KW\!Q\5R&PWV\`|`Wv]s :\ZPv]Ps\XWZv $m4`s\RW^P PmP[5`\vs zm`s(VfVvmYv5 XXV mQIlc mbl3c }Jb`Se`^c A}uakd k}b`eLqbsVvW\L}3`}E!`uvbN:&r+UG9v\B-vj^SE7mtgZOB7)[NC׀~qbUF9*!1 ,Q~@ooasY-[ZY YY ;XY WW sy_\z."_\K]\ZS p  y U}[\Lw_[* _Zz +Zu'z Z{Z_^9@9@Y^/Yn2&@Q8`WZY` ;Vl'=!g!$f 7b!a$`< Y_`+Y[` YZa t XltXb OYXa}[YX` k ,Xo X^agX]l X]b OX][X/]`[L+X{_ZdYh+8X{?$Vp%R' 37X? &b %W>%cW_o[W_l W_g7W_f&; OW_b>$W%\b{%\`%[o $4b{%Zo .5Zf%: .5YX% !XW ^gf$Wf$WaVsi\rѧ0ao[m[`ݠP6UX00 5V0M7W1LS 610 1^VoreQ0_ D0EZ^c@24@V``bR;VvA8AAo٠1C_`["10k14~Ѫ1wW0^d@yP\V1yP_Zb O_Z`@C_ZW \_gV ^0 Ւ{ c A^\gm\ 3 > 'X԰2@P* >[]_ؠOR ]\ \ 8\ 7\_PO\olg[\_P S\^g\0 ~oWp[\Wd`ޢWl\WYW >$\UWP(,[ b$[o3^l[^dO[j[[@ ?Qg~1A DX@3Z>$Z\a{YlZ< > %sq~o`QB4$3vgWGO'Wtdqn#}pN=+zjYI9}o[G+ ۀtdTD4Sj]X]W[?Q0W\XXZ\VY Pb\du ^Aܠ$g0P101VAܣ[\d;bXAo0\d*awܠ~0Kho[bzuVu)db2$[81q102ldXWj$uPj[]uVYh`|p?^5$sVWw@$H Ѡ[B[_Yws[V@Bp!X[dy$W/X \[x2"?[vwKR!ZVh $YR  $Y! 'X 'XJ 0!W\ (V!'WXv $V\# D&7"$-03 &7 2$V[A<P0Z^][LOKZ^԰ 5z0Y@y1@syP0Yhwe 0V23W10=@1 hp9X4d 02kl[W#3k5 5A2 5k452BT02f1V@2f0XuѠ^FZpm@2`5 5A2 5`45Bd 06h"vC0E01obw]xA^C@`}]DC{Zj@@1Ch\ZhUkCE2@ QAWR UYR-P aZh UiB]U`"CE@A W RA Z UR-PZ]Da2}W3 c P4 cuj>P$j`DakNb $e2B}cj{cje2C$eB䐣j{jhj!Teijph`fdeiXu[`zd`ѡaVX^~fVXZ} /yܶ/yh/wWX} \y<\y!woV\/wV[yy``w ?\ ?S wi\O5)%fK0esX="}ueJ/ދwhJ+ `DJ xbM8#?pRBavfWYsxbtav\ar\wWVvmZsv*/ЌYaaV؀X^XWMv XWZ %H҂V{0 O^W^ {3\ 元܁ e VvaX^uEs` TG XT\ V.vaWj%b~M|Zv  nڔ|܀ڭ@  aXN1W ƂW_ fX omV[0]~YXvpyks\X\˽ZW_ (,ª7Xڀ RbªmXV^ ͘ª^VV] Dªô DҪw$-ݨE `۷I{ ݒ, Gb $} 8ISny0`~W]o[Z]j@}cZ\z[fbV\``VYXH#X[`S//W"dOVW`"_V\VVk1^|2^W`Y[V| 6!^VZ^\d|ZX\\^VY?^]d|dvXoXgX sn_ ץV.5o\J9'=n\J7$|iWD1 eix\N@2&yzk\M>/ zmcSC3$ ug?Jy0b]E$bZ^_abZV03bY4A@ CbYIQ@ 0Q@ @vbv@XZY`VXZ+gY8ywZ` c + ` XXW1 W^]^z"bW]@WZVVXt@Jk"bW\@\![y<"#ZZe.#Y)XW@0&@g)Ȱ)a#W\V`uX"[_"W[^[Y@ Y^YM[ &\Z%\ &XZ) W+p$pbV^[`fT"3Z)0-5]61<5X)0 -5\%\)0W6(1W661W6Y)0$V[^" 00]`Ef!6`0! ~bVY^uboA2X?u[ 05c1p6\u^2n6\^2 7\^37[u\2 G[\2 7[\37Zu G1 7 27Yu_R2 @FY2 GkY_27Y_37YY2HY37XtDGX:4 GXl]B0":VXBIXCXD7F1X47WD GWu[2 Y3 GWu2 Xl^BIWW#l[hRiUR02$Q1hCX)DM7W[3X[3I\h3X4\hbDXV3 0p1Vu\C @f[UW2iZuCiYCiPz3-GVuc @pa{W[l3W]qVuexl dpkropFdwXl x`pwXnqdpYtWlgfuW~pwadpL"ulL, 1sf[M?0"|k^PE:/W in`QB3(u{~pbTF;-}oaSE7) k\N@2A,Xd]Z[kOpZ Y Y] \ Z`t Xd]XZ^IY`茐I'IX^lTv\WXkppUWp0JWWXapXڐđW`ڗVڐVS ( \_ $E $YE@d$^Vkwڐgd\]˷&\q$[ZXEJV$R$'tɦ\ki'ʥmWYuX奫XWc Vc XuVI V [_[P|l^]I0cjpyb6s )b+Y]R Ic$N YE] Y!jsy0WYVbj 0V[bbkWU <&VF% O(WH#9 40^bbUu(UZ!u'Y"(Xm u'W]!u'KV_!(" -" Zmb{o( (Y 1LbZX8&0W\ /5X :7_ :031VVsjbrmrhp[2 p04U]aX[C[ю1S 1c1 0I1Y1$1y[`W"4 AcA# @YEA$EAy_\_ 0rD~~F^\at 0V^Z( F\c F FZc 4F EY[uFW`@EXqEW%]c Vb V V#~D0ADV"谜D]_QcUpPL^]Ց~W~V\^H~V ~V WZ W ~U]>R V\RpU}f6pP[]rdj!gV,b~U[K^XCgՑCf%]agag6bf`$c]C0`Ѥa91 f\fgBg[Q`` gMa xgՑ f9wq9w I9w9wfbxw[mxI֑wwՑ%grfWG7' znaSC5' SWvgXa>2' yth\P8+~iT?)zfR<(p߀eP;&AQOSmsXX@YdfVVYbdaVZV`aV60XdgY^[ XdwM mfplf}vfwofwujb_sT~]"joj^ #ʝڕWV 衐\^U#] YX! )4 )W \Z[X*[9W\Z?ZYqȦ ^ǐ*Y9Y?,X4լW" )/|/T AV ZW ;UWW&৖V[V oWX][mkC0;2m`u{2m`Z*v XT rBP'`lkV804Y=NlYV[gYVźWw05Xaufdam`bl tX[Zv>lWVCЪ`vvruwfdmrxuvsjsX:нisl~`D.>hgX 2 *hgL hY[^ n gv尿XV8ZZ@EYYA EжgoO1Hg}bdrbd~ЪgW\_X[[gVЮfs|\[m2fm\__W)'qҽZVYX< _`[ X_Z[Z_C0 ՋZ] (Y]``W\`Эm da2fZ\|bnfW_Y+zgbYMbowWYѲL 7dv] s<^s& }\s ʢV=o\\A#QZ^RoXY^m@ Xmku $@ApiX[hpf\oV_iJ]yhZWYa XkXW?`oXW$sbmXC.7q\G2ޯW[`NB6*}mXC.taO=/!xgYC,r]H3 =oX]1 ^B0V?sbdg,VXZW[DMMѧb  X$A J _Q r W,I >x oX\mv H- h oX[gX{:$`X  A^0vb`mf !#($ o0oXj "VV[Vu\m%G#W_[PT o60[#Y r"N X4T !W o #Po r@ VL%! $m ', 'if%V$V[QW]T 2Z,T w|jb`vf,5X53<0.1ubvvjZW(N7iY4 <5iuuY?ZYY {4]0Ndv3 7W[26i3 73 0w\^W@c7Z]Ydd8 \3XaaKt6$JWddMM8XX1$HJ`28oI L"H3 $JJJ_0`1Jb0wW[>PZ VY V VGW PBr40XoBOVZ]ZpgcYYlf#Bw[d7vwZZTbZWlgMXQfu[c [dgZ! \fbX@pwMXasQ lR kog jWdbXW[ oQ$skPQwX"jDsiVYpCklfN jA`MXHogJQ {lCcklbbT66$=FZz(Doz=DI PFzDzzgDBnlWB-+`K6"W߈reaNDg  Y~l`NA3% n\I1$|l\L<ymaUG;+ @A`s[\V^x` 41\ Z* YsZXY qYT +XV^aH N Nz NsWa5W[[oVY["sWY{i V&sW NWP`PV_YXWN7V[]VlG"s:iW끿Y^_^X WY_] #sV\^]y[)VZ\V'лJ\YYVY\6YX]W:]0y\YПrs^rrZWqrr?Y]bvrb_[@!rWYVapW pwjr| npaX_ep`m}vw`d`swru upYsurpYmja'Wh pQ1wbZxl]lp =XxXDI=WxDIWVf Ivw\X`ssmvw W|[vufgV wov_ !v?/~wqoL Q1s`mXXCzWoٵ`F !sZ G#sVZgs ԥXWgg|!oY0"5vgWG7'~rf[SE:# asbV}?1& veWE6%|mO@1t_J5  \?u?g[X_bVYYXls $XXY i  "W[7 LVa"aW[[aWWVZ V5]%ɐ ɚWO@ XX䯒ɐ ^V' ' -dA#KXV'L0i@@iV)-q$eI0 @@ iV~VWf___|__aY \g`~ vv  WX #EA(#X |J#X*5i#aWum^s ;0FZYiZZWhW|];PZ\gmDZvpLȰ7`Qаų7аƲWZܰܰWsW FVv1XX A`0 RzNq`Ev9u@zvW`bsVЀ Vbdu pXs]poZF2 yfS@-mYc1 m}yUA-yQ=)ūuaM9%r^6"?]fZYfrWX!a_XfWW]VX[`]VfV[݄$77f7[[ =z( v,xV\&/ZWia@  >[~_^kZ`'f][ "'($:&W $|\\b'VJb&X :%J"W * +YY&V\%&%u[Vk#sYZ:%skYX%sY:%p^Yit4p^XI5 S5\ZI5R6\WI5R6Wp6R5oZ\I5 [oX]569Pp26WYZ6V_75^5lV2I0{5i[Wk$=5iZ[k1&%J@[iYu_%%iWZME%5f $5# %b^l")A (57[gCVF[XME5`7@*ND VZV&%jE# %`VB[1 V7[W{wsМX[l"7TVl`X[\V;kYkWkYW\^rPZkZYYPZk-ZW[P@kQ`rii"pa0kj[X%Xzj zj'`" jzig zjM`3jQj3{Vq| jV\^ "Utɗs "YYlr"e t`L8$u-WH9* ~jVB.zfR>*zndU, ߃q_;+πا{kYG#p@\A5[]XYZv\o܇X[_oX XOWoθov ,c[]x`[WXމPV[Y tzyWd V]kA ^`{V_\\;3֖[ZY[ד_] Ҙ\k xљ[]\>([][LٰLX8 R@X(Y^Ε]:Z=XZXW^ ة=ФVaj`}:ހsX[YXeZsWufdFoQӰZluYQcZdhuffp QZ[W^ZZ][o &}` ~po z\oK a`ðW[^^o]Z]]p޷^wK m` k^Z]\۹#[+հ+WVS'۹f[J d'۹밑 hʄXX ﹗/aaLSыPZVlXZRqѼPypEY{ZYVVvqЊ~pV҂^Yk'Њvv2kXwSk_`Њg_1 c lљ 6炐 D SD( 8:$X&8 3]880j"Hi_ i_-V%\9_GrBaAD  Ns^߂p^=.'jT>(I}gQ;%u_I;'q]K9%m[I7%r`N=+ApA2݀\]i\{\w >܁E XZ xP[|&  M Z_a7ZZw*ZY|$$G`:?D&%$&$)$ $)GI $)Z*$&[i\ZXZ=`!Vngb#=WdW $Yh|W^'X# 'X!V j'W# &W^#Q & 0R^ 7%]#7$7! 27$ ^\[sq5h }#[pWVh420V]5]4oW^55@55iV[h"zT5D55@"55vP50nЋ\VRp[gqV@ Z8EVAGME^@HU LF^VHLF]@H GVHLF\@HGVHLF[@HEzVHLFZ[|CEWVHLFY@HT>WVH LFW@HjWVH L@vT@Wd_V`ZyzSPQ8C^UIbE^B@B[ UVI"WX_XWX+kUVBTWkDEVRTkpEV1RTV]RTVRT,kDDb@ b@Ew[]vbh hrahu֐dyh݄\v[V B\TKzS [Ds oyR ]rFq=oZErZ] o Z S)+lWC.3q^K8MjU@+mwnYD/r]H3 vaL7w! TQ@2{?d]^XkXpWMB҃VW݁XۃڄЁZ_ZhW\^Ylp&Z]Z49YY49WWVZ59`1XooyZ`XY5oXX4x԰W[4xWU[ V4@A5s 5,IJZ]s _^JYYsǒJXXsJWa[sݭV[5I s4 L'Y\%OZ]V [YYZV [XXV[ W[Vu[ 1żXBĻGٻlĻ\ٻlĻŔٻڑlĻٻl lr [d[ fZ ^XWWZu`ZPWfsbY wX %W8tP$]`^vBWk^YoٳdˆZ@k smk݃ԝ YGPk9 sۗk4ٰ XGRose W@ksk$4n 'kQkrkT4 [ٰ}bVXr#]~YWw1%~X_V]VUZV oYV %0VV^V] %~ ~sf?~lZF6"%|pe1K?2%pS6* Uyl_G9iywfTB0$ e@xk_RF9- ŀzjaaZV[a Sr1`|W\0YX`9 {\X0{[\{[\7z__{3F}?]V{LPQ?OZ[@MG}P}W_ wwfu}irmdfuZ|bvp`s}V`` X|d -X{jufmf`dv# =& R-Ww`hv-#' --#C+ 9@bi`uhfuwo^[ w^"6W w[Zv3 4b+0 ^/7`+0 3$0 +0 S5Z_ 5Z^ p6]p6<p6Yp6Xp6W vlfwgruhsipibK p q`pVZ v0 j{3jqz +@`wuxXPUDp&@Abrdfsujp!vuZYvO NEb YG` Y@S@sF04uW^Y@Apviff Q`p^Vo\ _Y ;"CWW _[`DZ/XoZA @'AWo[C eF@_ _X@@oY[:oPmmfpdsm`vwlf}\oo%]*5S[a $td|ZZ; XX X p\ p$Y80ap${_ 81;b@c-%z\ 0>!`vo !> \v`&5&[t?'s?'` &80 f'6f' [w_&D%0&p$wG!&81'`ip%t'c&`&XO 7 7/ '!FC'B80/A@0~Jpdg[^]W``Adat[VV-pVsgW~Z_4 Nx3[5 jU`dn$]Zo!$]aA 4\n 66V}@46^6]ľ5@5^F^F]F\E0BD[PB@i0-bdZ*]BDZsF~0sF0sFZ sFY BDYpmRbdX1 ZDXʹ1 FWG`EYMBD8F@F[FFpFVEVYEUX(PV)`PTW hUztV^tV]qtV~tV[ tV mtVChU PP'!Ylo@U@BVklWgkWdgP<}^_-PSb}PP?}]Ws&fp2fVs&fOZPP2d|Yiigwaig`rk|W{e d{{G` fVe\_ e@ffpfAPsz4uYSoV\V\,t[V[ },tZVZ FvuYLPFtfV^8tfV]28pzZEb_XZi\NEsa{s,  3xl`O?0R, POWEIjmYVam`bljmXVufd #amxEfH2jgvOuYjyYj[\]uZ[Whuf}l1oN}i0o_s t%,DlMi{ޒuvGVigf'dv[ggfXiF iYvWvX .ߠiXW+ߑXW + igfߠhm}αh}wYwXkh?s9rOqZP`+r5pŠhZVW]WXZ^zd)VhBg}_V [XW]V|&[ & N>V &@ VV &X#` qg{Wzw_Xgv\VvXAPSvW]{rɱsvguʰ`ѳu_ Xs#`@ XPuVuW4pt ttXY^sW__^ U__Zv ET_.\E\`Pp ^``^^`pj[[VfZ_Z^Z``` [_ ^ f .X .W.փ^YR{@^Շp^XqvmpjX[\^'kZH Qе' : R ' W_#` ^>gW'@TBgm0z hѳm0p z<3P1gV]ZdVZ]mZPUYYaeX\XXazeW\Yl oXl XXi W[Va eIfb~2pW\t =rfp;1W' f[]^v.=YVXMhHyY^[pSZ d|0N]_pp]н$sd nVA)59QI$n\F4 iD3"ƿq\J&u׀QF;0%ǿ mcYI:'f2A2(AdWamoZWs\n0vsw YI`^ wW[W/YW`#.!XP'/mb]mfpV9Km/HPPPPZ P' mY[ ^(9rtC}[^0}YX *uW\|ZXAP|I7PCдP0mPFQm%]0%#PQ0mVYupXu\A"XG% TTV"WJ" b%Wk!`L b$&d\YZX 4qp d\\Y] dP)\!'YZZ:(,W *"Y) [+% ,'p<)P,Wb1mV[VX_XVWt*/l\7oo'sfd2Rn0a1Zf4n41rlYsmxvol/`SQlY[g`~[+rlX20~q1X[vm1G2120a1WswvbLP\AkYbA=oaxvwujs3@r`uP KPjoKPV L@h}qDEVZQA VEh0wf|K[ jMV@L0p@]h} shG\D I[D@Vp@] `rE\ h`vlfw"EI[EI[Id@CIaAIYEIY WYIXEIX@FW қ@CZG TEPZDYYDyV^@_ W_QAy F^@^ W^QA V@b\ X\7Wh}6`iQQA V@Bifoj ugj Q(gP}QA&i-Qmxh@ W-QQA Si-Qcf miZ XdAQA&iaAd `VfaAcf mi}Qd i}QQA&iX XPbiQQASiQcf Pm`VQQAiV QA[D6EV6REP Y&<p}j\RD6*rbVF6+˿{AaTG:- ſWwj]PC6,zncVI=/!xl`TH.!ucTE7*\@tvYXgWb)0vYV4Vwv$^*spm2mmmI$VvQy*VV w w XXVds$W]Vs3 w w5W\d PRWX^ZbWV] wL Svsbvv-X@@20W[du:  VX0kPzu}YwwuZil{uCgkMyf@MXoM!@V!0uPX4DAtZVWY}o`%WǐW"UVtqspGPts|\[uww$As{^E0s{ZWp ݡ{YZga XWu zWWgg'shmPNsh/P Q\g]g[gݡhZ[[ZjXhPg0W8gW[LjAggffuO=s=@Z gk0Ystwg YpsM0mpg0log0kmg{Wlg 0şhvg qm ^qkg 0f` hg0d -sawY ]X@ 9Lr|$rv^2W6]@ V #ѽ(4[2 BGW,pO֗Nrlvrp}oforu}d`w`mxlwfosfu`wxufvAjphg e8vbQ@Ԑjb x@~ ;!,NrrQp[;raC"er: p9p|AbW)W1b p>2ps;b R箰b @pbwa *PbP  od^vNoZ!0 \XЮ旐Y[ Ioco?XX{ sI@ZW] V W} WW{ &1$ ~qdN9%yeYM@3& }pcVI=1% ueO?~m\NA3{n`S/!@\*wZmimre}@wZqvwo}b] wYvos@89brdAb [5jor @pMjV[ hX:r3@2W[ pI ~r[XW\&-2Woq @'!#' W [Ԑ_wW[Xu9K&@GWCX_sǐ T[WT6Dv u@:UvuZ_pX[>XRaur{p`R fPPlSmxfz`RfYm`bl`R)fPURY[WfUP/huffuSXqW|UQUYVUX[W=}T`VfU.bU&`uEW0vTc@vW`\*Du*Ds_sZ:&@TsY]leYfW_tfg\gP6DsX__g]g\Ng[ fecW]D2p 6@5pWhid8 a@rJsMSp Kp PbxmSpԑlVYVYYhuP y^_ ଏpeh v/aXVlq pSqR # \Zzb$lo]9'߲=n]L:(M}kZH6%ufUD3"ݙxgE4"ŀyjH:+ }m]N?0d)\A,ߚ?!}]_e"#v"pL!C1u{\_<  $VY J ^ѩ j<J^T#YS"lpZlCv\PĐ_WmW ʖWԑ v[ZXfwvZYX?ffYV\Ȱ ̓ZX\Ր WXaY WV'/Vf jj1 I$aXZd!a maaW\wW%2ac"JVq{xV"wvܫaܦˠ,סܦd ˤ`Z0"y2 2q9 ˠ!`ZV2V<uN`uq`uh`2Xգ۸qܷ[M q Ȃ W%\= Sq ﳄ= u_uƱb{Š u{ȳȂYưX!ەc"v#&״G&ؠG?GMGh ӢX֏ G֥ӓ գ q؂GVؠMXw{ 1裣蒣VnwZ$r}wb?}Zw _VVW` a\pVWhWg˓\Ve@V/W\hZ V &V[ JW`r[Y{ps3uY |5p|Z@ Ub 4b4w fs3{ u_ ~rXE7)xdVH=,saO>- |jXG5#}r`N=,{iXF5#hUD&?{u?TL7xm`Ysps`vvruw`brmrxuvt vppsxl^[\TS!0tZ~l[^Yd t[^X`]ǰ|\Vi :2g@tPc!t@ZUZZEy&[2Z|<,`i%+@ &EP @"a' ;M@'[[`;9 ;92_<;9 "<ǰ'Z'H9G2',#;R &=$6Z$L` 0k#Z G: G WI_6Y^{G$IIG2{G}4F@K[`I}2I "4EӠF0Y9 UE1v[kPvWVXF0hm1!zm`TH:-MOS OP AMPTFEzuXhpzYX_Xp4gb~_Y 7FAQ~_WMƱAaaI\OpZ\Agy[`d[[jWsq?W Vs ٘d ΣV 8V nq~^V`gj>^V]]]JZ*]*z` e 7Xz X *wV4xv[*vvvYV_WY\WZ.W_Znq_vW^VW YqWZ W^=V4W>Ws[XcqopoV cY] [ lQsYSsXJ~asrblZ`dxu`af`oop($s]u pcVI</"=o^NG0# |obSD5&恀}iT@ xiYI9* reXK>wk[K;* u?np}{]^! 3]sJW](#8B}{[fXXPX:^W# X[W \X X_f #  0I#VXP}z_\f'd&[b8'?8'lЫz]`(#p*p%[ZYzp%ZX p%IY  )# *`p F1 (VY0(Yp nzX^%P&$&8#696A&1e8Cu9l!$X' 7d100 [[$0*}zP7 770wYVsjR 0@A20 AB0T`}wX\Wsjz201HB-FA:CAF_CBV EW\BFYBaG@55WXE#D@B@CWBGBEV%^BHk! @wVY1 WV1Wk! @!!hG^Vkp%UQf"p]T]XP\U\VoCpwVk\Td]YhOTdYYwoWkW!OT^ZXZyUrbPW^WXP[[bZZOTY__sf=tfJDY[_"hED.pAH-b IRKiAAXZ#mh1\AXYYA meCd hA h;RhJRA`^M|VVGag[gZgYfX]})w\'+uY DuW`9VqXp_uWplp{[VZ |vX p0@{ZVW^XZz`4U4CAvVqVy@qp~qY^p ܈tpX p8l蠮ҿ~qdWJ=-,{m_QC5&G}Qeq]Ii o^N=-}ک߹hX8(sbRB2"raP@/u?MTMS27 ~z^[b?]z[ g[ \z`x \^ s[z=W`Y_ Mp2p ptP \[&pX>[X`v0UW YOPb_r[yWr^) ^Xut9ժX ` W~ NY 5\G6&p5 X]2ppuBuT0m ذu عP&\ 0 t躐 X1 ذoX] ~@V \Ya Wa [_a []a [N  [ 0@~o `7V\X%$I6 J ^6Z6D@~i upA НVU  } VW h\P:~b[[  2~V̘@`$9P=1V_ >vP?[?Z>xph@\0f Z>|\ذ1|?WVhsP `#ذ_^3S`2سCذ!!{&!-d7A DaD` (_X#1{^ 7@j" (^ ^T#VRlsp p`P@0 'ziXG7'paRC4%xhXH8(wfVF6&~m\L;* }m]M=.33s?,6|^YӠtW ~ |^Z},::bI Z:Zz":|;YzI_ @Y@;XEZ?@ౠ~ :|]_"|  &)9 *0"[ ) I+p)I k+W9))N+Y9){)+l+Y+09) 9\;#:Y#:@#0 &S;p#9 u:Z u:pu:j#9P:R:[: :X::@#5~%H'F"(EUJXUHINuJWUH JY UH J\ J2"AIHYZY@YHP?Y[AWYpBVlYWlYz`lU)_:TWPWP{VZs[z^?SR^X%pPQXP X>WW*Z XW P;_V| 6gI Ei Ei gkX EiIkWEiEiE`bipj贰iJPj\izr@zzE`c<`V#e^\X0\!Wq1lTxx1u/0HO~ &oxiZJ:* 3{k[J:* GKziYH8'escSC2"}obP@5( sbQ@/ nL;/#u?U217BBU2 bVYZ[u`Wws0d`X]^VVp`d[P,b 9a9\``ufd_huffplbmf`uKn`oaful+[2p!om i g; f aap`jhi:g-A-N-[X-h-``h g d b Ђ`-b r,Y o osGbgm[[Vdd }b]`XV|XYV`3}u$bxW~)a~}_5q#"{`qq4 u {4! {۱H\u`` !ߺ`  F{Y_00 0 00{X]Ou0sZuZ% Vx>W^u 0 y ʚ[{Yu XXWW2C"˰ةp Yt/0Y xّ1ѷm0ẚ '['X'5$x#!x4!xEX۰ xeBA\֐@/0 GAY HpV; ^ M [sl |kI8'th\=8&SnXB,ߚwh[NA4' tZI;*{gVE2!Àq`O>- u?LWzt`vh`kZ]V`w \^[YswV +`+`6fS,XWVWYo[YztEwa`V WgL}hupWn#V !K'mhpg9$fY`a2 tW) !2&V|aN%a;ml,"~%a h}&< C&V` ( %]! 0 WY$ 0B`$" _WIXf*/1pC ,1YfoYbjXI7X[U3W\1 a0!XXV_pXW_XV] 0,1)PVzfg95;h 7g2 ;h ;`9WV[\} Do2@^FgWFdP${ Ca;F`P{ @WV[saDS @/0g CWZΈFV@1V0!XWX\0V]VI]fp[[K\fpZK[^fpY[FV@[X[PZWX@/[Vfp^[I/ZE[[D[[D /P0V_WWzQu gs Xf [d WlagY`Ԑ[kx @PVlagA g-"%j! ~^{W]c^h`UeD@S\jUd\]`yeD@U`\XVimdQ:\VbggbbQܢ`Q[\r@o# .@c `[Zu`JUdZ]`eD@dZ^Vgi:t%uYrxs9=tt 6{s7zpi{mi{kiwWtb{lp{@VY^PwYpRo_ziXG6%/ziXG5$|laVJ?3) q_SB0 udTC2"sfYG6$tj^RD6 +?[ZVEs^V|Y ZaslXVV/^VV[%Z10[V ;`Am K0[AoY Z]_ nDx ZXYYZ`W`J W[\YZ]V^ @ಝ 3j pUc0a U`p- T?Z_g|XZd@GGG4Y[pbHmqS 0W X# YVo^?Xxi 2UV |[\p[\[ Z]|YYZYY UX0 Q XNozAWY|W[ TWr@`ʴ շVIK V00,P&bY`Y#R-F"d`oO>oWX"`WW[`uoXVVpPs6a˗`] g cX] h `0/0p1X[a@fWA@,#h.nXTNը@  gAl@ @XVY}}@/VGYelG Wn\$XÐ#- ` AI ٞ ٯ oÿW^]VirQܢ``W^\hfcW^[j4` 4W 4`౰`+1]V 60{`q)60 W-[h.#[Bc! $Šڠ "Bc sP]pBlE'a+1[w:Wa}!pBc Vr=h@ "`N sv v_N:&ߖt5^P=/#}kYH7&qrdVH:,rbRBzm_QD7*a0׹рrdVH9+߀@,@+0`YX\Xf *1 Z zAVfP0&5W=CWfC} CZVw mHmS&uQCY:wo1ܗAfCX]f5V_\f;&V_Za&< @f^\ ' 'XC!0@^`>()1&[w_Z'Z >&Z\o 1&Z\ @ `XlpZVx] 'g0)a] 6'YW ( 9'K]) )) %d!P|23 7 P$/9!08 0O7)'[_9 _9 0 O0c@V@`5@J4W@5]5354F 0)V]ZWbxS@2\V5[[[0 >$@^7fFY_'H1FXZEVvdZ2WBX_@``*z4AAP@[ޣZxgz D]gZZ@@B\*E F[EFFE @BD@PA0aP_Wi2Y$ZY`!$P`SFXw3{^^\߱XhRpTpzZ@zPL`^ZY^`>-^Wha]hUc]aU`&^V\ZvP{TY_XfU^[pV]Xpq^VX^]|p3^VWUVő UVXvQ- *fWPno]^_ LcV}]V[Y `g˜rger`Z0a‘#‘-jPh`jPdjP`\?[sw2`hA\[p___|__o dV]e]eoW^e vVv efV\hVXXa eaVuXFue`VWFu`a rPh; va°guf% s @zV Wa]w}m]M<+/k_SB0CWpcVE5* kpc{I7) Ǔ_C!tcSC2!qaQA1!u?m]UF|dP[abokRZabp]oY8oX* W ^Vad V o[W_&8ɾXΐW]o](kΗ] ΐ \_:I %\h0SrߗY$8H%Wh xeVjV\Ηo V]VBX? 0ʡh?x X_ i@wd WVvd 4 VVγobwvvwP(bw xWPzuo !bwdmwh O x[hdzݲv2`ݲsujk9EhP߰l/W^0+_iesdW[ U.ݲaVV\@7ßj@bY# RbX/bEW?y Wm0 _0bQ4awYu"avv^l5(WX-2xamzY[WE[0P՟ZZ_PВ0a[XX&2a_[W]vY~ЩvЋ@aRaYa taXaWa%W[Z]wWZY\w`m}vwg}ְlh/k`vPPD`vQ pAud|w snC{;j~rhfpj#k`]oL:BXPLmmfudjvsm`}0 A`amfujaarP7`pؾR``W@ "W@W\k_V rH 3\mvWW~{Rd1\hv_@`_DU[ [g 2Z"{YC  0%$_YmvV_YmdDJ",:2d 1Y*Y_@= 1f 3Y0`tYY#@\ )YV\0 _ %spPPscSC3$vfVG7'Uzj[K;, `PA0 ѯB"~m]M<+ `P@/ <@2]Z`bY]ZKI jY{ Yf X {R3f X^XpdM=PZ[(0MZM@ -XV  W\M@ W\ Y []L[]@@-W =WM@Y^o WIoV1@V?@-Vg =V:*f&)M@)9r)V+:f%wVY4i]j;0?4Z][Zʡ `g1K_0q3Y^y~6X2Ǿ2o|~[g0n62 0b3W^n600477{Ɵ5z0$5ɢ7h@q3V8MEV_ @_1n0pDZ@ˡn5AKmGGR8]GH^mF^iF@ AM @]i1F"PF1Q~](WyYX\_x`n0Q AV\_,~\ FP Q\WPYAW ~[`iAVah gXgْ$gY gi1gx3$gxggaSPa*0ZRa ~Z_ APd" }f w:pd0wWC0wYg Pw0w~Y0vXw3v%X wizjZI8'%xg;D2 ~lZH7&r_M<+ ueTziWDπ udSB p]i7bwW ! I 9 HI0 ./ib^\G @4R݅[*Z0q'ZY[י@0[9rZ\`:1엲ґ1݅Y_0JV]% g g" 1v8 Vz  XҘݩ0VW_‘\$$!E!5Y cg s9sXHsU0! B 0 s7`bw~y wXړ\Z 4CfdP;Ȟ bɬ _q)_qZ $_q!W 8HA:Xpqi5(5ڌn,0k}: }*I   qɐ0ۘ E! PNY eg ڙ! $ڪ!ɺ! TI 29 0%0~J-W k}Hgч "seWq_M;)'weSA/ {iWE3!o]K9'̃mZG4|jXF4"raQ?. pu?4s\^ib\^w  /W^` [b[WfX; W ڑ>ZfZp9bpW^[wk0NVXZ ,d`w`vi|||#wS~ ^ 뉎 = ٶ;\^g ؗ`]0J]o )B} 3+ E+- 3*E* {+0*o3*Y 4w1_*TP'P`*PP,+[s*";[UG;!;G;;Xo *W]`)Y_)0@;o:]0cI:~ K&K:\H ݆0뀖X_0)SII)eJ[JB1Jǡ JK[K@[/!JJ J*JX @PV C뉴1I IW]Ƞ)`t[m k!Z jiA$@k^Rk@k-I@kZM j[0k@݇$`Zn jrIZ{ {B0{{1Z%X{ȠyЂ{1{- Wz ^&VwcXD0#߅tg5B1 }KtgXJ:+ _xfQC5)o[I7sbSD3,\;B= @ǀUPD78P014CW2NIC-8-BIT CMOS MCU-OTP_JIIH=20i33AHAd{AƁq=?΋݆5P008CUK4?d(<"(ff.~݆225G00-001LCD CONTROLLERZIHHGU<~bG[abp~ b`YX1 Yswp`aW[VYztp`d bVY^_WWY1a~|^[Ka~z^[b^zXa}{^VWVVa{Y^Xaxmasrblfwdxu`af`o`w}]_^VVu@wZmiwmav\ZgWbamoZWs][Vvsw@jmYVufdpd|\\bb^[]a{aa[Ka^X]XXkXXVXpW a\]i]ZX|$[]XYZvZaYpZYi`X[|__LX[X_6YYl`zuPPݛqs\V&\`oX]bWX{^&dbmsXX`P`aXl`dhXWX`lp1`d][XWkpp`b_VVWa{Wkuq]X]gXY`w_WmWBw}`WZ-__]\Zas"^V__y\_]YVk[]jWi$_[WyX_\[lp_YXZY[>WW_[[`lݰ\_Vy~$^^^VZW\^_V\^X_XXŢ^VYZ`~~dgpm1]_XW`_]\svaVZŢ][W\i[Y\Êd @p<2@sbYXY_\W^Wu[l~p]Vxk}Xl|\v`&o{1\o^YYZKz\0"~q`N<*|l\L<, |jYG9+ɫ{m]OA/xcP>,2ԐANSISTmoX_ZVwjV S Ǡbw+[  KXYpAW[mjbYXZ A\~ A[weW~oR 3bwG@@W`W`Q h^ * X\w .' zW]p^S ~W]o^J&eVT" '_Zp(<7p'Yp(0=Q&Xp(G@'Wp(@'Vp %^]^s 78! [}_T `dk 8647Z?3W:K46^^w@2PF61s{7]3::YY708v@2P90z[]]` JX HA1 G\w 9I'IJ:6/02 9HA1 0I3][wA1 G[AJX+iG[Ht3Ho@2J!O@@1iGa4PW)Z1PPDa0PZ^k PZ5V8 ^UY_@kUY^|aj`SX ^UXZC0kUWYPTWWikUVW`wikTW_] W VXWw[U^_ f^ h7pPW.1gf@NeY0H`.cDwpHe[_\H`aQW[^i ef[gP hi HeZ_\Phoi sefQf[^e hohiH`m`iH`dseQVHeY_ VeYf H`z6r`pM0u\1Nps[iNpRXbml]uQjvV` w# w[p w w NuX^\cW]lvwffmNpwzjW whYJ;,raTG:. ugYK=0#qw}pcSC3#ylaK6! ߌwc:&mWB-bmuBWWWv[Vll߉Vul R߇XlalVup[ZX[ /%W*Z/l /ށW Wv[*{݂+$?֛S›iI~֛ ٖj֙$  *I έ?S i jހlx@`Pbmjsr[t\bmiYY ހgX^V}w#0uh b ` ހf`uhmxf hbmbZZV`ksxYVX^\[V]0*\aZXYWWYT vsbWX[lƚxȪxȺxHʰxSYYY W ZY]Y`] W Y ހ7^V,@t8@8[[E@UZbX]8w[X~WX`osÔg\[VZ\wò[Z[$VV`09g݁YXZ^xshu`df^uXZ0Q W\`ԍp`{5Z`AұWoZ[x쀅UPYX_XXWWpV[QgW_ghy梐Z_-P]\ L[ Z \W^[[G=Z<>pVZW _yY(WW($2$ F3FB9FHW s3sBFW# $3B__V_]`fђx4sa q]I>!xcN9$MxeQ>+mvdR@+荀}k\F0ҵ|fZNB6* ˀ}iD4(Հ?dq=?bo\_YPVsbaѱo\^Y_*^Z+ku[\,Yglo\Xsvp`b XZdb 'x?WXP VAsgvXLNsgXX[ h &o[YPh Z__YoN toY__3#]_"Y\]/&ZY3oYX}[zz~/w gY gb="Xg= ! !W\\ Z][b#i 'b#i #|]uZ]ZlW\z!% B l)wШ' P#*WV[$ V"W\b_hZ]Xk"i 6M,3 i "OVw P2XfWZv\s0_1X[JPS$XW&e 344Y#8!c"0!2!#$2 !! ݀P'8i EXX+4i p`k$O/HYW`D ?JP`#W^"W\W1-k`w[ puVG A"094CXX4 0!C1# V\f=`]v {0DX@ KW[v Hs1@\\v {01WWv \P\Xv{0V!V["Y~" 0AQ0b# 4DX# YYY}X#@S#HWM3 [TV'1VkRhN c-hXXdhzcPjd0 !VwXvdB́as0`ARXmISs`VXf`A`BbX_ƾjW[-g#RsEq4WMk`<{0hXs{0Qxa?R*9yђJ{$^}+J{i|!݆qy/6 /#r }o^MB7'zkYI;- |pdXL?1  U_[qpseWI;,  wvj^L:(tWG9% xd< 1013CN82NIb=.ps3sVBsWy\8oio)Vlo)~roQKrs^]^Xbp W V rpzfuv{f r B5 j@G?rppfbwrulj7}Arowfv0{os`bwYU*ajbifblXoosurafvǶJ[roW`Q yWw0 rmrxukfwvfujfvX r\{V ИZކY^_WP.Zp}]FסXޠ;p}W]gYrswW\@QZʑY!W!9vp|Z^ LY[ W p{W7W`zAjeTrwX!9fY\Y\|ZzޢYzXz z F$#z\4޵lްV.poz`@#za޵Wް !vbW"+osV[hs+Wbs6Zl]yCK][pR !YVuRƱPoXp`F`l Rl!sWoa Rƨp`upR!rvmrhjbX2U"bmjsr_XfV,X``Ardk"@l_|3lΠEZwxFY]ևX]ֿE !d7\Z[3  #[]]Zb CЏ0 бX ` s Z P0w]$d[YUY0 YY? V][b V V0 ,Z_ l!a]X\IР`VXb)ô`f ` ! @_VFX o_zX^\o[1D 1R^:]Z~D]] \1l!]Y^ -kw]ZwVd, /]<@KXWU%]@C_v{00LpsTp{jYH!&~paPA2(Wwj]PC3"}bB"cD$dD$߀D$buW X{vY|_[waXl\^ [l2! \u2 ~Zo] "N !]uYo 1Yl_yQY_uqYu-X-@A*Q-A)N *X-A)m 1-A)Xu&-Wo^q-:[e0=6=9l^-`:`p=`:04=c7 =9 -:p9[usM IM$9 /M_JlDpM8koMJoP=JlKl o\ @`A``?vmgwbSbd PԠuV?VX^-6PVm0=W] =W[ =Pt|W_ $;s{V`g\X _:sujk8TdVVa]V`TssUU\rЈUWP)sm&iIsl~ Dsdujzf_g*Pb^%a[_C.`sQ5a[`M.h[`64bZЃ@eVIa%aY]`s]_"[c^YbѠ\^ts[WVY[ 4-sYYYX9ud@ 0Z W[W^ gXWi@p[hV^yU[FPyY`PfYcRHwaLWyq Xwryy\Wx/ryyZV\QzxAqyp0sjpfYoordxmf< `@ bB"fF'iJ oO0ÀU5xX9p/;Lk =<ڇk sʍW 06AUȍ0獕Z&Ԙ\Mke]<ԘYlRAĝYaL㝑_Ωk"BA a-"]ݭlk <˹\XlZ` p {GAf@1= Z0 ȋ@Vɫ@vl ĀA ڽ$ٗ7͘W9ScYrcهW 66ĀcA 3٫@c[ Dc]_@c/ꡐOc"0n@c؂^EYL 1P'O^m  M} M} - l0s;dD$gG'gH(;* jJ* jJ*pjJ*  zU zZ{X[|\^wa[  䀷 Zu] M mG7>Yu_WYo_qFYlw*-_uG*^7-YuW-*9w-X-*P-)i-(3-':P8=(S-g:װ7=)k@ w=:B=Wu^=:[=9P@ M1yM9o^=pfJy`vMfJX@:MiG M9W=J[MJ`PMG]9^u =dZ0=9[u t]Zŀ]9 ]9]jobZ\PCj>V(*Gum후_"1ͤhhRX ݘ^ y!z0혇]"PmaxPyX mp}װH<`@ [;{[;{[;{[;gH) vW9wplZ1<+ s^`|ZXu1Ŷ! ͍݆B ߄4 DTr̀gho̍ĒP cP&cpꘊ&lXdJ5d8 񐭠l rf@ Lr gVV o4+r T]XװM\a h0[ غ0ȽZq `PͧY_a@(XQ`HXȨhPq`ͧX#͎l,q@ɀݧb(XHX*hݘQXةˠXظl ,~furrOioVM^ m}iH}]}(`튧\0r@pP}pm u\- oM sU hJ,vX:#yfS@-9o\I6#xeR?,n[a5"TA.upRB\Bdcq\WXXkwjWV[ Z Y&  V  U U U UUUUrUaqVW^z V^X TM\K\^) K\^Mk[\ [\in)[\i[)MZ]- Z])-Z])MY_ Y_Y_?9 9M8Y ,8Y?8Y9 x9MX$ X$JX$9 9"M08I8\I 86GW$W-$I B#jH[W[ H[YJH[MHH HfY,HHIYYHR9Y4 rsv}H  D( 7gi ڝ7gcmshETveiTZu] Emgl] mg]})x m)x$ѾmeymlY 7}umtp P vcP=*lYF3  ˀubO)}^?fF&jK, nO0p XVYXvmg}sbä́X[؆W\؀V ca[|WX:Wf - Dd<^n[?"q Z\#`I}^ pW\0ʳZVpWZI ^VbX^2\ X 3v_[\\Wbұ 3vXZf޷r"B (NvXY[ahamblhuf}af~fmp;XWXұ0W^vCHjXZz qVzW| ߡYVzf pV[VWYa[ ĜZXŰ Vgm2vvr.y[W\ ״_` FfMr|WXpIrrvv8sp^\ Xqqup\Z X0Rת1[Ы0dٷ0ت1QԵZZYTsY貪1йpYW1 ! qiY ub \V]V``b_iu``rw6^ *^$4U \:$\H\ \n'[]c[ ]\Qoco [%\QZUsuЯvfTI>2zocSC3(?~qeYL@3Y]}sbUu<0$}xgWG7'waK5 qZF1݀?[bxZ\vbsavX\`j x+wXV`U[W4"v//ZyI'Y` JX^GX'yw~~fXVb{Wsg V/Yt{j ߐw~Yf[Vb{W ZݒY ( (WV`Z (V[E% N)YE% 0| XfWV~XfV[ X6#`` pw|/dYth|"oaXGB$ !n%W [g ]V^dpi!^W4Z$:Y>$:X14$0W1VZfqw^ZX}|"}02*w4V05V0z1 w]e\0404] 0}!\g^405fw^6]5d^F]5b^F])0y1\108BX04I@Ə0\34[f06Cq@]wEd @G]G԰wEb%@ G] G\ wEaa^ G0G`wE``0G](GİwE^04'P+4[~1-U\AnAVogHXP0-U0`@!^P}!Y]o"Y@%3Y mgTiT`pxZoTP}!X0 4X0T0U@U[oTgʙTXTT'ci]0faXWPT%W`T3PWYVW_v[lZP "ndapo z`jgX[` jWoZPkuaka zj`qo z`wWW] 0 swWVxIpV>qoam` |"V_[PP!V_+uW'wgoWZZxlY@"\`i3Y`wb(L ip(ߡw䣟{<|s{ݣw%{9u5{ws9ue{Yh}n_K!ٿ1m]M=1% ]_M;) p[K;.kVA-lYF3  zjJ:* p=I~YV`PYG݁YY[XX(~~ W ~ WV# |YoYYCGXXC -`:1[PGW[  ~WV pCG$b}sufvvsurhu`o`amfmrhjbd`w`arrl }s`mbW\mo^X[{wp Ғafuwrpfgrxu ~}]bYZZsbz Xkb ib W__;W 5L_X^`ZYy0}YWX ДX_]b[WXVY} Y/X[\]  b ʬ .VWV𭟡Yna i ;ҒV][Z7bu|YQU4Y;CW[];X[;TXOXV9OC|}WWbB [m|=wٱVvִVs|v^z?spsŸpsp ֱrWWZ.2|wo^uw*8Ӑ|l[^\ZbsbmmYNVUNX[]`UsWYNpV-`Y|Z^/\d|X 0h#Ж\\#Z^Vd[k" WV![ım0V V[=pW=pK1òVD/#():dT#(ֱVW`A(s}2p(~H|Z^oD\YXXZ՟} {_\sC!{^B~"{ZVsВ{ X Zs0a:q$>@zb'`a)`qhTlWWЁюP:䞐Z]XD肼ᡒl䞒L\{Wt%.V^ Ysw`jur @X V. z^^V[fv8 V1zV[f0WKU2p)WJ|d Waь`Vq\6ь\\oEY/ u sysfY=0")3ZG4!Cyj[L=.qxjZJ>2&}rfZH;){iWE4%30{ŀ[ɀ9̀?dJ?dXda0 i61V@iпdX_Z^=pV0XZgVWvs )X0Q0b U1MZV07^YZ@ hX^0 yR@ y`hW\0/JhV7]. H]b0" ^[ 1CpdX\bZuuuuv05#V[Kh{uBq7 `M%V Z][ovi!m" k"[povX""hqm gI1" "X[d #WV k"XNq!X%` "#P {" 5J ZsP 05!Y:#0abpHW#Y`54(0Xfm qL1i S0 "VZW_"q05P_dWmjoz[Vi~[ "Wd MW 52 #W^V`2W\bJy"WN1S30ie4` 3u0EVY DX F@k WWW7V[ YQ@X]^sw3]B]w01@1V[szEEfm@^vB[@@q@\WX _3 @1VVx%~Ḛ9VR MC. DO WR_3 Up E UC 9VR UWVdWVQ UVoRW5 VWg__]Y0VS>)ѧS[RX[U__XFR E"SPTVXVA3VhWZa !jXai !jb !iV^a!`S\` bdoE"_V[f`%b\`pdWZX@x2`WXdʞfWf`ljЮT2\\C"`[` 0^ ` a@u0dY[` t$p9t1qV d w^Fw\t dW\`Bnw\sup @TqranuV`w(`ځZo[y#?@~Lxn]I?1%1yk[L=.g znbVJ>2&}qeYMA5) qdXB+ n\J?2#wbM8)9B_ff@dC\XupwP Z!D V0Vhwuf@ 'kX[1:W^. ODO\. : \W[omhayral kV_V_= ahv`[qd[^^Zaݒ[[W[Y7ws[ BB!"pX`22!@5 [VL#V#[V^ aCIZB8"[V[` ([[ vZW[z81k Z`W\XpS%YWpXVpaWZpG R[WW]I^ojvz7 X2WV` W)X/Z^`吪(K@E_#kZ^  Z^  Z^A3v@v q b0Z]b\_`dk! [\p@05 ZWibd1;'ZWcr0HV\[ Z @5pP@[05S^1 YYv@bT2|CpX'Z (@#КƇЎ2VwVWsZ.(:5pE$ @@+ּ0+x+ aD죂jӕ vӛY]P _Pn R^^ ^] ]]] ^ \qPp] ֞q[ `[c9k!`Yg NXXg 0`Xz{[mX`Wo?t5!{WĞ)sj"{ob[ei@rg@ga@k{!lXWod1)= 9%WDJ 5!d=D b1)3gmX g! !bQ/gvsvpbUH3& p^O?0 G{jYH7*~p_Q@3%vj]P9" whXH8( xk^PA2#?_!`[0^]b?[Wgaͳ%`! %0! % K[Wi KZ_i ! ߐ^[sw`uh"^[Y^bwr]ݒ[ ZOa1^W]@pCP'pr\s #!^e`Zbk ][VZVP#X^%'%$Y ]X|\Voz"X|ZXVo`)r[ Wp t X"z\Vdbd w"z/#Z2!&#/g"IzD I#W"1 I# I#eW!d 0]X |O=W{"YV`\4 |7:5 &0m0 [w|=7V&0ߐC1 =6W|=5gp/w"deoN&0X"do!}62A7@&03bN t%db%dpCp7pt g"` d |22 % A=5&0C121F1-F#1F"-F01DF1-F@1F*1=5`F00w"[`[ $`"@Z2MmV$`EY!@C0DCl00C"Fy1@BW "\l!`'S\^/R%U[X/R5VZ.Sp!`!p>iUXsxVV^q YcшW`xPARv\|Y_aC PRQV V^PXVa hf(Pp`PXbXXv{hV|\_ՠ` bc`W5S\_*ybgZhbFS`W\^a h`) dZb FP[V`h) /\Y]Y]r ph (\CXX[ؐcp;pE\ #% T( :Z)x:$ .#>#v"UluX :X)x:uzi[J9, /|n9C6* seW[& xwi[H;/p_N=,|lWD5& veTC0560R28201Y20MTR H`wWXh?`wV^ |`w?\]Y yB%]Y`0Zb\0p\WВ0W)_ 0`/v[z] zYI`sgW[vz\Jswsnz`RpYV wX[ Y̐pXHw␹ 薸 XV ̕W[  ̐w`cklf"`b^XZ^gs UZGXOZXPiWtiVZYPiwb]WZsXs ib]V]ks \\ YWXis ęwx𠸢wd !bWXY?Xmbk iXVmbp*@sz*6LV\6V^ޠnfsrnbs*V^#pVE^6=5=`XaXYVz`bKۼWq~"]]]\Xw [0`\]E\YVi (4[WXhWF2!£ V )Rs>Ыssp5cg s saQ'QV5'Z\ (03Ze`Zz!>`WYQ9P4!__bwuj`mP__ba Pu Q  ` S_\"]# d#Bm# t#B}! [" \"E10^23ᒷ!11$1[2#Ⴓ1Q33 C2d z(AH-C6DUD#&= &tD H1I &D H1=3 _\A1 [_\[ Xܘ[5P uvdRF:. 1naRE8G xj\M>4' sfWJ<*rbM>/  thZM?1#xiXG:+bY]g5 r $ V 5>\\im\g 's\EQ VbY`/VV|mևQVҰ^PQ ]~tXWYQ &D 3!E^%Wa HX 6r[ AbWbbY``GWY`q PӐ%NP0a #` ZVh}-Lbazjdfrvw X#X[vY\Zhw4!s"|ax grT4s04w|`#pavw_VZVg` W <2@0\ Z,S3XZ|gI2e2avggaW>aes{20R1sg R4Ĕ̓aӔ31aoforu} Y"kl =|D!gm`viI25"ffsuroI2"d/jrdf" v1b w/B/A 7Gvnv1^X\ aȐ 1\WY v{Ea[?u[dZ]Z* I$HWJZ8 D2\W`VaZ[VɐaYV_p@CZ@[e@Y@:A' a@AU1 9G32Ra5v12R 1Q:PZUgam]RÐ1Q]:WӓR1Q $1QP"V 51P_:V_'aIVM!QTeVsoPsVi%ggFV V\QV5=1X[XzWX{`} |rra[| `|R1aZz iYH`LRZ\[_/QXYPtSW_3W^]VZcqaէWeW`DCa ` QWV£up QYX #YVX_k#`zD##Wq5 cWpYY0v`xr 3q&1 b0`w`mjp_lfua5SrbrpzwuufgjbwfbialsҽtfuwpX r_ reW<,!ufSG:- |obUH:,{lXD0{cO;'ԱuaL9'~qdVF:, `@-@f_gw  V ISf__IIiI v 'R 3QV5:GfuC_<9V4f[V[aZ]WlWl\fa]Vb0fpVfr~\pYV]fZ]X~Yl (fZ#W" =0V]vmXXWk ސXV[gWVY~Xl $NO fT V vXڐwfV_=YV_PX\V>iXt\xr3r0uh issY $ss Њ &q!sg0 0es0 0sV;p3 RXZ< WYHoW\ M"kl30pfV0t 7CvDCvNA n~s~aW;p qCaCp a/Y4ӱV1j46\>1$ZZ!6Z!6"6"5W_008 6^!5]!6Y00806X00 R Hk>5W00 'HWk 5V1 CFu^00QHkCF!CF!CF!4@ 0!YV#^a!G/1H FY>1+P!Xk]W EWX!H+SAAF0A W* FWA @vP/hXVaH=PZ1R EVW/1 SXl1EVV SVVlz27TW[@P gw__pbU^`Pgu; ̸U\ VtPQmdо\gb_VPW\VWvvW[Xhoz.gX[zi`j͑bXZ`[ $hWX`$`QWVo@QV^oVe\oI@z\scstamu vsfxr ә`rpwrub`amff ok5w cW`\fsg_p6o`KDmPbPl#Z\^\\\g{Yt[p]YZ\[rppkl_KS5tsLd xlar{ 5"fb_bz~np~b_ tvs#tv#ݛuXZ^9ΛuDiQW`~dJ1~hR;$K}_s^Ee|hQ$ _~qU9-!n^F.}̀Հ|obUE5%_pmhWZWZ5"mbYombX7\}烟vudjdhd`]V^ {i+1$Z- 2ׁYk L C\VwuOsOɁYZV݀ւXJ OX_\wusO\EY`uWwyWjJ OWP"/mWW[iۑsǕ Ypmvs gs mljwbrupfu fpwuf Oi`pdmf OĠlwZ Y[V\^]Z\q'"'\[Ztd[_p\lX^Z]Ygpvls`mwrhbrpzfuv?jrpx&Y[Ĥbvrgw 9vV^w vVZ X jjs @jsW?Z_] B",44`4jrdfvpWrjpZ^Z^bsemma^p pa>WWs{muqXZVz!~ FWWb pYW"ֲ·Ͷٶ­'·`jmf`bA[XX/`eWscimfoWVhj/`dy ĠBe|вcd±e|VWgGa[fpBØٶԙ·Ũ͵YoaivТY`i@vЫXiXvՀҭ¸֕Ү H㭵 · vճWo W]kȺVo8U֮*· `Uࢲ@UVVH U"7· Us · Ulhjwjbvkhjbifblрⷳ[W # spwjU>'yj[NA4& 5~o`RD6( Ip\H5]}m]M=y xgVD2!yhWF# q`o]ZmvW\Y`ppao^W[^p{"]p3o %\p}"[p#ZwwWp w_`UY_APwY:/o @pXo X\w"'[#XC+o UX@p C Wk`WX "v)Vc`-04APv(V(/*o&s= )[o 9 )] 8 )@p) j:osJ0`mv0ob3[]\`{0;Z1;Ya00l4ZW0 9Y]Z*0 ;Y0 0%T1 9X B 9XZ[1 5K206]IVZa_`oJ0@K_V!b^bF]bGdG@CZ]G,!FZsLG!EVUX VW@ 1Wb PCW\ PT[ F MWQFN#kW V!W@{UsWW$V@pW Po[|mbo`VxցoX]|w]oX[*`.eY*`.`AVVXJgWZ#bWa`ibV``аoVW^d`w`arrl mβjZӔBmw Z]VV hdpV `ɁuXGPԀb΂ ԀmosX\X[Vhuffm eZh gX$eyg `^`x`ׁo\_fJ]qI"b]p^fdv^pvWf;keuWdpZr[ypjet[^vVfdu[WVpuZ`pduZ_pp`B$ao_YppXp]C>L[1iXYZZWuV\:Zкp˱а%^Wmv-_>!_v1v("AF@ 8^Qj&0U^]1h%070xl@jU] x\]gP ƃQ0F0_V0t#0xY)_V1YhY@h300V A4ePv\^-!A'0>!6 ! 8Ya UXU^P X@ $]2b B[ X[]HfPtZ[0!Q$1RP gP X @0 8,Q_W$ddsT !"\b s  sv zl^OB5%1xj[M@3%Mt^IY ybN;)xj\N@2$~rfNB6*|pb݂5# 1|$`o!_ #ao!^" o![ }@"WV"V} `o!ݣB) W\d;"W\bxasoYdbraڐW V `WaXr) SaW^`)tb!Xڐ_`b #&Z#&Y#&Xq#&p#&V#%V_in#Y i ڣvc`h$V\aabT0i 8 @t0X\b`R`b` 0t0W[^`]`B!VZbXbt0V_XaKbuvY! Nh7`6V` %2V-4u 2 4B1V I6(1d;661-0$`uh  augb` 1u7V \V]801, ]V^T001 pt_ a2\ 0tO 3s|Y3wYݓq aDqssl_}fmmr{l_ABufd@@Bhuf}@@ .Efp@@`Bdfb2E ;Haur{JAfIm`bl@@CY]Fa@X[ G@+C@!C@>C@B3D@CCIB@IEZHIqEIamxfA ZDFWH (FTP!C ;FTP3DF}SIB@CTPZHYqE$tY.T ZD F-U9@o_[mp|rW]\aw4fП\Xd%"WdVѿ(W[ߙoߘ o ߗ ߗW* *ߗV?H!`[ $[  i^qn`Hp^ Ͱ%Y\_#ͤtߔߡائ^ ئ\$ئ!.;_YZb^]II\ i;Z^> o ĉ# T;WV[abDzs Xܰ|@DZ[[}[q Zoa0.XXYvKV\Z]V` ]-X]W, 1XXX,I, aͯ , y@ Vg~~ ~)`y!p1vXfmXdb[z&"XZzWXz!\%Z_^ 'b0&5 &Ơ%Y: '\ K`_wWX^l p 4k!p }3{8pwbsR@vvO]WVd0XjϤX2!Y[ W_0Wo@]vDZiaA =Y1 =XXEV2 =1 4#a=@b8S MXa7M3QMakF!xY`k0J(C6!cyKEM~DMaF Mpb]{Fk0H pa k0W2\T~vi@u3\fZ]Xoz`X fv/U`PYrTPu<0(sYar{)$2vsWRPsQ P̢R"vgPЪE͡hdfw[ b)bZ1`(*a: ?iX 1`ibX>_cW h`a]\ ̰QU_ _ ޢ_\Y_<$D5`^+Ѹ`d]<Ҋg\<f+|`bVVs ` ͡^_EXS`t7w?`^0t.d^^bFqRpEr4r^YbjwjwjvFq h4qː ju\Z? uWWfvd WW ^VVobh 4t |pcWK9+ 5teQB3$~oaRD6*reWCu }kYG%qdH;.!t`M>.X9t?oC?\|V_]Y ud@hPP0|V^^_ Z zW`ZY0P@{0P zvzvnVZ^{{XZn;u[0[ 70>Y] +0; ؗ[ ؗ<`ɕXҒؗYꢕW[ZɕWҒe zs[WZ `XVs lWu lzsVP\Y #̙Yફg/g̠2ҢZ^ g .`p`Йg= = FX 4c[ ̠dlvolsbobjPgs}rգjw:Jgg¦=’,V!=̠agpldK |K.`_y_y[ADwOГpyǧY_#[D=p̢zab[ӮNW aaf0&t ̑8Yi &҂0?ՂJ d`aO[o nX{g Wog `[1]VVw][VaW IZV=D0 ؗP f̑W\SYVVYKX<2zV}VY JOxfwsmxv 2xb/f][]XS\VaaZk aX[XaW[WCVwaV[V[a!~l u_aml00# jY]v@2n 0*WzD0zjD!z5Q swwXlv ]]uf| x" !o__[jV1wbm[\Vooz FnR` fw&sqp}m]M=- }m]M=-}m^P@1!}m\J?4'rg\P@1"u`RF9- uePA3% fYb0PQkbZsvhg?SfZ d*bQy }  au[lh 2nQfYPuYoZd3hJ^OghpWy_u^4!_m xc! \Y[Wag8yUXwTp4@dVXa>0" "W %Wa{2afXvw}sf#?Xso]^X`ovmWb6PV>S j`l[#b&ZX\`m[#b%gV"{Z]!&k"#Q&"#b C lVoo`k>$bX[o}b$' 'f^bXf|]dW5/1Y00U1]00 X\_iY_`fXZX 10K30T4"a3Q0j0 C V^odjzYaf Qz4`0z0Y"~5 5110x2_Wodzj1 5020WvG"M 1`b```ftafW^]`=3@`0Pmv ViafWIT3WP0yT0x0WX[v40 =C13W"|7 3`C13dP~5lE5}E12 nC5 0UKPk20^AvfWvs`uflf} 1fVWaf`dXVf0tAVW@Usl~oW^\Vivfi/RZ60J3Rd3I RV|P=PPQRR9ZUZ&S-P<@QVbKPQKW^&S-P!QWbv=PP~[f0 7R Y XV YV`VP0 PP b|WWW_FSdij'g^;hRJi'Jg]g]zi'g\Jg\i'JeV_Y }m;diÀeXa iigWa*y*yJgVa Zy Zy `.m@I>p{i as[^ wuds yhps xrus p mqaQA` |5^O@1"EweR]. ooyK:,ٍvi[?${l\M='gN5  N x0\bs`{h[D{\D{PY@ ?G| 뀑b{Vt %HVt\_bV\a+R\_EaJJ2\^YGs]] 8||X|x| |\_|\VW; $[iX}Zb`djpbϛWzϒ}ZsF2 yjb@ߑ [fk`Xiae[bvuWs||+Alk|I=tDItSIW[bkuXs Lkt5y {tX y>jXVs!NޑlܓեжZ >֐V&N Ef[`|6aDNV-`2 Y| PV yutbVL0Z@d[VZ\лVYѵ.аq @ ||wXW6dPZ WW"YzbZYv"-a3x8@-dv]V2IC 8Uz]C 8vVXX_^]ZBVW^_Yxv&0waZ y@vuvYV|ŢX5"mv[bZv aZvW XV|* bL"ҵW' 3hCvY` gּ'āv6;07*lڼbw#)u#mXWdWX~`wY\W W\W u N0==.=]N7`Y31E3\N0:Р_bpwvh:EvjC@GIVABF[JUAm@Q _^6E[\[\BAGGAUAIyCmGZ@BAGGYXYXBAKUAIfCmGZ1UA mGXZXEZBAGG/QUA%YfC K[UA m@61}kCVvXh`\^Va`$XYYWd`YX?XWb`YpJPWdPQYZ]QYPPYPP#XWVVPW`PXP g`+aP fWzPTa YiWVYJP YgkPAai?`PYgbPza ix`P `-`VXWWbLkVX t3!VW``^issuZ[ivfiY rpeauw[YYa]^lVvw`uwfu_`v}mjplj\`d:dU`d#@dhp`[3s|p pyq&#@ txQ peo^[[*Z^[Zrpf]x4d?]aYWWp>*\g`a.V@kqbQ@/ ui^P??% o]J7$c|jXF4"sP>- n\K:)}lZH6$VRރ bf`xW[XfM.-` pbx`dnYYYxb Y@bawW`x?`=3faX{xZu] >ZjYR: {jXI pjqjqVjaX`dGvjwΩvP +1Р}sܐvjWz9YvW ~lYv+1 kxT@mߡ~ߡW&,`+1ːWv fx~$GW="N =N+0XNX< }Ȱ~B}ȵ`WiMp]iI !ʝ +0v E˞gżPX8bgWiPks0`vȧP ʚPksȺW[ʚVcpBal$V^DJU]WJ\WJ?[Vbb JjWb JX $^__] W)QZtQ_Z^P];Z^^p XXЕW }q}PZR[3 iYb sRYp}TY[}P^Y1u^YVvi@ [warsXbssp`sT4upÐ0 Y{+[btg%Z -$ ! O ^ 3!|M |k!м} !sap^L:(%}jWD1 Mq^K8&p]J7$yfS@oI6#xeR?,59ldZ60Xodx dWQPYel?"@R?ek?`  eh   #*egPlaI(?`W!D\*V"I(,`W!*JV"edW!*&V"!'g$(z$I($*V"'$aW!:V" 8g$I @:V" 8$ f:V" $ixWha[ Ó1[u\28Z]Y1:X1 :28P18`1$:2 :28 17IVZha_JJ2 JJ20i-2 DhbWba\u^u FeuvGaauJV@FVla^uXuIHpIBGkau$fzb`P!ݎ,R4P8Y8Y7Hp8P)Si`u1S 8W{Q3Q TqZDS ZYFQZXX4PY-u Y7:YVuWr4PZvu 8Wf0T%bP$iWSijS1gaRlQjijS1g`,ÀWE3!p]^viWb\@߀`|Z][@Vk| .bXXꀹvXF vV^bfdv' taWi^XXkg1gpsw[\rws0xY_rYrXZљXYswsWrr ^wW [+[r +q VwtQsvWXW[ ':>sv[ ҠsaV[WV3̧t̠.rvjzsp` +xbs\^Yf 0` @Sh@aX{Va9-Wðfhdh԰b\h bV5hha,ø0'f¹t¹ԹԹ`a%Էf .ɖ8.`a .Wpd Է`f9vɳ dvpbvɩvWp 4ԶWz}n a YY 9 @dh@tkkdǝkb<٦<٩a*h@fԵW\X[VV\X@os_X/gnV `Ɗї0"ت0ؽ0~zaX~g hظ&Y_U 9Y LYQ ܐ&X2 X +YX g"'` 6&W[*  [ VZ~zb h@~zH{ h"\skpp^L:( ؿ+{naSE77K_K7%e}k\O@1$p`QB4"~lZH6$fzim`@1`W4AfBBv` 1H=1GBX B$\_>(WY M&|֠Wm'V]| 2#|X_^l'Ww!|'W!)ZX| 3"zY\> $!voR>&hYa%Yhi &g[ > #g0>&bWX_+&a 16FA>&p0@> ۀdv^_WVVWJ l\1Y k4X u0 dvWWl3W 5V^\0ugdVZc1X[%0E8Xc01=Vй101p|o5m0[1pY]k\ooĐxFpKgIYBA@L@K<@@ܚCW[AwMM<@EWXi]CMgoM<@ @ BABLB LK<@ ID $]*@8]<@@\0jYdjpz`][Vzg|dR]XlVvP \0bX/[bYV@@XhLZ<@XW[@![tZ<@YQ=[gY<@`G{r^VO &eI 2g[\ 2` Fb NgZ 2`+`YW 2gX[hgXXZNgX2`(aWkaXZ`bVVΐ`Pc@2eWaNeWVKeVg`vsZVVdJ?"`Ldpۄz}`u vz} u 'x#p 9y'x+'x= fd|{r Wb2pbF 'wxd> r seWI;, teVH;- ~obUH4  }p`N<,xfYL?2% saO=+|j]K9' Flka hEli` wh-~3ipWp`xȠ& & Z &Y W:!W!J &V^_C\U^]Y@Wo&Ж[]ɑBWZ[WXVWFȠNZD"<{Ƞ""!bQmvw~w^uzgo^u fml`lZWXszb Xog t xu - Yw,<$Hh_+zZZ#V^0 x#B{4<[@H-5-'Hy@Z0r] +fbwurvfpvjwjzfurm&m""bxuf| $jbj`pvhxjdfz rzm]d XXl1 *m]]\Wbp'm]\"&$[V!5XVX 5W^1"6VZ 0`m[V}fmmr{hu0gG2{ijwfW0n!G2ru`phf`B7ia/amxfR1W0 @F31W0!Z[^;1 40Y 7Wbv 9p[ 5Z[17!6Z!6YUV 6X!5Y_A5 4XYWALEX#^\![GAa@%]eAyGA!pX`WbAX F[GG5F9ZGYG/`tFG^@r^CY,2yEWXV0 (Y0yEV__b'w FV+2 FVB FV@RFVVPQJW^QPW1W1W!!WKmW\V]QYV|PL7~0hTufd~0T*v4kic3~0n!T2~0RWPmV^ov`]hWZtliP|jZ5J_b\ecix`iPjZ5m{jI@jmfz`m`!`lZ Y[V W\ "lXVZ]YlX[ uͰ p&W\ t plU@x Vp3Qs 0 xM>mp[b/Rbmpgpxiphsfxhr:qxhwyc eG# -7r?9* |j]H7&sbT=0p_N=, qQC5'eJ(p_sv[wW~܃XPk܁ P; Wc[ TZ`X &rsvzsurofu`vfugru~^^Ftrs^o]{\[`YX; W >psi v ufg Wהo rssa LnshD@eZ\ "T@ "gWYYc0? aNruhNamlNfZW 8rsfTi9Pigsdv`0V^^] 2\Šɧ[ŠɧZŠɧXŠ5ɠɧW&ɠrvXfsYYWa ,W^VZwaVv,ss`v;pG;C0pwWkdX^mݰX^ J_veaiA tpdbasmxvWcpdrgmjpfwfuojp`wru=abmrv!d]vt ֽeY`beVzpb $``|o tnoxXZ ` -QroxP PopX[b\gomg#lcah{]gY {g (l`aWh {] g Vi ${5gl`^WgW{igl`DQ~{fomV[Q^Ro^ `Yro5p67٩X }p#oW\]VW_2]<=[ZR|uW{j !-xu-+cv `Pc_+a'+;svE(&Z& 4X)( H$p ) Hd-t' +Spmx@"wWѶ@ sI@ ʿq_M<(vh%D2 ~lZG$r`N<- ԕn^}>. }nXB3|rhYH<2ÀSpwxX` #PkJwv9 s rp P</XY }gѐ5 ;ѐ5r mli;d swb}pbwa` v|XgmпWig{=ÐX "7VX@z`pp VY &lP&[0&W[& E #$W vx:1Z ap#Ol&X{("p{ m%X a{(X+(W a {(&X] A >(W Y Z0vvV^bfdvĐ R^avo~Jp[dz]b~!3`z3s &1+5Y$3Q1:vgXdvI`Z 1bkuXia va_uYZYWu}"}^XQvYd 3a4W`5b;5a0ur)gbvdv04X3 0"@umisp4 GYYj`3hW\ZXX \Em2/F[;;LX;I/'\_L`D`Ki0JFVWDIkBLX@pu2mauXV]ZusX[VhO D s2hJBGWD @uWhr[23+P45WY34+PD&YVV]45TV73 3ti}s\V\•UUZVW[S[ZQWZS[ZV][ j1kYV1`tob^ OVgZ#c`p[bYŐqhXZ qhqig c`Qmv^bCc`fj*hZbhaSjc`ڀxbrs^]^VXs0r K;v/OwR:u3dmLqwZ@ҶLpd^urpxs 0s6Wo Wc)puh[H5$ߪ3`L9&M}jWD1"yfT=$~bG+s]K9+q_Mp)pQS p}p[\}pZ[oV\i ዧg Y: g WL 0RւYY.`Ao|{WB 2|wX\[9=Y@ |s]_ \ZqL𕔠𐰑sP; q 𐫠|rYbXVoi~o (W\3 8>Y^Z3 8>ZYW^W^38X38|mZWYY{ijB|mWZXruhdsl?qʡWmWY\2ǢamlѠF|gv iu\0sg WkZ] m6XXjx"P")޸am`blujaarp bW_\\Vr 8{p4@fp{pPKS򀍠YygyʽD[gY[VY^ {l@@zw/` 0zg0  0zpwusEbS!,a1zQ` 1V^ 1׳__Prz5pp[K ~7Бo0gQ!ҭV耐g tڸgڥWM 9 ovbV\\a[maZmJaXmSgWmgPgQYcѶ@XWP`  nX 1ol)aVn P%P@zo`WKZ{zadbK9 ig Ph I`m obvX[0}Hx^V{0 wx&` X]4 W]ppspxfTB.ؿ1xhXH8(I|l[NA4' l`qH<-pdXI4 tiZG) }hS=2  gY_^+Ӑ^Xd Zs gY- gYYZ\[=\]"d\hp5jwZ5jY5jN06do*XW%e}bIpuiW_j^j[ udfi^5dc1}sbsurq}puhavXmȒhm{tpb/|6/{ upsbe}Dx|gF}}p]XW`Vuv[A7+oZE1= _IMQ{U]O@1#}pcVI}/"͍yh[M=-ugW rbRD4$ H"`w~pb W\Y^  f! 1.Wr!pXW KPVa\Y ÑX4Ð namj ʽ[JʗXQݔ& ZJ!ʗ>P&ZY0ʗlX&YXXrʗX&AX0JZ'Vʗ+I &;J:Z V|bxwR`vw`ssvI@ !`v^ gq luzlbWW`Wag`]ar{`[XoV`u3YȠ~Z\yD@PRP@۶zA0 ۶Z` ۶/Y` ۶X۶W ۶۵Z_Di06^&@6װ6ƒ@66$6 66%7WV^XF @V4bfK]XWJ 0^Vh#g-Ь $-\)Jt<\V.Y\h-Y @ !RN1^gZ&|ZZ $l!| 1AA! 1Ȣx! Тxsmm!*dwhNA6*oYC-yeQU)cuaM9%q]I5! 峀p]I5!gVC0эgBbp]ZZs`xuW\ !p]Y]wwVW]iXY(V,0G7k`xt 426aVUZ T@ FTX\Tv3Vbvfv v W'Zi0W뀳xrXZ r" V'iSVX[i<0fXi]XTV]s``xX!YT0XҫҪ0 ҨkVc #r6 8f%ˡr6ߡ'r r 6/Q X6a. ºCººk$ºº/:6[t.o ko vovˡosvߡop ^lovho vZڗګ H^ п*6Z QV`0W bp]^[Ah t|WZ{jZY\S@XWs0sXY[8@f#e\^lrbY`wbX`W`bs`^~ {`^~`W[~T  _  ^_v_ #s[V?[ {i@`IYP@`7ZWY\fJt[JgZAbbYBwsct`L8$1=q^O;'ubO<_{k[O=+sfXB/qZD1 PsfWF4/"ԃڗf@ܕfdva_vW`fpwX WVdrhV[obvdVZYobdvdhFX,dm0bu"diY ' fjK5fv\|rmX v}6v0p v@dba/Y]sk0dpgvo`PdbVV`%bBv v%" v@da a N"CW O"DO"$f"o1$f" G$`aWR(^$"`D!"$D!1$#2 v`d\ZXWugUL1S06[[hgu[Zd5vfuzjbfo`px`m .Bf0j0WWzdM "eigZ||| G2XVZ^uS41S01 WhV] 0 7 7+ 7= 1W[VPqfwOA XHVuhwv{zpv\0J]g\a0]ȡ]h`>IX[@JV_@HiA?IBHHAJBG]bg)ZX[b@)ZW[8P)ZV_8P@g0Q`V] uZ\ uZ[ uZZuZCpF\'@\,0QC[ Zk. ZkRAT/['l^[[VvQpgaZlb rjkYZma rjX\ma klbrjWbklbJZ'^i+Zh @w %z/ 9{%x xu{Duz/{ wb Cu{:tpZC,zl/PB4& C~k]MA3% ] seWI;-u}{naTE5%wmXC9+w\8U gjmfi`pd\a`vw`udbxw X mf) WVYdf ^ ?mgurx"[ XdL/gm`wXdH0hZWVf>1hZQh[VZ~9XWZ g1WW ((Y0Ggv GjZ sYY sgm[MZYZX0fwgfvYWWKW][ 2أ\Y. \0m Vb][^XX#]F"Vfj Dbvw{VOuU[mWNmd9[ yBPH0fa\VkYV^0X[0ષ\\VԷVն\Z[ZZ['V\ƥ! DǍD\ `{C`wbsy`rVBȧ\  =[d\" .3 \Y ֳ }X yXj YѰ!ׁPcЮV X A!PA/%/߰ W7 !apgQuu3!0f`oSyˡ_ʢ\] [@C[VmA [J fYW_[[XZVz`bzdb *WW Z"93&'XwŠ Ww_] \ ZYs<sJY= '~/A$_rfZ;lk1J-hIۀ 〕qcTE6(  0H0mW^ \aTZlUYzU[^UX[YWP {jphWI wiuffvtx`uf!d]QXdt ]ϠmW d d#&Oi\>InjX ucWXms .gg[^dlpjgjIdAgrur|a vslITvorrwixu[dqyxg;Ixp qcVI;-mT;" )ugWH9* n\J9'xm_QC' ŀрhՀIـ* }raP?.aP\W\  X_[ Y[ Wj Y >&,Y6 NWJ% ,W6y ,ZV[%X`o{XZWPYlgowbw*ߓggsܖgOlsg.ږl  g Zk ږk UHUg df|bm v ovX smxhoow`_X6ZX]° .Ψ]Φ\3^]~Φ[_Y4TZ"Z,}Y^bqobuR^wobW[a_oajogZYMYt^[NTRoXGrl]W[Ksw|W}` uµ ˶g[vj SPϲbivò ˵odo ʺ fiZ fiWb˵?.)d/Ȗ^ 9 mxlfzjf{VrvbrsfofwfuT_\[|]\h:\ǜZWa =Y_ VWGxdХmx7d bm?xVWmbv^VWP3~_mrrdh`_mdX\YSW ЏP f|a`aX^V] VP qի\Z Zj X\ `vis`bVqo`wΗsHX[\l Zm`VW q\V u mZVp[Vupu&Î`Г݁`aX[{wmX umXisќ^ X6\YXq ^^X EX[XX݌^]sap|iXG6&7wf?B0s[C,kT=& T9j]QC7+рp_SA3%Pvwu}p[ UY Wuf\i d ufj au`o[|Vou[abf uXXigXXZFjMW\UW ]Vit]~ssXX[O` W vob[vrbPjrJPskmbP[s^8s]ar{HRs\VmKsZ^[{ZXZQY\KsY  YX  X_zK%[0W ^zd&XZ@d&WW W ܐsW7#~!V^g db{ a a1#VQ_0^|"Vz`b*WW[! p"oB+ < " D"i 76&8h+Z=67&8$85IA8*=85&8%d+ =67 %#"L4Ha'(LA4 8aB+ !vF76 $`|vy!" H6(`G $L4 J& \4 HWvY%$0]4 H[FH[&ET4 PVrsvjrpU' rS]rd)Uvgz ] p@YV_V?Vav_X\V\ scZ iXr ij\ `. \WXc,Za&ZaXVJuhWbdhMbufVacN`c aob dd$hchMb 됧pZ\$-Zc2 ZV\8#u(~dJ4cwhY{;,ҿssdUF7( sdTE6&ǀxfTD1"ܐzVXdW\xvfljwu &fڒwvoWsΉ\w xu$qVYXWBXMSwgam[V%"w^juXĐhyV^V?VW\dsK][sGLz[XdYWVvW/pv\' p #_n 2g ܓXZ`@H$xxjŀYzϒTYʩлXzXWRz$WyBvwW`pUuvw?vmKsiupx#$q 񐰹0 θ θxС $  x(- FȊFșd#qlxlSpB2vb z\^sgpON!V pȺ e,[\kZ]Z]Ƒ  YYsg W-YY _RX07۴^HXX h˿7W[G-W[ c ܺI0v! _^VwrvXp am嬐u!vV_WW] [ XWuvn,`,ZcA,WIVD0ufW4C=u\Ydא/pbl |`D sVX)`  $sw oYE1 pb5D5$yl_RB3'O scSF9ircVA3&l_R*yncXMB7, qhh{Z1p hV\ZZZ$$yY`$X^ EGZ E$WP`fX$~w?_[YW^]']Wg~w\S^_ \%\-ep  ~wep pa\'2|surhu`oojpho`px`m{ Q|rZ[`=|rYX`?$%!X|ofmvfbofdr>@Y  jpwurdxbwru})%Y 5!__Xv |_~0hf|^Xvxsfʖ$]# v|X?^[ $ !b`dsY &arW!4"g@ 2Vsf h0dxfY c|V`)~$VZ[]? !J0[ vE5[_0#1J0Zv 3s1Y z0o3W\ `5mQ5WZ27[k5Y MD4Y6\7y%}0[__5YL06ZN6YgW 6@#KW0!VYVouf 0CFd\0 0D|VX_\ as[^ _5X\]0S2X?Vvjo$a"JB PEA\@ 0F2W 0CBW^V? al`4@[EWZAEWZJB PEA\@ FZ p@!VPYQ3pVV(-#wY_z/P6{\1q2EQ| pLUWWYYWfpAS` sP-{[j =z{vsbWX[g$_RRC[4PDSXQPPP^Ya`ZZPhSPSX}vZ` j?Y`bqoP%fZ1iYUXPPSQ c ]m`PSfb<` O`Sfb^k`k0O`ȚPPddY) O`Qs QddgQY][`T`XpPdp^]`Pqd%w[PaWh`i-q PcLrgarPbv*t q}?s}Uq Tb]YpfzSqPvpXPbQPlW oZ?+w/x]5I?4 sh\QE:."c{fQ} wfTC2!s`N<+ w]C)ravrmfhXzpX^]s[W X_dːZ] _^Z^] ]XZ0]S \8J_[Z[ JuXvpFC^a Yo ^rUpb 4zTQ*Db@ Y)ߓ)Wv쀢 "`W "`i`^"`ԓ "`,Wf P* ŪD Ū^ WJW) D"*(5)"^DߓAgmW`+$}D^D} yC^ f)pZsoxv] I@mi+svD ] ԑX3,C[V@0IDSkz 8Ô)ʼnC G^S Z[ W0txvWp2`1p1QVf -YXw'6 3'X_'/X_ 2Y >՗Y 2Wa2WY^|'W^PnӉZ-xZ[`#@xVP{=@2VP' VQY>`hW%W_P(}ӑW_ZZ/^ _P+23!/Z`6]gW\Y^ O_\ _X!hW[wPFqj^Wv Wu1}Xo `}W\` V4Xp _WVv ^p 0Z 6* ( N;V00f(( 0AVB80X uu T sgpymbWLA6+ҿ5p`P@0%yeO9q jYI8'Ŀ~sh\QF;0u_Ex`I1kg\pWWoxvv‡\afz12' D3  ?M e<z=DD P) P\`ZYZsңXvw-i%aS'D b-!!)O'Z[z,L \_Sp\\p\[vbXXsp' R(W&V! *\[o\{[`V(ҿ\[W*\[}P 1Z]^35Y)\" 1YZ`34X^ \"\X] !@\[~X`A3D9^AFԐ[}peH7D=^e0e1 AD)H^Dz! }5S$wrsBO!@"!y$6S4 d"CCIbpY% fS@0_>wfP5!b@Dor"2$  zrsx|k[K;+ whYJ:+ }qeYMA5)s`M9u0{jWE4  vhZK>1$ |pdXLA5'X`jVVZẀm`bVW`Wabm_ a {o!mZ_ZemXY!jrc<\E!Z FQFWvFV2gWo;lhda`agWx\XmbWX  f|_X_VZ@pY]['Y'%Xd 0fp d`wZbf^ZVYY J$Kp$^W^h I#VVa f]ma ^:"[V^[Kp\#pZ&W J!Yx cpֹ%5pAdvpYV]huf}0$aN l 0#X% &1# ̀dv]V V`S1'4Yր20":4ր20$7>39W[z2:K20!ovWWmhXYV#4fdXZ*$opW#52#04V_#70#53Ԁ!4 B,51%z" I# G5 &G6 0PbwZ^W:bwOYXE0E@X"bWoZZ BXGPaxM^0Dl [r@hFdFaF`E\ VE\h V,.V EBq RVq@RVk RVh EZdRVaRV` @4sb^@q"Qyp ǧVV\XpXX XWP݁sb V bP iX `bV[ f] V 7hPFi@'fO`Z3` fY[@thP@iX@'f`3` fX~ahPb`g"(eH3`hGb zw\zZzwXzWṕs3`TP ^ ۃpr`xy0xyX30)d eq@ao]XzWfvPsoNpdX2ς{ڀWp~o^M< rdSB1 ߞ[`O@0"kuylWE1wbL7# ߈xgJ9'yiYM3&9)Tu^^Up* UuYX^Wi)` u .(huW/X^^Y Iu M .W XsmXw W*`s_V`giia^[7``lSR]jĖVΓJ\VI嗡 lRs` sXX`0A/}sgi (V̔ĔW^) W [g@xPVsWZVxlΒ?ΒŨK`irXYXoSgS op0V_C 21ii *!@3Y$pk$ U 50U0$o]_maav]C`<apY\vhYq𽲖']\b^^`mg{t0C \WXX걖 v%qݷX[\EoZ]Z{[Y{fX{f`oYf"2oWXs{32 Μp\WV|f50mrzfmjpfu vYrmm]Vw_sbPp)[  *`mfaVWf]a y"#~-4`X< -V 8^^a< [PrPIXZg@o_V\gBi]rn"`gՔ`i 0aV_`0,Vb'-> ios W"_iPs [_> \`@WY]cp !\[ '#1}Z`bdg` <}Z0p }fm[V_o ^"Y*$X* @} AC!K 8P|@P{v]Wp{v`X2{^X ovy!hzX7ob`oU1^8L^8p^7q8]8`8[;8Z^0R3`pWW 7g*P 7f0 ^60 ^0=@xN|\ZY@ yrx ]Py,@wgb 9b5Bm =@c@w_~`V^ s_QPDfP2pPCm@3A^^_UptLB2`og ݊D~`WVC ^D]^NR`@Fg[FgB[w]~`Y\DD~`KD\W]YXsG0ULB[A_C@Pw[]^_`P[pwZWXYZ"v{*3 pKQ@sapwXSvp`1dqQNsvvvvW Ppvu_\s svu\ZVwf jrvu[WXWP2Qvu>PXcPQQVV[vXXPRO`za 0PRa|Ø!dP[pvLs .13vpB sQo[svx`"XcZ_aEpf`Qd`NPQ}aHTdbQQaګV TaXtb-@`QaW^Xv`XzvEspperp QtQsQ\ 01+c pK" qP!w@!pQ[wXZ[d ]hvZow fvZiy[pQZ_^W!!ir!QXw|_ OpQXw[dP Op^qIftW~tvtWZ6qWtuffp[^]R#bt`M:(-{h=PC7+nV>&~rfZE3"pfR=) t\F-N0gU:#piYduimFb{ dчX b уgن сbـzr܂3>q,=G)bNՀ^moO3([̠= o[iن oЁ[g^"نㄩ'[`^ =kڐ0גJ ߘ `-@7ߙIYb`tP\w]Zـ.\ H_YWr 9qy"YW][1C#1\Wn[Y17 @iYV|X[aur{pOӨ^bsӣ|mڠufL@^sjpliP ramxfաҢXbvaـ T`Hp= | Tajzru}i`pdmfgruoml{ :q_Wp mrIͳ{ijP۰β)Hܷ8 ̴MX\`m`uosmxhZXn%@XZEW_Y %lę wXY[XV_YV{VɵX]WQҜp[UYWƕZ ۑ  XpVju PX/fZVX~ ޱXfPVaiui JX#TÃX`pִoXXMY#J `eXdl yeX VYf҄0=V_XؠV7 [ݣ ޱoN h h V?$ [0 Wb ȳW[]ݣ_DN$?@$`YYWbQSXMw$v8$p@pNs[ }nXB-!nZF2Sq\F0wbM8$r`P>+ٝlU?5*mS8+ŀ?1# ^V0Go^ Y||KX|]fwaq`]{fuez6"w]fbS)]bua{X@ޙhd)0@]bp Bm`d~ @XXx!y CaHZ`pZud| ӡ]A*H X ]a"\[~GV\`4 pwfvwmf`_dv u[,ޙ@[a|bp| g_ |?ap L[#{# " ԠE[ %$*$%8+M+iԠZϸQ3qd2+88!+02M+8+0}yv>Q8P=[o :Yo=Yi 2|swgddfwb0KrmbrpޚpuMda|ZZq vabwbda^p +{a  "$! da{`lj_XV] J`|kX\q v`bZ Phh!`j" !\^aXWps-´!9&s \s &Z[vs 'Vus &XWs &&V_7Yо @!\Z]^bsb 64X[^A1F;F9YS2F9XS2%Zcs \ZW^V~s\ 3uWs^,;c0"Ya!7Z[ 8!$71 71 0"&@Y}0!I|0!IR00"Y!62QF16+B$|H=@|H00Z^][ovWgi"@[V@X@,A搬CAhEXG[CdZ^`04Y\ZVXu_+Za!P6P;Z]t_?WZ\^W^ 7TOSPNPWAaؒoR}xPsd X #|oY@d\z"|oQVVS P|VV[QWWQX`ʟPTw HHSS i gP ] 5gW}JcVsSf:0W A~8cY]\V8c{nTePgF:`@PW BZ[\QZ[VZ hVYɐgXh,!g wY@<g7pV$=x\l]y`mzW =x[m =xZmװ wXY~ m  %p`P@0 pp`P@0 gpaRC ЏtcRA/ ra. taN(zk\M>/ I0fdv[g[ZV^H1`V\Gl#(W ;$=ARa$(_rswa`^_` ~1$f][W`@#=ݒWmV[bfl`XX I8> N NKWf p p%bpŨNZXXb^Y@w QEfY\͠&  ڑQМ_+l4WX;@kV[;P`Z a9 aJ a[ Pfz/rfB1ifKyvspWСɴiW`ֹqֶY׵`v.WpZ @$Ƭ0a4@`NpWgP`ml?WXY ~ɺ`iWM mǧ`pʷ@mǸYhp`hgW DŽm>`Y >`p-؅[=P`=٫ 0]ں`-؄@}`K[\M mǷؖ[ҰىٙM Y;Wv0CMKMM m`*mpBZ_`Y0XC\`  Y_r$ m'[ -Y -n`-A`-&;0la}`qZa-q-Ya@sn~n^M=- vfVF6&rbRB2"io_O?/}m]M=- }m]M=- ŀ{[Kـ+ .?gZV^Wawˠs-]^Ws]U]\U[ [ UY Y X0R  V Vڑ\_x @ s(C'\D :(J(:'[_tz( z(( z($(z((-:'Z_0H@ 838C 8RE!8U" 7Zj8j8ʐ9@j8 j8d8 j0Y]u180Ysj7Yj7X17&@y@H$,H#H3,HCHc,Hs"GZd,Hu1@+XZs7Xt05Jw07X,H HH,H2PH,H GW!GW_ R7W_R7W 7P$_X3XCoXrI X2 XE!XS_XcXs$_XX2`WIXS`rUW!A0vhEShX*shVE! Ga,07V_#iE2Jh]! Sgb xB7$p sgVbI x*x xS`_Xp(^p(\D) q# x3q {#p`P@0 p`P@0 p`P@0 eq\G2|oaSE7*odTD4$tdTD4$ h\.AgauX$@'W[XZw&XOW% ZWZSX SVZ 10`X[sa\vj. ÓW[w̑yі jaі@j0іR !Y-ѕV^ےѐg__ )g^'za`b`Nrg[g\WVVooYzXzށ\]]]z_ʨXTY[gX[?W^*S٣W^V_\YIf{\Vd XVWf $d ${d$wbsgfuѐ_[-jXvWvofXtps`p`m}v}rmofwbmjsvW0mmfujpf/V[(]8fͽX'ay* XXX4,IW} _^`gzd=]Y^z@U]W [^c @U%[C E! s DŽ0ǒ2 = M"Y7B}Ǘhp}u1}س$FBVBCISسBذbؒ iR ]$ǫR ]C]E!I}S]s]A}]%r}C^Vr} B6% V#M2 n1 V_A @}}^SĽsu%+vbUG:-Ao_O?/ygUC1 }kYG5${k\M>. yiYI9)/mo`bipbmbsk if d baZ`mW[z`b^jsr{fuolݰtj}sqjv/Ғ[w |`D  EW  `  VX {pOXY^bP+'X6 :)aɰ[^W3\l-X'Xk=X'Vs!Y_ՠ)^ ѐ&ٰ+)\ ѐ~p!,iv ѓj_WW]WkT $-WڰZY &!* 9V ѐznsW sY ^hupbbX[ _Z6:^ F<] F]qWIP\rs;w!103 * .8kP Y,I LPP/a -K 2aNPZ] 0 ???fY_[S?Y^Y]\Xp\^WcR`ŤVK֤ϩ[ܣ㩋iqϩ0Kܑf;L][ҥd!K 㨴 [ [ZWyPkZ0 0K㨺 [Y_YT pkY &R[;`WpϨW0˒rϨ/`ݢ /a~X_\[^__ ^{^[/[[Xݐ*R]/ Е\O HVoRo[oU+ou+oW^ZPW^p ][ 0?+j?[W[`` Wo` Zp ̠&pjpݐa/ Z  `_α _2 f3omP-![dm1hbJbdpyp`P@0 p`P@1A|l\L<+mtaNB. saO>- p_TI5! Կˀp_O@1o!ق_ܠr`XZ_^bp5b/a #r`W^]a Z |ر[u@!Y_]X) ir`V^\[w ipbs r|Y[|V]\ vwd$1p[^b\[u" 2#2~gzX[\sЁ ]X]bZV_\h p]VWhp9PR`WVXZih;W`hR-ߠa&ߡ 8"pA o\X^]"R$Z ] R![WuX] r'gW"n'WX^m s,U0'! *amsg0] R`&gs^ ]&\rV Y@'Z`s p ;p ;0] [03@ p<)]_^i4BC]IANI^[B\4BB\]aIANI\ZIAtI[\i`J@tI pJ@LlJ@/0CR;@9 owLQosba6aobmjsUaoa`w@ PO!RA@s@[?w-c q`R@ w_SH4"~dL<+ zjYI9)VZXYX\{vb@VuZ]MSvq\u^-^u}.Zu]Z]u&>oVu&YupYYu&Xu0XXuFXXS&Wuzp l{ [urSFpuF  XX  `am`blW|W_|=XLoozvYX^fvvVWiAvWXbimp uW[! 1AR DbdWl¨ 9 w1Av[`;;urmmGe|[oPs`dvDXdQgbdu|Pwp]Иd|gW;^Xr_g2@uzuq{ijwf yB[V] * [m` kP]u\v .RSs ^Z9vԐps ^PT5`H!^sYQsU|s_kYs| P^@QZ`bsdmW\ >@Zs H.d_ aZ^ae]2a8[\lT[aZaUY XI 8spaeмis_!T@2@s]\a}YwrY@RWVpX{ eq e;ѩ "vPJR?qIW9 5`-B@mh ڲsalR h;R 2%X W`0!Y@/*Rrwlpjg_fw wr{xmfv`{bxwwjphif`dY^g'9IXxXPGyVgaa}Xq zr`\_wq[ Yb sr  veTC2t[C+ {Y;+e|l\L<, ~n^N>.xhXH=2%yk_SG4Հ V\_VZ }z2G0!30B}\Vs 9 y }[YZ1vY! XZ04v @Z@{w _W]{YVhv` )1AzZVa qAz$8`&Pu8a?0zYAV[f@ @X@@ADFaPuaGX[aPM@w|m{m1bY[v/m~w+  9 wai!"^@bJRwZS ;!4P| E'`Y E%BVV] 1AwX aw#5 x"V^5 Gavuxd)jd 8!" )ad x!WXgH0B f%d$P 8!V^WΘ`Xu 3V\rP!7@Z7`p 51P .bQ0X%0&K6^!|E Culq@~ulX\0 o}wa9Қ1b\} cvov3 5v3e`c1X^Ms60Z:XIS4 IP9T)J`JV IP9YJpYJ0ySvosY(a5sQ_Z4BpJ`I1 IYZIYXJ2 I1I% Z`ITqHZHZVI"xZ&5k0MU5i3 5h3)W25g0ypU 5d3 5d35`S0g LZ[\buY- _`ffLUVV R 6 WAԉ@ Y^I̲XYxF!ڰXWekuز@oajbWh`\^sd[a]dv?fkf !_K)]qfL A[|LV L+Y,X6WFP@W]` 搪\`Z`I(6ҹ@ʴWWS 3]VMLkV_ZV^)'G5]&']t |V lVx\_` Lհ2WV\ֈUPxb ͱu@<3Y\xY xпVYVpeB ua ~pX` VXa&&VXx oW` B3VW_ xRgxWV0xJxhmrV[`maq o`vwfuoW__Paobroovmjpl =``wb`am'?abopVZV^iePS`VXhvgTj`t BqjYoY|af(/mXoXIPWoJP``}vbof0 o[_T1ao}! Qa`o}  a[W*a!\X\EZ}  !sjprQ>,ֿ+zjYH5;vdR@. xfTB1 m[J9(xfTB1 raP9* ^dV^^{`}QdVZuZ XX w=wbXZHWZW\bmW^\^ no]jsd 7 ?[jysNa` Nj8pZD.EתUhY<&w~XM2 _thN5)׹paRC4%Հ~]lH2po`RA0@psuf.فg`bfjbv ׀vwuxofpwwu`}gruV]4f`p 8suraf_lYov>pv(w\7l*HkCG'po`a kbp`X/s8|xbX^sWYW`s鐱W ]sLW\[֗Z ֗ ֗Vls[V\[lx!sUXW,=Nis)pirxvf`vvfoa}rm}Y? opo~t }R˲o|X ĥWĠwt~ڤ_`Wbo hs^^_[roabY_V][olopmtpmrmdp mdn 0V\;YVVg 1N3mn @;C:;oplXopigpigZFKb~PE~F@[b[\Xua@+EA EX\V@ Fsx Fal |PBW\V P+Sp PPup\VVv3|u_}{+ơu_|_PVR{f*kTvujUudjUhpVdjUaxjT[V[DRYX{XmV]UWRVzrfQ $WSWS P@?XW[[ D` ` f9 f :gנ fW@[`T֫DW^[PjTW^G| _PrcrPf~P fP fP NgdfP _PJրsr}am)YVl`m4Tcci`jh`jd`{$} zmDQaVZVd{0pEuXVa{0ps`ZVVifs` qs]^w?W[bw@uUXpwVqtYu`lWİzXiyPzbod^PrdVH9&-zk\??+ OtdTD4$}j\N@2{l]M?/!vgXK>0#xiZK:+ 0W[habS SYVxSX ,EQldp3g% X XT V`GQGZ%)ZQ4Q@~ZѰB~~Z\pxRоZv޳@pA͖ZYYWZX /XZ W.[x_W E EV4cAx^mAEu*luOȧALȦm@Ash>Pf>PXnb\bV$ [bgs_X+ M*Z\BZ&%~ h[XIvD>Ph*+Y&װηDgu g >PaAX\Z{-V?.R>PIII=Pu  =Q I I*IV7 Ǻ I[m]R0|R0mX^ R0l\ijRJZR=QXdRQRj@hqֺ܂Rj_Nq>XqtRhrU h r t0h 0h hѮdPKd_:OI:gT,抡,Y20, X=@O! - ah20 c %0 "  @._3CC1__{_1)Bz0A`20:=#ssufW*ueUG9,]fYK>1goo[G㓀whYL>1whZM@3qXJ<. kVWYbg`w|[VV ^ \ 2wsiY6X . )W < )[Vup`wJps`bl(:  eW[VX{W3 `wX^VXVWA1Y[WZuYUQwXXЏ`OW gm 3 #$Y -%Q uuw {vW_w v s|$# \ 2d'@ ivgkd%iX .# bbl%bbc-$ a` U jvsmvjXVYX^VmkD &W& V*W\# " XZ# U0vsvl$0 w 2r|?0WXks I2=P`s bPvoc5v !1iX^H2dWZW\sU42h  `)v_VVWz4 -5V|P` 810 1\WbX[\`iXVp 48k=W[P MW[k" 3214M@HL/AC `J r1Z_[vVWXXxp@Es!p@I1AQ0GѴp@!1V D?XW` w@wuzQFPvgY@5oYmT*Rm CP V4 CPW5S 8UxOSWESVp@momvXPTY]Kmo[AP;Rm|m8UVâWUV6`̔m fmY]jp&eX lw_Wp BiV\ Bf]W p bi^` Bf[U\Ma BfZLbBfUXbBei[cf"{cf`^``uhwj@g^`eV\[a\8*si[28r qg ]O siZ~ 5vCxBb sC3vCg DwZ qv yApbvɰL&vqwzrZ%+ߐtXI:,)7gYK=/!ymbWLA6+ {dYNA4' ui]QF;0s~qeXL4(saO=+{ij ka|WrxwsmV_mv& *] *sNJ*V4 j*_Aka^^Vf|m]XV {i vw1 [_rX@uЕW0k`m 5Ē`Z^}uY/}= u"qВSib~_W^i9k^X^[dK HZNaVsRUf0kQ!!k][[^g H\P} F\[V['}\Y0ϓ[X\[ 2Gޠ1pO[Ee1V^] [ Y V ZR-Zu]JWJJZ0tXV{Y䣌WbXXX}W}Wb A@ ^Tΰ ԵW ȳYY[[QkY?WZ\} -z Z} Ɗ W-Y* Y&F0~>XZZW䠞_Y]ȳn\XVWW]]`HWg W\V[2ph0`YX0`!@p Йě _d2к.9O`;W OЇV^X]XfWf\Xa HV\V\p䣐Zg[hVZ@ꐉPВVWW]+@V^`V^Qkid@V|vGkghW|VYW[o}oyo\]W0\Z[_mRYw H!/^`8?`8[X\WW TjP ce~Z_XYb Z^ 8ჰ)W`\0 Z[b_XP* X>bYWT] Z}o[ooX oW XZv aWW^8`fshwiR=/"АrR4SqdVH:,~kOE6 |hUB/ рvaWA+yeN8%lW^`7VV[,\ V * ]]O[ZYat=Y1`D)5N6@*YV|`lν_hk](A@]WVoX[[[l&ZXWY4VZ I--5 0lWY`b^ X|`V`bhY^|Xc g!5Sl1llol`awGy 1V1loj\aVlpf']0" "V|9s)A1%EY4 7&11 /; 0UH6A . 7W[2 i;1i;P1U72A i93&1P10 ~35[X~zbf\0 AIG\Q@zwL4B<@xsjwfu9eKEdu 1]G@xufYc'CXg\@ufLby@uWYu vHsFsBJsY@s|%9i?s|Y` @soWY_`{E^` W]` W\` W[` WZ` PHQP VX`^WW`{^WV`^PTQ`d÷psp,rl`ujprloXpZV\Y^QOSZRZ[QVXV-]S\mQVUZQW PkjX[aamljplb`uwujdhf%aVbbrmrxu/j?`i][Vsouljw kiYY\sju q`[@iYX[o`hI`p dXX`uf?orwf q`fdfbwWː1$UpX^rurW[s XYVuV& px@` sܐ` V3%1]8Q oo[YհVVazpmojV\XV]z%o][`2Fo yf oX^b\Z`sJ.@ oܐuy lmfsvZ`dR"|YvwQH"|Ymg[,`(XbX0?#ax!7P&| T R}Wm'W"  0mXs@~q d1m*FmVymVV^^'09A!]p&ZS&Zp&Y\ &X ?lXcXpbjwsWCAA1ܐ_ Bjw^YW\V[V\7ði2o00jw0W Z0?2Q7[С9W*L0Y >0XYVoJ4X 4WW[oc0^m`WidXvvW f|k+qBuC{ Bg@^imhuZ&q2:@YXZYBGpCDYKA^G^EXYAU^@zFX ^EWA^@h lg\Vhuf}V ar|BWX[KDWMFL@f}?gra6QP\jpm >fzm`ubxPuL2fdZ]Xb}fdXXKQPU;LP_VVYLPnWKQPPldfzufms~!UamplW;|WR[ DuPnsuP|sx^V\hyqR[hWYh WXh9 UAh gPI g` g`U%ZQNgPNg`Ng`Pax?YXXWqPܐ`$RbꠡhΡhX`mavX]da!K"aV`ZsV >u^o k`@Volv uqalwv vZW_qvZav`%x svY\_Dq [x[^"DqvvrppZ`XArvWrpcPg p& ^ \ n"jm7%m[H6%Uo\J8&}udXMB݋tiR=(ٯm\N<* yfS@-N<*|E W[ WYVH0X\ X^ E\ @@M|2\{8|VY] sГ|wXY_\af {]Xm l(0 % dš  xps$smxl[W\fWlS V% hxjw[`Y g|!vApHa^\f|vu`Αwlp5BuZ}?0uF  N}X V}$}1z11\wup2vlY Y[wY^_` vlN ]^Xq*UV@~vX`LWFpVB|u`!v ]VRPlu}swrpU ma {rulmjhi>Pwrxhiwrubiuo^wZʵ0ʵXʰ/0u?_\VVsupޏPu^h[aw%Q)\su] o0:Usu :KYWEQW'Y QZ w@:sX_e\^ZZ]YYY|\u^l^ ^u \^VuZ6l]Z]u Z]Yu\ېYYuk YʥXAXoXu XXWl[#[ugPuHP 8V* V"ƈ E i ӥI |ӥWur@l7 ԒyV@,0p\ H` [ #sr {nbQC5' ߩ/qcUG9+=}qaL<+ cvgVE8_+ yrb@0 7{pdSB1 q`O>,Հ Gz0\_Xu m [kf{e\gPVdmV]upVfv@0E0VgW <[3RE^^_VVp` ʰrb] `Y3 <X3 Eu<<W]]ykj`da+`]%\^a mV|i V g] m_Y{h}{qm#fh{ x&]r" J(ft ) x n Zvubg`, Px& hv-(m} J$vud &jd 9hd\ !^W_ v #y#41s!?8!?0![63b?0 c3h}bJp7f{08l0p5"#x 4!8 5\a 120  50=8id 05)0 0c1[\X d0Y\W%@b2Y"x 5Ha5:@l0DTG!x$jA1cH0cH)0x BX%DZZXW%@s1Y3-4A0 a4A0LH@G)0@,k!V $RF 4R0 )Y@ )Y T `="U9@jdw DWYnA|U@VAP4s1Z aS"1 PU0X)0 VWW_. Y?T [] \P @]`-B l H?!l  +*XI Б+m [Q\ %@Z,p`ep`Yaίb` [WZ[ӏZu"g pypwZ_] I $&&T&%\L& PZ_ZWazf&Vz[GH r1z" ~aPZ_XV i!^WXbz֝%V[ $]WV 00 }/fmmr+! ۲  O ~!amxf 'P "" $\  |`QY^  C0]^D$͓Q4ȑ 5$Q4r:ؓ `8ٳir8xYZgo[lXsA2W g= M24ؓ 0aPX_^p @l7z E] /@43cX_` F@X_2EiT=K~н>Hm=ImpKpKbpK=@ BYpfs#@a!E7X,D^XzW9 EbK9\ A^V\9'Ǣ?X]Xo#PR6b\`zcR`1V^^ BV!D`K@ QVXdh`bfPSVVuPpa,$_[ P_ _Y ܧb ^3cQr]3 b %\3 b4 nyv nyZr3ny3v^ \w`gp}_  ykZL>2& %)vj^PB4& tYVG8) }m]M@2!ui[J9+|n`A4'seWG8vm`osV{wigruojpjgmrr!`aP`_dV__]^ m``^dp E R(]lpZ J`]dYjz`d`ZE\dlWgEZlfWx 7RΡa `Zgd{aМd`Ęf "`YdCuZOPVoОXdwZX <0Rj`X\ZWuXWEX[ps`WlpZOTY~[aNiV[[*p[dVRe`~`_Y{f} !_YZ뤠@p_W^XZ]'^W_fh{Oq^W?\avud @&b3 7R,jd&W\V &X[V bZW nObz^Nұ0@Ha+bCRhd]_.v"32&dR&]_ 3@bC :ʴ:αJ"C 3R "XZ J^g"]_W^ Ƣ!Ʀ"Vƴ! ]^v ƺ ״! צ! Ƴ"oCRצ!Cֳ"^_Ybr ӎ VPkլX!Iպִ!r!f#s \!"/p [ZZZ pj=p=YZ slr`{`"d@Ժ@ԺAX_WNW4WbVb]VXa f#\_Y191?6=9Y`9; IGT9Fp9؅ H \[^ K\XW_= VY `| \VZ vlԁ\si  p_M;*'{k\K:)Mn]L;*o^<+ 着p]K~ZH6$pdXI6#yk0doWZ[ `@1W]V Yj2W'i dh`W\ (bdX]w1|Vh!dVXubz][^@T"q\@|Z@|Y@|i bvfp!bsWVY{ij3am0?Xruh bpXW\VVYo Wo [[o+ + x5@9`YV G*V]]no[ZZYWi`r#@ @bg[^Z $sbgYk&VZ%W $dZvm!hu`sijbvordxmfvaP"bi`u`bSwf' "`ssmjb`wjrpprwfveavuauVFp3(6Z22800,2WX2280nXlV_WVx]ld3g]n8VWRj0o`4\h2n7^0a]n4We5I :{0 :0 73:{0:082 J0 5d^VWWx[ y/@Dp[ KJ,1KF\[EB mJ{0mJ0KF[DCJX@J{0KFZDCJ{0J0KFY`G@Z{0iY0(VX[RI9ZX@9Z{0 9Z$6A(VWJ`G@ }ZX@I }Z{0 }Z0}WSZX@Z{0Z0(Vf0rG@$iVQj{0j0ab^[]Y7[XVX`pa_0`fwvw "neukijapb}k`xj {`diw`{`Ga_0*y eV`1aY^Y[`aw|cd`dja`cXZb# e r`f q*auWdeTs`]zaLv tD]v1u(ura(pzaO X "мqp7wZboss 8{_ ylOB2!1tgY9>/ ugYK=1%] _q`u?1"nZL:, reXK>1aTG9,gY[WpwK o Z]p Gap WWi X[\i cgWYVpN&XX XRzoVz\[ W_YVa Vfz^YU 翖X["fd[[b$ܕaf`wi b`vf<damf f_X s$Y,_8WYZ yV^^RY R_V?][d{,G0+]Xa ^f\^r` `]_,\]5 (pWY8ͣX 8)Рraw` 8T 8fauXʤZXV_Ǡc^`ؤ.8]D`{cM959\9C'!pJ'Y2bp Y0 :Y0b `V⡍`D@$ƞ,XC@d1(pA(s@grM\U_n[+?X[[X RW RXWXewo , Q[p0V_Y1 fW][, Ӵx,WZZV7p*V4 *Y[]'bTp\pTׂIԏTמVTYXlpGXГ 4Wz`W* V ݑWf! RVV c7XN W ݑVQ,t8Z),.]pTY0-V\qJb {[ơT[ C泱bI pY0 :VY]VYw`T! qw`{ p XwLTDT儱{ⲱfӱdo^?[vmVJbdoZXXYD Wss߸ wi\=. %rbRC4%Qsi[OC5m ~pbTF8*}gK<#ڽpaTD7*Հ rdF+| ]iM 4=Vb#`m1 >W`Ko|o"" CXKQXTM_WKQW"i _ o_~VZZmWm_Yhagm QYX X0_XV XVm_W^ W^mM W]&\= &\m_L`3mWA KLBT =Y:X]&Pi! ] mlop`wps`bl )"b,$a[ml(#[,c#[,  Y|,'+ L`lY`p㠐m+3V[dpp>0 ."X}`,X3sam (ѧlWZT01VV] p{h] YXufdRkxY ΅z5x6Ӱ7(5Xj15X1q6ӱ7]1( EW1 5W1$3GӰ AG( @~`jpf`ujboAdvwurovxsufofordxmf(DruofuhrwrrmEjpb[C12jpWXsp+jmmjsxwXZz_o@dAjZ\Z {CYW P~Diw\]Z"1ifpq ݻRi\Y$`2TV$RZ]mlP ]2RXZHPpi&wlVW[1镀nW@){n_RC7*ѫB3W['V`gQ^:\91YXvpmQ5*1X[; ?֐[X?OV;?W_uW\;\5B? Z Dɑ  `Kosq @\ W_ ] gs2[Xu]df{l|YV Xe@lp^rurYY lasb^V\nW^2Vka|rrxwmsV]Ck0P juhabZV0Cjug_[XVspzbЛ@h iW`V\gWb_Zgi}\XXms]Vivb1u ir`XZ_^Ymos^u `dPgaugPZfgZV^Xasףfdv[\VV`MdvsYxbsmXXHi^X{iYdus1z`b~WWpWohu^^ hx0CXaaiXvfgPzh\b]sxvvz0dbhXzpX^[W@huuȢgzdעguffvw}mf^Vg5\X[ XZ桢gmW^ _#gj?i`pd\a`vw`udbxwo»@gfP0gbp]ZZsVX\`xuY] $`~pbXZWoo^|l_עf}p]XW`VfwxW]svOV^bR'fmvw2^wuzg[ۡflka wffziaWޱPVs3bviWbdXX\ubldZbXXWodxEfvW0XXhֽfbX[bW[oo|\g`aYbbȢfvXV{d|V__Xru as[^dwbm[O\Vooעdv^VbYXVo`dvWXYώdsgYνdo]ZmvW\Zp~moZ_jhfmfbw wjao Z˭df_vrmҡd@`w`brpzfuwfu`Ȣd_XW\ޠh0fmdXg}b~YVbU w~bxZ)`\vbsawXíbvv `bu^Z]YkwbuXWvעbuq ^{X|ZX[waXlYYlZ[|\^ [l[o\X{vY|_ >\^lCLl^:sYVZ jpfsADbo\_๭bmuv[VulWmV_]`fӠd@lrd`ld]ZibwW40 su  gds]F/+cP8  W~rfZNBi(qߍoVJ>2%|pdRF:.! πzmZO?3$ujWD1 E8+ \b[\XbW @ZomWwl\x|`Yd]VA 9*55  Z l^ l]+ p\Q * N IX lw[lZl,lXlWlSPbW V?^aYrX-$W8 YX]d 0I0vaxaPvawư^ )Ql#Z w # a 0vkamR #a[uPY%DPmakvaZ|[[QvaY|B !YQ!\&ZC&P "[P=&W$uP "DP aXfXXuٲtAD0'48]6Ґ]6X '01$5C}oYL?2%vi\J=/!̉tbP- ߙ`M@3!뀼xfSF9, &1W[[^XoYZb~ Z |^po\pYi<8[^a8[tP Vw_ ivXY^AVm`~_Jhl_yleXTV`oQ  XVY_ wokU `^wڕY^lvwMl]w:]vsm~Xo]]d|T§i }dXwY hY\ & ¦\~ jo \a++o_¦aiad¦Zko]WiY0P=WD4n ӶVXPӵ?X_d~  aX[p*7o7k ZDcp*°YVXYd*.VfXny@ƑאĒ h~0W 9 dq#iV~=W]os\RjحUTWІITJizdߢi Ni _`w Ws #V_ieTs涰=V^DoЌ/ 4 ]p \iS |[!.ܱ}NߡX`f/ ubPA/ {nbVJ-浀taM;'tL?2%  ݀v@mssdoB? o 0@sVjo[9Y Xߠ?[\0 a_ZjwaY0 a!vg[ao`Κo[VbwC6\c:[V@]sW|XZ Wufd;/bmf`u:/amxf:`oafuo*WX3!u=~GuQ$~[n usWdWXWVa7mrlpWVVs`bl]գX][ީ]סW][ߨסVWa amߨ mp^[9^}`=D]WOvpVW[` hVusbbj]ZVVsmgb{`ti~{\_WXusyzWsuaΞZVXrĶWsmhԸhuԶY^XޘuWtEi ȗ ^g_VbW(og\0p[VvD $g8 bّ fˠ[vxXvjVV[wǜǪdd 0 bb]\\Vlrab 2b\\XW  !N+o`0}\Z_XaIZ^Z!j!IV"b\u!\>fG[\VI R1 ֗2 H_\ k^Y iQd]_or*2W*tB ]_mc /pbXBsb$/p&0aP  )2^vZ! e^m^~ \~ tl o ~I Ii#G /p|moi^XZWL s whVI<0$ 3whYJ;,n[H6$e~kXE2 xmaRF:.!}k\L, |obQ@0 @lW }2w_bmseϒR0^9 `0^ r`Zb~X@-WX lwV]Y` \UW` \:wV[]\[\`CRY^`iY]\w@V`\vw]]Vil \km0JX[] hv[r@gs :X\Vdr1!vsar`vh b]WX_^!b[^pvbWVW[fB X@va[\ {ijwf p%5 m(& `1$_Vr"K @v]YY^ Ov]XYX &: &WV}%W\\%V\V :v\V}`4VW %2[K ![pl}I53^$K?4UYG3N4Y#0$]Y243Y^ 1!6_5*#04WK50 5Z@5Y[50 !C VW 0Y {9Y@ KW@ DV^F 2KAd2K-A @:uvP7JQuoRAu_Cu\aZe!uZZ ПDU@@pu0X`wXXCDbAKa@K`"@CGA JA GWC G-PBI 5[A 5[A#ZA#ZACPu_XlVYW@ŽSXYW0XVw^Y]Yw\Y[U}dl0YVq i0 fX#a(iY fWYXLFi2PFhW\ di@diPdiW0FhQiPiiP~BXVaX@zAWgvaW]duWZ`@AVY@`:t]^$ r[$ 9pDptWW$ @+sV$ p+w`d`swruKy bsі JXtWdw m s`vwlf}[ooBs^\vZlV_͠{YSPt\sP_[OsY\[wwo@|rAp{jZF6' |m\LC+ |lXa8(vfVG7'seWL?1% `n^= s/ bW{Z^^jbWY^Z9@( 7 kU ^' Yз^ W]^ WZ_8[ w^iz V\YZV[Wbvϐ~՘Vbv^jZ'i k1w`[VsgY"0 vsXP "059QE KR_XVZ[t@4O]Ae[V_Y`fX \[ \0U0`fuX \ Z^Vmd Z]lZ[_Y^^ R%0qp0fRXY\'{VH*F 4 U[| Y ;XX|^ԷQԷԶWԶZ&W_t0$^W`ѐCʇCV^hW (]^Kpks']ZLs7]VY- YZ^  Y^ ݰ s[ sƆKV_YHs0rK qoYjB[7zKt o K s[sf!Y#CKC]|ʙ]fLsV䞒 X W  [kvVYZab~W)PX03Wޱ[7VhX0W'WZdvcYdds~r&ssyfT?,#z7`TG7( QwcT@1"zhyH<0% xdP=+ rdWJÀ- tcRD4$vd o;vu{Y@Q/K  Z%Yh@ hvl&gb0HY]vP!@xYWKvwsw+X 1 ` ydkPwdV w@ ^~QoWXXST` V[#[ Vu -!`7$ @4 ^Wgo{S"\_a`a_$[^f|apm%Vf|~_$Z_f|w_ dos q TWoZo3g@}P$`Y'XP [ZXb)*q X  4W WA~ptZlXZdb7WX000 1/xv[0 0v052 =;$2 =6X[6=5ZVY41\04q~pXd3K20 2VX451$20@~\< b~\fI~YXs{73Vs0|@0ha3^PsK3XB@s3XX4K KeVF$1[Ґw\sPwP|A~UWVvwP`|Wd\xЗUg]VXһPWPWa]P `{v`Z?VWfBPYaff`zvVXX s )c rzb\8bz5bKMeX[yM``zb^5(%az@107aX[fxfvX[HdW``xaY]?WhlPpx]V _V ? X]eRdda xZ~Pd ZV`Fpxb` w`t!`aab`aW`Q``aQ w`cwu]ZvY^VZu \uXJs}whSy]V\bpSy\`rSp-b[\_sk\&$0uZypxށo_{k`UJ3(/wgVE4&S{l]N?] o}kYG5#0q_M;)vcQ? ygUC1 N?0 XV___[!ZV\[Yr1^P@WTG\ q% U\ xЊ\> a[> ꜚY>[ʊ\` A[E h ^_ !u$= ߑ  YY\r򩖒ߑo$=^6P>prIpޒ " c= >`䲼f,` V[s"ɀV4&04Ua4`344 +"Z.@‰S Ua$wʉʛQ 4VM obf`0U.`6;a4өJDJ`5hD;_[XWlVlX^VXgus7 CdW]c`Q]@ 1]9?]G]caP(Ua2\s_ds"s{ps p sHptp"W0ط\Va Kb\p [vm1%l[Zc807 Z^aW)r]\dpY>lY[X?g__ <Ӌ^ 0{W Ys>`PWp(si o]K9'yk`O>3(q_M;)ucQ?- ygUC1 }kYG5#o]K9'  X> sXZ@f3 m@ SX[$X d1\WrVAd/X]\Z`2mZGuYͱ mW]"ϰݰx۱յYXpx xi77x8 0ı x!]W+ !We\ı hjX^p AʼnxÒx]fd]7\\ `\V`g',Z[W]Wy Z\Y[jX=ګWYVV9 TjP ~Z jےdVQY$2Y  d[aY^hvl/ g?)L]T00`f`<"Vd(qdqPVdWYhqtk(Я broovn. = b`aQ mV iNiAs#|W-3`aQa QaQ'Ƣ < QjJ Q\VXpZ[Z\X] W o` m`[[V\^oi~ $\. 3Z. 3ʑ)XwVoi/ J)W>3kX.3V\ ϰh[V =ZVY\ YVZ[ ԰=yXV\vZĴZz!ʑWufd#QW_[>V`W_p0`z^n2dX'lŔxPx;i y EYĴ Y) Vb_*WE0 >*ZZX :`V[ db pua (S`E0x+d^\_wX^cZ0cЁ _vmB_[sw9RhER^[[q W[Ӕ4@ b]]ZVg-0l`-0Z[]WKH\] \ [ ![\CW@T]0\^* [_||i"I |c q|%ZNi" nZ[Xi"W* N VI_3]*VYYX 97" Y]<YciqW#0shzk\OB5"~pbR7$QraQA0o_O>.΍}l\K;+ wgWF5%[J:* ݀XV'|^^Yb?v` t &s` X \W V|^Xpʑ>s`7!HWT]]_][\Zfs8]Y^`RYVXW_bph Rf V_m"**V D'[2T)D'V\_n O'wf8 f*'~"'T*r%^~"&%\7 7~" #Z!&Y 86 Y7B3F&VZo"{7%Z!i76^7^"979q5]2 G @:c EXY^ "^V z^8*ncXMC+}Gh]RG=1%viXI3) |nbVJ>2&vfVEvdTC3"`??dk?:bW\absY ҡVZap * !Y, &Wx 0V  jZ_Vs"}d{ uYYsvzWWsV__atV^^pSuȒX, V]\,ܑ^0VZ^x,%Z+LPppԔXܑjԔW+2V] SVTH] b Vlx"XwXW4"pV`wmXZVz`bRУbros٥ͦWXzdb⠏bVW_ `[;Y 9 7Z 7Y awpXw [`au]K`ѐl;`ѐauY\VumʃZ ѓVZ X[Z[bw ѐ^uW\ ;` YЃIJa;`ٰѐa]aoX_gw`q~3ЃjWWq Jf$g[VXQS%UY" 'X" x#lա !rvjwf =ZX]irX[T1 43@  "=Y`lbY[ٰNYZisĢHTo1w3!Y0p$0\p1wop^`6kZ] w5X\03X6WW_s6VY0 0 5Y\WWp FZ 5YW]L0 $IS $H: BIp$H`Ip$FV]0~Hb I0F%V\@0#Yl=L[4X[D>EY]_EJ@=Woa\3W\pE bW[_s ,P!W[[͑;RZ_0FV^Z0^_0TWbb T [f [_^R IS[b FVFAQ #^^ 2QAU ^n ]Xx hd bW\R (]  \hX wBMfW jMfn\0+[RhR #p"[[Q0`=JhW, hbAZ]0bfBWc :y\H`JzpJzސ:y[(:yWY<* Yܑ 0Yb@XR W y tgZ- yl\OBɠ&q_OD5_ |n`S6! uRD8+reXK>"}m`SF6' XWu0ZZXu3df[WXW^WvdfX^]wECdd \WBddVWX!4@8@&b ZWa 3mW W[qWYWH3&` z8`W[X d_,fovwɚWoٚgՐ뜧oِ_zW K0d_V_fj$W .+V+^Ew^ E] +^K[lZb]EY+\\о+Y_mYYb Yy Xb X $X+t0u+\A\^[꽤\ Zʤ\ZXWuaR7БՐړFP`H@PBY-ԑq2bPo7W_X\)pco ³W gȵ ѽXg `o{ vjuY/drxaw&~@W Z ^1zW91@!xZl] O]u[l [1bVwuwl[XlXXu;l wwul[^1xPl[WȤ ws0ul [= Gw]^_U!CdXwUCoLעYU!w[XI!\Ç@8VOGWY<^1wQ<4xwe0Ui!v\[]WYXf"s _^<A{biW\\0[V00ZnaC`X[[ <Z0{s^I!wj]QD8'jW>+|pcWJ>1!reYNA4' wl\L<, tcRA0xi[OC4%\Hf]XZ`mu3 , 0 Wl 90f 1Z < 6Yb Vf V\[_lfgt^l .g t]t4f[f}M"f[]VbK9Poq:{ o  +o G n.+oXXIP+Pb ِK`f <ِf[KZ][ tY[^b&]b&\"&vtb0ё*g&Y!@*g& m:g<#В9:gc<rF#X]Y $X]! r6А fl` s4[[R) 03Y`6QQ0@b0@I5ϐE1?6V0?W_Y` @X`FW`FV`W[Hd03 < BV A?KY@n1EV _F]1?WVEX2 ?A3 F44R3d|afY#w<%v+*GBdo_q3@o[W^`YV~v:P}`AY]o@BY]4oX[0+UX97UWR@P+UB@ @mvZX\[mzmfdmSVZ\\VvWۂWXYP[fmPZ \iz$PSXrUP VUS lPVXPuXg5d P^mRW\XdtYPL^h qmPPm_v ,Sm_ym/4mX[v֠RfmdW` gym#Ck_Jk3PeLPerB@iv{CDgEgY]'sY\>p4sE1vFp JvLP1pokpÐJvW^ >ptsDI wI >uLP1p(rp>pgW\hv /sVr t XZ  r" raRA2!rcTE6'teT"4%gsaO2#p{[;)q`O@/ {_Q5? VK'PIg\Ⱑg@P"Zo{ZgYoZgʐf^gKgRԠm1 !^^ A ߐӓzb]_ovs3 V Vg 0<(k $^( s 2V]^^0kZ[  ΦȢ᪊]ť]E <0<+(9Hg9gi(ysH I(<\ťQҳ(\Q(V\V0VK\1,t[_ƤDNťΥhÊY[\ F ߐ( 'g Ɨ2Rt%gƒEB!(20"ǰa(@ZngD]Z^g 'PRDЀ9Z0qVрVJZC  ZD-4]Yns#2鹠#)Ykn锲sn •VYEDB((HV0g悲.B( ?  n(9(XDn Ŷ(ߐ^` sbp!#!_K;%}oaS=7) yj[L=.zcUE;&yiZMB7,! sM(ـH#G@\zp]W\[WW[][!oguW X{Y[|WVW[VssowaWlpu  Yu0!YlG #  jWXu@XlZM@u9 WWu@-Wl%-WEW  J-[!->p-WVl:--Σpu` ygfX gdYV^q p\0gb#W$`[H#`wZ 5Y 5Ԧ@5W0"^bbpy ґg/\bppG0!N1qG0 Pg\Y\Y`am`bI2ZO3 PV41rV4YX@ f4YXoWmbd`wp%4[]36$6s4{02W55WX_3rW4XVXVr5{0A -"WX3 G0WgWVB1 G0FBV!r5{0gvopXiGVtAyHVNX IsB IYtA y@J1vZ{pEqvEu||3@Zb0GW^[{G\S0 XY 0 W@ *X\[ *Xp *XZV{*XYV*Xmp PEAm`a@`fxW] TP Pwfru\qAw`mvfwJ{wWUW_X] X\ X0XY X70XcPUCPTPtrrF`ZZݠrTaY70\gV[NfQ@fWV]{xgV\N`~v`sZYIavVXX sxa_ aSm`osa`vf~h1`airmdf `oru}jbvu0`arrl o`ssv_ZKhjvwujs_Vai^96{U0 xR-p`N7  ?- ZlP-lY Z]ua` - Ѝ1 - |OYl_ ύ>uYl\ Yˀ y9Y_u _l--Y_ eRY\u(0Cy\ hY1íY{H{ Y )B3Y!XX~XlZXlXԝȽX #X]l) H6Xn[XZ}&́XZl KͦXZ `-X X ;R aX +ݥ0QݫWl^SW>Wl[ Wˀ0@Wٰ qeWl0z3zW^ vW^%pW^R WCW\ h 3W[XW[l}ts2%#ߏjEYe@_:|wV0uoH"b;zT.eyj\Z{]X\^[ ~ (Ш#" Mѥ -l S +w Qq wlDA g/-!!lS9-W;_-o --o (-`-!?O--Wu-- 0-= 0r -E=U1E-l=WWb==0d@5==0r \==1H=MZ@e=-M=@l=SM=@r =yMA@_B}MK0JM_1 ]^ٰM7]^ 1]\]^W2'Pt]]L L]]]R,]]]q]J]]#! ']m\ЉU=m\vRmbm\Rmm\ -mJm\mm\qҔmm[wm}[R2}B}[mJg}[ }}[0|}}["Qp^&$ d>Y2 qK%f@Z3 rL&gApt)_FMZ@Mq_еˍ 󍪑 Β .t8# .d@|la՝a CM#ŝIozN9͠_͠?A@ 0!ӭWgL iM}gr 0Gʽ?Xl]yZXcT=-cX]% m͘ ͘rpf@XZ"2H2Оpqn~lX 0 8ݼ @^ОpPᑀ/Q ݀Vf@|fpMFVoCoN`x%\+;%[Qa%Xww%Wcu '%f@됀Z3 tM&54 ItMShCt^{W^[|p6C&v *v !' A+ 葚 A @B eB  ;+A0 @l  S#- QJ-FRq-kR-kP߀--S:--SF =R-1=b-W=`-}=&c -=&a!==LbG==qb@MMb/M?M^=cMc =Ma=MbSMM`DyMMs M#]q[ЈMJ],rq]Qr]]vrM]vpް]]s :] mqa]0mr]Wmp]}ms mmq,GmmZ]mpY }}Zmm=}MpГmc}Mppm}q m}й$3(&jDc>\7Z5{V0 KO*pK&pܿ3zj3 ݁(ܲ,1 )) #Ne 8<8Dm0Uȍ۝ "3'Y˝Lq<a@㭭-5Q @ҭS\RxC` o-i' L"2rGWW")pl|͘͡"]ͥWO@ hWu@ 4WAYi(CWP $ݥݥWP IWa@{ПWi0) ;W0 `W10 ʫWp PWY uWY6!+AW!g%W W"1WH&u)' E`:3zT. ON)WnI$wX;K h1 ~ 2o 3+ A8$X6F"NA ktA B CA-Q&-4R K-[Sq-Q[-Q--Q--Q;-=b @a-+=Ac-Q=ha-Dw=a==b A= =cg==q M"(q"M2MNq=WM"tq=|Mr =Ms=MqlMMZRM]Z, M7]GPM]]Yl_SGM]YC]B]Y)q] ]]Y_Pp]mY_@'];mY_qM]`mPp`s]mY+mJmYPmmYvmmp8 m}YRpmB}Ym g}Y, }}p02}},|2 Yu*( eR?-!%taO=*q_N<*vdR?,{QcQ?- ubP>+p qZQWA …ˁЀ_uˁ ?ۂCV @ۂD\\ۂˁ b0ˁ+YڃBRˁ$+$԰ˁ+Xu]&>Xpl: XlZ, ЇXۂ ,]ZX]ۂX@8ZsZۂZZ$XsZc˂c$s$۔?Wu[WRӄWo˂+B8$ṕʂ%WpЇW^D'i& р6^HI pZm[_pȖ@ȼ˂ڃ pȶȤ$Z p$I7 Ep0J0%$p۔@/} _ )-b_0 W}_0 |}_1`yp-^RWw^x JB^ g^q}l ]l[2vtc +)n[H6$~lZH6$}kYG5"}kYF3!{iWD1 |kXE3!{iVC1 ҝ[BP[$QNʂ M O| 3 GԀ0U|$$Hl }I 0C ZIB70ӂɲٴ{) [%{(W hI0zC0$l%((I("((Z($k7@((n(۔{8z%Z_u5r๒5\Ѐ#Gۃ+^ -&7Rw3G'+] Pp7]]])53GP+\u۲ \R 4Xڳ7\I)XXW\$\{P"XI|XZX$X"7 +U۔[u [J7[45h6 U[[Z(u`+[ YhEákh~h+ZZ%ZPhZ~Sh $#x5x HxȔ+uYuH÷xЀ$j,*m5"}oaTF9,?hL1 e~iXE2qyncXC2 חqYC-سxl_SG:-pojgۄXYW\ VVWVV\}WZ[#@0eY SjfwXZ X^burvwujs(2uf|wYWdXXWŜWWŐsurbfvrujbvmjpfX^Vvfus`ulmfsvufd Q4am`blFvfmd ay [^sZXp z rVWfs ap VtYYao[VY_[bpĥX_[VXawէYꥻwcW-էW[݀`[ HGZGY PX[W[]WV\ZwVX`bf oiv W__ZillX`YXapbjpGaxW\ok^b[ igsordasX>bXxsW Za}d`_vV4\AEs> E_\y Eٱd`X[O |vA E܀8vsEsi^^ZXX=y i^\VhZXV[] §YxwW hvmXZV\hvwdX5 ֽZmfdyz WX^w,Y=/ mvW_X\Z2 rX^.mzX2 [ VVYX` г܀hdVVW{ gw[ |PZ Z[Y YX X W W vY[V gvXVWp'习 3WYWdA6u_X`{#_bD'tE$D0E CEU PT$'tTT0UI CUUH-e'Qdcd 0ueCed$'t-t 0?u ss  -+o_O>,-seWI;-=AOqcUH;."s]RG0q]J7#~dUH9,p[ˀ3 vfV[ lZWw[\p | lZVYpZ[Z\Y\ W o[lYsXZzdbײ& X4&YVC H+WWW 4j,HJ}Vj~lYgo ܀lYYW^@] vy [ZYX1CV_PKV\0 &'[5''X'c&'X1!&'Ws#[W`&WYplf [ z $!lXs* 4)4#V )j'}8&}h70$79WXCIJ9j70HlԐclXV\vZ  0JZ 2V#WgdslWWA0X4Y(40Y XV1Vb_4# 3ViП1VVVd^| k{W\VsfCV`| kv"km@܀kf[ԐBY]WF/FZVScAfJ [Eݠ@EW_{I]{«k^F@TZ8PA[W^TY]Y^Ð;Q IBXZCWY#BP8R TAk TXP P TW[^mBT:X[ PUZWtWg XYTWZ^ UWVYU` gX_;h^ ga6h/RVVԑRg RgZ nhZc RQ@E^X` bBIQ@CRjwZ[ma·`VXX``c` Fjpj|Wo[ s{``f X ppjamffswrpf`pjwfvw p`m`uorp[Yo|ZGqpTpGqLuYEsLpr;Eq^ LuXEq\LppWX[rLpbqW Luvrnlthiw}orpr' ߀]Pz/!@.},ppP0v;9gJ+ uW:mP3ៀiJ+ X̀pRE8+vZXXxg WVPz_WV6ZV`V\^ZZ]΀ XȂ'Q VW· V΀- YY Qښo VҍVYYvs`bfuXXW^VDqo XŐЏ+;ѶCХңVc\Y`τX!șȢ Π#"ZȢ x%"Z%Ȣ ΧBZ#cȢ xCW[Z3Ȣ Π]ZǚZݒǣbʄɡbʿܽxbHeb3[WVWV5VbXm[D%`c gݒn!&GcـUcِ&bc3˲&HQIq&fd}}1mr\Z X[O[<-ql\^_WVWpg Cl%P0&su_/-ucO<*o`QA1"}maUI=1%9yi^OA4) K߬S|naRD9+`l]N>._uF7' o]Zb_XXp!WZpxVpV^p3\p3$^[Wp$]OrzrYp$Z?YR  $Yl/XZ XZ/ (XoWp W\$W/'>$J(J(/J%gaY1o\Zc[^X }pB W]sZ` '\]a( ![l@qoO[]iv0%]bXr! 0o[Z[''' '/%Z3 "Y\ '[Y" @oPY "" P B2Q@ $Zy4Y !`5X Q1YVZ[6P42`~roX[ b3X[ $PR4X0! i4 !$k@4W1D[4# i4ua EV0r@mw{ovafiPEXCkuw`B fEhp`B vFf`B fEam`B f@@mwZv?bsfr@imsEXBFB@PmlN`D[PE0FVEV_EV3`VZVYVX;VW @YAg^DFgCgnDJfDg~DzVCzUDjT]^][bv[A[^ WYVm[V Wu?fdSqS?amxfP`>U`blPYAZQ?3`]\bvc\WQfXZbsWST5`W@ >fW^@ Z@X^iffwg7ffd'p ScaujaarPu`AX]V‰d\0ep`QX["TTbRTd*QeVVPpfQ P c TWV TsR d0uq ubQ$)ugY{o›  No ,X]XZ[ ([OZbb=WY?No,> ϛoј ϚZo Ϛo,ibE^O " EЫ \^^Ѭr[^m_0x []yZZWyV o  fYWAXY yZV\\a k V\!No r!1 ZO̼o r!1 jrXY_^y$8IʛZ8 pgIyIZ[No1 Z[`ZȀg"*!XW X^*W]n 0&\n#\[:! K'  f[][]$,=' }U WYEv깑ːI 9)XOXn gWY ,g$8>MD]P ]9OIy su 1/l[J?0!xk\O@4' 0~o_QD6( gylsOB5(vj\2sfYL=0#؃vcˀ=*X_^\ps][XZ` #s]+@Qs\[VW\[VZ_V#*^!*]4*0Y! d[ rXv4 [ rnQ0s\Y0As\Xw_ ^VP *[`ww[^^^]]W\V`#WXfU0Vht N3sZ[^r+@@ W F'V F&WW F$Y]Wb!s! ^ q!}Z/]VVsrXp`_z&X ",(CA, psYVZ]sJ&(Xt& $W, }!dZG=6YI0W_V$WZ][ j0Z p6` p6[_ Z2Y] B00f2YZv<|"0mv03wY 6X6W02VWiv [1/eV^XVk)9$VV0 EZ A#FWӠVVX[ hA@W\ GudmDnYG_YKEXTAYGX@\VVid zr!_١HY @rwsfumarw_@\\Q@^VV@@BC@ pBh@E@U[Q Xa Dp^mgC rrpWV:P>PAdfm^ol]B6RQZpT^W0kPOR^V2rbYVgP)"2QX0iJ2R0XVP`phogp_ SVa,@RQPpp TW\VZa;`T akapY e+QZ eP8PbQX eQIeT` eeXV@P8mzxlg bogab`VY`\z[gWXz[fg ai`oaX[X a`fo^^PJ o^\w cVb_upql0 p,H, ɣoxy\w lzZ {zWo20sdTD4$w+1whXH8) teVGc% xiYJ<.љ߆wiO>- z`D(ူ~k]OA2$I<`uvW\w!uW7al 92us\W& @rV_~V].p@.RugZYY @2u][\ mXw[ ZXVa[xg ZZVz`bkZZYYr "0uXV+XVXڔ  `2ӒWWєW*ٔWW} [\Xv0dm0 uj[WmuuYV\XYVyW}V_XZxWQϠ& Xť $ϣ& Št][WԚRtI} t EIf}\YZlswgVV`sw}[Zb[\_\JC|d[hgp@>P|VXsy >Pf{wZXP3xC]làCŲVu ͺlXlq`Xl8)ζ u }!(lWͷvuaf0ERsviWV~:#?v`_Yrǀrr\YrsrZY Tǀ r rW,@^Yr ȍ@rƌrYWufV@R, am`bluwWV_efא?Zu]ǰ;zXPC]uChYٰ CYup@qYuab CXuXuaCм}!אWul CW[ʰٰaa a?VuZ]5Pưr om h[Vw db[X[urk BwVYkXk{WkVk `k9k W| TW fb[V_~X^~`]~`\~`WVZ~r`sba}wfbu`gw/saW -KBaWf/]\ZW9 Z[amp9 s\p31 q\H kVB.vbM8$iyXD0ʕxdP<)zgS?,}iUB/ [vX[<2 HZrY X Wfop ^F IȞ"dGC K\/\ B\ V\ j[/[ B[V[ jY/Y TBcVY jUX/X Bh*VX J%W/B@xVA)/KVoxM) BV  EM^8R9`#h8 @:#e0t9d:R8\l^e9\(y9\; 9\N909[le9[v y9[ 9[9e@#9e9\ y9Ȱ9k98O"9Yl_u"e9kY_ y9Y_ -9Y_91P<G# Z%#%Zc:ZL$OYXC e9 ZC y9XC9XD 9PZ`#Zs#IZ$j$29W3 $e9 k e0pgHCj(y9:9MbOY$jjI!z`#js#j$$ !z64jM$8%_ 42|iVD1 p\I6"uGO<)e|}UAmZG4!taN:&ǀzfS@,p|h["Bφv/QD Q5炅Tt#j%[# $$j>RE| oBLC߈ZڙC/D $EE {#I%#8$Vl" jYuB Yu+B V;"oCY%o+B Ϣ C߈Y*CD4B %#4B S/U1UVBFU >D # $%#8$TI O #R54I4jXXuZx_2IϢɭ Xo ڶciِCXlIO_2 s#OْC /TUVeZZTZO Z#(dٔt٨t ٚ$9$M$R I4ju2WLD_2 B  o2WVVV_2VH 2V3 \#s`53yeR?+kWD1 q]I6#Y]xcN`&p[F1 vL8, oaK5}VVWWVZ CYV[ ovo\XZXauv  hvzl [^YX W^XXW`YVkv Za[~v"u2 mdY WclovW`XafY*^WiofoZW[z`bZXWd \poxZ[ZZ_YWWXZbWW_W`sp(>"[VYC vYc`W`io0vYWV\`X^XW;-sN+XWZv c-WZsN ("A"W^J -_ +Zv\v -\sWN -[-Xv-XsN*WVvmYv=mYskO&XD&I=_ ]0$R1Xs!$];#r:#=_ '1";"= =[s$=0=0N'1,3]:@4 N YbmW_X]'}P"XY[W@XZWPWp[~VW &"^i  ~@]Vm-DW\iCuw?W\`]҂_*_MH؃ ߈ uWgc_tAP㒴^^H^c ߈^(c#X^ `V[a`(!uW\wYl8op\[^^^X/b^Z`(!&[_D nY^dY|` h@lv2 py75 uaO;)~t_K6"lXE0xgYNC4%}ևoaTF8' yl\E. paRC5'Y}X[oo3}ZV`Xdb?Q}Z\5 X"~Z^0Z 0XZN "( TXZ0 l V WV.6}PW'hh@ XjKZpVHv) |j Wpp{A|gVW`["_Vwtl [ot%ZY ''&Yw_'\$Z'YL!_VXWu'Y&& ~|^^`fh@ 0V|3%5\^$^\]`S63\%02\f36Z%5XW23][ZYkp|1Xl6Y]05X^05XX^07\z04[]Z`0 0@|[\3[0@|[Z]3Y\`ki 5Ad 5Y 5X|[Wf|'aF@1[2%0WHo\4[%W21ZF@@|YXf= ||X^gZsb 09P|X]m[@t@[ JdB0B]mA@|GX[/\tb,@JCGB0AXy]K@_VFD;SAEZ@APY]zb FbZV_RXVBAP]A8QBAP HTBA ZfS D]b W?RWTcAkd@Q#kzSE|X ;/cbWk`1D 3\4|a0eDIV!0fe2%0~\!VW\` %0{iYuafYF{iWBc`~`bdd`{=lb{W k`3zmX [V# RDt( (ptDZp (wnp( (ppq"r(phu((pzdjmh0z\VWdsz[]W] vbqXYW]sZq prYq pqWZ n 86 ߩ^G5%/߫7jVB.ﰡzhW`4#_evhZOu7yq_M;)vdRD6( whYJ;,mjU@+ p]ZgXZ%[0Z0 V0W_ZW]( (\\p F JY`p ([^p t]p W|BY_p(YXp(XgV V  $Q  ɐ p\vX[wVZAPDYqQɐQWِQXX $_ ɐQ߰0ϫ`Q ӧYϫɑϫQ@I(_I)ɐL Lp_pɐ $p Lۢ(I_ɐ z L^g|]H@ 0C[q)W0C, [VuX80HſUKZVu*Z!LYlpV}mp'pBZZ 0}^k^Z]]w&J&Yp?Y< teXxfs vap@[@W[P0B@P` 0VXV]V# "3\[!NXU 0VWa|wya$yI`pXVYxv3>bЦ\z ,dXXZz WXz иW]`WZf|__[|0___ lVk]fbfXW/`\9WV`[%[NfbVQ@ÅpV[[sZot#YofVMo0 q VX 'sY~ W~A]_V^W\fB}ZpdXVgB}CZj0#+4 ZiV!zth%&)X W @bsv  97{mO@1##+r_O<)= O|l\L<- ߁q_y?/aQB2"seUE*{m`QD7o [8u fa- f[`{0f|t! w[X~f")XVxf 7uk3qC M`w۠I`"&1p`uNkM'n[ Zo]HvF Zhfbh b 8q`]WQ01`Yos=#o "gsoq sg Au[o1 *"3)jP\B ]XosU%gY U"g[!`% gn%#$buư3#"#` $s.  's' p$p! 2!1e2ZQ02Wb"5713#pE39UA7V^8%ZN8*1~:U25 $2N0AV]42 ^43p:P8 N4Wp I8 P5$B,HY8UBBDV/oZE0uj_TI?4  mېvgZM2& ui\NA7 vh\OA5(yk_R8+!'b]g|$dmWb]Bb\o|ac K\o g!I %1\ [ p&w@[osP}w p[9 }sG}gsWasW#}̓ }Z } Z Z9 a$ .ђ<U:}bZd7ks| ℤn |bZ_ ^V ]Y]XU^ \Z_W[XWX WrZ Yo|}!a">4idq42&5V1ucVs{bdzV|AoYz  ##iz# i+ bg7Wv;gDIGV޶kHoґ޶޶* g\ \if U ѵgڰ V2ʠX]\^[#1 Y XmD ʟ $} ʟb@ X$W_6^6]6\6[6Z6Y :XYf|wu`R8XWVx[VxZ ڬh٧ X[ө  Wڢx 22 8m@9V@ @o{aaW.!&ޞ`aYV`aк) o; `s a[W^ho[VfXzxVyaaXXBX$`w?%O.na7kVCYV/u$[rO O`27a7 sq=<yi]QF:+'-saQ@;"vS^E8+ip]J7$yfS@-tbSD&̀ۀrcTE6&qVH:,o`Z^W[vy B Xv B#V^VXZ 302)d ")2Xd A2VZ=2WX}d}d}V_vtd 2 V[>!)\"(;22(d 2O@o_[ivVXptbU#W\!a _Ybv(qs(V)pa z \*)p '[)p '(q s'ZQ '! \a oZ^=a `oZXX`d% a @oX]b tXj0F;W[\`<@:p(1@<@7X[\2f;(1z;@:M28WuV'27WX^2I ;(1 <@ 7 VZ3 <(:M2]8WVz(17J@3JK(2]L<17Jp1y0XZbVdpHPH8p$GpHp@!XYXdGbt H>@!A TW\V^ @WΰW4@@m)9IBSoðBRgbI`lWVWmk VV CwPW[/WdCk)0 kpkQkZVxW?{ RSfX SU T3\ba`hRRPSbSV`PQXVxW{ПRXU LT4d P`k?\RTW[SȾTgcPTwd Pjwd\` dZ` Ğf0 `бaVoY0` b`fW`g``$jw\,cZ`j-wb xX`q eX'u^ >v `jvb`p hdObisWYVVvgahxxpijXXsl~XDtWWr p 0ijWWpo>iX_ffA@@|bg@r^Kvg@(0r@EY9paRC6( }hSF9+EreWI;-}n_QC5& n]RB2#ɀuaM9%?,5@YYY_sVVW[?VZ ۉYVXT.PX&*W NIbv.P ځZaw`biv7^YXpgX{ WZ]Z9ҵʔYԗԗXXZDԗ]Ԑ o\\\upY!ۀY X N^YW]W]0`B ۀVv ~obr ~͠3X_ X_فX_izŬ׭y쭎XH 5;'.Pc ]$q.Pyǽ f[[Y@ "L W`s pXs"p]"dXLpXWpf8xdxt&yX_@] @t ¤ \|P W^V ]ZV_֥^t(Z@Z\] Z[[@dv__[\=bsY{ZY {ZY$p {Рdv]VV0>|V\s]V\am[djmXoWoHb pgYZ_l0XZYm3_~wa "i frBWNOkU` ^a kZa`Y\_OZ[^jXjW{PbQp[?V{ijP bmpfgsè`ofoP bmfGPbk_glz%B6i?\9$Oi? 0bfWV7VwZ AovVZ{ U`uAD_&^&b]o|a ]BPy]]odmذ]g ]sk :;obUH;.!{m^QB5'vh[M?1#m}hT?*}iVC1 q^L9&{d6BߔB g|[]^q@z\[[wX`[VGp X X`WV]/\(\:[ #Y# gw o{bm }aaPgv^V`VWW[\ZmZX\ 0guX[iZu][Y+`]u )WXuX*X!Q R W!)+WV! O'X" '[Wdt'l" )]u! a$ V"( !)l" )X"(XeX# <$W" 9l! (W !0:*2 (j!! sXsDw0{5w0{5w0CgPuWWbXXYw/P+;X0;08VWbZ]UW0=V0KD00KjP00Pa!P"B16V1&3VJ3UK3IM1jK3jH"B1 K:CjHE j@k} QaV XaSP`g`VV["u{R[RocP\Q"h qgZfa[zsRQXZz}XWXzTY[zSTXSHTQQXQPKQXbXa vgX6T`sBR HSfo^^V1fbma<#c6a1c::`>`Ra>`2bdop:`>eophett:`>d\W[uTp\eVpYpf[_XpWZ_`dG^_{#e]if\f f wfЕ e\ 5vdehOv`_\wde[\i{wOv[sx[aNwd s wsP>wdQ@/7yj[L=.Qzk\g>/ }n_PA2#~o`QB2"}l\K;* l]SD7*MsWX\QWK8 bsWRrusn %lX:`SLb*Y,>`~r[Q_o}dWXNMXYQPY V[w0wQPo|vSxvrwXxXŘVʴVŖx ѐ $ yŕRx$R jѐzI jz jz ͩѐݩ ͨVvVIMzxZ6Xv>> I\I\W>SsVhvYwiXZ9 d IŹV_Ygds 7m!Odn/I.Ȓ= .$[: jȿp=KPD%લd .Nd=s ߰ dq:d.ĿhbW[oo`gg`,g YAHIW I7#2KnIvWIvd I *W vf@Yс߰ȏ7 v[@% |eK4ScD&v\B"ƥqV; bR@. ˀwj݀N!pe rfuVZufgm4Wqr{fs0V 1ˀq*rfoXoavfܼ1VY`gArY[lbbɁoYYiG5[`1KXwX-duxArd\^?WZt`1aap rbpiZl]]lpȗVu9ĐؙlՐXlXęXXlXX lՐm@]?lęW lՐ޷_c1r`k Uǂ`_[ Q2WVQ`Z]iQl}M1Ӡ orXviffwG4઴V'F!Z&(8#CEY&^n#ym}X&s!# \C଱Y yV^Py[hgyy yɴ]#$/IT<$}ͥĺ㲪*ɳp@^| |Y@ ն[V'1#ZEP#YEo#XE['ݞEݖ#W\' XB' >> B fƳ D"\>!\B#i\Ā<ZWY$|ǷR-pR޷IY '܀W_V V7_ V_|iY ^( ^V  s} A?߿hXI:+rdUH8-" xk^QA7) ȿMOhZL>1#tfXJ<.g@whYK<- vgXI:+N i@ɀs`\[VsPaY]`sYlsX"6V2V\2UZ#cY#cX#cs`ZWYWss` PZVZ2 c Y]hsU X cX XkVWW2V"-cW]&WX_3&X:!&WW`60cMs_]gse%f`q%Vhv~'~q$^!q$# v '&m q$[_^p$Ya| ^mss[V[dMǂsZ_q 3! 8 5]W)6!77g} 5\$"q$ZZg~a5Ya5X:j0 5XWiQa5V214V!8o7O00g!v7s 4XR! X2 40!F[6 D621 F$2E^v1EGFXA15!cGTE]A}FWj0I}F!Gj0EZ_1DXVh~EWYm  @2"E2D"! HGj0 DWE\  'R21 DV]d>WpP>VmqXW3@XWWp>U[nP@soZXY^ <"oY[^6armuox0ipYVZVx@TYPWXPCgpgwacg KrP^% d eZ\`ǃwna*`m~G|__8d^29cHCg^^{Bh^\niniZ niV%Bh[_h[߀B`}7dWV\ W` B`cVCfv3dWRfdZCek^V` Bf\YBfZVp'yW\ eWX[` dv~|Z\AVt`fh`BdjqYWbdwYwcjqW[cxWru\YhWаipYXsY`WﰼuXVr v|pQ`r] lB@}ufW;- xgVE2{o`RgznbVI<0iQ:"kXD0 q`U=/ {sXZPsMosW^Zam`bl+qXz [YampDPVV^_x]qPWppC,` WW_^V`SoVՠd` `ۣV%r}vwfua`w}bi`uhfu "x`X]` x`VV T*V6 `-Szm+TW\[ wu-b3`Pvx$M #rv_jY[zPllWY rvdfvw W[[ws ްfj ybjXvbrsfb`v/`m"v]Voruw`bv}um;]E[][ZRujr5h`pjvfusjfvY`[WXlu` jzX[\oa}zWdfzfmu'ruXZvshfVWxlXpuXV2W^*; C\; C C' W: swrfmfbwurpjaPwj/vwuj0u粶uWVph[| !a0V?VY蛠< wWVW40rsj^Vs "m*YX`RsjWX\ZdEb S`!7bStSa^\\w[[#f"a]1Ta\`$a\X[A@ #"(^ .sqpCA{o`SG!/# |jYH6%uMK6! p^G5)|ZN'|j]P?. fZNA5 ,\V[oX7\VkQsd Pl[l[aoO[f-[y#*[ՠӐ$][ Ywo`{XX__[h\Xm^Xo CjZWsxX]sY*sxWxV\sZsx[_Voiosf|u\ fih Y '# yZvf2?$ԐZb{W\sb] W[e LZ#W\Ee |$^ Z^O Z^v"͐ѐ#̑ѐ"ڕѓ &Z l!^&6;ѐ 2dѐ-Zʡ >2נu ?1s`urmmv_4DYk̠Yh`:sY^^Vvw5g5v}7g0z1\`Y"7Y\v"01\17p0aYQD 1j-hAEQs`QX"Y\Y'(B2 >%Ej.B'YP1mYaXugV^±CUXu VWY b ow oh Xu@'s@D[oPDf VX\ X gv@@DCzV@IWC J/ gs@H vo G V]UG`0T3T:VVMXX/U@6Abg17R3X^gDн Va Z |#PpZRai#TQV]Vaag"`5i#gP`QA`V_Wa|waTlk~laamQX]^W"@aZI<2XXP^ffW_ :bW\Y dH uY\{ uXZ .>xm?ijvMpaVr`"CXZc hkwWZ]zvurtzvgd`J \wtr wbbtr(w|vaZv;*" DB|i[M?1#tcSE7( xgXI;0# g}reVD2 m[P<*~oaVI3& udSB1 @ףԐ`Vm^abpv}"` P`bu  Z;  Q; `d `đ`b`Bj!`bdu`v` m^Vz g gː \WZ vv 1`ZZ{sg Z #f y`Y[{V0`ob^v`^[^[ X]Xw\XVZ W^[W ^ ! hp|x`W߹`-~2_\"#B$ l "Q'3!" #a! 3 6 D6 # # ϣ07 _\tY!^]b][Vsasp1 l Ngg TNҰmfUZefgҰnZ_^N[ӳڷZ* ڷX h ӳ (PpWi1I^][^MZ^i ^\Xv?^\WFXb[[`0CĚa k^Xa]v p~RX_W`~^X]ZwQi[`[[ %pbXxjzW[[i3FVb^^ 6L ݱVbY2[~[WaiW6{V^^6^[`2Ĥe] U1^`iWWoi~Y]mgd |OqV\d ]dPZ4d` ]^rg<*hr2kk]X$ #]X% '3]16 #]eX"aԨ 3{ 6 6 ## V0]VY]Vas WXzdb\ v~2\dV_Zsaǀ[٠Y\2WZY0:Pl 0m[` t1 iX VuWbiW \k<20^+WS P\pV|%sd ECwbN:& x;M5Q{dM@1 uwk_S?4*GiXI>+xiXJ* mQ7sb ` w ^xg l XȐ`b[  Z  Y (  X >XjK WV +?WK @ obdrf k!bfmjwfsuryBb`qP Qa`moi`pdmrwjrpX[Voma}u]Z[= [bwE Pp= W\A W&VA e)`e 0k"e 0aub^VVauR_ 2%` 'Z$'J^!T+!'X$&\$7!! u0am]s~amY]W] e H!=2X=e .2oYamаa5P60@ampw6Z60!dY[Z^ e$dYZ[0 e a[a00aZufdaZa?m`bl01Z a01Y `43a0z1#qG}a/pba 淒@2 a40hΡa obp~jpX 9y2^Z[aLFPLE\LE[|L@vwv p~`wYxlX!kwn @ dzb@wPVjwnP -B`wv @@ru`mmfmmjplvf/ujfv0wNrA@R sfuurmmޓ`\ 7bfXZzWViX[kb e =UXFP~JPsbQ\taSe #XUi]sb3Q\iW.LPZe YaR Z]/`R.XVz^wT]QKe WV mTVW\z^`T:`l`@etKR $:kd PkS :` d$bU mT :`=TeQ:`AAdySmMPkbmMPJ|VdP'}MPPkaSPf[Racf[RWzzXq:`}dPm`voI@c[RcMXV9  c FDv]B'0%+eZJ?4'5UraP?. vTC {WE3"{jYH7ɀvRA0 psibwXZ[wۅZw{VwXWw2ۄWs Vgs .؆W]〭W]Q\du[O]wu W_s ?Y_w Խ* .W4; .V^V^s$5$Ys$X5Xs$5;W܁^\Lͩ͠ [^ YwZr؅Z[Y1 s@Ze[:D DkY[* DV_ 𖐌[ ĞZ\O`w  X ºsDuD Y_Z Y_0ɒ^A YX X%[q$s-sͨ W%_K pI  ٔ =ڒ ͨɑ -چ Xぢ _0I ن `'P$p-1 H#X`_0W\[[VdpE $W\ ,VW u`jmv o5.RXeiz v {gZ]pgWlzr@z[SszVZuXXXXX PW W"s/@B}@A| a \Yzd`>"siGEdR@-udSB6*9=qVD-YtdUG5#o`NA4)ߏ}kE3!zbK4=Pb{WkaXZlba[VX >4^Yw g`M7u^u\8Xf}< űB0]]b?s g~M79s 2BѰ:8G6G>4]Vh0[sI0[G!fmjwf\.0!d[Wڑ G~dYYWXb[ PBV]5#at@!`xA`!S0`!j_X\ } cW^ eV^ T` xR w1 A@\^.؆3tktjRk@iZ).ŵw hl5!dϲkti*$.y?{?p Y.YtzR.FX]S?~zBuHFp^L:(|m^O>0! |lYJ@1$Y~rfZNB6*vgYJ;,{eOB5)weWJ=/"'VY jP!jWYP X  jWW[`f α VZ ,VY% fjYX j vzab 00gA"!iagpV ʀZ RiX_mfW[VYbҰRf| Ybg s^vg Ʒ hvl@0huWoZ]hV_h ih  W\p\%h &o_]` ^G!>t HZW[N R HYb RWZsY]N RV^^s z WzX* YYNVV\NR h`XV]s` T\[0i1Yl0JX3 h"^`3jg|r 2gu^[\u@gsmo YXed gY0Agm^M]wL\ȵp1@ȵ@YȵXȵPȰrb`W;hgPe][5Gb)V /( c0 2$\_Vtg[X]0Z( ZVdX[ hX[  cX P X~ jXpW^1@w{ijRufd}ruhǟamlrWWibWY`fkn V^'gVVYY W[LV sbZUiIWWQ[YU fw=@W0fw][][oX[W[W[~WYZֲ ֧V[V[ f_pmjhipfpVW^]!fp^ZV CBfii`jRfgD K`D K0f7 dvwoZ^m`WXvr ] mTZ#ddY80 0㧐 0daYZ__[V_` 0 VYoE.W[zA'!'[ KVZ KV\ oU oZ oY2EoP4 E' sh IGtfXJ<. %)}qbSD5&}GOyfV[,at`K9&t`L8$aN:&oZE0 jbW\b\ VZ ]2 k{ 4!Z v WV  r2 W.WXA z0nUQx[^`+/?U []|wj *ivB  3!sY []  ^]|wB*Xm!pu+ub u+Kms u+)U\n#;)\"**H"N)\*#I;";)[n#O([ Ha0P7#s;"s;" s;H" s; a0Z !s9Z a0Z"dJH"Q&Z`7ᴐ7p&J:m "!sM6":#Kub"!K#K J*Pda djmv6erYPPvl o`px`m/ [jx!Pbjbbrwrla]P9 bja#_WZ\ yPPHPPxQW&WVNJVYQ WQVX_&W^&W]&W\&TW%WZ&WUY&WX&W&QVQO`iQ^^^_e]j`^VY`wefV^ tjZ\"aO`c,af;afQ e1@fI f,a f;a fReZa v,a v;a vQeYaEv,aEv;aTEvQdYr}v*,aY1rvQ uMrvbvbxvbdcJ}HlVA+s`M;'r_L;&lXC/!ʙ]wW<thYJ>/ |aK6E:)u?Zm`vwlf}YoqQ戓 P\ X W ^ jps`sfuurmm]V{g &P`[^] 2& AweSA/p_RE:e$utZM@3& reXK1"~qdUH;c]V[Vpog\Luodu~Р}fm }|{iw5{5z5x5w5vufd5uw tsxusmv 5#@rup5%Юpojp 5o@Pl k j i hu}huv{) 5gPdba >aml # 5Q`_^=] G7[G7ZG7YG7X NG7W G0V)0 G7V 5YV *3 6V W[ .5W[ 0"j2 G0G0iPo`3rP_] C[ EY@_ Vf`sR8A0?@հo^_W^ V°?@]\X^mi _C[ZgAM lG[glGYh@ lFfBGZ@lEXX\@GZhH@l@pXu@CXYV2.`C@oWWWZ[ZV XWP JWXS.Z)Q VKV_SRZ)QP^WVWX@DW 3W Amz`a7U[\0XV`Pհmx}vu^]pl@vW[YplCR`pVVO[p0TV0o^\ Bmr@ `mmo3X[aPb-c[4`Q;eZYEb;eYX@;`jaZ@q`Wlw`fW xbV^0x鑂23Bau`dz0fWmbb^ZI<.ãzl_QC1!}hS>1 MOZ[W P aWYXAR aV_P`3BݎrvV\0\`os \YY--p AYMU!VW[fNAvobx@Uq}osajby0  F`!Wr@UR(xgXufdRBram`blW*W$/v_Pd J1#rwr` 83BH@burq`jw`^jwfvwsvj8k(v { (/rg\)Q @rX\u^ ῬR")l$!1*&Zu] 'ZB)"':|:'YuY '" >5PJ8_'mw:xY7'88 t':lY7Wu[ A"1'a E$8̠H۠ '颁KJ81HA KHf G O"haPuoN"jVX[Klbug_kBugU Eg`@O!g|@Pub W]pp`@AC` XZ_V@A] 3Xux`6PYVXs9FP]]N"Y Yq/bF0 6PAFa8&wP}PtR =gPO!XE`gT6PRQWY UX@TWVzZ]ZgC}P(amhSW7luV S Y4Px DPD$VWD0_U$fX 2gW Ai[ AiX 2f^^T1^^%^5`ܠdE! a g!%"T5" E[

XX kWMWc>Wp ՐYX_WNi9>ZYk`hPuXX,=P=X =W򧢡rZ!Y PW' T wV^w0 iv$@V^ $V :{ip ,^|A|_YX|^d0v|u`o^8tWW\oXVZ^I!xqXYWWIvARXȢw[ZfuY\z#p!u@}!vr3WV8@Q U vrXfx @ rWxl-Яvn@d\jpwvYd dXWfW>P~ db?Y`bEXXlaH Y@_ dXWfX nXY ^V됋hRvv!{_jp}BvP,vWXWh\l!XVzePVVhBCphsnOM}nbVJ9%~m\QF;,OyncXgB7,! PufWH=/!jU?(lU>'ՀkR;$~'xpbi[gurxpds#& ^[!Z[ZY]Y"JYZoBXLooY ZXU_XKoEX ) )R ) oWU WKp)\Ip){)p)ҫp)p) Xv#vtx`uf@25$&W:jt8W\U [6W+ W:W <"6:W8 xos_mbxmvA@R"@9ARxXZ[KuYW6GPDG%m@@SHP D@@7xW_`rRwAEzP@8AW\ZljwDDW}p@E[BrD D@WxZa`ZW^w W ڒvZ(CL`%=`B\Tsbs^U]U\U[ To_q PUQPU]PU\Tm^8|Up|U\T`U]U\ETiPU PֿTPU[Tg^U>`U\ PgWZ`*F| `f`ۑf_ Tf^; 3e] PWf[sVWdKdUa ZgVeb ZfVW[UaJ|gVbhTbZe}XhZ`j"f`jᖯfVYbj gW[az Z`ddQP:snPCvyPP dW]V\`ybb_Ctbb^vv]lt\vv[TplvuraaPfCtaa P aaPxvP XPN҇v^N6%ugN3z`}GuyqV; )@K.߬WA+jXJ<+ p@|VVrB{]]\[ v)b{[p{[p{WY^{¢;`׀`Uzw`plf}r zuY5 bzuW24szoY[V[ zo W\O%*jsa?*dXY[XsE~WY[,|EZbw`s0_YY}h<YY{;YYuPXh}uYYau9(mם(/XV`YipV{8PVu"ZVuCPŭV*$ڭmNPVviffwoZ[|V|`O H1!Y-?sl[ 8Ourd!R8']"slаme! mW{g[8,`Y`׵ E0z_Yhuroo'sl1^Y]]Yo ]Y`2 (WVM \eZhBz\kz[ W\LV1[aV͐P[#Z;yZͦPY]ݱPVPzY@ͼPUPzXo݌PXYzPW*X*,WVs_)[PbMPbY b@)ZWVcb`oZ|vsEFzVV`W#)/WO[Z_@pZY@W)vi{juf`d`s{wr vfw.%*_8](]e'z\*d\e' (!sv_ QOyiYC& {n[L=.qbSD5&rcTG:* ~ocQ>-}ufZH6o$p}n_PC6( Z^W tW^dhp@Nfu[>%Wu0 [mg?>V`wg[@`N^P_\Pj԰jwYjX j@j[^5joVZ[]aZ-@~s{aG~V XoX~rrX) ` #%)# @}s@ 97A}a$`b} dh,A}ObsS J!b<B}WZV2R r^Wn@|]VVl [VhG G% )eX!)a ( $YWZ;~h!362"3.3L"170@|X^I6B|V^XX vP>a4k7Wg0z9Wsk7Vg0 9gs k0^W@خ 3i 6Y6@7W70!V]^Y W[ \Y= A^yrB @]]p*D'@_2]] 7CD[^g1BE[]1_G\g0_@ @Zu0 ][rio !DbG0@KR DCZ1 _Fn@s _FY_g0II0FZAG^v0GiA "YsSGxAW\v1W[g0G[v0_@*CYZ@}VYGf1 Ys$G1W1W1G1_@` @X_PSsPDCXZA is giA*iPPBw\_[D3e\u B\]wPbjg@(D\!'E\ g\0eY\fpg'E[__]$C[Qf!'@BVAx`c^ǀ#d^i@f3 ep `Z q0b WXWYX # t:qf @@ `Ivƀ `cq`DP@yyƀ4#v[e[[[`BZQf0(DZX_x0(DWWXP_ʀq RP{l]N?0!+|;`QB3$r`N<0p wgW7'wgS@.οtdTD4tdT3#iUA tdu`oXZVw p|@pm l]k hghgn u`buaWXVwl}k8 g  k h] gal {k hgtAkAwhAgsW\psZl]o`V]lVu.XlXҧXXXɢZ Wo *Wɢ li``ʈVZkdhdkhdmlk]h`khg$k$ $g 3Y`bwVX\X VeɲpujW'`0uhYV|vifGX[{l,y$:9WUv, v9 =sz X[m{vy,uw;ۢ @/w6_I_}fS_m%Щbg6_gH  f_d5II  'fd6 MIM[ih pM MW^ 0 ÙѡgW W^1ց 0+=^g IfDLPI:hfY I  'f   I "skpSQ~qcWH;-)7qX?1#GQwcO;'svhZL>0"⑀s\Ep`P0&ɀzjZJ:*  { uX82}! 9 uXV0va eauW_Y_*!yaX_!MP)K1'[:827W_VPTXK1'WP ^W]^_[XWV\V\co8WZ>WZa  X\Zbr~s' ms`v@L8WYZV_:0 7WYYG" M&X*G" M&VG" M%H! }&V#}&f#T}&v#M%WF#&Rf#&v#90p!`91 '0$ 9]&9\&9[&0 Z{X[|\^[wa[lXo]VYhPZW[z@t~1 Xo0{iP@26P@ot|o~35M@0|ia{Y] 7XZ 6m0 GWw[HX5%`1+G0+G@I+F AUG0UGr@tEX1ha 4h` 0zulmA uv]ZgbwY]Z`wtLsk JYA@K@s IXZ S ZZ[A(]@ <[BP]@2T4T@{\'`dx\B\BHWWY_A[]A @vYY^Z_s UYE`e4PuPgP`tti WVWVZ`ZV K.gVY_YVY?b EfX^V]]V`X^ ^gZ>PfXZ ^gOgXA` EfWh`RdWs`g\g\yg`XXa`E`ss`WlX{w VX9 gW {sf [ iqtmbA@b.pҹB@ i8Ki0@C@03gaX{ijmsWtqypxW[~~WVY /wzk zh zg 0oTR~p]N>.yk[K;+vjZJ:* eteVJq2&xiZK<* ՝lWB2"tdWH9 ӀgjZ!cGZVVh` YXgVYZ40) z0ZWYb)buY\]2!(Y\Y"aXja U[[ {\w 12YX^by!8Z򠔥]Z\[ϖZ@n|y0bW_[gupm`1X< 1^]<D^UZ<Y]emW< Z\\<-[_<DTl]ZW]G!(4/ڢ\'1/ UVg\]V̠ZYb*8[88T0@:j 0Yw\pE Xq w%V Ѻ Ѻrw_ LY+X\\\VgOE8Swdab awaa`aNRťfdb a `pa gRǃdb a `a[{{[vbdcYY7XY\" /Fe  XY & ^Ҭ*\YҼX "Vf!0݃Vb!!2 #j ^" T( ]1/8N ]™pfF_ Hf ![/ /\VWhuf} A[  /m$[! fC/K\]\>e YY`Akpk.Y]QӞv!]Bn p sWjpUSw\A& iN3#UfVF6&mxhXH?/ qdWI;.ugXI;,}o[K>0  `YZ[W UbZ (`P^u [V6 blaq`]Z q'@`bW^X_ ``['I\Y(>"__i`h[d2_WG qWV\VZ`m۲v[0^w~1a#a!2 'g&}'Y\` 'Y\6 0^[򰏐0]o{b q 1>0u\DЊ0\[b[XsXSD™!W &XXsY)X`%kX'!`0 WVr!& Y)ت`G\[ b 2`@(55P%P5cYXMP5 (5XX20^6V205 (5Vg1n$Y_]`w:2]X6h`(@626`X6P 6a\6X6X19"`Xq $ e%S[p ;CHEE EE EE*# EEWrWV`WC^9@!/5dE>5TZ]>m@B[D6BAYF >DZEZVZ)D7ZVY.Q#9R>U;P TWPBPjSDMQDD'DX૑UCX DᛑU P P5CDQNQPZ>A[(`(a(aS"h'a1fZ;jX.i`\kl^ \^%+\^8>\E^K+8f[l\ [\Z%+[\8>[\K 8fZl] Z]%+Z]8>P%P8fYl_YSlY&_%+kY_8>Y_KQ8 Y%U©Y8թYKUY_ fX4H+M^G+EXZRA% A8 K$XdaJ ^ > WofW:rWl[2ʂϣ2ɅA!kR% 8 [}[T"[K [_I$}7J ^}ꁘfVuV}vxsufvvru [!ao+e a aac И@a^wp`wQ)WamlQ [ ZZ-aZWWĐRLaXZ+sV\gLbv5~WfP~+#@wH#@ U X`C+cgv|G`oAXVfoh!`oQ_\.^V[]\&\e `[Z ^W\ brk_cSi^\[8 .Y[^ \\]s^pWU{gS@-}iVC8(MiWJ[.zq\N@(}}gQ;%v`J4 }ـYC-[[}W/VWTl bV] '` ~` ] U ZFZU WFW *=Uxp^S *[!*[Y*!*Y!* V V+Bp"&*=!)VS*D%(:Z%*X* (:X* (:Vhuf2 ar|o3amB6 0@b[YZXVvproabt3{ijwf6RbZ[[^s /CY_Wp ;@vPbZXX]hp IFVV`p ;EW_[p gGZpgGVpgF[\pGXpgFY@;@1Z<4ZKDZL-@1YJ|-@ XZo_fX[lSP1jUbXXWW;@XVoWX&R"abwX]M_W\oXY&RPnbWYSjPLA~VW2WXPbWW\ P1WWLTV^ P1WV [ qPAZXr F@1V]PacYPqWq 9aWΪWVl&Dh3W CiYWl{`l~iW CiW.APl\~iiWCiX7WP@|~`ofa~i=GWkwCiW ep|zz R TXV}Q;%v`J4 oYC-ogQ;%waK5  q[F0PkU?)pړkX`6 c`@jUՊԈWlK_\$Y(Q^,$ ]i X \_U $[ƛZTYHXX(JW˫˫B (V! ""$ _l ^y( \ꈯT_ _U^ ^% = ^Sw5>ʍ5]*]% ].%i\l\$_L5 \_b5D% $\Z%w5 \ڍ5U[[?% [*.% [i !I7% ! `ZZZ= `$p%I%%* Y` $j= SI Tp% % uYWR<&?!1nXB,SS=sxbL6! E/jT>( nYlV(ZY_%` w5 UV^ ^p% _,i &A~ [aA[ ZA!4AZ%T% Y%AUYw5 X AX gAWT V AVi *SYVݵMl_@%X8 0*{ J*\: 9;*[F*Z{;+I*U;>*%X;*:XDg*I_ AX_ @jI4JpIꉢjIU\ jI\ZR Zݵ ['ՕjI[ [ZJԉZjIZ*S ZiZ I Zԉ`jI*&XꉷI!jcjԉD0\Mi Fj PjݵjoI ԉvMi%W )z$jz Ԋd?y MiV0 ZXQ;%u_I3mWA+{eO9# s]H2mWA+{eO9# pkׅ]`vW,н \ω^]5䊢䊈6Y9W$V9_ai Ή^&V~^RVΉ& ~~ ΉW~WΉY~Y ΉW~WS2ΉV8\VN΀B[V䈏l$e\Ed5[YeXWœ󠟦V[_5Έ[]J]`<J`VJV`Y*k%JY%`0TJX `W% JW%ΈPƵ~]e ~\9 ~[ J~ZEd ~5 ~UXEd~WEd~ʕVEd~_&Z)_&ZF ZٷFUp]d Z]㕡pZ\EPp Z[ p( ZZp& Zمf p0KZUX pWDeZUW pVDeZ5V l_ZYl^05T[%Z5$ 6UX9Wl$VƵ s_[Yv`J4nXB,|dK3thZM?1#seI;-ʗhU8|pufmWZVp`wWVVs`bl=amoV   h`v`gf]V^ YC Ugmr{amrblW][ool[V~ lZYhs |X[~ d  lW_XWX~VX`s~V^isXbwv (sjW7&: D(sD'D fmo`vwfuVYVVXZ2&WX(V[ udo p!div{|afY bWZ[`  _Yd1"\Vd !Y_|,o"Y]d2dXZVZ^ 1W[V\V5XV\^ dWWZd 1V[30"VXd, d# wbzZpsD 0d|lWdX^f0bo r2b^%0YV 00_{ijwf! ar|0^9| 2]Vhuf}6 H316 01];+3\<4'@"; 0#B<0E_]G_JJYJIjl~_XHIIoRIY vIVIUVH^䈧^l\eZZ7tRZX7uZVY*|~^qYDŽY\qYYUZqYX6u YUXqYVe YVeΈ]l"v Bu j jW7t i|~A]׻i݄>y\][B>y[WiX>yniWDe~k \Z߷XF3 #xhVD0 ?tbR@3& UrQ?0 qbRB0 ugX:+ gTA/ RB2" hYW\xX[o p!" XWY `EW]_a PE"" .Z[0D H0W"1\VX^ [\vg[ ! Yo3WX^W 0 쯐0hԠ` xgs^s gs]WVmfVpV\Y]\Vsu['[=ZmK[TH[xT0hYmbY!\ [ T Nf 6bXp ky qǡ[mbW[qWkmڠ Tq `!m/pWڠ^bmWpXq}h [fNeYn/nRjntdv0n n d]f ndM ndW\[m2۵+Y }硧\ \QFt&D88 g^!ZYX{WVYofv~ "gWv[s4?0Y<{?YP :? O/qB/qj@֔qE8 qЌ q։?։? ⩢DZDة qǢ ǣlZ_W[] ?mˠuV_$XV^^=^\?һ Y{Dvsrpvf g %0  3 sfofpwwxafgruojpjm`o3 LY dujmm sl~Xw D1fm`0^VҚWn X[1 "se][ q`SE8*w/ZH/IkO9 asZJ:*pyndYNA/ ~l\M;)߿ɀo^MC9(on mw{v""uw"hUp"f"am" ;(i0gg$L\\y\ mdVYbŲo"0mɐ  m. 1l{wY'xWuQXq l  r_]WX%0l""2 $ b2li[\ B2lX1 Xob)#P!WνlY*y0.($W\Y $}(R B$ ( $A( =!V_lWXb9 Y &` Y v!WY5 a -` )4!a .-`Y$V0"x!: lx0 kh` mk^h (k0F4\ Q0kZ[vll0 _o?^bgy3g30`y1X[~5:44WW|3\0801A01031:40АjbfW\]ZΒDW (H[| 7@@[^d bVfdY?]jaHMX@X\@`@dEY\2VFyMqDaH"VF`IEtA`IRWEMpEGVRCvZW\@ ]`^Qua&YXXI?]6U&YB`S]q]`v9R@AYWPY\rfu\Z [V`T DRVHYU \U \V @ixXW][`wius^\X80M`YVQ`Uf΀VАiu y`^abbUeb sfY}b JbdZQ` sedZ v Ueb됲i2ahuma` ih70wXWl #p*0 p r%Wpu4" %t6 ch_V\Pw\X__0[_ r8[^bMt \p;p&Oht8pr^ bxxApv ^\ }oaP@4(1q_N<*GߛwO_SA-[߹a}n_RE8,  wj]PC6#tcRE8+wj]PD7*`R6pW\[u Xu0 [l^>Z31^u 3Zu0VuW Zl]=Zln1Zlq]yui eYud` Ym=Yzz1Yl` Xm =X- N W SXZ EXKPWu?W =Wlw[ {Y1p{FnV?WZZaWHPߢWk[KVC HJ̦`nUVm=V=H=0 0 0` ~"p ovXX[sod|lWVdX^ o~UwudWXp/YvLYZXashGV]LZ5Y.|-kaLZ | ɰ_aMVWW !'Vf?vp4b`s=J`oVV^f !Q]X"V[ PMwb0vXs&ew  s+ _]w̉P~qdWJ=0% ~reXL?2%? }SXE4# ~qdWJ=0#}pdWJ=0 {naTG:- xk^Q8+70pYlZ^2% 111V_^XW2_Ss2^TǑ^ՠ]-U]S\Y 2[mU [Z Q ( ZFYE YI:Wl\W\|֠Vl_V!u&_-h&jXl_ZrXl^nr4 S&#@&\x'I&[[&Z_ 'Y ީ&Y] 7X &X\ *7W&f&W&rr e%_-X_S %^m$05^ 6%R5 %\m5\!$X\R 6j%[U5[%Zq !5y7F *F$%5"!kF^F% $5 Fd BXG%AXN$Dj%" $"p 5Eå@SHH@B2X@8`KTZ E+J XE E!p 5lwV` l_8[prPWV W@V]^V V\4@W[#WV[IgPUP4VZ8Eg 09fZ V0A kg9fVXgZg VWw^g[gwY9fWV1$ ? {peN7 W_us[W_ZvbVWS ssY $kXm0s T]]@sWW\W XZV 3sWV Y a|esWVrpdruf|{XpWÐmms`sfuvw`pdom02_l]P_l [`Y`a]W -@qt_U[ 4[ՠAVR4Y Ap!4"t^!֐\\Z[VYq4^sq\W ݥ\d ZFݥZ ݥX VW ݥVd tp /^D(]Aa_ _Rf _Yq4]sqU R\p\ppoS[0R"!ҵ/!$RAҵ Qtp8W `  YZ% Wr _!Ҵ\_p^3pJn^ nŒ2AnLA,nYűP n\UV nV ([q p#R`# #YU#XY#ց%[_l Ҵ[ _Q[/}<*q }\@2A)}LAYW!}զ8d XRZ@a}W Zu!12@_K3]`3\ 3 3ZgP3:I3濐 3 3@ 3_q ҴZA_q&2sq &*s] &A+\ &IV&ZZ@&7X&107X@Y&`7W@U&Vp7VA&l_'01^1R 1`1[ڠ%sk_a_w{QB%}$)vaM=(k0w_eߌvk[I:uw}}yhF5$zhY=3(׀sK6! _~YE0uviXPxgY[z X W\z Vzk XE[. [PW>A @LA 5W\Yz$kk2t .tv- ) Ig[Y}t`b P#Z[}V[Vtg gZZ~tkgVY[t$Y|"bV} R!YY`_` vb`]VWzaa_h- hu `rpG&` "`'W0|0m0v^s ]M1]!\"9$11W !\Yigw -HM0{ijwfoAv\E!Sm2R x5PB9 6B[ 8R} x5VWW}[P7WPϊ3[Ex41R$55HRFD"HRx4Z W"14KB101Y0rvYkrDh|Ed|Ea|E`|@IYX^53"Aa!U0iBsvY0OB4B10Y'lov01` ]!XYXjpw4"XVO2 U4.P_4DPO2DWk|DWh cUd cUa cU` cU\TWVWvvW<VoiWV/SU0[Q_4g0!VVX `mOj 13CX WS u{zWV[slZXR8`/pY4`hd:`cbg:`-av2b del`\sfCa`(pi0s`=asw`Z#`:cds2d ̸eCb fWb` as`aaWWgV] s`ouvs a"szlW`l/!svusgxYW WXoi~&bXa]s0 @rXuY0hpXrs]v {{YYhp; sbWZs\saml ^ys\v5 hpn#0s^`ZvuRs b`s^I5! w)-ߚ3k`V@)]|n`oA2"{{m\N2"yl_RE8+dSC4$]J<.!C2z|fVXVW]V V6 ]YVuV@/bubmjsMir/`fCJj0/C!|XVX[hf {KiY7s W7s! R  Szvg!xp\ ؞!͑tՖYVRѐՕhLGVՐ ])@WV[ [VՐj0bb AXL`@-`W[Kk`ؒd\\Vvc `ʒ X qd0 Zѐ`.xf_xf^%]%\%[%Z%Y%X[=%W^[Dѐ V ːaafuwrubivo`mm ým`uhf ڰ woo[V] $j^}RVp0g^Vu^OȒwg[.;j0wgNAp`i3 W- wfXZV?Z^jPxǗ`Vdj WqIP` dvsu`}2"wb^[Y^aqwb/]XZX@ɀPwb[{;Z[[@ YWIb XZMW\[Y@[ش`[-MkaÑ Ěї ` `gB!rw]^\X[uwPwZwpw]YZ.]YZw WXwuXufgCZp"~#0wWQ1waa2waXpvwZleirWq]grvMikʈ{:pX{!iXAvieWW5Z]vkD2.D?6Z- "]> k$w2.sy_ca wdQ>+1uh[NA4"k]YB5 ako^M<+ |^N=2% ீ|n^O?' xj_RE8+`V\fvvX[|Z3Pi a [ * Z 2Za]^1vXXp56-PlXI*\| eHe[[`g fZ g mX/[zdn%V1XZ&WXja{b@bG+1   T  "a5 "h 5A"?b_Vw , #v5! ,'`[, S!, }v oso"0N^Q"@#@$@ O- W[ߑLZWZle Y&` '| e!!5~aL 0}fmmr{ p/ 0`3 p"ufd;6huffp p0amx;6am`blp!W =1p0P0 vZW `5p30!Vln41$l70e-1V]_zp``aI6`Hl``dJ )Ka )K` )Ggo5A\K@\K@)@~1VY_ D qQ\8@2P]#W@ P 估 @ZV^[o pCWVoi ՐDai ՐA hpp qAQ+ D]235R#e5P` eQ ] V[R-V0V\\o@A\na#VU["JT[_ Wj0=T[&peQ[VoTY@@V_/w`V[PqVZx[XWĴBVC'aY .gX .gW9.dZUg`UgXUgW|@ [V AGWR`e`0`cW~`uwEdhpNgf`2p}PN2fhT`:mWZX30dsl?uW#t>,uY[TD0&q+vY"u>pWr|#t>w5u dwWou>pG a| &0 0 0 B u  dbzpf\PG6" }se=QG=% WwgZJ4*raP?/ }O>.]L;)|iVC0 DS75162AN2n^]bWg `S Zp X+\[ZD)&0CQV_`ZZ[s\t|WgbPՐaPwZg&0J`P ܛw șe`Փ QXlX(P9i9y(^VWWuLN]s{a]V%[402y0|s0]os3!]OB\Vd{`"\WF! 3ڠaY `-Z[V[^` |VVo` / \9 T WOV` Wcy SxZ \Yjr&yYNZ`jJ?WEYVb YzK\Y tɷPY@GYW[X[`ɰָWX=X(,[fWp UedW[k pbb^YJpbYV Wh nj09p [ 00Z|[0vpv MBZapa aa WWsjpa`vf! ` b}ZV^^ / Zvfuj`maWRW\]bu48bQms p 8ZVs Vf08`W5w pPpY8^ `^^V?{u>!!vvmU`?\X]p 7$d !\WZO`p \Vzd`2`[r!`P B`[G"5Vv6"`9y (![Yo|@H&#brp##&$YW `5#!g= ]_ }&]_%p Z!7^ 0#Z]k;5VrN0)y YV[fZ]Zg@w&c6WVq1 v0!0  |!p:4#$X\WX@32@9Z 0;X\VZ ^ ud;pf9Z1DK@0p!Z &2[^015_pi X*ASW\\V \\W\m\Vf` РX m0)0Yba~u|fV}`uvi xgEz_us_uaWZvuVW^ΓpYl[]]W\_u\ umwuamafY[uh[^ bx poZufmX[V*Yub[[}]Wl[VWXcYlV_rWc PurVcWYYlrU3bVXil9pTΓ`Y[\\S OuZV{RΓXXovQ tduAwgP tW^duwOΒs|_Nsxpbi[[oourxpdMswaoa[LsvpohbKۢsu6QouYJEogPVIsm`vwlf}?ZooHcOW\b0vrGEjYYW`fF!sdpXBEb]ZibwX[_wD `| a `pg l \YC s`mXVu^`B~9\V\VA9XZv@rs`\[gp?rfbhW>ۢp|'Г=ΒpsWV\:ےpobW\at1[l]w'ݽYVu&!kl%Z{X[|\^soZYu$'7Wwl#X{|WV1Wl[W"rW[l!of_VV^g f]X^`ۢod7f[W$PM!bWZ[W_ad!`|^^Zbs`~o`mV\[\ ]7YXaWupo W^V|gW!X}YFsY]Ӿ___V[#p9oWYmw^Ybp^ۢmwp_b~ΒmsY\[woo]^zPwoYZd~ "moX_ 3moWW]lvwffm PsF gpeʐobM;) t_O*r^NK& ucG4'reVH< qbSD5&rcTE6' ,A'ZWr0R&!Y YX_^qVE0#\#[#0##|Y#^_}^}p}[}Z}Y}1#Y^ X] [q YWX[@)\@)ZWA(Ym)m'YY(@)[ )W[Y)wY)XEZVXۢ~wZ]`~aXa}XYX][9~]3X]]_~W[mWXWۢ}`g XufdΒ|@|NXVs"{tzP?[ZZ\3{i[V^[S4[3m3bXV\\^ޔX;W\н0{N{XX024[_2ۢzw_XV^[hΒzm|YXz3zrWZ`YzZXX[ZSapPY?0czXYV^Xj]`xws\XZZgp9xv[栒ʐxmWV\W`{h] YVRR҃AW^A;W\AzjrI퐡FV]J}fmmr{x`]]\bpww~pW9w|QCviWVjpʐWwujƠJwtX[8pXz݉ےwse0| gbWY^;SmSmZbdΒwm smopwlaoWffW\`Skjmp3wdx@~0YVo`!wdT`][Q~Sb^_Ww`sYYZoVY[S_Xs'WWdpSk@gd~S{a}Βv{_|vxphsu`dj`m^[b{vwsvFpzpvwgf\Z WX p`wyvwZ\p mxvuY[CPV_^wvsxmWbYXooamlvےvs_o[ [ CudY^WWbM1tdWX]`bmf`usocmv[_Prf`mv^\pq cowƠp3voXZomWd]Vxlo!vmWFp b odsnsll]\fmLcl(oX`Sl ciY0ksgu^Xjc\v0l icvg_Z[`p{Wmih9vdv_~gZY}0(Y. (WY^V`orݠvd[W%Rcad~0>k`W m)@p|VI{qZ wWXYvw]mXYsp͕W[dflWXWZW吕VW_ɐ͔W_֑x͐)@>ab|mVVZdpcab|YVG^b|>pbl_Y`dh`Gph\TYVTYNVqYVWchǡYwd=b bV|y(@=v^Y0`r W&V^v[YY]bi`uwvgiu>YXidgwh 1dXku0u vZ `sqqxj]N=. yjZL=, K|obUHa. {j[K:* xl_QC4' reXK8%zjZJ:- x@~vY]~X[~Wq -W 7 $GC7C gCI7S C,r`-WVC)qsp _7s^\kqs^ZY\- |V\Yk["$qds[`u0)PW]%W^"% s s $E% E%" wmdf^@gWVX`l?! }$Woi<(`lW _f|_vpwr r "v" " $v#' f $_vrm2ʐ$)1!034 !04Vq033֒!0"_as+006|0 $$3r L6\3Gs _vp 4֑ qdvB8dY6Sm4F4Q]G2 A3$b! $?C! *BrHH b @w s4~A+1 00KBB!4~A $B~A4~@֑!!0*B0@}2G1aGs>4RGsbX[\kW aD !DVBOVX" OPBBE* 7b4yVSIYC VCyVFC7a|X[!'DQr $ad!$cWDar h wDaPw s4@a+1 DNc!4@a $mb@a4@`֑Da}2DWg1$aq>4vbgs r`!'Dar $`!!$s WDqrx 4`dv z @ s4^q+1Dls!4^q >4r4AD}2uw1$`!0mjhseWI/!ugWI<* rT6ytcRA0w^P=*zfS@.fP$VWW bvg_\\ZwXmioYX[fk\ZZ{WYXZ*=WgZoZ KQ%vY {WV*W&ZҘ㐜L[Ԗ˒WXVo/@3@˓@)V]s=}\w[ZTX ?P=o gZXZz m"۠WXz 㠜XVY7T@XW7I@ءXݢ X guWgWWs/jXqwWqV q.xWV]˓vfuzjbfo`pgdXY[ig\[|||ҽY[gZ fujfv^f P0b a ` Zoa̜`abaaa`X WVgjmwfusV`m@xwjrpyڰvb`amf mjplo`bÔw$jao7 As^]e[ r!#fs0Mӕ LPrXXZX YX`~pwjpfmfp\YXSXJX[oWV?ZwbswW[[[6`գf[Z]r ZY[X9V^Y?sbKW !f[W^o uf PfZWVz~[`oor)|mdZv|\Ved|UZ5T|p5Pzo!|VeYY$VhXOwq W[W[D`X|$$V?VMWȲ*z_>$zfo!#VZ3vsekirdTF9*3z^OA2"vk_K7$uaM:'kWD1kXD0 p]6"uW\v[u\[l\u lUVf Zu] ZlRE#:] Z] >#> 7Yu_: YuYYl ]Yl j_ Y_ -Y_#) R Y *Y *Y]XD XuX*W *lR! *j X}X)@!E)XX*X@!*X :X:1E)Wu^! GWu[;! xs4 :o!7Wlz1 ]Wl1;!#7":^ W^f"WE^2 9F@@!l:I['J[2:J[2NJ[1 l:+2$'J>2:JQ3NJe3 l:+#'J?## NJV1 lsbY [mu XP `gi][VzeS\~1עi\YZ>QnޏWW_X^X\ XP6uSX^k }pQ|QrPvRW^Zt\0YpW][ Q]h}PsUW[}P`SWY\G Q|Q`zSV[W`R[[WࠁPbZ^[srUZ^ܠflRfXWsPc(`WwrUYlRrP+wc=)|iVD1 ur^J7$دd<)|iVC n[H5pޫx{iX[^Q0[ ;:܃l=܀7\u^Yo l <^:6$5ׅ\G@ fH[o*l5\ [ /C VHZo l5i+] [舣oolৱ_H [)!=!Y Y )} =Y L 0) o < +O H [1舨1X $X7Kx00>ʿCX4HW o ڿ Dox.0VVڿ c$VA T[FALZA5n@j[}ٕ@0٩@$k ~vV=>y鋣1P>EP+5auXYXP5]^"J ^"+2 >2 ߁-1#7A! -F]@! Slf!#xz7`sj mkzj[O@4% ubTE77 yfSF3  wdP(kYG5#}jWD2 ӀeR?,ˀ_ui?xg\Yz &1W\z ' VzY[(JX(?Z] m en' ,: eYY: +',9#: 9#XX"r":r"+eXDs!',#: j&"`iWZ$,W[D2' ,7:$24;=@1V eWb66b1' "6b1:H46b1;X6Vb6 l75We5,[2V"'Gm'G'Gr"',VE%D6,PhvgZ\[ zBaY[vmp`haXVvpBXVVdfAh'`s[Voi~CZA+GZB@FYXAIXBVIW\AIWB@AAD[YWsiC$BWCSYCSP`FR^BSPpFRZw_W[BBDGQSSPVBXSYBYCyWbBP|@Y_ zBY[ZYpDak@``Xp$fXZsAhp Ahd@`hXabCqhX^W XZV cX^ Yo1`Aa`aX]`sb\V'd` e[p eX\peWW|`c`eVV}dW]V`5aW\VWVW Us`uXr !u``5aVZr !p`g}u EpXrvw_|+suZ*Z(^$L57HJŢ5onlq`P>-")}n_PA2#m\J9'n\J8ʍtdWJ:- ocMA6! nYD/]VV YZ[X X`vl`oWkfWY` kipoXff[W\l`jl_[oo WXo ;bl\f\Zebm nry@l[ofvsp[fyby5`lZY[Vb]wTZ^ ns`lY^[[YWX W YinXfyX[XP4ޔʓX:Xy^/W_oo n{@lW]t|pY\VX`[_^`ꐟ[_VŦ^_ҧƐդY^ ~[kX]`p[ƥa`lWY]\wbs ƤYV^YV]{'X\\{` 7T2 7=WX] nWWWXWYhrl?WVX\:/lW\nhn^V[[fWV\~` !ʹZYֱ]۰ WfZ][ڱ|*[X[p+Xk[]^Vam`bl+'V[0*8wu`pv `!OVTIV\TlYTIV]\0 [X]07@7^VXYhuf}Y0\VW^W^0hr]7VWXIV_JV&VjrXb`udpoZ @X{jufpms`dl\Yo|viffw \ԩ@`Бjh4aj__[\d}[Y X Z^].Y_U?LZYZ*T\VV.ZWtyVy.4pdk 2cܝk ]\?\Wbk tZZ[JZ ҂`j`mX[d`xl & fxuA+` +P' +oW" +T8 |+5`ia\V`)q}bvyZ@z_[] ^!\u^ ޗ@iYVYpJ$sdomoZE0s^I4 YwdO:%s}hS>) sUI=% whYJ;-̀tVG7'*li_XW* )V^@ZX]&$ld^Wp4X4@ 4Z\ a@ $ :ʹ` NXr:W\F $@$ijX~pSlf{dujzfuoS)dw @ d^XjjdpX$$@]4d[W0 @7& Y1"U(@"X[%^2$dCp sÖ"@ biX^"@$!$laa^VbY@ `V"~`0Vm[a"(j#(ja]\w,4[60a] I1w$^0`Yj2Y2WaX\"8! $0C1o!8X@*@^m[W`7Z1 7X1 @Zu]'`1B>+IZ]XoWfmZA[XGblYjJ`kY[zxjGWkY&AUG@ikX]J#D JbgXW-J`gW\@iVF;CL+FPWk@ UG$,'Z) [SsbfQjEXuX'" S1lR>lQVX_A@TdVQbCZ`@J@WWAE`'C WR+uiLRW1WY@c@@!jExCQRSjmdjbc%j`$@@ERp'2a1:r*pAGyPB ADdqz") QUdr^RgUg2w&c Gw;,1 g pnvdSB1 !'whXJ<*kVA,oZE0wbM8#۩|pd5%sdUF;+ (mWk b dsmW?Xz Ǘi*bmF i%pm ~mWVuV\ y9[WByZNBYYBBW[VV[q9XW u$PZ ug@W0۰ V V*V i(SmV__$]]H$[[y.+VZ .QW :WgZ. \!(f*w[absX֜[0"f}wV^VZyubZZ(lsbXnҠSRsb#~Ѣ蠺s3C .qf#Wi sD-q e&@zshX :kkXr%C dbhWa :QhBg.Wzf Q" %1S 뢌YS :S 4⵫Rz3TRI az2D` bB\ C`t2c e" 1Q bbmZ-q :bzrsRI)drzƳ` {s CbsQ Ǻ\p^] L[V1" L١o][haW\YdSX[VZVhds$oXXZ@)W^Wg oWWWu~u 7L`uI TQod-1mqfw_X [] / Z곡 X / ١6WY T<2V /V T YQWV\^!si_qoo[H5!ucQ>,ubPC5( wzikNBo vbSEѕr_L7! }hS9ˀ}oXZY0wSQoi`mWwl\xlYd]V ˠW^s  sxvi.mmzdb:,6XZ;@99oW]_Wvl\'0 pVZ NoW\t WX[NZzYVz`b zGCXWW[# !W[9(W H VY\[ \Y lVY[]o b"i0;(m}dVVZ` [` ܑi1!mvːviufdam`bl;vZnʡmu\o`dvZ[Z\W_gs`o`"oX^Zg Ummz WPjdfv{jwbiojpj`wxufdsb/r ~#h"G5`^VropB7O0O7VZK0O5Z^J1r9JO0r7m1O0m`WsbaM"`W[oSO0%^ P3%6^6i(߁\\4 ֣m\Ѡ% EX %\ 4\4}'z1[U /D[ 4[14[!$mZ_V a DZ_^\ p`_mZZY B6ZY[Vb]KT/Z4Z4Z4Bi@!Y\VswgxQP R[QU*PP߁Y[ ^ _Vh qvCTW^KP?XSWYbX\IR OX\[StZoQ bX[*IROX[[SZoQU bXZIROXZ[SQOPWoQ bXYIROX\]Qh\pPUbXXIROXX[SAhm`pP QVWS!OPd\RkoQIiS iTkoQi[c imdTkoQiVIR i$]Q5{oQ bP%iY4Y3X]^V v ICX]v uPp v[qHp%4p߃E$vrp yl_PB4& qeVG8" vi\OBW ufWF6&|iVH:* oaQ>+~@|o]K>1$$owW *>Rov_ufZwuX+lWsW iW \;Y \\' +\4 8ZJU\ZZ' +Z4|ovYuf \֐ Y*+Y' 4YvY@DUdʑsWAsIO'+Q4 8X JU\X+X'hX"\֦U\A۠IN۠W\XZflWzXɑ W"KUKgNKW\WXflzW*Ρ \VGN"flö UӶYHöYfIӶrölёs\VpV\W^BosZVsV DpWVDsWWhh:PDs5*;orڠ^Dr8@mW_Vuw@`#bҦik H"oiY iN`\<0iuGgm txdX[V ,լ0"Xlp" V]PI I Щ o`uwX\huffm{tX _`WVvm;P_\_\]`pmWmi ]\Z[ ׯYX[f \ZZ YXUZ WG[^]X`pD[^\Z`sC+ZW?6/Co[@2X]`l[W3\`-}[W@>P{@O{X zUW zVz V_0]N@nVQ[ Y_VVh=Y`wYW/@O[fXr wzЀ V w$)ZnpJsmsqvi\OC7+9vh\PE9-!w[[M?1"{sdVH9+ygTA-uÀN<)ς}jWD rdU~p]Z`mv1Z\[Xpwg Va1[^?,G]\@]d{ []UZ@jZy~YbpjYbZz~\_0 [ZWpWZWz VpU WY X WY jG!z )Y]Yp N+Y]! ѐA$Xvg)d)X] pQWz X+Qj!z +Z+ +V0WW\Y@ W[ T:Y^pA:Y^)W )Vt0)V,: - 1~n^N>, Uo^L;* y~lZ6%{jY7&|l[K;nM=, 8) Od#N_ c% !A',Z Z\x@ Z Q Y_p l(Q*s1Jb1JY]  l]x@@wbp E \^01:[A, P󁮙R(nQiX_@ |@ ^ P:! iz0 o!j(X@ [_@X[]P1[ P:Z&x@6@F PI$ F FB6! FiX W_$WZxFW_FJ^޹ˑʆS #\W\\0 5, #ж\S d505k%[t0͹a1ʲ@kH[, PQ-A-yWZt0 A Yɢs1K6QKڲ@Kڕ 9XTX™߸ Rڕ ևAJW/ @Vɢ V@@.A;x@;S ;y; ;;@Fg^\p]Zd#g}ʻY^d G ! A@^! V!%g d ^[] -gr00UX@VR V@>A]smpusߩ {l\L/ ߬iUG'\L:'xbH4msWX] [ am`blWX }fmmr+0{ijwfCrufdhuffp D!b?mf`u5/aur{q Dr?mxf| ,[`uXZ W V `s`VpN"slpjgfwjsd!sirwa' Z^hWg9(dE 9%oYXvE Z'T!' )@sXZvi% T!]9%Wrd!i%WWVT!y#r`VX` `!m V%(W $jbw^ 7,#XZ*`)p:Z @raXVVof(B}YYYma R0i2[mabW]\s  ,[b@h0H2p2 h9 x8BRh0Y3ذkI;`P:c1h0)B[Z]Ys8Xs8Ws+7\ H0h6Z[Yas@.EX7@;HW"7@@3r2;F jJd [H$ъIhl[H`P jG]^7@H\7@JI`0[GˑHS$HHhH`Q͵\F[[H@CYdCXSCXVs CWW XW $XS Xh CPmDWVW%CUZMv嘒P$-ړ WQ iW0z)hC )hXSWFYhݑYh&VmvٲU^^غJ@%ˑIiȱ i0 J5\A\^a+z +y]\Z\pw  dtS[pzW~qpz(p+yXzSW40]vts^J5 !kYC.}iT?]ׄqyJy" qZF2u}`2 k^QA+pY^WYĉt{ȅ ( Y2V` ?Y[`KGKeGKY.mNs [!tݼXB  !, 5DO^ !t5AWTKPKVTGX\VX[Z 㨵ΐ㥱߈t N!N0 8ND OׄNt{N ն뷷 "騉3>t Δ>(P&ex N, b^ MtˊwšƷ,_V 'ձH[H !05D O@eԌ{Ԋ D # *!W\[XVY`bfW\j`♤_ౖΔ'D_ D0 b^ MDtAw)WZW`K3``SK_E^ , AVē>s\wum\LA6iT<&QxdO:% lXK5 tgW*q[G4!s_E2eB2"-!_[ĖΔBAāD d- 89M ebpw|x F^\^V a dh3h070s]|Ph0\(A!["dΔ"ړ@될ā;#DO$ O$dO$-8)MDO$ebO$pwT%V̐@[YX`K[Yi 6G.z[XY8 >'29 $5WX8 > 5V^` KD[0h1ؕGDh1 ^5 t$5&H$CD D D-8YMD,bDpwCUlAZV0 3KZVirP1ZϠ9a4Y|rIR# S\BsSP#VZVPĂ#|Y>Pf VYsVJ` fX[s)fva;fq٩)f7 VWPV`UgXsg`!YwT%s.p1sjVVV.pp?pΠ"Dq .p atjħɀŕrYGȅ ^ȅ tȅ]"YxvxZ<xeR?-;qN+OUxgVE4#kU>)w`K& ~o_G/po"xmX[ZooamF:+b…˅Ԁ,J„W_̓ԀWX]̓ԋW[\̓9X̓4}w-0gfb g PX\:0vv 8|vfoY[Vh,%3V]_vfVWV[hWhĠ,auf`dviffwmrwxv {ّ^6 gs`U {Z1{wiVbEоfvbxwr0Qw`W ev i4$$ sf ywbM6  sdUG=+ 1~ocP=*Kl]J7$myfS@-q^8%n[K7# uY[=0V\[aulwgJr'0V_^#"ͰuYV[f\^Zow`J7XX[V NWVhnbZ]kZlWXXynV ^pIB_ NWVuZv ˲#sh\s *fZs )kf\'v8,  !F!  uX[d Jv`d #  u uX'W[fVn!YYU(VF(WVU'Y)X 8YY2:2 8X%X2@:2 8 f:2 f:2 6Wp5 &12 :`3%35W"%50%4[1K48q46 Y %?B HW[124`A84H[`A^4lH4J|yClG`Z]WkWJVA4AYYBHYYBHXXBZBHWVB*ZB |0r!WXd{ i ruVXXv4mTѐ xUW\0V ZkVY~xPr! NmR\{X1lS\uY WVsY U[uWPt w lfub`}n|[Vd_p^|>@>`BhB`7bYa#Be>`nh`eaB`{axmo _[̓Ԁe\˅ hZ^̓ JhYC h Ԁ(qa[pʆf,p vCq+ O{DԀxmB^;,׈f$ԋfԋfԋfԀvzx}maQD7'#zmXJ8&s^M<+a{peZPE9,yiZM>/ bSD0sbRA0^]VZZ?wXow f޲bLoW aWvV^ {4*?1Zj?Z*OX` p* ? AYVvWOXs ?V!!?w5P[VPV[Y_ ̐7`ґYV)U,aw w P vxW ̱vwd`w`arr( vo^0V5 7 @WZYsOOWs>OY[s|x?7ws@-s?yvm͒vj^_ Rwvh?[wlRۡL4ܠmXwq" i墨x iiXmWwY⠝abnubV\YanfXp x`ôf\W*n fW faX _Z`X{ pv\[V^WVv`gmv\Z^^vpg[hmdG 6aXP X6&w v[2X\ ;IZ RV@R4W^[.p M o`y)af-mҠe&wba@i\[\\ I pgrvG@ ZZ YY :":3*uvV[VfsdPP0"m[ov_X'dЫӨmmffddr7`ujZdPoRauh>@ XVYV`wSgI}Ξ#`mMurPrnQ_@yS_[j`_ZY`PXWV*YxP㒽 xT_sQ'PJXr!_  W QV I\Z :Q jYv j+ r!\sWP_ sm {yr^J6"5uaM9%~m\H7&xk_QC5' wj]NscUG8(yfP;%p ^`wgfZ^rpV,aYXpX[Z XVW_2 q f_Vp w_f[Yp` ui[Vp Z[p R͓fY?^p\Vui\d pP0u pV\["Xp^xW^Vpc \X uW[" +d^ m5@ ݒ,"05&4 xd[pQ`4 ("Zp`J P%Zp\ `%~4  YVm\ P%!\ `%X[p`Q$X,L%W]mPa$"(P([mNP([0%X" &1 9 9[ܾ nPwbO^Rw`vjV@]1X d0ޑ`vfj[hx10t56`s[q6`PP8#d0`C 0Z3Yp 6XVs 03X5lz1q5@YNHXF1"HY"HP5l[+5l0XF0 5l0x``@ _\bV($_Yb\\KG[\;IK BYbZJKG@;EVwZV~b\WY RUfP$P P>`ljw x`$Ts\Xu`P \Xw\[ao\ IVcQaOkXVfQ |ZxP $PxaP?Z[t\ 5TaPX[o\ v{d\iPYaRS\QXVTI\QYT&l*QWWUNlQQfTvlQ VUa `Q vh1e lQ \Xf^dPgW hVa vfgWSlRhVt#|Rvf\|@Uvf>WvfXUvv\gj M w[^WW]֢w[V [gpz`botWWr{ wZ\p n|zo`QC5% #+1iP8 |l]M=- _cteTE6w |m^O=, }m\K;+~m[K+ H? xsVboC]~YVbw@ gX2VZ?[bsj sOYRoC]tkKV Zk~oYT HpZ[wzX oKWQ kW[Z[&!:诖! 8oW[Y$ (YJ9 WRH(RPukis^r3s]Y k΢YpV\pV[pz \ [<[p`_dR ˠN i˥[Xg+W%KV[%1lY` q! VXZB Ҏ G  l M1jXqL2iz^izWi_^Z`$i]>#$i\ѣ HpP M 4$iZpV >0e 4 f$  4 _  \sK}{{laVK8(#3eUE6'C}kYG5Zy~X3ŭ}X2 ǀxR.q\G8-"!vxphsu`dj`m^[bXVXXVxg\YZ Y[z W\z Y W +V"?Oe`|Z] G Xqg[ +Q  j-z,-z, E--- =D0:-U=k={=-08% 0=0-v =L =v GMWM E=|J=MMM@ip6eKxaFpI(S\V^ 4VZ 4U\[sՠXV^i 4Pq{8 K{^E UF URUPPxadujmmvvfwWvsfb.0 QVR\V4}rwv[V\`ba^aTwabPqwaY?VV\s2f">`2f`PK=wUWXwz#e`^WXdtgaec\<`oae`[~a]wa`;bd fX`_ g1$ _gqdWJ;-um_RE+pcVI</" }n_E8!{_ W`VW`{_ܭ{^\V{^[Z` 5Y` P_`SfpM[V[~(V[[3wOYVjY wX[wW[wPZYaH[[s ʐOY[_]ܗ^^%]^^`]]_`G }ZX`)Y[`j]Y;CHC2)7jVj~Y{]X^ ]ꠊ[`fuXUZYUXW?\YZ3r3\ {[ZWb[Z]VY?[qxt%ZנZ Z%Y^PxZ]Y\Y%OX^\`fĥ ƶ OXk^WV ?X[y9Űx>ݠxVWhs X%W]2OW\[VK%V]]`)V]\`?\hHPHZ;VZHƥTƀ Y RK HW VWZ`|Ef{b/P\Vd iuhfsurwfbwruyp>xsfuordfPjlPuzjvrm@ bdxos`ubijofdfve'qxs`mxaf`ur^[h%Q]'h"*Vbc:@RFOUF`V jsU xsX`b g!=IoF!ed#eAT-W}-f1 sqp}|obUE5%xW9+)3wiVH;- saVHg kVA,~qeTC2!{jYH7& _[W w>VokldklVa `wV_W^vr`;a$Z:$].6H@W\.%qtty`bAfy  ^``_qwVZYZVud?``gDXAa`Xr g%!p2Vg`p4@g1* A VVW_~X[BP W3d!Y k v}v^`glm]Vl{#`0Vgl|^[l5`}W]LH| V][Zbu|[Vo'Y$ 4$V&(%-%X'% 1% %W 0]$%61[$C9%T.9% .9X$ .7'9% 95 P|YVhdXw0dp 1dZ01W[1 4WE[0 4@0 F`pF`0$610P|@15V1 0 |V]_Z oFYyA~GXyA~F^\yAGxBGBGB GVyA~E\@vmsRCBd@L1A@1VB 4VA 4/P0 0(p P[V au`vvSW1 (UW0 5UW1 3{{XXu_Nm] TJV[ )R[-UY[UxДIVY W DW2jTW{jwbiufdsxviw`lf ~*eam`bl5fauf`l D`O`kV[@`[[T`ZVViRuc`ucJ_Q_RRcXbf(1fVbeX"fjscvcvcRꂗ$eOve/@3BuZvvHvvavvV[ ^;]O\Ww[bZ fd~ߨl_O?3&3w]C)][OC)|l\L<,qW=" iN3}߼|l\L<, puf wXY^vu!YփWW/p_>Ձdbu א XY]W 7ՀYVvY]XWZ)s%9j5)X"ZR5 iD iW"I5Dr5XY`V ˕XYVؐふ^f?``hჵ[a ^ouzVsR` < vgp`w `+ }fmmr{ [2`sZpw5lVt,oZhuffpf s#amxffsa mkc!R`) o -=um+Ib_vj+Uwjw VAW]؄)ӳZ[Ӱ s  в!fݵ!psfi/æp9af Iɦp $I4iɦp9őfɦp4țƦpű\opW[\YVWoI[_…h0+dE ZZd OS"WX]d<XWEXO@V Dk+Q *X#  ֱ W{zJ@V[xgupmZ"ҍX[*#JW"JB$Jбݴ^YY W W^aKQ`\i |X[oo"u[X\V7V^Is`v [Vvvm[+ m]ds\Up VEv+#! [l YU _7sl!}',l!ɭ l! ۣ# *%!}^ 5@, 6-:8^[VfHq46%7Ű[VVa[^gQ"o~Z{Bh @Z^[Vsa@X_a!@Z]P\/G[W\@[oVY[(Z2 W[]!Rp28s$Zkk@'W[S ZVd kڑ8Au|ї@V1їS 􅜠XwW^Xrp nt_@{^_ ^]@yYW V{]P/^`kfZ]\lVkUl3glfd\S^[_uyd\ Z]t YYoa ػRpyVWuVq .šybb fbKYYK/rKAb faz‡ƍšyaWE[.‡̦bǽy`W\^Zf`âbJ:BYY:t/֍HU%҇f~kbf`bm 2`aVWw `[oϐegZohYo (Л_ls}_`v[XZi!1WvC)1s[d%[+ g 1@vwX Uh@Us sDp pҸ W\" 'ZH'f] mr"Xs]_Q]- usyQxgVE4#y3WJ=*Cxl`TH<0$ ym_SG;,! }m]M=- seQ=)tdTD4(z@b^ (irb]_) W<b]\\Vbs` #WX\bsm[2V]<Ab;A * U\ \ \b[s?f`wOK`} [*[HVV`d0PAePb[[us0Xf~a z@ ^ZzpZ (X] 'b %*(!%AYZ]`{WZ@P`vkm3PA@f!W` T@&X&m$0`bsfAЉ BbZZ $Z^YV["b@## * &1P  : 9T@*:X*:j%ZX_,Aa0^r,j7K`j7.;`j7X,j7EW,:P"uY6W 5mX_Y X_G6W ! @bXY0f4XVY5F14FPvw%bWV@&T[D mW0@F@FWmiBTByZ@DowZ@AV[ab~o:PBZBF`*A 4V0@ms FW ma?vreP<_PVgdU%@5Vd5Vb5Va 5V` 5P$asX^vZXp 0tTmX}P 0~asW^v`VYVp 0怗RR 0a`^XVo0aaT y WZUXUV]NU\ `Vw2bfy `vpR0`XVU\^LcLbg fgR8bAUgRwjwjg.'\Z^S\:kV bggR8r gczgSΰ ezv{V mrg'zS8rewc wS!xQ paUI<.w'+1zm^QE9.!{jY_7&u}k]JtcUF7(wk_SG<*]sUC#ST24Cd][`)\VAo0@ ~'@`!YVtIb`q7GA+@` W aA~w^QFQb{Y[zh X Z:hXWr9hիW^W\x"{WWzY]Va+b 8Љmam- W[ Ы V V}vf tYx" !s~Ӳbs^}-AbsPb?sWXz>As~g &AU>$sYoU>bsWBr 2}k 2̔~ 2s)> p0AMPG0jo0o0AoYWV[p1woW]p _bm buPRm d0 mb0 mAPOP1] a0 m`u J__ B1_ZV0ds+dWYa211 ^%shxiWH6$}?]J8(ߝ}eZI9*xeUB/ _ lY6$n[I6$ueS0 S3v[V\\Ma <~ YE\0@W\"0[&+ |  %[( \$ n"Z^} !=@Z\Y#)\Y}6* 0nP6)|#)Z8)YW[** m)\ ){D*<# & m)")#)F:<9n0W+x 0< 9)06\9{ 9^9 00 z*1 @ 9yH)I I\I{/I" 3/@FI/@6n @$v7YgWR@.7c@FZ%Vv!wldob\Vd̠p^dfwb$ddW]ZXw|rc\ZW^] @.Q DbZ[_+ NR)WPJV\`OQRWVY\F.$1Q P JSPY PV)Y\Y$YYnY" UW^Qb ZiMZi\@Zi$aMjhf=Y f gS&`cWQR`30P|Uw]|x\p$2U=q35x"MP8u\x4p> 5x$x͓ xy#v|u{k[J7% ;+3kYG;,r_L0 wk_SC4% }oaSE) seWH9* yl_RE8+Vvm7jmXY%jmW__ ^ ] \ [ Z{Y XWcfg^^=!t]WW] \YМmXX~X[bpwȜɐXV\ۙdۖWd ەgXY LS0  ېvbXB DdD[\DZBnD!DuXdzdEWЦިdާWdХWX\p #uW $o $WdVNwoNdРUa˕`֑xVu^ԓР@~oW\u\ԑԑmμWV&Pj`\,ݒ`YXo\V2@=Y[~ Wo[V2F C’LLťdƮi}ujvwruv ivg uiv]ibP@bi9hua`wB$`x@)is]bTőioY\Wavh]Vh&Ph_WXBifv`xuxvZuo`msujpwfuur?mmv=#wv&m ?m`uhfLNifsmxh+d| XOZc RWx[iYDБ 0{gbX^_\b V^Z]?)=g=`CgX ҄w`qVZ^ [Mfv}u3fBZZT76W_[GXjx`.ojp'arrwmfs[upa{ow^^S<Wb#tZ^ZWX^^bP fmfsirpfmj*fu q6iT\>3 WV$f`[ p&Sf`Y]W^dsH]T &P7`Vw pW &P:pu HVWbW V hVZ!Wt&P(W̠1&P&P zT#@ s]spnaOB5#!zm_`SE;+?Бwj]PC6)wi[M?1#yfQ<'jU@+nYD/`b]V`@l`Z]VoWb@mA`~XuXoXffonXXoWfkY[zFbkYXy O`kX]%pW'~ 19WzgXW-FKkh )Wb* ,pV<i !*-)WzFk FlYRW*W*b9 _"`hX"'lZ 1" ")+W'* *f),:' f½10D4h'L#FVWH1"11FпlX Bv2@05@@3vo@0@9P3@@vssYXb E13PG HP0F,H/,H<,HwX,HW,HV@ޑsm]u_PEm]]JG\a˞GvPHBIg`@sEZ_F^; F] @sZ1 W3P VA#W|P0 UY\b=W<.=V[bWW $=VP=V`=V0!W~ EH>UW@Wg`PSW{VVbW`P2YV[[ VV UX_b g`UX_`UW\X@g4@f@fgg\gg[ggXggggVAeY]gmg[gXgW gV{ fX] w/\ ` wCxwJ`wW`!wеf[w``[w`[wdmYYV\,pvYVrXx~xxL"_mXC.q\G2Wu`}Kq! gydO:Wh>䭀o`QA1"r`P>0"p7) 7m}vW[o}P2m|[߀ Ao%gFp4f~L Ԃ|[bWsWf J11fSR5a6=NWfMXUX +X5 =\MXW iMWuF Tϙi oW3Z WV߀ @0! WV> V05=0bGfM_WoviS{[oIazYYClv` sZu]<dWWzxiPelYXh`lX[ ghXr kX\hWP@bhWY+% + !c 7# L!bds``<+YuYEYgO(} Y5y J_z<'ʌ'Ǟz L#vD9c:y+ǹHsʀ3"#"ǯvWV0`mY& +_!a#%ڡ! #"ŒDy 0TW ]3L!3`K0k1F fm""A z"U5JRj 0b# %$U 杲#9!Hȳ 40su   seWI;-}o_O@1 ~m^P?. o__?0!~n^N=,~m[I:%yj[L=.uo?Mp @bX]mXbs ?d _bp]Z&N9d  WWd W uwd \[X& XV W[ZWjp bWZV$Vayu0@lvuXZVzu`P5ma!{@ ! ]^Yblb ԁ]_^VWX1!6(KV[1! r]@[& @[ak 9"s `b1s1k( *T{'X# k'! *d {%[Vm^S ms k "rm]@ ۲q\VYuXq[[]Z1Y6Y#3?Z_{{VA=5VF1k=4sU2Z_]`k Z-_Ck 1?1^\4ZS0>2\D3 [5E\T3k03d3 k0}2@~z5@sCk n2@ 8Wd7`0IWdk$YC4[4T3@U24Yc4 LE4CW` 7ҟZYs1kdy1Z]sXZSXzW|NVWg]p1d8U0WX\oY ~XZ^balYXg]So]@߳%[۰%ڱ߰ oYA&l3xz[YVxaimZwvW`\ms[XWMZtPzl \"fXƠjd{jpf]>a@\DT[b$rZ_jY_%Y QB` Y]~QYX]oPMr[rmC)@$sZ  }c6'%vf=F:/% Q_U=%k{s[C+净pX@(s^4 iYM?/r]oH3 9 tXmX[zdb%5XZ WX  svuA!sks Msj^VWp 'iP8wnT;lT9q>$ p<SpujW`>t =@CR̈́bڃAŸ́[qۂှʇru`phẍ́hup `ڃ ဢ 1ۂኑsۂFrۂ^rۂVӊVBzj/rmfwڃې%Vۚې.EV7F1U ېDŗk ېD Y &V ԉDrBېmp8 YDUۖk(RA[ҋA)"7ܥQ f ˘ٶېpujb`udPZxAuiv W[YV`wuhX_Z XVW WWw &u`}VVw 3vjovwru'P`bir5r ^@pfudfwfau`Z -Y6`u`WXxpCWK#aGi 6=?u\[ZZ^>S~X;WDZVXXZVz ew`\uXYYZ[WeW\Z['V/ui _ sba7hC Y ZggRx XX"?"4W>"W"obu ܸY XW ^ZXW\W4][Vo`-]V`+.Z', f0Y[`,Q0`,Ѐ`tX{v`ݙ! [`ޘsgphP5oV<# xk^QD7( kxkZI?."j\N@4!ƓsfUD:." ~fXJ<.d$A,awvb_]Vyvb\V]~sD.[V\ /ova[^Ү!W)Y$7W!vaXX0|W_ooo|W[t.YZ[`XkWX}YY|\cY=`ޭ u_V[Xjp _`d]s)a4qv^ZV[^Y`kX`\%_ avdbv\^XYVb`4#>@=!\X]$`\%W_`&(` [[\bp }#[  &Yz %[Ӵ%Y_YZ'Y_ .Y]X  6pvYy[ Xosqrg[<$(YV[ \"VXY`b{#40` ;7Wv ;0y@vY^[bYgupm'wB]3ad5ŀJY4]a89y6m6[]b79y6vY0x@` X^\ 5](0XX[ 4!XW|?h)"Xo w3"W_$Di,@9B^$DgW A0W[Z&` fFS0 ;0[B[Y`4WZ* EX#`C_kVYXj VY0F(PvVWY`` FgFXAYX@`$8q4VV_@1Vz_1VZ`1V@ 0`u3@3uwW#`buPP,ʃ\F DQ P.Q8 P䃜Qk! PIR [!Pʃ8ӊV2a"V2aV2a8CjkVbk)fPӊaa+Da8V+sUj"k F^r U{ FVPr8)frxPkwj]C6( #yj[NB5(-q[;wS3kL* ti_TI>3(pcRA1% t_5s|s "2XWXW= WW  |XD$ .$!$]W[X W ZW  @C{jp`|i^WV\j#{ffU@t{` xlar{ab2{WWX_u"2zmX{ |,z_]s!0\ \\c,[6[^)!z[ LZw\VVL*vcP=WmO6#veZOD(t`L8 zodF4"yl^PB/! a[]XYZvY x`]Z^bsp] W p YY* X8I sbOV gېx`XTYWa fx_zmx]VlVYf___b `VWfVZX ܀x\]~YWw|[@X_Ǖi\ZwZY]|w?ژV\XPX` x[_Virrds aWW_; pvbx[7RY\\ 7Y[uz AxZa 0wZ^\\Z^Y!p򀔡z+magxuZW_`jt|V<ڣ]ܡ[z[Vi~sl~o ZV|V_ ^%sV\.%oWV%%f\[fVWV %aZ]fVVW  XY %QWT źW ٻ VZ ۡV 頔mY]pb3?\^ 3›أY[VuXZz XaagYxd 1xXW]WaVV^a`gYi`}dWdXiJ] ]~Ͱz] x_0s`m"1=1oxW\Vmg=rFQ?YXV=\Y[ZVMiQW!!z}WCw\ZЈiҲ ˠ]W^FW^sX'VXZgxKmmJQW¢0~=W]P~M0.P~a Wa|Z~V\Va`WWVwY`lWV0~[VVfuW\ְV[wuY +I gAq gua$._ l.I . .d  q Nsw'!uj]E:/$xi[L>/!|lZI8)} gkh[NA4' {sg[PE:/ ѝpqeZNB6*ؿmK'܁ߑ\>ȑxm]W^`{hW\ YV{ijwfo &(ufM3 8'aur{p18^nmx0\Z`bl1Z]X\"] YZ =lvvDZ ֋lv W\3 q na!X #&p#&V# XV UaxlWV[phht[Wg `"pY[VYxm&g x|'X m h^/dw%b%awٛ$`w hZd%b%a%`$Xd %b %`( $Wd 5b5a5`$V\dH6bH6a#H60 b qjdh0rppfbw0Axg[ZD` 4]7\ؠ6Z7Y7X7`7V ܹ40] 7\ 7[ 7Z77p70g _xfum}͑Axfrswro@fAasWo@f^XufYWo`pDYW(G7`x *`!d5` 0ˠdpX_^Xm{0BA0THD0GWh0F[^[`٢dbWbbYu s+Tmb6Pd6`[\db0%Pˠbp^[s YU[^ZW@%Pa oS yWUY0 yWXD0 iWWV`g yWV XD0XV`yTbY_WX0r%PPV\@WYpU^[ZGpyTa@fZ[pfZ[2@+g`:f&aV`.d `V`kb`porwVg}` egP sgX~c Vg` efXr5` V`\bY\ `ee\aVe[X&aV`b\=b[ufpuu paW[ uW+ 2uV;p uD tpg`sVc/`_\YV`ˠVvq]`w\qt]^W[blWbwXqvV^qȣqr]\ 6sO. ~A9hE!ypq,a=jEߓpLp}GnYD;W[lH%{l]M=.tfO3%mZD/ ucQA3  pxvY][axuvV^YusX[VhKÂ[[Z]us[VЀ քX^̄VZZ̄ W̄ xswVYba $d^]Z_id 2]^sVWZb{?[sVV^bxPXX[hVWbVP fWVb P1]WV^Zb PĀ[_bWV [[b WzWbPVWW\b^VVXbP2ZYX[\ab~]VmP ^[mZVVb]VGWZ\ZF[&m#dZVibmX]bXVVWdW^X{V\jt$@"o]`o\[VX` m ̡X\ZaW- m̡WWZ Ȥ~Yvz f0ow[VdwzY u[ wu`af`o'pvojwwfu}$v}vwf9<#mvZVVdmvdmvVWmampX^XY` m1VZm{`pm+YYmW`V\^a[aڞZaV:*dǵ= JYm *ձ hd YɈ*%XJҠJVb[ Ri rbw!= t=c"F5ěi:B:Xj=b%=`BK# sVZwv s/VXZZ$5U" *uA 4*4'Bb T*4' t*V )s')s٠wh\p U(s T&p '0'"'2 "W^]vpzdOfx 96sC4&A&Q^7bpo7r0^7po70 D=02 6 7p70 Ā2j0D0GV2 @#whXZsh]1@dbh_`0A`b\!0@X4@8FXBAGFXQ@ UFV4@8FVVBAHEVQ@ UEW^4@U@;BW^BBAEpՐF\4@8EW\BAF\Q@ F3AFAB$FPA F^AFlBIF{A FAFB FAU@25WT$WW"5,$ B< ]vD2 DEQsSVAVQgbgr$gg ;B# kfhg wg Ab@1 @fa@wXuX b`W[hv!eWesee``bp` epee(ptWEg` dFpddVSq?uf`Luefe^up?uEd`Luc^u杠`#vbmfW0_vbWVvq p츁Fd} }thVJ>2# W159VB.qcTa+wwbM8#ޓrH3v^F/~fN6zXYV^X`WXVw[`Zp3Y]g]`ZV`y [ #\WW =3W SYLk[]a\W{ZXz`C>c$ڜϔy[Zd7VgZXFh#TY\cE{`$[sY#ړZVFZݪUE򠆓`   Ychtϔ)3X饁kB˽WWE\ĹUaW3 : O̥S ZZD y̿aWWV ^X~`YW Vo_`Za 〷 פW^Ԑom\wXYwWVxV^V[ #m W{^VVqFP ][V`P[\?Wb[6VAsU[w|Yw|EXw||NI^nXm`[`ҾXVa`sXiZ#6; \aYVspSY ov`kXviWX hXIU@PpW\V}VI,D?W[p^ \ZX \ P VhSٰX[Mf+AoVx XV_3 x}axwwbrppfbwruxz\Y\3 KZo _ } u }u]E-+nW@)s_K<-{fQA1vk`SF<0$iQ9]p yaI1}ncZraYXV I$РaYX` Vb?_\^ G8,V6Z^@^V f\ZN~ / Z a~'Y-Xp&-6"V>+.0#HW-# n-"PV-N$+# aZXpZ" ^" P"`Z Y?v}u 0W 01 ,0Y_91`0Y_]O3Z O3>c5pc5pc4^܏5\c4]_{X4\Zc4y\Ipc4[]c0>SYY~`] @407hpYYr2o`W hB pa# ^$BІYE[ DC#YG;DZW?[z R>X]~`(Ĝ@xpaX][s!`ҵ@#Dg` C H HIp#B RWiAVYp)PX\D>TAKX[1S)PA[`"AD! DS|PDRXcXgXTDZ0VڒW<]EYWRD]kWJib#cGDk;b'K/kzesmgX bJ̑Wprgc"am{a#da6{@}̑!2} J}t wV{WX=X|bZwCrpAoP^dr TP]epX@(hP8$3W]]PC3# ouq_;) yl_RE8+s_K7#o[G3 pA2zx1V?9R׃V[d߁V[zѡZ]HU ]XaT!4p X\XH4 mbV3ԝ^q4%i 0I$D8W L`t$8 W` А ĭ3ح?40`А}51`[`423<Q'%& LW )3kfWPuX\ 2%XW`f30ijC^_movr42^ |F]_Vpv?VVuD ẖX :h:;@tYp ph p̨@,0]Q] ^u2i/ I51\dz(SP 3\ )a\\pc0a[e^"պA>@ [\ 6v03[SYX[WT[# hC[BZJCPRCdys` ٳyҺAu0Z@] 0ZYVo`]@ٰ0ZXv CZqd _~!2G=5JVwmX`P@3U3Ub!"(-.$EF]^ ~/pW ~psktiUH;.! {m`M:'pERF:.Q{l]O7,sraP?. p\N<*kXH4%.!60m`afm 9m_YZjdWXzo}d@paRX0vu 'Ԁ'h" !QD@HdXQ60lW] !j{WV_0"P7juޱzvaamv,ajd`o 1jbfZafpbiSL$YT% ^{`dsub/s"\)p|"&XdsgbvO Q%{# $z$ % p}!E &V$%% $iZ `|" %W[{#I%%6$$${#=55=5`|"_6$_6$ X+s`taj3g_bvm sb0"67!7&bjf367;t0hHztaguf1Y[W`}X[P /BgbYXls Qgb``hJD+ZVVtfg`yAgYYPfy@P9fİd`wܐAϑJñbuZpJ@BXpJ@bo_W=Bbo^_Y[ MCWW[XNqQbl^XZVz[ b\^$PVdFZ`;cCa bβ-Pp@-P GbpVW^kY_V PMSV\YVd\P ]XX\d[ ]XW^dcAYZdQ$ZR]X PAB@MQT]T.V[bZނ5YY~aU@"܄P*f cPaobao իraj9fkcXWY23aъ`WY[^ [VapbkwX[ad|Z`cV_ XZ`pa] #[c`WV` 2`u`gm`of?jhpjwr`ta}2quwhwr1^"pVz0Wb[ 6mGVpZqgj|jphvbuf{v VpԁX\VlpG@}r؁{TxTzRySzRpv uh[M?1#x\K</!w`I5!yj[L=.zk\M>/ ƿyk]OA3% re[NA' !@w_wW_AVАptB'.W.jwe`1wV,.YZ`W[_W\lyW/l@r$@@vxZ{`BvxY{=X{[vwQ tBv'cvvw <"vv_Z[_=Bvv^XlPC AZ@XPYXX_CPZX`XXXXX^@vg Wrv$@ґqmBWvWdj Gu]___^^08uY]^oʰe\o^[o\}Zo] Yo_ +Y +YoX' XX XXWoW w[XO[oE KX[ззз&з5$ "dѶb*t*ǏH[H'X HE @u`[bt;Wk޾BtXVufd am`bl `vvruwfdbrmrxuv tqksaibŽ`P@$sZ b`a /X\zd08^""Л[`6Z]8ө6/"XI7|/9X>ۑMԪ/,А@sWb C𯰥@P^o0`̰rvf` prpát /-ߠrh\WVhuf}rhY\qxXYqx$rhW\XXqXW^qVWZqx> p^^`gdp\\Cp30XmXZWVmsmV W o9,RPo J@p sPIo Hg5NbNlo HlfT\ Coxh`lXP h`n|[s`5YX$surdUF+)zj`PA2# vj^RF:." oucQA5% q`O=, q`=+׀p_<*w}]_\ {XWXPu?[hs YYjVXug<Z*LXL ?5LlFiWIhql]LX]J;Z#Z ;wtpWu^&LWuf='hI^ qW5^'lG"- WlX" (h (WPr$ '^W^ R<'[#'[ <'w'"$ <'5$M'Vu%3 Vu\G"^&VW#^ s5ZF8YY@8!8h 8" ^ VWfw5d0 {W__|N`)p @` @g[@0W^`3B]Xdjsc@4DQ r>KZ7PL] D]W7A`tJ]x@ zDX]K[JWmP"DY[ CAE`'2@GPDEE%)C.Q\$QZr@UW@CW\\`@4T AATrTbP[RWw {hRp@{WVh$BV]'9P Vm`gYfZ`хP CVVf\3H`d0Q@w0AV`g`_`g^i]h]_ _QV^h P PTP@a\E` P MdW\WdZE` Pv`p ^RObZXcXE` QTMdXcWE` PMdW`0V+V[E`P@aTe@Pِ`~}XV d p u`ow ! zHiX xpР|[m`YSta8pY[1Vbu\MXUχlځ>χPۀrۀߌ,ۀۀ Y#٠ߌۀۀ ۀ#yߌD?ۀQۀ Lۀߌ ہ a21V`-}AπV^V[h /٠@.l̃P0h0&᳠#P0"ۢ@!H0K"h0˫[\ۡh  $a!K062QaWbɰp!ܳwh_!0˫Y_Zۡ Y_Bbo6YHaY !Xza5#U˫X X0Iw8Ţ 6QtaR߰ݝ!MWoȱwWEWp!Wۡ70 ˫WE 00ơˠۡ"pt6큇a6$7Ţ uڢ I"  q@a0!36lboW 4b\_bW\tp8sS_xbL7! %+qZD.zcLK QoYB+waK6  lV@v`J4sbo-#\ߋ\ 1  #b$W7-ߋۀ IJ5 ڲK!c y)#$a7Zqہ,6`Kߋ2Qۀy WbX[ E,2C,HY,^p,u #YMo'"+07p4x <ߋb - ,\ N3bVzt`vhtzW\ 6[?YY\ }VXZ\ {swZ ;"Y +swXYVamlKsq\]Ww+W( Vv+ưsY:ϱsXXW{`βKuIpTa`[$  ruu`b`df^oo"odY }`~0o`ab _"mdh dXh!bmhmb`) а?W) !`FyV[``I^ Ypo;o)mW_m`afm`\ ` _iP;{lVZbsfkrl |մXXޱb赈)lV]Z [Vo WZ !ZW !%k{\Va ~kPm }kVV[!w`xg\Yz^pY[zW\z]Vz(tV* x ZYYy TҏX " y_Rjܢ V- XXy ۏ٢Ӷ y>ܢ T.wWyWa ~~ƁPy$> C; 0%iovh\ZgYg[\ ib[i\wZXV +HibVW䠣^ztRsp rg\PD8,  3s_QF1CK~lXS.~jUA-q]J9&~rZ6Ӏ~paSD6' ? V|X[ G|XZbZZvw s  W\v^ W\sV^V^s1Z@1X@Xs}1W`vwsXbW{ާVs XV[b``^|XV]` W`( X^[Ð H|_W^]  [|W XamKsl V]."|WX ^&"V` /$WWW[` a@ Z` ;%YG%X`G%;%7 /$V_`G$V^`3%$O I %s % G vVZg~ߐXop#t bfmmsmxv}p4o`kr^0P{ufdY1+4"70}۳ob_gVl}oag^5k3Hܐ(}1zVX_ nwxvj9 i:>D;>hղ2a0D909>LB013G"F_>6I6 K>K@6Fӏ$FLBF7"+ 0ZGb!0{P0u6Ik[ k[+FF \+D\BF$yQ0$Z+0V90#www{ 2u  ws`bd^lflfl`%wg'}cV_[`~ca[V}FwXWXZ} hw8`>X-ǞcW_g `Aa;WV9ccvxY1)avw`qpZ\pY%vX&uW+vsWvmWvj)\ ܐZepWb``v^?Z\Yp`[DtzXX\ r+\ Y)[ Z N ~sbQ@/vj^RC:." znbVJ>2&ag}oaSE7) xjXF4' wj\OA5&xiRF:."X|pa1 r|pnq(JX'r o_x{oW21!70\C3 70m^xvvVysС|m][+Lm]VmZ[7_YV_tC3 ’xfvD᫒hucffmW12G{C3l} 0r{70l21 70l* vlڒ .C3 viwL@*|ۡ\\]^dOWXdopdCZY` pz pfpmq WW faju_fa5 Wa|fۢN$"d`vobukZ[{:d Oax`soYiX_ '5 X*. 3W. 3`mkW^^.X]Z WaeaXWY{ Wb`XW`e㐕V\vsfbVYc/Z訴`e%GX_Yvֲ޵WW츣ڰ sǰYWY{s3X< t@:` XZW< ^x7#[f!S#[r!/#[~! [Vo|Y Z+/%[!ĺ!g ! !/#Y?]WiŘ ],a|Y\ S#Y\Yi\Vi[^i+`->[]i+}C\w ao gi+\[[wg[oi+O Zw{gZoH0P+[ y[|XwgXoixWwgWo?i!YeY`p|GVopVd`X +AyWf5W` !YV-ppX_Vu`phfv'2X^_ib\Zs \X[\ ^E# Edz >H0> y0d#]W\b[zk#[\Z KXz s^o^PA2#}7WE2 WxiZK<-omXC0~^?  zlaVI=1%݀ugYMA2&1}`?g X|f ZWY X21{W_}`^Voor HbP T[N bdP Tpo`~bT}_` z ZW1}\`!}_7Xg+a G!_X`_\pUড]XpZ_p{^pX"p&W_iY<4a}IE"[_N IW\vboY^"ib[pE!W\YJN#W/Y#\+E!V q!vp$Y %wX %W $V^ ,!VV\`WY^ɋ# "Z %X } } fd#Rsgb`s*PVz`b M2v(1KA;,009<K9$Q<K9Q<,0~bV_{0|}\V>*Po^⑿1$1 01Z3iC 402 0H1[`4Y74$@70GE 4X70z`A4A\ p2a@OGmDP80{`W\Z0h{]Xmo` lޯBx~b^`D@FXZ@xokoV\_VYW_d3 k2wxko90YW^PPYwuplx WsN)VVZ`8WYCP8WW`qVYsްws '.vwbJqQP0vj;o`XYVTPmvPYvX[XZz qSYVzf &U PTWP>QXZf PPVfPvWpW^s`YZ_SaXbdc Pd)cfVcvDmb2fMdeoS |fW^T PaPgfPuw1У_bްe^`ްu`\^Wbs ZVd^VY^`bKްYu` ޳uX d d q` vV]` w-uW[`ްhu[[Xbk]KwZ[V`޳szsW Y"|sum |ɱ'pvFTZuX9qYwuW wY%z_w vk`RD6&)~rc=K9'YyhPC6(g us_K8(׸lZH6$vj^PA2"ߙiZK<. gbd] ~W[m,[X Zh?{Xa7 %)t38WWa)X #œ[jO![ZmVmZq] VX|Q pWJ  0 YV^]0WV^\1ٕ,VZZVXbŠ}Yvi~tdWX!^p !0Q}p ԡ3 0~W~ hP[]IW`W@Ww~ߐ^WM`vb )P~[Y_\V\z " )ǫ)P 81Z% JWEY00Z)P[df<}pd`)PYVV\ ͒ΟZVX nVWᐎWi{]^a]X)h{Et)~ lЪ) dvfp69C "x^Y[bof cW}wgu  sX'.I { F wwPFTFw'wXWFv_WXjp7"vX ss >}ugs{QpT`T uT9 uZV{ #u T}sYvmffzjphwrrm@Bsurphv0I[ ҇Z tYjptmmR}֋t ip[Vu@]dZVddX[upu`aaX[{N`f`>>(.VDPDQ`FS`' _ Fz F'bu )ðpsb x j bosan] QZ Yr oml 9*Z1@ TF bwb'.PXXWjw@ (.3 :v Y z).s8 tfXJ</!wqCUGI+Yui]QE9-! ymaUI=1% wxw`T<0 |pdXL@4(th\PD8AZiYX]S"͒X] р31\~ bLX\Z/^BJZaG\aIZq`tp°W fbT!a ^5 .b \^VJEv[^ Ev ҏ ow Y_]v QEvw[WxwA"= |pdL@4(th\PD8, xl`TH:,ui]QE9-! ocWK?3'{m_QC5'xl`UI=s\[b[Wf#`Y]V^u 2]V \u `d<@2 R Y e e e@͒kX@[]V vl20W CÒW}up@C} MZVYu|@RXu@g~Y[\Xi#b"[" "W ^rR`Z  ipvYY) ^ X^P PP]PPP`[ 𰨥%0-@8w]8\80[wugou@z8x888 8 8[_ ^ 8q Pǵ<Ҷ`UWjP WvP ] \qЩ&&ƪ0&1`&VI &Ƞ bn0 cf K@20 00%0^EYP!c P0 bY`& p[s `vbYk q\V^zÁPPhMtM^pM"%0 q֛4^>a նð]]^i֟@$#`ֈp  #0Y   ) yb0yn0yz0y0#z0@@#`pA %PMe [.I@ P1^U0չ!Q] QZ6ԝ0u u u u]_ $]_)$^pjPȠ1j&st}n[H5"-EnKN@2$Y_asaN;(wʏh[NA4'qǀUG9+׀tfUE%ueE5%baXa;}X2'Y)aڰ 2P2P2 P2PU0PP`"iN*^)q 0̐{^ZY[>H!9T'0a(0a'ڰ.W F#V(">@ a %z@ (9 (Y"pzЋ $.a $P&P V#zea&z܅8Z 8Y a&vO B7ڰ\ m_ZE&m>&mX-%lW &0Z# 9`&kא7X&hM07YC7V"#fa!&0Pp&dRG$^&b .GXp%`o@0KDUGSPIFJoGVo@~V@ _M^shpq^dfor @@\fZVWXzvb Is@ @ B}^A FYE Klovf FXWD FV^@v@([AFV#pA(W\3T(WZV^6Qs[A(WY~T[AEbbsVV~fo*Y`PU_WW\A@^\Y [hIhRhXah`A[b^ACPcA<[`AZ|_V~PA[dZbZXV\Csf@gxa fb [``XVS`afXd meȾ`Q` fpVg`fbfVJ@Vaycmd]V]V\B6zBHp ^ X^sjp ]sWrdr jp ]m[ \"]mZTviuY u'v uQv[Іp-WVu{6zz }rcTG8) 3{ocYOE9+GqhXI9* ߶sfZL>0#ǑreXH*Ӏ ݀߰sdF7( paP/"Wv[VVul~{wZ !aw`@vopPBvjprp`YZ_d kfˑvdѐBwkrC^* uwѐb)*uwV7[Vhh^tRh|oZv|Zg|X[h |g\VWVa"V[aȐoa} ԋޑ` |`_γ `ȔYV`p&XUWB\U$\3\<QLBo`XE[ =WKh j[Z[hcH0ɓ/]^mW&|V^pP\]PנaPYYPt| upgEP|szАZa$sz`Ya$ psA %p`XYZfwRp`WZ[_bsZ[^a`᰺Z_f ڶ^f X_f^ ^ X^d ]\[εWZ~V_bfε00WVo\sl~D!o~ZslX oYZPeV@ooYcpZ X[VX[ Ғ@o0hPW\p&f`&m^ YPk~l{orp[Vm AX[E luWW^k`01V^ Ў fw vdapjpftXh 7tXXerGBн.f p Ќ@f_ Bf<10WgVnL dXp1O(^W ^9 bt[ ^btXW ӏbpV[[@a/aZs@C Hp}` ~!d_Z_~W"0&J0P0o@D@o@_V"^/^"\"N^"P"4s~0p}pbU:,uh[NA4' }pcVe</"wuh[NA3% znbVJ6' ܿńrcTE6' ۀsdXD0+nbo\)^P00 @~zzwr{~`$ GsY(s01@zkwJ"zv@dzQzs/ZZXZN\rfK{oVg 95ago, V\h!pmWXa`h &@` #' &` A' oV#`z; P)`&Wg p)H''"`+W6 aZ]auxvifv 4G[W[ B=0VC4YpzY[V[5@FR`s4[4[0@zVZWWo{d`l|_[Y4W꾷4^\_6[]7y@7p6=0w|]_Xh G F^_/ 5]ְ .G`.GYZ/FWf/Fq/E==.FW^|G.FLGwE\_zjGXaGĐE^_a@2\^^tFְG]GYGGVI F= F@ CWFL ]WZ ]W*`]WF`FVđ]WWVE[0WWWW0VUWXWWUZ0!gk!g!g3PUY^UfY] Uf ogog_@ogqUfYPgPUfpggWgPBXWU`*t{*d@] wXuWh3 u7\ZW7aٶ7W[^ՠk[_XJkYdkfV(l`s[YX#z  s2 0@P`preXK>1$ `ˍۍ&6FVfvƝ֝t►^w]\p_`Y wX W 'V0q'Kq']q'eq'@q'@q'Yq'Xq'0"r&V &9'@' P'\'['Z '' 'W 'V t&@u7^u7w]u7\u7w[u7Zu7wYu7Xu7Wu7V!{m7@7\6G֠G]G>0GX GW GV t65 yG]yGw[yGYyGXyGW6KpG^GGGZ FYqW1pWWUu[/WY /W\@/Wi@/V cW^ cW@cW@cW`cW`cWXcWW;cWV/VW^W]V@W[WZWYWX WW NWV Vz ZgzPZg@V=0gXgWgVVgg`g Vՠfw\g[gwZgXgVfJ 7w\ 7wG 7wT 7wa 7wn f5wKwwZwYwXwPfeYv`  ( 8 H X h x  Z mo"WXI +-&\ ,[ ,Z ,j,`[ ,Oz0zrNzW,@,%W*`՗Y՗W$Ֆ Ֆ i@8Ֆca#[ #jՖ0JwJPJ@Ֆ~0~]~[~~W')@ 10v  CY W8404[4p4Pu@u@uY(vWz 0[V_z ݷApݶ@ 6CPjXWVݵ^_ǿ`__p_@_Z'`ƦX8ǼVƠ^]q Np[ Z $XqwVƺc^c]c`cעcZcצ&d z Np,$Fw`D gzо]P攡p@P%PP,P4p@ ^q \ :ZY```'@x@x@x\;x[,N@Y'p,y%5EUeuōՍpk<Y92-&V,9- 9: 9G ,( ,` z\z@,A@@NV,@  1-]:h '^ '֠ '\ 'P '] '[p 'e0 'r0 &~'0~'0~'0~'0 &P'@ &'@!'P'Ґ0&`766p7FP7J`6@ A7^ A7] A7[A7NA7`A7`A7` 5\77`076/6 p76PGB@G6I +Gi@+Gv@$6` 6(_GN_GO6Ƞ6pG\GG`GG.FF:G^G: GFPGSPG`PEsq EZh IWPIVPcWOIVlIV̰W[WYWWIV` IV-VҐW`V pW0`WV g gCg$g1VqZgKZgX@ZgeZgrVggg,-Yhg- gg10f wwY eX *v,N7wV*vpQw^QwPQw@QwQw0QwQwX ,zw6,x,,   % 5 E U e u BZX55C132NDI3OD"%9-, 9V ,\p S'pS\@SS \S@uS,[uN՗]՗08֖0ZYX 0 0 0'040A0N0[0h0uXV٧07ڦ0@ZXq >0V  NNi@N\N[NY;NXN`NNVl÷< ÷]6Ķ@V @p +]+'p+X +W`+NpZqyhpyǔP:ZxAX5 VApP6\ [ ]'puY@p V^VZV׫V׸VVVֶXPV4$W֋0(XRP  TanXWV ^0Ґ[ZYC3p - : P]jX { @qQ Q Q Q VПPV,,p,ty%5EUeuōՍ7V5E<H`]@GH`j,A,\@,V, `^`]`\`P``А`P`?-@^])`Z Y B@O@JVp J&PW' W' W' W' W'ZW'PW'W'K%@'^'P'\'P'Z'P'5@'B@'O@&"` [7m[7]C[7&7P7@7@$Y_06N7@=86@7V6ZpG^G] G9G]G'pG\GW`Gv6t6GZG Gɠ6"`GGK[   hm ######X#WE$Ћј '4CP]iw {D '4𜷀CP]PwDŽǑǞǷ{Lj!CГ! '4CP]Ɗ"w"ׄ""מ"׻"n"{"׈B#Зp` '4C P]Z&w&&&&@&n&{&爠A' @ '4CP]` *w*****n*{*,,,,,ɠ,֠,+&&y%5EUeuōՍ>2= W>dߚ><[V0 NG&i@,v@, @F0F0Fp0F0FZF0F`MG`p8 q^ 0`B@O@)6C@0'00'j0'w@d']Cd'd'@Le& @'P&&ё'>0'K0'$Zu_` 'Y'wX'W'V&+47^;47]47047[47ZK56Y6я7ɠ7֠7㠏777 76/7~`7:7G7T7a7n7{7pJN6VlFyG`yG#`yG0`yG=`yGJ`yGW`yGd`yGWyGVlFGjGwGGxGGXI%4VW VW VWXVWV VU^u WX VU]J W)WVW\WpW'VV4 ga g`VU\E3g[wH4fXMgMfggggggɠgg0gggg4pggMf/ g]g\g[gpgpg]Mf*w{ *w*wZ ,p^w^w^w,,p wwww0xw,  % 5 E U e u BZX85C5V6BL"R U-_ , ,),6,C,9!m]mjmwmmmmT@n՗Ֆ#] \ [ 00$010ՖqK0qX0ՖAa ՕSp~10Xp< O ^ ] \ [ Z Y X W V3^]R\Đ@÷÷pz 귷@@@귀@@@zR^R]R\R[NRZRhpQSƐv@V@];\ )` W_`^PP[ZNYJ0p { p׈ pו Pq֢ ׯ ׇPW   00$010z@K0@X0@e0@`O]0W V 8] - 00$010=17K07777SP,0[Z ,,),6,C, y%5EUeuōՍu?gY91C<[r#0 "V,:=09^999)9090@9090,p`,A@er,@6r0"#'P#'#'#')#'6#'C#'P#']#&p'p'P'p''p'W'V#&'$@ 7zP 7p 6RP 47wW 47V 6: [7^ [7`[7`[7p[7P[7p[7'p[7 [7 5Z7`PFP4]7\7[7Z 7P7ܮP7W 7V 6@_G^N_G]6@GwWGV6:G^G=`G\XFGpFpG`G`G`GpGpGpGPFcW^cW]cW\cW[cW#`cWYcW@cW)WdV6VWWV g g g\ g: g]UYZgzPZg\;Zg[ZgZgZf@ggYVfXxgf]^gPg,Pgggpgpf\DwF@DwSDw`fJxwPxwXxwPxw6,C,P,,,  % 5 E U e u x C27R3-<^d-^ ,c:FF$0F `Fh zz z -zFv@@~``Z+F]( $ @#b$==$0==V = ~^ ~] ~[ ~Z~#~0=Mp٧i٧\;٧[٧h٧~٧aڦW!44 N `4 4 4\ ^ ] \[a C`Ə+ǜ++Y+>0+K0+ƔyǢy\ y[yZ ++!@p@-Z""P"10"{", cוcעcםcתc׷cXcWcV"Y_^),[ ,`w MM0`M=`M篠M缠MYMMMW),@] $0n<` 7w7n 77 7 7V[c`^] P^$y%5EUeuōՍ1C106D12NTHYRI<?1jG? , 9`9w,q`#``0``=`````,(PYp`, i&:#'P#'0#'O#'\#'>0#'v#'X0#& 'r0'0'0'0'0'0@'0'`#&`7<7]h6@'7@'7]'7j'7n'7W '7'47=`7777Ђ7Ђ7Ђ67]7[7`7Yg61+G>+GK+F⇠RG`RG] RG\ RG[ RGZ RGY RGXRGW+F\ߐGhpGupGwYGXGWG`+FWf#V^/W]/W[/WZ/WY /WX /WW /WV /Vp W^W]W[pWhpWupW`W /V!W0WCef: &fV3gp3gp3gp&e^0 gg[gghggugggggf ggggfg)g g,tpw9wFww,B QwQwpQwQwZ QwYQwɠQw֠,qww]x,,H&  % 5 E U e u 3082{CA2NIC"Y3q-Y,w,Đ FdFqF~FF,XͰڰ1ȗ@ȗ\ȗ[ȗZpɖY T  "=mP=zP=P=P V ~P~P~P~@~@~@~P~P~ o- G ' 4 r0   0 hhhhhV Wp𸶷YXwnW6ƾ`+J`+W`+A+q`+~`+Nj`+ǘ`+ǥ`+Dz`[@`Ƕǀ)mB@O@9/i@+P I]IjIHwև ^@\[׀PP 01l>0  > K X e V1ZZpZpZpZ眶pZVZ`Ґ@쐵޵ZkY)P][@ 7]7j7w777779Ґ@+2 y%5EUeuōՍT'G PWR D_RIVER<\PxG\`,^;,],GN,V , mw^ m] mw\ m[m'Z, лл ,0]10w>0#'-#'>#'K#'X#'e#%Y@ q'wq'q'0q&'0q&A'@'@@'㠿'Pq&+P7v6 7\7SP7]7X6P [7Y [7X! [76`7@7706I`7p7\777Xu6W;GVF+G[p+G@+G@+G@+G@+G@+G@+GFOGpGpG0G[GZGtF@GP@G(@EZ"W] "WO@"W\@"Wi@"Wv@"W`"W`"V`WЊWЊWWYWXNWWW)s#UWCWPW\V` &gO@&g\@V MgW NMgVVUYgggŐgWgf9g^g]rf\g1gwZgYgwX gW f:` 7wW 7wf^w^wP^w^wŐ^w`^wfw`w`, ,v  % 5 E U e u KJ>23g <^G^N,X,-(SR`P`#``[ `Z `r0`0`d``q`SZ~`՗՗]՗\՗[՗)՗6՗C՗~-OJ10J >0J]J ~eJ Jq0```J]z \[w}ZAwYAXAWAjA YXWVA  `|p8 p8p8'p84p8V 8` Ǽ\Ǧ0dz0 `ǥ`8W08ސ`$0{p" p"p"'p@"4p"׃"5 pw^ p]pw\p[pwZpYpwXpWp'V"փ"z,! : G T a n \ z!ZNpZ t@ttڰZ`w]\[XyWNV 0^9PO@\@i@v@zPPސ)PP^$y%5EUeuōՍ卼?pCP82C55<] W0G&K,X,e,r,,S mW mV+ ,V+P 0]`     ƔVp&0#'$0#'10#'n8#'K0#'Y #'w@#'#'#& '0'Ͱ'ڰ'簘' '#&`'x'('\&>'7K'7X'7e'7 r'7'6i u7u7u7u7u7Ͱu7ڰu7u7 u7'6ސ77(7\6+G#+G0+G=+GJ+Gt+Fy yG[ yGwZ yGYyGwWyGV+FgpG^G]G\G[+F+D\_vV^"Wa"Wn"W{"V "V` cWdcW\ cW[ cWZcWYcWXcWW"ViW@W)W"VސW\fZCgfy3ga3gO3grftp ggNggZ ggYC gg[pfpgp֠gڰgVfVggpe^wCv,!,̰*wX*wW , Qwq`QwQwQwQwŐQwҐ,ߐ,,,`x,,   % 5 E U e u -80GP2YIC-32k-B"Z-Z,Y-ApFNpFVFy mmPmdmPmPmPmPmpPmPmVF:@^$1>K0PC0e0YWA dupdpdp@dpdpWyP вWg٧٧٧ ٧ W,P']'@Aj'@ [mP[d[P[P[P[P[P[P(['Xݷݷݶ3p@ ơ 848A8w8DŽB ƥ1w^]wYX y 00(@CApNpjpaI] I\ Iא@Ip@Iת@IXIGWI`WP^@Px6YwX W V V[p3q`3`3m3 Wtt缠tZttt @)6t懠#0 *S*`*w[ *Z *'Y (xPxPxPx !y%5EUeuōՍAdzA,<\-]P,\,[,Z,Y,- z^;z]zn zizvzzz @zP@  z~0#'#' p#'6#' $&d'#d'0d& @'\'~`''pd& '''\'['''' 0'd&@O6'p[7][79P[7FP[7SP[7[7i[7v[7[6 7 77 7 077'W[6I+G+G +G-,F4p_G@G_GNp_Gj_E[ F GX .GW F]FpFF[@G֠GYGXGWGV+_EZVW\VWw[VWZ VW@VW@VW@VW`VVWWW\W[WZWYWXWWWV'-Zp@g@g@g\ @g[ @gZ @gY @gX @gW;@gV@fpg)g6gCgPg]gjg,B *w0,9 Dw\Dw Dw[DwhDwuDwXDwWDwV,_,^,],,&   % 5 E U e u LCN2NIC-8-BIT "_̰ JG_ ,999P9P9 `9`9#`90`9=`-<q`~``````^=)=6=C=P=]=W=`:NY!٧ ٧[٧ h٧ulAPAAA9Ptr0[ɠW< ÷`÷[÷h÷uꜵ]5\@PPPNVƃ_茰_r0`ZɠXW; V I` ^ ] \[ǜǩǿ3////Y0Xp׃@pא@p, ^ ] \ [ NZp Y,pFB@\@i@Zv@ZXCZ@ZW0 [hu瀜pppZ0pppSРT a ,]@Q{ Q Q̰x^ xڰx\ x[ xxx,G,+ry%5EUeuōՍDAC8228CFP<cŐGc,ߐ,q`,,`,,`,-,:, Ta`p ppn { &W0' 'P'@'@')'6 &Bq'pPq'q'X %Wc`'`'p&:̰']'N&'p'4p'Ap%VEP776P A7A7A7A7YA7WNA7V6I`7w^7]7w\7[7BN6=`6p7w[7Z7wY 7W 7V 6# EG^C EG6, lG06GpGpGpGSІG`ІGmПt5ѐG]G֠G[ GZ GY G)G,n D]_FIW IW]IWjIWwIWIWIWIWIVVW~WWV VI` W^; W] WWWW0W0V`ggpggpgg Sgg`ggmНhfzgеfggڰgggggg0g0fpQw0Qw0Qw0@Qw0Qwd,vw~,[,: ,G ,T ,   % 5 E U e u A,= @U"Zq-Zq,,#FFFFFF F,Ta[𩯖h0@00ڰ0W 0V t̰ q^qw]q\qw[qZqwYqXqwWqV Y@@@(@X anu hhh0h01@쐩XNW`$@(@5@B@ RRR0ZpŐҐߐ쐆H@@PPpP,PX wW VS Ə@}Ő}w\}[}wZ}Y}X}W~0 ZYXA 5@OXP @@@@J0tŐtҐtߐtttt -```NVp` w^ ] X0e0r00wXW`@쐅8X,@p0, y%5EUeuōՍ?u?< \d0  ,,#,5@,O,` mrmi@m\m[mZmYmXmW,}`x@Yp ' 'V &:`0']0'10 & W'4W' pW'wY W'XW'wWW'V &N@'@'ߐ'@'''& 70 6'7@'7P'7P'7P'7,P'7S'7`'7m 6@7^7]7М7P7P7`P7 6zFG\G)E[+G +F` EG\ EG[ EGZ EG EG EG EG +Fp`GG~`G`G`G`GYFW W-Va/W`/WT/Wp/W p/Wp/W=`/W/W/WVZqWߐW쐱WWLV,,EV g\ gp gp gp gp gW] gV UZtg^tg]tg\tg[tg0tg0tg0tg'WtgP-}gggXfNA*w'*wF*wS*w0*w0fxw0xw0xwxw8fwVfw^,+  % 5 E U e u ??A!\XŐ Jಧ] S Ͱڰ@P(5uWO\pivZ wY XwWV:A^TawDŽYwX_wW_V_:^ ߐ쐆 -:_tp@@ZYב@ ֞VV֠pp\@pi@pY pq`p~`pV$00@@@V@Ma Mn MM[; MZ MMq`M~`MMF$1>K@M滠*^,W @DvDDS kkߐkkkkk k-k:,Zu(/%5EUeutdUI=1$ zm`SF9,vi\OB5(\@m/ZV:W0"P"]"@IV"VA@c@q]}\}[}Z}Y }Np}mP}hp}S ppp[ZYXW`}Xgu k"Wt'~t Dk!t j"}!&HIa$ & '\@#Wdt &'['Z',#Wdg0 6X6St Wulj0t F4}!t#Vw$ 0 `b6o0E0Vuj`}!}4bwto4bwg(đo0"Y` 7ɠ6+ 7776p77$717>7K7@x7P7W6JlFyGZyGYyGXyGW yG lFѐ G^ G] G G0G0G,GXGWGVlFFxIWmIW]JV\pWz0pW@pW@pW@pW@pW pV W@W@W W0W0W,W,P@W9PWFPpVtMgmMg]Nf\tg[tgZtgYtgX tgW tgV teX g^ g g0g0g,g,Pg9PgFPtf0Dw]DwzP,Akw@kw@kw@kw@kw , wW ,\ ,[,2  % 5 E U e u {naTG:- wj]PC6)sfYL?2632N2NIC-DUAL Z #ZM ,,0,, `@`$`1`>`K`X`e`ra ՕY◙◦◳0ͰڰWV W^W]WW,W9WFWiXv٧٧٧٧٧٧٧٧٧и[^[][\[[{[Z\wYXW y 8ݷ ݷ] ݷpݷpݷZݷYCݷXErEEnjEǙEFƳͰdz @ pp(5X9FRPINpI[pI~`J֋`}ט`}`}ײ`}׿`}`}P `]\[ZY30S`}t MzNggggg@ggga wZYwXWV0^;]QDq`"X ^`^`^`^`^江 $1T" y%5EUeuōՍED;20?dq2\`=\&p- 9p99$9[ 9@ z`9l p( 909PFP9[ 'Z 'Y &0&=']='\='[ =')='60&RP '`'Ћ'Ћ' ''#'30'?0'N00&P 7^w6]'7w\'7['7wZ '7Y '7`'6i u7`u7u7u7 u7u7#u70u7=u7J'5Z`7$0610G>0GK0GX0Ge0GX GpGV F`yG^yG]yG\yG[yGZyGYyGXNyGWyGC-pGGG@G`G`Fd IW`IWIWIW IWIW#IW0IW=IWHJFW$0V10W>0WK0WX0We0W\@WpWv@VNMg@Mg@Mg@Mg@Mg@Mg@Mg@Mg@MgC-g^g]g\ g[ gZ gY NgX f_7ww]7w\7ww[7wZ7wwY7wX7wwW7wVf,G ,T ,a x,n ,b  % 5 E U e u u?DS86zKzX`r@ ɠJ֠JJ q{ q qX JA  @ 0Pd444Ͱ4ڰ44 ^ V4hV44!4 0궆6W+8`8`8wW 8V +ƺ yZ yY yXyWyͰ+X`XF``m\["Z"]"X"r"֔ c׶c׀c׫c׸"""V4 - : jwV_@@i@P ZZZZZZYZXZW(Z@^5pAV,^Bu/`B`7r~0 QQQQQQQQQp,,],&s'/%5EU}m]M=-tgZM@3& }pcVI</"yl_RE8+uh[NA4',H/Y:!!! HHH\"01|>0|K0|X0|e0|\@@|i@|v@|~0@@@@@@@@*@"V@f'pf'pf'pf'f'f'f&P 'Ap''[p'hp'up'p'pf&)7^)7*6\P7PP7PP7,PP7wX P7W P7'V P6P 7Ap77[p7hp7up7p7p7p7p P6V`.FP:GP:GP:G `:G`:G#`t:F` G\ Gw[ GZG'V:FpG:FpGGP:@ &PXWs`x\a Y[a YZa XYa:YXa^:YWa:P SPjW&PjW6P $jWFP jWVP jWfP :PQ@W@WоWͰVQW^;W]W6@WCWPW UqMgpMg} Mg MgMgMgMgMfb gMdW\`g֠gg8gf"awfTf ,\zDwwWDwV,: kw\ , wY wX wWw@,w_,^,],2  % 5 E Uvi\OB5(reXK>1$ {naTG:- wj]PC6)sfYL?2C-CURRENT F'BAY9 "Y0 ,Ґ,FF,@mm m-m:mZnY;X[phpy \ )6CͰAW `W`W\WW WY!X(Z0࿧g0J࿧X (vX @ 6 @ ^^N NN'W c #භ0භ=බyݷ] ݷpݷݷݷݷݷݷ`R `R`RLj@RR RŐSƀҐ[php ^ ] ǟ@Ǭ@ǹ@ǮЀǻЭWo VVV VŐWҐ[php^ן@׬@׹@P9оFоSЗc@@@\=@["0!ڰ0up)6CP]j6@@pZ!@kXkWkV !_ !!] !\ !`!Z{! y%5EUeuōՍpEL7661CNE>2q I\ , , ,9,F,S,[_zmzdzqz[{ŐҐߐ쐻@@@P@]j q'@q'&0q'@q'*@v20&^'Ap'Z'' '&0 7 7 7 7` 7 7Y 7X@ 7p 7 p&6@7ܙ7]7\6~7 7Y7X7WC 7 6 p 6` GGCGPGP6`_Gp_G\_G#`_G0`_G=`t_G`FVFG^EZF GGG$GPGCGPG]GjF&cWcWcWF"`WhVҐWߐVB`WVMp WpWpWpWVUY_&gX&gw]&g\&gw[&gZ&g` &g4p&ffɠg]g\gZgY gX gW! g)fp wCwPw\w[wZwYwWwVf xw ,\]w֠ww`,,,^,  % 5 E U e u A,Ϳ̔@<_H_,$,,,,,9 ,j,w,^_є$q`Y,XW-^Ֆ@][ Z Y X W ՖJPJOՖ[qiqvqq`qqŐqҐr@̦A٧P٧̥]    ( 5 B nz hhvhhhhYiX÷ö ݷ^ݷ]I ö ö& w^ ] \X0e0 r0wöyLJPyǔPyǪ@yWX@]\ -:G#`h@/=`/J`/W`/d`/q`/׸/Ő`P\}` @ (5B[ZYXWVz g^=g]h [Z$  6C: G j]jvDDD D,P@,h@\ P`,Vy%5EUeuōՍA\^Ad= ?A,<@0-@ ,0,0,,, m(m5mK0mX0me0mr0m0m0,hu0 '0'0&E ='Y N='X &@ d'w^ d']d'W\%VV`'Ap'Y'X!'hp&`'u'0&0707 076gp 47@6 N7{ N7 N7ܕ N7[N7ZN7 N7 N7hpN7Hup6@7`6p`7`7[7Z 7T 6 +G `+G`+GWN+GV6lGJ`lG[lG[plGXlGup6zG`FpGpGwYGX G>0GK0Fm!"W{ "W "W "W0"W0"W "W "WhpDP^CWuWTQV(W`WPT.`W W-tV gZ g,V}@g]@g\@g@@g[p@g@VpgugO[- @g6gCgPgеgfw(w5wBw#w0w=f+fzkw[kwhkwukw,wЬwЬw,^,`  % 5 E U e u 56K NVRAM MODU~"Z_]-Z ,@,Z, ,>0,K0, z{ z z z0z0z z $,J0,0$ɠ -BڰNV===$=1=>=K=X=eDm ~Y J0  0''' a'n  NAu\@ui@ uA^]\YX pV m P,XPƷ=Jp[ZXw W'VW0GTp Ƌ NIV Ə@ c cc'cVtp^]\[pZ YX-:m &G &] &\ &#`&0`&Y&X&W&WPШШШ 00@@]>0K00 QQ4pQApQNpQ[pQQWQ p ,6y%5EUeuōՍu?0HA35k00<\G&),@,@,P8,],X ,S,`,m ^]  Z@ @0, '  & #' 0#&='G='T='a='n='{='='='i@#&'''Ͱ'''' %#7^7]7\ 7[ 75@7B@7O@6@6p7W`7d`7@7Z7ڰ7簏7V364@6GFȠG(G5GBGOG\G iGvFPF8PAGW`Gd`EVG[GZGGGE W-W:V/W=/WJ/WW/W#`/W0`/W~/W/WV00WW0WڰW簤WWH`UE0WW(WB@WBWOW\WiWvWV pg^g]g@g@g@gggffY$w10w>0wK0wX0we0wr0wvwfxw0xw0xw0xw0d[[w[wZuZz,r   % 5 E U e u HD36402B9-*"Y,!-Y9!,wY,X,wW ,V ,:F m^ mhmummmmmm, \[ZY;X+=K=X=e0=r0===0 Ͱ0p  #  p4=4J4`P4mP4q4~4@44 pжpжpB ƺp5@B@X  ESEǑŎ lǫlǸlllǩlǶllBF w\[wZYǀBAN V\ V[VZVYVXVVt=0\ 0X@P0Z 10 >0 K0 A N֊` Z^ Z]Z\Z[ZZZYZXZWZ p )6CP]jw@\ip ^^^^^^^^W^0W_^,.y%5EUeuōՍHD64180R1P8HD<\ $G\ 0#-P9$919#0`K`X``P`mP`zP`P`P@``9Ͱp[Z"Y0'X0'W;0'V0&` d'^ d'] d'\ d'[q d'0d'Yd'wXd'Wd'0& p'^@'''!& '7-'7:'7W'7V '6p h7^ h7`h7mh7zh7h7h7h7Wh7Vt'67^7]7\ 6)G6GCGP G]GjFVwlGlGlGlGlGظEpG^GкGкF 1G G F-W:WX0We0Vq1IW0IW`IWmIWzIWIWIWIW0VqVqWZW`W`V UZu gp g'p g] f` @gn@g{ f p gggggg@gggg f0gеgg ff^g gg,gBgFgSfu@ QwqQwzQwQwQwQw0(Qw0eYuw@w@w@,*"  % 5 E U e u 0e >d;^]* -^,, ,,'p,4p,Ap,Np,cᔗhp~,) 00'0e000 d[ dZ dY dXdV0^]\[PвX(W@''@O@'\@'i@]+ hX hW hVh(^]\ZYXWV'iip];\ EZ EY EX EW EV @^]\[ڰ簓$&ip`p5BO\iv׃אgת׷ڰ a% pPGT4A@ g g g g g g \"`@@[)6,_CP],^j7w777777wW7V,@,@,@,@,,|%y%5EUeuōՍpHI305085<UZ3"Y"x~0;]1:\S1SpS'pS4pSApS0 0Su@ ~`````Yлл SVp0>&^J']J'\J&( q'^ q'qq'~q'q'q'q'J&''֠'''(' J&[`/(6p47547B47O47\47i47v47474677777ڰ7簩7x77V.>%p`+GT +Ga +Gn +G[ +GZ +Gr+G+G+G+FGGGGڰG簭GGHG(@->%P"WT "Wa "WO"W"WAp"WNp"VZq}Whp}W}WŐ}WҐ}Wߐ}W}W}W"T\_pW[WZw,VYgwXgWgaf@ Mg^ 8MgMg\ MgupMgpMgpMgpMgpfggg f'+fCwHPvސvv 7w[ 7wZ 7wY 7wX; 7wW7w u^pwɠwͰvtw)wwp   % 5 E U e u BK-52NIC-16K F"Z9-Z3,M9P8:]SjSwSSSSzPS PPPpPPX'WS4Px `Z7p JJVJ00q^q] q\ q[ qZ qY J0̧̧wZ̧Y̧̧VJ8@P ` 6VN[^;[][i@[v@[@[@NIq XwWVN [ZYX5WEnEY`!_S_`_m_z_g _ƻ Xǜ_SDz`_=0JEXv" 4#0r&>0~'K0~'~'~'q~'~~'~&+P 'P'P'P''V~&777 ~%PxN7#N7Z=O6Yu7Au7Nu6V`7h7u7777Ͱ7ڰ7u6G@G@G@GPGPG P0K0y]X0I^I]BJ\pיpצpYpX pW pu@ ^ ץײ׿@p5 C >0 K0pv@`@mAAzg癰gNpg[pghpg [ g` 00@@g gP\[XR,B^ ^^q`^~`^ߐ^^,u@ 0,+ y%5EUeuōՍC-1MB CMWDRA"X1N-X1,@,@, t,R`^`w]`\`'[`r0Ma000Vu@ Ͱڰ[ ZYXWV d'9Pd'FPxd''pd'[Le&Z'Ap'Np' [p'hp&P 'p@'p'p&p7`7`7`7`7(9Х&[%Wh w5`u7Kv67 76E 6R 7p7p7p7@7Z7Y7X7W7p6ѐRGYCRG{RGJv5GGGŐGҐGІGF GG@G: G'VF#"W>"W["W\@"Wi@x"WN"WWI#VV}V~W^WWɠW֠W㠊WWW }VWpW1W@>WFPW\@}UV0Mg]Mg\HNf4ptgZtgYtgtghptf gpg g gXgW!gPtfRtfJwBwOw\tf~tf,̰kwkwkwŐkwҐ8kwߐkwW kw,,^,Wd  % 5 E U e u 41/2 DIGIT"[B U -[ , , ,- ,: ,G ,T ,a ,{ [T՗՗՗՗Ֆm    - : G T a ՖI{ $~`S-٧P٧P٧P٧P٧P@٧٧P٦~ACAPA]٦̰t٦'YXv@@R -Zh÷@÷@÷P÷P÷P÷P÷P÷P÷Pö öyRR#R4pRApRNpö=^QmzкLJкǔк ǥm  w[ Y ׀`pPI cc'Y3לAZ׸PZI ֆP ֓P ,)6CP]~Z'Z4ZAZNZW;O[Vp^] [ Z Y X WVX~0*,P*w]*\*w[*Z*wY*X,4V,_,^ ,]; ,\ ,,^,y%5EUeuōՍOLTAGE CONVER!@ \Gg ,,,,#,0,X,e,r,`^]\[  [  pP,]}` =']='P='w='='=&N'''Ő'ҐZ&ߐ''''& 7) 76 7C 7` 7] 7P 7w 7 7&7777ZY66@777`76@ 8GGZ G9@G`G'6+PlG#`lG9PlGFPlGSPlG `PlGmPlGzPX>%PGڰGGG GFtp "W] "W\ "W[;"WZ"W ptF, pW[pW܌pWXpWWE\`V`WVVVBW[WWVѐ V4Ag,g#V@g^@g]@gzP@gZ;@gWVg^g]gVfZgYg@gW gf+Qw9PwPw]wjww@wwfpkwPkwe[wߐ,Ѭwww, ,.   % 5 E U e u IC-1.2V REFUJI<_ c G_ ,,,, ,,i@,AN@@@Bb$1>Bdv@d@d@d@ddddPa-/`٧@٧Y٧X ٧W; ٧V ٦I` '^ ']'\'['i'v'''٦^w`]÷pP÷P÷Z÷wY ÷X ÷wW ÷V ö +^+]C+DŽötp_N_ǝ@_ǯ_ǮPõ^3]_ƿ```@@ơ C#\@W!mPVdVqV~V׋VZ{VY^WPץײp \ [ B@O@׀\@FmPmZmZzZZZZ][P쐵Z) B@O@\@FmPI`^m^z^^^^Y,WV, ,W y%5EUeuōՍF<23e?<3 jG3 ,,B@,O@,\@,F,mP, mЇzЇЇYPi#0@[Z Y X W V 0W'W`W'd`W'zPW'PW'PW'W'W'ɠW'0h-m'@'@'P'P'''(& A7wA7i@&`h7h7h7w\h7[h7Zh7h7Pg@i67647)7 7 77#7j7w76tp_G0_G0_G0_G0_G0_G_GPAf`FGEVG 0G0GG$F "W>"WK"WX"WF_cWmcWYcWXcWF9We@VWVmW)W W WW#W0W9WFWHVV`V4tgptgptg\{tg[dufpgpgpgpgpfp g] ggg,gY;gXg\gVd_kwzkwkwkw kw,ww,,  % 5 E U e u LKKJ>20?jT"Yq-Yv ,V , F^ F] F\F[,ܢZY,,՗Zp֖``m p 6 C P ] j e0qqqqpŐqҐqXqWorVt٦g^]0Z Y X W V ٦[[[[[Ő[Ґ[ɠ٦4nĶ^з\з[зZзY з$0зPжh +9P+FP+SP+[+d`+V}еX_^w]\ߐǿ`m` 06C_ \ [ ApNp@[phpc}׋`}ט`}ץ`}ײ`l~ֿ`Mg6CP]XdM瑐MM竐M縐MŐM ҐMɠM֠kN}` w\ [ wZ Y K0X0e0hAQ0Q0Q0Q0Q@0QQ,XA0,0,@,Why%5EUeuōՍu?pIP3R18<[Z_WyG[z,]x-FFFFF10F>0F ^]\[ZPPPgVFdw$& 0' 0' 00'0'$0'10'>0'K0'X0&}`'''''Y'X'W$'v-h@77 77 77'7B@7O@7\@ 5Ztp7v@7@7@7@7@7@ޜ7Xu6WGVFpG G pGpG'pG4pGFGSG`GmFlPGGGG FytFGGGG$G1G>GKFVW^VW]VWVWVWVW VW VW F(sV^WCWpVWWW$W1WW; WV VdZgmPZgzPZg\Zg[ZgZZg Zg Zg 0ZgOVr5gw[gZgVf4 w^; w] w,иw9wZwYwXwWweYwВwВwВw[,Z,Y{,  % 5 E U e u ANSISTOR, HEkXF<]Gu]#,Y,wX,W,V,dm^9o]m`n`pYX W! (̰ BO\ivYXWV$4qP~rC簋]\   '@}va n { J@dq~ 0|y l"`yjyylV ^ ] \[CǀP]jl@"ׄ"ב"`{#`VpVŐVҐV ߐVVZ  -:GTaV[[@ZYwzX@W@ p@@ g'pg4pgApgNpg[pghpgupgpgp@@p瀶ppp,+P8*p*X**,_P kkkkkZkYkXkWkV,y%5EUeuōՍET TO-2<_ G_ ,O@,r0,0,0,0,z:zGzTza,^N@[=Z=JW pp''p'4p'Ap'Np'[p'hp'up'p'p