From 30d76eada90f10ba643f270eabeee38e073128ad Mon Sep 17 00:00:00 2001 From: Luke Benstead Date: Tue, 13 Apr 2021 21:28:59 +0100 Subject: [PATCH] Fix texture issues --- CMakeLists.txt | 1 + GL/texture.c | 29 ++- samples/nehe06_4444twid/main.c | 270 +++++++++++++++++++++++ samples/nehe06_4444twid/romdisk/NeHe.tex | Bin 0 -> 131088 bytes 4 files changed, 292 insertions(+), 8 deletions(-) create mode 100644 samples/nehe06_4444twid/main.c create mode 100644 samples/nehe06_4444twid/romdisk/NeHe.tex diff --git a/CMakeLists.txt b/CMakeLists.txt index ffc6089..991435f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -130,6 +130,7 @@ gen_sample(nehe04 samples/nehe04/main.c) gen_sample(nehe05 samples/nehe05/main.c) gen_sample(nehe06 samples/nehe06/main.c) gen_sample(nehe06_vq samples/nehe06_vq/main.c) +gen_sample(nehe06_4444twid samples/nehe06_4444twid/main.c) gen_sample(ortho2d samples/ortho2d/main.c) gen_sample(paletted samples/paletted/main.c) gen_sample(paletted_pcx samples/paletted_pcx/main.c) diff --git a/GL/texture.c b/GL/texture.c index fca7c07..6c5260a 100644 --- a/GL/texture.c +++ b/GL/texture.c @@ -777,8 +777,19 @@ static GLint _cleanInternalFormat(GLint internalFormat) { } case GL_RED: case GL_RGB: - /* No alpha? Return RGB565 which is the best we can do without using palettes */ - return GPU_TXRFMT_RGB565 | GPU_TXRFMT_NONTWIDDLED; + switch(type) { + case GL_UNSIGNED_SHORT_5_6_5_TWID_KOS: + return GPU_TXRFMT_RGB565 | GPU_TXRFMT_TWIDDLED; + case GL_COMPRESSED_RGB_565_VQ_KOS: + case GL_COMPRESSED_RGB_565_VQ_MIPMAP_KOS: + return GPU_TXRFMT_RGB565 | GPU_TXRFMT_NONTWIDDLED | GPU_TXRFMT_VQ_ENABLE; + case GL_COMPRESSED_RGB_565_VQ_TWID_KOS: + case GL_COMPRESSED_RGB_565_VQ_MIPMAP_TWID_KOS: + return GPU_TXRFMT_RGB565 | GPU_TXRFMT_TWIDDLED | GPU_TXRFMT_VQ_ENABLE; + default: + return GPU_TXRFMT_RGB565 | GPU_TXRFMT_NONTWIDDLED; + } + break; /* Compressed and twiddled versions */ case GL_UNSIGNED_SHORT_5_6_5_TWID_KOS: return GPU_TXRFMT_RGB565 | GPU_TXRFMT_TWIDDLED; @@ -956,6 +967,7 @@ static GLboolean _isSupportedFormat(GLenum format) { case GL_RGBA: case GL_BGRA: case GL_COLOR_INDEX: + case GL_UNSIGNED_SHORT_4_4_4_4_REV_TWID_KOS: return GL_TRUE; default: return GL_FALSE; @@ -1022,7 +1034,7 @@ void _glAllocateSpaceForMipmaps(TextureObject* active) { #define STRINGIFY(x) #x #define TOSTRING(x) STRINGIFY(x) -#define INFO_MSG(x) printf("%s %s\n", __FILE__ ":" TOSTRING(__LINE__), x) +#define INFO_MSG(x) fprintf(stderr, "%s:%s > %s\n", __FILE__, TOSTRING(__LINE__), x) void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLint border, @@ -1030,7 +1042,6 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat, TRACE(); - if(target != GL_TEXTURE_2D) { INFO_MSG(""); _glKosThrowError(GL_INVALID_ENUM, __func__); @@ -1038,7 +1049,7 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat, if(format != GL_COLOR_INDEX) { if(!_isSupportedFormat(format)) { - INFO_MSG(""); + INFO_MSG("Unsupported format"); _glKosThrowError(GL_INVALID_ENUM, __func__); } @@ -1090,8 +1101,8 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat, } if(level > 0 && width != height) { - INFO_MSG(""); - fprintf(stderr, "[GL ERROR] Mipmaps cannot be supported on non-square textures\n"); + INFO_MSG("Tried to set non-square texture as a mipmap level"); + printf("[GL ERROR] Mipmaps cannot be supported on non-square textures\n"); _glKosThrowError(GL_INVALID_OPERATION, __func__); } @@ -1101,7 +1112,7 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat, } if(!TEXTURE_UNITS[ACTIVE_TEXTURE]) { - INFO_MSG(""); + INFO_MSG("Called glTexImage2D on unbound texture"); _glKosThrowError(GL_INVALID_OPERATION, __func__); } @@ -1239,6 +1250,7 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat, ); if(!convert) { + INFO_MSG("Couldn't find conversion\n"); _glKosThrowError(GL_INVALID_OPERATION, __func__); return; } @@ -1247,6 +1259,7 @@ void APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalFormat, assert(stride > -1); if(stride == -1) { + INFO_MSG("Stride was not detected\n"); _glKosThrowError(GL_INVALID_OPERATION, __func__); return; } diff --git a/samples/nehe06_4444twid/main.c b/samples/nehe06_4444twid/main.c new file mode 100644 index 0000000..94125ae --- /dev/null +++ b/samples/nehe06_4444twid/main.c @@ -0,0 +1,270 @@ +#include +#include +#include + +#include "GL/gl.h" +#include "GL/glu.h" +#include "GL/glkos.h" +#include "GL/glext.h" + +#ifdef __DREAMCAST__ +#define IMG_PATH "/rd/NeHe.tex" +extern uint8 romdisk[]; +KOS_INIT_ROMDISK(romdisk); +#else +#define IMG_PATH "samples/nehe06_4444twid/romdisk/NeHe.tex" +#endif + +/* floats for x rotation, y rotation, z rotation */ +float xrot, yrot, zrot; + +/* storage for one texture */ +GLuint texture[1]; + +/* Image type - contains height, width, and data */ +struct Image { + unsigned long sizeX; + unsigned long sizeY; + char *data; + GLenum format; + GLenum internal_format; + GLenum type; + GLboolean mipmapped; + unsigned int dataSize; +}; + +typedef struct Image Image; + +int ImageLoad(char *filename, Image *image) { + FILE* file = NULL; + + // make sure the file is there. + if ((file = fopen(filename, "rb")) == NULL) + { + printf("File Not Found : %s\n",filename); + return 0; + } + + struct { + char id[4]; // 'DTEX' + GLshort width; + GLshort height; + GLint type; + GLint size; + } header; + + fread(&header, sizeof(header), 1, file); + + GLboolean twiddled = (header.type & (1 << 25)) < 1; + GLboolean compressed = (header.type & (1 << 29)) > 0; + GLboolean mipmapped = (header.type & (1 << 30)) > 0; + GLboolean strided = (header.type & (1 << 24)) > 0; + GLuint format = (header.type >> 27) & 0b111; + + image->data = (char *) malloc (header.size); + image->sizeX = header.width; + image->sizeY = header.height; + image->dataSize = header.size; + + GLuint expected = 2 * header.width * header.height; + GLuint ratio = (GLuint) (((GLfloat) expected) / ((GLfloat) header.size)); + + fread(image->data, image->dataSize, 1, file); + fclose(file); + + printf("%d\n", compressed); + printf("%d\n", twiddled); + printf("%d\n", mipmapped); + + image->format = (format == 1) ? GL_RGB : GL_BGRA; + image->internal_format = (format == 1) ? GL_RGB : GL_RGBA; + + GLuint COMPRESSED_MASK = 4; + GLuint TWIDDLED_MASK = 2; + GLuint MIPMAPPED_MASK = 1; + + GLuint lookup[8] = {0}; + + switch(format) { + case 0: + lookup[COMPRESSED_MASK] = GL_COMPRESSED_ARGB_1555_VQ_KOS; + lookup[COMPRESSED_MASK | TWIDDLED_MASK] = GL_COMPRESSED_ARGB_1555_VQ_TWID_KOS; + lookup[COMPRESSED_MASK | MIPMAPPED_MASK] = GL_COMPRESSED_ARGB_1555_VQ_MIPMAP_KOS; + lookup[COMPRESSED_MASK | TWIDDLED_MASK | MIPMAPPED_MASK] = GL_COMPRESSED_ARGB_1555_VQ_MIPMAP_TWID_KOS; + lookup[TWIDDLED_MASK] = GL_UNSIGNED_SHORT_1_5_5_5_REV_TWID_KOS; + lookup[TWIDDLED_MASK | MIPMAPPED_MASK] = GL_UNSIGNED_SHORT_1_5_5_5_REV_TWID_KOS; + lookup[0] = GL_UNSIGNED_SHORT_1_5_5_5_REV; + break; + case 1: + lookup[COMPRESSED_MASK] = GL_COMPRESSED_RGB_565_VQ_KOS; + lookup[COMPRESSED_MASK | TWIDDLED_MASK] = GL_COMPRESSED_RGB_565_VQ_TWID_KOS; + lookup[COMPRESSED_MASK | MIPMAPPED_MASK] = GL_COMPRESSED_RGB_565_VQ_MIPMAP_KOS; + lookup[COMPRESSED_MASK | TWIDDLED_MASK | MIPMAPPED_MASK] = GL_COMPRESSED_RGB_565_VQ_MIPMAP_TWID_KOS; + lookup[TWIDDLED_MASK] = GL_UNSIGNED_SHORT_5_6_5_TWID_KOS; + lookup[TWIDDLED_MASK | MIPMAPPED_MASK] = GL_UNSIGNED_SHORT_5_6_5_TWID_KOS; + lookup[0] = GL_UNSIGNED_SHORT_5_6_5; + break; + case 2: + lookup[COMPRESSED_MASK] = GL_COMPRESSED_ARGB_4444_VQ_KOS; + lookup[COMPRESSED_MASK | TWIDDLED_MASK] = GL_COMPRESSED_ARGB_4444_VQ_TWID_KOS; + lookup[COMPRESSED_MASK | MIPMAPPED_MASK] = GL_COMPRESSED_ARGB_4444_VQ_MIPMAP_KOS; + lookup[COMPRESSED_MASK | TWIDDLED_MASK | MIPMAPPED_MASK] = GL_COMPRESSED_ARGB_4444_VQ_MIPMAP_TWID_KOS; + lookup[TWIDDLED_MASK] = GL_UNSIGNED_SHORT_4_4_4_4_REV_TWID_KOS; + lookup[TWIDDLED_MASK | MIPMAPPED_MASK] = GL_UNSIGNED_SHORT_4_4_4_4_REV_TWID_KOS; + lookup[0] = GL_UNSIGNED_SHORT_4_4_4_4_REV; + break; + default: + printf("[ERROR] Unknown format\n"); + } + + image->type = lookup[(compressed << 2) | (twiddled << 1) | mipmapped]; + + printf("%d\n", image->type); + + assert(image->type); + + // we're done. + return 1; +} + +// Load Bitmaps And Convert To Textures +void LoadGLTextures() { + // Load Texture + Image *image1; + + // allocate space for texture + image1 = (Image *) malloc(sizeof(Image)); + if (image1 == NULL) { + printf("Error allocating space for image"); + exit(0); + } + + if (!ImageLoad(IMG_PATH, image1)) { + exit(1); + } + + // Create Texture + glGenTextures(1, &texture[0]); + glBindTexture(GL_TEXTURE_2D, texture[0]); // 2d texture (x and y size) + + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); // scale linearly when image bigger than texture + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); // scale linearly when image smalled than texture + + // 2d texture, level of detail 0 (normal), 3 components (red, green, blue), x size from image, y size from image, + // border 0 (normal), rgb color data, unsigned byte data, and finally the data itself. + glTexImage2D( + GL_TEXTURE_2D, 0, image1->internal_format, image1->sizeX, image1->sizeY, 0, + image1->format, image1->type, image1->data + ); +}; + +/* A general OpenGL initialization function. Sets all of the initial parameters. */ +void InitGL(int Width, int Height) // We call this right after our OpenGL window is created. +{ + LoadGLTextures(); + glEnable(GL_TEXTURE_2D); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // This Will Clear The Background Color To Black + glClearDepth(1.0); // Enables Clearing Of The Depth Buffer + glDepthFunc(GL_LESS); // The Type Of Depth Test To Do + glEnable(GL_DEPTH_TEST); // Enables Depth Testing + glShadeModel(GL_SMOOTH); // Enables Smooth Color Shading + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); // Reset The Projection Matrix + + gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f); // Calculate The Aspect Ratio Of The Window + + glMatrixMode(GL_MODELVIEW); +} + +/* The function called when our window is resized (which shouldn't happen, because we're fullscreen) */ +void ReSizeGLScene(int Width, int Height) +{ + if (Height == 0) // Prevent A Divide By Zero If The Window Is Too Small + Height = 1; + + glViewport(0, 0, Width, Height); // Reset The Current Viewport And Perspective Transformation + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f); + glMatrixMode(GL_MODELVIEW); +} + + +/* The main drawing function. */ +void DrawGLScene() +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer + glLoadIdentity(); // Reset The View + + glTranslatef(0.0f,0.0f,-5.0f); // move 5 units into the screen. + + glRotatef(xrot,1.0f,0.0f,0.0f); // Rotate On The X Axis + glRotatef(yrot,0.0f,1.0f,0.0f); // Rotate On The Y Axis + glRotatef(zrot,0.0f,0.0f,1.0f); // Rotate On The Z Axis + + glBindTexture(GL_TEXTURE_2D, texture[0]); // choose the texture to use. + + glBegin(GL_QUADS); // begin drawing a cube + + // Front Face (note that the texture's corners have to match the quad's corners) + glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); // Bottom Left Of The Texture and Quad + glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f); // Bottom Right Of The Texture and Quad + glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); // Top Right Of The Texture and Quad + glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); // Top Left Of The Texture and Quad + + // Back Face + glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); // Bottom Right Of The Texture and Quad + glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); // Top Right Of The Texture and Quad + glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); // Top Left Of The Texture and Quad + glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f); // Bottom Left Of The Texture and Quad + + // Top Face + glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); // Top Left Of The Texture and Quad + glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 1.0f); // Bottom Left Of The Texture and Quad + glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, 1.0f, 1.0f); // Bottom Right Of The Texture and Quad + glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); // Top Right Of The Texture and Quad + + // Bottom Face + glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f); // Top Right Of The Texture and Quad + glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, -1.0f, -1.0f); // Top Left Of The Texture and Quad + glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f); // Bottom Left Of The Texture and Quad + glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); // Bottom Right Of The Texture and Quad + + // Right face + glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f); // Bottom Right Of The Texture and Quad + glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, -1.0f); // Top Right Of The Texture and Quad + glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); // Top Left Of The Texture and Quad + glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 1.0f); // Bottom Left Of The Texture and Quad + + // Left Face + glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f); // Bottom Left Of The Texture and Quad + glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 1.0f); // Bottom Right Of The Texture and Quad + glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); // Top Right Of The Texture and Quad + glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f, -1.0f); // Top Left Of The Texture and Quad + + glEnd(); // done with the polygon. + + xrot+=1.5f; // X Axis Rotation + yrot+=1.5f; // Y Axis Rotation + zrot+=1.5f; // Z Axis Rotation + // + // swap buffers to display, since we're double buffered. + glKosSwapBuffers(); +} + +int main(int argc, char **argv) +{ + glKosInit(); + + InitGL(640, 480); + ReSizeGLScene(640, 480); + + while(1) { + DrawGLScene(); + } + + return 0; +} diff --git a/samples/nehe06_4444twid/romdisk/NeHe.tex b/samples/nehe06_4444twid/romdisk/NeHe.tex new file mode 100644 index 0000000000000000000000000000000000000000..a5479307a714a6278caaa27779d10067700bbe3e GIT binary patch literal 131088 zcmeI5Yg!x0vaZ2<0)QuAgx3ICg7tqJ!32!p44@HS6KLoWtnM>|y@qf`rz&0OfBSrI zhCWp(ktpFZrn_C#Bcd`gGcq#r78!Y|;nl_e+1uB%w|B6&_ipch)8F0%ur~q5kN0pJ zAJBNir{UM*JKQ!{rMr#(^XYG+yDPpu|Lgh9>FvtLTZMaj`9EL2P5ix;-2N`<=Jhpq zH{~-ApSzplzqNnPZ|-j5FAtx)o8ou=odn)e0!{sElYd*@o9H+Bw@v>?kKZKUCjYkb zYog!e-!}cfM*PEKZ_+D!~IE#8vk4>!x^**L(LCYytPViSzfK#}Sr&o^VZfS(ZCwK%8Er$!f9q)U?Twl%IP5k8Hb9Ynx zxAxEZ&D~A><>7O8Q~b`qlfYX_Ag`~vyNS0veC}?F|JMFFzqz}KzdU^IZi?Ue|9vHJ zI5}Kt=k;73O^y=2H|cHkuZR7bchfb@X&7&q`~Ns@Yhizd9EUzyaf%K(npf`U-w0a| zk4_s}Y0#~xg&rI8OEgt9*-B2KpI2!?lTdpTLWO?J8@lgkj!yp?`Ym*s4OjX$sgSB+ z=-x5YATKfZ4GkO@als+M;GXvg7qSUz^_+$V4<=HFiscGr>-WeZ-25jM>;Fy}e9Rz% zlPH5oo%fJC)QKH*D^BWf5kKS%-WGs*n7_k2wTxfn#kCH}G(E&Y{+^vt+EE_$+S5ek zCI0SL4fD9h8|MD&?%*6=$q98SYR7u0y32HX8fVC97#Q7DjC%+;BFUQ~#p(!|(8$ zr0@Feo|f_oT=Wn1@}u@r*5C+_E6R%U0}m$ZY=nUlea}d}4`sccy}Qg;*mCjXbFmxqr&F64;BL$c8uy58n- z>UALM1o3$zq|42eqefLe)Hg~p>R(Q~b9WMW8wu2Fb;SX-mA*XM0yR8(%c$|2`;;nn z^+qdL*AK#vRHNO5JJPFTDjJ*KqIJ1F;fnDmdiBk8Hs^E`_3wcTxgg&dEhEk7C8AG> z5z~0WN67VjfM3TD1GNyAg!kUwaLG&gqr9#`L|8~M~~km-zNXI@@t~s
  • ^ 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
  • ^ zA3c7Pe4G5+%CCujlmF)Qt()2x9V_%KW1fe3{BWbs^2B_X^Q_iz(O}S4uO7AQMEXAZ z59i-?f_-`Z9Sw-^p+~|EdMcU}znB9MmN;oIio$E(m39(cae_*^-t!!P58u$gtN&O% z`1w(ew7W(24r$DsdDhON!A*%*{AdG z`d>ePZv8sAjJa-bhR)8sHO7a}RuWcU|5eCS>;@^O>7|`c(#MUhV2YbkAZ5}f zY_gijg?^0|f6hFV`6cI8XR<_T2E`njySubkba`$xsD>nw4fYkj7<@N-(2Wz3dYtt` zF5Jj4&~Ce%*~#=*%~d5w?VuWz|MSOb`5*ma-<>)2zB{{zvx^yf?S|9e9)Hs=yVGgx zZahu$j<_#rrKa1#ua`hm|JvmL^(jZpCi+eOZPWkJ<2T8-$-k}qn&{X4u@PY1O#P_( zJnSX(fShgRY%F;A0b*4Ek8PN{9Qnrj(jJo_HVH;0`cCXO+}VhQ2HPuVrs-D+541b& zRb@n@zZJy7qdrqH7~R8i0iOPu`+s#yquzKldMGuxz%GKVige)*`jLAZj(Q3UOK^$_VRKDLNaA6N83v0HduR6dKzUoGkq;P@?<~??um&f8Hoq^Q}SeHX!ct=FMF-=kdT}O01}tI=YDc6DcROlzJ^J6A+#hx9N}g6l)t1xy%IKb3U1_0 zQboRKDQY$18vTH{l8a;#YaHyRjyjm+m*kq{w>(dr=qfGBBiTAtqjU>yajO0M=G!pN zIoO5H%SnR4!t!I+{t@!iK7E}b{)77ho|7MGvwlHaSH09qfwU&QaZ3qq+ADX9>R!@h zL&Y|W8w(^hRoQk^J7Vpo;;MRM%>fsBP=&4D)Pv~urR(WH{+H7W-G6%~olsg~ajkO> zcUsr!$&S{`5*`#5vrC6LH>VHJs3X{_DW|adYb#lGOhNe`(?CRMY~NkPvweEik5$>9*lD@ z$evbkp?&>o>!r>=>3j$G<{VCF%g$3Bl82a+#VoAu$2+;@F`n@P{q>~$pVWTu7x(FQ zi+kPnMi|=rbuFcDt;^D`IqL#X-2EfzC^gn6<8GhCZR!!}@8wf4{#56mqIabgq1m%u z%3Oi@9GX0mP3NDqE}|8I7oLCGrT%gLNpobKf7)L=|8${#_GH8PC)!Z-kS>7^b`tn2 zNTBWh)wc29T1IX8ZyW!u^WUZaV@sfI{cRint)<_V|LyUayEu0-PYg_&($qZ+zgGS78T@6#!WrlnVAms;mRn){~o<9ue)Lqi)48C05S#P(MwaK$VdZo@_#X-BxG|HODc z4E%PQeb9|#@k^2MAW&c5pw zSMA(l2BI4&i}Cy{oqyLHWqzSE!Pt04>HPb#G~1I>C*yTy9IZ8;FA8%fE4SUuib#vw zMm5tcKIm3rPAYQ`V2>3I&1N){SUX3e^$sf**8?z*sVz34zx@3Q?hfQ)oV63 zA8KbK>rkJ>H#^U?t5P&ik*n_by3@&h__~)K9`jw%N@)(K*Yo@3jfrvE$c_9zX zH(230(JV-(=f&MMvn;(0(rtdsg4Sa==K*zpfZE48u5-Pu1nTzHO`J6OZ;JC0Toe5! z|CglIg?%c4Ciyn`Kc)CGOcVVk|CgoKh3+KqJtVMQf88zhw()mM<@G|f<-cwG*UQ=8 yjdD}}+T`C>9!>O{{M)AgI`P}q-?s60&sCFroBTJYv^)Qs=~wZ?pa1{+zyBYjv