diff --git a/Makefile b/Makefile index cf51353..ef0f2d3 100644 --- a/Makefile +++ b/Makefile @@ -11,12 +11,24 @@ geometry/%.hpp: geometry/%.obj PYTHONPATH=regs/gen python tools/obj_to_cpp.py $< > $@.tmp mv $@.tmp $@ -%.data.h: +%.data.h: %.data $(BUILD_BINARY_H) -%.data.pal.h: +%.data.pal.h: %.data.pal $(BUILD_BINARY_H) +%.alpha.h: %.alpha + $(BUILD_BINARY_H) + +%.alpha.o: %.alpha + $(BUILD_BINARY_O) + +%.alpha.pal.h: %.alpha.pal + $(BUILD_BINARY_H) + +%.alpha.pal.o: %.alpha.pal + $(BUILD_BINARY_O) + %.vq.h: %.vq $(BUILD_BINARY_H) diff --git a/client.py b/client.py index 6ee3ef6..59d58e6 100644 --- a/client.py +++ b/client.py @@ -34,7 +34,7 @@ def symmetric(ser, b): l = [] mem = memoryview(b) i = 0 - chunk_size = 8 + chunk_size = 128 while i < len(b): if i % 1024 == 0: diff --git a/common.mk b/common.mk index 4f833d9..b5fd50c 100644 --- a/common.mk +++ b/common.mk @@ -2,7 +2,7 @@ MAKEFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST))) DIR := $(dir $(MAKEFILE_PATH)) LIB ?= . -OPT ?= -O0 +OPT ?= -Os GENERATED ?= AARCH = --isa=sh4 --little diff --git a/example/example.mk b/example/example.mk index fcf269d..3799c84 100644 --- a/example/example.mk +++ b/example/example.mk @@ -608,3 +608,19 @@ SHEIK_OBJ = \ example/sheik.elf: LDSCRIPT = $(LIB)/alt.lds example/sheik.elf: $(START_OBJ) $(SHEIK_OBJ) + +SHEIK_VQ_OBJ = \ + example/sheik_vq.o \ + holly/core.o \ + holly/region_array.o \ + holly/background.o \ + holly/ta_fifo_polygon_converter.o \ + holly/video_output.o \ + sh7091/serial.o \ + model/sheik/sheik_00.alpha.o \ + model/sheik/sheik_00.alpha.pal.o \ + model/sheik/sheik_00.vq.o \ + model/sheik/xc_eye01.data.o + +example/sheik_vq.elf: LDSCRIPT = $(LIB)/alt.lds +example/sheik_vq.elf: $(START_OBJ) $(SHEIK_VQ_OBJ) diff --git a/example/serial_transfer.cpp b/example/serial_transfer.cpp index 831ac40..f0d2a38 100644 --- a/example/serial_transfer.cpp +++ b/example/serial_transfer.cpp @@ -10,7 +10,7 @@ void main() __attribute__((section(".text.main"))); void main() { - serial::init(1); + serial::init(12); load_init(); while (1) { diff --git a/example/sheik.cpp b/example/sheik.cpp index d1bc778..933b889 100644 --- a/example/sheik.cpp +++ b/example/sheik.cpp @@ -144,23 +144,6 @@ void texture_init() } } -void dump_ram(const volatile uint32_t * mem, const uint32_t len) -{ - uint32_t sum = 0; - for (uint32_t i = 0; i < len; i++) { - uint32_t m = mem[i]; - for (int j = 0; j < 4; j++) { - uint8_t n = ((uint8_t*)&m)[j]; - sum += n; - serial::hexlify(n); - } - if ((i & 0xf) == 0xf) - serial::character('\n'); - } - serial::character('\n'); - serial::integer(sum); -} - void main() { serial::init(4); diff --git a/example/sheik_vq.cpp b/example/sheik_vq.cpp new file mode 100644 index 0000000..d8090da --- /dev/null +++ b/example/sheik_vq.cpp @@ -0,0 +1,345 @@ +#include + +#include "holly/isp_tsp.hpp" +#include "holly/ta_parameter.hpp" +#include "holly/ta_global_parameter.hpp" +#include "holly/ta_vertex_parameter.hpp" +#include "holly/ta_bits.hpp" +#include "holly/ta_fifo_polygon_converter.hpp" +#include "holly/holly.hpp" +#include "holly/core_bits.hpp" +#include "holly/core.hpp" +#include "holly/region_array.hpp" +#include "holly/background.hpp" +#include "holly/video_output.hpp" +#include "holly/texture_memory_alloc2.hpp" +#include "sh7091/store_queue.hpp" +#include "sh7091/serial.hpp" + +#include "systembus.hpp" +#include "systembus_bits.hpp" + +#include "twiddle.hpp" + +#include "math/vec2.hpp" + +const int _binary_model_sheik_sheik_00_data_start = 0; +const int _binary_model_sheik_sheik_00_data_size = 0; + +#include "model/sheik/xc_eye01.data.h" +#include "model/sheik/sheik_00.vq.h" +#include "model/sheik/sheik_00.alpha.h" +#include "model/sheik/sheik_00.alpha.h" +#include "model/sheik/sheik_00.alpha.pal.h" +#include "model/sheik/material.h" +#include "model/sheik/model.h" + +static uint32_t body_vq_offset; +static uint32_t body_alpha_offset; +static uint32_t eyes_offset; + +void transfer_scene(float theta) +{ + const uint32_t parameter_control_word = para_control::para_type::polygon_or_modifier_volume + | para_control::list_type::translucent + | obj_control::col_type::intensity_mode_1 + | obj_control::texture + | obj_control::gouraud; + + const uint32_t isp_tsp_instruction_word = isp_tsp_instruction_word::depth_compare_mode::greater + | isp_tsp_instruction_word::culling_mode::cull_if_negative; + + uint32_t tsp_instruction_word[4]; + uint32_t texture_control_word[4]; + { + struct material_descriptor * mat = &material[body]; + tsp_instruction_word[0] = tsp_instruction_word::src_alpha_instr::one + | tsp_instruction_word::dst_alpha_instr::zero + | tsp_instruction_word::dst_select::secondary_accumulation_buffer + | tsp_instruction_word::fog_control::no_fog + | tsp_instruction_word::texture_shading_instruction::modulate + | tsp_instruction_word::texture_u_size::from_int(mat->pixel.width) + | tsp_instruction_word::texture_v_size::from_int(mat->pixel.height); + + uint32_t texture_address = texture_memory_alloc::texture.start + body_alpha_offset; + texture_control_word[0] = texture_control_word::pixel_format::_4bpp_palette + | texture_control_word::scan_order::twiddled + | texture_control_word::texture_address(texture_address / 8); + } + { + struct material_descriptor * mat = &material[body]; + tsp_instruction_word[1] = tsp_instruction_word::src_alpha_instr::dst_alpha + | tsp_instruction_word::dst_alpha_instr::zero + | tsp_instruction_word::dst_select::secondary_accumulation_buffer + | tsp_instruction_word::fog_control::no_fog + | tsp_instruction_word::texture_shading_instruction::modulate + | tsp_instruction_word::texture_u_size::from_int(mat->pixel.width) + | tsp_instruction_word::texture_v_size::from_int(mat->pixel.height); + + uint32_t texture_address = texture_memory_alloc::texture.start + body_vq_offset; + texture_control_word[1] = texture_control_word::vq_compressed + | texture_control_word::pixel_format::_565 + | texture_control_word::scan_order::twiddled + | texture_control_word::texture_address(texture_address / 8); + } + { + tsp_instruction_word[2] = tsp_instruction_word::src_alpha_instr::src_alpha + | tsp_instruction_word::dst_alpha_instr::inverse_src_alpha + | tsp_instruction_word::src_select::secondary_accumulation_buffer + | tsp_instruction_word::fog_control::no_fog; + texture_control_word[2] = 0; + } + { + struct material_descriptor * mat = &material[eyes]; + tsp_instruction_word[3] = tsp_instruction_word::src_alpha_instr::one + | tsp_instruction_word::dst_alpha_instr::zero + | tsp_instruction_word::src_select::primary_accumulation_buffer + | tsp_instruction_word::fog_control::no_fog + | tsp_instruction_word::texture_shading_instruction::modulate + | tsp_instruction_word::texture_u_size::from_int(mat->pixel.width) + | tsp_instruction_word::texture_v_size::from_int(mat->pixel.height); + + uint32_t texture_address = texture_memory_alloc::texture.start + eyes_offset; + texture_control_word[3] = texture_control_word::pixel_format::_1555 + | texture_control_word::scan_order::non_twiddled + | texture_control_word::texture_address(texture_address / 8); + } + + + for (int j = 0; j < sheik_model.object_count; j++) { + struct object * object = sheik_model.object[j]; + + for (int i = 0; i < object->triangle_count; i++) { + float x[3]; + float y[3]; + float z[3]; + float u[3]; + float v[3]; + + for (int k = 0; k < 3; k++) { + int position_ix = object->triangle[i].v[k].position; + float x0 = sheik_model.position[position_ix].x; + float y0 = sheik_model.position[position_ix].y; + float z0 = sheik_model.position[position_ix].z; + + float x1 = x0 * cos(theta) - z0 * sin(theta); + float y1 = y0 - 3; + float z1 = x0 * sin(theta) + z0 * cos(theta); + + float x2 = x1; + float y2 = -y1; + float z2 = z1 + 3.5; + + float x3 = x2 / z2; + float y3 = y2 / z2; + float z3 = z2; + + x[k] = x3 * 240 + 320; + y[k] = y3 * 240 + 240; + z[k] = 1 / z3; + + int texture_ix = object->triangle[i].v[k].texture; + u[k] = sheik_model.texture[texture_ix].u; + v[k] = 1.0 - sheik_model.texture[texture_ix].v; + } + + for (int pass = 0; pass < 3; pass++) { + if (object->material == eyes) { + pass = 3; + } + + *reinterpret_cast(store_queue) = + ta_global_parameter::polygon_type_1(parameter_control_word, + isp_tsp_instruction_word, + tsp_instruction_word[pass], + texture_control_word[pass], + 1.0, // face color alpha + 1.0, // face color r + 1.0, // face color g + 1.0 // face color b + ); + sq_transfer_32byte(ta_fifo_polygon_converter); + + for (int k = 0; k < 3; k++) { + bool end_of_strip = k == 2; + + *reinterpret_cast(store_queue) = + ta_vertex_parameter::polygon_type_7(polygon_vertex_parameter_control_word(end_of_strip), + x[k], y[k], z[k], + u[k], v[k], + 1.0, // base intensity + 1.0 // offset intensity + ); + sq_transfer_32byte(ta_fifo_polygon_converter); + } + } + } + } + + *reinterpret_cast(store_queue) = + ta_global_parameter::end_of_list(para_control::para_type::end_of_list); + sq_transfer_32byte(ta_fifo_polygon_converter); +} + +template +inline void copy(T * dst, const T * src, const int32_t n) noexcept +{ + int32_t n_t = n / (sizeof (T)); + while (n_t > 0) { + *dst++ = *src++; + n_t--; + } +} + +void texture_init() +{ + int offset = 0; + + { + body_alpha_offset = offset; + + uint32_t * start = (uint32_t *)&_binary_model_sheik_sheik_00_alpha_start; + int size = (int)&_binary_model_sheik_sheik_00_alpha_size; + copy(&texture_memory64[(texture_memory_alloc::texture.start + offset) / 4], + start, + size); + offset += size; + } + + { + body_vq_offset = offset; + + uint32_t * start = (uint32_t *)&_binary_model_sheik_sheik_00_vq_start; + int size = (int)&_binary_model_sheik_sheik_00_vq_size; + copy(&texture_memory64[(texture_memory_alloc::texture.start + offset) / 4], + start, + size); + offset += size; + } + + { + eyes_offset = offset; + uint32_t * start = (uint32_t *)&_binary_model_sheik_xc_eye01_data_start; + int size = (int)&_binary_model_sheik_xc_eye01_data_size; + copy(&texture_memory64[(texture_memory_alloc::texture.start + offset) / 4], + start, + size); + offset += size; + } + + { + uint16_t * start = (uint16_t *)&_binary_model_sheik_sheik_00_alpha_pal_start; + int size = (int)&_binary_model_sheik_sheik_00_alpha_pal_size; + for (int i = 0; i < size / 2; i++) { + holly.PALETTE_RAM[i] = start[i]; + } + holly.PAL_RAM_CTRL = pal_ram_ctrl::pixel_format::argb4444; + } + +} + +void main() +{ + serial::init(4); + constexpr uint32_t ta_alloc = ta_alloc_ctrl::pt_opb::no_list + | ta_alloc_ctrl::tm_opb::no_list + | ta_alloc_ctrl::t_opb::_32x4byte + | ta_alloc_ctrl::om_opb::no_list + | ta_alloc_ctrl::o_opb::no_list + ; + + constexpr int render_passes = 1; + constexpr struct opb_size opb_size[render_passes] = { + { + .opaque = 0, + .opaque_modifier = 0, + .translucent = 32 * 4, + .translucent_modifier = 0, + .punch_through = 0 + } + }; + + holly.SOFTRESET = softreset::pipeline_soft_reset + | softreset::ta_soft_reset; + holly.SOFTRESET = 0; + + core_init(); + + video_output::set_mode_vga(); + + constexpr int framebuffer_width = 640; + constexpr int framebuffer_height = 480; + constexpr int tile_width = framebuffer_width / 32; + constexpr int tile_height = framebuffer_height / 32; + + region_array_multipass(tile_width, + tile_height, + opb_size, + render_passes, + texture_memory_alloc::region_array[0].start, + texture_memory_alloc::object_list[0].start); + region_array_multipass(tile_width, + tile_height, + opb_size, + render_passes, + texture_memory_alloc::region_array[1].start, + texture_memory_alloc::object_list[1].start); + + background_parameter2(texture_memory_alloc::background[0].start, + 0x00220033); + background_parameter2(texture_memory_alloc::background[1].start, + 0x00220033); + + texture_init(); + + const float degree = 0.017453292519943295; + float theta = 0; + int ta = -1; + int core = -2; + while (1) { + //serial::integer(ta, ' '); + //serial::integer(core, '\n'); + if (core >= 0) { + // core = 0 ; core = 1 + // ta = 1 ; ta = 0 + core_wait_end_of_render_video(); + while (!spg_status::vsync(holly.SPG_STATUS)); + holly.FB_R_SOF1 = texture_memory_alloc::framebuffer[core].start; + while (spg_status::vsync(holly.SPG_STATUS)); + } + + // core = -2 ; core = 1 ; core = 0 + // ta = -1 ; ta = 0 ; ta = 1 + core += 1; + ta += 1; + if (core > 1) core = 0; + if (ta > 1) ta = 0; + + if (core >= 0) { + // core = 1 ; core = 0 + // ta = 0 ; ta = 1 + ta_wait_translucent_list(); + + core_start_render2(texture_memory_alloc::region_array[core].start, + texture_memory_alloc::isp_tsp_parameters[core].start, + texture_memory_alloc::background[core].start, + texture_memory_alloc::framebuffer[core].start, + framebuffer_width); + } + + + // core = -1 ; core = 1 ; core = 0 + // ta = 0 ; ta = 0 ; ta = 1 + ta_polygon_converter_init2(texture_memory_alloc::isp_tsp_parameters[ta].start, + texture_memory_alloc::isp_tsp_parameters[ta].end, + texture_memory_alloc::object_list[ta].start, + texture_memory_alloc::object_list[ta].end, + opb_size[0].total(), + ta_alloc, + tile_width, + tile_height); + transfer_scene(theta); + + theta += degree; + } +} diff --git a/gen/k_means/k_means_vq.cpp b/gen/k_means/k_means_vq.cpp index 499e88d..5aa2f3b 100644 --- a/gen/k_means/k_means_vq.cpp +++ b/gen/k_means/k_means_vq.cpp @@ -162,7 +162,7 @@ int main(int argc, char * argv[]) } if (argc < 3) { - printf("argc < 3\n"); + printf("%s [in_file.ppm] [out_file.vq | out_file.ppm]\n", argv[0]); return -1; } @@ -199,9 +199,9 @@ int main(int argc, char * argv[]) double codebook[codebook_length][12]; int rgb_size = ppm.width * ppm.height * 3; - double min_error = 0; //std::numeric_limits::infinity(); + double min_error = std::numeric_limits::infinity(); - for (int i = 0; i < 2; i++) { + for (int i = 0; i < 10; i++) { double new_codebook[codebook_length][12]; // find locally-optimal codebook k_means_cluster<12>(&random_state, @@ -218,7 +218,7 @@ int main(int argc, char * argv[]) double error = total_rgb_error(rgb, ppm.data, rgb_size); if (i % 100 == 0) printf("%d %.0f\n", i, min_error); - if (error > min_error) { + if (error < min_error) { for (int i = 0; i < codebook_length; i++) { set_vector<12>(codebook[i], new_codebook[i]); } diff --git a/model/sheik/sheik_00.alpha b/model/sheik/sheik_00.alpha new file mode 100644 index 0000000..b1c75e2 Binary files /dev/null and b/model/sheik/sheik_00.alpha differ diff --git a/model/sheik/sheik_00.alpha.h b/model/sheik/sheik_00.alpha.h new file mode 100644 index 0000000..a76c8d5 --- /dev/null +++ b/model/sheik/sheik_00.alpha.h @@ -0,0 +1,5 @@ +#pragma once +#include +extern uint32_t _binary_model_sheik_sheik_00_alpha_start __asm("_binary_model_sheik_sheik_00_alpha_start"); +extern uint32_t _binary_model_sheik_sheik_00_alpha_end __asm("_binary_model_sheik_sheik_00_alpha_end"); +extern uint32_t _binary_model_sheik_sheik_00_alpha_size __asm("_binary_model_sheik_sheik_00_alpha_size"); diff --git a/model/sheik/sheik_00.alpha.pal b/model/sheik/sheik_00.alpha.pal new file mode 100644 index 0000000..f6cd446 Binary files /dev/null and b/model/sheik/sheik_00.alpha.pal differ diff --git a/model/sheik/sheik_00.alpha.pal.h b/model/sheik/sheik_00.alpha.pal.h new file mode 100644 index 0000000..80c5735 --- /dev/null +++ b/model/sheik/sheik_00.alpha.pal.h @@ -0,0 +1,5 @@ +#pragma once +#include +extern uint32_t _binary_model_sheik_sheik_00_alpha_pal_start __asm("_binary_model_sheik_sheik_00_alpha_pal_start"); +extern uint32_t _binary_model_sheik_sheik_00_alpha_pal_end __asm("_binary_model_sheik_sheik_00_alpha_pal_end"); +extern uint32_t _binary_model_sheik_sheik_00_alpha_pal_size __asm("_binary_model_sheik_sheik_00_alpha_pal_size"); diff --git a/model/sheik/sheik_00.ppm b/model/sheik/sheik_00.ppm new file mode 100644 index 0000000..66602b5 --- /dev/null +++ b/model/sheik/sheik_00.ppm @@ -0,0 +1,1199 @@ +P6 +# Created by GIMP version 2.10.36 PNM plug-in +128 256 +255 +ĒHĒHĒHĒHĒHĒHĒHĒHŔJDDDDDD@@@@:DJJJHHLLMMMM͹ïŴŴŴŴɽŽȖLȖLȖLȖLȖLȖLȖLĒHŔJŔJŔJŔJŔJŔJŔJDD@@@DDDDHHHHMMMMĚHĚHĚHĚHĚHĚHĚHĚHĚHĚHĚHĚHĚHĚHĚHĚHŔJDD@DDDDDJJJHLLLȞLȞLȞLȞLȞLȞLȞLȞLȞLȞLȞLȞLȞLȞLĚHĚHŔJŔJŔJDJDDDDDJJHHHH۽Ž۹̣P̣P̣P̣P̣P̣P̣P̣P̣P̣P̣P̣PɠMɠMɠMɠMĚPĚPJJD@==DDJJDDDDʹ̣P̣P̣P̣P̣P̣P̣P̣P̣P̣P̣P̣PɠMɠMɠMɠMĚPĚPĚPJDD==DDDJDDDDΰűضǶǶǶ̣P̣P̣P̣P̣P̣P̣P̣P̣P̣P̣P̣PɠMɠMɠMɠMȞLȞLĚHĚHŔJD==DDDJDDDDyyo䍍|]n]ٮŽЧTЧTЧTЧṬP̣P̣P̣P̣P̣P̣P̣PɠMɠMɠMɠMȞLȞLȞLĚHŔJD==DDDD@DDD÷ȦɽŽիЧTЧTЧTЧTЧTЧTЧṬP̣P̣P̣P̣P̣P̣PɠMɠMȞLȞLȞLĚHLHD@DDDDDJJJΰƤؒS\KЧTЧTЧTЧTЧTЧTЧTЧTЧTЧṬP̣P̣P̣PɠMɠMȞLȞLĚHĚHLHD@DDDDDJJJ̾ƾƾƾƾƾºº¤ɹɹװŽͼĴĴűЧTЧTЧTЧTЧTЧTЧTЧTЧṬP̣P̣P̣P̣PɠMɠMȞLȞLĚHĚHLH@@DDDDGGGGŽŽŽŽɽŽŽŽŽŽŽŽŽŹĴӽŽŽѽŽͽŽŽŽŽЧTЧTЧTЧTЧTЧTЧTЧTЧTЧṬP̣P̣P̣PɠMɠMĚHĚHĚHBHH@@DDDDGGGGЧ\Ч\Ч\Ч\ЧTЧTЧTЧTЧTЧTЧṬPɠMɠMɠMɠMŜRLMMHH@@@@@@GGGGЧ\Ч\Ч\Ч\ЧTЧTЧTЧTЧTЧTЧṬPɠMɠMɠMɠMŜRŜRMMLHDD@@@@GGGGȾƾƾƾЧ\Ч\Ч\Ч\Ч\Ч\Ч\Ч\Ч\̣X̣X̣XȞTȞTȞTȞTŜRŜRMMLLDDDDDDHHHHȻ̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̻̯̻̻̻̻Ļ̻̻̻dzijȷȷȷȷòdzijijͼͼͼͼЧ\Ч\Ч\Ч\Ч\Ч\Ч\̣X̣X̣X̣X̣XȞTȞTȞTĚPŜRŜRMMLLŔJDDDDDLLLLòọ̀X̣X̣X̣XɠUɠUɠUɠUɠUɠUɠUɠUáLáLáLáLʘVʘVʘVʘVLLb/H]]o+ǃ?ƕSGHḤX̣X̣X̣XɠUɠUɠUɠUɠUɠUɠUɠUáLáLFBBr0^^HHb/b/o+]]]=ƕSHLɠUɠUɠUɠUɠUɠUɠUɠU‘F‘F‘F‘Fr?^+LLNNNb(w3?I̙UÐLÐLFw>wFc2Z'PPPb n,n,n,s)y/}3}3:DTTr0TTT̻̻dzijŽŽл̻̻̻ǻ̻̻̻̻̯ĻĻĻĻĻƻĻķȿĻȞLȞLȞLĚHĚHBB{0w>Q= = PZ'f3f3BBBB9999@:r0qHqHTTTƯȿŽſȿοȷȿĻĚPĚPĚPĚPŔJD|:|:b/{Hb/LmTDC*-% ####""**9™OĚPĚPʲòòضƾƾĚPĚPĚPJŔJD|:|:{H{H{H^+ *xV4™O™OĚPĚPͼͼͼͼľƾƾƾǶIJòòѳġȖLȖLĒHĒHD@|:j(^M^M2 , + +, + +~~m~~m~~m ""^^™O™OĚPĚPǻ̻̻ŽŽdzijȖLĒHĒHĒHD@|:V^M2C* , + +rrrr, + +~~mT2xV49™OĚPĚPųij̻šĒHĒHĒHĒH‘G=w5Oo^^!{{!4#88'пg4DPĚPĚPĚPĚPɽŽòòƾȿʨȖLĒHĒHĒH‘G‘GOOE44!o^^!{{E##gEE4#88'пg4vTZZĚPĚPĚPĚPǿȵƾƾƾŽ̨̻ȖLȖLȖLĒH‘G‘G׮lw5  {E##gEE4#4#pp_пg4vTZZĚPĚPĚPĚPɽŽŽº²òòò˸Ƕ׻̯ºΜRΜRȖLĒH‘GΝS׮lZgVEgVE^;;oMME##gEEgEE4#4#pp_ٳvTvTZZĚPĚPĚPĚPӽŽˡò׽ŽũºȞTȞTȖLȖLϦdϦdϦdXŴӍ|k&&@@@@@@Q@7&7&7&ǔ_,9˙O˙O˙OĚPĚPMM̿Ȼĵƾ׽ũŽžƾƬ̻Ϻº°ѭ˸ȞTȞTȖLȖLϦdϦdϦdϦdŴ]]&&@@@@7&7&7&n]ͫ\_,E˙O˙O˙OĚPĚPMMλĵƾƾŽŽŽžƾƾƾƻ̻̻̻̻ϴŽѽŽŧŽŽƾƾŽŽŽŽŽɽŽȞTȞTȖLĒHMˡWˡW׭cjٷԡԡ|kZ|kZnnͼͫ]_,\ȞTȞTȞTȞTĚPĚPMMĻŽŷȿοȻĻĻĵƾƾƾijسġŽӾⲨĿ˻ĵƾŽŽȞTȞTȖLĒHMMˡWˡWjjjjͼͼͼͼ]]\\ΤZΤZȞTȞTȞTĚPMMĻƾĻĿȿȻĻĵƾġŽͳġƶƶɽލĻĸƾƾŽŽŽȞTȞTȖLĒHŔJŔJĚPΤẒX̣XƝRƝRĚPĚPȞTȞTTTJJMˡWˡWˡWɠUɠUɠUɠUȞLȞLĚPJɽŽ̻̻ʮƶƶ||˵ŽůȞTȞTȖLĒHŔJŔJJȞṬX̣X̣X̣XȞTĚPĚPĚPŜZŜZŜZŜZˡWˡWˡWˡWɠUɠUɠUɠUȞLȞLĚPĚPŽĻĻȿŸػ̻ǶŮƶ||ǶǶ˸ȞTȞTȖLȖLŔJŔJJĚPȞTΤZΤZȞTȞTȞTȞTȞTȞTȞTȞTȞTɠUɠUɠUɠUɠUɠUɠUɠUȞLȞLĚPĚP˸ĻĻȿȿ¸ɸŴϽŽºȞTȞTȖLȖLŔJŔJJJĚPȞTȞTȞTȞTȞTȞTȞTȞTȞTȞTȞTɠUɠUɠUɠUɠUɠUɠUɠUȞLȞLĚPĚP׸ĻĻĻɸɸɸɸŴŽƾƾƾƾƲºƾƾȞTȞTȖLĒH‘G‘G‘G‘GJĚPĚPĚPĚPȞTȞTȞTȞTȞTȞTȞTȞTȞTȞTȞTȞTȞTȞLȞLȞLȞLLL۽ŭĻĻĻĻĻȿŽŽųĻɽŽĻĻĻȿ׾ƲºȷȷȎiύ"̚̚̚̚ɏәԣԣ؞#؞#؞#؞#wۑ؞#Ԛۑ{Vڐ-ߝ!ߝ!ߝ!'ȞTȞTȖLĒH‘G‘G‘G‘GJJJJJĚPĚPĚPĚPĚPȞTȞTĚPȞTȞTȞTȞTȞTȞLȞLȞLĚHLL۽ŷȳĭĻĻĻĻĻĻĻȿĻòòìɽŽŽĻĻȿ׾ƲºȷԀȎiύ"̚̚̚̚әԣԣ؞#؞#؞#Ԛwۑ؞#؞#ۑ{Vڐ-ߝ!ߝ!ߝ!ߝ!ȞTĚPȖLĒHDDDDJJJJDŔJŔJŔJĒHĒHȖLȖLĚHȞLȞLȞLȞTȞTȞLȞLĚHĚHLL۽ŷȷȷȿȿĻĻĻĻȿǻ̻ǻ̻ƾť޼x梺TTĊiύ"О#̚̚̚ɏәԣԣԚԚԚԚwۑԚԚۑчVڐ-ܚܚܚ#ȞTĚPĒHĒHDDD@DDDD@@DDBĒHĒHĒHĚHĚHĚHĚHĚPĚPĚHĚHĚHBLHѽννŷȿȿĻĻĻ̻̻Ǿƾƾű梺TTTȎiύ"О#О#̚О#ɏәا#ا#؞#ԚԚԚwۑԚԚۑчVڐ-ܚܚ֔ܚȖLĒHĒHĒH@@@@@@@@DDDD@@DDŔJŔJŔJŔJŔJŔJŔJŔJŔJDDDѶǶǶǭŽȿȿѾƾƲº{{ȕЖ#̒̒Ж#әɏsˉԣԣΝԣΝԣا#ا#ܣ֝֝֝{ӑԚԚ׍!׍!g׍!ؖ#ؖ#ؖ#ؖ#BBBB@@@:@@@@DDDD:@@DDDDŔJŔJŔJŔJDDD@@ѶǶǭ¾ƾƾȿȿŲº{ȕ{{Ж#̒Ж#֜)әәsו!ԣԣޭ)ޭ)ԣԣޭ)ޭ)#ܣܣ֝ɇ ӑԚ؞#׍!׍!g׍!ޜ)ؖ#ؖ#ؖ#y7AAA@@D@DD@DDDDD:@@@@DDDDDD@@@@@ºĻĻȿŻĿԽκ°Pá*á*á*ΔԚ؞#؞#ߥ)ә ו!֭֭)#ܫܫ##ܫ֥֥֥ɇ ߝ!؞#؞#ߝ!ߝ!wߝ!##ܣ֝s1y7};};@@DDDDDDDDDD@@@@@@@@@@@@@@@@ƲºĻȿųijijijĵŽŽκ°ƥڹճ<á*á*á*ԚԚޤ)ޤ)ߥ)ә ו!ܳܳ)#)ܫ))#֥ܫܫߝ!ߝ!ޤ)ޤ)ߝ!ߝ!ߝ!5)))#%%%%%%%%%%%%%%%%%%%%#### ѲòçŽ˾ƲºĻƾƾȽŽź˪˪Ģ$>>>ޤ)ԚЎ֔Ԛ؞#ܫ٠͔ߵ#ߵ!ߵ!''#߭߭߭ߥޤޤ %%%%%%%%%%%%%%%%%%%%#### ղíŽĻȿĵƾĻľƾƾƾȿȿ˪ĢĢĢض>>>>ޤ)ԚЎЎԚޤ #ܫ٠͔#)#'ߵ!''#߭###))& $ %%%%%%%%%%%%%%%%%%%####2&&&""""շȿĻĻĻŽĻȿȿĻĻĻĻĻĻĻĻĻfr|| ####ޤ)ΔЎ̊؞ޤ #ܫܫ֥ #޵&##  ''Ȼ%%%%%%%%%%%%%%%%%%&޽޽ض ض ض ض սŷȿĻĻŽŽŽŽĻĻĻĻĻĻĻĻĻĻĻ׶݈݈݈݈ ####؞#ΔЎ̊ޤ ޤ #ܫܫ #)###&޵&&#))  ''3'%%%%%%%%%%%%%%%%%##&޵޵إإ̙̙ўўўўΛΛΛΛўўўў٦٦٦٦ااޭ ޭ ) **߬ۨӑ{ӑӑr̈բբ٨٨ۡ% |ΌЖЖԣاޭ ޭ ߝ!{ӑӑН ܚ֔ΌȆԣޭ ޭ ا#%ڹ #)֬###%ƾƾ%%%%%%ƾ%%%%%%%2&3'''ݪ"ݪ"ݪ"ݪ"ԡԡԡԡݪ"ݪ"ݪ"ݪ"٦٦٦٦ԣԣԣԣͬٸ **߬ۨӑ{ӑӑf̈բբ٨٨ۡ% |Ό֜Жااޭ ޭ ߝ!{ӑӑН ܚ֔ΌȆΝޭ ޭ ԣ)#%ڹ #))))&&####ͻĵƾ%%%%Ȼ%%%%%%%##$$$$''''****޴޴޴޴ٸٸ$$߬߬ߥɏә ә r̈բբۡ% ĂΌ֜Ж֬֬&߮!͜͜Н ܚ֔ΌȆΝاޭ Νߵߵ#)#)%ڹ !!!+)))##))&&λ%%ŵƾȻĵƾ%%%%%%####****'333<<<<33''++++**** ߥɏә ә r̈բ.)ۡ% ĂΌ֜Ж2߮!߮͜!߮!; ܚ֔ΌȆΝاޭ Νߵߵ#)#)%ڹ !''')֬)###))&&%ľƾ%%%%%!!!5#17;AA;AAJJDD11'!&&&2222) ߵߵܫ֥֝r̈ض "**լŔѠ۪Ѡ޽&&ֵ&###ؖԒЎ̊ɗ߭)߭)ɗ $*'''ݻ ***.ԡ..$ **.Բ..$$**%ξƾ%%%%ʠʠ޴5)###117777;;DDD@++!!޵޵ֵֵֵֵ֬֬ߵ֥ܫܣ|̈"***լѠ۪)Ѡ&2&&&&2####ؖԒЎ̊ɗ߭)ӡ$*''ݻ$ $.  %%͔͔!:::(  ....;;;;9993٨ ͜͜٨ !! ֥ܣ̈̈""޵$.޵)ͤ''1+##)########ؖԒЎƄˑם!ם! ݙ"ݙ"ݙ"ݙ"ݙ"ݙ"ݙ"э""ؔnĀ ؔԐԐԐԐՑkՑՑ"%%!͔͔::: $..77;;9993  !!!٨ ٨ ٨ ܣܣ̈̈""޵..޵))ͤ!'1+###)#ԒԒЎ̊ ם! {ǃ ǃ ǃ ǃ ǃ ǃ ǃ ǃ ̈̈̈̈Ā nĀ Ā Ā Ā ʆʆkՑ̈̈̈ؔ %%ߥ͜٨ !5**ұ٨ ٨ !))))## ****ߝߝߝߝǔ ǔ **2&#))Ѡ!+1'###))) ֥ܫܫܫܫ߬ۨբ բ Ց Ց Ց Ց ||rryyuufr r r aaaaoufZPZ%ߥ͜ʠ!*>*٨ ٨ ٨ ٸٸٸߵ ֔kkjjjj{{ӑ ߝǔ ў*$22&#))Ŕ!+1!ܫ֥ܫ߬ۨ߬Ց Ց Ց ݈݈݈|r r r r aawwyfZZZ%ߥ!!޴޴ ! ֬֬ӡ ӡ ӡ ӡ ااޭޭܫ֥֥֥إ إ إ إ ܣ + +ўݪ"*$ֵ22&##)Ŕ22޽&&& ߥߥ3*****  إ إ " ݪ *jjjߥ!!! !!֬ӡ ӡ ӡ ӡ ԣΝԣԣܫܫܫܫ""""ݪ"ݪ"$ ֵ22&߾߾۪Ŕ2&޽޵޵ܫ֥֥֥ߥ '333***$$$ *$$$**$ ""ݪ*ل ل j]]  ##ѯѯѯۨۨբ ֵܻܻۨۨբ բ բ բ ۨ߭ ֤))̛3)#߮*߮*ֵ͜22٨))-׍ۑۑ!!!!!&2..77DDD@)####&&޵#!ֵ֬ٗ ͋o]  )###.ۨբ ֵܻܻܻ߬߬߬߬߬ۨۨ߬ &֤֝#̛3)#߮*߮*߮*ֵ2&٨۪Ѡ׍׍ч ч ч ч ͋ٗ &&..;;JJJD######&&##!ֵٗ oo33// ֵֵֵֵ  &ܣ#̛3߶!߶!߶!ֵ&٨٨۪Ŕggs͋͋֔֔ҠҠ17++''####!ֵ !!!o""))/33$$ !!!߾߾߾ 2ܣ̛֝3ߵߵ߶!55ֵ&͜٨))-׍ۉ ۉ !!!---..7;111+###)!  !!!ww$.$ 999/ ##$ إ̙͔2!!..Ðբ߭߭߭߭))'' $$5551)##### ,..ۨkw $.$)/99  ###$ '̙͔&۪!߾.Ð||Н  111+##)## 688ػUw###)) >>** ## #)#$ '̙͔٠۪Ѡ ެ؃o ]]]]o؃.޴!!!""""////""إ ٰٰٰͤ&# 6)8Dkw######))# #)#*$3̙͔&ŔѠ ެެެʘo ]II]]]oʠ޴!! إ إ ̙̙ЮЮЮЮٰ̙̙̙̙ͤ))&&&&# 6)8DƿȻο #'+++)# ֬ܣܣ )))) #)#####۪Ѡ Ў +֔jZTUULL^ rٕٕ"")#߾߭ #)'+++####)##,F9)1+BB̿ȵƾ؃ #''++)#) ֝֝͜͜٨#####)##۪Ѡ Ў +֔jTT_kr^ L^ ٕٕض "#߾߭߭߾#'+11########,F9/1'FF̿ȵƾȻ؃ ####٨͜͜͜ŔѠ۪)##)))))##۪Ѡ Ў +Ў +ߍߍߍgZZ_kՑ.k{ٕ̪))٨֥ܫ   !++1111+####)##,F9/1!FF* ̿ƾƾw؃ ## )))۪۪۪)##!۪Ў +Ў +ߍߍߍgZZ__k..^ٕ̪ض ٨٨֥͜ܫ߭߭߾߾!'+1+'!!#####,F9/1!FB* ްǢ ɇɇӑ ӑ ΊΊΊΊЎ +֔Ԓؖ +̚ОО̚ʗʗʗʗ̣̣ЧЧԣԣԣا٨ ٨ ٨  ߭͋͋߄߄߄b\ +X__^n.Ðnn"ŋۡۡۡۡۡߥߥ߭߭߾߾))3/++**'' F9)!B6/)ؤ ӑ ߝߝӑ Ā ʆΊΊЎ +Ў +ԒԒ̚̚̚̚ʗʗΛΛ̣̣̣̣Νԣԣا٨ ٨ ٨  ͋wx x ߄b\ +X__^^բբĀ n̙"ї ŋ!!ۡ! #$.9999+!"*!' F3) B63)ذ΢ Ŕ۪ ԡ̊Ў +Ԓؖ +ٰ̪̪̪̪֝֝֝֝ ٰ ٰ ٰ ٨ ͜٨ -͋{׍׍g\ +X__^^|բؔĀ ̙׌ˀ vv!! )..11++!!̪" *'' 23) B,9/ΰ΢ ŔŔѠ.Ў +̊Ԓؖ +֝ܣ""!!!!!٨ ٨ ֥֥ܫ--׍׍׍g\ +\ +__d^|բؔĀ ׌ˀ vˀ ŋŋ ߭#$$''''!!*ұ̪" $++ 23) , 9/оƨ%%%%%%%%%%%%jjͬٸ !޽ʩإ#####լܣ +!ŋ׍gaaaakaĀ Ԑŋїؖ +Όu +{} +ẙЎ +)&&:Ѩۡ їƝ( ##޴-*  )־ƨ%%%%%%%%%%%%jٸ ͬլܣ֝ + +!!׍{e +aaakkʆԐїۡ ֥ޜΌu +{} +} +̊Ў +Բ..##))&&Ѩۡ їƝ( ޴-* #۾ƨ%º%%%%%%%%%ʹ߾ $$$*&&#)# )ۙяяۡۡ%{qkkkkkΊԐۡ ۡ ֥ޜԒq{} +} +̊̊ǔўݪў****55ѨѨїїƝ(޴*#ƨƨ%%ŽŽ%%%%%%%  $&&&&)###))# ܣۙۙяяї ŋ׍׍quqqwwԐԐ֥ޜؖ +u +{y} +Ƅ̊ǔўݪǔ*ʱѨѨїŋƝ(ʠ$إ##ȿȿŭŽ%%%%%%%==! ###)))##**$ ߛ$ۗ ՑՑ̈̈̈̈яя--p p ků̊ԣاߵܫܣЎ +̊{ч} +} +؎ +؎ +וŃ߭!٨ ޜؖ +ۙ я͜! ٠ۗߛ""ܿȿŽŭŽ%%%%%%%==!!!## ***ߛ$'ؔؔؔ))ׄrp p kuЎ +̊ااߵܣЎ +֔чч} +yԊ؎ +וŃӡ ܳ͜٨ ͜ޜؖ +ۙ ۙ ͜!٠ Ց ۗ"Է%%%%%%=  &)Ńrrp p ku֔Ў +ޭޭߵ֥ܣЎ +֔ۑ ۑ } +} +؎ +؎ +וŃӡ ֭ܳԒޜޜؖ +ޜؖ +ۙ ۙ ٨ !٠ Ց ۗ"Է%%%%%% 2&&&))))33333333?++ўŃŃrrp p kq֔̊ޭޭ ܫ֔֔ۑ ΃} +ޔޔוŃ֭֭߭Όؖ +ԒԒؖ +ؖ +ۙ ۙ ٨ !͔ Ց ۗؔ"˸%%%%%%##))&&&2#####$ԡԡ|p Zfo o o o ݪ"ض ߾߭߭ݪ ǃǃߝӑ ӑ {ߥߥә {чۑ ۑ ؖؖ֝ܣ֬ߥۉ ͔٠֝ ˸ͳ%%%#)ֽ&#####$ ԡԡ|fZfo o uݪ"  эǃߝߝߝ{ߥߥә {ۑ ۑ ۑ Ԓؖܣ֝֬) +ۉ ͔٠֝ %%%%$֬$.#####*$ߕs̈̈ؔ ݪ""ݙǃ͔͔٠ Ńяяۙ ؖؖ֝֬ + +ۉ ٠ ܣߵ ͽͽ߹%%%%֬֬$.####**.ߕӉ Ӊ ؔ ̈ؔ "ݪ""" "ݙэ!!٠ ٠ !Ńۙ ۙ ۙ ؖޜ֝֬ߝs  +ߵ̾ƷȿĻ%%%%%&)#ߥܳ))####*؃ ww{ٕ ٕ **߾$$"̈%ڹ ֬֝ܣ֥֝ܫ%ɏ ֥ ֭ݙݙkwߥߵܫܫܫ̾ƷȿĻ%%%%&)߭ܳ)#####*"؃ ؃ ؃ ٕ ٕ ٕ **o߾##$ "̈%ڹ ֬))%ɏ ֥ ֭ݙэkwߥܫ̾ƽŷȿ%%%%&#߭######**ѯѯѯ*##$$"̈%% ߵ %ɏ ֥ ֭ݙэakߥ ߵߵߵ̾ƽŷȿ%%&#߭#######**..*##$$"̈%%  %ɏ ֥ ܳܳݙэUkߥ ߵߵ˸%"*ۨ ## *ֵ8888####!ʐ)##IIIض?Ѹ,Ѹ,%ɘ ֭ܳݪ"ǔ M]߮͜!ܻ ߾ˬ%%%"*ۨ )߭ *8888#####!ʐ)####UUIض?Ѹ,Ѹ,%ɘ ֭ ܳݪ"ǔ SW߮͜!ܻ ߾ ɵŽ%%%%%%%"*ۨ )#$*ܻܻnhhh######!ޤ##(:::Ѹ,Ѹ,%ɘ ܳ ܳݪ"ǔ MS߮͜!ܻ )#ߵŽ%%%%%%" *߬$))$*ֵܻdddd######!ޤ##(::ʹBѸ,%ɘ ܳ ܳݪ"ў]]߮͜! )###׸Ƕ%%%%%)#ߥ)߭#$*۬ϽŽκ¥˸ɵŽŽ׬Ƕ%%)#ߥ#߭#$*Ϻºͽɺ°̻Ƕƾƾƾƺººº¾ƾ̾ƸηȿĻĻĻˬ%%%##ߥ# $ٽϤκ¥Ǫƾƾƾººº¾ƾƾƲºƶƶľƾȳĻĻĻĻܸǶ%%%%### $ͽŽŽŽŽͽͽɰǪºųĻĻĻºººº׬%%%%%  ŽŽŽɺ˺˺˺¨ͽϩ²r{ʹʹʹξ²ĻȿųĻowowȿĻĻºººº˸%%%%%  ߥ߽߹ɽŽߵŽ˨׽ũ²²r{wwȿȿžƾƩ±±±±Žƾƾƾɬ%%%%  ޤ Ԛޤ ؞۹ֹɭŭŭ̻ɽͽͩĻžƲºŽƾĿɽŽʽŽ%%%߭ܣ֝ԚΔԚԚճ ߽ӭŭŭϾھƾʮƶƶξ²ĻȿŽŲººĻѶǶű%%%ߥ!ߥ!ΌΌ׌!ˀӑӑIԲ]ѢŽŽŽоƾʨ“s{s{s{ȿĻĻĻǢ%%ߥ!ɏ € € ˀˀɇ ӑI؃ŐǶǶɵŽӽŽŽ̾ʨι¥ɽŽŽѻ̻%%%%%%ә€ vv v ɇ ӑI؃ŽűǶǶŽŽŽŽŽŽŽŽѻ̻̻%%%%%ɏ vvv v ɇ ӑI؃ŽθŰӽŽ%%%%|p ffnnʆԐ鱹߹ɷȿؐǶǶǶűͽɽŽ%%%%%%%p fffdnʆԐ屹ӵŽǶǶױ̳ġ||r{zzzzzzzzҶƾֳܷ̽¸%%%%%%%%ka[adnʆԐͱɵŽȿױʤƾֳ̭֭ܳ֬%߽Ž%%%%%%%%%ka[[dnʆԐͱűɵŽȿϮʤˬ֫ܯļº%%%%%%%%%%%%%%e +a\ +\ +fr đ ԡѱѿȵƾƾ̳ijʭֵ֭ļº%%%%%%%%%%%%%%%%%e +aX\ +fr ʗԡѿȵƾƾʽŽŽ̾dzijijijʭֳܳļ%%%%%%%%%%%%%%%%%%%e +[X\ +fr ʗԡ߱̾ƾѻ̻ļ%%%%%%%%%%%%%%%%%%%a[X\ +r |ΛԡƾѾĹʹʹʹʹͽͽ̻ǻ̻̻v׽ŶǶ' ''''''''$$$$''''e +[[[wáճijᶶ4Eпֺ׽ŶǶ' ''''''''$$$$''''ka[awáճ  !!4EvпשǶ' ''''''''$$$$''''m +icm + ճճʗԡԡԡ׳ij  !!4E4EֳשǶ' ''''''''$$$$''''sm +is ̙"ճ.Λԡԡԡǘ  !!kIZ4Eвйΰ***++++++         + +# + +# + +# + +# + ++ + ++ + ++ + ++ / / / / + ++ + ++ + ++ + ++ + + +ѽŷȿĻĻ #$$!!!''!ӱkIZ4Evv4EԺ¤***++++++)        + +# + +# + +#)1111 / / / / + ++ + ++ + ++ + ++ + + + +ŽųĻĻǶ ##$$!''''!ӱӱš4E4Eܺܺܺ˚x4E4Eκ¤***++++++)    + +# + +# + +#)777;DDDJFFFFDD@@//)) ѽߵŽĻĻĻĻ ##$$''##+'##+!ӱӱv4E{ܺܺ˚xQ/@4E4Eκ¤***++++++)    + +# + +#));;;AJJJJLLLLJJJD3///   ۽Ž̵ŽŽӭĻȿ ##$$'##+##+'##+'͌9Bev##*;x4Ev߽ھƱʹ***++++++&&. + +#/ + +3@@HLL Raaaakkkk!s!s!k!kLHHB77 + ++ + ++űŽɸ²!!!'''''##+##+##+##+##+'q7Hq7H9B9Bn;LӚ####xx4Eв۹ѾƾƝ***++++++&&. + +3 + +3@@HHL Reeee""w""w""w""w'y!s!k!k RLLH77 + ++ + ++ɽŽɽŽ//////777 #'''''''##+##+##+##+##+##+'ZZk##eeTe4Eв۹ǾƬ***++++++&&.$ + +# + +3 + +3DD[[a k'y'y'y+#}5$5$5$5$1)+#}'q'q) k#ea[;7 + ++ + ++εŽŽŽӸeee######    #### )'''##+''##+##+##+##+##+##+##+'arar9B9Bn;LӒ####Te*;4EЬ߬߳չǬ***++++++&&.&&. + +# + +39DJaae k+#}+#}1)1);*5$;*;*1)1)+#u+#u) k) k#e#eA;1 + ++ɵŽŽŽ˶ξ²eee#########    ### )# )''##+##+##+##+##+##+##+##+##+##+))1##+b@@b@@##4+4+~44llKSq/7q/7ٷٷٰ׺˝444******&&7&&722T* < <kk!|!|'+#/'/'/'3+1)1)1)1)1)1)1)1)/')!+#!|JD@:(55E99A%%-##+'''3;9A3;9A s$,.6.6$n2:6>$f$,.6 s.61:1:7@;D$$$$$$$$!!!!!!!!!'''''##+##+##+##+##+##+##+##+##+##+''/''/''/''/'!˚##˶ll~44KS}q/7ٷٷ٤˺˰444***$$$&&7]]nVVx* < <k""w'+#+#1)/'3+3+3+7/7/7/7/7/7/7/7/3+3+1)'JJ@:(ll|__g99A))1'''9A3;3;9A s.6:B:B$n2:6>$f.6.6 s:B1:1:;DAJ$$$$$$$$!!!!!!!!'''''''##+##+##+##+##+##+##+##+))1''/''/''/''/##+'#lcԶlleKS駯駯ճeeeeˆ{{{{HXH444444***$$$&&7]]n* < <k""w)!/'/'3+1)7/7/7/;3;37/7/;3;37/7/3+3+1)+#%%W = = OO_ll|KKSKKS))1''';D;D;DAJo:B:B:B$n2:6>$fBK09%wBK7@1:;DAJ''''''''!!!!!!''''''''##+##+##+##+##+##+&&.&&.&&.&&.''/''/''/''/##+'#4+ԝKSeYa駯ճ];;];;{{HXH444444$$$$$$&&7@@QVVx* <k""w)!/'3+917/;37/;3;3A97/;3;3;37/7/91911)'%%W = =BBtll|OO_%%-%%-!!'';D;DAJAJo:B:BNV$n2:S[$fBK09%wV_AJ1:;DAJ''''##+##+'''''''''''##+##+##+##+##+##+##+##+##+##+##+&&.&&.&&.&&.++3++3''/''/##+'䱱k'Ƕ1)!!!!锔锔\\,,ǥ|kп 333nnnn,,Nbb''''5$;*:1@7:1:1B1F5<+B1:1:1;3;3:2:2.&$\\\BBB%%%&&:BDLDLJR +_:KBBLL j:BIQ!lDLJR%wV_JS4=@H@H##+##+##+##+##+##+##+##+##+'''##+##+##+##+##+##+##+##+##+##+##+##+##+##+##+##+!!)''/''/++3++3++3++3''/ )#䱱k'ӏ~òò1)!!!!,,\\,,,,|kп77Hnn\\~Hb'''';*;*@7D;D;@7F5L;L;F5@7@7A9;3:2.&$sTTl\\\ &&@HJRDLDL +_:KBBLL j:BIQ!lDLJR%wV_JS>GDL@H##+##+##+##+))1))1))1))1))1##+##+##+##+))1))1))1##+##+##+##+##+))1))1##+##+##+##+##+''/''/++3++3++3++3++3''/#鴁k'Ƕòòsk1)!!cc];*];*];*xòò+QQb,,N+H'';*;*A9MEMEMETTxxTTTTD;D;A9;333u33uQQTTlTTl888 &:BDL@HDL +_:KBBLL j:BIQ!l:BJR%wV_JS>GJRJR##+##+))1))1''/''/''/''/''/''/''/''/''/''/''/''/''/''/''/''/''/''/''/''/''/''/''/''/''/''/++3++3++3++3++3%%|II_NǶ؞1)1)ճճճճò+77H\\~;;H''5$;*A9MEWOWOTTܢxxTT@7:17/1)QQQ]]~~TTl &:B:B:B@H +_:K<G(1:BDL##+##+))1))1''/''/++3++3++3''/''/++3++3++3''/++3++3''/''/''/''/''/''/''/''/''/++3++3++3119119119++3++3++3%%yqee##bQQܭ֧зȿKKKTTeMj////?.I8UDUDMMaaaa;;....ooJJZBBK%%.&/73;3;3;n??88DDn.6:B b,4BJ$wS[19'//79A'##+++3''/''/''/++3++3++3++3++3++3//7//7++3++3++3++3++3''/''/''/))1))1''/++3++311911:11:11:11://7//7))1%%########eeܧНƽŭKKKLLMj//3"?.?.?.;;;;;;''oo]IJJZ::B  &)1/7/7/7n??..88n.6:B b,46>$w6>+3!))19A''!!)!!)''/''/++3++3119119119++3//7//7''/++3++3++3++3++3''/++3//7))1++3++311911911:77@77@%33;//7))1%%####|kkӻ⧿Нƽŭxxxx鏏''I''Ir''|''|''|""w""w""wk'''匌::B +  &$&.&.&.n++..88n.6:B b,46>$w6>'/!))13;%%''/''/++3++3++3++333;33;33;//733;//7!!)++333;33;33;))1!!)++333;//711:11:11:11:77@;;D;;D%33;//7%%%!!!####yqӴأ̝Ʒȿ **;TTe__ffrrkk a a'==_ǥnjJJZ + +  &&{$&.&.n++..88n.6.6x b ( ($w6>'/!))13;%%++3''/++3''/''/11933;//7//7//799A//7%11933;33;33;%!!)11933;33;11:77@77@77@;;D77@%%33;%%%%''!˧ЧЧЭ֭ޭޣԝΙ̍òò'''''!   VVVẺxx//@//@''I''I''I''IᘘVVV ''| ) )hn****k ){ ){k&&v)2  #+)1%%%&&.119''/%119++3%++3119119''/%11933;33;%%!!)++333;%77@77@77@%77@%%%%%%%%''' ˝ƝƝƣ̝ΝΝΝΙ̍òò'''''!##    VVVᘘ ''||hh$$ k#u#uk&&jv }!#+%%%%119''/%%''/%++3%119%%119%))1%%%++399A%%11:%%%%%%%%%%%''' ˎȖȖȖȍò'''''!##$$$$"""VVV"""  '' hhmimiuukk}y!'%%%%'%%%%%%%%%%%%%%%%''/%%%%%%%%%%%%%%%''' Q@@ˊĒĒĖȍòò'''''!#$$$&&."""""" VVVbbb   '' hn im siuuku}y!!%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%''' Æò'''' )#''##+##+##+''!&>>>ԝ      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +TCϐÊì'''' )#'##+##+##+##+##+''&&TTT       + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +㤴Êì'''' )# ''##+##+##+##+''&&####''!!### + + + + + + + + + + + +  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +϶ϔŔʼnè'''' ) ) ) '##+##+))1##+'''&&####'##+!!### + + + + + + + + + + + +   + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +ppؔǔǎII !'!!)!!)''/++3''/!!)''$$ ##$$##+##+# )#!''''''''''!### + + + + + + + + + + + + + + + + + + + +|88ؔǔǔŎ̯II !'!!)''/++3++3''/!!)''$$##$$'##+##!''##+##+##+##+##+##+##+'' ) )## + + + + + + + +|88؞ўѤΞȔč̯II!'!!)''/++3119''/''/##+##+$$ ##$$''##!''##+''/''/''/''/&&.&&.&&.&&.##+##+''''!'!'''''!! + + + + + + + +|88تݞѤΤΞȞș̻̍II!'!!)''/++3++3''/''/##+##+&&.$##$$''##!'##+##+''/''/''/''/&&.&&.&&.&&.##+##+##+##+'##+##+'##+'##+##+##+##+##+##+  + +88بۨۯॾ֥֛Ηǻ̻II#'##+))1))1))1))1##+'**444 $$## ) )!'##+##+&&.&&.&&.&&.))1))1))1))1&&.&&.&&.&&.##+##+##+##+##+##+##+##+&&.&&.&&.&&.&&.&&.&&.&&.##+##+##+''''!$$$$ + +88ج߬ߵॾ֥֛Ηǻ̻II#'##+##+##+##+##+##+'**444 $$###!'##+##+&&.&&.&&.&&.))1))1))1))1&&.&&.&&.&&.##+##+'''##+##+##+&&.&&.&&.&&.&&.&&.&&.&&.))1##+##+##+##+##+''$$$$ + + + + +88ج߬߯ॾ֛ΛII#''##+##+'''!* 頠88I$$ #######$$$$####''##+##+&&.&&.&&.&&.&&.&&.&&.&&.##+##+##+##+##+''''##+'##+##+##+##+##+##+))1##+##+##+##+##+##+##+''''''' + +ppج߬ߵܡԡII!'''''!!$ 44488Ipp頠22:$  ###########$$$$### )'''##+&&.&&.&&.&&.&&.&&.&&.&&.##+##+##+'''''''##+'##+'##+##+##+##+'##+''''''''''!!&&&&&&ڹڳ))  <6MMaaaa;;22v22vLLW]]]##$$$$$$''_N_Ƕ_N_''Z''Z''Z''Z8'Z8'Z8'Z8'Z;;n;;n;;n;;n88Z88Z88Zqqq  + + + + + + + + + + + + + + + + + +׵ŵTTTTTTJJJDDDDDDDDDRRRLLLLLk""w';*<>>>>>BBBLLLHH\ b..88DDDDDDDD888844x44x44xvvǶĢTTv**Lccmi j j6.B:22|fLL  #### $$$++>>>>>BBBLLLHHX b""..88888888....44x44xvv'''''''''**LxxTTvcccc j,$vB:B:22|fHH  ### ++<""w..<+F5M=cSWGM=H7H7D3@/;37/;3;391913+/';;]$*'##+##+'##%%%%%%%%%%%%%:::DDD@@@@@@>>>>>>BBBLLLHH\ b ************ *ggxCCTTTTRRcii( >6JB>6&&pfLH  ### ++<""w..B1L;VEp_VEVEL;H7D3@/;37/;3;39191913+;;]*$'##+##+' )#%%%%%%%%%%%%%%%%:::JJJ@@@@@@>>>>>>BBBRRRLL\ b $$**$$  ggx** '''''''''TTTRRm s4,JB>64,&&pfLL ###bbsbbs""w..B1L;VEڍ|VEVEL;H7D3@/7/7/;3;39191913+;;]$$!'##+##+ ) ) 9 + +3@D**?.UD}|VE!!c M + +3 + +3:::JJJDDDDDDDDD@@@EEE[[[ZZZZLLLCCv++M++M++Moo!!2!!2!!2##4##4##4##4++<++<++<++<************++^++^44x44x44x44x++o]]]  ###,,_++55B1L;aQݯaQaQL;H7;3;36.6.7/;3;3;3;37/2!o222 ) )##+##+##+'##+' + +3/@J$$**?.UDrY|VE!!c M99:::JJJDDDDDDDDD@@@EEE[[[""f""f""f""fggCCv++MbbEEV!!2EEV!!2##4##4eev??P??P++<++<<<<<<^Mtc^MRAJ9@/913+3+3+7/;3B:B:H@H@>64,80r\T 6 6HR##))<<<<**| 6 6 6 6 / / / / / / / / + + + + + + + + + + + + + + + + + + + + + + + +!!9!!9ss!Z!Z)!3+7/;3E4O>^Mtc^MRAD3@/3+3+3+3+7/;3B:H@LDH@>64,80r~??? 6 6LRii##m))s''k33waU + ++ + ++1 + ++11111111̻̻̻̻ջ̻̻̯̻̻̻ !!\\~ضضضجĬss11R!Z!Z3+3+7/;3E4O>WGcSWGM=D3:)3+3+3+3+7/A9B:RJRJH@>64,80r80rǶǶǶǶ鶶ضضضضضضضإmm~ 6 6HRciiiaaUU + ++ + ++ + ++ + ++11111111կ 5-58888!!9!!911R11R!Z!Z3+917/;3E4O>WGcSWGM=D3:)3+3+3+3+;3A9H@RJRJH@>64,80r80r'I'I'I'I88888888 . .88FLLLAA;7 + +# + +# + +# 6 6 6 6 6 6 6 6***??P + +; + +;JPo u)!)!3+3+7/7/7/7/9191@7JATDZJZJJ:913+3+3+3+91@7D;I9_OWGM=913+/'/'/'/'/'/'$$y u uokkXR@@ + +; + +;""" . < < < <1111 + +# 6 6 6 6 6 6 6 6޹**++=43+3+/'3+4,>6@7D;ZJZJD;:191/'/'3+1)7/A0A0M=M=A97//')!| kaRH;7III''' #####$$$$$$'' 166GLDeLDeOGpOGp @ @W]$$**B1L;JAD;@7:1913+3+/'/'3+@/J9P@TDG>=43+/'/'3+4,>6@7D;ZJTDD;:13+/'/'/'1)7/A0A0M=M=A97//')!| keRH77III''' ####......#$$$$$$ѴŽ'##+,,=BBSLDeLDeOGpOGp @ @W] **<+F5JAJA@7:1913+/'/'/'3+@/D3J:J:G>1(3+/'/'3+4,>6@7JAZJP@@7:13+/'/'/'7/;3A0SBcSWGA97//')!| keLH77III''' ###KKKKKK##$$$$$$ɽŽŽ'##+66GBBSLDeLDeOGpOGp @ @W] **<+F5D;D;D;:1913+/'/')!/':)@/J:J:=41(/')!|/'/'4,>6@7D;TDJ::1:13+/'/'3+7/;3SBgVcSM=A91)/')!| kaLH77NNN~~~EEE ####  $$׳ijijջ̻̯Ƕ:!@'@'@'@'@'@'@'AATZ{$$..::@7@7@7:1913+1)+#}+#}+#}3+91A9A9913+1)+#}+#}+#}7/A9@7D;JA@7913+.&.&/'3+B1F5I8rSJG>913+)){##u b\D@77NNN~~~EEE ##  $$űŽŽŽŽŽŽïǶǶǶ@'@'D+D+D+D+D+D+AATZ{$$$$..:1@7@7:191/'+#}'y+#}+#}/'3+;3;33+/'+#}+#}+#}+#}7/;3@7D;D;:13+/'.&.&/'3+B1F5]LrG>=491/')){##u bXD@77NNN~~~EEE  $$ŽŽJ1J1P7P7L3H/H/B)AATZsy##}))3+91919191/'+#}'y'y+#}/'3+7/1)/'/'+#u+#u+#u1){7/;3@7D;@7:13+/'.&.&/'91B1F5]L]L=4=43+)!##u##u\R@@77NNN~~~ jjj$$P7J1T;T;R9R9L3H/AATZss##}))/'91913+3+/''y!s'y+#})!/'1)1)/'/'+#u+#u+#u1){7/;3@7@7:1:1/'/'.&.&/'91B1F5]LI8=41(/')!##ukXR@@77MMMjjjBBB %%%   !'nUbIgV{jnkZUDUD@@LLX\i))s+#1)1)1)1)+#}'y!s!k'q+#}1)1)1)+#}+#}+#u'q'y+#}3+91;3A99191/'/'.&.&/'91:1D;JA@7913+##u##u keJD > > > >MMMjjjjjj %%%  !'ɾƾƾƾƾnUk| wfaP@@LLX\i##m''+#'+#}+#}!s!s!k'q+#}+#}+#}+#}+#}'y'q'q'y+#}3+91;3;3913+/'/'.&.&/'91:1D;@7:191/'##uq keJD > > > >222VVV$$$"..''8))1##+'!!'ϠþƾƾƾƾŠnUk{j|  kZUD@@HLXXciqqqqqq##uq'q'q'y'y'q+#u+#u'q'q'q'y+#}3+917/7/91/'/'/'.&.&/'91;3A9;3;33+)!|qqeaDD > > > >222VVV222$$&&.&&.''8''833D33D))1))1##+' !'ҾƾƾnUx_ gV{jkZkZkZUD@@LLRXciqqkkkqqq!k'q!s'y+#u'q'q'q'q'q'y+#}/'3+7/7/3+)!|)!|)!|.&.&/'3+7/;37/1)/')!|qqeaDD > > > >222 + + + + + +##+))1''/++3119++3))1##+##+' """eLeLaHeLaPaPeTaP@@DDPPcc keeaw3"3"8'...$v$viiii'q+#u/'3+3+3++#}'yq##u##u##u1)1)91913+/' k k b\TPDD > > > >222 + + + + + +!'!!)''/''/!!)'''! ܉@QQQQQaHaH[BaH[JaPeTeT@@DDJPcc k kea''?.I8D3D38'.$v$viicc'q+#u/'/'/'/'+#}'yqq##u##u+#}1)3+3+/')!| k k\\PPDD > > > >222 + + + + + +!'##+))1))1'  'MMMƾƾĺ˺˺˺ؠ΄ooEEV!!2!!2!!!EEEoooooox˺ľƾƾS: S: S: S: W>W>cJcJ@@DDJTccqqqq''33I8UDgVgVC2C2.&$vcccc!k+#u1)1)+#}+#}'y'yqq##u##u+#}+#})){)){)){##u ke\\PPDD > > > >222 + + + + + + !'##+))1))1' ..a..aMMȺx/@@ppp888888;CC!!2!!2!!2!!2!!!!!!!!!!!!**;**;**;TTennnn/@@xA(A(A(A(A(A(A(M4@@DDPTiiq##u##u)){''33I8UD̑C2C2.&$vcccc!k'q+#}+#}'y'y!s!skqq##u+#}+#})){##u##uqee\XPPDD > > > >))) + + + + + +'! '))1))2& I,,**nh$s@}yuqii|c|c{bu\qXkRmTmTiPiPeLeLaHaH\D\DZAT;T;P7L3L3P/P/J)J)D+D+@'D+J1D+@'@'C!C!C!gE@@DDLR\ bi##m##u)){3"?.I8UDraraL;8'))thZTTZci##uqqkbbe k k k k khhhhZZTTDD==@@@@))) + + + + + +'''##+&& ,,,,<+*nh*s@yuqiii|c{bu\qXqXmTmTmTiPeLeLaH[B\D\DT;T;P7P7H/H/P/P/P/J)J1D+D+D+D+D+@':!C!C!gEo<@@DDLR\ bii##u##u3"3"?.UD^ML;8'8'hhTTTZcikkkk\be k ke ke^^^^ZTPP@@==D@@@))) + + + + + +'''##+& ,,\\P?*nh*s@yuqmii|c{bu\qXqXmTmTmTiPeLaHaH[BX@X@T;T;T;J1H/H/D+D+D+D+D+D+D+D+D+D+@':!L*vTxx@@DDLR\\ci##uqrr''|333333''h^TPTZccb\\\\beeeea[PPPTJJ + +D + +D::==D@@@ + + + + + +!''##+& ,,P?*nh$s@}yuusmm +i{bu\u\qXsZsZmTiPeLaH[B[BX@R:T;P7J1J1H/B)D+D+D+D+D+D+D+@'@'@':!J1vTxxx@@DDLL\\cckkfffrww^^PPPZcc\\\\\beeeea[PPPPJ + +D@@::==DD@@$ + + + + + + + + + # :)m==ť33]WrP|||yuooii|c|cu\u\qXqXnLhFdBdBSBSBM<M<S1M+M+M+<+<+<+<+;*;*5$5$77bIkmsim@@@DLLX\cieaTP U UPPTTHHHHW]]]WWWWccXXWWTP + +L + +LRRJ + +D + +D@17;ADDD@$$ + + + + + + + + + )#:)m==mm'']SrPyuom +m +ii{b{bu\qXnLnLhFhFWFWFWFWF];];];S1B1F5B1<+;*;*;*;*aHlkx_cccm@@@@LLX\iia[PJ U UJPJPHBHL]]]]]]]]ccXXWWTP + +L + +LRRJJ + +D@177ADD@@$$ + + + + + + + + + + + +##:)m===='']WK:^<dBdB^<^<^<dBdBcJmTmTsZyayayakrr||nnndkZkZaPUDT2T2xV<64,,$,$6.6.6.6.=4=4QAcStchWOGE=1111''++********..8888DDDDDD88..,$,$ffRLLL&&& + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +555PT9/C2!T;T;T;T;U=U=_G _G cJiPmTmTs[yaaeiiimmmmimmi|cu\qXeL[BP7J1H/B)7&7&]Lru\u\qXu\RLLLLLX\i##mii **..88>64,6.6.:1:1@7@7G>G>cSwgtc^MOGE=A97/1)1)....8888TCTCTCTCYHYHYHYHB:6.&&pfRRLR&&&& + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +515TP + +3/C2!J1J1J1J1I1I1I1U=cJmTsZsZya}ekkssssmmmsssm|c{bu\kR[BT;J1H/B)7&7&I8r{bu\u\qXRLLLLL\\i##m##m##m$$**..88>64,6.6.:1:1D;D;SJSJcScShW^MOGE=A9;37/7/..8888DDTCTCxgޢsbsbYHB:B:22|fRLLR9333333311^**^1+///33333777;U=I1J1D+?.3"<+sb n{bs[s[LLFFWW]])!c)!cii##))9191;37/919155;;;;;;IIUUUUUUIIII????;;551111<+B1L;L;P?ZIZIfUfUfUZIP?????++nLFFL9999333311^**^11333333337;;;_GI1D+D+?.3"<+*x {byayaLLLLWW]])!c)!cii##))3+91;37/913+115555;;??II????????333311111111<+<+<+F5D3D3D3P?P?D3D3D3++++nnFBFLDDDD@:::55^* *^Ð;Ð;;777====@@@D_GU=J1D+?.?.<+*n}e}e88888888)!c)!cii##))3+917/1)3+/'**]**]**]**];;n;;n;;n;;n;;n;;n;;n;;n''Z''Z''Z''Z''Z''Z''Z''Z''Z''Z''Z''Z''Z''Z''Z''Z88888888JJJJDD@@Ð;Ð;^*    ####### ) )# *^Ð;Ð;;;;;==™G™GŜJŜJŜJŜJ_GU=J1D+?.?.<+*nkkضضضضضضضشmmi##))/'3+1)1)/')!TTբբճ泳泳泳泳泳泳泳ضضضضضضضĚPĚPLLLLJĚPŤjŤjŤj]<///2!2!  ''''''I'Kđ<đ66>66>66>119119++3++3BBBBBB vT!ĢoáLáLȞTȞTȞTĚPŔAŔA;;3//9BĚHŜJŜJQQQU4S1W5E4v!yas[s[s[###$$™O™O™O™OŜRŜṚXЧ\Ч\Ч\ΤZĚPMMˡWˡWɠUɠUʡWj YH&<+ <+ <+ &&&&&&&&&&&M+M+M+M+1™GɠUɠỤX̣X̣X̣XŜRŜRŜRŜR9339@DĚHĚHȞLȞLȞLȞLK;"K;"K;"ueLeT2eT2eT2eT2  #$$$$#™O™O™O™OŜRŜṚX̣X̣X̣XΤZĚPMMˡWˡWɠUɠUʡW=]]]sb@sQsQsQsQsQsQsQsQsQsQsQsQLLLL=™GɠUɠUƝRƝṚXƝRHHHB|)|)39@DĚHȞLȞLȞLȞLȞL''''####  #$$$$#™O™O™O™OŜRŜRƝRƝRƝRƝRȞTĚPBBȞLȞLɠUɠUʡWʡWWWá]W?I̪U̪U?̪U̪U̪UI?I̪UáLFáLF™GΥSɠUɠUƝSƝSƝSƝSȞLȞLĚHĚHDDD@@DĚHĚHȞLȞLȞLȞL''''""""""  ##$$$$#™O™O™O™OŜRŜRƝRƝRƝRƝRȞTĚPBBĚHȞLɠUɠUʡWʡWá]á]á]á]3̪U̪UI3I̪U̪UI?I̪UáLáLáLáL™GΥSɠUɠUƝSAƝSƝSĚHBĚHĚH@ŜJŜJDDŜJĚHȞLȞLȞLȞLȞL''''""""""  ##$$$$#™O™O™O™OĚPĚPȞTȞTȞTȞTȞTĚPDDĚHȞLɠUɠUɠUɠUƥ[̫a̫aƥ[3III9EˡOˡOŜJ@̣P̣PɠMɠMȞLĚHȞLȞLȞTȞTƕJ4DŜJ̙D.8̙D=™WȞLĚHĚHĚHĚHȞLȞLȞL¡O¡O'''' ) )#  #!''''''!™O™O™O™OĚPĚPȞTȞTȞTȞTĚPĚPDDĚHȞLɠUɠUɠUɠUƥ[̫aƥ[ƥ[3III9EˡOˡOŜJ@̣P̣PɠMɠMȞLĚHĚHȞLȞTȞTƕJ4DŜJ̙D.8̙D=™WĚHĚHBĚHȞLΤRȞLȞL¡O¡O'''' ) )#  #''##+##+''!!™O™O™O™OĚHĚHȞLȞLȞTȞTȞTĚPD@ĚHȞLȞTȞTȞTȞTƝṚX̣XƝR]q'QQQŜJ@̣P̣PɠMɠMȞLĚHĚHȞLȞTĚPƕJs(@DVVVVb ™WBBBĚHȞLȞLȞLȞL¡O¡O''''&&&  ####+'##+''##+'!™O™O™O™OĚHĚHĚHȞLȞTȞTȞTĚPD@BȞLȞTȞTȞTȞTƝRƝRƝRƝRͫ韼QQQŜJ@̣P̣PɠMɠMĚHBBĚHĚPJƕJ4@@V˘߶t™WBBBĚHȞLȞLȞLȞL¡O¡O''''&&&  # )##+##+##+##+))1##+##+'   ŜRŜR™O™OĚHĚHƝSƝSŜQŜQȞLȞL™G=7ŔADŜJŜJŜJȞTȞT¡O¡OƜrccggggjjjjjjjjn{QJJoȦȦoooppIIȞTȞTȞTȞT''''&&#!!!!!'##+##+!!)''/''/''/++++++++++++##+##+'!#!!!!!!ŜRŜR™O™OĚHĚHƝSƝSŜQŜQȞLȞL™G=17:@ŜJŜJȞTȞT¡O¡Oѹrccgܩϥ{QJJoȦȦȦشpIIĚPĚPĚPĚP''''&& )##''''##+))1))1))1''/''/++3++3555555111111))1))1##+##+ )## ) ) ) )##+##+'''! ŜRŜR™O™OĚHBAA==ĚHĚH™G=7ŔAĚHĚHĚHȞLȞTȞT¡O¡OƜrccϥ{QJJoȦ￿شpIIĚHĚHĚHĚH''''&&### )'##+##+##+))1//7//7//711:11:11:77@<,,4,,4,,4$$,$$,$$,$$,$$,$$,$$, !!)!!)!!)!!)!!)!!)!!)''/''/''/''/++3++3++3++3++3++3++3++3''/##+'  ŜRŜR™O™OĚHBڱgڱg׮c׮cĚHĚH™G=7ŔAĚHȞLĚHȞLȞTȞT¡O¡Oʩ˺կ²²ȦӠpIIĚHĚHĚHĚH'!!!# )'''##+//733;33;33;11:77@;;DAAJFFWBBSFFWFFWBBJ66>,,4,,4..6..6::B::B::B::B..6..6119119119119++3++3''/++3++3''/!!)!!)''/++3++3119119++3''/''/'' ŜRŜRŜRŜRFBđإإđFáLáLB{{{{ijϴղòòïSƝJƝJĚHĚHĚHĚH  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!    !!! + + + + + +ŜRŜRŜRŜRFFđإإđFáLáLFԲԲԲԲǥǥǥǥءϠòSƝJƝJȞLȞLȞLȞL  + + + + + +    + + + + + + + + + + + +ȞTĚPĚPĚPáLáLđإإđáLáLáLF樹ͳčѮ{ȷԲԲǔǔǔǔܩܩܩܩHHHSSƝJƝJȞLȞLȞLȞL + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +ȞTĚPĚPĚPFFkòkkáLáLáLB˺سԲ^^^ZZZZggggHȦbȦbSSƝJƝJȞLȞLȞLȞL  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +  + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +ĚHĚHĚHĚHEEĚHȞLɠMɠMĚHĚHggܩܩٿԯ͚L͚͚lHHH1;:Ě@ȷύVVVȞLȞLȞL%%%%%%%%%88%%%%&&%%%%**%%%%HY&%%%%]]*%%%%'8%%%%77%%%%YY&%%%%'8%%%%LL*%%%%''%%%%%%%%%ĚHĚHĚHĚHEEȞLȞLɠMɠMĚHĚHggԯ͚L͚͚ᖼHHH77:ȞDȷȷύVVVȞLȞLȞL%%%%%%%%%^^+%%%%@@%%%%PP.%%%%]%%%%P%%%%ar?%%%%nnL%%%%]%%%%ar?%%%%rrP%%%%MM+%%%%%%%%%ĚHĚHĚHĚHEEȞLȞLɠMɠMĚHĚH̙D888551+****....w".88**إPإPȞDȞDĚ@Ě@;;:ȞD̙Dw"8̙Dđ +extern uint32_t _binary_model_sheik_sheik_00_vq_start __asm("_binary_model_sheik_sheik_00_vq_start"); +extern uint32_t _binary_model_sheik_sheik_00_vq_end __asm("_binary_model_sheik_sheik_00_vq_end"); +extern uint32_t _binary_model_sheik_sheik_00_vq_size __asm("_binary_model_sheik_sheik_00_vq_size"); diff --git a/twiddle.hpp b/twiddle.hpp index 170c7c9..e74f88c 100644 --- a/twiddle.hpp +++ b/twiddle.hpp @@ -96,59 +96,6 @@ static_assert(from_xy(0b1010, 0b001, 16, 8) == 73); static_assert(from_xy(0b000, 0b1001, 8, 16) == 65); static_assert(from_xy(0b010, 0b1001, 8, 16) == 73); -/* -constexpr inline std::array -from_ix(uint32_t curve_ix) -{ - std::array x_y = {0, 0}; - uint32_t curve_bit = 0; - - while (curve_ix != 0) { - x_y[(curve_bit + 1) % 2] |= (curve_ix & 1) << (curve_bit / 2); - curve_ix >>= 1; - curve_bit += 1; - } - - return x_y; -} - -constexpr inline std::tuple -from_ix(uint32_t curve_ix) -{ - uint32_t y = (curve_ix >> 0) & 0x55555555; - y = (y | (y >> 1)) & 0x33333333; - y = (y | (y >> 2)) & 0x0f0f0f0f; - y = (y | (y >> 4)) & 0x00ff00ff; - y = (y | (y >> 8)) & 0x0000ffff; - - uint32_t x = (curve_ix >> 1) & 0x55555555; - x = (x | (x >> 1)) & 0x33333333; - x = (x | (x >> 2)) & 0x0f0f0f0f; - x = (x | (x >> 4)) & 0x00ff00ff; - x = (x | (x >> 8)) & 0x0000ffff; - - return {x, y}; -} - -using xy_type = std::tuple; -static_assert(from_ix(0) == xy_type{0b000, 0b000}); -static_assert(from_ix(2) == xy_type{0b001, 0b000}); -static_assert(from_ix(8) == xy_type{0b010, 0b000}); -static_assert(from_ix(10) == xy_type{0b011, 0b000}); -static_assert(from_ix(32) == xy_type{0b100, 0b000}); -static_assert(from_ix(34) == xy_type{0b101, 0b000}); -static_assert(from_ix(40) == xy_type{0b110, 0b000}); -static_assert(from_ix(42) == xy_type{0b111, 0b000}); - -static_assert(from_ix(1) == xy_type{0b000, 0b001}); -static_assert(from_ix(4) == xy_type{0b000, 0b010}); -static_assert(from_ix(5) == xy_type{0b000, 0b011}); -static_assert(from_ix(16) == xy_type{0b000, 0b100}); -static_assert(from_ix(17) == xy_type{0b000, 0b101}); -static_assert(from_ix(20) == xy_type{0b000, 0b110}); -static_assert(from_ix(21) == xy_type{0b000, 0b111}); -*/ - template void texture(volatile T * dst, const T * src, const uint32_t width, const uint32_t height) { @@ -174,79 +121,4 @@ void texture_4bpp(volatile T * dst, const T * src, const uint32_t width, const u } } } - -/* - the following code is not correct - -template -void texture2(volatile T * dst, const U * src, - const uint32_t src_stride, - const uint32_t curve_end_ix) -{ - constexpr uint32_t t_bits = (sizeof (T)) * 8; - static_assert(t_bits >= dst_bits_per_pixel); - static_assert((t_bits / dst_bits_per_pixel) * dst_bits_per_pixel == t_bits); - constexpr uint32_t pixels_per_t = t_bits / dst_bits_per_pixel; - static_assert(pixels_per_t == 1 || pixels_per_t == 2 || pixels_per_t == 4 || pixels_per_t == 8 || pixels_per_t == 16 || pixels_per_t == 32); - - T dst_val = 0; - for (uint32_t curve_ix = 0; curve_ix <= curve_end_ix; curve_ix++) { - auto [x, y] = from_ix(curve_ix); - const U src_val = src[y * src_stride + x]; - if constexpr (pixels_per_t == 1) { - dst[curve_ix] = src_val; - } else { - const uint32_t curve_ix_mod = curve_ix & (pixels_per_t - 1); - dst_val |= src_val << (dst_bits_per_pixel * curve_ix_mod); - - if (curve_ix_mod == (pixels_per_t - 1)) { - dst[curve_ix / pixels_per_t] = dst_val; - dst_val = 0; - } - } - } -} - -template -void texture3(volatile T * dst, const U * src, - const uint32_t src_stride, - const uint32_t curve_end_ix) -{ - constexpr uint32_t t_bits = (sizeof (T)) * 8; - static_assert(t_bits >= dst_bits_per_pixel); - static_assert((t_bits / dst_bits_per_pixel) * dst_bits_per_pixel == t_bits); - constexpr uint32_t pixels_per_t = t_bits / dst_bits_per_pixel; - static_assert(pixels_per_t == 1 || pixels_per_t == 2 || pixels_per_t == 4 || pixels_per_t == 8 || pixels_per_t == 16 || pixels_per_t == 32); - - constexpr uint32_t u_bits = (sizeof (U)) * 8; - static_assert(u_bits >= src_bits_per_pixel); - static_assert((u_bits / src_bits_per_pixel) * src_bits_per_pixel == u_bits); - constexpr uint32_t pixels_per_u = u_bits / src_bits_per_pixel; - static_assert(pixels_per_u == 1 || pixels_per_u == 2 || pixels_per_u == 4 || pixels_per_u == 8 || pixels_per_u == 16 || pixels_per_u == 32); - - constexpr uint32_t src_val_mask = ((1 << src_bits_per_pixel) - 1); - constexpr uint32_t dst_val_mask = ((1 << dst_bits_per_pixel) - 1); - constexpr uint32_t dst_src_shift = (dst_bits_per_pixel < src_bits_per_pixel) ? (src_bits_per_pixel - dst_bits_per_pixel) : 0; - - T dst_val = 0; - for (uint32_t curve_ix = 0; curve_ix <= curve_end_ix; curve_ix++) { - auto [x, y] = from_ix(curve_ix); - const uint32_t src_ix = y * src_stride + (x / pixels_per_u); - const uint32_t src_ix_mod = x & (pixels_per_u - 1); - const U src_val = (src[src_ix] >> (src_bits_per_pixel * src_ix_mod)) & src_val_mask; - if constexpr (pixels_per_t == 1) { - dst[curve_ix] = src_val; - } else { - const uint32_t curve_ix_mod = curve_ix & (pixels_per_t - 1); - dst_val |= ((src_val >> dst_src_shift) & dst_val_mask) << (dst_bits_per_pixel * curve_ix_mod); - - if (curve_ix_mod == (pixels_per_t - 1)) { - dst[curve_ix / pixels_per_t] = dst_val; - dst_val = 0; - } - } - } -} -*/ - }