From a34cbfe09c29f2cebb22016973994758ecffb368 Mon Sep 17 00:00:00 2001 From: sparky4 Date: Sun, 19 Jul 2015 09:46:53 -0500 Subject: [PATCH] exterimenting with ems lib! modified: makefile new file: src/testemm0.c new file: testemm0.exe --- makefile | 8 +- src/testemm0.c | 276 +++++++++++++++++++++++++++++++++++++++++++++++++ testemm0.exe | Bin 0 -> 31343 bytes 3 files changed, 283 insertions(+), 1 deletion(-) create mode 100644 src/testemm0.c create mode 100644 testemm0.exe diff --git a/makefile b/makefile index c055a3fd..03b0183b 100644 --- a/makefile +++ b/makefile @@ -28,7 +28,7 @@ DOSLIBOBJ = adlib.$(OBJ) midi.$(OBJ) 8254.$(OBJ) 8259.$(OBJ) dos.$(OBJ) cpu.$(OB 16LIBOBJS = 16_in.$(OBJ) 16_mm.$(OBJ) wcpu.$(OBJ) 16_head.$(OBJ) scroll16.$(OBJ) 16_ca.$(OBJ) GFXLIBOBJS = modex16.$(OBJ) bitmap.$(OBJ) planar.$(OBJ) 16text.$(OBJ) -all: 16.exe test.exe pcxtest.exe test2.exe palettec.exe maptest.exe fmemtest.exe fonttest.exe exmmtest.exe fonttes0.exe fontgfx.exe sountest.exe miditest.exe testemm.exe tsthimem.exe inputest.exe +all: 16.exe test.exe pcxtest.exe test2.exe palettec.exe maptest.exe fmemtest.exe fonttest.exe exmmtest.exe fonttes0.exe fontgfx.exe sountest.exe miditest.exe testemm.exe tsthimem.exe inputest.exe testemm0.exe # #executables @@ -70,6 +70,9 @@ tsthimem.exe: tsthimem.$(OBJ) 16.lib testemm.exe: testemm.$(OBJ) 16.lib wcl $(FLAGS) testemm.$(OBJ) 16.lib +testemm0.exe: testemm0.$(OBJ) 16.lib + wcl $(FLAGS) testemm0.$(OBJ) 16.lib + pcxtest.exe: pcxtest.$(OBJ) gfx.lib wcl $(FLAGS) pcxtest.$(OBJ) gfx.lib @@ -148,6 +151,9 @@ miditest.$(OBJ): $(SRC)miditest.c testemm.$(OBJ): $(SRC)testemm.c wcl $(FLAGS) -c $(SRC)testemm.c +testemm0.$(OBJ): $(SRC)testemm0.c + wcl $(FLAGS) -c $(SRC)testemm0.c + tsthimem.$(OBJ): $(SRC)tsthimem.c wcl $(FLAGS) -c $(SRC)tsthimem.c diff --git a/src/testemm0.c b/src/testemm0.c new file mode 100644 index 00000000..16f5654b --- /dev/null +++ b/src/testemm0.c @@ -0,0 +1,276 @@ +/* testemm.c + * + * Test program: Expanded Memory Manager functions + * (C) 2011-2012 Jonathan Campbell. + * Hackipedia DOS library. + * + * This code is licensed under the LGPL. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +//#include "src/lib/doslib/cpu.h" +#include "src/lib/doslib/dos.h" +#include "src/lib/doslib/emm.h" +//#include + +static const char *message = "Hello world. How are you?"; +static const char *message2 = "Pingas. Sup dawg. Hello world. Dork. Hahahajajaja."; +static char tmp[128],tmp2[128]; +extern int probe_emm0(); + +#if 1 +# define x_memcpy(a,b,c) memcpy(a,b,c) +#else +/* what have we come to when friggin' memcpy() causes a GPF?!? */ +static void x_memcpy(unsigned char *dst,const unsigned char *src,size_t c) { + fprintf(stderr,"memcpy %p -> %p (%lu)\n", + dst,src,(unsigned long)c); + + while (c != 0) { + *dst++ = *src++; + c--; + } +} +#endif + +int main() { + size_t message_l = strlen(message),message2_l = strlen(message2); + + probe_dos(); + printf("DOS version %x.%02u\n",dos_version>>8,dos_version&0xFF); + /*if (detect_windows()) { + printf("I am running under Windows.\n"); + printf(" Mode: %s\n",windows_mode_str(windows_mode)); + printf(" Ver: %x.%02u\n",windows_version>>8,windows_version&0xFF); + } + else { + printf("Not running under Windows or OS/2\n"); + }*/ + + sanity(); + if (probe_emm()) { + int h1,h2,h3; + + sanity(); + printf("Expanded memory manager present. Status = 0x%02x Page frame @0x%04x v%x.%x\n",emm_status,emm_page_frame_segment,emm_version>>4,emm_version&0x0F); + emm_update_page_count(); + sanity(); + printf(" Unallocated pages: %u (%luKB)\n", + emm_unallocated_pages, + (unsigned long)emm_unallocated_pages << 4UL); /* 2^14 = 16384 */ + printf(" Total pages: %u (%luKB)\n", + emm_total_pages, + (unsigned long)emm_total_pages << 4UL); + printf(" Physical pages: %u (%luKB)\n", + emm_phys_pages, + (unsigned long)emm_phys_pages << 4UL); + + while (getch() != 13); + sanity(); + + /* print out the mapping table, if available */ + if (emm_phys_map != NULL) { + struct emm_phys_page_map *me; + unsigned int i; + + printf("Physical page to segment table\n"); + for (i=0;i < emm_phys_pages;i++) { + me = emm_phys_map + i; + printf(" %02x: 0x%04x",me->number,me->segment); + if ((i%5) == 4) printf("\n"); + } + printf("\n"); + sanity(); + } + + printf("Allocating EMM pages (1): "); + h1 = emm_alloc_pages(1); + sanity(); + if (h1 >= 0) { + printf("OK, handle=%u\n",h1); + if (!emm_free_pages(h1)) printf("cannot free\n"); + } + else printf("FAILED\n"); + + printf("Allocating EMM pages (%luKB): ", (dword)emm_unallocated_pages << 4UL); + h1 = emm_alloc_pages(emm_unallocated_pages); + sanity(); + if (h1 >= 0) printf("OK, handle=%u\n",h1); + else printf("FAILED\n"); + +// printf("Allocating EMM pages (1.6MB): "); + //h2 = emm_alloc_pages(0x19999AUL >> 14UL); + /*h2 = emm_alloc_pages(1); + sanity(); + if (h2 >= 0) printf("OK, handle=%u\n",h2); + else printf("FAILED\n"); + + //printf("Allocating EMM pages (12MB): "); + //h3 = emm_alloc_pages(0xC00000UL >> 14UL); + h3 = emm_alloc_pages(1); + sanity(); + if (h3 >= 0) printf("OK, handle=%u\n",h3); + else printf("FAILED\n");*/ + + while (getch() != 13); + + if (h1 >= 0 && !emm_free_pages(h1)) printf("Cannot free\n"); + sanity(); + /*if (h2 >= 0 && !emm_free_pages(h2)) printf("Cannot free\n"); + sanity(); + if (h3 >= 0 && !emm_free_pages(h3)) printf("Cannot free\n"); + sanity();*/ + + printf("Allocating EMM pages (32KB): "); + h1 = emm_alloc_pages(2); + sanity(); + if (h1 >= 0) { + printf("OK, handle=%u\n",h1); + if (emm_map_page(h1,/*physical*/0,/*logical*/0)) { + unsigned int segm = emm_last_phys_page_segment(0); + printf("Seg %04x\n",segm); + sanity(); + if (segm > 0) { +#if TARGET_MSDOS == 16 + char far *ptr = MK_FP(segm,0); +#else + char *ptr = (char*)(segm << 4UL); +#endif + +#if TARGET_MSDOS == 16 + _fmemcpy(ptr,(char far*)message,message_l+1); + _fmemcpy((char far*)tmp,ptr,message_l+1); +#else + x_memcpy(ptr,message,message_l+1); + x_memcpy(tmp,ptr,message_l+1); +#endif + printf("After writing message there, I read back: '%s'\n",tmp); + + if (!emm_map_page(h1,0,1)) printf("Cannot remap\n"); + +#if TARGET_MSDOS == 16 + _fmemcpy(ptr,(char far*)message2,message2_l+1); + _fmemcpy((char far*)tmp,ptr,message2_l+1); +#else + x_memcpy(ptr,message2,message2_l+1); + x_memcpy(tmp,ptr,message2_l+1); +#endif + printf("After mapping to page 2 and writing there, I read back: '%s'\n",tmp); + + if (!emm_map_page(h1,0,0)) printf("Cannot remap\n"); + +#if TARGET_MSDOS == 16 + _fmemcpy((char far*)tmp,ptr,message_l+1); +#else + x_memcpy(tmp,ptr,message_l+1); +#endif + printf("After mapping back to 1, I read back: '%s'\n",tmp); + + if (emm_map_page(h1,0,2)) printf("Whoops, I was able to map logical pages beyond what I allocated\n"); + } + else { + printf("Cannot get segment\n"); + } + if (!emm_map_page(h1,0,0xFFFF)) printf("Cannot unmap\n"); + } + else { + printf("Cannot map\n"); + } + if (!emm_free_pages(h1)) printf("Cannot free\n"); + } + else printf("FAILED\n"); + + printf("Allocating EMM pages (32KB): "); + h1 = emm_alloc_pages(2); + if (h1 >= 0) { + printf("OK, handle=%u\n",h1); + if ( emm_map_page(h1,/*physical*/0,/*logical*/0) && + emm_map_page(h1,/*physical*/1,/*logical*/1)) { + unsigned int seg1 = emm_last_phys_page_segment(0); + unsigned int seg2 = emm_last_phys_page_segment(1); + printf("Seg %04x,%04x\n",seg1,seg2); + if (seg1 > 0 && seg2 > 0) { +#if TARGET_MSDOS == 16 + char far *ptr1 = MK_FP(seg1,0); + char far *ptr2 = MK_FP(seg2,0); +#else + char *ptr1 = (char*)(seg1 << 4UL); + char *ptr2 = (char*)(seg2 << 4UL); +#endif + +#if TARGET_MSDOS == 16 + _fmemcpy(ptr1,(char far*)message,message_l+1); + _fmemcpy(ptr2,(char far*)message2,message2_l+1); +#else + memcpy(ptr1,message,message_l+1); + memcpy(ptr2,message2,message2_l+1); +#endif + +#if TARGET_MSDOS == 16 + _fmemcpy((char far*)tmp,ptr1,message_l+1); + _fmemcpy((char far*)tmp2,ptr2,message2_l+1); +#else + memcpy(tmp,ptr1,message_l+1); + memcpy(tmp2,ptr2,message2_l+1); +#endif + + printf("After writing message there, I read back:\n'%s'\n'%s'\n",tmp,tmp2); + + /* now swap the pages */ + if (!emm_map_page(h1,1,0)) printf("cannot map log 1 -> phys 0\n"); + if (!emm_map_page(h1,0,1)) printf("cannot map log 0 -> phys 1\n"); + +#if TARGET_MSDOS == 16 + _fmemcpy((char far*)tmp,ptr1,message2_l+1); + _fmemcpy((char far*)tmp2,ptr2,message_l+1); +#else + memcpy(tmp,ptr1,message2_l+1); + memcpy(tmp2,ptr2,message_l+1); +#endif + + printf("After swapping pages, I read back:\n'%s'\n'%s'\n",tmp,tmp2); + } + else { + printf("Cannot get segment\n"); + } + if (!emm_map_page(h1,0,0xFFFF) || !emm_map_page(h1,1,0xFFFF)) printf("Cannot unmap\n"); + } + else { + printf("Cannot map\n"); + } + if (!emm_free_pages(h1)) printf("Cannot free\n"); + } + else printf("FAILED\n"); + + getch(); + + /* we do this test because Microsoft EMM386.EXE seems to max out at 32MB. + * the host could have 256MB of total memory and it would still report 32MB in EMS */ + printf("we do this test because Microsoft EMM386.EXE seems to max out at 32MB.\n the host could have 256MB of total memory and it would still report 32MB in EMS"); + printf("Allocating EMM pages (48MB): "); + h1 = emm_alloc_pages((48UL << 20UL) >> 14UL); + if (h1 >= 0) { + printf("OK, handle=%u\n",h1); + if (!emm_free_pages(h1)) printf("cannot free\n"); + } + else printf("FAILED\n"); + + printf("Allocating EMM pages (96MB): "); + h1 = emm_alloc_pages((96UL << 20UL) >> 14UL); + if (h1 >= 0) { + printf("OK, handle=%u\n",h1); + if (!emm_free_pages(h1)) printf("cannot free\n"); + } + else printf("FAILED\n"); + } + + return 0; +} diff --git a/testemm0.exe b/testemm0.exe new file mode 100644 index 0000000000000000000000000000000000000000..692e59b7fcbc540124e2912859e55a6cf539c7b4 GIT binary patch literal 31343 zcmd_Tdwf*Y)i=Ip&Y4RlAp}HjA`FTV3}6C?M8Z9ph$RpS1iX-G$OWQFCe6$wXlV$Y zQgd>W(O$*YdT$?UZL1dBC{{y`B%nP?z-oZjE44EWMFb2ngqh!W?K8K;_&(3?egAns zpZDJUsR!vlNSBdv7BKc5BpK=YOvYv-twX9pYDco%!q^6+A0Rz}bPOqo z)L?p5xMd+@c}QE4Tu2WgO+vF)AXOs$5=lWigEU>o*td{mq~9XFfph{XfbcK1T{6O%fTKiIk1B4rw#ePNa6E0FrEAY!6Zg zlF7)}Jfv)-yOAo9zK0|u{RZi;NGj3^q+X;ECdN{cY=&2b+bAJ_FVa7dK1W)LzTA%V zIMTaFUm(p-VC=g{zd-sI(nJgDLuy2N4atPQpO5rI@M}i;F7nqVG4@BKpO0Xy59yC1 z8G9M&Akv5w;E`-ddy)1bC60n_kPai=cm?!|^h2ayBArA!gJc;4`xy%zOohzXF!mhM zr_&hAypFMrNF_)e*Q2dSUm}f|4q1`XkZefbM%sqdi1aAZ>qtJNJu{%I8yIU%gDoIU zg5BmKIgoZD{Vj0$Aw1}D?J2l@ZQ+LX(!V^XC$+sQczfPhoNahH6q?(9?hhBcSH7|M zR)e&_cH+Z-(4Czw5Nn5EShe5K}H?QX$;P$PVz&M<9c z`pFl>eB_Syxiq0L|CHB&p6>52U3xfa2A=0bA{B?a=iN^d48jz`y=n< z?;CWTp?M*fUOJrLX4k!JVEGwGd>HTGT z=hzy&{f@usn6J((b?j>2K0TkKWS|}b$|xQ7?Iw*+=HOodd>@qvX#D>R?-gNw-kxE# zOV$1nWXrV2fdq_yM( z-ah7Udggo1B-sWeTko#+?+N~PU8IVP6Qrblpfbv~0Uy)sXqzsh-DiU|8rfH1w3|qF z9jO=mvvqP2^;Je_g||oQk>_U{L7%@5TF!#8pmu1X%XSV!>V8wSMRWD}zN@JXa^VHkDL0&3j!F;9 z^KV6^w;8;)p;bzUrC`hcmgA^;*eaLl$(Y_0GmfA-+1BeDF}SklMXJo!C)b^mSNp)_ zl~;wO!*bdI;i1?aF;*SMUF|N-CVmIG%ZOFD^G@S^J-zP>g-|PW{xcAV4TuT(z6Ei_ z$#|cx$NAUlQy8c^6siO@Yv%;7!DQh|RiIC~1C~Dqyq)yy*qTUEQ@IM4%$#zz< zoq@)dO196qS$KP7+h_4+ae7GC%eD)V4qWP0B-_ca;XfnG8QyMW+sW5=o1|kIy+cZ^ z-Ox7PyjChYmESf)SPR2`1ughkkBN?2n@UrPHcE=nltX}vyzTwyi-Z{RejuMCBneq} zR$hJjn{0p^$r*X|DTuT5YqG3`F!^iSehzkl@qG{P zadu%P;&5TIixf?^e&4tl9oa>nE=EUo;iGq7P&17;Q1E>M@UFaDMEm(0OG2Lxo#Flf z6wPpd7NUaC4EHdVh?|NYi1NE1{O;5EjrV11{4yd&m+vbI^D8HQ*K-MoUoMq^`JCQl zFS_%NyA+Nf$!8Biz+bz4Enh9E`@B7##f1ju&T1_@*IIP0Z7Lhv(!G}Ejdb5E(>^#5 zb?3Y%nhVc&8Sggi7NxO;25EAUVP`)x)Rr|ie0kYr2yF5zthwl7v#l59LUU=Q8vBAd zvi>owf9WAq~wi;mhMjDdV}8gsy2PgwsTK^+W>ob zdb1%go(s8?gw)q2qQ;QhK-4I<0d>W#g&pw69v+OiBz6BI(~$THVOvS?IO zC$;HIYSVv3+Z3jZXh&=r;XvDChP9ZzS_*@{^~NwUcR--bP0B#T z3*qu+v_HMw@borA<6^ggxsvxTH>z7q(&X(1Y3w#bxQC)8Jg2pGw{2maM$r5If|bFY zfbKP9wEGw6z!7ep)a~tQGqX1q|G+RAt3u+T^S^N!CLHn{3r*Q|$YlkJ6TPvxX&Aiw z&s?nMbx*ksPr;dJfBJsI-lZf|Q>x3bcNyg@C*32Y$$;DF?WsCA4&OIC3E$xee1~?| zXkVHpCJHwip8mceFhc5h^7}N@?I5|Ujfv2#?^dJt1n?5dh6^r}3j48GcG-g1R!?G23@ zt?Zb+Ir7h=WsO}w42HD%KQamjZV!8=`uw#8Tm!r`cexhY`s>B?_CTt}Ytr8A<{$Ql z_!#H$^Jem7@NxM$C%}?HM;O3vv&UMo~8SY{z zv&VU(4F66}2H^>)?vQJWw7>gfD%kxo_x#>kxIynW$tGTSX`myco#%L+Pnu0#Ml<#% zP`OUoYgVVGpH%$KY)wsBwRJ>F;l!Mb|= zs#Vrvr?X;9byZol%UW9IDl2i7m9o_im$j_g;oh>-G!`BOlRCi!UhDeWJ6L2qL2MRKy9wX~-lT-aTk zhy|_9l+^O3Z;7F$T|VCZsrJt;>v-dX+3*yQ>V6k=nQ1Xf?TnW#^x{q5awC*|Tf*rmIs^pJJxerc|9t zekV()-RPY>lcn|kmFZ-0gw?tTZ5+LGyMDpV?&}-3i;LV-J*qA+X;Edld!n4JPXfUr zcS>`%m}JeWcAIwoD-`r}8XB|MbMAipb-(hQ&4$ls-2L9;@)y$lYfLT1X(ss}@`0z4 zOxDy?lLXmbelY>-ZrVG~v-8h-7AHd!3Jo$mY}H@X(eJ#D8FTi$$ij-?=fZOc2} z4_}#()TUdcPL+G6+$oQtbwPI_6-D8Dhk4Izn<%=b%ijORxglBV@E()lj-Qru_2fF`itwT2T%%+=C+C{sqszG#Z&8W_ zCo~7Z{+4dp&{}kw{P)AYr$uiO9GcS-9F#LswqAz&m5uy4DH~p0uapg^wol5oU`n_S zGfH+6IKi!ua>&1zut=TOW{M6oTU*FiRkPIDYU^t`;=5BE+gjMSHdJQ`Vc&Dsmm30U z(VZP4yS-5AlzPw`ljK!;->(hcS=QiMr)DNJZbcF@W@DTdXbt z&J{^u>rcqGU_U~09U7I<9=K4j_a=2JwviooDFwGn-Pm!?*xCQ8;7Y|F;i<8_0~aRu z8C_R+k7b;|Af=w!pSsZ4Z>&$iBJDdd4u8GJp6)l|vmi2eLZfJu;CHY^pM~o0F$ioL zeDS_TMpk<-=ZP*N9(AQMm}54p091N2;{>)gXC;7qcV8(fV6jFzCmr;CXFRh1guP0u z`yodNh9Kuyu-{r8)I_N~&@dq9iGi0g+A|JGZ}J90o-SLTkp;XN?Q(Lj5h4bD7D$7J z$4rnqr2Sxd4PG9b!24-y2tAOD_oOjYu}eT(rJlf_xU`iGcq_Mq5|N2niiUUOh z(gx9cJmUlzR<7Q^G~_)F{{H$hXOq7&zyfAA}Z;1pFXJG2hQ8(zq!M^7Z;{ZYmE4IyFf!NcyEWeb-J5yrfY} zZ~4k62KM+FmO*L1^qxI#8OgAyBZ~7VE zj)`OjFsJ}6Q{Q$XU=v9}^_nY4eh zZ{MZYe{9;Q>*;{gTwY|~@&AGb3=R1QxHo3;NX6tGC zH2b!PIz@e;tL3<_ITW}sg)4}BN{u}qwBX*P`tG{a)Qwqm-;b#V-_A?Bht^OZt6{gv zHTjlRI;VkntKqr~zLZel3@Vx$3jABE2=yqK@GvF3iLrLx_ooT)@09{cX*uXU4r^(_ zJR;>9TiWqqYB@|VB8{EMB&p}>eXYgNn7Yr6m{rEYPL*)>u+3k|nUS_VH->JPlVux_CC!p`7l2IprPCjy_qG$Y zfc^W9kpGseHHGFw^m?P59XBbAYbafwsB2j%7G=Fh7sOlAyX(<#PYQ;H`$%Yi#(N#(lfosG$J^` zO@=Vpu6hfmc#Srd)7F93byZu4Rv9vpHj(+1N#0|CG_J8&13nZ_KNTfpvpxrgTb%QSJI@g#c1zU_( z+u@cY>7h_zQs5u{8}!~HOKZ{Lv9j3G4M(5=juP!XZ5I&iD(v-LsrT9}l7e;Kdpwoa z{tKyC{H4O)X48r$+bPrp_AkSoTGwp*JEWcnb{@hSfdi4KPaZp#OP z?IXeViC{Y^*gg|%KB=&8hOMX9_O97ArM01{rQ6f+0c%M29)q5muMTS}H?;bLz-NsO z0jv9jr=f>6{C%I5aYaInq18QsQ=W#8SVPLb^f>58fm6-4Q&~=T9=I=cTRjb*u!b~m zQJ-8iK+LCb=C%RO;*-Efp}HjW1YcbGTDpDR7y~C+!@NN}PX#(It>&<}^ZxjurdQAG%H%yX(b&FW1N;w!-+gI2qkI50EHEXu}E*s@>G?I0LYi@+Q z4cwP&+$~?@ZV8-7y|~Go+L$Mr11}C=kp&e^wKa>a>vUOLol~+_IoD^cbQd&k*Ufh? zY22=#=g#y$#xyAc@3-EquOAKER`*6oAbmirQv&0%T+VB=D&6yL$=122MG=iOscLEz zSztzBQC(5i{jNK+>fN7##ztkA22Nz%<9?sN?#vS#b%D16*VUcP+Ta?Kwc7nUv3d`5 z27Ta9SvL0{!^I3@;F$R ziuyZET7V?7>#$Ix`lX^?9G2}mw0+)zBC}_Q1<|&yT#LwHcJk_eax%~R?j0x9!Qbrn zVm`J7TeEd=lhFLmzy)kLR-*nz@qJ% zh~^;@gW)1jt_Zu`O!tybF+K1PZ%?O~0SFoUb{)D|l!Aftpu7U;R<{o8D3PbT1zUh> z1Js6U{8^WSqW|X0aId__VJK$zHH|y2N_S7fMlvloIW0FOEq8QU?wGXPv1z&3Ml=Yz z+?2Z_8Z?rZP7_8^(6fCs+o5?>9eV87uw?bMV(WQCp5n3f>3vUKDeWf{c^9+`vq$fk z*4ohDQaG^E^Hs>zj-G@c-h8!mmXhCz|q zl|7yo$_uG-_INC2W0A%njYdjAN=|Lgo`?l5Yct#rkRx7zMX1taGQY6|(-k&U=kS3e zt+V(*zn;MddgFB9+gT3R+gWbcn_1gjomm@Q9a*LB8)F=<|8F_?L(KmG^S=cD%k?df zN#ymRqCTzKevQ|}*DWlo)LEXD?<~v8ah7JSaFt-0>&k}Dh=m2hLk~?R4uX^6AE(De z`o@wjTR#raAwRef%ie6!3Lk@@f#1+uitBM0RQgFE5hHsjtHS*tHdy{Fo&QgQzgGYg ztV{=%K;iPHpwBV}y@F|tDu%NCFX$lj_+f+&r1>AzaS5pMN5Zv3sTf0htT5F&oIdnD zf?5FpHlv+{X>{G=X*kEWr?@SihO^9#rSJ@e(JDv>ayCL4a>KxKU015KF4=1frgj=; z5r&sskkOuoXoKxE!Xj58R$)8CGdL|e%QJ9p&iP*q!Zmpa4c;B_cpCcI_TL1axLDMW zQRyk_Xa1k?6^FVWF3s>2runObd&rI55*(hu>dy<-7eGVULWEpmXZBTAyr7HV^$T|= zV*pD<7r4aJ`6lB!YO#9?Z|?+Zulov5!)fLofiY@A)WDyOoxR`}ge-^ij;!+9P4z|L zHd|e{L-XjF151oB%|a*>y2eOCtV7z5Zu70U#Lxd|xcHV~K7toIS}wF;=bHs_F2K{% zmLxN)PkPvbLZ@%mWBWX-at=$1TSS zy&r~b7eZs_oBY=VabUhCn6=Sq$tnPYGeQ6HO8^ywvP#@mbkk@ZqtUX|U5;LYVlZ)_ zi)iBTe|8yD-&3#anSc4^x?g4Gx*ma-A^3lM+5hk*Zt#B!YGpPB5fm5ve?{1=7yH?w z3m8=~_4Qr!zlJy%stEXhOC?%uz5`1zv19i5+en%{1pjw0qsNNBCbppcy`7oN_?HpSPF z0wfG(W7J@#&?%=Tm@oSxurPk~<@VbloeolbIp7IdzSoDE%m<1tG%iVZo#qv#_)iS* zkx79}sNRhgrWZpo@G4c$Z4FbGT-d(>!`ZiLRN#j&ju?dq=v0vJAa}pylTXM_S$U1cxD z8Y6W}3XW_q9>d=H;t9_&=5vhl^oQJ|NTrCnQVUume-S2bJW@a8 z@l6^fb&woa5VdW9q|jl1^?pDNj6u83wmI4k z_h|~P8$=%Hjyv{+00>gPEX|*3lIKr11>Qoq5}!}cGzHo^J0u+rNZS3YhyjR*@lmjm z8vyP`O@ViaXzW($AexwYu-1;S?T47Sb1j~)j85TYBg@=he;Z6g-ek<|uDe~rxkZX> z0x%D|r5Oi9IZ33GJERYEZ%YXNiHPS&Bc<(n3h`s5g;Uohx%G`Bbsj}eAs}0jYK`{0 zB5xXl(B+=Y!*zPBtadT;y!#1?O|7>OUEsY?Ub0-T2WxqUC~X%5FGgBIrrZr#5A#;+ zhvEf)J@cH=_li2#m+}}1HvCCYIllDg`2Q`a8`QMByAF<9eOzLR0X8& zmqp=91YtAZb1xDM6nHW$+&~3(7-jgXUTwNTa~9pqAI zVOjqZOd3P_`T#4~ci6&uef{HTCSG@=h-^=mdX}PEzEmb<9KlL?v93?*z>(iHjP@Bl z-JfLk)aA>QbmwK$9-1Y-9U>bwO$+Lj+uQ-pgP6}j`jk}mLG3@ZkH6ysVPFnABwdno zM|+f%%+9(d|J9*aVD!J^Wyb_Msnt2jaAc&rp;f3?lTU3y@W;xJ3KBK6`B`1CL<8X#_K_+>hcmfa97Ndv%+ z&jgnFH?uf~b2w_as>W-DcvXKuiDxz8>Yf4|o1YVx`QVTs{X&c*X96Zi8m9GE6y153 zqLtNJ^G=|VhMmu!J2E;)8l^5?+_U%=9I*-hqYQh^6S66z7d?f+b;i@7_w?(X0yIj5 z?Ws?un^H47oIhky1wxZ9Hp5p2FOxiG3+F-#(DgNJt9Tij27W&W|lm8x(OV1h|HCid9-c{ieM1^$8*W(d}bf! z>Bn*7&Ho_tKg#?+Wr5Z5NZm0^gvY!+m1$84p6$|9h3H~i9m3{A=> zN%i>b$M^&R*+-wwlyL&#WZsiF)I-!faCXKq;_+`(C4JC%NTF!-_3rL{O2x;Kci zFoDiJEsONb{b}!hohv!K%AqHvvw;hk$9*3mpyl#Gq`-ddfQb$paqf29_jm|X&6OEP z=%}d!+ktzMX!*wds6c>@p6J|(Ux;X2JR9Q>@Vk_?`F{%-Hx#bS&RK)IBe+b3gO`G} z5?!S7_Pi2ep|NvJZ7Ix`M7Q$1J^WS6%tL(NfBB=e;X4_FF^B!1e#F*KUYkEBB)`@D zsc>wkGHzDOA@6?QOja;?y?pvWk@3+7b4MdKyoN%+QoTjmk@R4$`N7=e2XVZUn*vd$ zY*LH`IML_{)hDBy)`;>3qg-#1cO=OUvo|+Iw(F<7r7}g;DXL!i+e3;fDyl(Ijf!eg zRI{QcD5^zK6BRW{QAa3hvZ9Vu)D%S>rKqD7^$JBDqo`LZ>R3e`r>NrlAgpq82LZ z21VVdsCOvpor-#wqTa2jn-sN3QSFNQZAC3s)Xj=oqNt^cTBfMwin>Knw<>CdqTZvZ z_bO_oqE;ztwW2x{wMJ3Dqo}ot>Qq#hqPi8ePEqR>b(^Bzr>OTU>UR}&yP|$iQ5zI> zhoUwr>P|)dzM^^*^#_W&OHqHQs1GP=lcGwB+N`LuqP8e%tD<@p^+82_NKt>Js6STJ zpD5~274>I|`g28nSW$N?>LZH!3q}2M^<>hBfx4~qInMSWgTUr^K+74=Vwx>r$OQq(^y>R%MK zO;KM~)K?UBpQ661sDD+|*A(@2MQvBq{fgS5sEVS#p{NHGwNp{M6!oB@9#Ygd740_(DC$2I^#euy zP*Fcp)Q=VQ6Gi=0QBNxBzZCT|Mg6y;`V`f#sHYS)ps1%6^*@SwMo~Xk)U%5Eg`%EQ z)bomZK~cX{)LuossHlC4`jw*gE9xah9Z=NEiW*eZkfL7a6n^!U@++WIBe{q}7rs(a zG=Qm}PCf;HBg+V34?>%i`w^gnzs`fW7keI&y5)6AI3g?T4__hu3}G5viAW54^-gm_ z7qZw-m|c_j4Gpur!QvZ1UO!&Da_N*amrgl}DADX1fvJYVYe?JR0~AM}9cMze~aF%@5k23kwzS z26r(qv5-5kurLUoeF!Fe;5`;NPO+%QJPR&W0ZFIrIC269X^gk$$w$rd*vIIgmo~fb zCvX}&`BCf|!UxI_gSI_X9Z6GB>%^W?JoVrPkw|C@#3e#!HxLS4ZXv3ASOR69XYc&YeJo{ zBJhQ{tjQF(C>`XAq~rEJe%yZ72c*gHde{8;@6C;$>Tqwjha4yWSYx=6tJd-p+P$o` z;U%}VoFKb> zvJDrdEL_zcap!+^W;j%66Z~dRLy`qIs@k_-^G~CNY4~BHXGO zr|)0lBY_LCa%ce>Bfam-Fd$|)=6Stzp3ZlOOSt%T2MPzIufP~L{3aZs5w?9a%`+51 zxpDxeO`fNMTl|49{Y!CASt+1HIkcW;z!MoEay4NnBd{+`z)bTYIhvmnu7|docT)&w zId+`rsAU}5nw^5ZO6S_#rw==p>;Wk|=n0IKvd>D`5ld%jt6(pJ zgGr&2eHz<(ec+`6o_!Kkw2^gbc?cy1_@1cn7zB{=84qd=@1Yi zz|IYgz)17$3uPXzotbe26XiHh$7FQzzcr@mCL)qLKutJ=$lk`hf+90I0!OfCrpZOS z`}pK7RDXhJ@qjVt#)$&g6$WjqEr{!eJK^%WPJ<`*;ocr$@_=z6l9TSL;x5-Hk+%77 zNu7)OLiKNCDs}BM6l`8vbAy>Z^?UhNjV_OA+D+t=(YD2HgR(dASJ~9MJ*ex+>~iOM zY(co~@W6E@p&{6X(?yNK7EIDf*mU6#8yA|$-M5@YTX4%Q^L(8}qd|ZDDy+QBv(6_2 ze%y$eV+%cYze z!%~NDbWnGAmYMl(KkZxfd0=nEtB3NXvA39T^@?WI!w5~f5_W!t?S|2J-RG!}?i>1E z`wwyvpM%0-?@1pvmItx98Nkj)I!Jq)2fsi+O{Bd|BJFKX($>+H9J#lH{mR+Emof&) zLEpj8LHSuDws(QoXbq*=eD7i!HyORVj_lB5r*jbBcsZq$&T3!z5ZP;?kniojz`xu6 zkbo8{ZO`)$T0xaImW`r^dOI3jCUi<z3tuJ2squ)^5K; zxqa;hAYRttYf0YYuRmvg`dRbSStf5sdOIh$6T2w7XGWHF>!M)DwPMlb5cJU%^1sX$ z4TRh?e6NOHd7QQFWWI+(uMDuZkC@M^^>df;Su-~F#w^n_f?uXHFe6!thfSW_?(NxI zLU*a1`ne(aI(qry6oe}Kx!cq0vir7#ydQdS_L4Qph;Q5z}Fd?0D1vkUS#mpqsrZ-;7cZ)A32TYBZuBn~y;uXL(VU?#?|6!l7i~W0;rk3B*!iS6aYip>eIL7IOwlV4@kj z-PHZ5cXESCcT_gf`g}WI2sn{IR;S3xQIfYLx;~2~oQ%ZRgwO`%xAx)XyX+zCaCs92 zOj$lXBSVhZ_QJ77Q|+zNQ3RNjkw*iVJcWHMCEP~36`z9ptGHWujK+~p;TPU%U|rRY zB}k*gkd!c%$f|rhFGqbZT%bG6oThx=tHF%{eOkLh5o6td^Wa<9WtEiOSHO1AXWu@V-4p^&-tBbdk)mm$6%bfU@0V;46yWCFeB5V3K zl-Op?2ijU*Ta52AEG5vqZPq&Cw#~w<*7eoJ5V)imUrVsofY5o1m7eR|*6G((y1%u2 z1`(}uxQZ*|(VS)oQU2EZoE0Tsql@P>h{Wo0Se<2C_%|b5#hWY3s3sEl7B2X_ZOp=! zX|h3c)||XNO##uWOZ;4b=TUJ$E6Df^s4V8ulNaxl$Rx~8a^P72Tbw^55EyN;Y*m^f?bvSCA zgsLxgT1me|i?Y^A$Cg+>SvQy6=b*~B7P~+jHHN6*TgqIKZi>R()x0rb{qcN6K{Nk< zYRSU2q^T<0hhZ758P-{gtu?SJYkIVQBe?V^E+e8;XMI?!+>8h7B)*pVGHa;=9aiDA zy2_j`D4?X+?JTqARg}~^oQ`rAncCb1^JnL5%t6b`sz67I+h%pRT~=sm?wq{kv+-?$ zt!37&4lpQjxGPIxi*@M8o95>&w>rvEf<}z?R93=FYVdU;&dOR* zjT#HS!Pe(3$m0e$ym@A#Ix^3dtJhiQWNfuAyLHjr^sTYijf>{aO`pG&p+y_Grx6DXCL@-fF=y_) zo95rVAhURLNoiU6maP@{+*?^y?Wp-qt<&YMtKW9t{rF7@9C%*CUKO&CXg;O)|J6hI z&=7()@l|0zQVfhA$QbhI*-)6CA<#eQ5m+1xj?uIKMw~(A|DSmotV-N=|DQi8tYT)x z%-iPPHkUI=(CHG5qQPL$3!!AwG^1G;8iSsqz7f9GKSOI-hu>6T)@$+W9c;lL@mm|r zS~HjaR^zukcI2$GVQG#QA%3wp{H{qDGmlx3o6ZvGhi3kV5AliT^(bEKQ@>sqKTR@- z?h<}eL>Ovxpt*VoU2qy>s}OS=`pg_cciWAOO&*5df+2KU@q0M4hoQ3#q5C-UUbhX4_$WsDYG;#FCa%65SbvSRl|Hh2@H#%!eZlo!=tg0$~ zb_p-0V}%*B)2$npty{4sFOCrn%!HDy#kI_=OQ0`Q!d>C7MqPrtIvzmyt(aSxK_A0t z5R*Ouv)3R5y#rk7sNTX1VyplMn8XCT9TfBDF@rgVi@;3g1p9J_qmr3);~RA=A>mP- zPO#9-(?2xz2;OzG zYs)a<1A8w~mzSd4RqQ5HIrZTb-CR@oM<{fgZjY|~Lu7X89>L%8Q~2|q4qquMp9He! z^tX%UqmVhIpCOhTk(nb52&_B>xg;?O9a(-AvYBEgWmhA+TdXjauRul>ml?|!AoD|m zXk_K|V@G3*WAIZ$<$1{7ZoHkc8or_{x3GRM4cN(Id_iT#a@72524n5w;>~`8O)z+1j+U=2o5vg@-aGelno#EZ6@CzV2)f3e` zNmpK3T<0L&tvAqcOQ>^Hlrj?rUx3>1Ac1J`)zmsRbCIGW(7e=CWTp{VehNe@O&iSR zWXm4Pe1ObB(`gec$G(?sFmDJiTff8ab?I3SB+?uIfc!TaJEm3`dl?9a7(3W$4^8d= z7aRK^8)U4stgadxS(*o%xK(R|A!<%(>!_({wVgH&cG?Qqv1ef7d|i02Nqubr(R^LC zyJ~Y;Ez{58@37km07v^Y%7cmvLZg8=N3A+62M|99i=j=&+5q@bJZWqI)EIsRM52yQ z+>Oxtpvv5_oj8}<3Fg}kuf|yE7|FzU7Eyw2Unk&g=G%RHq{)JCzu^(om#Eu(pQ~)J z?MBl^_aPx zb2vd9eoR`4jZ4T8D|OI}z2( z`6Du4Bzytf`^bGopuZtA%7V;W$XtgEc)b_Rf-{=70t+J-EGg17zAp>+d9+b;ELB{* zgF3C}uxL{s4_U{#w9CP9v8B{fz6_aSOEGFiJ-_=}J+y)ht)|-YyKpsHv<0$#V?ED; zFE%zsq5eyb&I1Lcn^5;;2 znCMO{ry065@jLkaLOj!uu(^c!iu#&bEPv&glm*QC4E`dm2?Vm!);LCoxJ$`aB18Qe z8Ha%Cqd2M(3^0rp0Vbpo+3ohtWm{Zj+g#damOG?&d$qf=5|PMaCeY7o@>=a$SvwOd zum)%#LGdHjb-fc+^pHX7DmwynYi$e&`6QiletuW)U(S2?#}EfsoW=-ixj z*#%4p0>Y@Jnjm&tevZA?Rn3IZ5QL+yk|WrP_%>EKO3NxSVI)TcaaLhO*h>ILby4sN zyyp>VUIhrCJxua(Y@p+9=?LpUrO_gQEttOzOdgK#<`5{^8(-3~8KuM)G9L2pq2mh2 zW+q;MKN<#)p~e#p%=OA#A;joVd%#vF?@#%||?XwJ;I!liatQe9aIY2p|75lyXg z$%oP4=we1Y>xjjc)3iXuzm5`f5Ne7-_{@Rd)Qm4io#f!P{5w`q1EOdY7J-QLqoNW0 zmTxViRU1EBF&MPgfwhQ<{c-SB#kB}qy9z4qFIzq@jQ`;f{bkHcXDlmTIP^NYk zP)!GDg*MePAqtFw*nJq_5uKFO)?>9PW+LvaM(=Bmk$#FOOj*KLX3-J{*;-Lq%EY7?q}s9IW+qOI0r)`Dre!E47!#$&3FYCZ za3b8%v343;m@P^m;pi9!PO!^STNaNU8^gkPfdfq?$-bC4IfhzQv!beWRYf(R*Th5f zw^Xf$hlbfF26bRO-UH`Y)D41FR1*xRG!ZdD$A^&+1KnD%wW8dG2uWP$ZNo%E_W1lL zUXrF2J~KrpAxu#*R5|(yvkDvn{F;-!thUxs3j;qm43qIF7QS zy26Et%SpAL0VN-LC9oOHi`8YtU@RC%4+fWW=nOzL8?)P1g2`GiVZy8!GzM&n0c|!^ zsFAkBK_kFHjlfQ)vb-9CiK#K|*)=F!jkrc&q+^+5!r2&095exh$(vc@2r(DdQcJ&x z5E5XB?obRPq?E{nE5dCI!$6rfh+Bn=tcXY{iWgP~HQWZU6XYA>$sN?EM0^g!T+yWt zZjVqm^jv|kA7@b>2c%eFm~S~&JWSK!HEYn)T2AvMajuJya|i^OK1hJ*46*piDBB80 zc!pq?;%Fn&@w+iX0zu3>$A^W-5ajE;v!<*BZ57ND!-%rF;!12Dw-E4-2#~A>Tk*=W zYC!Abp$JfujYb*!wthSW= zIw2=o8on=}+D&@cBQDqzTkg$m$hPNe2ke7AG5CV;KWH`)pNi{#`?A_Cbxi!t5KswY z=!@uhD6ZOEc`tNHrSZ#Ak;)=q>{a84Bhz68`EuNuCZ}GT->@d3$%F~_97kc`&zT#Z z0EK%Z$gmUtaO6EqAkK*iKtb)=5QOK z)@9$gQgdpUNbn>Z@r^gg*~tAcEAGz*zRg zb@ke+byYRAsM+8@ER3%bvq5GLsIjT=ra0ht_E+=(BMtgWqf z5QEQS!~m0DQ|$l`-JB?20_S9}$pduM5a`-vt8;SzpE?A-a&_UdRe;YM42Q=M=0C{g zDA{_i%XJ?Kvp7bt0U>z&rnkPt<*4F=ZA*kw1Az{jj1Gtjm!p{YJrtpG0|0sc6L}{B zl%bA|EGiZAs+f?14NF*^E9d16dS8$CLBgOD-8I~?nI0*nfxx&pj&ZdE$Jpgn+y}W0 zl;J_=u!oPodGHzGV+0pt7HiM3<=V9kJrfrUfje=-p?t8HQMI|kS-QD|JW3JYwT_G$ z`$}i_@)ZR*Ns1GQXe-0c)?E?N?bz&Y#_bNij`I^yZKGYanLMjC*n(pGxnW7-b8+nR zzd(Qjt0sSgU8t-Dn$6AO*8SNs3Di}eGZCN#$3XBL}{v(e*lh2CtU}ZX7HAAtBO2UWSR!M*(z{qyY!Dw!&HL;)a+JVay@- zL9}=SE3T~BTD-Z8D8-3}NF{drvM~H>gB|0STAT;2+*oKrr@6w;7c(@ZB7!Nw_^%y| zlOwX&?U*;f3Z0h~*Lj!$u-DGV0SRKkaSB8eaR^NHmc!f9G^oLfX>)P!5MVlBwNV&O z93rYl8KD05O(@g>O+qG|K8GitZI#8C?H-7erNTk+0Fvds7@yoS*UB{%=L7poF>pZ? zTCX;;=m)?67knTN)<{?Of3$l4UYh^r&7UMkw4c80x61 zB9#xC51j}P5rYL0QUahAxsi9oZV51G8;VMyDB77kA0vwZK|78Mi9d|o)t!h@@$-EG zJdUJiTlBa$0`OOOqhU!MGvtW)dZ33#k;lXC0Gdh-IsE<0U@)V@+9Btr^#2r5$?)Om z!+4DyfRc#Iz(dd0VKmU;=bd<@Cg{*C5Up? z&P(X}0D&ThTRS2oVK@KL@H=8=xK7L3Bk0I^gi|}FqJu1A^Y!B=I-=5A3p}IaCZgjT zv+yAco%9flbRP!Mp$vhdMdR|4@yaFH{F|p zw&<}UX%?Z^FNL{G*6qekIxEWuKM9lH=5Oeh9UvG1 zv`6E9D^4p!JrB9FV-Xbp)bP7FoXgt{QBToo#yVq2i!14UnAbST$I--0{m>nZSPUDmY_M)B#8`%$r!T*rsDP)K< z$YJo$aXf_z@qd*KgYV&ZiV)(*;nCBvN2~vRv_aHU1PyW1L8{P3TZrQ+ZpPUANVsqn zwhn@5kH*OZ8AUxsxZrLLQo6=T;dqK);eS*^N&%;v=yWpf(KsbQT2aq$Thcri_h@)( zt*ED96l3S&uo0c!!|@b<(&Feb60Q7hj;DwdEIx)rPQ!O{JjIl7Y(5NLH3a`r+|bO!crsj&IZohW~2i z*Ks^;-O-9+@VhvkHtE`aE=EF)*R$VqJl~pg>*(QQ`x@YSzfrrRuOgWy4x=-T=VFeh z-Lc_(RQ@Hh5o?f5eS?!&tIbgy zWi)&q$3MjJ8-~HxaXf8qhaW|cay;#6hsVFk@q8D{5(gO)5YY3jxUwwjX-mnNoBl)} z%_5)Vc-k;(qqHA77=9G_I3;ZghhI%bPNte@FR1Nz=~H_&Np9hI+5+OvTNtB#Xp(H^ zc-s0g?gY?%>6^siM%jCuk~VCbmg!S_w3;q+d_T7+;vIXmn$o6_qhja^t?MnpX%`0lR>x2yo0JA_SNY8Xh-u-h>%~dBrS2xY@d3rXWl)BRhBeRAJoX3&tWh9%MNSVa3zzJr`HtA-A^BjO@j^O7WM z;{3$xlU60pOS-`_N;g_JH*u+jZnqJ?cy8s1C`bg*>Hk!`xQhRm0;XNTg%Zq(@X7H% zZO%zd9GNt7#7Jt(0^XMYsoeiNQbzSOoQ!cz7$oIy>5w$>!jICQ)5Uu}u HEWiIB!=rXr literal 0 HcmV?d00001 -- 2.39.2