From e35ecef214ca0664f17ca1a7977340dc23b9209b Mon Sep 17 00:00:00 2001 From: gered Date: Sun, 3 Nov 2019 17:28:02 -0500 Subject: [PATCH] add new simple example project code (no assets file yet) --- example/ackinfo.c | 492 ++++++++++++++++++++++++++++++++++++++++++++++ example/example.c | 227 +++++++++++++++++++++ example/kit.ovl | Bin 0 -> 62924 bytes example/makefile | 58 ++++++ 4 files changed, 777 insertions(+) create mode 100644 example/ackinfo.c create mode 100644 example/example.c create mode 100644 example/kit.ovl create mode 100644 example/makefile diff --git a/example/ackinfo.c b/example/ackinfo.c new file mode 100644 index 0000000..1e5d83c --- /dev/null +++ b/example/ackinfo.c @@ -0,0 +1,492 @@ +// Function to process and ACK resource file + +#include +#include +#include "ack3d.h" +#include "ackeng.h" +#include "ackext.h" + +// The application MUST have a global variable called ae for use by this +// routine. +extern ACKENG *ae; + +// Globals +int LineNumber; +char LineBuffer[200]; +short LastObjectIndex; +int MapResource; +int PalResource; +int ResScreenBack; +int ResScrollBack; + +// Creates the correct arrays for displaying a rotating background +void ProcessBackDrop(UCHAR *bPtr) { + int i, j, pos; + UCHAR *aPtr; + + for (i = 0; i < 320; i++) { + pos = i + 4; + aPtr = BackArray[i]; + for (j = 0; j < 100; j++) { + *aPtr++ = bPtr[pos]; + pos += 320; + } + } + + for (i = 320; i < 640; i++) { + pos = (i - 320) + 32004; + aPtr = BackArray[i]; + for (j = 0; j < 100; j++) { + *aPtr++ = bPtr[pos]; + pos += 320; + } + } +} + + +// Loads a background image and processes the image into the +// separate slices for use at display time. Currently a background image +// can be 640 columns wide. This number can be made dynamic if needbe and would +// need to be changed in the routine below and in the DrawBackground routine +// in the ACK engine. +int LoadBackDrop(void) { + UCHAR *bPtr; + + if (ResScrollBack) { + bPtr = AckReadiff((char*)ResScrollBack); + if (bPtr == NULL) + return 8; + + ProcessBackDrop(bPtr); + AckFree(bPtr); + } + + return 0; +} + +// Reads a text line from the resource file +int ReadLine(void) { + int len; + char ch; + + len = 0; + while (len < 200) { + if (read(rsHandle, &LineBuffer[len], 1) != 1) + break; + + ch = LineBuffer[len]; + if (ch == 10) + continue; + + if (ch == 13) + break; + + len++; + } + + LineBuffer[len] = '\0'; + + return len; +} + +// Skips to the next parameter in a text line +char *GetNextParm(char *s) { + char ch; + + while (*s) { + ch = *s++; + if (ch == ',') { + while (*s) { + ch = *s; + if (ch != ',' && ch != ' ' && ch != '\t') + return s; + s++; + } + return NULL; + } + } + + return NULL; +} + +// Loads a wall bitmap specified in info file +int LoadWall(void) { + int wnum, rnum, result; + long pos; + char *lb; + + lb = LineBuffer; // Info file buffer + wnum = atoi(lb); // Wall number to load into + + lb = GetNextParm(lb); + + if (lb == NULL) + return -1; + + rnum = atoi(lb); // Resource number + + pos = lseek(rsHandle, 0L, SEEK_CUR); + result = AckLoadWall(ae, (short)wnum, (char *)rnum); + lseek(rsHandle, pos, SEEK_SET); + + return result; +} + +// Loads an object bitmap specified in info file +int LoadObject(void) { + int onum, rnum, result; + long pos; + char *lb; + + lb = LineBuffer; + onum = atoi(lb); // Object bitmap number + + lb = GetNextParm(lb); + + if (lb == NULL) + return -2; + + rnum = atoi(lb); // Resource number + pos = lseek(rsHandle, 0L, SEEK_CUR); + result = AckLoadObject(ae, (short)onum, (char *)rnum); + lseek(rsHandle, pos, SEEK_SET); + + return result; +} + +// Skip any leading spaces in the string +// NOTE: Actually modifies the string passed! +char *SkipSpaces(char *s) { + while (*s == ' ' || *s == '\t' || *s == ',') + strcpy(s, &s[1]); + + return s; +} + +// Creates and object of the desired style +int CreateObject(void) { + short onum, vnum; + short result, oType; + short NumViews, bmPerView; + USHORT flags; + char *lb; + OBJSEQ os; + + lb = LineBuffer; + + if (!strnicmp(lb, "NUMBER:", 7)) { + lb = &lb[7]; + onum = (short)atoi(lb); + if (onum < 1 || onum > MAX_OBJECTS) + return -3; + + result = AckCreateObject(ae, (short)onum); + if (result) + return result; + + LastObjectIndex = onum; + lb = GetNextParm(lb); + if (lb == NULL) + return -4; + + ae->ObjList[onum]->Speed = (short)atoi(lb); + return 0; + } + + onum = LastObjectIndex; // Object number + + oType = 0; + + if (!strnicmp(lb, "CREATE:", 7)) { + oType = NO_CREATE; + lb = &lb[7]; + } + + if (!strnicmp(lb, "DESTROY:", 8)) { + oType = NO_DESTROY; + lb = &lb[8]; + } + + if (!strnicmp(lb, "WALK:", 5)) { + oType = NO_WALK; + lb = &lb[5]; + } + + if (!strnicmp(lb, "ATTACK:", 7)) { + oType = NO_ATTACK; + lb = &lb[7]; + } + + if (!strnicmp(lb, "INTERACT:", 9)) { + oType = NO_INTERACT; + lb = &lb[9]; + } + + if (!oType) + return -5; + + lb = SkipSpaces(lb); + if (lb == NULL) + return -6; + + flags = 0; + strupr(lb); + + if (strstr(lb, "ANIMATE") != NULL) + flags |= OF_ANIMATE; + + if (strstr(lb, "MOVEABLE") != NULL) + flags |= OF_MOVEABLE; + + if (strstr(lb, "PASSABLE") != NULL) + flags |= OF_PASSABLE; + + if (strstr(lb, "MULTIVIEW") != NULL) + flags |= OF_MULTIVIEW; + + if (strstr(lb, "SHOWONCE") != NULL) + flags |= OF_ANIMONCE; + + lb = GetNextParm(lb); + if (lb == NULL) + return-5; + + NumViews = (short)atoi(lb); + if (NumViews < 1) + return -6; + + lb = GetNextParm(lb); + if (lb == NULL) + return -7; + + bmPerView = (short)atoi(lb); + if (bmPerView < 1) + return -7; + + vnum = (short)(NumViews * bmPerView); + if (vnum > MAX_OBJ_BITMAPS) + return -8; + + lb = GetNextParm(lb); + if (lb == NULL) + return -9; + + vnum = 0; + + while (lb != NULL && vnum < MAX_OBJ_BITMAPS) { + os.bitmaps[vnum++] = (short)atoi(lb); + lb = GetNextParm(lb); + } + + os.bmBitmapsPerView = bmPerView; + os.flags = flags; + os.MaxBitmaps = bmPerView; + os.bmSides = NumViews; + + result = (short)AckSetupObject(ae, onum, oType, &os); + + return result; +} + +// Reads the ASCII info file and processes the commands. +int ProcessInfoFile(void) { + int result; + int mode; + long pos; + + LineNumber = 0; + // Position to start of info file within resource file + lseek(rsHandle, rbaTable[0], SEEK_SET); + + mode = result = 0; + + while (!result) { + LineNumber++; + if (!ReadLine()) + continue; + + if (*LineBuffer == ';') + continue; + + if (!strnicmp(LineBuffer, "END:", 4)) + break; + + printf("."); + + switch (mode) { + case 1: // Read walls + if (!strnicmp(LineBuffer, "LOADTYPE:", 9)) { + ae->bmLoadType = (short)atoi(&LineBuffer[9]); // Sets for GIF or BBM + break; + } + + if (!strnicmp(LineBuffer, "ENDBITMAPS:", 11)) + mode = 4; + else + result = LoadWall(); + break; + + case 2: // Object bitmaps + if (!strnicmp(LineBuffer, "LOADTYPE:", 9)) { // Sets for GIF or BBM + ae->bmLoadType = (short)atoi(&LineBuffer[9]); + break; + } + + if (!strnicmp(LineBuffer, "ENDBITMAPS:", 11)) + mode = 5; + else + result = LoadObject(); + break; + + case 3: // Create Object + if (!strnicmp(LineBuffer, "ENDDESC:", 8)) + mode = 5; + else + result = CreateObject(); + break; + + case 4: // Walls topic + if (!strnicmp(LineBuffer, "BITMAPS:", 8)) + mode = 1; + + if (!strnicmp(LineBuffer, "ENDWALLS:", 9)) + mode = 0; + break; + + case 5: // Objects topic + if (!strnicmp(LineBuffer, "BITMAPS:", 8)) + mode = 2; + + if (!strnicmp(LineBuffer, "OBJDESC:", 8)) + mode = 3; + + if (!strnicmp(LineBuffer, "ENDOBJECTS:", 11)) + mode = 0; + break; + + + default: + if (!strnicmp(LineBuffer, "WALLS:", 6)) { + mode = 4; + break; + } + + if (!strnicmp(LineBuffer, "OBJECTS:", 8)) { + mode = 5; + break; + } + + if (!strnicmp(LineBuffer, "MAPFILE:", 8)) { + MapResource = atoi(&LineBuffer[8]); + pos = lseek(rsHandle, 0L, SEEK_CUR); + result = AckReadMapFile(ae, (char*)MapResource); + lseek(rsHandle, pos, SEEK_SET); + break; + } + + if (!strnicmp(LineBuffer, "PALFILE:", 8)) { + PalResource = atoi(&LineBuffer[8]); + break; + } + + if (!strnicmp(LineBuffer, "XPLAYER:", 8)) { + ae->xPlayer = (short)atoi(&LineBuffer[8]); + break; + } + + if (!strnicmp(LineBuffer, "YPLAYER:", 8)) { + ae->yPlayer = (short)atoi(&LineBuffer[8]); + break; + } + + if (!strnicmp(LineBuffer, "PLAYERANGLE:", 12)) { + ae->PlayerAngle = (short)atoi(&LineBuffer[12]); + break; + } + + if (!strnicmp(LineBuffer, "SCREENBACK:", 11)) { + ResScreenBack = atoi(&LineBuffer[11]); + break; + } + + if (!strnicmp(LineBuffer, "SCROLLBACK:", 11)) { + ResScrollBack = atoi(&LineBuffer[11]); + break; + } + + if (!strnicmp(LineBuffer, "TOPCOLOR:", 9)) { + ae->TopColor = (short)atoi(&LineBuffer[9]); + break; + } + + if (!strnicmp(LineBuffer, "BOTTOMCOLOR:", 12)) { + ae->BottomColor = (short)atoi(&LineBuffer[12]); + break; + } + + if (!strnicmp(LineBuffer, "SHADING:", 8)) { + strupr(LineBuffer); + if (strstr(&LineBuffer[8], "OFF") != NULL) + ae->LightFlag = SHADING_OFF; + else + ae->LightFlag = SHADING_ON; + break; + } + + if (!strnicmp(LineBuffer, "FLOORS:", 7)) { + strupr(LineBuffer); + if (strstr(&LineBuffer[7], "OFF") != NULL) + ae->SysFlags |= SYS_SOLID_FLOOR; + else + ae->SysFlags &= ~SYS_SOLID_FLOOR; + break; + } + + if (!strnicmp(LineBuffer, "CEILING:", 8)) { + strupr(LineBuffer); + if (strstr(&LineBuffer[8], "OFF") != NULL) + ae->SysFlags |= SYS_SOLID_CEIL; + else + ae->SysFlags &= ~SYS_SOLID_CEIL; + break; + } + + if (!strnicmp(LineBuffer, "SINGLEBITMAP:", 13)) { + strupr(LineBuffer); + if (strstr(&LineBuffer[13], "ON") != NULL) + ae->SysFlags |= SYS_SINGLE_BMP; + else + ae->SysFlags &= ~SYS_SINGLE_BMP; + break; + } + + if (!strnicmp(LineBuffer, "CEILBITMAP:", 11)) { + ae->CeilBitmap = (short)atoi(&LineBuffer[11]); + break; + } + + if (!strnicmp(LineBuffer, "FLOORBITMAP:", 12)) { + ae->FloorBitmap = (short)atoi(&LineBuffer[12]); + break; + } + + if (!strnicmp(LineBuffer, "RESOLUTION:", 11)) { + Resolution = (short)atoi(&LineBuffer[11]); + break; + } + + if (!strnicmp(LineBuffer, "LOADTYPE:", 9)) { + ae->bmLoadType = (short)atoi(&LineBuffer[9]); // Sets for GIF or BBM + break; + } + + break; + } + fflush(stdout); + } + + printf("\n"); + + return result; +} + diff --git a/example/example.c b/example/example.c new file mode 100644 index 0000000..ba1d96e --- /dev/null +++ b/example/example.c @@ -0,0 +1,227 @@ +/* + * Example ACK-3D Application + * -------------------------- + * + * This is just a bare-bones simple "walkaround" demo application that lets + * you walk through a map. + * + * The ACK-3D demo programs, FDEMO, MALL, and also the Windows demo game + * "Station Escape", all include a fair bit more complexity and a bunch of + * hard-coded magic numbers, and other messyness. + * + * This example program is intended to be _super_ simple to get into. + * Unfortunately, ACK-3D requires a non-trivial amount of game resource file + * loading to be performed to get even a simple level up and running, but + * those details are mostly re-usable and is kept in a separate source file. + * This source file just contains the basics to initialize the engine and + * move a player around a game world. + */ +#include +#include +#include +#include + +#include "ack3d.h" +#include "ackeng.h" +#include "ackext.h" + +#define KEY_RIGHT 77 +#define KEY_UP 72 +#define KEY_LEFT 75 +#define KEY_DOWN 80 +#define KEY_SPACE 57 +#define KEY_ESCAPE 1 + +#define TURN_SPEED 5 +#define TURN_SPEED_DECAY 3 +#define MOVE_SPEED 5 +#define MOVE_SPEED_DECAY 3 +#define BASE_MOVE_AMOUNT 8 +#define BASE_TURN_AMOUNT INT_ANGLE_4 + +// ACK3D bitmap loading routines, such as AckReadiff(), will automatically +// populate (and re-populate) this array with palette found in that image +// file. still, this must be manually set with AckSetPalette() +extern unsigned char colordat[]; + +int ProcessInfoFile(void); + +// this is the main ACK3D engine structure. holds the map, bitmaps, objects, +// and also the current state of the game world (as far as ACK3D is concerned) +ACKENG *ae; + +// this game loop made semi-overcomplicated by rudimentary turn/movement +// acceleration logic +void GameLoop(void) { + int newAngle; + int moveSpeed = 0; + int moveAmount = 0; + int turnSpeed = 0; + int turnAmount = 0; + + AckBuildView(); + AckDisplayScreen(); + + while (1) { + moveAmount = BASE_MOVE_AMOUNT + moveSpeed; + turnAmount = BASE_TURN_AMOUNT + turnSpeed; + + if (AckKeys[KEY_ESCAPE]) { + break; + } + + if (AckKeys[KEY_LEFT]) { + turnSpeed += TURN_SPEED; + ae->PlayerAngle -= turnAmount; + if (ae->PlayerAngle < 0) + ae->PlayerAngle += INT_ANGLE_360; + } + + if (AckKeys[KEY_RIGHT]) { + turnSpeed += TURN_SPEED; + ae->PlayerAngle += turnAmount; + if (ae->PlayerAngle >= INT_ANGLE_360) + ae->PlayerAngle -= INT_ANGLE_360; + } + + if (AckKeys[KEY_UP]) { + moveSpeed += MOVE_SPEED; + + // this function handles collision detection for you reasonably + // well actually. pretty handy + AckMovePOV(ae->PlayerAngle, moveAmount); + } + + if (AckKeys[KEY_DOWN]) { + moveSpeed += MOVE_SPEED; + newAngle = ae->PlayerAngle + INT_ANGLE_180; + if (newAngle >= INT_ANGLE_360) + newAngle -= INT_ANGLE_360; + AckMovePOV(newAngle, moveAmount); + } + + if (AckKeys[KEY_SPACE]) { + AckCheckDoorOpen(ae->xPlayer, ae->yPlayer, ae->PlayerAngle); + } + + // updates object animation and various object state things + AckCheckObjectMovement(); + + // renders the ack3d world to an offscreen buffer. also updates some + // ack3d state (such as door opening/closing) + AckBuildView(); + + // copies offscreen buffer to vga framebuffer + AckDisplayScreen(); + + moveSpeed -= MOVE_SPEED_DECAY; + if (moveSpeed < 0) + moveSpeed = 0; + if (moveSpeed > 16) + moveSpeed = 16; + + turnSpeed -= TURN_SPEED_DECAY; + if (turnSpeed < 0) + turnSpeed = 0; + if (turnSpeed > 16) + turnSpeed = 16; + + } +} + + +int main(int argc, char *argv[]) { + int result; + + printf("Example ACK-3D application\n"); + + ae = (ACKENG*)malloc(sizeof(ACKENG)); + memset(ae, 0, sizeof(ACKENG)); + + // ack3d renderer viewport size. on 486 and lower-spec machines, you + // probably do not want this to be at full 320x200 for performance reasons + // even reducing 320x200 by 20% makes a nice, noticeable difference! + ae->WinStartX = 0; + ae->WinStartY = 0; + ae->WinEndX = 319; + ae->WinEndY = 199; + + // various other flags that can be set too + ae->LightFlag = SHADING_ON; + ae->DoorSpeed = 3; + + printf("Initializing ACK-3D\n"); + + // main ack3d initialization. AckInitialize builds up a bunch of lookup + // tables and other global engine things like that. kit.ovl contains a + // bunch of pre-calculate trig lookup tables. if it was not opened before + // AckInitialize is called, then AckInitialize tries to find a file called + // trig.dat in the current directory. + + result = AckOpenResource("kit.ovl"); + if (result) { + printf("Error opening kit.ovl\n"); + return 1; + } + + result = AckInitialize(ae); + if (result) { + printf("AckInitialize failed\n"); + return 1; + } + AckCloseResource(); + + // the big whammy. pics.dtf has basically all your game assets and takes + // the longest. ProcessInfoFile walks through a ".inf" file that should + // have been packed in pics.dtf at the first slot. that file (which is + // just a text file) has directives to load everything else (map, bitmaps, + // object definitions, etc) + + printf("Processing pics.dtf\n"); + result = AckOpenResource("pics.dtf"); + if (result) { + printf("Error opening pics.dtf\n"); + return 1; + } + + result = ProcessInfoFile(); + if (result) { + printf("Error while processing. Result code %d\n", result); + return 1; + } + + printf("Processing scrolling backdrop\n"); + // processes any (optional) scrolling backdrop that was loaded so it is + // ready to be rendered + LoadBackDrop(); + + AckCloseResource(); + + printf("Finished initializing\n"); + + // the main ack3d rendering functions all assume that the various fields + // in ACKENG have been copied into a whole bunch of global variables. this + // architecture was used for performance reasons. + // ACKENG pointer fields are simply copied, so modifying the actual data + // should be fine during runtime (if you were so inclined) without needing + // to call this function again. + // other flags/number fields from ACKENG are copied, so if you needed to + // change this type of thing during runtime, you would need to call this + // function again for the change to take effect! + AckRegisterStructure(ae); + + AckSetupKeyboard(); + AckSetVGAmode(); + AckSetPalette(colordat); + + GameLoop(); + + AckWrapUp(ae); + AckSetTextMode(); + + if (kbhit()) + getch(); + + return 0; +} + diff --git a/example/kit.ovl b/example/kit.ovl new file mode 100644 index 0000000000000000000000000000000000000000..9e70eaec2d0e2bddafb915a39ba2b74aaf8e4192 GIT binary patch literal 62924 zcmeFaXLOZi*S0%XLg-~Bfe?D=y|)mOED#HbN)e=~h$y0hHOqOXUpkp%9}N=U>28Pc1s+pXtuhN+1$!zZ&lHIRW)l{ z&8&8Hvm!Oj(#6i2X5Z8@`=GYjOLfd1s%zG~p5CXvUPBycVD?i(vssPIUTtjFvx!+! zQ?t^|^!MUGbF-C+W*@dNdpXIhOG{ltvRQPBS%%n_YW8JF_tDDi$<|trJIpGy(LIR$ zcbcuZ%k2HTb&vPx+S-~`Zf6!22ktfduD#iN_nAF?zge3H%*u8!yDoNgH2b2H*_)ls zdOT>>u!~uNu4c!@%7@G*b<@3eH%sYZ7TeS8yja~!&*fpg)+1)AkDA5wHaja;J*M~Q zWA^ytW=;E=<$J>Hpjh&x*~oro9iB2v=x=setbN*S$}{@f0ea7YrbXAah)^$*gz z4A%D#(K8lvpVwc%VAkSAv#6J}&f=q&bzMWv8oXkbDb@`$oA9bx*VoL-4L3V2mW(ia zVWeK`b-n%@W*fwWH_bYY(sLcHYZIToW!C3yvnpeB4`R_fW&_5W)fs1&CcYYP_T0N> z^(N@|V#!3aXWlcbF-h+s=1n&1{k~b5DQ5e`ln>1Ao2qM{rhO+~oo?3XL$ixw{tP|y znR=eH%r=P;AL;piY<5n3{E4pXQ?op?&3+Ki%+WKNt7k4o&eNWruYD@s`%KT`bF)ig z)&jG87MfiXbH32~F4CSC^A?-k|D~Rn4&`>HEcypUn#YqVpp{ziKav z!K=;k|7JE@G+kr%hj?tQ*}r1kI^EmvI^Ux8db3@k?*`q67`;*ZX_KD0sJGedXVG?x z_JQdAhuH=3;#RX9F=m@t(d}l_MA;p>Z&72X*;3K)Pwjcpe3#CgXt`UjC6f2(SJ85> zVuxtHPhTe*{H3!cs_oZ%i_!;ljzyt^x+ak+2LG+K6Fm=^Z5MYO*7u5PN3^yg|53#% zaZWsR%wCme(ei>~g}5T_zo=&>?2=h`K|ho?&Fo?EjmVp>>lRCeWoWO7dE$z=;~%rh z;)tkyS@$5;iK18ZT4JuaAR1jY8zxqZsB32Tiuc5yBKBXMJuzME6LHrSzr+-=LlnND zy(&hDpT%`i@21YM_(bd$`EO}&iy`7Ou}|dBG)oly#SF1QToVad+VA2OF;8q2|B7(J}ifj=d)_D{Ui2mYDF;jdkHi;wRs>tU$@1m{< ziB6)A7%W~F6U8jCP<$hP5gWx$aX=gsXGNO0B5sIGkt1B_g#AD8d;Xli=j-@-zK`$c zb$C5qm)GZgc)x{$_vbpe9dWqny^)|+)_{do>N51tFphv&re;<@qsc#b?zo-5Cn=gjlwx%2$l2kZy- z1^a`2!hT`juz%P`>?igW`-^?Xeq-OU|JaA@NA@NAlYPp5W#6)Y*~jc>_BH#Pea?Po z-?RTY2b>4a1?Piv!g=A`aDF&PoF~o|=Zka3dE?x1{y2x6N6sbZlXJ>><=k?9Imeu5 z&Nb(obIy6^+;jek1H=R30`Y-3LA)St5I=|`#1rBQ@r5`;y!rju?f63+A|4T!h)={R z;uUd=_(dEeo)OoGZ^Sv`9dVENM;s&`5*LYW{Mag+E-9Q`kz?$+-Gah7;X+$H`J zhl$6;W#Th&ns`mzCVmsgiRZ+1;yZDkcu(9X{*wpD2jm6v19^gcLEa#LkVnWTEAkfki#$d?Bd?L)$aCa7@*eq*JV-tyFOnb0ljKYC zCi#;*NWLPM}_(ZlHdkj-Z~PuAsi4&Y<3)?x6ml4xt{QE-53ZQ>a&{Tc}^CW2k4S zYp8FibEtQyd#Hb?gQ$n7i>QyNlc<-do2Z|tqo}7gyrH!e)LGP9)LqnH)M3kN4-bgNBu_~_~~=E>q6>7>O|^A>PG5E>c|8^T}gdO zok_h(-AVmP9ZEgA>M`9z@7r}M^(u8M^(%EO^(=KQ^(}Soq;9wCUg}@!VCrG&V(Me+ zWa?$=X6k3^XzFR|YU*q1Z0c?5Zt8F9aO!dD^8I(-uG6X4soSaF$F{m%&r{b^-&5yP z?^E|v|I-K156~CTAJ8YzFVHu<+F1Lj(d~YMzJmUOK7)RPzJvaQK7@XRzJ&gSK81dT zzJ>mUK8AjVzJ~thR)U_Zpzopop%0=TqA#L9qEDhqi>^sqmQGXqpzdCqtBz?qwk~tJ8ic!VHtOC7IyEH<32FkeQcKd z{7m;>Z@C}5>HhBx_n@eA-Tj__-TPj1A9>Y%))n^^m)-yT$Nf@7*lY85Z?oV%UAHUvx$?v*`b?zB!-J?b0HSS%1(|xRV z|L9k($1m>3f7U&S8mrvf|KvXCN8RH}UE2@thrf4^5Y<<>-}jyS^WVCE_>KE7U%Q`L z?p{zdT;|^WEBDuzx-VSfzT->x8;jj5h_;K|hkT)XUFg1UfqUBL?j=R*&-7g8>$T>& zubu0jKF7V3xNElF<5TxfKXL!#WA|GhxmOciX1R}=>HhT$_hTQr7Za(|-JhGLubry* z{6JNYXgJ0F@%MH8leI3B^!@MY8H?T%^-LzXZ+zE1YrNK3JULF+HP(ISJMMW!${6<- z-**4c#uP>5b*Vl}6Up7L|b-1ogJpP*d>{s0n4bwe{Zm+mc z8|uF2W%pRo`6c%$FS_q~LBAJWo_C)<#C`u@y@z;oko(-{+)qF2UQ0YT(EYmsy7p(Z z@5Gp=-M9C5FCiXzO3%EXp68S9iDL8$>{5XFulNPE7BuXY{C^xfu0` z_VmNrr{eiudKNw1i;I3e+<)xuURXTVP4D}V_PltstNXWI^nAr*4{9%T)_D>AJGrmv zsOuIlbp$CNy@B6t6aNztYfsfH>7a_bv9j`CV7aig5BTT~P)%er?EXUgc@iFol%Y4`iZxl-SRo^E$j9ugmN6KD=KK!TWO^To2d9^>LkR#BRa$-xAyp_r?8jpWH9^ z&Hb|utOx7D`mj!{7wg9Qv5u@K>&p7F&a5}<&ieBlcpf|#o)6E7=f!j5`SBcio;+8c zFVC6h&2#7Zvk%x0>`-J_%zG45ckJwM_EA|)rjQz&GWB;)a*^lf?_9y$4{mQ;& z|FVzS&+KdVH~XCZ&c0{=a}GEUoD0qe=Y;dZx#9e9jyO-8E6x|^jPu61f7 zFP_%X?*(y|cuU+R{t}0Y$HZmgGjW=DP247a6UT|?#C763ah`Zj+$a8%2gnEH1@Z%V zf_y>VAb*fY$S33#@(X#UPe}JG$Uo#E@)3E7{6wB2Uy--SU*s|J8F`KTMxGF$-m@b@-cat{7jxEUz4}V-{f)fIeDG@ zPM#;7pp3+g}WKU!{uc@=Cx2e0Szp2Bi$EnMy&#BX?*Qwj7-(OjM zyPl`6r@p7or{1UTAHV)~A3#4qUqF9ApFqDr-$4IBA3;AsUqOFCpFzJt-$DODA3{Gu zUqXLEpF+Pv-!kjq?LLNnhQ5aWCf`v#S3%!H|3e={KSWcDIUVc!Qed%@OA{*Sk+M zzUvxl?q4&%vo-rWQ8U29H48jIGr>JIAAE13W`i{^TuXDqWi&rrSaZZVg1O=oshYVB zX=c2Y?zgq(Yc+rTSsUGtW|H5#OLM@QQGWFv&BwRZJaaqE)8DI^=k{iu@6-J5{bqMP zpgH#rdi{=Cn@*ZD@2q+82Q?$!MfcTJv*ZtHe!iP#dAsY^9-^oIyq9K;AJ*4Bq8aK( zHILm}-~X6ir;lFmam}Xp)tvJa`gw^bbw>MXt)9})V)WOwJgu4OXEZB3K(o;UH81?E zuKPL7PY=>M4A%M$(a#XPU{>)(z2-~0@0WGGL$!XdXm)#;X0%_`Z1`(thlgtpd4ySs z*LA&b=()bB`x~X#9<68jme%ua{mjD{{ru!uUC%hpF^|{m@w@sNnhE+DfQgz3pQPtD zSu^qP>sqGhd3~TMtf_jf>3aSjY94=vyw{nUVg5)z=kl@H>z`RM)>uv+&C`bN{t|w&7dNe1E5Bwn8)7 zKWMIhrQY*Lvqx8%{ra^z#&(b?sX;OTE=> z?>5cF?@&FsQ?IqlZ1ZkC%e~s8`^>uS*Ut_e&^`aHH8`Xh?<1PkKc-pn2;o&xr8e89Sv4p`^1 z0ei4~z`7*_tWTwYJy#`QuU8A$v>E|hRx4oJ>ICecdI2lhFko#O2kgbB0bA5OV5eFH zta5U|o=Oea@>T&0-=WvKD_~#V6R-mJ2JG4U0=DmgfZf$8U_U(=uqF=$Y(@8gwd@tJ zO^*bu*JA;@_ISXiKB+(JAFy-J1nlEy1NPA1fW^NMu;VWU?3-5tHvYAMJv}mD9p4OC z=&gV?dnaH`#|JEVV!-a39Iz)p2-ukEx`vqnJNa?I66Was=Igx{1gzNNfIYu7V8@mR ztowHX`}>E0^0S}qoDmjyD#FS<8(|$^h_E@sBCPNm z5jK5Hgr!W3u!yMwG#<%bCCwK~FLHbz*+_6WPSFTyGvjj-3w z>b)}}?CYBm_I@DJ<`#^!Q?ZfOqgh_qjNM%tfGMq14w zk+x}gq%9w-uh$O*JT*7cQof4RT1DEWO_8>3U!)a19ckZPjkI+Uc`Ou@$LdweV^bUD zv7v49*r6_YY)ij9)^=DP>op;d6`7MqKgW~D`ftu-m5=7J+5hIT(}klfqH2_WfH}(2 zx<%Q(=c8=Pdr@}q%P1?cCCc7EA7#A@=Cv7h^4fzP^V*`9^4gCd=e4=(^V-}0%O9PXVGF7I9<$c?FrhM6VbMzc&y$3d~ur; z6=#`$m$ak#O52HfWv%G03U*~{Wjl1ChIRa)*b8JluZWVE=m593TJqN?*TXgD<~hr&lTQmlth($gk8r=H(wb=@oCD_PkZj`H;-> z{_Vtzo^Eib;HYla>EP%eZwb~xasHayXlX7EuZ`EEguw@=@*-3dbKW@-fT#w*P58=v0vz? zAlGJk_+X}&xti&H3TFA?ge;%YEK75FS$?&5mVf?2maiO><;`Yhd6h4-eB94jK5$!> z?>e02YtphjB`3@8E1d0DN@siHn%Q2wdA85EGuzj7%J!L$W_#HI+1_zzwkM9x_P^fC z_WHB3z0K#@9=AN(7yYDRq~Ei>^p0%L-k`vwcuF+dJgT@jx)g-;U4m zBMCWPxMq$=H_Y+$#2o*;RgO1no8$94-o(zxH~L zKQ<=Emruy?(^E9`G(!_kvvd5+XF0xNagGmIp5q0-&++$H<#^k|<)&d@(jx4=QZ#_oDy+2%d)2mK|DwIV zzeCvH>#VQo8us=*!anO^y>9QYm+Kq$j{U;^>eFHWXkggC8x;26pAY*VFNJ-}D`8*r zTG*G54Eu*~>b>3y`vdQUy~6mgpPLZ&#goGR#FVhdPYe6{55qoiR@e)F686t$hdptg z{_Hco*TS%GT@?1amxO)QS7ER9b=W`nHtaW6guUy^uz&Sa*duYHJoni=+f*;?nY*2}}b zQ73Uiq~`9TG+UidGtK!mgI!SbY=zy=7jd6iOf!4Y?*GK-aTnKIU7Y*Tk~+Ml+{UHaD{;`33?M9lR zYpfa3rh5No?m5jh|JOqEbxE3kOxCPsie?={n)z#`naS4fceHVzcc zANPnfwnsJl_n6+VkM8+#&42gRjNcQQ-R`IP)u%KE*k4-g(|XSVdX0ga2YgmDr_bqi z25AO!u&(`i&9J|q8Ne5H&o8;JdRg<5L$wCOG{gF;=Ad8GJmqlB@s7~_jMQtr?tbwN zz2_+R%A++C`j%!i-_{K07+udhnhPGQ>mR3C(D7R1cQt!FLHF{W)?t$7F(+$=_I+LZ z6wP3Mplg|`*Pf>JnXZ}e58dCNp&8AYn&+OSdCZSAOZ%~|=M&BQeySPF*?P@6nhl++ zx!HM|shscr*Jqj`{#-23nlIF^Uued5k^X$KW@*3F*DcZYE_L7XmA-$OUT3*p?`u8F zZ`{B7Rx_sG>3Uaap7eX&-w&GaT&ZjMQNH$1n#o_K`O2R)7x|0U_E%l^YRypo=3aiy z?YYs&b((J$r+;_fw_dNmLHE5;bE2Cx!@F5?II_#8R z{HOM!IJ8T1xVtsCyhn4hd$oT1G`IVg=7slb9`=Bq*Fo*izqNjcG)F7`I;`h*L^JM3 zwN}U6haK1JYhJYNN$t^7dhOG$3)0N$8O@WP)$5+q^FQzY#s%HaMLo+)n%hXzTyDC) zPMpfn+We#EdRfZjW~Q&{e*e|AUe~Pe4c((SaPxnj7uBo%kGg1XKbYGO=JtcR z{a|iCnA;EL_Jg_oU~WH{+YjdUgSq`+Za?_HZ9n)r`Y1XndMUao`YAdpdMdgq`YJjr zdMmms`YSptdMvsu`YbvvdM&yw`Yk#xdM>&y`Yt*zdM~;!`Y$>#dN8^$`Y<{%dNH~& z`Y}2(dNR5)`Z78*dNaB+`ZGE-dNjH;`ZPK^$WT-`ZhW@dN;Z^`Zqc_ zdN{f``Zzi{dO5l|`Z+o}dOEr~`Z_v0dONy1`a3#2dOW&3`aC*4dOf;5`aL>6dOo^7 z`aU{8dOx~9`aeDZegM7z{s2A!egVD#{sBG$egeJ%{sKM&egnP({sTS)egwV*{scY+ zeg(b-{sle;eg?h<{suk=eh0n>{s%q?eh9t@{s=w^ehIz_{s}$`ehR({{t7+|eha<} z{tG?~ehj`0{tP}1eht12{tZ43eh$74{tiA5ehg z68{n(6F(DQ6Mqw*6TcJR6aNz*6h9PS6n_+-6u%VT6#o<-6+abU6@L|<6~7hV75^0< z7C#nW7Jn9>7QYtX7XKC>7e5zY7k?L@7rz(Z7ylO@7(WiPH*1!zwyEG!|}!O z$MMPW%kjtGhp6;xdY}8m_uM5fw=_c z6PQzAUV*uVx9+|@$G|)Ta}CSx(Au`XJ@3HW1M?5eK`;-&TmfzgA}h0%x6iP4MEjnR+MkW_NCHy6P zCj2IRC;TUTDEugVDf}sXD*P&ZEBq^bEc`5dt&$<#Pm10z`L^$c|Ah~RABHc6KZZ|+ zUxsgne}<2SpN6l7zlP6---hpo|8}y%Z9fiQ4u1}x4!;iH4*w1x4?hoI4}Y&&;oE*6 zz90S{J|KP|zMvxfe?B38A-*C0AwD90BEBO2B0eL2Bfca4BR(X4B)%m6Bt9j6CB7y8 zB|awoE50WFCO#*AC%z~CCq5{CD84BEC_X8EDZVNGDLyKGD!wZIDn2WIE50lKD?TiK zEWRxMEIuuMExs-OEj})OF1{}QE>roCEU?%snvwz#Ihg5X?m|AHkdi^AgNWFh9W@1@jclRWM({oCWh1 z%v~^l!5jwj7|dlbpTV34^BT-;Fu%bZ2lE`vbuiz-oCotB%zZHb!5j$lAk2j@AHtjn z^CHZRFh9Z^3G*b(l`vnzoC)(L%$+cQ!W;_oD9oiWpTe99^D4}(Fu%ea3-c_@wJ_hp zoD1_V%)K!G!W<0qFwDg;ALBa0x&2^nKbYGO=JtcR{a|iCnA;EL_Jg_oU~WH{+YjdU zgSq|S|9SnOR9?#`N{b}%l$ayV^7}y0W{SKKL3=~wjnwZ&i#+;y4KXJwX#Mi)_xbew z`Sm&luRD#&^p%A>(mL_)Otbtqe0M$H4a*zra}9ydC=-6 z1?`LEpfv~uZDVVF-JL-zcTdm`w+q_h`+_#6L(m3y4qE@NL3^%y&_?yrH9Q)$eSLyf z;>n;r-alx+4hUM!K|!1Me9&sWtk)eDv?oUdt<;-AJM>o2z8V{}_a+2wRTq zX9R80$3fdWCulLB2kntXL0h>rXqCSS+Na+Kt;VXLtz8|ofxic>+UB7BvrX5%D`+eJ z()}I^+Rw*>w*O4f@?6sWUDjG$4_Zc6(0WVoK9)Dyo-Z72aWT>MN6Bb=zg)CET{+qw ztQl<`>POonO`~mi%V_(mb+lc%C)(OQ5N+RdiMG1EqV4BC`uqOT7BeW?4!jg?-wltp zd84Ck{`hG7@%?B!F(cY4%!#(a3!`oCS9-ngqwVl7(e}prXiMA{ZBcup?X3PmlOw01 z?c$|qEAnr&-IWtM_>8L5!ugh_PCC#8|!dF?Mg47#s0O zjBV-{V|50{*cZcMEO~T{U6>GK%csZKq&YD*c5#e-^j(Z?{58gkZjP}*yJPI);TU`K zT#Plo8e^UlW9Rb6+NIc7D_kMg+SQ7+c}-(2zICiExi8ip?jCEkpNO@RgJZ4I@K|d< zHrA$2jkT;fu{LUHtkwJ}*8bTLYk%#IwWG&ktw4ILJ(v}1zvVA(9pYpzR4HzI8Wy*$ zq2hM-{^C~c;o>&#nc@~bthlXyr?^d-UfkaOytpm?uDJcPuDCtAySQCFQQW@1Qrtd_ zC}9g?O4!j#C9HMh61JmF345nY2^;Wa348VB686J8B`jg4eqCI`hW}i`25&E69~>)T zXReg6XXK}skB_rFwd1T@YMk}&6lZ6jh_hL*#M!6`aW;ESoL%`Y&PHsGv(S+^YjHKs zp3Ps<4wfrvqZ*gAe(g%y+r3NLiI+;+@ChZY>->`T+)pKK!q!A$uc%B zv5Y15EMuL9m$7}Hma$E1%2>_QWh^UyS!-RltYvp9YjuZ~wf!HLweZ@qHt&2{TOTZE z0}{*G)W^!n!z*VazbR*J4wbVH^Om>Q8kV=K50|%yapi5%it?6rqP*=4RGL$UAPBcugSD#3*tsf@Xp+6GrE30UCH>+r046JDT=U249|E_4?6|ZE^ zJRmb_TqPU+dnG$zl`S!~vW*&E**31KY=yHcTlbVIw(RvP7Qe2F&B|BRTHaq(K73WX z@po0LP_>%9HK>}^Syjy{{8`W)myBap^lN$Or)N0t7b~SC-yqdNo zyQWR(UdyU{U&~%EQQMZhT-&}sP}>%#*0C9%*Rl7C*0ou~>e{w5b*|N!wBKtsvLVYGS;eHr+Ru&c#zRf)!3#~S;+swFjWW&b z{U4jzi@loL{eeWg{^OZ;Gw@GsRZUOSRXBg{?Tha1?DJ9g+KBJl+tO?I*-t4C zSo0|z?B^>TExmVVd;Q>pR;O=QNuv*0`FY)~PS2i}R{3EYYLD8#|Ma$H*ZWw$*e7h{ zJ^k#*Y5nbOf5r}udDf2C9c-D`pSSg=Ub1SLuUOZl;dcCs*X{Rqqit}-ckF1BckRn@ zldO8RsrE+nOgsGGr}}s8=3A#ci*4w*<<@oT4>rH)YKwStqs^JP(@GCLXzxFI+A0jZ zY@2q5t>oq+fnVp856t+XVc^2pdjiK-JQnCzVr1amt#bk&zO*G!uTM^(P5zXK-;cf* zaoV#Yp4&JzGVSWHJl!tbh?;odYW}NVo|S{)uNUbOpZ-F%!Z#L`$e$Tocudxm!~xl5 zEKg2y!jPO_ZmiAO^=U-->G4g&FE#ERo^|2PaD{tkhvSB>4EJxlJ$y&+*HST;LEbQ>fdR2*efsT<8P$*^8*J4 zc-NN)d&NIq^vOqF@#OD^dxdUq_?PQP`@yJpyk(j3p0~h6udr*9R~t6PU$bd`&odwT zsFgGQ)}@cUQ-M#tP_a2a&gXjUq4~b&^UwXnBMUt>YLV~xc(K1(b&1E!S?YHdS>~Ic zUG8_U{n{Ta^sSF>_nr3|vBJAA{NAr@{K01&l~$boqtE{LCtrPSl|OaqXTNah7oWP} zS6{wpwZA#$H*fpM8o#UFTL1diT3@$%oqzqt@4hs7y`R3i-rrfU!GG~=}|XM`d_6_d1C4*uhr+2FB^Tz zH+_D}hi*LOtIwVC*#%B}nOdj4$-Srj($lBC&A8K^{KaYiYr|=eKYiN65oi3}gfqS- z<&4kmdB*DuJ>yS&aK_s$JL5;TobgIBvf~41eNCCOUar|$uh;Rc|NHb=e_`}l|Kj7b z{^5$V-fH_UH*MZI%A<*sx7<-_OvtryOD`SIucwK?Z}*7xUpq&_&m z+KF@i!HsjivG93cQ}MiyZg$>_wma7>N z;^7P4Gwp&uopZrE6uIa{%3bt%buM}^`JzA6{-VFs^P)fZ^hIy25An|!bJ2%RyXXh! zU-VMnT=XWtUGzHJFS;GN=wF||=&f#C^rd+&`HkpHUa`U@uUY4k_VXqG>#j>avhyX6 z>V3%v4!GnihF>Hc-Qbg$hh-6wZX_v5|Oz5G+@ ze$R91{>V$|{^;;@zi)K9S0A75>66oa{)g#)=cnnu`?GX^;LCLX;p=oSx-#86|C;V^ z{jR^?qSxD*?o0Qj`-g|peb9+?Z+b4>FQldWdsovv;a0lO4X1l_o(vycAj4M|&G78l z46jit!|yDg;T5X|-n4Fp2ODMh!DbmgwPl8BX&dTswpJsTkxfwq4vkafIFvDjo&hW`gGyK)%8UE0>8D9DO z3_rOt!>6sv@D{&j_|D%ly!*Ng-@RV1yD7tGZ^`h>TXo$#GJN2l`nug2zI?Cl?=Nv6 z!@vDI!)G4O@F7PtJmq+XXPwCKC8u=1XEOZES*^wS48L?i*Pwq$;+M1xkIBgJp8x1| zE@$|+8f!u|b>>w}k$s!vB8d_xw43&)4zwd>`M>>-_h6dR<6`U*4bV;Ci?& zu8-^Fdbw_{pZnl`xG(OH`{aJPZ|{s?J` zbHsV#TyefQXPh_A9p{g8$a&;kay~hyoL9~*=a+NLdFEVmzB%Wdcg{WMpEy7~ATAIe zh!eyM;s)`9I6^!jt`J{{GsGL>4)KRLL_8uc5ub=t#4F+!@ryV{JR`0V--vU>JK`Sk zk2pv?BrXykiIc=j;wJHvI7&Pvt`c8~v&38CF7cN*Ogtto6Q7CG#B1U<@tZhKJSVOb z--+|Yd*VLvpFBW5ATN*~$P?rX@&@^XJVHJpuaIBJGvpic4*7>XL_Yd2FDXBfr^r|2 zE%Fz6jC@93BfpX7$amyD@*jDSd`Mm-KawZOm*h?ICwY{7N?s+ul4r@cD$@k=a@;`L|^#FAN^#OGP^#XMR^#gST^#pYV^#yeX z^#*kZ^#^qb^$2wd^$B$f^$K+h^$T?j^$c|l^$m3n^$v9p^$&Fr^$>Lt^$~Rv^%8Xx z^%Hdz^%QlLCSd=ov#7VIyQsgY!>Gro%c#$&)2P>|+o<2D!|Oj^QiZz`>6k@ z1E~k83#kvO6R8)e8>t_uBdI5;E2%H3GpRSJJE=dZL#aopOQ}z(Q>j;}Td7~EW2tAU zYpHLkbE$W!d#Qh^gQZ&Plc|@fo2j3vqp7EPxq%c;-* ztJ77lQ@2yUQ^!-!Q`b}9Q|D9fQ}K#U(?`=!(^u19(`VCf(|6N<(}&ZK)0fkq)2Gv~ z)3?*V)5p`#)7R7A)92Ig)A!T=qXVD^pbMZ6pc9}Mpc|kcpd+9spevv+pfjL1{HHre ze?W&ok3g3|pFpQTuRymzzd*-8&p_8e-$3U;??CrJ|3C*p4?!0}A3-NUFF`j!KS4)9 zPeE5fUqNRr4?-70 zA3`TWFG4p$KSD=BPeNBhUqWX>Z$fuMe?o^sk3yG1pF*cXuR^y9NWVhILeE0iLf=B? zLhnNNLjOVsLk~k2LmxvYLoY)&Lq9`DLr+6jLtjH@LvKTOLw`euLytq3L!U#ZL$5=( zL%&1EL(fCkL*GN^L+?ZPL;phuL=Qw4L?1*aL@z`)L_b7FL{CIlL|;T_L~lfQM1Mqw zM2|$5M4v>bM6X1*M88DGM9)OmMBhZ`MDIlRME^twMGr+6MIS{cMK47+ML$JHMNdUn zMPEf{MQ=rSMSuNIhm{_SE{i^kPK#cPZi{}4j*Fg)u8Y2l&WqlQ?u-754vZd*E{r~m zPK;iRZj646j*Om+u8h8n&WzrS?u`D74vij-E{#5oPK{oTZjFA8j*Xs;u8qEp&W+xU z?v4J94vrpE{{HsPLE!XZjXMC zj*p&?u8+Qt&X3-Y?vMVD4}c$lFMvOQPk>*5Z-9S*kAR7Z-IY-kAa_ouYtdT&w<~8?}7h;4}u?pFM>aUPl8{9Z-RekAt6suY3tFN8mYPlR8D zZ-jq@kA$CuuY|vZ&xGHE?}Yz^4}~9vFNHsaPlaEFZ-sw_kA=awYMzL1>B36oT#8R

