From 5e80d9ecfc05b73d53e68cc701ae787b26bd32d4 Mon Sep 17 00:00:00 2001 From: Zack Buhman Date: Sat, 1 Jun 2024 19:23:42 -0500 Subject: [PATCH] chess: add annotations, multiple pointers, translucency --- chess/chess.cpp | 23 +++ chess/chess.hpp | 27 ++- chess/chess.mk | 2 +- chess/cursor.hpp | 26 --- chess/cursor.obj | 16 -- chess/main.cpp | 88 +++++----- chess/{cursor.blend => pointer.blend} | Bin 804988 -> 804812 bytes chess/pointer.hpp | 26 +++ chess/pointer.obj | 16 ++ chess/render.cpp | 228 +++++++++++++++++++++----- chess/render.hpp | 50 +++++- maple/maple_bus_ft0.hpp | 7 +- maple/maple_bus_ft9.hpp | 4 +- regs/maple_bus_ft0.csv | 12 +- regs/maple_bus_ft0.ods | Bin 12054 -> 12046 bytes regs/maple_bus_ft9.csv | 2 +- regs/maple_bus_ft9.ods | Bin 12154 -> 12848 bytes text_editor/keyboard.cpp | 63 ++++++- text_editor/render.cpp | 14 ++ text_editor/text_editor.cpp | 9 +- text_editor/text_editor.mk | 3 +- text_editor/transform.cpp | 2 +- 22 files changed, 453 insertions(+), 165 deletions(-) delete mode 100644 chess/cursor.hpp delete mode 100644 chess/cursor.obj rename chess/{cursor.blend => pointer.blend} (73%) create mode 100644 chess/pointer.hpp create mode 100644 chess/pointer.obj diff --git a/chess/chess.cpp b/chess/chess.cpp index 2386b7f..18e0ff3 100644 --- a/chess/chess.cpp +++ b/chess/chess.cpp @@ -286,6 +286,8 @@ void game_init(game_state& game_state) game_state.halfmove_number = 0; game_state.fullmove_number = 0; game_state.interaction.selected_position = -1; + game_state.interaction.last_move.from_position = -1; + game_state.interaction.last_move.to_position = -1; board_init(game_state); } @@ -411,6 +413,8 @@ void do_move(game_state& game_state, int8_t from_position, move_t& move) destination.piece_list_offset = origin.piece_list_offset; origin.type = piece_type::empty; game_state.piece_list.piece[origin.piece_list_offset] = &destination; + game_state.interaction.last_move.from_position = from_position; + game_state.interaction.last_move.to_position = move.to_position; game_state.turn = -game_state.turn; } @@ -443,4 +447,23 @@ void select_position(game_state& game_state, int8_t x, int8_t y) game_state.interaction.moves.length = 0; } +void clear_annotations(game_state& game_state) +{ + game_state.interaction.annotation_list.length = 0; +} + +void annotate_position(game_state& game_state, int8_t x, int8_t y) +{ + int8_t position = xy_to_position(x, y); + auto& annotation_list = game_state.interaction.annotation_list; + + for (int i = 0; i < annotation_list.length; i++) { + if (annotation_list.annotation[i].from_position == position) { + return; + } + } + + annotation_list.annotation[annotation_list.length++].from_position = position; +} + } diff --git a/chess/chess.hpp b/chess/chess.hpp index eecc96e..f4ba3fa 100644 --- a/chess/chess.hpp +++ b/chess/chess.hpp @@ -57,9 +57,30 @@ struct moves_list { int8_t length; }; +enum struct annotation_type : int8_t { + highlight, + arrow, +}; + +struct annotation { + annotation_type type; + int8_t from_position; + int8_t to_position; +}; + +struct annotation_list { + struct annotation annotation[127]; + int8_t length; +}; + struct interaction_state { + struct { + int8_t from_position; + int8_t to_position; + } last_move; int8_t selected_position; struct moves_list moves; + struct annotation_list annotation_list; }; struct game_state { @@ -74,9 +95,11 @@ struct game_state { xy position_to_xy(int8_t position); int8_t xy_to_position(int8_t x, int8_t y); -void game_init(game_state& game_state); -void select_position(game_state& game_state, int8_t x, int8_t y); int8_t piece_list_to_position(const chess::board_state& board_state, chess::piece * piece); +void game_init(game_state& game_state); +void select_position(game_state& game_state, int8_t x, int8_t y); +void annotate_position(game_state& game_state, int8_t x, int8_t y); +void clear_annotations(game_state& game_state); } diff --git a/chess/chess.mk b/chess/chess.mk index 052f496..7d95d79 100644 --- a/chess/chess.mk +++ b/chess/chess.mk @@ -21,7 +21,7 @@ CHESS_GEOMETRY = \ chess/rook.hpp \ chess/square.hpp \ chess/circle.hpp \ - chess/cursor.hpp + chess/pointer.hpp chess/render.o: chess/render.cpp $(CHESS_GEOMETRY) diff --git a/chess/cursor.hpp b/chess/cursor.hpp deleted file mode 100644 index 78311ac..0000000 --- a/chess/cursor.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once - -#include "geometry/geometry.hpp" - -namespace cursor { - constexpr vec3 vertices[] = { - { 0.407995f, -0.805648f, 2.000000f }, - { 0.000000f, 0.000000f, 2.000000f }, - { 0.550770f, -0.527772f, 2.000000f }, - { 0.302290f, -0.556623f, 2.000000f }, - { 0.297535f, -0.852536f, 2.000000f }, - { 0.000000f, -0.762211f, 2.000000f }, - { 0.191836f, -0.603526f, 2.000000f }, - }; - - constexpr face_v faces[] = { - {{1}, {6}, {0}}, - {{3}, {2}, {1}}, - {{1}, {5}, {6}}, - {{6}, {4}, {0}}, - {{0}, {3}, {1}}, - }; - - constexpr uint32_t num_faces = (sizeof (faces)) / (sizeof (face_v)); - -} diff --git a/chess/cursor.obj b/chess/cursor.obj deleted file mode 100644 index 870e10a..0000000 --- a/chess/cursor.obj +++ /dev/null @@ -1,16 +0,0 @@ -# Blender 3.3.6 -# www.blender.org -o Cursor -v 0.407995 -0.805648 2.000000 -v 0.000000 0.000000 2.000000 -v 0.550770 -0.527772 2.000000 -v 0.302290 -0.556623 2.000000 -v 0.297535 -0.852536 2.000000 -v 0.000000 -0.762211 2.000000 -v 0.191836 -0.603526 2.000000 -s 0 -f 2 7 1 -f 4 3 2 -f 2 6 7 -f 7 5 1 -f 1 4 2 diff --git a/chess/main.cpp b/chess/main.cpp index 57a1f68..9046576 100644 --- a/chess/main.cpp +++ b/chess/main.cpp @@ -22,26 +22,29 @@ #include "sh7091/store_queue.hpp" #include "sh7091/serial.hpp" -#include "render.hpp" -#include "input.hpp" +#include "chess/chess.hpp" +#include "chess/render.hpp" +#include "chess/input.hpp" -struct button { - bool a; - bool b; -}; - -struct cursor { - float x; - float y; - struct button button[2]; -}; - -void cursor_update(chess::game_state& game_state, struct cursor& cursor, uint32_t frame_ix) +void cursor_update(struct render::cursor_state& cursor_state, uint32_t frame_ix) { for (int port_ix = 0; port_ix < 4; port_ix++) { + int cursor_ix = cursor_state.port_map[port_ix]; + if (cursor_ix == -1) + continue; + auto& cursor = cursor_state.cur[cursor_ix]; + auto& port = input::state.port[port_ix]; if (port.function_type & function_type::controller) { - + auto& bus_data = port.host_response_data_transfer_ft0->bus_data; + auto& data_fields = bus_data.data_fields; + if (std::byteswap(data_fields.function_type) & function_type::controller) { + auto& data = data_fields.data; + cursor.x += static_cast(data.analog_coordinate_axis[2] - 0x80) * 0.0035; + cursor.y += static_cast(data.analog_coordinate_axis[3] - 0x80) * -0.0035; + cursor.button[frame_ix].a = ft0::data_transfer::digital_button::a(data.digital_button) == 0; + cursor.button[frame_ix].b = ft0::data_transfer::digital_button::b(data.digital_button) == 0; + } } if (port.function_type & function_type::pointing) { auto& bus_data = port.host_response_data_transfer_ft9->bus_data; @@ -50,20 +53,27 @@ void cursor_update(chess::game_state& game_state, struct cursor& cursor, uint32_ auto& data = data_fields.data; cursor.x += static_cast(data.analog_coordinate_axis[0] - 0x200) * 0.0035; cursor.y += static_cast(data.analog_coordinate_axis[1] - 0x200) * -0.0035; - cursor.button[frame_ix].a = ft9::data_transfer::button::a(data.button) == 0; - cursor.button[frame_ix].b = ft9::data_transfer::button::b(data.button) == 0; + cursor.button[frame_ix].a = ft9::data_transfer::digital_button::a(data.digital_button) == 0; + cursor.button[frame_ix].b = ft9::data_transfer::digital_button::b(data.digital_button) == 0; } } } +} - uint32_t last_frame = (frame_ix + 1) & 1; - if (cursor.button[last_frame].a != cursor.button[frame_ix].a && cursor.button[frame_ix].a) { - int8_t x = cursor.x + 0.5f; - int8_t y = cursor.y + 0.5f; - chess::select_position(game_state, x, y); - } - if (cursor.button[last_frame].b != cursor.button[frame_ix].b && cursor.button[frame_ix].b) { - serial::string("b\n"); +void cursor_events(chess::game_state& game_state, struct render::cursor_state& cursor_state, uint32_t frame_ix) +{ + for (int cursor_ix = 0; cursor_ix < render::cursor_state::num_cursors; cursor_ix++) { + auto& cursor = cursor_state.cur[cursor_ix]; + const uint32_t last_frame = (frame_ix + 1) & 1; + const int8_t x = cursor.x + 0.5f; + const int8_t y = cursor.y + 0.5f; + if (cursor.button[last_frame].a != cursor.button[frame_ix].a && cursor.button[frame_ix].a) { + chess::clear_annotations(game_state); + chess::select_position(game_state, x, y); + } + if (cursor.button[last_frame].b != cursor.button[frame_ix].b && cursor.button[frame_ix].b) { + chess::annotate_position(game_state, x, y); + } } } @@ -73,13 +83,13 @@ void main() constexpr uint32_t ta_alloc = ta_alloc_ctrl::pt_opb::no_list | ta_alloc_ctrl::tm_opb::no_list - | ta_alloc_ctrl::t_opb::no_list + | ta_alloc_ctrl::t_opb::_16x4byte | ta_alloc_ctrl::om_opb::no_list - | ta_alloc_ctrl::o_opb::_16x4byte; + | ta_alloc_ctrl::o_opb::no_list; - constexpr struct opb_size opb_size = { .opaque = 16 * 4 + constexpr struct opb_size opb_size = { .opaque = 0 , .opaque_modifier = 0 - , .translucent = 0 + , .translucent = 16 * 4 , .translucent_modifier = 0 , .punch_through = 0 }; @@ -102,31 +112,29 @@ void main() uint32_t frame_ix = 0; - struct cursor cursor; - cursor.x = 4.f; - cursor.y = 4.f; + struct render::view_transform vt; + vt.piece_rotation = 0.f; + vt.board_rotation = 0.f; + + struct render::cursor_state cursor_state = render::cursor_state(); while (true) { input::state_update(send_buf, recv_buf); - cursor_update(game_state, cursor, frame_ix); + cursor_update(cursor_state, frame_ix); + cursor_events(game_state, cursor_state, frame_ix); ta_polygon_converter_init(opb_size.total(), ta_alloc, 640 / 32, 480 / 32); - render::draw_board(); - if (game_state.interaction.selected_position != -1) - render::draw_illumination(game_state.interaction.selected_position); - render::draw_pieces(game_state); - render::draw_moves(game_state.interaction.moves); - render::draw_cursor(cursor.x, cursor.y); + render::render(game_state, vt, cursor_state); *reinterpret_cast(store_queue) = ta_global_parameter::end_of_list(para_control::para_type::end_of_list); sq_transfer_32byte(ta_fifo_polygon_converter); - ta_wait_opaque_list(); + ta_wait_translucent_list(); core_start_render(frame_ix); core_wait_end_of_render_video(); diff --git a/chess/cursor.blend b/chess/pointer.blend similarity index 73% rename from chess/cursor.blend rename to chess/pointer.blend index ceeace3996e3a4d783aab393220b1809cdc65d8f..ab34813fc16806349a313f5d9ab330e6feaf4d71 100644 GIT binary patch delta 69921 zcma&P3Aj_$)jrP2O}Ih5R^;*-u~>Ty=%R9>i2uT|9u|Vd$0YzYuMA- z+2`csi;KoSdEwZL+7pMLxccKS7HxV+qH^@Ar>8DG@r?-^?>%X9_vAfx@7{g)-MeRf z@1*V{4qSHB#1Ep4XJilSK6J(n-PyhN>^}5>$GQ(WXxUMFd=L$rvG3vC`_KGq_hARF z>^|_o*Sq(hI=yu4KAokDc1;sG&akT!dX-9PbFn6=KIi+;ij8V(ZnEFE0I%jIO`@rvf zXW3!jdwcNuQ>RYt)_<8yX4&@-ST&+_+sMS=-6nMJyz|b>wmWWJH0(Ry`A+woxj*Ti zdiaUmbLPzHo-kp;vh9DqHriyj-FEB#(P4*oA92JH-9P!&{@p)3^04k)F1Kv^6Qpwb zZo7A%xbO7tALeIwAAQ>X-6zbQ(|zs4sip0Ixp4iNGiP?snl-C?_UzfEXExrq^yX$0 zN+Vm2E8X_1{DSf0$9EqwcW(C)Kgo5^{^^lW{)2;a-D9@@cK7z<59s+fcH)8E*=f1% zohKd8z1!sPcV{L|N8RYj2lZh3;s@q;+~eTx$x{y#?2PW+rXAUR^jSA|AAI6X%R=GI zXu&@F?9+Y750CBM_2?xCdE&&0-8<}<>Hc>1=iNK%zkN^W-aB_ncj0HpcJF)OG2Q#l z%y;iO{imoObHFdUx1atCC>lo@3-Igmz{p{(DiIomo7VN#PGsJ&8MdxG-yzL$%{zS ziNViIUAFS9o#OF_fAHkgQgrU=izaOl<~$ouF3RjQuJF6WGYbEIr7eT(ul&^^P?sro zKRq?9X^FLO@bvYNq>g&@>8Yhr=S@3c_Ya>?RoVLwcv91fm(zP3j56h2&&~$1cH##} zS zdQ5pMdt>~reY68e$ev^anU>g^MoSgDwP8(1)Sj>aUi$s>@%tnI(KNFyJ@5C>T{vclt{$Q(yXh)u z8ecl@iev&URyyU1@d6P!b-(%W}ht7rnNUd$|Eklx@ zELR*v)L1JKg>_rRc4{vl*wZ#?8BMTVnt#=V_!+V!mKHA_S9<5F+2KjMXmu8SdN8g1 z&X#wiVr=`+aaTN9diLs$1R$m8?vD6)S-49>7f($XYVP6@TXO-X9$kd>@8Fq(2BoFY z^+&UQVVJNAm&?xLZFcQq+FW3kk&5MAN)P@~j4Gz zE~sN`)8fk41{lXir)K(sc_EEYy~F*gX!;l4a7o9}HZaje@*fEX7+V>Z0JXGl<=oEn zWgo)bM)Da9I>i=+lTjU|b(NpCrCwZ%-Adv5qzuP-OST+NNvq)0sr0@&P!}(mvq9GO zNJUMfL@Gk4q6h{`^KO~h*5#^^ z4panTY27WCC#;RuNee?|X~~~vwxw<`uaFL;LRcDm>*Wb_gf#fkZQdiv%e801(AVRe zp#g{2y@Fl>AkBVATmJXfiAV>UfKb~#VFdLKs^DD(R%8#V=|C!kr5U$hp6HsVoxkq( z3!{aL#*Xhy{(hDXa!+=%hqRYoyLzJppf<$UVt;r4w78=C&2j4E5a+s* z`-z%ebH|0zX)wEm&n-{0*V{lxsuTR;yE+m{t%SkU&pE*j(076ZC0#twVmYrCSJZYX zC9ApUbhX;WAU#cg$M(!fv8;Sl?Tl+BtY#k3bt$@LT3m7c!lb5wMzdE)8x$TDkP6Xlss7vp@ zFgjDMHhv^UX%VKyCDyn|5$3b^bR`5aeD8(P zS!%F+q#0zIDz8JBND=1Yg_dOL!TUNAfLNb?Pg_?PZG-jgQz{y0H~AB_yXgK4qu;9C zY~JiL%_Z!5judvWm%8nNjszfR-k<0`OU)XpuUYD$*_rzd8Z=1?MO;W1K6qhN6tiP$ zz7Av(*1PG$Ep1+7VV8BsCGDSk1LNnaEyB^&*7ik{M#?rOUOM&S_;70ACxPTpY56c? zXtZS~vO;E6*KW2|10^gP8ja|rh>+ZH8^)lP<~}r{lM*75&)6mn%n)rXN+=>Ex2rp? z%1WzLiA#vc9BFG4n57{PkLaX?i1aVb5im=W1wjcB^}X%m7ntFcZCgfkQbb7RPu7W` zmX@j+mk?3-r?jgy5tya5f}n(mu6t!j3j)m2s7IvDTtY-`upz)K%@PD9L{ttk1em2o zf}o@aajEq;n5C7Ebac3Y01glkOVOhv5|ETeJ=z{uXld6+M~va<;m4M)u20~*T#oU_ z0fA-@YxJ|1Bgjbo`X5hewA93o!zd`NyQF=z14zhyVtq|h>_;*aY%Z%%Ewe9dKka94|uf2!22*9K}KzcZ4;@9qYYk_^rJ8lWF(W; zWd+y7!H0>Vp9x1hpoegkg+WCBgn|TVo}f(XM;I~4tE3@wTzE`*F=U*el)Ek$jDc% zX=#fLn_)|36gq%}+$r9)u83h&bZP`R$t?*1!O>bPiM26_I*o1bM@H2j`Df^@9m)Ex39Cc_` z9O|j^>nfBioBY%@QKF`z($Xu3CBR!2JtIOG3yU|8o+|xv)gBYvX$DdGrMbl5=sc%T zzZD_O_-<@M$JnQ^^rbv49A$GUbF>CAd1N$xI7M_7Rn=Q|ktpJdDvkP2dt7PD=Dr{v zLQ{ygie8HsWpxQ_wu(-++}y3DLsTYl>qn)Fq^)n$a%s`a!-n%Hc^mJ6#v#v1&GMH| zn#iaaWpfXUl3m78%!_pY0WrU8d}r=g78TR-F;*`BLejA23F#`AFv#3-8qlVzZ;CpR z?bB7MpF3G8%htSdP1H#d*oq_IPw?0BRx5J*Jwh!OBhDuJgHf>{9S1$Wc##JSZ{b(IXPOtbnU8*CNfY4 zj%}dmWrJ|@#|Gd+X;(_?Z5{^?eob>Fo!ObbKb`K+V}WQ2er8|0C@JpZ=>2lBJF>Q`!Ux zgsca2?OU?d5)5U;z__Rdw>rN?FbT-eB0yKiCZeB4iS&Yl2TTh{ z!rTvITU48aqf1&6h^)G3y=Z14QNc0U!UxBN%{Pi>M`!Ejio(5ic`N_M272Ao%vI)S z!PCrhvO|>Prx7@Qx^!qXVK}MWdDgRX8fzaYkd+WvmH)GEn$((oprDA5?04+42`WBN zP(nm`mK_R$X&)#kBBbsRP{X3zVzSkD5g|=4gBs@R#}bMNDPCzGIzSCe6haXpHHUy2 z)+mG`LK+SMHEcReAQTaj`hyt)HOx>5MTBG>0xCXLP(noBdkoC5LX}WN2s;jo z5aF&5z+r5AG-3=ppBs(j0viSHmOb@5uFz$AjfsZ zG%UO?Hlo_z85QMvt6o%PqrHAKk%2I z?5Q#j+GUGrzGgvJ>Y^^Jc~!RFE@9B=y9HreDrEcgW8*RN0ZMF3MG@K1D-=+Bwp3%%6c6SVzvM_0iv2M!x_M9IlCV-A}roMlH<~=En23TCoF)%vl>0d zGDQra`J_};_uV0qEf(^9;;%hzba1LezpeWx%E*Um;h3IPJL>)kGK_PetBb~|6i$Vq zheS`X@`? z>ms^Ze?cH6`S5VVgxz%3YOznWUEABZO)9Ol@coYJFUCi|m0h&UsRkB=XX++@ctdz_ zV)R7S69=A8KSKL$fis$HFvG|g?SD9&U zb$Ob~Svluv@zJ<^DDJmcB$YdonyRwBBC_H(_Z;ug$T#6-+1v$9bo;(%M@D*J%F=Z z2au5SG8K_vy^2$`0gSSjX)5IbTjS$|asZ>t%d~~olVM`RVvU|@4q&7Xv@mFk42%JU z;eehnyi8Mc%6b7|3}BSKOj8Wp7zkqkqsz-VPwA8~5XJyT>L3qe00SM5FdWbmhL>py zs->ksurtj8jIx($s>^%BW(&d?!07UFj!b8OX~(|<7^#Cj441gs=nJr-fUrT)0D0ib~s`C!jSds4&Yx6dztD5TA!!%aP$gkaQ z7}K-vaI}ZZh=F-+57k#)dIZ`-U9$F2w2YU_!v;T&o=qg5I1`WB^`7cNV#imRBlY+S zVOCeoljEz2Y^9!7(`|;>Vrz0_U=+o$oQt-D@gx4@+vTMiC=Q z-7i(uA;)Q}Auk$P*Y$wYRZVr(d~FfRh$*iyjOkf)ykaOL2Ikdc)mNSI3vD%XY1FYY z^Hf81=&wXNgpNO4T6o1b!su(`$+na?15$ltY-r9UOk<_FS8Otbxch~=$&{{dKZ3y? z_a&$~-=?&FL`sT`_4oN)t{i3Ogj&CW)T10OJ2BcK0cyBUv#=P}oEYtxz$Vb2m-OMy z)s4fMn>O2|$SOC!v$&-_3dA(`n6+NzcRKR1z){4;vnsh8GqNfR+_|!5DHh`m(CUhl zwLPKHJ|yOY0_5?}FnvNxdJKxv`dfLZZ4#dTJ5FID*N~rOIjmbCA1M3Zs_FBo@%V7w zsZrLS$J5>Oh6`o)e6H@EE3PhgnW-&$nt#Sa^fb3zpKpq;>I@$&j5h4dfAKE75C`yg z>TTgs^{PHk&JM%Sjn^ACoSL~0>{3g%xkgsdtV)*6I4EJ^X}XJa5g{2bo0jDYp@@*Y zLqHAd6haXpWru(owmn@S6cJK)2&iGMLMS4n=@3xEWeTB)khC`=s9}{tC?bR{4r&;3 zhU|+W!tp1-VX_Fvut&Hfsk>@6J=+-$mzK&AodZZn{=R?Lvh|Ii=cNuHA?syYO7@Mn zq|cWRAQZh!OPPLz75`1BJAszqiVhzoB8CALl76g8OKAEYg2v#0o)~xz>x$?SS{pG8 zAf%tR0Z&V8B_phpW_189!%~?v#xzjluyvQFyt>R6l}55m$iiB&i(crSVPa!pGYuxDs9iyI$*mLf@}@ zg@`7S)F$($#poMjySwEXrFYYKUY8>~bE7T0ObgFi7d4+(m+&>D?d*Dyc~y6B@^G$v z15H zKy=a7ZwWxD1VAJ3NXjrC&ORr4VXHmNPI^asxSeUF-%H=jmLdAaVO^*QhIhV}?`*HbgSQL?X#7Il1F z^E!JHN*hI;qrSXfvC6CMV?j@MzAt{L$D4*dFN_{az>hHW3b{4vNHSC3u#Tt3+&_+! zSSMd3u_A~tqZGAwIEbX$i`IWI85pxfp56>%LGR`ahbmu4t&Fn{=MKRCoaFjF8$yeZtu$lM>%nYhYSb4 z;yS{iS43}gQchg)VZ(uMxL;f;xE?u&(<6oh-|U|E2eDgrIrUW@H5~YcyY?!Y&cXO5?(o=^T8m;3y}q`MBZ0SKJn1o4%c|7k!iy zmwL)@;2Ung8w5u=ap|WG2fpEstO$;B;xf+|4t&G?W{Kb^CocP};lNki<{{h|z1~SV zak*8710QXA?M+dmlVZa1&lwDK!0x?SU=$Npc-~;31NOo#0;8C);tK`?9kBQQB(NSa z$KQ(v10AsVZ2~L1nA$2Y84Ps5I+hBIV!~=K8w_;7cDh|)6cbkOG8pK9O_(+u*~DWV5nBWZmtT9V#2ad z7z}j49;pe8V#0Dy8Vq#6URy3OiV3T{Zjpix*r#_3jAFuSe=!*7fNgNEz$hlH{)WLo z*KzrICq;xb)_BvZ#<1$qXtS`_{n3)Pt~X7N6q}LI_CT~r!pbuLza0*FAX?K&KJ_Kv zG9K)xz7RfoFdE&~{Hw{4n!brEM4y#K->r&EhK(MI=5$gCm8RY{GK`s%BkIv9VdTTn zk2+aNaOUp@h7tu=!+R^@$#D21QM@hvj#VN>!=3SntZFD$#fxEbO5=R$%dIsE?5Mtn z+p-N4A%&JZ9uqAnR#!cyTF9c7{6CBW?L8r^>7<;v!n=k8-s*tV2F;7H)Xe+;O@~(A~!u!!rMycTx(?aC~RLjFh=RGACk4v76 z>Yb3uMv$1=ho%Z#H8C<=_LN>^Tuxm5Bg28;gBuned0LdRl3@5HMxey}e)^f{r3B=< zJCrX&slJ}7Wcc9O=;=bE`21V=e>`OggpzT&nF*RGaODJQP*h2g+gTt~R`72VsooVenbh67)lP6i=G zysUg>5KvXsi15~Hx~*|JRn-Q`H_fEe!8hC&uSb=(O1JTmq7xtai%c~Xt84zEQ;k%r zsz;^@CQQ}nH^n67#C63C2fjr)WsO8hIdP2^!+{?r|5c)-h>+x9gMg}#&BL$$7G2lY zjGG)Oyr1xvc#mRO{P$>FxZo|B+@w=os?}&P6IL~3UsQQp_C=Hvml@YQT*xc?p5 zyQPyRM+&oN{9RW$6<5Wqu5wPLs_c43feAJFc_&4L-L`gMezPuJ}k)QBGXuG{b>!xI5Mfj&kC%ryCA@!#(-2;3y|9cZT7> zH{4sF2##{%@@EkJ3J;bKwjl}^fuOWt5O@D(>YY%Ob4C*{Q9L_^j}@NI`P`a#*@JlhhBx1}nk z1gUPcwo4#e9U6}flc$&UG{i2VP-|O}LlUty!+AWyJBgJ;Yo&@G z?crorcsx+d^gZniYuAsB9=%YGcLc$|`kzb#)9g)FPTryojMKZr?TNxnNxo8Ir*{PL zV9mgK8zn5=Aa-y2>1HGQS9@d+DNgU2KRXylSNV6=%JGz*-c_1@P&GU~vG<@#Pw!0W z3OMo;RaFLRg3_4?eF z?&OzpXK}1F9mKIxyIlv?qG7Su+GqNEND6k+S=1E6r1H1Fp#ci%hvZ!=I!qcrl`h14 zNJekidoxjo3G_(})L*#6om9JF*6`R1@dLz8m~n3W;c(F|EkimSKmxoM1yCgBFAr}H zi^W52li0ZUfj!I}PHq_zN1XbFEma|p#C3*$rDE0i{(=(X%(imuMGTD89WwB>L53I3 zwqs*!K)D;g`D+-8`i7Wz>FST;2{h(^Jx-Sl_l}6A6X-a*5z0R0u|DrIaH^vZweRed zK7U64dEOP-1BOhSf43tG+#-alUFX;tczzFiT^8Qi5f;l}7)~&othQFjVP%K(;e}?V zoL-C`LyA7kd|{C{c9z96L}O!H#s6-x?>MGDxBq)~ps#NqzH83GZdkN=>;>BCy3?3Q zZMt7zlFZD9eY#h+c*CaqnB@8|^emq`Rtm0{ab!O*I~LE3k+B!Hy1?RTK5xy%H1ob8 zkxG0!w$=V>&6WI*yoJne2#miO<9Em5nXg$B>U`8Qcd+b+KyKq-%0M3Vjo65=)7N7U z%B=t~gu4Qr^oHJ*KQo)~I&8b8jO4S#JMFB_bOM3tk6pEz(hsSdgw!^%%fh?kT6PR? zZ6gdK$jE+b3}`Y&HXZ8-)4mZqB}{%M8rGKi#1KgB_~grP#5PG-8OO1Er(;)!e;&Ht zc6w=T-&V{}EzJ}>W|-I32y?a-&gAhe!`gEHGz0m6sndG-3S+(*+hll;+?Q#^nEip@+|cIfu8VH*&2z_G_3U0QShgmByrEy+%f2#yfm z-^a)ai?)wlp4d%Rn%%;>kutt^*t=zLczUyz!9!EgeL4*BuW^x&p|;%T<~33sGuP;t zNea*;=#C$aja?xxAq+cxTbcm&0-h_;v5D_k+G@GMjE;W!}_wa$ic@ za_j7s_O2|hgZVS9b?w8x4mA|&q-fEwoSAzwkGh>)^FKn+)3 zB`>6)h>$wlLDR5Cv?L(HBMSiQi!3$?J4}kj$FQ+@r@7*d$BtnunLXV8b_5v>FH;j6 z<G{6tq2gs)ViWa=VgRGzWtyT- z)?SEW03&^mN8xfdJ30?hIDk=9UbgW_Q*0;@1De(mWHh`?Qw+lxaB2X9W1hCyeLYPZ z*U6v{3beO7m62N8M9X9C6MVvO`&b-f7ekH-AZ2>=b4SWH_VMlh(Z(ovn)!y6Yv0tX z9UjG^h-+ChEmc+h7Lq(YsCiMyI?$vHPId8=m^_nZs`TA_aWLoZqf!{uk5hjOA0^}I ziFBQzU=0vWToV`q8-bG+EnHf+N}eh^-@2J;?px+t{algzQ)MoqyQtFd_}?Vogi@G2 zP^PHrifQU5l-UDi8GL}pw~j1}ZyinY;{x45=r{dQ{=dF;lt6U;+?@AWzX70u_gg>Y zi$?PLr7JB$rnL*LTqyTMND(6}ERw3~i8Er-S;+V4tW3%1;8Z8ilz2NSBfoixn}D9^ zK*dl-Ozl#`fLmR0kYXq!1}=(iaH|V*+P09{BcrOJDlY<%uRCXcFL}8*^*%2OiJa`n z*PWAdV)DEw;;$|~Os>QUdx4ieg!io<$7V<8>vg8dRc8kq0ToYc_uKnWnx1B#(YL$x ze1&DNXkxoFxk4Av=eX1$D-p0N- zcBY7stV5v9zU@pAAq9tk8kYY=E;SJ0QUh>UC&Dpos-A_-d0bK03T6rmn`FiX6qlWnm1kk@0azO=Or?8ioUCqQC*{iWr78~OU3*O5Ps$(QFIH5$|U z16IyHEU7Kg6mj7wuFxuc=XHm+mZ%eDvBY{%r3{{Yr=g?zyPw76%WsflaWM_}&g%ik z#^gJ%u*HNK(&htMT9gR0&0ks%BLZU2uZ(U0f8EJRR~3dgQ7 z5BkE{qPmkJLO5_h4J!nafXJ@I$`7B3a0~|)SMr9dhJE=D{Vqes`UO{FN05mCJ} z{}qJ;dZO@hk0~dlwc8QJ07Avfv_zjku#bBK7!5DyJ%#tuP&Vig#Q;Y7FCK-<*?VB1 zFC5Slg_mgx&d>y+7(l3anU=WP6g6y%VgRGzAGiG(bsH|E6vM#IZ_Pua4@KokQQX>essEvRSBq%P33>f3@yN zjuE+S0x9BEJoA=%hE3qLcgs!yWzoudP}NOURb6q9Ue6)JRUYW7Yyd?HqrUf}?~J85 z&K#?Fj9dpeXfqxgW_y_bpv02i$tX-KJ6JjYZN#E)l5+`NMU5XhAP*P8tFC!SU4$+@ za(FHNi0mQk&4S3`&4QYfPmHL(yLNSo zr@5W2oXQ|neT5=Lj1^VY%l<5zyae*L=~7~K?n;Su2$f!?-*mkAu4I_-L~Nsp^p4&( z_BB(CBJCG&b`Uy5+605Gq%Wem;)$5Nh-P=AF>QFzl?go_Q$&wZRUP}Jdh9U$R7-vDmG$xa>avC!K(aWdQ*Sls@O>hdwY#!$1kXzZ_h;#)wR~<63gjN`j?xV z+70ra`mOtyb361e7svN6*S^!QykJmcMnA!z)S>;$*?j+U;rRaL<^}!B>EHJ+=dSBt zF5cF+yg-`pp1uP4lICOm%cFK4$Igq=5ABs-yhxqfi}a`yN>ybIQxFS!1Ssdv>0hp2)xVrt(!ZR)y??oUU;lFImHy@O zzgS*i(+Cob0yyP~;a!wDcPjwQc&B8)LmJ_7QPvVt+t3 z+rM0x*}q)*LH}~sy#D3fS^dk!Mg7aQE3B;ctqYd-2jm~=UoJn>znprne>wZ_{^j~G zyN^cw*&X_q>(fv^M(g1~cHRKMnf=Szo%%f~)AMA_Fz540oAv?aZ}csPQ7^})`b(U! z{NeTaeb!IB`?61&zuzWG;3aNI_Nm9=ai20i?Dr{m=`SYqDcAG|4SLH92Bq|;26_d9 zy7V^y`jjjBlRJIN_z|2wW&TPT9mH>F^r^>>Tl6X8rzd*K`^e}2>e$!x{0Mom&{OwE zYZGv)pS>=Z?aqSBh=FS1fUAdRH_Ul6Chw$Gi+Izs;;SdF(Mvwus*d_w?55a6M#pGz z%p-c(3fwR!`+m?-JJ|WlMrv5-ct`dondRmq)AS40YV~Czw~#5K%Z(QWQeFCvhKzil zkh8a$I&i8dHZ)|)$WPvG7;uBU*`uR+;6LQ3w38JC!Us_f1*N%vxjam&$KuuUd$G7| zpw&U_<3O_~3$#AW`5;zL6z|mPzISgRsmk3Oc}f7$%2NWbRzLkDR){CidUo2#hUE^F z4T**mXRssHo#?P|Z&MmD^{_?5H1~j)S4e6NND<>oX;pQ`XV{Kv-nOGktZw?b_H@@n zN?!3rY|GBZuX=Y@Iy-g0t*_C5JVam0QzI}PI=_rfZ3j`jWGcUYIx@`Pr{#-K_$szT z0_%t#BJL92`YM)-F2qUVJ~qk=SxYOPX08(_L|4JnR6|{j{+A#7NV^6eE#^!*3W^;lQbb72A)w-J6(vM8908`kZ_P!7q&x^v{ce?u2+4XG+WcZc^n8hfP}o4X^IV# zg_C+9Fo00;GA%)~_ymF-YYbpC-?p7QP0=T72fW?X5p*hZt&JPnV%)~iyGafpq2Ohj zf-^esJPNs+G=Nd_GEJrX4hY=hB7!!W&M0`wmO=x7K?E5b{?t@-8^(|@;yN$vn1WpT z0quAf7bg$b>GI9iI5s4FFt7s{v!rM=`3NcZG;T5m)9m$Dt}jvZa#5Pl?h>vq$%@qY zgAvG!KGuPy_LO5kd;pQHq#(YZY>_1h=J3l0;XgOF>^_l>GZ3r>>aed4>@+lw$or2I zeJ-N*jycXWe~XoyZ%JyeCUps&MU9_PAP+CW^T#5f%RU9CZ-p9t8LMUSSi}x06?b?{ zf%5p}Zg-e2t5expG2qNnx#+m_+fjayQkxwC9%#;4Sf4$|`@dUQ5 zdimKo+_O!~tmq=W{AAv-1txo|nJ;+STxR9W9hTPbQe{04N$8C%Qn{ihZxM)HcaW7} zSe4N#DTCrqNw|oRyq7_>rz8d-%2cAMKP52$Qui{H`8(kUK$>2LHh(Al07&{z<}I}8 zb*H1lC3H6DWhleXOdUuOAw`E!8JC6Hyqfc%FT5|mV09oxgftvN zDphX~)6Y>h+eS)C9C<14Tj&diezRr7M2ZOEFd$Xc>E8yi{$2xz>o7Egr$pHpjvcPy zHMeIf^cy19u4sC@PB?;$rkAM+{V3xGJz>|00gTLTrjxdyTNvmWyp!AkG*R#}O+j@J z0S`|MVAQ-!Q*o6@0VVGLkoeDR|#Hm)%=3;s%`civ!VfG7+a$9 zC&pl!ywf_pYn{mLB1;i3ZmEx?O7}$aTTq%6eXIgY^{W=!61gIM`#X5UcWRNJ#Zjxa zBRXg2mOUo8+YBT3A5+Wl=sw#u-!~jQDB5fqgK6QPuHoNm2*(W+(btSt`Hw+q7Doh1 z^ZgK1*?uUgXGZpNddp%zw2_}AaX*Ce|Fs{Q$k-Tb-gi~(I$ntTjXG&k4BK$##Fhyi zEp`Ca@HG9oI4y{DOym|TMU1uag~l~zckMFG_UW?9SI$-~)qn0Gz0=_$vh#!7pi*V8 za(Q+7o-IS74i^&!`=S{dgFKhhS-p6#mfuEk^~<)K%BYT;q9Z_^ugar2XKXvcTYxRn zHO|bjrTR@+(U0LTDF%1A^0=1qo%x-N(vyy{a^>5S+J4w2J|o`*a;j~|>n@No@}XHc;0AeD{U+77PH2%IW-ya@U%#rUp8reT{J}AOiR}7Om~>)G zej>i7Iu`= zZJb2mdpV?W3t3h*_AvliiG)>kw*ZQL44{aRrbA52sN3XuHkS~Q{=T^frhN>ch>)B^ zpv=CPLlGfGhk$C|%b|#nnnOUv_i{QZBBbFEQ1LlnB1MF-HA&@lc3z_YW*s=}sG%X8 za<%NJ*#+DK6#LwXP(^IuwE9ufSAsf#gydP)XH>-IMNIg4Q3sHa^)f9%vvgq*7W6Hp z0|-Sg(-JiI5Y(jsgu0h$i7ugm@Rrg6gye5623lg!M$osEI-n;8FVhly7nh8nF$^FS zy-Z6OpF+S8L$eMb)V-Ybl&yr|5yJpN(&rE@(Lw{wsxdgACk8Lm5-k`(V;DdvdYP8s zyToAQO8a2|fzvwca`@guSSlxMS`ii<6_ekwv>t%*9*FKHlfEYKn$*10kR0W7yXX@I zT_76JhuBRv?r`0ncDcs%GPRCv7)4wl^Gl`5PuP$bg{%Wj%HY^`5+d77fOuvF*B`al z=Y)-(Gm^?Z<`*Mm1Z<}M!*<=O2_1JEA?s=VE-M#nY6yW)L}yV|{c=cLe(^|Aa1tQj zP(qh&D9h)n8hr1_ve-~wtx^e>8%mV_&kZGGW2{)wMGM=2qqE-_l6v%i_~%l&j%FS; z!%PeJTDkDBx@o&-7ctt*{ZduE@^;-yATJtO*L=X~%BlYN4(Xvz%8040FpTNh`Yy## zMhwhrB&sh=T-&ls^^4*0pG9$X3(X5g^}6Lc2H?EzD93CYe*IRmp z9cTZibwr1@x1}u#d-}uRo@RHla&n@i+7=VqT|zgLJ4;RV&bPHGknhtJ^<9h&E!9*0 zu3=I}esNc~06h|>U??LdJKiwh>Y=0T(p^Ld92C=_R_}XH+r*ug*LcJgja^3SL)m52 zcei5iE&~$VW$gWt?lRC2`U8~PMAepmwv34u5jH5o2ea6MQ&&YCrag;e&@U-?b zD>pqY->L?A3L=lR2(@{LPX9H zVA@`TB0`D|0oC>z6cJK$2&lH#poox$LqOHNMn{KBh)A)ORBl@hiU`R%gvz)GUpZi_ z0h}G)DI;9@g&y8HnHQj%m#KttTVvsXVgRG*WokWPL~l5NgaRk5 z6FB}5j)gIR!6{Bta9>)=Mx^v#0to*env;7x*9dT1ujw_ses%rQI$+>f?bi`KU8uM9 z>c22XPkM}%vp<*AFV-&NVp%*+s(jahyeMQHXi}~#$G`9l87?`-ye=M>pVLX6V1^o+ z%Hrxjr$aGcM}=zpIUUQ&d#Kvu%F)+eJrY;c(PexL$M*)-f5qj z4GbT>J(xbp7)&d_vU2`JwS*tTb_ruf4Ig1v6k-L>cQ4STyO-DEcd8cIyqs(~*}Js2 zt4!LATbJ8_`9B|F_Q)71E)v?cJ_LAi>6ubK>@kSKi(iY&55t^ghMDG0v2yMVbrM?_ ziWqBZfmBsb*(fg8YvlX%eb=c@S2fis8^`5ZOd0v*(+p#J677nij2M{LNK{|-(cywg zm`iwphia&vxrs{Qcy-LC@zb|WAb#7iu+#g^7g5Mg$9xX&?dG%dvhj8|R@dFl3Y8_IN#iaQ&eGW{1#vp;G;v~0g zIOd@EciXbh7^jibZ>&FhQ2d8q8=mrCa?RJQA+Q+9vxmj?9pYW$stnKZBq5rqvFX#!kk`L*&-ZQZQZDJ_y<1^OPW~o%7>+MQv<%yd16iv!9FXd(BtuhryGI6K8d8$cq9xyFZ=x=f6{TSzBAf z^;*iG^MpA0U3CpfKCw@qxp({*v(Op9($PdiwD4qLae7hf0#}v`6did}>AA;w@ z^7MrbHqe*C|HGHs<&TT0Q+_GFSQfry6Qc5BRt`AN=P7 z{(R`0kE`>UY<@$5-#p+K2zsAFpJQ#u?>_Kxc0R_g!{Km&aGvbvUBJiG^FD7lH2EEk z{GcK2pDYL)E{K0KJa}?EHP{9Foe-ZbA4s()7RPjiYSu;tRdH0%1ixdzFDuX`PTB9f zOMEK3>tPvaGOKj4(Z3#-zIULQTDbjs!@|e~@f{L*lx1kliR)z7ks&l36oN0k4C{1i%$52>&RtNOPXO((1oF`Li}WTH~YBr8TlB!-+;+o5L0m&0?NxtIa`Wbb{YE zQ74LG0ZU~VRg8}h)6bHNLG5vG*j=I_2M8bKaOZF1KS^LURp=p!`jfq=tptT~SaEiI zmvLMv&k?akAi?3U>myr1%j@-i!9^<+vwm3h%HS=-^mF7g0bDrrocMMLs0!zw6W?+; zwW{0t3_jN3@aQ@5ZzQmE2Q)+1)9TjJ`*iKntTw}TKjxaRO`z*OuLbAyh?*j1~ zGn~0<^J@9IIbK_T)5?Kn>eoE)a?cN&m&PfEq4S2t|aH z9Rg|?a)m%BA|&~SX#q8ys1S+>DL4ewuvQ@y5z=r7sA1NX0-=bI+?!?y)UZ+^6cJK) z2&iG#KL~^(LNaSi3#egy)v1Zr5V5Q+%tatNql-^Bu+}CrUlfnTp<(@QgaBXVcS0ngd#%H zZ<`iS!(|Ggh>)^FKn+8#5eP+uB;PSDpoS9_LJ=X&1$H(DYFMifiU`S{Y7kJvtZM~A z5g}a;0X3{t2t|Zs7n&AO!>-o}gd##}4gobRQ3yqZq)+psJcWi$uNMeKgp?fuYB*aV z6cLg<-L!xjK2r!qgcKYCYM6I}Kqw-l;Sf;6YK2flNbU?X1Zvo~A`prQsXGMJuv{S& z5t2F6w1676T_O;Q2q}JSJq>EOOd%8z(sT%@VaSaFp@@+DC#D6|aH2veBBaY9poX;y zp@@*|r=|teFzY6PP((=0A)tnp3ZaOQ^gm4tsA1Qe1ws)aWru(omMDZGLX!V7Eue-? zZxIMZgcKYCYB*aV6cN&J2&myRg-}FD?%!qz)G+T)0-=bIxs}({KA(^IW0X6J< zt3W6sq~Z`z!*YdCL`dp0(*kPP_BMe~L`cygpoYs7LJ=WNhkzP}EENbvgyjEYhCmG` zDug0Jx*P&(SgR0<2+4kKT0jl6ZWjnegwz}YYFMcdiU>)6VOl^9yDk$5MTC?c0%};I z5Q+#%erZ}j4V&H}5Q+#XI0V#iwn8W(q~Q=y!)FSih>+Y@W(d?U?@obGL`dBspoY~7 zp@@)7w`l=2?0c6$C?cfd5KzN%g-}FDYLJ{V$Sw%fux(W!6cJK%2&myQg-}FD(;=XS zAvJ+eL`Xg|L!gEe6+#gqT@C>?tW^j_gk)o;1=KKWxj-l)q~;J%!%BrvL`b^Dw166R zy;~p@5mI&ts9}jhC?X^oH!YxsP45v1MT8U_0%|y0ArukPa0sa3Glft@NG@T9Kn?Tm z6$nLy)Exq9SgjC>2+0gKEue;d?-K|`gj5^?YFMriiU>)ynif#Qw)YE!B0`D|0X1Bv z5Q+$CIt0`(xZA5d}tz+)bu*j4wd2Thr|Jj2q`-R)bN=?C?X{3y8uwbyoUus5g}dP>Y#?z3ZaOQ z>=5f1P{Y2D2!tX+Y7PN4ELR9cgrwIqEue;N9~B5igp?fuYPd`x6cLhK-?V@lhCC(^ ziU=t<1k`Y%LMS4n;Sf;6T7^(VNNxi&1ZtS|XMs>eNZlczhLsATh>%R1X#q9tS{DdK zgj5^?YFMHWiU>(-Q=gd##J4gobRQ3yqZr1Xx1Ug8xRHhoqg6cJK%2&my~g-}FDBeIhuP{U^m zp@i;D1kxlRyU?$@h zl?2@Tr$5UhS37SpruuW``bRaCo0`FR6~#eeheM*TU;1i%qajo~ORa1lvaiPHM3&%* z!L6V$>d@A4;g#3ov!maM^8Ld0$3%%l@jbaPhxwZfIjs8L>v8P@6CBxkNTQ-2-K%3~ z>RGjB!@>`ed&l)1Or~q&hUmJqS6AT+sj4n~XYfsftH*s9zgnLCe^7riVcnmT?QyM> z7e0yF)K>~yb!4mDra?Z8dcIX|O&a#Y)_ua9PvUb9%_&Sr*B~1Ng*Ho5U$eBak)^eb zEiJZNn)@G1(j*hFjFylUPG_4yg zzn_GBnEOcU=(ze}fLtE{@?phqhK!D@gJIoohRlhpi>{!i`LO6zsYhHhr81x~d) zm-Q;E>5h(sjA<9>n9k}ez}z+D!_d6AhPz|t+Me5pw%P z4h|iEO%$u6zoqVVsW?n7i+lPKG1pkod{}dtxQ86v`}J5+czLgT$>}{BtFL7ecgVAf zD$!VF&gmP-e9mdsS`K#y&Arj>#wCtukIai*|IV)$EtgurUMQV8*q)ww9*$7&HG}auhz2>x7k^uZgH== z!Zoh$w!zg?&QC0p#Y81GB}Sf~+&huFP7$UPd0SFcYAW|%Br5;dtFrPZDDcbV-h-=^ za^gYxDwBz^u-w+GGOKxCSdc~3=UgE=uYpc1EX$Q36T_C#MD_32B$msJKB|O1i`UJ!>f!~lwQl7x zMc6f7v%cOS3zh%5T~uDzt1|PftCYq)^loijNK9MTDy_7oMzg-u=$&e7*Kgl1+OF@_ zmVZ?VaxJ-jaP{0r6W7UX{&UZ4Mx|a+=EPrDm@PV*_1O&Qj2nmS6E3Q>ZV}$tAh~sT zaAhJjC95Er*QqxwZMFdJ*`-((?B9O3M6LOEWuKnjB|o*Upw!GL{y0lhiH(Fu10w`wUg)R{_o1RRB5E zr@qp9y9{VndvbJKEr+GcrE%1@KR~0|FykJnMsCrkQmrm&M@idhHjKJYs*#g{GAF*1 zRxiba4Vn$>?w4wHKa6@nsx^SBJ%ggzu;M|fMsD4MQmt|MC@5$?EP6=lk;4T}D27LmZqj!+L&f(Z9hwk(=E;IZ)y4fOPdEuYM)$S z%{on$d1#uoYd3PJZ+utl?c%LjTO!nQKz&V(d&?qkYlKPz)(CaV>x-KAH3C^%Bh+0- zh+keaKEejU6*J9y0p!xze59rMyrr3=EKMG5Y1hvztsHAv!!?e}N-1ma!ZQ3G-X{!Q}47r zS@HdP^?}}LtCcowf1@y)wwm=$1+;hCepKBcy!joSwu;edd#a_W(=2VAZfWgION+m? zG2ob@o+qhITUfJctI9ky&Dyj@&Zg}`t+#2bS(~bn6~Pa z*B3SK(-v8qw(71Ua+>#Pi>yss4a5;?&HJ=P7Sr||1=zIJtW8@D+or7s?)*9$0n-*a zOxp{3>&u$=X^SlScjKJ&@6COtZCM%8!9$|(^c(SS-!*%1x;2qfsZUsaH8dxz=EJ%j z<%2JB(D>aSipE=dHD<4IjdBIA9HlFL`Z}dypQUwvdT_16Y$0f9-o}h!zjw^wYo?^H z7paVr<_(tCmsnc9$C!{Tt8R@>sB zSz8=5Fk2inG+!JvYl{PNSR6EB_q~AVaZN`Ki^E-7?~idSebIE;_^Hs=^yd~xSN;iI ziM`kZ3b)S{sZ*21>b<`mET1dtDz1 zq1(yX-d}t5H#HxYjvlgi9MJiDB=-rUuZ<_esmIAF%}=YX!^5-BCF9|vJ(3%QO)H#A6Z)aSkka&%#ilDYSK^kbK-AH&WDg@ zZ3w9W8$xQrhmdA%2qA|dq?S2^G;h}zNPBOgMVwH+^VxW1^Pz6fj97GdP@>FNWm zwl!F@wgziZ_UTH)a^p44+Y*c%mS7Fn>x&58PEwJ@0-O7^7lFJjfOyc~`a5>N^!M%P zZ+t%gQVBL9-+NR?WS2^8^c3{9^*$nzw@>0KHDyn~J-D^>@m0Hp2VaObjh6L}qT~>L z@3D-`smVlRJ;~d^fjF$%Uj~i}{S!Ir=N};B2DynZ$l}*nU+Q(|(`IS;YnJARTACSV zX>z!wUH@ZgC1q)0GfBg`_hs{?n)C_nsiFAd;EfVR)u@dq4|D5d+9-$lpA6n4eEQPh zkqKDzrB03dQm0v4>X5@eNPY38PP4YuA%~?-T~tG|)M?h1I^-};+qK%3I?dWR)o^T_ zYCt|tHEZJ(IgC?{(}zMq^EOVA!#LIWeVn2xun$5G<5Yitz{ja(eIJA@u4>Y=v!grE zq4@Z+wc@Qm3*S%z7J{;hZ3m=69V!wm>Q_7_S4l&DB>h=POTF}G?wgjTM_bw)V`+VR zOUq*|&F^SwW}KzTT_m+Fk7~01?D$yvGo>2)^e4*NpSvVr%(}9zcRAB68SRsC!;t*1TO6k;9pRy6q!Hvo=zY!$nb}@sXlg8!5%;%s&K&_BQ-k8Wb5?ogx1ATe0zmrsMWR34!u?A7hTjZJw%2Y zaxZS#dd-x|4pJ{et@v$Ab30j@-r3UTE|%7JwX{6m()>hAGkZvCCmpIO%-E}SY8bh7 z>qd#JYV@{2KCIhYu59OR(>giYS0G@^1jPev5&@aim=hBSsRV&pKWv1Lyktx z+h{}%qftHQXwZ4J!HX4z`Xw>+9G@>bR?1CId<0P%N z(WqG)ZumhG>(t}NwayAVjfu6(w;9LV{ny-gm17;d!^l?I6KAF=)piqFX}gK33bV1- z)V%E`4EoXF5#gdqt;H#s?@5jHZ|eJ&Hm6%!-`~>m0hZ&OHw>UcOLQB$MtD)KrM_DaAP>*KPz!%ot?brN#u zBz4m}Nwd~T$f1+ed+#L8S|=fgPST*flQe5f26E`6Sz2wKq*+@sv;pkmqD|mS23iAW zW60s+a;R2IJIKB3g66}h_2rJP<#gU|vA@jQ<+cRqw)RNHuiC%$hsi`!^L9>N)*qqq zHbUMvv?|u2a$$70slZ1{vcxxKWiqiYCiUZc)gf>99`Ieku;}>K z-9jnfdSG-o!QruvMerLpnf55el`B0VjKR*hq*V& zO~R|x0nu||bbqgk^c#w`Gw1T6RylKq#1z%v>{W!k1&FV0+8Tb$?_>>spjTaTjWT2# zC>|ki7lX=QRc!0GW=#*ibs6Sg-Fjh|o{Psz2YfKqrg`liZ3$dh!t_lN9o0#d)|2JO z=3@T?Y*G#Fe6o9N377?? zK7BQ7(-%4H4b_NGU(MR|MQ-6e@*zcS`}EbUO<&|NeV^58o4%U0>8pO)^i@xN`fAqp zhR9+1Y5<(Rnzy|na@ZScV7@ohtbK+-4tqn5*Y}199rtdL!)KV)T5X?UG^^|X=(zse zlXl>R(L=p`m;akWZP|b18NHsrtuQnt>a+*t1Dm4kwioK91NV01M}vojlb>&0wD&uL z(KWweX=AOWwRbHozHe#nLrc@^ENy;lY5h}4)o^=UHCY!n{w`UMM6>p3Of6V_O^tXv zB5xnZRBC{tT6X~QcA_rZjp?_(;-R;t>UC!}yUD}`H!>4bx9uPg;+o_Fi zB`kisby_kW$!~Jmd{m*&M-}>fM7_;NgMQe0?VOnXkXJcwX@0P!nWUx3^(^gL|Nrai zYJjAwuJkm_$m=Jgj5snFMwkGmQT#y=n;`!n1E?@Tp^4~9j5<{Ofq>d%qk_7-W3mb( ztEZ!E64sxLTWFY4Gi|vkWi_#>{FEdyHrcp_Rg*TlDiy7a>n6MB`_4Hw302hj`rPlF zd+)pVyZzqnH}9G4Yc^Xv)@)~sS-y8qr$pTGR6$;0myp@J1ZdJE;x{WQbZG*bG>Q1l zigw_D>B%^tNt1}u%%a$&324$pn@yT%wM!Gwq)9|+qBA}kMPQRA5v7Svx-0LNhIgnXEt|=*}+rIR!&oE(nKcv6?&W^ z?+BnN6BXD#399g;SOzv>5^MCVMG=$^+{fK8V~)Fry@XL|)_zaYrE&*MaggTg?m7ymk7iWG@ zAJJMK0sSW>UrZVS?HjxYuhDZg0@^7BQD%}(i67Pzv@HbHPbtn!p2{@BAzf!_U-9z2 zINJrbO>iPT51203PfOOwj+vQcXW`w&b~4bp95K3)sOv-*Lb&?EY3oF71^!gBh`4n98O64A0os(}ixg$wie$U|litF5#6?@8?-%rY z&}xNbxL&lS>ainQK%rf3eeVLRAB2ds_^v~(AHxjuE(g^$D;^r>oF16 zW3-$Q zFQF}CcZa;_N{D0cHzjU^vHo{l9}?0y~#!L!i=FO z=&_$6XW&x%YJ}(|mNse-*baILFC+B7oN6U0{-@a42006i!O(B*?o%JjszLGzppchP27CXtWDVMRh_U0 z>I&%Fj)-{&F*%5Ba&-2>Z7Vb}Cda}?c%}Ds717U_g6qTmpxSgj^=(YoDm*q_i@WN1 zh;6>|#kSU<|9e*(^z(Xyl1C8H|6YQhfxd%8HpXz<&p>ecV!?9$3`CUqpG1EK>eF(a zSml2;+q1`P;c>IMy=Djd%~qZ;TYAcD_kdcvLO~|G{|LEaY=C`i2yJXoONf|3B^+5=LWgjYV5Kb! zy;RRYW@Q-AzsSoDE%GvZA{BeSZLt^jFRrK6h3jc#<)1+03A>KYZqNLpK5#w%4gz=M zY}f18$7QkWWp3_zy`T)AR5@VZ^&;HYk)1Bjo{(LWdAXjm{1ZfIPMw{^pWOeuu&ID| z9eXxnTfg`UWYKKfGrz1Ss#QU@pQuMXIb3$kAL_qRSAKCIGjC5mKzItPeZ zGP#k6r*o*oPv-#bbdHFpbEq1#L}324hF z5tmQ2-=|;^*p^QsE}!U^FQ0(6d=hc_M0b7pWY4)tM8xIuZ4}$`35dBix$zw!9nEuO z>+EbH^Gbb4yFUbf${frMVq3YAKf-NWLx46b_~L8XwnS$|l_~gb-Jmb8#y;V!VFQnJ zWslLF>mll~5h!8! zTIA(Dz`mpr+LDI0I->yWOBx{=IrPFA#J;4#ZA;p*AlQ-yXiFOUY?nUhwZ~U@1bA;2 z5ifo4dU7u>0o(e+x0Yj4OqV%V>4I^vJ}KJT5utk&`t31z5+ZmrCA_BWGMv6@5Zl>_ zap!H!KDcObtTJ>cD;;J_M3UXCYvpuuGZ!dQ(<{t+lXY*6JWcD zBjQCIDsj~Vn(B$DderTz2Q<|aQT1pNvg-^5G}RMP^*I!q>H$slXuhc)9dOkHn(B$D zdi2YiUIaGP6H)c(udAM2=WPQ-oW*#hyw74l8$!NlUV3j+J^re$#~GkzzMY*tY+&GP z*=E(_OhoVmpoBuxBb=^BmQ#;J{F8?fcSDfpDhYy|ZMJQ$+1fm_*aQh^f<(P0NYw1du?%d2B%&bEA}{X&c0m%FAkkK5 z6o6fjgeFMz!WlVW7bGEfpgKV?K?0f}(PtARdhPKQ9svrHh|~D|dU*-h1xcu*d9Gai zt?WuUbJdZ%I&G^Eq{9kLu0{|w39oAs&d?+Y{JJ%+4ykIgpbTj8^JYu>YY0AfUuHIc zx!L3kW~*12?Yq)!@oKfMNu)AOBAIu#1ZBL&&r5>b;y6q_aiO_QkCG>Mx1IF^A; zlSI@cTIA(Dz^+L`(27iV2P(+_tdCwNxu(ch{ukepxrY#UvwQ*!B zo3W3eYCY0=FGvO01`1UO2MU$=Kmpo75pkeUw+|Gc4HOXvYCei>pa5;4&`ujDwA2R* z&<2W#1BDL6Kmpr85pkf?s%Epk|x=B z7V}bjmc=zK>DtU|`nH_rPW+Xd9{S`e1hgENjyxe;OY~k-JlD5`pAA;Y>5mUPQHGzI zChg{EXb3_LcUou;2FjM>(oeOAD=2NR8-=0L4@$U#Qp5drnuVeA7PGi3C~fB%g`v_h z5?S08lurN5Y_bNFa0R6pSzx6XlyC)Q5c38-B4s});R;IbJ4RusWR6!#xPnq}3PWWE zDB%i9k5d>b8$k(IP|8kWs5}ZvxPsDlz7C!?m!Wb9lyC*5(vh0&`SQ9;j$Zf)cKv3_69O(lSaZ;R;IbLhBVnWeF(Z3QEB# z43%x5gexdLPGP7#4NACzQg#YM43$Z3N(om`+Ll{$87k|PGBI31>2ykj zKDKA_?1r5i?-|)1CBZB@lNsay>I+v;`kca0$&OY^xPnr33PWWcDB%i9vcjhhsImo= za0Mmr6oyJaDB%i9w^JA@Z-El7pp=}#Q0X{PDd7rA#VHJxHK2qmD1%O6sPuvouAt<) zeA<92`#}j;Pzp|AsAN8+lyC*5$0-bz8K8tKC}pQGR5pSVuAtPM!cch>lyC*5?Q_;# zhRPvO!WEQGr!Z7Tk5Njvf>Lw}L!}Fpa0R8$DGZf6K?zq-s!n03>;olSK}l9xa~Uch zffBBuj~N}qpbsBB@DzoJwl3#{}jWkR?jOY%D{(r@L+hJNjQZeQyd_XjWUpBXP5 z9onF91*O|5Oet$X30F``PGP9@f)cKvRGh+4*$+y%f->k7hDzqsN(om`ay9D~LuCdi z;R;H@DGZg3poA+ZJx*b$JPJyL%0L*)=C;R;I4DGZg-W$s%5Ag z03}>O>2wN1CHonrgexeub++s=ROW#auAsDi!6*!sEue%eD4kAWsPwZUcLk;BpBXA| zffBBu^hHIm(vee2xPnr33PWWLDB%i9a)mXQq0$RVxPp>*3PWW-DB%i9w^JA@nMq0s zS5Qh$VW`XiC0s$NIEA6IQ7PlY6_i1zMCij0O^`X0($@AU2x9Jw)-NWIL#QrXK`A(e zp)&durGzUeJx*b$bSY(AxPnr4N`%VX^-agi-mz(8dlUt==2WJTeW);8L20|vn$1x8 z2$XOIrPC=4l_{qxC0s!%I)$OK9+YqerOzo0mEE9(D=1Z`FjNkL60V?ddja2tpi0YR zeKw%&I82$Gj%*@ZmZ&!y&&c$LZtj|_8x_CdM#ZJp;ZE3{cvaqtF+<1jNt-w8lQz9{ zHJ`LO+MZzA(6D@dL&M%CecC2=H?;Z=yoB$JWcmCR*RQ{B^ObV=gY5L)xuZlM-#ILE zNO!p|!IMZQ>&;8oG!1@9V+Qm^O`C>fUK#jsO8TPy@jHC7Z)&JU_fPO2`zWx*XZ6{va%fumhotsHy`xdvbYDK5cHi0QF4;3Z9j7;);B{^X zrl)^s>i$6AvIe+7hUe3lnriHM=38UGHzS=kB+FD9e;2xZb$hf#E8#!fWxhcX{jzUn zdV6!!c$c~}JE#2eiuR&6+d}Ntbi6N$emQV%dbPJ=)~xhP)&O}-;rQs^Uk9>{+Nf!n z2IOn8nbz2GDvpMPM3K%56{-DJY=$Nj?M#vTjr!=?Tv`?&vW!hzs_;# znVYU?&fjE*wK`D`4IaFD-@H`s3&baBo~PV5l)K=l!iIKz>7dNsGIV}Z+k+Z{XXCba zZ?fRr4Q6XM9$`f{44;_T&DsXpD4y;bc%8C;+&$m{NcwjM}g*Vx7?3#HF@N;g*8GPq%vD59$jvL$ zmDzYs@h#_*|E+I&)K2rC&P-$~>4!4>(p*UQBrc_wZO8fjg2w-DVB_MUUvF&g zzT4VS>{TmoUYgEqD&T}kCSI0qYOdX7rL+)RbM?7PSX&=S*y_v9)ygd9&C774Z`K%H z5XS3*(3I-P(y^*RURs@w8`!#d=v&8P8QOXIJ&m7an~kT0OUKM~WHze&IT|}v_FSKy z-x`fPpfza^8>(ouG;c^RIhjy6k2^~b)_l2qLzzyWBT?iGj>epr^pcKl6h5y_ zGs>d8Rsmh}0|#HyDC*Asq{BY%$`&w)RE1>7hLZsdy`l^^R@*T9=! tRc;gOkjHLGpJ=iaSKgWqRW~Sd?N(hxvb7hN{lmm<>A=KoN3VYI{{c2%FmeC@ delta 70631 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 z zk(g=`svGtqK_CJoZ4jZl%NYU@AZ3FH)qTbghyY1WR6{~_3tu7#M1T|xB2>4LArJu) z=c_Dq`9!Gh@bv_N2oSjtLlB|5l>`YyhXjIlV>kH6RPK*VwyQL9pTsTM;NKKz zw(Dho$UxjhId|cAlCEn|!z6dr%l^zjZi2WiFVp3)Jf9r7?mzj51f^}+=t1NuOUJs; z|K#r&B)CjhjJn)GpZgPh0rJ&#<49IHk`=fc{3-$DK8@>s)!)AvcUb=F22Z6AxA(m2 z$M;RMVu}~3TyLZQP)>AfJ<=?fUE6E^=%6G%@vkAwe9e!v6s9UtQgZc}w)khd;`0$9 z4xR3;*Zhvw*I-9d{e>O3sF-cxLnK^mCv^|AJ<5mm1(^ZIswXKUw**5j#GWJe1&F%O<~l zD&L$U^tM0#T_n12Y|VtUuTK%s0QsNAN~3(Z;&`{$Jo>rHnVbAU&2rO=^v>b>JzdWx ze?I-*2fcnjqor)BC8hgo!`(ScnznNX{h)t~`(THL?Uzj5)y+Jnu{n&M5)*A|qF=v* zXVbM$`Y9v12jmvbZ`#-G{-!_I+m5v#?e;v&3xfQ`eCc!bH=0k%O?u0x_BX+4P4j}- zaK2Z&cs5@l<*Zxqou)$q`D&ADJLT`BZTl*1+2wpqb;CQ2cQ@u%edymt_d>Vpm)%3Y z1hcJG_yV#Z>5EZhCcc76qfT$4n@5s&UT5>PK#1=2PyE|YOf!O-DDj}C@%5UPHfWmv zlcwocHBG#(X>_Be9+a= z=iTBpO`Sgb;bwh~`sJU8si~xTL%xY-DEp`N>|svpIqQ1AAoY?H_3XHrPjKF?{*vk? zC+=}TaF6rqp5#{dk@@1b`ZDL8H=Xz#zFR$o>bU{zRv~BIf^Mpo+>&mp<_~Y>db`O~nyPN@j-+mfDs`!?43mL<=J0?9wh4G(NBF~G=A7hhWV2Y+T{ni*4XIL>ZK5x2 z<(4Fy{@Ccw+!Ca77mQ~YMeLSd$HSPvK89h;dG%3l5vtPX_9CUNRZ5FHRFvjAW5EOT z7%fXQ$00{oYj>> za?96H^>nTt)yMbXIO}BP5W{ZiqtqaIwrz7?@`@0bbZud$Y;EDJt}T+2wS|4f+QNBV zTO=oI3&()9h4Z?$NKV$4qqo(UIj?IAN33fL$82khgfDB0QpQX41WmF{ETqk78uEj(oHv!()KE)*`G3nW`-`QL2my$f|azuuvopFI-)r?c#o6% z9^Tw{;S=XB=zBQMUl%khlD8Fy#p?PFcaoKkDl5e_Q>vD+t$*NUOvE~+Q~ZfSQ!05| zc37-RkGP+d?o_2Te7z~9HokWyx3Nf6UzR^{X!<0tD-KIl-NlcQx)D|CVz)Ab4lciM z%)Rk+@H-j+OBvlYKiukbogQI|w=qn&4U%_@UZ!J$VwWy!KFn>tvuT9eb6|Lk8?-iv zOpn}71e)BXJ2cJzPSfYxPL9ov{G4@NhtS4Aa@`-(;>026mgIPGlIUr1>eSrePpJBSu3q#BS94b9wmhq% zecOK%_3g;2zRf=(3i&Xaqr)goZjrdb%bHGX;41CU#AB>&`CU!ZS*W@Weus38s?t?@ zh6%dayzTwqHhN2!L+HNEFXwlvP19)Fi;)OC@Prlt2Z&Hq!=^aq+IKGHPWt7-WYO$+~`)Ghs!jUVbc z+Ijw+WOjV!tR0`(0(UJPpVtz zu>^2lmjKDh67cc1`ZDKr3Eh(0QpnTkz;Bv99}r>Uqf`%uA`3c`3P3A2+sTUVLxxlBt2a zXl!F@dLg7=neFj4O*U#83u_wguW50Brr8!vQ`>7AA55uEN!G;uHs5Dm78hsTmR=gI zoS{iM-)9TFve7ta+44`Vk|yPRpUv8nL!5Ps|82F)|4k#7EA_#yX0Dv|U#ndFU#p~P zX=-U!cKYnJoAuc?CQnO_!1aD^)KOocR;DF~T58+0{5Utz z?R6+m%MnE5X*o*M($1RZchNMxtEP#lrqSIsEsxW*FrHGkd|)1dloP09$5c0#@)0V}9T{`4AeGUo(N_2_GxTcCwCh-% zNK{?&dtABT4}86ev#L%WvQ~B1-9YNbR;erhh#550`0QxC=jT4Wxsfh7iCA^^@R!ML zlu2Hd$_L9;>2tS{(%ntz6?84)VrIy7gUo$T49rY@ZGb!JsqlaNOG$pisQ#@2aEqR% z^Uh05IXTQ(H~1O4YQi{rXEJ=4yWkE#?AD)6S6Lo;sHyE&e{J;L)G6VCE^$v|WP14L zgrm`2yiC(L*X@YhTZPjQV<9)d0%= zhABE8C#~V}C=wkz@!Po4u0V5M$Bul=UiIztPGeK%lUonq*J_4&omGm{!ljWpBOHXM z(90*f4vARTzv%7Tv`bz`k6?fKCtCi(Q}vydY`3QILo|&{*R*t~run$0=_52v9I0va zXi9Z}uqJ-idWI{$(l{tcifMf;n;*EAvRnO0<4`y4wZ@TwSk%=rD^OjMIIDfmo@jk( z8fC51IcuHHE?TFvm*{lPTc=A_I-T9OPUoz4y5ywOIVyBI=k<6iIq7tc*6O32*W<0^ z{07BiF$Bmk8{5%UK;W^7{mpKA!81uj<vcOVi>>nr0VhnmSd}_-UF(zN2X=scHTU zN@XEpMcS=r_ENVNPNXt71wC!g-7017*8KyqWj)H~Y>nWot`U-x{ZESBum+X9E)p!& zqYS%eiv(wNk&v7$6701t5}efmBRN?lPUmV}Bsgp1g+sLQ!cm&}Jm+n^NLI!Rhi~JB zvpQZRC*$SJZTtl1wL|3<9qrKjy{5U|9#tJ${2@~|+!ubnF}GK9Qx9GEVu>ySDgGr2 zTLdI;ivWvN-#-SDzCEk-g%@+3++*0<(iDV!E%Oz?EdP#$X_LHO0hFJ&U~T)k(UGP( z-d@$Bb^eV|wHolG3;2qyUM^*3B}+@maJP9%Q+j&#ZbDJN zrtj4>`A1D-%QX$J(6sn~rrC!yP31L>KTN3}ov>xGVU9>pM{oCpDPtIuf zo;{1YcW>=pxt+B}@Uxpv4F^fiyCsfxi~O53)M{2QGiX0gUKKd6 zSK^azu~>KAoV8uIWJ%FA-o8~j%I`8l{G#Uq=pM(JKWSP;8*UY|Up*yOr<*3pt7GzF zp__F%tr_3`S<^Iczbd7rZyiY#??QG=^6FUnWEQI?$*X7bY9ed8#@oM2NkPzhf2eeA z6J0_UiN$ydtI`-btD59>OkKktzn<3cSe3f0Flb{)K1trTgx}ugQ=IdvN#3V)t8XQr zCYlmHlh~1dVMmWE?zV3P?YV33Y`TEngk`aXSfwt#O`ZIhkX!t0Q_OYU-E@L?fa&Dh zU}IS4mb;s1Us>Lj70GEeOYO9ph1P0$0m!1ESh@;Br`5X=g4ThgWjZ-Bpi=m^en>hA^)l^0%W?3^=4={kr_XPd2_W41icY{z+Kix-&9 z&o^6JV7B)nwRYl)Onx#ySD|+W&`-`#g%QfA#g8PhpPa#Mj1JWAXJ>$Rc1FarGc?N+ z6oKt*o``4jXs(y%f$eObh-dQ`_LbLw?Q9;M^Ix4&ZnF?QwcRr!`_-An_Nz0BxqHS# z!QHdPDDLF%T7dRF&R2I~ET_txw;C5`rqwMI)s;;6R^$0e!=+64h+Yc7X?thz#S+GH zZf6te?FD;QtkQBw@o&twf5~j?ie8E=xd@B@tzL1&U3UfF?_{*<^`UyDR}smPC{#I^$zq0ybF^ zQI_bW%M#FJNkmzq?=DL~yU-w_EZ3pfWC>`p#7o!i>P)t0rq`+RYhcd2Jf}B`l#^so zrr~<OK1KTSN;n;jv8k4#q1xj`c!(HqTHH=8Yg-E7BA zW{cl6o9{4N+h(@+R<$NkWD@pjlOpdGpeqzL_~jES@q=0hc7+o1@(H!OKmkplL=-3* zHecp|L%n8Ytk_JHg7Vp5j^+J}w_ASn*D9FORPLH!Z2flH? z3$mYBoSreCrj+h?}-VY6M2nr-hf+xocKm};&^%Bt5OCqi;2T^S6C7`b?XppZgXpGO({Kgj`wBSYKHHZDk?i%7Q+4d=c1I z79y@J=$n`4fo)|W;>z;xedRS^TUmG{xRLid%I&Kk(1w;zR>9CtlAm9tVw_bszJ<3D zvE}MS&+&a zQD!%a!spl9Ear`(hVWa@uKlX((qtv6t_xGlHcd5Koo2Q?!)!;J+2Sm-`8j55bJg07 zqR3=F+aZ_h7SMD{MBSc=V$&_4>lPKeZc%sW7T9%5NZq1Qu3JFUEfIB#wuWwjO}9kU zE&33;1vcFhQMa@E%4@);TlCnzfzW5yExXSfMTvMufY-|Umk^-InlGERS^CRYb(Ws% zGYsF?3lY#+!Hj4Ewi!{z>u7yO5ZiY(ymIIboe}5NP13>&kZqFw-ES~S>9I*#U5P?l z9{_ER^7XdXqWSM7%VqF3{d1J^P5sZYKd2~OfuPL$iC(uC*C2|w1H)_IB2935`-pA- z*0>8lOujd__+@42ic0onN^EEWd&({Dk^-gOb;?)OQ>Q^6tcJ)ETs}FR* zuRZ|n>Vt@93SULBohbm?nF2a%XA0=9pDD2C{4t$~X9{@xuy?!!Y!izwC6?W3ZhPi} zx(QL+3P#<&*J+>4Vc*N#-1qth^7+0Ou8CC3CTELz4RcoUWXfTQRrw+e*`!mwd-;WtZ9R@0u;`FKkOmmn!2|y zz6flSkI#j}_)eA=r{{{&JvDQTKHhMOEg_Z15VU0m<_obcY^5^XHt~r4dmL^#SkSq$ zux_p-&w#D_htnH-{%1k%Gns7lSrB<20m^JO>W0&k65DEIT;4^!V6je&>c1#WCq{X{ z*^XYb#h;qZzhJiZGqb%vH`{g4Z2QYXbT<@7d&*#7d${) z@QAqJp})T1vFp5hh=>c`D=4=6dI4p9s(0uRaRu3anXVug)s1Gye<47(F7#Wa{a1*f z*y*-`%){#gNo)gY<3-6k3de3b2eYI9E zQwe*5WZn}%Te^w3biajSTe<;F{HWN(kE&h#fF^z-iXScVAua)%_=zZfwA959XyPZL z_|X9uKcI=9h~ob(icS20E`IdZ#g7hq^<{Qmzt!}w`Uolh!yxSAU;P1^xcNGIIkZIu zxu|XklRtvI@H@E~jXjOG7gCPHGwj*P& zurCfUo6nl94K&-EnC(i60ix9h=N2*U66n#NFoXn9dJPcnjncN$dgcPf&_FyqPH$cbl9sev-2iM zLJIN}5KNGOE=a<|KT<(1sT;y%0>~!F)8B1`ASWV*f<&1M63!4L2_{HF3Ub|k2y&9r zAjnp;9cP*?PBWXIVYYUb+1{CEyJnkhpR3jciA*L)b%ouM3i0 zryz+a$a7F^f&?@{5>b$kzN&&;S~r><3lOlnLP1`H2oogSE=YJokYt!33HQALK`v4T z1i8d)vdnCyXtw*W&6ZY}EnH%@X_eXPYPBv%q%uJwnfC60ix9h=N2*U66n#NFoXn9dJPcnjncN$V*Xdf&_FyqPH$cbl9se zv-2iMLJIPWAebNlU66#C->V>()eT{CHOMB&lRx4&2(T2^-VWQ30F{R z(Gpmh0!p}olHX#DWvHwNC0s!%I)$O~04U)KN{3SzDu+M`S5V4MVWM;R;HZQy41qKnYh+dY!^h*#b(q zf>Lt|LuJd3%&|K*-`UU{?x5vw@;L*#97d*a1*PZ|hRWDuloGC>bU1~fvKo|d1*Pm1 zhRRM*!WERNQy3}-K?zq-n!e$422{x%tCVmBrQj5X%1ltg6_k=w7%JC+60V?hJB6XL zPbp)<6_kooB6RPAr_JcMWBr{&o1-L{$v3Ul%pfgIT3@(=(&`k3%5qS`6_j?TFjP80 z30F|MoWf8!07|%m((4q4N@loH!WER7Qy3~!KnYh+@;6(L7%J;Q30F{xPGP7#07|%m z(%}?_${|p~6_m157%Ib$Q%bmkQgsSLWg#fx3QALlPa9BW8z|ulO2H`%m8U@oS5Qh$ zVW@lvO1Og3?G%Q}xZ{-)uAo$$!cbWQO1OfOZ1ed7s_X_OTtR7d3Pa^JP{I|IcBe2@ zhKx{3xPsE<6o$$?P{I|IUZ*frwty0@pwyhgPiE4;R;H(Qy41yKnYh+Do$ajyaP(Of|7j8=L@LPGEynw3QDU}7%Iy_30F|M zuh+*1>A4O=r4y8J1*PH?hROj@!WER{2Ft=w$&Av4Gh9JwbxMTx>$mwVTR5X6nC;GF z23fDkn!^>8E~hY59sng=LFsi0L*)=C;R;I4DGZh2ElLSjQ1Y9sV+@srpoA+ZMW--S zwt*6^pmaEeq4G2+;R;IGDGZelK?zq-s!n03jQgBY!WERJ8?Ctvl{KJ*D<}o0FjRJf z60V?>oWf9f4U}*NrQ0bCl_8^*60V?BoWf9<2THhtl5F;A1FCERC0s#ibqYh}aZth) zly;{uR1Sj@uAp=|g`qO`M5Tl)D7{W$sH_GhTtTThg`u(&lyC(lzs2VZsB#dLa0R94 z6oyJ}j8eiCln$pbRAzz_uAr2i!ce&mlyC*5>J)~`K2X9HlqNh#50{&u$~&NhD<}o0 zFjQJjQcAdjQgRAIWjQF}`h?PDixoqqlN5IarQ1It7f1*OX=43$Hmgexe$PGP7F&nqQdL8&=~p?Y(l zQot$^6J>io9o8HLK`c9w31r+@tu97X-27pP4|0oTAl*D=6Jg zVNRI`O1OejaSB6a3n<|VN`mWsRRcriaZth)lvbxOR1Sj@uAsC#g`qO`RHcL~DBM`k ziWn-Zm6D}Pww#*kb7Z*fuv5LccqpbnX7k-sb(3PbZBis-m+`TXwEFncDYEPM0VD8m z&CO>t=Av|&9A47U)YS46J2rn-zkUy8^#&mS+=5r{o!&Tq*6fX6*|1h-{ysOUvu$MN z2Gnq|41P8@Qh(pQE}Pu@r0$~V%a}Iw&-|ii?zr?heOMNJGGu(ZJ+q1QiN)XP3-+{A z#lvR1f4QBN_6|RW{zlz4!GG93fvvo+JQ+73{UE7$s4SSAPLKr?();A2iRq|p({UOq zEtAp@vR$oh`w3^uipi7pZh7PO`l`sbKUYrhTKIaf4CW3(Rr!^1PzDWYG7 zOii~Aib`)&cV@@9UwpAST5cis#7(>xihgOCmR{k_xNTZ`rL{mlRyaDk_!oiR^$D4N zvVL;^;d(UNcC5RvA=j!*2Fc;+>3QDInKLvikDBb8q4U7tff?z@Z1-I{Gv&84^k}cN z!Ks{;E*R7yHetJ#>w5(GsMQ5+X_DnfS=pxSOTa#U;O5sG_I=^T&T*d`SlsokXLJkt z_R@e^+4etaINo~N-1VF#DjqP~>WOJZ_jw;4Q*jrLam&=+FqB%Ld_%ueqgllVH0TvZJY+U=1GbXoX_K6mot2lZ~}U31cf z4V~I>`NN#_k6E@#vyJ~k;ZuoNkIsTf6a!)vNcsc46>Hboo~-8&XQ$&c)0>{RK1avm z7(~Y+M|3zoKeef(-Mp-j-rHP#VmZ6nUC>v!LDzQ-=G3RvhE9}==4rR{pK5J{MQh88 z^v#QW3vK?~w6ozBbohyL)AI&a@VD(trDa(<^6m}&pB>g(*JM1;m*tW@KONo79Cb$^ zn#8(f?)m9`4c8#=p!u4&_87kY`|=h)m6zr6`3p5~w`N9K*Zn0w5C(wsxpfR=1_cPK?os(TGDGQ%Ij~&3_op zHbs<({OqE1QLgfzuW@vSBGc(oT%?QXrO?O1o`H+gGcqlO?sXitu*iWoU&iMKHbK@c zNmu3KZ(3R`S+Z1tG~vJ*;Ho^Jxlw^sAcIWt@WLwusZEnb!WpT*=FEz;j;eBbZ9QB zd>JhsFCSf#o2w8O1+P@uj#*T&W&5}FT zrMWR)9Q6EKMvpY4k0-rtZJL}E<-zZAepEyLgg$67}>M|to$YMMT(A%AioKgxrz$BzFZ5BaU+KlK&;xq@${)qKx$y4<}XUD5ye zBTzi3(s?-_@lD&acSE{0lM7!j*vAg59hynX|FJ!nZA@?Np9|l=l6q8r>6b|@?!5_C zS~d(Aj!7~0MIGKKd{&!^(XQ?x$y%=ePX^zxKhtwrDSb9GCdz{A2|vkEZM@~VOwR>h z12@Wo8wn#vap#NAWO^oEuiPx_kdJRjAI@5eM>nMdGFejOi5qn>x$f{2nVUCmPJ1?P JK4RH({|i=5E8YMA diff --git a/chess/pointer.hpp b/chess/pointer.hpp new file mode 100644 index 0000000..cef95fd --- /dev/null +++ b/chess/pointer.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include "geometry/geometry.hpp" + +namespace pointer { + constexpr vec3 vertices[] = { + { 0.407995f, -0.805648f, -0.000000f }, + { 0.000000f, 0.000000f, 0.000000f }, + { 0.550770f, -0.527772f, -0.000000f }, + { 0.302290f, -0.556623f, -0.000000f }, + { 0.297535f, -0.852536f, -0.000000f }, + { 0.000000f, -0.762211f, 0.000000f }, + { 0.191836f, -0.603526f, 0.000000f }, + }; + + constexpr face_v faces[] = { + {{1}, {6}, {0}}, + {{3}, {2}, {1}}, + {{1}, {5}, {6}}, + {{6}, {4}, {0}}, + {{0}, {3}, {1}}, + }; + + constexpr uint32_t num_faces = (sizeof (faces)) / (sizeof (face_v)); + +} diff --git a/chess/pointer.obj b/chess/pointer.obj new file mode 100644 index 0000000..f91ef1f --- /dev/null +++ b/chess/pointer.obj @@ -0,0 +1,16 @@ +# Blender 3.3.6 +# www.blender.org +o Pointer +v 0.407995 -0.805648 -0.000000 +v 0.000000 0.000000 0.000000 +v 0.550770 -0.527772 -0.000000 +v 0.302290 -0.556623 -0.000000 +v 0.297535 -0.852536 -0.000000 +v 0.000000 -0.762211 0.000000 +v 0.191836 -0.603526 0.000000 +s 0 +f 2 7 1 +f 4 3 2 +f 2 6 7 +f 7 5 1 +f 1 4 2 diff --git a/chess/render.cpp b/chess/render.cpp index fd123b4..d063304 100644 --- a/chess/render.cpp +++ b/chess/render.cpp @@ -6,7 +6,7 @@ #include "chess/rook.hpp" #include "chess/square.hpp" #include "chess/circle.hpp" -#include "chess/cursor.hpp" +#include "chess/pointer.hpp" #include "sh7091/store_queue.hpp" #include "sh7091/serial.hpp" @@ -16,41 +16,77 @@ #include "holly/ta_global_parameter.hpp" #include "holly/ta_vertex_parameter.hpp" -#include "render.hpp" +#include "chess/chess.hpp" +#include "chess/render.hpp" namespace render { -static inline vec3 transform(const vec3 v, float cell_x, float cell_y, float scale) -{ - float x = v.x * 28.f * scale; - float y = -v.y * 28.f * scale; - x += 124.f + cell_x * 56.f; - y += 44.f + (7 - cell_y) * 56.f; +constexpr float board_z = 100.f; +constexpr float illumination_z = 99.f; +constexpr float piece_z = 70.f; +constexpr float move_z = 50.f; +constexpr float cursor_z = 0.f; - return {x, y, 1.f/(v.z + 10.0f)}; +vec3 __attribute__ ((noinline)) +transform(view_transform vt, + const vec3 v, + float cell_x, + float cell_y, + float z_offset, + float scale, + float rotation) +{ + float x0 = v.x; + float y0 = -v.y; + + // piece rotation + float x1 = x0 * __builtin_cosf(rotation) - y0 * __builtin_sinf(rotation); + float y1 = x0 * __builtin_sinf(rotation) + y0 * __builtin_cosf(rotation); + + float x2 = x1 * 28.f * scale; + float y2 = y1 * 28.f * scale; + + float x3 = x2 + (cell_x ) * 56.f - (196.f); + float y3 = y2 + (7 - cell_y) * 56.f - (196.f); + + float x4 = x3 * __builtin_cosf(vt.board_rotation) - y3 * __builtin_sinf(vt.board_rotation); + float y4 = x3 * __builtin_sinf(vt.board_rotation) + y3 * __builtin_cosf(vt.board_rotation); + + float x5 = x4 + 124.f + (196.f); + float y5 = y4 + 44.f + (196.f); + + float z = v.z + z_offset; + + return {x5, y5, 1.f/(z + 10.0f)}; } -static void draw_model(vec3 const * const vertices, +static void draw_model(const view_transform vt, + vec3 const * const vertices, face_v const * const faces, uint32_t num_faces, uint32_t base_color, float cell_x, float cell_y, + float z_offset, float scale, - bool always) + float rotation, + bool always, + bool alpha = false) { const uint32_t parameter_control_word = para_control::para_type::polygon_or_modifier_volume - | para_control::list_type::opaque + | para_control::list_type::translucent | obj_control::col_type::packed_color; - const uint32_t isp_tsp_instruction_word = (always ? isp_tsp_instruction_word::depth_compare_mode::always + const uint32_t isp_tsp_instruction_word = (always ? isp_tsp_instruction_word::depth_compare_mode::greater : isp_tsp_instruction_word::depth_compare_mode::greater) | isp_tsp_instruction_word::culling_mode::no_culling; - const uint32_t tsp_instruction_word = tsp_instruction_word::src_alpha_instr::one - | tsp_instruction_word::dst_alpha_instr::zero - | tsp_instruction_word::fog_control::no_fog; - + const uint32_t tsp_instruction_word = (alpha ? tsp_instruction_word::src_alpha_instr::src_alpha + : tsp_instruction_word::src_alpha_instr::one) + | (alpha ? tsp_instruction_word::dst_alpha_instr::inverse_src_alpha + : tsp_instruction_word::dst_alpha_instr::zero) + | tsp_instruction_word::fog_control::no_fog + | tsp_instruction_word::use_alpha; for (uint32_t face_ix = 0; face_ix < num_faces; face_ix++) { @@ -69,7 +105,13 @@ static void draw_model(vec3 const * const vertices, constexpr uint32_t strip_length = 3; for (uint32_t i = 0; i < strip_length; i++) { uint32_t vertex_ix = face[i].vertex; - const auto vertex = transform(vertices[vertex_ix], cell_x, cell_y, scale); + const auto vertex = transform(vt, + vertices[vertex_ix], + cell_x, + cell_y, + z_offset, + scale, + rotation); bool end_of_strip = i == strip_length - 1; float z = __builtin_fabsf(vertices[vertex_ix].z); @@ -83,7 +125,7 @@ static void draw_model(vec3 const * const vertices, } } -void draw_board() +void draw_board(const view_transform vt) { for (int i = 0; i < 8 * 8; i++) { int x = i % 8; @@ -94,98 +136,129 @@ void draw_board() constexpr uint32_t green = 0xff739552; uint32_t color = white ? cream : green; - draw_model(square::vertices, + draw_model(vt, + square::vertices, square::faces, square::num_faces, color, x, y, + board_z, 1.0f, // scale + 0.0f, // rotation true); // always } } -void draw_illumination(int8_t position) +void draw_illumination(const view_transform vt, + int8_t position, uint32_t highlight_color) { auto [x, y] = chess::position_to_xy(position); - constexpr uint32_t cream = 0xfff5f681; - draw_model(square::vertices, + draw_model(vt, + square::vertices, square::faces, square::num_faces, - cream, + highlight_color, x, y, + illumination_z, 1.0f, // scale - true); // always + 0.0f, // rotation + true, // always + true); // alpha } -void draw_moves(chess::moves_list& moves) +void draw_moves(const view_transform vt, + const chess::moves_list& moves) { for (int i = 0; i < moves.length; i++) { chess::xy move_xy = chess::position_to_xy(moves.moves[i].to_position); - uint32_t color = 0xff777777; - draw_model(circle::vertices, + uint32_t color = 0x37000000; + draw_model(vt, + circle::vertices, circle::faces, circle::num_faces, color, move_xy.x, move_xy.y, - 0.5f, // scale - true); // always + move_z, + 0.4f, // scale + 0.0f, // rotation + true, // always + true); // alpha } } -void draw_piece(int8_t type, int8_t x, int8_t y) +void draw_piece(const view_transform vt, + int8_t type, int8_t x, int8_t y) { bool white = type > 0; uint32_t color = white ? 0xffdddddd : 0xff444444; switch (__builtin_abs(type)) { case chess::piece_type::pawn: - draw_model(pawn::vertices, + draw_model(vt, + pawn::vertices, pawn::faces, pawn::num_faces, color, x, y, + piece_z, 1.0f, // scale + vt.piece_rotation, // rotation false); // always break; case chess::piece_type::knight: - draw_model(knight::vertices, + draw_model(vt, + knight::vertices, knight::faces, knight::num_faces, color, x, y, + piece_z, 1.0f, // scale + vt.piece_rotation, // rotation false); // always break; case chess::piece_type::bishop: - draw_model(bishop::vertices, + draw_model(vt, + bishop::vertices, bishop::faces, bishop::num_faces, color, x, y, + piece_z, 1.0f, // scale + vt.piece_rotation, // rotation false); // always break; case chess::piece_type::rook: - draw_model(rook::vertices, + draw_model(vt, + rook::vertices, rook::faces, rook::num_faces, color, x, y, + piece_z, 1.0f, // scale + vt.piece_rotation, // rotation false); // always break; case chess::piece_type::queen: - draw_model(queen::vertices, + draw_model(vt, + queen::vertices, queen::faces, queen::num_faces, color, x, y, + piece_z, 1.0f, // scale + vt.piece_rotation, // rotation false); // always break; case chess::piece_type::king: - draw_model(king::vertices, + draw_model(vt, + king::vertices, king::faces, king::num_faces, color, x, y, + piece_z, 1.0f, // scale + vt.piece_rotation, // rotation false); // always break; default: @@ -193,27 +266,92 @@ void draw_piece(int8_t type, int8_t x, int8_t y) } } -void draw_pieces(const chess::game_state& game_state) +void draw_pieces(const view_transform vt, + const chess::game_state& game_state) { const auto& piece_list = game_state.piece_list; for (int i = 0; i < piece_list.length; i++) { chess::piece * piece = piece_list.piece[i]; int8_t position = piece_list_to_position(game_state.board, piece); auto [x, y] = chess::position_to_xy(position); - draw_piece(piece->type, x, y); + draw_piece(vt, + piece->type, + x, y); } } -void draw_cursor(float x, float y) +uint32_t cursor_colors[4] = { + 0xffff00ff, + 0xff00ff00, + 0xffffff00, + 0xffff0000, +}; + +void draw_cursor(const view_transform vt, + float x, float y, + int cursor_index) { - uint32_t color = 0xffff00ff; - draw_model(cursor::vertices, - cursor::faces, - cursor::num_faces, - color, + constexpr float pi = 3.141592653589793f; + + draw_model(vt, + pointer::vertices, + pointer::faces, + pointer::num_faces, + cursor_colors[cursor_index % 4], x, y, + cursor_z, 1.0f, // scale + pi * cursor_index, // rotation true); // always } + +void draw_annotation(const view_transform vt, + const chess::annotation_list& annotation_list) +{ + constexpr uint32_t red_highlight = 0xcceb6150; + + for (int i = 0; i < annotation_list.length; i++) { + auto& annotation = annotation_list.annotation[i]; + switch (annotation.type) { + case chess::annotation_type::highlight: + render::draw_illumination(vt, + annotation.from_position, + red_highlight); + break; + default: break; + } + } +} + +void draw_interaction(const view_transform vt, + const chess::interaction_state& interaction) +{ + constexpr uint32_t yellow_highlight = 0x7fffff33; + + if (interaction.selected_position != -1) + render::draw_illumination(vt, interaction.selected_position, yellow_highlight); + if (interaction.last_move.from_position != -1) + render::draw_illumination(vt, interaction.last_move.from_position, yellow_highlight); + if (interaction.last_move.to_position != -1) + render::draw_illumination(vt, interaction.last_move.to_position, yellow_highlight); +} + +void render(const chess::game_state& game_state, + const view_transform vt, + const cursor_state cursor_state) +{ + render::draw_board(vt); + + render::draw_interaction(vt, game_state.interaction); + render::draw_annotation(vt, game_state.interaction.annotation_list); + + render::draw_pieces(vt, game_state); + render::draw_moves(vt, game_state.interaction.moves); + for (int i = 0; i < cursor_state::num_cursors; i++) { + auto& cursor = cursor_state.cur[i]; + render::draw_cursor(vt, cursor.x, cursor.y, i); + } +} + } // namespace render diff --git a/chess/render.hpp b/chess/render.hpp index 01c663c..184fc26 100644 --- a/chess/render.hpp +++ b/chess/render.hpp @@ -2,14 +2,52 @@ #include -#include "chess.hpp" +#include "chess/chess.hpp" namespace render { -void draw_board(); -void draw_illumination(int8_t position); -void draw_moves(chess::moves_list& moves); -void draw_pieces(const chess::game_state& game_state); -void draw_cursor(float x, float y); +struct view_transform { + float piece_rotation; + float board_rotation; +}; + +struct button { + bool a; + bool b; +}; + +struct cursor { + float x; + float y; + struct button button[2]; + + constexpr cursor() + : x(4.f), y(4.f) + { + button[0] = {false, false}; + button[1] = {false, false}; + } +}; + +struct cursor_state { + constexpr static int num_cursors = 2; + + struct cursor cur[num_cursors]; + int port_map[4]; + + constexpr cursor_state() + { + port_map[0] = 0; + port_map[1] = 1; + port_map[2] = -1; + port_map[3] = -1; + cur[0] = cursor(); + cur[1] = cursor(); + } +}; + +void render(const chess::game_state& game_state, + const view_transform vt, + const cursor_state cursor_state); } diff --git a/maple/maple_bus_ft0.hpp b/maple/maple_bus_ft0.hpp index 753a748..f6a7d26 100644 --- a/maple/maple_bus_ft0.hpp +++ b/maple/maple_bus_ft0.hpp @@ -55,12 +55,7 @@ namespace ft0 { struct data_format { uint16_t digital_button; - uint8_t analog_axis_1; - uint8_t analog_axis_2; - uint8_t analog_axis_3; - uint8_t analog_axis_4; - uint8_t analog_axis_5; - uint8_t analog_axis_6; + uint8_t analog_coordinate_axis[6]; }; static_assert((sizeof (struct data_format)) % 4 == 0); static_assert((sizeof (struct data_format)) == 8); diff --git a/maple/maple_bus_ft9.hpp b/maple/maple_bus_ft9.hpp index d2abd1f..d586610 100644 --- a/maple/maple_bus_ft9.hpp +++ b/maple/maple_bus_ft9.hpp @@ -2,7 +2,7 @@ namespace ft9 { namespace data_transfer { - namespace button { + namespace digital_button { constexpr uint32_t r() { return 0b1 << 7; } constexpr uint32_t r(uint32_t reg) { return (reg >> 7) & 0b1; } @@ -39,7 +39,7 @@ namespace ft9 { } struct data_format { - uint8_t button; + uint8_t digital_button; uint8_t option; uint8_t analog_coordinate_overflow; uint8_t reserved; diff --git a/regs/maple_bus_ft0.csv b/regs/maple_bus_ft0.csv index a081908..36b6f41 100644 --- a/regs/maple_bus_ft0.csv +++ b/regs/maple_bus_ft0.csv @@ -1,9 +1,9 @@ "data_transfer",7,6,5,4,3,2,1,0 "digital_button","Ra","La","Da","Ua","Start","A","B","C" "digital_button","Rb","Lb","Db","Ub","D","X","Y","Z" -"analog_axis_1",,,,,,,, -"analog_axis_2",,,,,,,, -"analog_axis_3",,,,,,,, -"analog_axis_4",,,,,,,, -"analog_axis_5",,,,,,,, -"analog_axis_6",,,,,,,, +"analog_coordinate_axis",,,,,,,, +"analog_coordinate_axis",,,,,,,, +"analog_coordinate_axis",,,,,,,, +"analog_coordinate_axis",,,,,,,, +"analog_coordinate_axis",,,,,,,, +"analog_coordinate_axis",,,,,,,, diff --git a/regs/maple_bus_ft0.ods b/regs/maple_bus_ft0.ods index 2cbaf1acb76d9f1d70b5c4d794e1c6411cf9d0ac..36a8ebf67964c3e60cd00cf1c0b0ebc845fb6d9b 100644 GIT binary patch delta 10052 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 Kz6)Xfh58?WG3V3( delta 10081 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
hXu4s@MIbgM2!2*Bv50BJoYkx&?&X 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 diff --git a/regs/maple_bus_ft9.csv b/regs/maple_bus_ft9.csv index a24c916..78ad170 100644 --- a/regs/maple_bus_ft9.csv +++ b/regs/maple_bus_ft9.csv @@ -1,5 +1,5 @@ "data_transfer",7,6,5,4,3,2,1,0 -"button","r","l","d","u","s","a","b","c" +"digital_button","r","l","d","u","s","a","b","c" "option",,,,,,,"batt","wire" "analog_coordinate_overflow",,,,,,,, "reserved",,,,,,,, diff --git a/regs/maple_bus_ft9.ods b/regs/maple_bus_ft9.ods index 1184608836863aa67bfd00472e4723aaa6749e66..78d403828779210372d9f8adc3957eee473e5e42 100644 GIT binary patch literal 12848 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 hFoOW%_7gYan2zjUjbb?; + using command_type = maple::device_request; + using response_type = maple::device_status; auto [host_command, host_response] = writer.append_command_all_ports(); + + maple::dma_start(send_buf, writer.send_offset, + recv_buf, writer.recv_offset); + + for (uint8_t port = 0; port < 1; port++) { + auto& bus_data = host_response[port].bus_data; + auto& data_fields = bus_data.data_fields; + if (bus_data.command_code != response_type::command_code) { + serial::string("port: "); + serial::integer(port); + serial::string(" disconnected\n"); + } else { + serial::string("port: "); + serial::integer(port); + serial::string(" ft: "); + serial::integer(std::byteswap(data_fields.device_id.ft)); + serial::string(" fd[0]: "); + serial::integer(std::byteswap(data_fields.device_id.fd[0])); + serial::string(" fd[1]: "); + serial::integer(std::byteswap(data_fields.device_id.fd[1])); + serial::string(" fd[2]: "); + serial::integer(std::byteswap(data_fields.device_id.fd[2])); + serial::string(" source_ap.lm_bus: "); + serial::integer(bus_data.source_ap & ap::lm_bus::bit_mask); + } + } +} + +void keyboard_do_get_condition(ft6::data_transfer::data_format& data) +{ + uint32_t send_buf[1024] __attribute__((aligned(32))); + uint32_t recv_buf[1024] __attribute__((aligned(32))); + + using command_type = maple::get_condition; + using response_type = maple::data_transfer; + + auto writer = maple::host_command_writer(send_buf, recv_buf); + + auto [host_command, host_response] + = writer.append_command_all_ports(); + host_command->bus_data.data_fields.function_type = std::byteswap(function_type::keyboard); maple::dma_start(send_buf, writer.send_offset, recv_buf, writer.recv_offset); - for (uint8_t port = 0; port < 4; port++) { + for (uint8_t port = 0; port < 1; port++) { auto& bus_data = host_response[port].bus_data; auto& data_fields = bus_data.data_fields; + //serial::integer(port, ' '); + //serial::integer(bus_data.command_code); if (bus_data.command_code != response_type::command_code) { + do_device_request(); continue; } if ((std::byteswap(data_fields.function_type) & function_type::keyboard) == 0) { + serial::integer(std::byteswap(data_fields.function_type)); continue; } @@ -61,9 +106,9 @@ void keyboard_debug(ft6::data_transfer::data_format * keyboards, uint32_t frame_ } if (difference) { for (int i = 0; i < 6; i++) { - serial::integer(keyboards[this_frame].scan_code_array[i], ' '); + //serial::integer(keyboards[this_frame].scan_code_array[i], ' '); } - serial::string("\n"); + //serial::string("\n"); } } @@ -97,10 +142,14 @@ void keyboard_update(ft6::data_transfer::data_format * keyboards, uint32_t frame bool shifted = is_shifted(keyboards[this_frame].modifier_key); char_type code_point = ft6::scan_code::code_point[scan_code][shifted]; if (code_point != 0) { - gap_append(gb, code_point); + serial::character(code_point); + serial::character('\n'); + //gap_append(gb, code_point); continue; } } + serial::integer(scan_code); + continue; switch (scan_code) { case ft6::scan_code::_return: gap_append(gb, '\n'); break; case ft6::scan_code::backspace: gap_pop(gb); break; diff --git a/text_editor/render.cpp b/text_editor/render.cpp index 937c0cd..3ad6d4d 100644 --- a/text_editor/render.cpp +++ b/text_editor/render.cpp @@ -3,6 +3,8 @@ #include "transform.hpp" #include "holly/ta_global_parameter.hpp" +#include "holly/ta_fifo_polygon_converter.hpp" +#include "sh7091/serial.hpp" static inline uint32_t get_font_ix(const struct font * font, char_type c) @@ -115,7 +117,19 @@ void render(ta_parameter_writer& parameter, parameter.append() = ta_global_parameter::end_of_list(para_control::para_type::end_of_list); + ta_polygon_converter_transfer(parameter.buf, parameter.offset); + ta_wait_opaque_list(); + + parameter.offset = 0; + + /* render_cursor(parameter, cursor, window); parameter.append() = ta_global_parameter::end_of_list(para_control::para_type::end_of_list); + + ta_polygon_converter_transfer(parameter.buf, parameter.offset); + serial::string("wait tl\n"); + ta_wait_translucent_list(); + serial::string("done tl\n"); + */ } diff --git a/text_editor/text_editor.cpp b/text_editor/text_editor.cpp index 6fbe1dc..45f52b5 100644 --- a/text_editor/text_editor.cpp +++ b/text_editor/text_editor.cpp @@ -15,6 +15,8 @@ #include "holly/ta_global_parameter.hpp" #include "holly/ta_bits.hpp" +#include "sh7091/serial.hpp" + #include "font/font.hpp" #include "ter_u20n.hpp" @@ -78,13 +80,13 @@ void main() constexpr uint32_t ta_alloc = ta_alloc_ctrl::pt_opb::no_list | ta_alloc_ctrl::tm_opb::no_list - | ta_alloc_ctrl::t_opb::_16x4byte + //| ta_alloc_ctrl::t_opb::_16x4byte | ta_alloc_ctrl::om_opb::no_list | ta_alloc_ctrl::o_opb::_16x4byte; constexpr struct opb_size opb_size = { .opaque = 16 * 4 , .opaque_modifier = 0 - , .translucent = 16 * 4 + //, .translucent = 16 * 4 , .translucent_modifier = 0 , .punch_through = 0 }; @@ -118,9 +120,6 @@ void main() auto parameter = ta_parameter_writer(ta_parameter_buf); render(parameter, font, glyphs, state.gb, state.window); - ta_polygon_converter_transfer(parameter.buf, parameter.offset); - ta_wait_opaque_list(); - core_start_render(frame_ix); core_wait_end_of_render_video(); diff --git a/text_editor/text_editor.mk b/text_editor/text_editor.mk index a3e5a4b..ff9bced 100644 --- a/text_editor/text_editor.mk +++ b/text_editor/text_editor.mk @@ -11,7 +11,8 @@ TEXT_EDITOR_OBJ = \ holly/ta_fifo_polygon_converter.o \ maple/maple.o \ sh7091/serial.o \ - ter_u20n.data.o + ter_u20n.data.o \ + $(LIBGCC) text_editor/text_editor.elf: LDSCRIPT = $(LIB)/main.lds text_editor/text_editor.elf: $(START_OBJ) $(TEXT_EDITOR_OBJ) diff --git a/text_editor/transform.cpp b/text_editor/transform.cpp index e472aa9..d3ba0ec 100644 --- a/text_editor/transform.cpp +++ b/text_editor/transform.cpp @@ -100,7 +100,7 @@ void transform_glyph(ta_parameter_writer& parameter, const uint32_t texture_address = texture_memory_alloc::texture.start; const uint32_t texture_control_word = texture_control_word::pixel_format::_4bpp_palette | texture_control_word::scan_order::twiddled - | texture_control_word::palette_selector(0) + | texture_control_word::palette_selector4(0) | texture_control_word::texture_address(texture_address / 8); parameter.append() =