w8+tC{+$Ythis)5e3D0eGcMAu|T{f9v7`dIgzE$N8B$~h$&)_ zxKC(g$)d#ZhFUi;mIH}K6{8h{lFNg<34G|#@>9ZEU7n8*^qKzmguIsZG zcZe^f@m-RV~o5XDKvbbMV7Mc3&#+_n;7%n=C8X~OE zbKD~qiIL(#QA6bDGah$|h2k~QQB)B(^|_B*#T@aXxJQ%`>G~|lHDa20N+gLQ;+Q@k z@*DBC=q754tg70_VzwA8?hvu!v_3=fd-0CwE^3NQeV*hN@sSuHl0{*0NMlz^#BkAG zlo1#8nUg<>aiWK)A#Nm?Z4lE$U(rYe#EuHui(-IC68Xix^7_0}F+_w!VR5jW)(HT5l@Kv zBD18~dNEn_5>>@NaXReIT46Eo%0u=qKul8%1)*6aIqPg%wdM4sM@sKDlP8Zaf6)%cpkw^SdK>J(t6cxq!{ASC=P!SS& z#kPEk{o-L!SzO4g&oLFRh>*xDwngb{L@!ZEoX?}z5kp0)h!R^P^_jS$r>H2-MJPsy zmqfDAM<&~rfYw9kBZo~N2W+QJdr-U}l7#-qHfUI8qR_`Ux;`q=Pw3Ouz7YEOzyCgW zG)Ety_q%vk@EN4~7(73!kGfkRo)t|*R+jr(F-~+8CB>0U_s_*Z(O6{O(&uH0v7&>B z6Nhi=Gc(0N(O6{O(AS7@qN6A&j$YS$iRVO9k^Qf(M@$e8iZbHFHTT8hd66UnV)Ipf z4yWiLDvI-0^cj+3m}o5uh+UWU`Iq8xQCnQqN7k(pZ;AUv32{U}4zfV#$0j^c1cZKk z!Ka8`qN+$wbN@lSA=-&pap;onUknl&=l2M)^`iT9(Oc9MS1-8#BHj_5MOks?y!&$T znz%~@#oy=jT4JzhDe{Ux&$??w-k%bUMEH#ESxgg;i8?|bvFGc=B+*M$7gtZY|0X7g z?xL!=d{X~Dmv~on6II0J6Z$hTLG%#S#I@skK4Ox1MAQ;DkLj~e#Wc}ZXuRDu-tOCv zx_=@Dh$K-!>_4KArT`^|K?b#O+i zcw6)k^@K*`eg9tfrDBxmChCX?v44*~XI8u=dWr@juQDt9~ z@tn9@lo!|k)cT2q;&stoG!zBJ$(`CWV!9YC?iE!;c!%C!d?O}`{^AZ%PTbnA&$kuJ z#Jl1t(MD7dS=+Q$;ydxacuuqzHAIv+xmEi`d@6>EoBB39hmpjaX{h$Z3!@v7(}+KT$3r114RgJOsHLCh9o#Sqa` zv=MbgoG@|Wcddc=RV)%8h>_xH(M7ZpwM9u0DKge+Ux`g(g_tKMiQ(cI(M{YX8jFe| zD8g&C&&46}hgc;Ri&AlisTQCCzFB}EYtA#VPr`w^$bA+bwr7Qcy=VwqSdW{VHSBr#UJDP9#X zh=HP?=q-AP2gL)Tt!N`sMGMhHG!V5#bx}nmh_a%Th!e3QD2j^0qJYRR@`^knQbdS= zu>S%6p0DHU`98j%*WvYeU0$E};r)1D-kdblpGkL%=mxo)nX``~`KFYb@~>>;>s z?w@sdL9i~Y&sf2Fv2Ls%>&SYtuB~r=z`=0&JIp92SE;t{Y6V40ghV#QY;yiJ#IA5GI&Ku{B^T#>lJaR5M zpPW<9E9aK;%Q@yebFMkxoO8}Q=brOV93UPL7l;qU3E~BDgZM!lA)XLdh%dw$;tg?! z_(L2b9ub#_PsAzW6>*FBMI0lZ5!Z-s#5v*}agX>%93&nR7m1I=N#Z4Ollb|kxGadP z#Me%OcuU+R{t}0Y$HZmgGjW=DP247a6UT|?#C763ah`Zj+$a8%2gnEH1@Z%Vf_y>V zAb*fY$S33#@(X!}d_&$L|B#2sN8}~)6M2e!McyKRk;lkqHiCr~d?H&8!NM^H~tS5RM2XHaiYcl;`-L#RinOQ=t%Q>a&{Tc}^C zW2k4SYp8FibEtQyd#Hb?gQ$n7i>QyNlc<*psBTIU1H>m{yKvF)*zJ0Yx@&{DDX7P& z%c#$&)2P>|+o<2D!|Oj^QiZz`>6k@1E~k83#kvO6R8)e8>t_uBdI5;E2%H3 zGpRSJI~$$7U58SSQkPPnQm0a{Qn&sssAH*TscWfksdK4!se7q^se`G9sf($PsgtRf zshg>vsiUczBo=nLo%=o9D{=o{!C=p*PS=qus8=*x}@ z`ZW4A`ZoGE`nYCct%sn$qt7d&t<*(K6dMHpqc5aCq)((@q;I5uq>rSZq_3pEq|c<^ zr0=Bvqz|PZr7xvFrB9__rEjHwrH`ebrLU#GrO&0`rSGNxr4ObbrZ1*Hrcb6{rf;Ty zrjMqdrmv>Irq8C|rthZzrVpndr!S{Jr%$I}r*Ef!r;n$fr?02Kr_ZO~r|+l#M+ZO; zKo>wCKqo*iKsP`?Ku17NKvzItKxaU2KzBfYK!-q&K$k$DK&L>jK(|1@K*vDOK-WOu zK<7a3K=(lZKnFn&K^H+EK_@{kK{r7^K}SJPL03UvL1#g4L3craL5D$)L6 zAUYv>A-W;@Avz*@BD&&h0-X`P5#15}5gige5?vB~GAz(5(Jj$0(J|38(KXRG(K*pO z(LK>W(LvEe(M8cm(Mi!u(M{1$(NWP;(N)n`(OJ=3(OuDB(P7bJ(PhzR(P`0Z(QVOh z(Q$tj=(^~;=)CB?=)UN`=)mZ~=)&m3=)~y7=*H;B=*Z~F=*sBJ=*;NN=+5ZR=+NlV z=+fxZ=+x-d=+@}h83H}KzUUwZ3G{AsZ}e|;aP)9=arAL?a`bX^^VI?!9X%ag9eo|0 z9lagh9sM009z7mi9(^929=#sj9{nC2A3YykAAKL4AH5&lAN?O606zd<0Dl0V0KWj= z0RI3V0Y3p>;T3_;fZu@cfd7CGfggb{fj@yyfnR}dfq#LIu|(i&;BVk_;CJAA;D6wQ z;D_Lg;E&*w;FsW=;Gf{5;HTiL;IH7b;J4tr;J@I*;K$(0j1kiWeht12{tZ43eh$74 z{tiA5ehOpM^)7CzSyf$xR?g%5@whA)OchEIlHhHr*{hL47yhOdUdhR=rIhVOPj z91{3(_;P0jK3$r?x5K}~$HULNDe(8Q1%4mCp9^dCzv7|)^}le4|8n$Sw*Je~f0?0M z`tN4wM(BFz-_W(t)zFpD<;@B6K`-G;}0%D0DEi zKlE2haXWsryrRr*2Q(lDafF?iQ$I|dk~$&vozzjO!&8T*4oMxD z+ApZuh|%cK@hEt;A?H6k@T<=>Qyl=CSkQVyl; zOWBdKIc06is+1KeU!^QenVT{z<%5(7DQ~BYOc|OoIOXY-$5VQxbV<2C<*t;}l;$b* zQ);ACOevKTlTt7xA|)&NYVxJzQ^|*t_atvkUZ4C+@`~i8$)6{Gk~}SWLh@V5!;@c3 z9+=!WxmWUo$@eDTk=!D=VRDV+gyfRRMU(R;=d`@m@?y&qEf2Q*v*o6it6P5Ga%s!? zEoZfSzvbALueW@u<-nGGTlQ$#vE@B2Q(87@S*vA2%aSdNw2W+-nes$QPVp)sNTFh+mUW?H!UTN`ci^p4ZYjIzT)-9U0sMVrEi`W+VTjV5OPCS!%FmXrX zy2Kw6mn6g1?6YRmn~iHW zyxE{;k2mYm?4D*x&FVC(&@84|o@O_io^N`n>Gr0-HT|~f=S@FsI-H~FW@i6(oRY-sXBlSNHFYBHh8$R>lE^l9>7lRKL$R=d zyk6CM#p^}ZyIl8J-R*UMuKQ)(nRUn3eYx%vbvxH>UAKPSa&-&Uy;bL2oqctFuk%fv zId$HvGrZ0-b-LBLt4`xO73&nMlU@5l?ftbk)c&^i+}iKe9$x#I+TCj3Rl8B`gxW=F zXVyAbYj3T!wU*cVq}KRaLu)-*t8=YTtvacC~ZW_Eh_=+LCHBs=ZZhaJ7f4wXN2qT7_zbs@sbESoqrc@eH>8VPcE2UJbQ7NWU zPQ`N-cUAnQ;ujUCR2)&Uf5pxfQz}-k7*jDj;cUX639AwoBuq|tE#b+84hbz1sw5Om zxLM&ug>4mns4%y}yA@ul(7Qsr3Qa1MuaLjOmGXzmZz#XK{LJ#B%RgJbTlv=IYnLxk zK3wixxn1RcF1MiEq;kW`^(}W_xn|`O$`vSgwd|p?8_F&#JG1QQvIEO@EgLFZqijss ztTLy|Y%lXenYm@gmwBPgBW3O`Q@>1nnTRqMOYbTDOX&rrCzT#n`tj23OE)Q9u5{kg z8Kw4@T2pFqsSipGFZE=p2TC)hf#3sj9i7gy^E#^?n?=eearpCM$(>JDlOyig`F_AGBqjyKIik=reKKl9Sp3!$i z*NTpgz7;$k+#FmUoDqB@*gx1I*gRMvm^YYSY+tcoihW*eLa`T%JzT6!vD(FAie(l( zQFL?BuZzwo`bN>Gigqa4tZ4b7QAN{=>?!hdk@-d5E%JPk9z|LgsZk_YUh+qsAW;pqeetM5!F7bQBKH8u0PTpLfycFe^!n?yih3AIHhMx;} z4JU^yhYN-;=j_i}o%4Clgq#<0dgipwsgYAG=X&~-0Tv)|8tCA)X_-Pv`si)UwL zoygjpwJd9T)`+Ypvf5`g$|{v*S!Xl1XRgTnICFI7Gnt(-6EiDh=FLpIwddBVTk~#> zyEXV$w_B;Vs@^Jm>*~#eH`m&CGg8*hAdW7>`3H=elB z{zju4rEb`bv)8v@Uvd58>u+5jaJ}>O|ErlZkBh3_`}mO^w^7tEDY5hlS4~tjR8rD$ zNxg=OH?ET5O$`%`5)-><-oh>w89lj>fttB+yO?HH)W!15!Ys_N@9VG#1F~<5AaLJ@ zL96F^UeDi81I(P6Gw1xyZ~1;d-_QHxf;*G$*xzaH%}k*-P!8f>eV{2)vmRvCAa10mJ2N(wd`vNXpy%} zYjJAnZmww7H(zW1toiTFJDb-vdo{Z@+c!5iYeNRZ<}vt-2UsS{l@K0x0l|YcH8N8PhC}=vF^LNxVrc1_SC&l zx46!&PFB}dTT!d8{kHb=+KAfSwHs>})lRJ)S$o%9Zq}KvnLjs2n1jt5&5O)a%`$UW zO?i#J=G&Usnjo2%v3Gpff`_uZdTal!z+0R}xvWw`5Dnb0wZ7 zt|dcDI*ZGTjm3$@Ult!NeyezU@w#H~;;F?>#l1y!ML9)c(dD9;qKKl`iZ&OmD4JdL zc#&gKXJJL5vGB*j3x%H)9xU8hxUulr!Wo6*3vCKp3Q7ue1>Y5%D>z#4R>6*f^#zLy zrWHI=U|rChUy`rO|33d*{>S-$%MZ%;%YQb1M*gGucKL02raWWbPkEQ}KFvFvw>xiB z-ikcWyh(W@^15@)xjDIt+$*`UxgX^2&)t^0E_ZS6^xW~ecDe02%j z>q=H!)`wXKvVyYyoV6@#PS&I>SypdmLuPTNKJ&-SOPMD!k7R~s{xx%5rcdU~%*Qi_ zXZB>=&M3&xWh7=?$~cj6BqKEA<&5%7e zYD#KSYC>vU>PM-EQun03l7Q7eT6vrk3=+^6&>*nib z=qBmL=##%p7>(b@=Yn0B{zt9GMym3EPKwsxv^f>x%r)^=$c zH5HmXjX`r$^PT1^%^A%x&HI`|n!TDJ&5N4#niU#v%`DASjf-ZK##Yml+>%_AT%4Sl ztVzC+d@VUX`E>HJCo6(1;$DBf1QrP!xjmu5eITEBeK5@s8LgHi~s(wOApRiiKjXm?@@;dNEm4h(C)zi9d+nidV!0 zF;w~{r+%CQ>28u6=n?-+d zqqsrz71xSu#OK5n;xciG=p!x?y~PEhmpD)K6laSb;#1;u@sFarI8~e?J}EvSx{4FU z$3z$LQE|NJERGY$iep44akMx}l!+t75#n%hm^f5)6dgo+9(JNF4;voVJgf#DL&X2< zVcAF8Tl$vtZM%UZIdIIO9D6wD7|FRtaZV@BJ(e~&)0RhR(_^&Fl{P*}Tc^_IKhpN6 zxQ5wW%RH`W0oS&OYh1#$uHc&2aP7YI!AAOGGkp?B-)yIkcF|X_(`WnXyMy%MyY%Jz z^l3DGdy+nmqp#1?=Lz)vw~WD0jD>XS~I4@8QXD; zu`6Tk&X~_(?7f)-%b5$l%!y6RjqS{l*O)7BF=vi2ccPg?pEH*(GN-;_Zrxyx>6mNT z%sCTtuYoz(rRY=GFegVdHzzVjr!iN(n6t~7yBnCpfz0JS%;|9E_6N-I80Pv#=KOW$ zzLGVN$yzY6CYo3qeM(!_$ynCQ6xPjL){mTZyPi4`vpGj-X?||BbLMyQ*IDjGKn!Y#G0ODTjGuj@n;rsXa(`;MdH$4 z;?w)YsWZf@?}%Fl;#UQ6tV?4}Oq)P#n@x;cMXcLO%nKv-MH2(#iG??biTT9FW^Iqw zo>)1Fm^q)=xt#OpPP9eou@|C)U>LI(1gWUKe8UJYumgF?koU`3N!k46*tr zVs;L(yGegv??^14LQH>_*d9QP4`x&F)TDHzSdkMZk{cG1BmBt~`^Xue zkUPF6hoq28%!WG#TXM^j zGiBuVIpp|1lj{$V^W(_)kbvI zLG;!Ibe9qR)mi9>7MqPG+l)4gK%-qotL32CdW)RUZ{Fy*?dZ9q=(C8jo$1A5gH-5Q8~jY7vJqGv11yUItRZx^C-gV4Lj(7iX& zzx5SXXyKV?;>~E|NHp?yXyx+CyOkr*&I{4dL1^jYXle!8x~a+*ojnJ=9fq@zayk0^4Rrb$^tut<-d#N!4ex`N--D))MceDq_+2$J^!_4re=z$0bLs#c z^}t>8NNR&c)Cjw&6+WkC&{I2f)yk+N7E@2`p{|IdzA#c}^wc>~b1bFyc!L_`3u=)J zYLfoj&eSI>s8jY+uUw*T$*pg!x22AmM?JHHy5>0bjhZ^AqhUBT&ok6MyQzUrQwyb1 z6ZJNZqdruDWB9k+~n?oH~tcb-^3eZka!r>O(es0aJo z$5R`wrbY~>R=iBjSk`g3Lq-j`gjzC`n(_j*WnO1PW-A_IHPwLvDuJ*3s)VYhPcVDOO{gV1O=U(GIJL=*2 z)Wy4~kK?G5)4I*w0(J8o>gVm$(I=^=_0-ipJ!7e{S5RvopyvJ;wRh?LJNISO;!CK> zL#fR#Qll62w)PICW`Bm-{WWU%bJX(LeGPrK)b?J~_`9g}tZnfryznb_;akMvU!>WXZ3O&`Irtje@i$K5bLj9px^2hceJsZV3BwEd3Qwfi zuETBw9*GZL$s2ek=kZQ*?VIfF@lqDxsRZM##Nn}|IhY*;JeN6mFWd28PT<98@nr5f zj>eyn{>e(B0vq z@P?M)5$(k*I*(_RGoo>XEgsU-cu7HcN}u5^>G7DlM>^p*$?=``;Xhr(hsu*R$?Wi@ zyzr-X;!}NwU!}*lx;JVx9@bL4ti5o^{m8ZWHFX*j;v zGx%e>@yTNG%MAEtJ!8h;p~>;m_Ts61iMN(Hwr=bYytY|*Zd>u*qVeEmv?$cwTsUui)t&$JKJcW0u!NY8S%n?8HX?)FX_?yxAoHy`0Yaj1>d>sDg5`54-_@SrpMK$=N zZ4({vO6TI42I8GY;h`qtrB=FjxsJqJT`Ui(P~#yAyBr zQ#{(A@oHI$m2Jg6NO4Af;yyO{p${X>P58*Li!fQ^)bH4kBVffE;@u6SDk3NDg zeHni`2cP=>)KPfW^YN|&@vtNDvajN4=izPlx{b!?o{!%hi0}Om{O_;v!E^A#yWL0P zjnBm+-;7uO4xV{D-gzn>dix*k@Y84Dt8c(x55s3ajo+@scdwn+J#7R&{2csve|-6a z`19xR={5NEx2NBqF2ld~#K-r?&p(K-{{{ZO8lS&*#=RNC@cljT|2Mz^_QL~C!3A!> z2g;vneaaeM@CUfTbMS*;IKokQ!Z&b*EcimlOj}rkJIrAf>>(HiaTFGD6(*4Zn`rg0 zf>TU}S1f~D?0{eV1C9|7&(Oj(YG-xLa)5KV!#h^NJzj->yblNYCp<(47ctMiJKG*k zG8JC39B#55ei8vk`4XO@fUB6`D}8fDz*?rmTvowef?zQ3!D7zCWE8NOG8j#d=TLZ! z8{B3Y{N}H4oVVdQv2dM4_)ZR-r)6&6+~IH^clggTIM7yj&_TFR41DN1oG1-mR5$PL zJRA6tD;#MdJZU3bDFnXs0i5Xqyy+LXQvv*`_36H+hry%%0GC<}pYn%Oy#cTK5N>rI zew75r%7JG!dfoG~g>O9$=b8uaS_}8u0slG#2RjZAy9^go!N-c=WUcdi=R3g7T;XT) z;Anq>r@ahUI{;t%7|wP9-u7>}TL%2C8V=X9z!oMq0XF9Wqgw{6+XS=Q1G{?{hIbN{ z_b-^QHw_NB2p+f&F1QUo_$Hk2eR$#LaKo?Rhd1GfnefC) zxMGKQueTkX(HY+84tHDte_RcR41h=OhD#oVPkscaJPoh>8gBVB{L%==EP-b>z%_fG zv4U|r!8)ISd3wM;7sEi;!a@UJqOZb6!(gQE!Ag(8OwYkiufR}~V5xeTY94I062{sL zYrVh73hp`*{^|mUb%V!x!etl3XIH~%{|vAFE8KQB{5A}Z`z}29Be-r1eD@rj_cFZq z2e_{Y|4o4dXTyU_;lefW;bu5-*W%vAL*T|k;m2d($S&~Y$#CWA@MTXpvp2k14tHJ+ zf8GFx-UN@{3YQLoPrnAI-UqJ^hg-h`zm9}sABAThgKM9HZ=Zp4Ux0Ui1^2!J|Go|f z{}CR311_$Bk0-;)_3-jkxOpc0JQt2$08cN0tDE5Km2mcIczZ3}y&nGF2#0Tm$G5`e z+u`$_aQeIOdWqV14-kBbDuR(0R+YlnJU=w zEI3#V;jgXTkY@#*eC?8T+z}_eEeHubgoFg?4^RHmOMmIVejfh)+;Azq;)&np=4O-0 zl%1WeQmL+AzaAeS9}^Q36%`d89v%`B5*Qfh=jSJv%e}n3+}zw;TwJn!1g)2lAgg~$*g#9#223v!cIP+b)gVua`jAuL!3@Dt?T!gMzw@MizY zc(d2BY`4Qn&cX4rfN1+Q;evONDN0a<2?;^MF@GU^rLfIQSmP#mx(Mfke2xWrMFe<; z`b`g7Cq)FG4+)44^bPa% z3H0$?k17J0=TYxbFm@caMN(}`pxU{*W+X2W20iC4@X6W9u5l%4Gstj z^!4|ZuaSHEczbwyOm>@GpLn%6;e7hpSXIoi>rs*M5r<>LLZgC%4{r+$_4nWAyT)HG zU*qNF?cw1udGcfzm%Aa(?ZIQ(w~cA$CvZ%?|Co9|nb}unUL&hoDXWqXGx-cNc@Hc0 z8dmISpU;nnefD(wY&ZM#$@b~4_68SwgR?z1EoxRx;Rl3O z!jL|pPu4D2$+*i%W+%u589zNjzpS5a?mpt#fp;t)^bYL7YoV7th6u8|g0=KfAA9x7 zY%ROp7lz3A-UQ26Ebk2*m6w)hVX5yj&Tr%2%^SV^_E`?oE9)585M=jxuHYbj0}bmP zXb7k4<*mUdscF)0JA3xS$dBbs>00^Wn2weg(w60z zmSgvE_6Nrp|LZP;uO7V7E9(~Q2Q~)2?kF8nI+Aoz(!uE;fn96|-W+(ZQ99w^J_8rp zD;>b{med)&1Gn@J?(*w_qz|M~k}h$u$E3H0|7J&Nd+#8XGcZ06 z&T47R!%r>U-zPlsn|CbVw7ek=jx=%)FHq_?X`@d%yR?tA@n8?B6MNX<-outW7}N(d z?7>j>S|*OP*~tO!@;lHqmPsQGjWlx7n>GUtk+!5?wwSb*ez|Y?Y_M%3Ee#%=b<#eA zQ@}D$ENvb&xYJxTYj%zOX0FH7@D+K1^i*tFlxack)#%f(C2 z(n#HVumWxPOc>~YX_%$U8(8B~tEEn}!~|)G9*m;&dT`{V3zQBftw+nRWx_sOcfT&E lhwJ#^XAj4c2K35?4m88^=YQ^NX}e_*`v;fb!%JeK{0I4H8rA>+ literal 0 HcmV?d00001 diff --git a/example/makefile b/example/makefile new file mode 100644 index 0000000..dd10982 --- /dev/null +++ b/example/makefile @@ -0,0 +1,58 @@ +target_config = debug + +target_name = example + +acklib_incdir = ..\ack_lib +acklib_lib = ..\ack_lib\acklib.lib + +object_files = & + example.obj & + ackinfo.obj + +cc_flags_debug = /d2 /zp1 /4r /fp3 /j +cc_flags_release = /d1+ /zp1 /4r /fp3 /onetx /j +cc_flags = /mf /i=$(acklib_incdir) $(cc_flags_$(target_config)) + +link_flags_debug = debug all +link_flags_release = debug all +link_flags = $(link_flags_$(target_config)) + +asm_flags_debug = /zi +asm_flags_release = /zi +asm_flags = /m /ml $(asm_flags_$(target_config)) + +.NOCHECK +build : $(target_name).exe + +.c.obj: .AUTODEPEND + wcc386 $[. /zq $(cc_flags) + +.asm.obj: .AUTODEPEND + tasm $[. /t $(asm_flags) + +$(target_name).lnk: $(object_files) + %create $^@ + %append $^@ NAME $(target_name).exe + %append $^@ SYSTEM DOS4G + %append $^@ OPTION QUIET + %append $^@ OPTION STACK=16k + %append $^@ LIBRARY $(acklib_lib) + @for %i in ($(object_files)) do %append $^@ FILE %i + +$(target_name).exe: $(object_files) $(target_name).lnk + wlink $(link_flags) @$(target_name).lnk + +clean : .SYMBOLIC + del *.obj + del *.err + del $(target_name).exe + del $(target_name).lnk + +.NOCHECK +run : $(target_name).exe + $(target_name).exe + +.NOCHECK +debug : $(target_name).exe + wd /swap /trap=rsi $(target_name).exe +