From 6f73f2d443c17f6fa36bb90bda13eedce842d885 Mon Sep 17 00:00:00 2001 From: Alessandro Mauri Date: Tue, 20 May 2025 21:43:18 +0200 Subject: [PATCH] initial commit --- .gitignore | 4 + compile-shaders.sh | 33 + lettuce.bmp | Bin 0 -> 492138 bytes sdl3.c3l/manifest.json | 9 + sdl3.c3l/project.json | 14 + sdl3.c3l/sdl3_audio.c3i | 3 + sdl3.c3l/sdl3_blendmode.c3i | 35 ++ sdl3.c3l/sdl3_camera.c3i | 3 + sdl3.c3l/sdl3_error.c3i | 11 + sdl3.c3l/sdl3_events.c3i | 604 +++++++++++++++++++ sdl3.c3l/sdl3_gpu.c3i | 861 +++++++++++++++++++++++++++ sdl3.c3l/sdl3_hints.c3i | 260 ++++++++ sdl3.c3l/sdl3_init.c3i | 47 ++ sdl3.c3l/sdl3_iostream.c3i | 3 + sdl3.c3l/sdl3_joystick.c3i | 155 +++++ sdl3.c3l/sdl3_keyboard.c3i | 55 ++ sdl3.c3l/sdl3_keycode.c3i | 286 +++++++++ sdl3.c3l/sdl3_mouse.c3i | 72 +++ sdl3.c3l/sdl3_pen.c3i | 27 + sdl3.c3l/sdl3_pixels.c3i | 290 +++++++++ sdl3.c3l/sdl3_power.c3i | 12 + sdl3.c3l/sdl3_properties.c3i | 40 ++ sdl3.c3l/sdl3_rect.c3i | 86 +++ sdl3.c3l/sdl3_renderer.c3i | 216 +++++++ sdl3.c3l/sdl3_scancode.c3i | 253 ++++++++ sdl3.c3l/sdl3_sensor.c3i | 32 + sdl3.c3l/sdl3_stdinc.c3i | 288 +++++++++ sdl3.c3l/sdl3_surface.c3i | 88 +++ sdl3.c3l/sdl3_touch.c3i | 26 + sdl3.c3l/sdl3_video.c3i | 357 +++++++++++ shaders/source/RawTriangle.vert.glsl | 29 + shaders/source/SolidColor.frag.glsl | 9 + test/gpu_triangle.c3 | 240 ++++++++ test/lettuce.c3 | 63 ++ test/test_enum.c3 | 162 +++++ 35 files changed, 4673 insertions(+) create mode 100644 .gitignore create mode 100755 compile-shaders.sh create mode 100644 lettuce.bmp create mode 100644 sdl3.c3l/manifest.json create mode 100644 sdl3.c3l/project.json create mode 100644 sdl3.c3l/sdl3_audio.c3i create mode 100644 sdl3.c3l/sdl3_blendmode.c3i create mode 100644 sdl3.c3l/sdl3_camera.c3i create mode 100644 sdl3.c3l/sdl3_error.c3i create mode 100644 sdl3.c3l/sdl3_events.c3i create mode 100644 sdl3.c3l/sdl3_gpu.c3i create mode 100644 sdl3.c3l/sdl3_hints.c3i create mode 100644 sdl3.c3l/sdl3_init.c3i create mode 100644 sdl3.c3l/sdl3_iostream.c3i create mode 100644 sdl3.c3l/sdl3_joystick.c3i create mode 100644 sdl3.c3l/sdl3_keyboard.c3i create mode 100644 sdl3.c3l/sdl3_keycode.c3i create mode 100644 sdl3.c3l/sdl3_mouse.c3i create mode 100644 sdl3.c3l/sdl3_pen.c3i create mode 100644 sdl3.c3l/sdl3_pixels.c3i create mode 100644 sdl3.c3l/sdl3_power.c3i create mode 100644 sdl3.c3l/sdl3_properties.c3i create mode 100644 sdl3.c3l/sdl3_rect.c3i create mode 100644 sdl3.c3l/sdl3_renderer.c3i create mode 100644 sdl3.c3l/sdl3_scancode.c3i create mode 100644 sdl3.c3l/sdl3_sensor.c3i create mode 100644 sdl3.c3l/sdl3_stdinc.c3i create mode 100644 sdl3.c3l/sdl3_surface.c3i create mode 100644 sdl3.c3l/sdl3_touch.c3i create mode 100644 sdl3.c3l/sdl3_video.c3i create mode 100644 shaders/source/RawTriangle.vert.glsl create mode 100644 shaders/source/SolidColor.frag.glsl create mode 100644 test/gpu_triangle.c3 create mode 100644 test/lettuce.c3 create mode 100644 test/test_enum.c3 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0637959 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +shaders/compiled/* +lettuce +gpu_triangle +test_enum \ No newline at end of file diff --git a/compile-shaders.sh b/compile-shaders.sh new file mode 100755 index 0000000..78bed50 --- /dev/null +++ b/compile-shaders.sh @@ -0,0 +1,33 @@ +#!/bin/bash +source_directory="shaders/source" +compiled_directory="shaders/compiled" +vulkan_version="1.0" +mkdir -p $compiled_directory +rm -f $compiled_directory/* + + +echo "compiling from $source_directory -> $compiled_directory" +for file in "$source_directory"/*; do + filename=$(basename "$file") + if [[ "$filename" =~ ^([^\.]+)\.([^\.]+)\.([^\.]+)$ ]]; then + middlepart="${BASH_REMATCH[2]}" + filename="${BASH_REMATCH[1]}.${BASH_REMATCH[2]}" + shader_language="${BASH_REMATCH[3]}" + + if [[ "$shader_language" != "glsl" ]]; then + echo "FUCK YOU I'M NOT COMPILING HLSL SHADERS, DO IT YOURSELF" + exit 1 + fi + + + if [[ "$middlepart" == "frag" ]]; then + echo "frag $filename.$shader_language > $filename.spv" + glslc -O -fshader-stage=fragment --target-env=vulkan$vulkan_version "$source_directory/$filename.$shader_language" -fshader-stage=fragment -o "$compiled_directory/$filename.spv" + elif [[ "$middlepart" == "vert" ]]; then + echo "vert $filename.$shader_language > $filename.spv" + glslc -O -fshader-stage=vertex --target-env=vulkan$vulkan_version "$source_directory/$filename.$shader_language" -o "$compiled_directory/$filename.spv" + fi + fi +done + +tree $compiled_directory \ No newline at end of file diff --git a/lettuce.bmp b/lettuce.bmp new file mode 100644 index 0000000000000000000000000000000000000000..a5f3d2f19beb1c2122b1389d9629d2de819ea26f GIT binary patch literal 492138 zcmeF42bdk@dA1!uWmntF>1BJ9Rx9nQta|Ug_p<7}_bwzM5TFi1NFX{Y6l2_Q0}R-4 zj13rU$G=L|J>i%kx4Em|8E-{VhtB_&73J`chC9s-Sa$enf{}eUEk_` z{C7yp4lQ^7-TU6xPRrlDujqZ(>h(YEZS}rEGvDVHy=?x^-uJ%L|Gc*TL&mSa>yF=4 z4ft-NFmd3=f7j5^kiTfrq6#f7PoF-WHu9goa&6>>BlX_Ztgn0f3vHX3zxbblKL-3U z;Ew@+4ESTf9|Qgv@W+5Z2K+JLj{$!S_+!8y1O6EB$ACWu{4wB<0e=kmW56E+{uuDb zfIkNOG2o8@e+>9zz#jwt81Tn{KL-3U;Ew@+4ESTf9|Qgv@W+5Z2K+JLj{$!S_+!8y z1O6EB$ACWu{4wB<0e=kmW56E+{uuDbfIkNOG2o8@e+>9zz#jwt81Tn{KL-3U;Ew@+ z4ESTf9|Qgv@W+5Z2K+JLj{$!S_+!8y1O6EB$ACWu{4wB<0e=kmW56E+{uuDbfIkNO zG2o8@e+>9zz#jwt81Tn{KL-3U;Ew@+4ESTf9|Qgv@W+5Z2K+JLj{$!S_+!8y1O6EB z$ACWu{4wB<0e=kmW56E+{uuDbfIkNOG2o8@e+>9zz#jwt81Tn{KL-B$F>syz_s9Lu z&;NYka`@*+=@V!%yzVOK|{`_Qrwa@}E5M?|o~}gQx%X(53rcIP(67#`>TAU-a3((^@Ix|NQRfuPpw~ z$F18xK6GUXytLPHpV?$L{L5#5<^S!V4)EKyY`SLYC{Q1vbe*g2I zviea2Exm2R+SHd?R<~-$l!C#XEHt`@<@9W4**)4?M&}A^E$(F0ms!D}PL`N4*vgiU zw_*F%US50V@UL%v^uEvD_Mu05`19ER*gTf;55Ic-=h3HkSlWGaEbqB3S2zQ6G9O!F z*>}#e2VeSBH~%~OAN!8pQ*(en4*YTOZjXU4eB&Q4j=E`+Wz>~g%d(KuFZumDI)=cJ zJb7l>-D@0c0wWp??&S5YbKFVqP;6|C)=PWNpS|_S6AvxhbKj|MU;XM= zulZBwjhDau_40mO7g?*SsI{z&7<`FL=wsory)1uVgGDFxwb*TFn6UegbN&@oQl9reb>pPBoo{%-#Hf7%@Q^*4T= zwf$>P{VMI~B*&M;D~Bxj(tf9Baz3`!iobN&8ozX}6`Y)A*H#u-i~6wb{ph*d{LlGM z`<(sH%m2Lo7RSJ@dv9;G?#$uy3s2wl+sNpimMeXcm^0M!2Q^r0X^D(36_zP25g6Uw z`fgch-~I6q{!L!kuYdNlpZ(;^U;grU^qIV-<%REk?|UEk-S2)k{_UU9*-t(BFV}{1 ztYt;SU`J$pAIBNCgQL2;g?+K91Ep^ooVI~KLFpReG_WQ#rl;G+SL3=&`D(o1wXrIxCfniTN9^LIOLpT; zH`%2}AGL3N^V@dY>D%q2pZJKq{`%`@m{-2@qt}<@HB?$F=@`5)7PJe#7fW<7}g3Y8$p=#T&aH zJiXJO+uoVE9md@HgU|mqPx1Zyzu)1w0$;j(_5MFF=C%7R_Mvr_yQqidE$m_WOL|%6 z)DCuC$FN=3K48->9Qe&0pM5gue<$zEcjAAJ{^$6=VGQiOaP~88*G;#OSkk(E(%N(? zbK7BgT0!ZS!eL!4e{h4-FcEoM?1wqQu{~|TriHd`|6ZFuWr|H4JI-b|&9$c0%WcrK z2{vTLL_2WoR{P%TuYY;`hNb^TJOzdX^nU1*pxD56cziGCnZdG%mXLmCY??HUSmgXN zX&TPsS~x@;hwEVtJ{s{G^iZLA#XerQ=~ya_lW*6R1|5%v?OFM6JMKSq=zqia@m~EM zU;NDvviE)eGrueNhh5GqdwXu#mF+J-V8KV0S?-daReUeVs3^=>) zt?&HohkpLXRd`SPULD{5@AdBR`i_r29-My5j$h!3rPr4zkGM$rUFFUfD;(a{isp|L zQ+i9!hy_~bNlRpDUWYGe9G2>36Ya={FWTf43vAS~xi)#nYO9?-!ip3tDd^k5s%H+j zk?R&(sCP$~SBBq(e!&+*n*>L8x4`g5#~k7`;c>kjXCf2DII+W>E8dVFK>QzF!}%}; zKMn4{qO5K;dcXSSYr4Ag_*pH)89X)Ch2qn&J*(babLytE@0Bt2z*8UYeC*;wM{j)K zo=a;F-}Ll?{kvY>cw;lb}o;z><$$@ic{`uzn&wb_A2k-sN@$(Npar>heZoBKr$2Z*jkq?e~ z=#x*Cz7v1z3%~w;=Faau_q*gPH(T1-8CLn)ZBD<`f92dC{Iah+XxXP`SnDy>7T!9{ z3Rm`ZOCGvrK{v~t*XXoO>tW?~U0uj_UA+DB@BjVZ*S!g~{rqv4iMOOHuQ*M)Tm{2ATWrQ4H=mzwORXizIF8CLtFmb-xtPg`R8Zf$a{8^wZ3tz6~4IpibwW#&V--d zZ0YjH(nr@=&fKn+HLas%PVS&>d82CwIOe2}supV$W1HRCTD1?`{Np?AS8x38gMaSt z=3nQ}gZ>zJZ;pYDcb|BFj&g@#3vn1cvDoy1&Ld;)4{9FI8(41{il-B+aUR*2?gncj zn%8ss)Eat+T!0YzL+87A%T$=q*YSioKE;T>F7^@{C1&Va^aolbrgOQDpXYSQ$VSH) zuH!u%ZqkZ&X(WMPU{B8qJYi`_2{I1Vr;t#x3o%x ztVK9rZA#--G^C&7Q>!8mc#P^~ zqJO{F(&s4dCa6yY+{oHozq2=xz^iGS0h}Es1U|;^h zKmFkKU;Z@kr~GdIx$n*S#s6Ne?(gONb01Hew12}7TUINtxGG`+-Sa2r4!aWLN6)|y zr!#cV&o;4|%*IN`ntb_JiP=M)UzRsW9+f!5HF#O@3f81_L^q2|?+|x!xTt$?i*j*mU^aNixLPW-Zb+)$@2 z%Eu3Pei%#$N{i%*0eD@oB)5IF`l}y5UwQv}Ye}A%>iMt4_?vsmyj{!WJh{R$H}n@vdOPg`OVBid)%~4@aja2X zreK+J0>qqD{#j4wr;!_wza$mAY1vobgZ#GP_ieK;e*YVX|H$v<=fV0p1O6Cz508O$ zXO7$!(OgUY3qBaJm8A3mdM2ew@UoOsCSGtH2C;@KcxuF9oR20QKu$A!i7Sr7G4u>R z8}G$=_*KmP%=;;QBd%y4nu9ztG>gkA(=}0@hh{07JHqvoK?}hj*IQ=ESjQn^Gq8mP zE}?-cR!wp|A`bu$jr|GuHnz9s(cYS8nQ!GMNxQ%p^h|toZ%a-XV6kEHZ#q|6Zf&u= zCi#M5O}f0ajPj`F`%;UJ=x*0PaQeIN#5{NWv5SQ_-h0-?V2X$JbMX{UpXAh5iX|n^ z=R%95d@=c#in+iad^664Lxu9oBJ#fq#g+VCV&`yu4$9|COc zeYXGIyu07clzkh&juwF-Z`UQThIk8nVSi5F6j$I#iZ8m)7H7~kPTPnnum=9LQLnM= z-t8=o$E7?pSc9HH+jx1$=nv;-p<%=Wr#YHqIp`F03k*S{B&Au!s6b4~YgcT+PE{7|p;&@Alb#4zmhuFmV%MQd_kQv(8Ji~_xiEL^uFaRx zFvRjnrtl-A=cGHR%W zh7GXDXlbK~id$)4eEcZKo9O5v+LjM0hQvk>5{t$t?{AcNqdbF|%mkjKn9|p26_^2E z;05u1k2Po*w&TrfbPWqVGx5>TG1aT5S;>M?(m%tke$8yhnv!{%f5%G~Nvl*X7;mLB zhB?OY8ZA@MtApcCa+LVeNBLa+8?0Dyn?zr6QF^AZW0{4!wzXJK^-vRI(&7b*ZzPl- zH`Ih#MOt-3~^R0UMBC%wo#m0@aqNx)cXG&*JwW>w4EjdZd z)>1rG{FyjhpT$@!pCe9boBfpwraH!y&z)pd3#U5{p?z8usRxjLr;c~+vTmSYn^h(Yg<*bVtu!ekqz`B7c4^5f|rob0iUszoJ8P`hB@E&L%*65n7?$z#^RJ=xc zXJSoss`7Hh2$xTwmC7G(=UlJiVcnGWr6;kEFk>?V~PfL7GF9##>5n> z33XM!&d$|hO@-yxmRO{_df9X=w^p$N^(}~6`;}Ae=o1f5{!_;5-uuseyl9Z_-xZU` z8_QGNrLeDj$Zj3gA5{5Qir*KAD`7DOz9f_jP&QV7yKiN^fmq}JEEfXCl zc1#&(6$@rr<-)mI&$hCr8CD{;l+T+by)s_Q7#*8#HA`ouG|XhN7v_jBFa`bM*aL&6 zjdp%oNBL>hOJ-U~+9$129^%Lz*7=!KO^l~oJie5_dd!kvy2Yr^OuKWMW$zhbSyPpd zs8~L+7-IiUugD`K=0fZro_O^#)Y1gS8~Ee+qHACZ=XrdAPn^$r_-$?U-ms?Cpb{(F zJJBw_{LDjt%J<-(`|i#${^xu3e!ko8K2f{=?xVl1Tsg^N(hb?FCrK9z@Vc1);R|y= zH8aFk&>`>#7O~%H5qV$a1)yCx2c~cx=elc}eYV_w$`jUck41QJ^b>GC9ITnr&-rHL zf58hl;^`VMH;n!08c*Bck)c&wyhS>Qwd(<(90Bx9-RhZ+ImBlwR!p+eStF!j##yJO z)2!nX&AYR8pD(r)O&s9jF>$dbIa-=ZIRN3tw(`enot8nnplQm6>*s45_HZ2Dgt}B) zR18Y5*7I=Go3nAe z`lA8jFM39Cn8NN27SZe4rYY8T_9QEtIKs-LKT5;}xKch(F%s#RqN&PF6KkrLG^s9j zfzvo>n2Lq7^chUh-#ow)^5@Vm@o|HlXNF#>oIh25oA%Ef=a_{vfgx26A};x)v>iCc;x|GgjkM3|jg4vG1LE?gK6Vf4&R< zoU3;p^uPOe@4Mgm@aYHp?^Qo`X#?i}f+56L>Ks4NBhKG)ept%ma+-wPWa$_en~{Ej z6~tIrQ?E(xnPZc5jN^>X$4_(IY4+LBIOIE{liWGdKdydL?;De@A1_ z*$;d0(a&@No#@doXKuhwzRtdv)_V6^7pF`6%Re?EDT<4oCX^&k*mcpXy= zCNWleMjS~D>|~|NZBC+V>MI;;&^1AMX2fOU>QjK1#_<$u$}OfG=%8wE=qXKa=rK2M ze)H)sz1aG{8o!S`{fV?yx83?na>S^Cp~i(e%CJ1CzyR??njxgvdtj*Qg2w6ZR;(nf z*h^@nyu6J=mg~LN%(J4!)2wV=lVWR%-7KAIjgQ@8 z^)H>ZxA(#9@Rhq<@3Oq-w^*T`RhFjb%CuUex~bhGEU;$46)oa?vDK=f6-NSE^BUf; zO>HKuAx7ia)65-wwztP_xEA(sPV3>7F6RvHz^>f+sRh<>tmVKGYuq>Y-yVPEx!V8g zyYTnFdvlEc*C zaj4k`L(_QtfEQuw=5@{LduZe%{rD+;g>ONln7_k^MO!=IVE(d^^ zKi*kV&wh?89+McT`Wbm)DX&a@1muyW_@dfW`DEFZaU&mq{V*ulS-sJe8&KGx%nEz7 zbBy5`YuV~)v**&;AOEp`XU8u-Shez&gKy%05!iv8#q;{N4xCtJgsh1P!iO6iH&mc3q{*X|~ZKD^JmJaU_L{rG9? z_G&5~6Mf}I%YAy|m0EwECDZ!m@h9%8d!}@s7MS9+jIKzxSnqWQZ29i?1lafe(o7MMexm=~uZ_5ypn{AAd}Yxq;Xe1d$kVT#|Ra+}#- zEMKi=$)qb9reZGnRPvjoXG*3Hk(SZV8s5#4gVp;+dL_~=<(J`wdEOcMX7C55HYWr>;!7XUcc3PPl#H?zQ4eb*dj{vcQV_cCsJ-_=k_beJr22`0)6FYZhNl)kvxa zR5~UurXrNZwdXDW<$St8V1%>zjnLJIZL}^nza~LXX(-=q0Q2z`^P!| zi<~iH`EVt=YgF?-@rC``N1Z0xhWbpH1AE{QOhNCsZ80Rcete))2oTPntR#;x^s)&-?v_&wp~*+rJZk``wvq{Ll63`&`dG{h`2w z8#ewpF-x@*qm%RM%=ORs0y=H+WXNa>?##+^4d0zA7cj>yS#WSqS$_0)waE5q(jr=yp z7H>iuNqE!b8g~aAvE;A3Jn~Eik6j6Q`}>{YNeG@q}c%XeDEt0%6k zD_=e7;xq*xT4OoVE6nfA`{)ef{KQf4&*J;WS?u~TjxBJje z9k9Z&L2;avccyyA=J-AOg#0u5o_W2^@YP(rMc3k=Iqyv8;f-+}^)vLMfhqL$FHwyP zy=+RCj&s++pP~gLrEzqxtK*I}x)#2WuS|>v_7K~5eE`HBm*1?M0IxRF#d-8Iif0a0 zZthse7;0s_900sC>MQ9j6OevM<&c$GRGNgmGIR}WVIh|}uWga@&muaW$}v;koY>Mj zl4qGE;S_7iV^&a8YK3)`Rz0-04N+cKw)(?_71!T-=C-fJREG~=sHLR$B|R<+=mR64 zEVq~PE&8hdWx76#sbefUK{YMZ;>+(!Dz4&qqr5VBlT_@!YSlc)8`y$>RxTf`eDO@H z)S5gp;x1m^7>r@5Uop=*t(b3}w2gjgulP>wmSvV$GR-2=FrmA5I+l3arR4Ej^=!-a zmUqiai=DsTVwbjChevO)t{*#QjW6D9(U)&@tZDz1GZuRJfOUTHPD|W1&mucUq&zNp zU1$xoNb;shjxq2gD(!-fA?`vfh6QgerAy?I={1aj8|V~Ilc0NGke37C*a2(c41AH6 z!Dq{!sj)5A@ILSc-f<1@&(9?14KJ-`!`QcuKXqZVKkvLd^N#`VvHy{C z-;YgKKaas3t;4oC7MnRxtf0P9o`M#~5Y6Ri3V7g{fZqipntdhi~TC zB+cS9jq=gb+80UJ)TZiYqp5&CZO^U+oO zY*<5GCTyX8r*icar(xJGo;T9!*QyR=_7E4p!COlxUx1}lF`Ba3swt6nsaZVH<(GMR z%*B(X(-g-q?5_SS(k|4)5Mx1~IPD@GLmZ}1x&-#%k#P?EAtu9Xr(?>a&P&TG(=$1f zVJlRBut2+Vt5)q~s6jos)O(CLKXv@{O{Sibx_#>R3&ofu`CQ^ifnxvUFc;{$D7|LH z8ur5#Z#yQ=z#%jYo*8UG+tlHiHL2ghB;_Q_Cxa!_SF*qtV*4)zuvuqz z|LEbTKb-XE#j9gp^uOnK?t6an^Us$~JigtcHC*rapGDI@+5zsi)mP_|^8;|>gR zwf>63;G^-nOnm{$=8Uj*i zG8#NTynOH{h0V3=aw;!SL#dL4){rSqp+@$89C)3Am)aj}LR zfJ(8WLOB8Coz<_L?|4G|1uqP548Fh{k1w6qEVgc2R$Hgt8?AKxVhikAY@vI0I=*jEV71UOC4vZoeXXi7c}<=6uS?KDFxb&>{ow=o7G$3@H7h_pJAap=UU*@T+2Q% z*0T1Ew(Nt_fH&$p(*EQlYpwc`trodwq2(W)W;wS`w!C{5Sm=}6EdPVKj^}n+ z;&V4y?&GU1^8t~87PJ6h?c(YEi>=?DBd=$)H`{Lk`l{K0FNei^!^a^9F!{l98qLhAqTYA;p)LJf?k zUmRCd8$*mA1{Jg~RjygF;|q*I%Wy7wCbv3ig|%Xh*is^o*zo8wb0!GnD+jLp<&&24_334Cs!<$ZLce#Uw+ zX}+c1Hr>*XOtG{b!z^uHR~vEL`rm!o6jF@d}^Vk>aQ zi@CrE&UN|)4-PgpYZ~+t?@z9@dtY*u72k&^u+8yBYcv&H@pKNcn$o4J9aN5U$>K4J zd9X? zppW>fo{zn{SyoT=MHwWYQ2kyCyUQ!;rDy1<&wfIAW#Q5KjL|B}`wFQ(CZJlGh-&dm z6kCa@Ha|8Qk4&sl9ZRX=FD0sNDHlu1<&U}A$>utJIOBATa>YExbY7*n{@NvuFTM6| zwTey4t$67iD_gtBdhFkB-Hz?E!jl`U%_hzJ;!Eg;7o9#Ug2`Rq7eA zL^VlG^1kNFdt5ik0=jR>9W6a3jT~Jx!aD3)WS#dcvwkPVu(M08@`F3A`uSU};fr@! z_b)vtPwgJ-@ao-;2h90-AKzjHpWbCKApcX_E%*=n9Yffk|MU(kd||iaMBua6J0_I8 zbj-?LKH;wK`071Y^|Er>UOH~<=QT^GSMRefVoZDacimrm*ezXOd(e7(`NEZj{rn!R zz5Q$#KEKx|+wp`#<;W z$OfMb{{cEx(3h7>n($>fgR`=GzYA4nnesj!=PDU5o~}H zaKpvB&?i5R-z#CZO^3B8+&gJJ7 zt8WaRT3FAJfjPyBDjsj9nFFPY>d=_0WvA?Bc4h{=#=M%@hFSw+)m z7pqB()qAN2bG%Qz>nlUfGI?ZZ8)E#_%fJ}&&xpy8+sxwjOW%Z@_ECI>TAFI*oRvw} z@Vv0zJuIicI5VifWpwLe>75my7IX5457y_cdiGw87FI2PTns_G6bx1W9BmgbP@b9e zNkVlj#o|n{a+XV_Rf@!*Xmf8%dM3jZ^2gvzDRCNY(;tSI46H%FG_GB0-M6i?hP|7t za`Otumg;S*9bYQ9uCl1u78SQ5;zQ(?)fQT#dQGvtc)9eS_>!2X9P^pt|6;{R#F@x+ z#XQF7J6^0FKHFwkO#9F^Fef-`pp|S<-OlyWC@1GQo#4&m-n#p%4;f3h*Ru{b(7FCFmHAd)IRXD zpk+O>QjA;g7>MUqw0eT=yYs{wUwrLLbFSw3#Q)oUp8n@C@alKJIjmfop+s{*`I-ri zF@>YV1o>v@7&K1)@Khfe*V9rO^m56V_t7OrJ9Pqfq&qqJ;vsutJW$I7H`$yFS zfE;FW&q`D`Qz~DKyfJi3)k4K=R2M_)wC`2fw@hZ@e1dNvo-lvsX+;xfu9%j+jbPaJERJsKTf z@`gxDcJHb@JjMG*D;}-o+GI?+MbDQUq46IfG74)d77S}Wf{Ic7<`GR5~x#2#ug zi>8creUf1by~W@Qd1Tb?Q+w&fV#rk{#@}xHYAaKnWm3A?xwl`73<5!lt(|12%Y^@Q(L<^(FvffLa;XHTl zD`MK`@3C(B8NFUqADox(yK+76!-584@!mJ_(yh*)%m2hSr*Gg*`kk{acFTP0cX*wx ze*Dz;j(p~cs{j1&&42CB!B^WDc>U);35>mA{afUcRca2%8`RNScThc{;xUCI<#i0# z^LxiBUOzLtqiwhM$9mK?m`3VGdde4sncYE4cU8e(EvH)I)}z z%dwGq7J&2$454ofxyvwz*VO#O8{#rW(mL#;*MHHtzIryXVkhDZ8m3s!oS}yd3#@Vd znbjAdRGKG7eWrMWcg7mM6YZwl=dSH7p&n!rJr6nDUm9?V`XDcw=azzz%7dCPRxz}It`OA_MmUV$~B8C2LMfz6iccV*QaMP zHT>|!d1I>=THB3Fta{55^-^1EUFDON&Y7S(&XHESa-LOgSz+z2-(=_*_(EK!?d}a$ zv2L-np*}+xKTY1sQiV+sw*8JZ7c7zQuhpHs{JjIUt2P&(MqJ3 z%C=6n_<nhVxK=`WuLjl zdOR;5?76en`-OX~=jZPe+a9u>T6%r%UbnCJ3+Jr&XLL-jyGld7UGuzMQ=xh4U%tyi z^70B_*rVs;Y;>L;zFyvirPgNaU~98hJtuCRX7fLE+h6qDhpTN)^8enyJq|zi;?qBh zOzdSPOO>#&oMkQ{4e4z zcwexAcnkAA^FEwnjm{xH0~cToOYtJzW3SVFxAMWzH1NXnzSzec$2D*ZjY8fUzf&qd zKyzPn9y33e>s>sk`S-wE>%5`KI;)2av6fQBUC=V7P4J!UG$C>Et>01$IQqZH{Hw{|_68w{NTYg{jY=Gq;HG1X?S_Yn!DR0cN zM$C!H4|9A`J{f)*=akAXD^o9+#3a?zj2&o|yOvw`GY75T1IM%+v3_R{S=Zb4TIuyG ztonv^*5`(uRvA{!XEc@7OD|}$Jb${WkHNJemNVYZNu#w{)5p3$xcT31e({6T{WN6#ll*`k|mv+hSU6b<3RF8>ohK|YZMUQ3GSh~20nB$%eBev*%6Lw@NW{)o6ICDS8 z3)PE^*Ub0m7r24`z(<1#&hwf#+~thHBeV=27`moha~gUlDLy2{7d$XnlhQ)sm#*i% z;ThTmmJt`CpA5fGO55oETJKAoD1Tss@jQS|%V)TJWqOnG{7V*kF4Nba=f}VtG)++Z z3&j-}Q;eq3l29+^h>OQ`&^>l{s}z&yfr&p>Bn^|&HVxYD>~sxr88l5?xoPB|MH_1^ z*}bEcOMg_(n5eq_;mR8yU={0EJH}LR-QXC5mWfPP{fgL=T-ao->(n!?X|^Ti&vv;1 z4bmZ{s+Fu$9e#PUrg8h^nI**;e6=$9TT@ORvby8Dtmba9MDh06^~&YlqW8IJrL}wb zMk_nL-KrlrVEs-VwA#Jv^)ttcF>|cfft^;jZ?p7?o@q8)-^JSLR;sZPpNm%}?Wp)m zOniYg#kx0%&5_oWzCp)uPAWE|`d8%vpkV^jm1l^*rtPry5t|_gEi!+YRqU8+)zsQZ z6NTm}r=drU^6+Ao7Rj;fvan^Bhb^->;MQ5CA;q=SYqY4)+Qjp9JS5%(EYh{gVj6!L z+MkguRPQ+Pr*o;b>JYbHwZjr$xW!7oc+A?pa;G(X_73ax_&)1!afj7k++_`q z?zQlT)>)gA>gjgxd`n+1U-v%Mx9V8%&RLeJXSAg)Q?2pQskZo2XTEjo7eAck&rSdR z+~j{ge;c3AKY#!G+n@i(SCp&N%dRacw3aoxR}^Q6`NJ3LXUGT0ADrru%zW;}{b2`l zJK6<(La!I^c>t+-U;Q*S$HN<#K;7gOFHO3|X&Y%D*ipZJj^hZL1GaelA?^=*@Xnm} zQGAE@fM>if`U#GpU&teH^*8z*(Kj)j>v9Riw8%vLo0kt4lW6M{jA38J-Mi&KDNlLj4CRKY=3X(FEbfV zV;6Jq%96@mE>W)tjhYFQT&TVY)EXtFYa%J;h$V0b-sFfuENC8H!z8ZDlGX`!6l=sQu1_xu z+O-mef`g7^u#$4)ukAM7oeB+Hb!cTncBX4$W8l%{AnWc3s zQXINU_x`G75o>~~orx-6C^Aj+vtl#E>(L0z;p7{WZ-y6!Hi0#cA&QqU|5NYpdYKXP z*ZJ)8VlZ$4y@5VSO3ToH84Uw#ydE;dU|e1q=Sa)I8Tv3g&7$|?cj5hs4Y{7s;uU%c z50Br4_a{#c&Y*E})C)PP=V}GTgn(l8LGgk9mplU#odQQfVoh9}iD@a64;CDtbL4$R z2PxJh7I99vIj@X-vIu!(&G}<6$E%H@cNslp+7t!dvzcA(rs6Y+Zt52!Efc9%4*}K0 zl*lV<5I0~-`>mU--PVoPNv~PpNo>|M&DqnX5ymU0yp#3Wr@2b!cG#m@`u&?!e<^J+ zQF>vj^693@XB#(2{+0S;uGHtab+J{S*<%%V=^AmR<_+@eJN6VmT$URFaH;vbE)z=WG!8;4-n%rUHx?+OY#xw2Oq?SaMT@y&xI@8k1 z#g}sQOw{QXytKUPxbxItOn%$AThKyi9T*doua@7II;EI9mQ|%*KjS-D>qY9@^Qrw; zm{KqQtNpXb-RoXr4@>Xo&so9o1(u~PK2Q0d%m41r zWy5{Pe>&mtR?W%kC9k@Mc3Wp^o>8w7<_z_hA-}9(glc0(%3Bg&Qgtq=Ui{4Ium=4? z9vA)K`u)2&j+hgZk48Mkdp=oqMND&8!u9+ohdHP` zGWyTJpS-q7SNES=m9(JKF?CkdLouA5ovj1UL|(VbF~!p_u%&)miZ^VRuU)CRUj51z z&9T6;DHhr|TY1FF4c@JIyz-dJ&!}c({dDzzS!u<$sD5LKa+VLRv3~a+wmuIXv;OB# zI<~--x9b^i8_orcr^dRlAyFKnigLy#TN9-02hym zE4I&qpT@Do0(qO_N^-gK`&7GGx>XuU??X-*n#N;GVx@i#9IT`mXlW#w`}=s=o@>c`d;6B@1cGR2MFzsCqN9R_XqaAx!{SD=lpr~fA_rVe}8}Y{??woMtMdx!a+6Rr|)!3k=cyC_go#EvwM)DWOOOD%mw|d&9*U?bx?I# zPwcd|k6v#@rPA710n zS$~+b{LkV&`B}t&{F9&L{pasy?QJ*J%)Vjs`|FhBOWrbGS=Hugx_6!^4@W(G)x)fK z$w-$kME}glBI1i5vtwOv7 zX2A~h3%SW$ht8qrGUuUl+ON}d9M`7uXvs;2KjzO1q?dvs9d){q&LHS!VP$V-0hH9mUvo>R+ZhnY4iJuiMvHo%}Ia z;`wB3S8iIXnxz$2JTuQbL(dSWiO-#>`CRod8x+UbGGCmTZ_#~=9cRkV?6lBUJ;(C? z{Z@QTd9~tu#kswXHE0%ZsnPMeyZ2b_**(_b*cR)&Ymv28pM*+rzEZqzuezd!Sz@4g z(@FW<(aHM0bq|70A=Y2KOffZ$3H&iQgVyo#njMe0Khe4Ig<5nzJ!T5^9`FVI0%M%M z(e(xLX7hD@ROhtcxggbtMw}rZAb*VVN5<;e)(e$$F{`V^=PMU+vicp3skP)%)m6<^ z-aOk&^xV2t%1KzR*x+nw+?mP;8C7dpUBrf3^(R%F2X74z4L-mc7=hk_6WP)_`O+qN zdagxCIW9#SKXKi=#B{F`?yMd^(m!YzSjBbtZ!CCq=py{PENQB=uKI50=~>eIRD*ha zs^bg(84JEy%>{ke7gCJz{4@5!8J0rzP|H1_eC`|6!&3{|hNbwxw9A`5aP~v;w_E<_ zf5-mo_vD;=HT0sn=JlWdbnch``CFe|b?m_JlFF5;QH*=Vse@nJaL=))rXAby^UmvL zUe4@6UTjy@n^(F%GR4XpN-kE6R=GZ<%SSuTz#H~$j3s%WUJ3hju?<94~=7mVnKnGV+zlUuN5RXVNsm`YIQXfiYQ0 z#jH!?R;p*ablt9d+-B|Kw9Mx9EWaBJrcVLB899btnP5r?hx>>AQZ-I4Ft>fMMY@qzJL1N7?d1yV4Znd`h zeA_k+vnoB8C#l$0TzW8}`8BD0Le?evj?46Y*GRim=({gfECq(3UC3W1{sMET`46FY z(K*^C&n%^N6suVveIus87d*4zOw~#e^Vj=$@&BN%$yR^XJoO5IL9XAKIMbkffW$(@ zE&7x=&cKzZxZ*LVV6CN8qQx&_x zTZ0X(@zP>E%T)}4A8>@6HTIFW7E~^EsFUtRUZpw_e!A>W(hF z{M0vI`rzfumot36_>={7 z^lw>l)hyM-v}_l1buq;H=~?FH2>D~lRr2C>U2vNEt*BnEafkZ9Z(rc*HDho_`oZN3 ziy^KTrZ~bpPrL-Jf|ejI?{du8uk%thF7nA-UVw6)o0);XmM?8nr1*b3)ml<7125 zU=48_-Y?i7eyP8IZf%9NQE$vp-|kkc=Y|d2w!v!9E{eU7%M4Rkqh*NG;E}-^&p#tS zAb&U><~V5wX+Nhp<Y4C8}o$g_TbnlNRK4M0zoy&$Lvrw$c@24NojCkBk~j zGz?yuThK4^(V}7rd1o-m^_;;sQ~m&T|I}xaOU9b~W|+eot&^u1Ao{`H>=lza?aq0r)yvg8iwUR^M-w}Dd+l;ZYex5RXwO@=zYdp*49Cmv0l$C zSku><9zSyVr*HiF_Wy}_#{ZdDFW-Lu?{99}|G??XrMfpIrb6tV9?RuxCOTb$2Zk;o zFBy+4y+O~tR1O(6mvMRSMX+Ut;_EXN6IrRAlgpITv)&V)BHF^_jax_XRQ4LM3!}gIEVKPD-M>B&MaTA+D~FCcw>sM zc)a;TuCrn|;sp#M56$VH`O-Ctzu=X{@X<7;0?J>6F>I527S??ZdWYVc)Nht;*Rwr! zuM?c8`2SF8Z{-0b7HUk%A4Aiy9ndlMJI;tP5qV~@c|9C!l1utJO~ZLG2;L-`dRoIz{`ghz(URRZR5)#L+ z+%(nYjYahD9>%bSKVFZrq~?hjG2TU*f0im1Bi2M0=(%27rdn)~Vzhc4o`ct}Yw@PFIFeqXx(O|5#UaNV znB&fq#(_IoVvFNTwc@*q<9N?cF4X%GzX>b9jJ`9~S`x|!pmz-Y{awy-LY&g|Xdtdd z&*bXohdS3-@c`xN_0@BSrzpNWTQ%qlW>|shUBWxpTj?FQDo^aFl^onyC~!;*s+GShzmcKgAKwp*TEmc3{6@a+RMlun>p1^xvADQNzmIf{r-NWrkvz3xaVR!T z_bP*x^WICkzB=kSL+r-O6@WeHnW#PkG?3Sa0JfyIi(HHc9YZZC=Ws2xK4~>!JwHu- z^B!7dQS}7y^b8!Ke#T=DOkp7>!1LJZFYb2N6dYA=1Zg6CG-5X)<))E0z`j=VyI9(! zj<)v0XMX$LfBi|#UunL%8sZNA-}tsZ|8KqZ*4W1$d+c|I4j#16y!4_iJ#)xCN7?Ba z{rfFe4iE8r=7N0H@{^~GuBlL;4?MJ-zT}JY?@|mx$E;8;&vL~)#2J|5mKDl7Ua0#` z-FGJBvBMI_6ZtOGvA`6MKWH50ea9AYhu5$M4!{MEQLYbwuEQI1tdK5&JLnmwgTx;6 zi|a+he${k3A5B_~_X~+Bfq|Wrcid>P!J1#Roup5Ua+I$r$h20m0zE%jF<{O0cxA-) zvlZtj?%y(+C-wv_Q`_j0%ra{C;ujAMjY18?xf&@-IFF=8#m_lu-aIF5FKA#pe&zl?RU z;xbX?pnJRusqagOc!kalQ~xTh6OaZ9O;GKUdZ`wu&LyIl3^{0U2ClGlV$+q_jmD~Djd&E$Htb2PRPMvH?v~LbDOO3Zi5IX2jZ?BlHA3PA z+`uD)Gq41YEUa_k4adk+!$)&$QZ6*-pmE%_iscaJ2~JXu`Y7eZchFc+?pd~KYpC&b zv3_ZkJaU(v-x-P zcW?|`^Yw3i>&cxr-)IN#Ib#oe<{7*5(@$BCW$K;LUGZz(3zkaPplMj6VfeSsJW#4S z?T*`Mx{GDWKR~m@#g)kX!Ok;-Gm$36KIEGfuT?&=`WV6?&M6kF;EeOU)H4Q_ zpl#4N^pK&>k~j)|%{b;_D9!o<-k@t-O~2M2cUW`GJMO(F*TR>Wa-mXa~LZx?IODQO-@#1djJ>B=o*KiomPxR{Lgp>^`ak^Cy<7k6qa z52QxNi&e*|XTrOG>HD-`yj#q7iw)6F@u-GQ)2|c?wp(VYGo|V%_d1(C` zEwfVZEv}`vR~%+oe`_;&w6z@E#{zmDa%}%L&b?4Lr>z-4NFYV6VX2mDy_j1_1 zEAIN z6J9%AqVEDtgN`YdN1D$|oK1o#l6GB6E zFCn(`Iy_vl_wnilp&amnzT%a*796WwL$T%$KAK`N${m0qG2QzR|95?5#1Su6LvAzs z(K%l4GtQ6d9;a-RVl@495758d=@9skKT_Y<6tQ2i7{?9q0+zrP^bOjF1>T@-*vEC` zNVDdcJ6ACqd^hq4&_A#$FusH0n0gL#L&DX|kQacDhE|~lG`9*}lgd4VD=-Ev)3Pwb zTI8j>S{=@%W(QWaRa~>njZ3WlzEqwWd?D8ipA5dh9k}8=wq{+!aaa`AGd*Dn9vZyy zmVzUbou&z#n(1OTEk?^%+%eLg`tGYwzJv3Oe_#K$`}(WtbN%)2-)K1f)CYgndEG+m zdHM#`Jlt%7+3JTOFDE*0v~q&v?I{ zdzzG=BwaIBp3YG9!kt5ZLwONm3h^1X*;lk$&kEZ-#W9E19D_9x&08?TX%_C6#RFaw zBXQ5n)IBj;g;)&xo!3RLG37OJ4Y8Kmbu*oA@w5v%$n)9INNAUYG)&QC{ao^irCo~E z$Fg{o7Oi;=Yoe;9B-T=(xJXEOUb)H_%fJhx9!AfnB=!PZa#>5)@S42lRr3W(kG3!*5ig*ruvVyR3CnKY^3Ts6c@=^G)sBI3oW*H zi=Hp6I*Bc-tX4cJ-m_UTn9Wvl{GgswztT!i-QxIyb}702W`i%zFVp_Ud+w07Iq3Go z92RsAOe)v;MTeA!v|*)sH#fQ5=L|9C+GJe5)J$ocb@CaN7p`1{a`|R>XT)dl&Uo## ziMT_|rLCBamLZOVo~hCI#D3UA9EN_#XddD)XqmX!k`RB2G=Av66A{BFYsMZmzpnp`>OJwo@WhC{1f*}+M$5n#v$#T5cOF_?`mbCbV(no)lT>~f3_-`>n^iXFp5ddx9cpce!{DQN zF&xh4IIMv$Vf9P%w$V9xH;%Jx3*N^P>N^zH>V6D?j}H z*}gm1T#hu2v$lsdx2@1zH%a$|E7YHN?Q9FEXH1@Y3g=E4VmagGmo<&Gnj>4S-7)3w zpV(n#dskS|R^`8LZgRY+*`r$fO;f~~j&2Ff#w(XrQCy~EgW~VfFEQl-plRR>y2jHv zF?k^LD0A@>agCaNSmW{l#1$9;XPh>XXXf;e*a2^dtQOjAXXD1ggmUlN> zKWCgY(gfWTizx{`tFlNw6}^$+O`>@zlCI%cgg#=LYaM6A+d|!6XDA;nLyXF78flrD z_c9gNCpOb6USO@&1Ez%-)0#ddx-L_Fma`X*wU)#CIGzMHEVIxK(ok^lHXSBZd>6G~QZO%cCn* zPNCu{_+(y;1@6ERbPGDCR-Xrqsa79<=aVTH04{M1rbOk7CFDuQN6QnGUWp7*{9oQ= ze4KJJ^o+NXnaU+|dPeyW`piSBS1q0)k9CsXPyI$=4~)qd>x=ZP(F#3pA)&Y%vAxQj zbDUq6Pw!^&gj$(|a@XAR0oYdkCcL4SGc}tr#e2eYRa>KeVsIc&@tKV7DenxQ3nsu7 zvvGc^ciM<0p4K7vj9fHca~_^svGOp=VZGvA#WR#^ePM;w zUP{%{kl$Q;VXM`tFB+N#p1>X$Lp+D=66qbz^Sm@(hwpB3ewx!b^446QfUaSGYx!s` zr?j^|7k0e)?Dzk%i$DLqbMx=t`e*s+Z+$K2ju$@pi_pwb)Y|x<|QX zxg%7&KUVsnNje7443A8F;omww8nGJ|u7fp^xjIMjTiD|Az*N(M&jmB+3**IB;0m4^ zaTnOawyVEX-kQrtQw@jHLOQQVF_{w8ikC_+m54jk+$VJ}olu?^>r%0kC9FA)d-&qf zs?*Rh`u2x4-(~A(x0VOjdYNhtZds`w@0%=b+iXi$@8vvcpA6lLXHOYm`MVZa_WmV$ zZsSI4rQF|^+Slpnhb*vfz5J`gjuWuLTPp58VYy2*Pl`RT1+G+!C!M85;DN`5q&%&JC75e}-GLKXGV}aW1-s>p35$z%yQxAHX^292Qu|b@6TM^}Q@m z-O3_E&yb52P~B#}a?jG$W1xlnoBR&NRw>qaei)t_^)N2p0*B#32n$S+E*jUt z(z`0gKBUqyC8+p!NGw2?kbedjV2Q^V7n8wLBL_`2n{F+JL}q9kU87^@8kYmDZTvNO z1zXs5`Dk7I>n$Xy*<^NCfKDyHB_~hRLrYX z3{Uh{j8D%!&&B(CM7idd)?UdAsJ^hl${${1ZN(LMg0F^$#+n7T;IF|Qj-zeRJuY_B z%o$k2zNq>Rq%H4ZEk;yX^uT1h^!3l}{9B(N{lD)oXX*VfzL2x&1LuDaPg*FJ5L`IH z0`tbH7EE;_(}%ewymX31)nm8vrj1s8c&mJtd6wKf-{Pv5NN!nR6*sK4iW}GIxW@B= zRW832e!vubvGN^yPOQqNUxquhaX<*&7rPt!`wf*EOBm6P_#Q&#!(IV(7~ z%W`kmbBCWfXI(yh-fEt?*Lr;VlKS#KXt{T6wpRKba!zcp+NbZc>JOf^y8BL9w|h=o zjTnG7iC(|e#qS+s#236Tm;i&|LF~YGL&v~{=)SFP8!n)G&?n@TaSVny206W=XKYC; zaU5QyG|NHN?Vm_#8gT~>@!l{DO~g5zpSW?CYBD!i)%Fdpr)F@xa@Ex*Afi0A!l8P` ziegS})Snp6u%L0M@Aq;8&@n6((v)6K06tqlasI#n`A3Sm1o0!~lfjTMJ>KZOqczNc zFG=Yac!S14!xXEJGw0Kf6usjXdRgndyq@hXL%H5Sy@at1qT)eBzE3M}E z4lCZV#Oa)pT}!QG=TgTRw%L!TR=$6=7_`NCXJyKFh8HgWFE5NZ4Ke@1DLq}h2F4Jd zVGVOQ*Kw&iPXPaneK0DaeCW9H&fo`{1;5OT+mIjNZNnWGhoN5G9TmNd+Y363f8 zPn@z|&pqN;(&5<$^z5k%;>*LZlfyEx_P7C6Ci_QN5r zgC~wrVh!;cSOcqyj_$WIu`GG=pe2s&v)G}X7TKHP6~~ju4p^59>R12R89kruh}9|| zIyh;p zVqnBtcuqoaknZiJ5kvAMy_i27ahws`z4%O-o~3|4hQ3KmR197V+~GW@d*pk@wU9HA zBmao;lq21oGfZ)J@g^qTplxD{bq}KNpD}>u3C&ilP#T&AEgjQ6M|_!d&1A(Al?wm^ zU<8^2P6Q{(57RchAua<;I0x^nbe(ea*DB|vnJefT^ojQ#u!`I@IK;w!yff#;i8QMEp zo7Ve=TgwgotmV=k)@r9bU9l$lkxf?r*j}e)Vh_u&y=T599$q5tvdQTaw2SAd!5c5O z!#);bIA|ZVOz5ogoo|`o`q#iD^3qyNs#QOMVYcUUkNo1ffB8R|f2(t)|9Aa)9ECCS zA3OIuv`bVzSwh+*XR_*nxo=!BUixIcTLOx~pjq(7;0oTE^USo3M+S$8$*{nhvg=n_ z`5t*M>nAup<5(hn;=Hqwot&m&Utp?wnJEqnZ_pVqAgUfBFvj_3x~6#D1gAe@(nYaZ z)XnHVm6*R4`ohplrck*@#By9bN4|UMhDoVwbUnI-`G%jz5}cmehI^%(r&?UPr$Rce z=h6Sm-g`#bai3?NJ0d#AoAd1)&Jr$RLQEbI!SubIutcaw0*18O$V@lO#)4 zvMkG%y$)mV&U(gP`Dh$QmZf)o&%aSHr8E0sR_FK}iTY5d>Q>dg-M9PRdg=-9`%-Uk zVY?Nhb>;1vXW45fS@!a=mcM_I6{3#`GlVU|lg3Y;dAQVrGqrFU9S=RV+X7d&TIlKB z7QVaR;%}a|*ek~@{>EvCGbJBhc3emM!*};u@Fuy^r*>KFt%*vV3l0LoH z%FeaoiFk&5eBqDBH-sS`-_bsC65*25*5E?oG}g?(Xikm;wCOr#_{ARa#(!s z#CNo4Tj!OtR4~uFY%+cv_$0j1w$|c5(%Zy&^f<(GDmKxJdFKL$8~R^s(dSHjIX;I> z35(+|tXugE8Z9`}`q^vEK!&G~H5fw%ZYDY&_))eF-ov&yhqSUrdTX}Z054YFSv+PQ zx*^*RAHWmgh?fr#R*Cy)pYTH1;_7kc@*HYwlsnTtaiY{5JS+J-bK!YlPT=wO)DX35 zYWmsYQ33U~8OJvLJOd-}bOup#GZf$O337Xj!OmUdEPM3;%Us^aG8ch0o6va=qZhof z8eMFa)5B7)ue10oD=l?Z z*Bj~ab6c+!jk^}O=ezq>UPo)aws@3qMn5ww-GsW(66Tha9$IBNvxi$I*T5`ZFNe9l z{!5!3Ckfx(XQ>Y^I(!kv2w#LV9X@)>Dn7hok+mHkL1h9@6q#wMGZI3Tl>4`t@hqID}DL2!>vRc~BEE?|-s5A01nBY(fi-2cy?z`giH{0MmPG_1f-#poxb}qDf`mdF5tye6cc73ge%_4NNJg&r^B(Y zY8~%o3SJUCCkz&f+k{8Au7yFWH%%;{U)$~{ENk~r%UssmGG;be)`8&`Bx4qPaf#J` zc+{dFZLs3&Gc5t$)W5`RPWVpsOZa}zw$2vtu*O?^*)?$=ZxJpj7a;vj=jAN!Zu#^P z81mXNd-{(*Z~1MzX8!K|{O@7sFU-EO<&9_mNt`5y>{Kzcw~AQgu?TPE(+F3DIl>cR zj?UG-ikwEPqOg!gV(m1IEV0~3JmbD z#bE~6;qet=M;v@eyhzsT+6Htjys9H}t@K)p)xLG!aTei_u*Ks$!X~|*7HMemaOB?z zlk~GZY|_sc2a?97pHunzMQeEKg2M-4jc~cQ`X`9PV2aH6}^s^bD!PU^19>gPl9)X z9~G--fkW`wWmCDoClfnOx+VAfizYeDsaQ1=tO0MpoX%U9(~Du2CCE)EPbU3LSmCrV zFhsn>aTavUYW%UPxp->A7+?hkO{Vg-4ZZ@r~Fo zzN5!ZX9J6*(WT%$!WrlJi0jPi2~XtyX$rF`28zqjX8^2;PEt({GhauLy&vAuYS93b zho)Kf_Q94hqsi%Lc_+vwgDvGB@3HWQ8_f6OBJ;nt%mS}1XWwpX{OURD{K+Y6c;}Ec zzHz`BU)gJ&Uuf-7^F_SzbT)6F$8+T4WX?ph+%v*@-rH@@{OI%Tzq>a7?_HaJTmD}E z`mg``m6fkP^N+%aj4tFj@nTBhA@cO)#Y7g6*;!782TT#R$nO`nP1yhs ze{|oe@4Yeu!W3bTxRA82hnPY}ATowtwP2O-N&1==@gHTV3kT67jGyVJmb`Qt*Cw)S z`aKHRmqkzAoOx*RC)Zi!OJuNKIAV$0`>fkXcOGIv-TT)qaqp-VpIpg2_vMxe9%WJs zl0_yqlRgJ+dQ@5VV>OmPh`-@L@fe3JYVKdP z;4^!y;J{)F9a~~0C(xjl!>Pd;uNE^pvDM#CkSTN88C*pe;__zX)?CJb$HF0H1f;PE zXFMNB$Msm8$KelHFSGV~(Zh3C2WD{6k7(&2 z%ii#qWwB(F4ahn`rsWiQjt^R_-RH-x`cpi^7sy3|ImwT=S>xBvgEuUnpR>l#&RXNg zr>yav!`Arn9&3DI=R-}+!(9!wgHsoXk$eL?S$tAH~C{Yml}E2a%R0Jd)p%S~$%0g4g}1j*F+r)5#w|zx1vZ)`oc?xy(Qe zOJl>=&+c0fu2x$Xebz!xwpj1??^v%lZ(7MK)Q`M=)_U-`=SO#~;>|PW-!#z*#=*15 z^yK3UXFk?I-|3WP@;$*Iep44rx&$-Y-`EsMV&s!eS_L@A4)!Y`(!J- zxW-b?ljnLD9S!aheesCnGvYVG9Ib^n!WpfFIUWXSpQq7Py$`>5=c<*z@}#w8URdQV zGGurxt=|5=hg?ORMHuo$-s546_IrzWyw6jYt=mgiokr$ynJ=!zXQZKt+h{%bAyG7$eLP28rvW;WaUIHsMWbF82fAl8y^+8aAN8@>y}Z z*@LW^^3CEb$_zL^2X3RhnOpE?gg?R?VUcpt4|@iTg70u%a@Hs-CjXpTI>KR#{2DD^ z#GO*^Np$}r4XuP+h;%gZnkf2i;mUEAyKkZ8?3iQ4m$q2DcW?d@&Um;}_Vy(UJ$I0E zHd+3mr4~H9#v)sJuM5a3%q6oz9zZiXLoCV#2y3K;$%AoRM;;CSj?NLE(Ofn69Q+!G zJuZvZibu+&xeT264!P;rs5FNL@8}q-~Gi2#16ixpwdYSYt<%OK)#dSa&M}Cep zHeDBlF~T9O<=Y5bgfWHWKnuVaX>hqcYb>*=g4+6Kc*sD@1kotX1Gpw_C<4oj|Wv2GteW0mh+ za=(Lq{==LA9*;1mGdf%MPo8_2i59mJ=16}N=6E`s-b3ws*DU?UlUDLPe#~|J{`1tq zoIhw47xD5R)ZIAWA1_AO;&RXA)>KC$ep7YrlvTo!nxDI59bbm`fFa^7;xO9o`06EU zCpMb@*lMSpX@Ba4W0rX4p!Iv@y7f4>->-P%w~5zC2lM9P1Ybx&@x?3SsPjb;{l;jrT~ zRqvpI!fDFhzGzW+X~|n~#QV3b!@IYv?*0w#AI@9B$<+><3XiWQOET92OTfFutvp0} znC7G@)2ul);wIA2lb)ufWJWLiJ9@01pKQ5j$mhc~@-Cn|+?{I$H>O+Bow<(R zL_XT+^fY0RaHsyOr~lV@^9DHd;;x6-;$e)pR`yvvIbGkH!(%LWaSxkz=g{ph<2Coo z_MUgY{nGzih$h~qjQQn!M}-yQE+rf1T6{4Y0X|JWweQZK0WZXP{K6QrX!2`3tZ}*; zxFpYC+(x;y(si@o4XRh6KLxxYpWd^Pfn;N-m+*lp+76L_4Nymx*O8u+EJ3zY)WF2) z1C!6ZLG?{6orYe{9IGJp+&*}W)-kjUzcOlYmf%=2KVXXXg`VifJt25Dp_k)8{$bz~ zGoi!GD#)gXa0Y#qGx1+?$&4kg@3fw;fh+Kr20V6M%X@R(j*5)0Sy+xVV8|D5~OMDSoXuj9sndG51lKI}w``_@mm8?dipTYex zz1<6vAapAJRe6q$J5n>IXXw0o3ywTnFIL-wQpas>U$Th{5BYJ^OU7e?y;P)!>nN1I7=Pa z<}gP6X{xWEwu+l4EcMJ`i`}IDhDG{V{OSD;OUmz^aclqKl@>U@#^H}RPQz=LEq)uH z;v(5Je)nG2j#=}*^^Ug)TZAd{V7v@~cupGcUwHuGjFyK!4jf0vbWYRe{-CM?4?ZL&&lbmCfclKD(>9ySV!;KFuvoJnc$9Lc} zZ(g@fFP^o!XXw>)dyln$p3L{_m#qCe*B#%fy?@QZFCBGQlece?WpA8ndH9pj)zt9N zb5pn?PewJMu8$2|$7KfOxsWqcp4sII$ODMWi2umHarrdvW0LF(j^aLNx_YY7PhlQD z)*L=>;7NkdVtOH3HJGCen(}AzYIH0)OSx<^)S5ND7%lqtTq}NdzGWXFCvcEH7S~&G z#(!_A1>Ra^q4&{}KizM^`)e%t_G-7?@YS={8Sh4Gc{q)qow3IEkKy0!`(J8l;y1z= zWt}zi)4!iuo|Z>#!E0w;__AGhzfA9U&pR*wov`AORK#%(<&cFN#ndFKuHV)8??&eAgU;I7W^F8lrx%9%wsip6EcV=(( z;kyOa2z!d@{~qk!`nZ6ZO#!w`#(^vJx+-ASlg^7j0k*K@b>aNJ?JY=8tnyj(mSmlW z4yIWH>H{67{<(-*mf7_wE9lkMY8Q^9mJrXAnPHh^j`GmgJKj5QJzu?Qm0S}`UO4Ko zrq{dFP99op+0*-3M&BySpdKNsQxxyG0xt*+gX=-D=8(WogeO{(XcMvdWKj8j#}`pQ zNX|9Jx%q>sT|g_Z+BM#)<`1$CTn|e-*I7}N9{%yL#cG%zlj5}_e#;N}%*WrqC{DkS zV38HG9qvd!{Ndb>9;N@xjop@h`>Zv8)S77%mIzyfCtfB&kF|K&HEruWX=}n8VUqB( zfqU!|j)$g<}x9c_V@N#>`&s(%ythBM17wPPYW^K7d*2!}r~%^ELo&;Qa{Yx~YM zOTlsCZ=JKy^M@^u=Vxu4W?9U2%_4hWyq+F^^iT_pg_q;$yB;)fW5;R06_3X_4Q*^| z&e>%L;5dHfW)?qI3(kngkl{xUQ@%_&fW&li-0*7QNgA!L1gz09Ke;pUn&bl<68`7z5sGr{uCjd!|P(X(^S|2psWlO2xRw8z5{?nq-3 z);JvvEv@tCV9qD-9p~Nbw$9K0yLKjCqr9`~IJ0KA&SERtMvvHKy=>tNr(gauU3=92b6ThIw!0*8qX#%lpbq>sghsb0DDvCb<1Zvx!&7c;*} zxFa4Te9^H-=+~63-c4-hwNG1iE&Yz^zY(V2qJB<(J^X_Cf(6Ws^6?r)0~)CJp(c&Y zlC;1q>hufN(Rbj*qt^5ay3gqrE8aS%mCt}T;bSW-3tcS}T}$7^@OUzz@>J0`65LaU zsYwXZyFJ1^W0db^a@hlnSpbJ(5#~hEEQ&^=xliq80qW?4HU0tM5_~0Gp0Y>%(WQ`y1$R=wDi-c}1`6q`raPW#p*hx2gMofGNTiX<^dD z#8t#;w20qmpB7<^xQwtz+M2kHd>fq;y}rxhS9e*(xvfq|b9@CHkx%0?&1h*Z4*;GB zTjbB^m=p!k9zz zEVyeLyl)0QAm|;0KUcPAvV|8=f3=8A+InX6Eu$Cb3ce?-eN(yTSUbWxUZf8)e5dXG z>rP{f;_nG_{5N(uElqk_;VCq=t^DoRjIjdz`GP*oS8b-Je`5?Ezm?wv(8*lBS-b}x zBfnpsO?*23(*ut`K201*-V7K5Pw}{nwj<-!Ta7wTc#br+{Do}~=R}Lss83BkJVvvnbC%GjhI&r*;9UCJlW%@muD@S~_xaVo{L>B%hc~)h znXp8)n2A-bS!Q93bT4t1yrDfTyC3|3IvU}O`ewTRWnfVrd9=Ji-K>b2^@Tm!Sy6MX z!w_LbVdqNAr8l{-qp%AzgM}CE>5ajD;fOHD&s-7l7GX{i7$KhHaTlHIaUVS=o7qim zN`mej?awGfcM>*%U%6mRK3ZEAnbkt>F|$VZw9FAbEORJ6{a8F3>Sn55K4tOiJ1l?o zB+Hsf|6_Fa$eHz4yk(ZIqf10KSCy zeo8MBe~E)bv4#Du5Iv%h`^z@)pNuXE3xZ2|U3tx@&tXPkG~jqls5Ak-L@lSd04@_S z?HA7Y)A%*;m^e5TDoa|R6b+N}@`A;V?-WLZmM890%X_9yKA#>pMf>SbaCwW%tO;v8 z4x_ca8)1#deUvlsU!;c(=U2Z$-V8jbeTDiM7SG#H+&P3!w%75N^vm>ihN}oK#A$>n zZOIwvv9L$SV>kC$@YFgBkj>NU2wyy2B`j_;!=~jK7+KxLrt^OHivz#J#K<-RKytVcoJJhW?|!Khbif8%pKiJ{&EfdD%kJVtA{(RDW2HX@!JIJP3Ev9xH#g^)@3{p|M^iRH%NMf&;x!((Y1Pu;H{ebA+tgXTu))>W zs8@jc2*|4`+%nj*7j-k&6K!-m{L*?`^3vJ&zYN#lFT;C$<9pxylkBeTonP;Imo?Y9 z?3g@#;f})pH^RyH_I9IqNzLLl5=(*xDdam%K0K5_AXkR|F)bqN4KVVCi>L}F% zhKzFNNH7N6%S3bY?^$H+?vdrfgUMfm&xzlkN52?hOaZz@_UP_-`)$ofKiu>ZYSHoS zrH@7U{)PA+2g&w?sdEsYNx@eft~|gN=f?~$v2eiAN2`-wD0^!;c*T0`41O4 zoh(oiZ^aJQ!V_Ue5sRmp9L15!m03Sde|Hw zi$+F3KEJq(*5WcQ2Mx}6oX6GM2xpXg7WS|xhgP;|q7|c|g{jjKj}gwqXORhmwk&QAPJ^fND$=B*vap_W&9=*TN4EOPI-MeuV%clMd@ z_)04#^A?>)-hUKaYGAd?Crcw!O=e;`88tYKup-X3hcm*KDECOpp9w2`WK}d1RM;XO zBa9M$=$PX(oR@&-2!~pqOU=z#`Y)ihDK8)$E(%W%QZE|1I@^5DFSKIt#{bGP^S!*- z<1N+h$7+>SIGM^Lgf8P(HuvWyDof*Rx8!%`-l`W`@33ypU-83dQuLDaIE?lQYvj?0-*{S@ zI89b%r1d#u0E9d8a+C)U*7(7x0R6FY$PQ#rq0iVNa{us?3^Gab_p_MG977wI_Y$Lq zPMDHQ|NmTi{ugeV2?oJ&`qf!(e>5#LuKFz#t#&j1!~$|jGo%-wF-T7UZycvVn{Ylq z_j|2gKRP#FjI^-`-^&0>{Nj%Q-@3_G%T{JR17T!2* z41AF{BRmneiB^?Z6ijjZgiG)qy;h>G(#kqhuZOiT_Oo8et~+-z<7Y ztDk4qboGuN!~G(EBet_9547NBJa>ACMthTQ9mL;|8Pl0n$G)+!xecm z;w|#$g(t!vaUJm*WunDx{yp!!n*IX#$M9(J80lt_DfB3#FNM?2X7b+PH6iYe0-P6G z1lGW5qWp~12Dpv!62FMSDH%zd?MZ@_&Jnnj|7M)*j zl@D@i%B6|lc$nj@wJ$`@J;Z%O_=Q6jl75F~TD*b`GIO2_`nBejA z99%9ftN8DTj^+xkDXsWA`M^m_Yu;s7A z7h2HO&FMV&^?P6YGTih3w!X)|{oB9&>)-$GcWm$NE7q2KLLb_HFOb%?%&QGC?MAl1w@IA30PA)F{|;Q3Fr?4EkoKN|2u~<)2I^%f8!I$+r$xjh~@v;C~i{I#&bT#FpRhLt-X0`=K=stk^A3Vg+_`$5{KLoc);mf4Z z-g$%R>Wta@%i1>0M0~?FSNq7 zW5AioRoi+b=x(`60E~Z=)t*X zhDEneweZG?7TYz$V%zBhx0(5q)ZP>vS_*y~vu#pk`N`z)(I#`V>Nza(b%ay?Ygz$?ZS*ZM_cvmcOqj zUVHsDo4kT7C-;5IbNSG%V&I7nypWGBKH}?M#~j>xhX;|z&~owYb^RB1h`adV7_B%^ z<1j~hm^_zUW|<35bWA)&`16p9i0gnK;x0O_Mccv`^{j}hi1m(bgd@07TU4^LFyewh0}KiYO7y`sYOTNiJU zr;_SWZRz@2mnqY=-_yWK*eAV9*dsiNRHhtX5yl9I63htGe&LXCL>`SWN_@xpG~iPB zL4H8{TQMvS&Xl?5rkVSq*NOAHA!~e!7J=&#?g5o6GFb?8T#~Of! zC*E3kB3`3K`#c;H-h6TKo-e#fJhhMc1k5(sywDoAuL4sRIqo7Y>totqoWsyb-5S zy-iiiJhE2!*Hgflaq8<0Z($vHLOsgRv6NY!JI+E2;WEqMGT@XrjZZuXye-`^+u=(U ze55OQQ?Y-6<;@`5ach|+udU^8Hr=vk^|yk>gUvsS9yoKfP#3xbPig-&r;mxVXrJ&# z8k)4T_*#4+G&Av-_>O6o*gM-|JDL9n&S;5jLc`lViwyZ%D_TxAdJexk*j2P)GX1{E zu+hh^@d3B_BF|ARsIqE-+k0Jq8~Hu?N0#$F7{P2jy!t_^kHN>mS5f{fpVFO zLT|2cxii&t%B%4_8V_T%7O(LhyL`ZV$F1|rWH7)OkJkjKrzs+DP_&i&*=p(z$Oz=G z?Qg3-zWFD=<=5ojy7|;U|M|~<_>DjPf%WIRtQ=T$i0ZA$-op!&{SwEJuBCM=PIPpc zE}fGnO^AG#w#8vQFW>PJ_=qq;I#+getkv^ppRl8qyR`Z>dJTtTV2rRThpd2dW8yf% zFHdg^^lJ5eiohx#UQ5Bs2@XHRUD~uObG$2a9DUxm&$W`5j#*&e63asm%9}yI^YPT! zjHNdlSfKojFr?jPYR&OqgehU_66C)`@b=~T3tO};-#-S9XkU!)k~A^li006&(!j)H5_J_;L7#ka6Y-QFnpvVVxv7R4^tEaW z*OfVLBCKlF)>=7=@@GN#ig=6oOo;7hRod+nj>W3MD2}z_4Em$6Xkd3MoW(VF?kMZL zV!G9Huit>5(f+9emQM{xCR%7Nx?y@G{Uo`@H7=iMrRw8@eirD?eKGxVs>jlUbQtrt z^calxHI`Wcb*=fFQ?vyC`|Jkm^o2e&!VqDKhb11)2x~k&O>6HwZ@-5($_V(#(WU7( zQMF}JYYzc%LHMFY+L^o>ZM!vCBTkb5PXZ(RlLuxl9`&8k=_4J^gsJNa34a#CA=b_V zUuIf#)oieVp7nFafeXxM+dzgIY-x*b7GE_M&t`_j_s>Hs+hQU3N)9!-d5eaaZ~g$s zS%fJ*Jb7tjS{$yB1&A!cGnvMlBAI z;y2n3(XU+C6I?T<^_<;kN6V-QIJVU4U!k|^J5T)*uMxiy_DDMy|yc{Uzbk(MUy%kdfU79NNBJPTWNEX6&Q<2~Xxl+|`BcI0W86cdIh9-`4>^pD#`R}mCeq-?HM?d<}zl>QqAH9qkXXZ;feT!>; zoLPpdZ;{{PX=K71;fiJ}6k&@z{M>dampK!*IRAy`JFkZ0 z@?mto7GaI^Vfa0SU&<#7U*f{P`OFT(>wcsvVPC=f{z^r{GN^$G96%R7veNv!(Kx`D zEODuh@G!J7AGt3-eQh02!DmTRKPes)(fu1(BF#)XnU*A2lH$0|6`x5{)30+12jLkF z!8@gfEeHn5-!DXOE95@W&owyFvC3hG@Wtt6V2!woJp2@Rlj^{AnrpxO{zUs~tA3Qf zEBYyt2)2gIzD^c5@gV`s+dLAP+|#mGGR^ilELUd%Nv4{3im(Dejo$f6M>0C;fm{jkj(uUa+2MX2J{)OQf-R znE~zh@W(qx$F$GG8EwbmHU7OzEU+B@LH$d~k|~b6$d{2<<7J=4X2PG5b)q*;`N1{TbZiTl zGuw*schbz7OWmZNXl8%74F1O1Wq2s0gM`@I$yFtkJw0^+YRON=}=7($|DZT08!-nEGQhv!ed=XKIL{We&5Z+x!mH%BWX> z*LPETnJ`DZMp=M|90siM>T9%5Sfh2rrw@9hJ?J5znV$ZGa{$dra(0_`1(1cds!Z{ zvD&mRw>H$jWRAvXphthvX8JKn2bxD;GIC}aWC=3ULG#t6Ek-^e+ztLSn3|Od=wYfa zAj=u*Q^&OzU3nDW8@_kK6k(6cl;MGvEqv5!moo#0Yl!sd$m5-?pg%ok@L!6^qQ%KA z2k=_8M9`K}oodm@sBM6A$g>x&hP2cBDP@wVj-Kb(Fh4UNUa9Cw_bA-zl(q_uvgxRjPumv&Z3jeH4S zehFEC7_*BLXonT#H>xJnhms6l+XZ9nu}$=J97z_vYn5fyM0r1rR)=OIyy>!Zyw#9v zssvx!&U(};M>m5reXM!*P=`BlFg!uO(_oh}EAB-0O<97eVD|Yf5B(PpTf|#DY!L=& z(PQoR7GaFHU&oYNi=J9KY?}yuEfBY z7`e6Z5@zzTj+15fvrpcPxJ(3}Cb40mmF!*(&g`)IqttVNH;qSkS^?R#jKN*-we-1y zn_O6H<$GpZ=}x>B_)G5Kb{2x$M7VYbX7&cN_?h&ejITi_+d>T^z0v~cV8Rk{7;zcl zjl&$UL^$Jk4LGEAblVh%G4VZcEsiG+%(c{UGFxX>SZDs0dL2DZlXVLpVfNUw`>pZ* z(^m1$W!J~9@lF1QFP^k6&mOWa^my%po|d?<1pT<1Wl-OfgNL8V=h(;Z9^MGoqlafq zc>s!U%^adJOhR z@6u!Km(Jz9l?VR5p6lfVoTtz6Rv!jTdVp#2TU0wEA10?QJuP{TaH)vb&0;QQ8}hns zYSPZ%mj@F;tBGIT;jpGnL$%{I|0yrqa!SG$?gSRn$I@TN^`6>_2tO|bwj?KmCG>kP zCks%`HMWvGRtfX8k`wSjSt5hc{pcxEIjWmg(Zi;6I6f%-1kwZQt(05-jobEpd+0PIXR8i}gS&r+;(1<4Y}aa*pNhCrf>1h8101 zV6nI4=`OR_tD7u*nO?q2M_GIHpZ1USv<`#lF@mNRfxCp@LIH3r49|(Tt6<@MmXIM} ze=FvcIn7MJLrfUg8*c^Azl0u>!j@9}wgkK{Hh}lc-=GF=(~ds+?dFfNws6E+%}}AI zg8u$KddpSK9&DBL>`9I1`hv$Cg=dB6V=8Q^l$JKG2fdH$Ek&Q~D&_=L(z7(mu?SeB zJ`CAo`&rJi@vinpnDIr7@wPqe@i>k!#@pvTM{CvGq%Ul<+G887L_P9WwrXhVk*28pUOX&j-)X z9@S*N)uZWUa}q7>mess@5&s+yW0>6DwscJxuph!kbnvhF;R(i|S{jqe)W}_fZ}|b8Q}}^4lZnLg(Ss zFlVRc;8g4U_K}Bt#lsC@itt6AjTUVSceLL-=U3OMPj*<|`H6f_$m(4tFTo6f@R=!& z(`3%N9xQXyUnKI#oYAm&u zRwitbzpuQp>RP0OiTAkk*zf!q&J`v(yny#;Uk-IM!WQ9@_>=Q=$O|YNApK20OPOUY zVX_8cdQoKxXPU_AKEWIqa;SlW%cxsxutzH5_6XRM3t!2M`7AdXuvD*()^XxMha;)p zct#z#$M05W6=;7oTxYB4Ia0~otG1*2TFnS%a|~sc?r7!&&<`!vpV}er<*T?}Cg>Mk zj2;w38;bU=bH@^ob+p(RG-@>KB=@gr`lprkqQ@4!W2B9x>)TpsGyTmvfopB4@kb|1 z(#Jl*9BJPH`gZJ_U`1EvTj7N{ma~=qke~0j!GHLo_4w{ht9pT+B)gc!zIdE2FDDdSZK+k=H`ca4<&sGihnk&dTtg^2t5q4ex6O=x0HC zsD<%z4Eyaw)~bH!_Pj*bOZk>&#Sk{O}yngO^z_G?V%pss( zQit2S9KN)_wasCS@J6^JtZ96jxqADl4_k>QKz<>YMH;PtJF^PO#YNao%v!Guk7PEO~J;;?9ew~{pzoK{rlbX z|6{P~;+rqj3q#b;MZUanM*KzC;rx8~ijIq~h`VUN^ethG^YYpDa?ZjbaTL9d@I}6j zj)^Y`yM!-#zJ7)g4G5qQ1l5wVbN@bQq^k~%5hPsshRGd%m82k>j zAaR$X%D9zNFVlJIP;21YR)bbl%e6J#x4}wS%IF7O+P||qrvmM$oEaqLL%9zh*VC%W zR#ns6xn>IADXy2k&g2hRLfxyu8?LF~ON1FT(VlI&mN!}@K1W552CF1DoCIHDHE@S+ z9hqlBUr)F}VCFC@oIJqtr!b4{B)O)STCDK$T+2Vrb?_wj)2C-!!N!qz%*kEKF6Ghh)0_f+|(>qA7T|0xCcKWwSTZ{A|Q&`Xc z8l2JpE)EVy;dcJM;2NAJsacZD<%tjC|3nroHUf_HI5ik}J37x>QuHlN&7+oO9=(Xh z(w~UGdukN@9P#+0C)QaVeI~oVf|dq{X{K+f=h1k&nTJ1Gf05%@f6SRx)%bBp>|vJ0J_-sLdHTep8|o5jv8 zH2>D|tsWql`I5hfCf$57!(^+}{ANoMMsl zv#s`x-4?kr&vBXXd3t4&cMk3xX{Ww-f7zyY5oXUsnL`$x zPDY=3$YFXj``|Ze>i7NR#xl9rmd78b&O*86NAUjh!M7l_9U<<&i>s5CruRr4J$P%u zm~QAK71U@Z;4%sB`;%OU%jJU)>uy!tvsZDi-Hur_m2eW_NEtKDYNrpdI_C6NFyBVF z66d}>#dS5!wKF}qla;7vBY0BT%+jsis{4^g>p|_#qhztTUk}k2ILJ&S1yIMHb>KDOTxc)bQGr|{L`}J5j;9-H* z!UG)_7ja$-7$S@bgFC_!;g0r;x719>TjIS+9}|A0*cNUHWAs{DyPxymbv+!b;`f%$ z=BF2(aHg35t9%>rm@xUW-~j$tY=^{Yz?ua8-(vjzlFS2&(E~dQ<_KqEhjQ>$Jinubm?;+_Q=Q&Go#X*BRZkrzM?gO`VGmlF@I}}ojPWo>nE@RW zx5+1`ox7CztG5nXf_bbV{^!AQ)T8o0l3wPU_JkEMU#*Cq|5}UFq<5{NFU(pp$BUh2 zCae)232TxES6Xm8Uf&}Ac3Y>@SDYG{>AlDvf|1kFjHuPD{OCL$^l-}<>;z>xNrH&HKi!h&y|G~YdD27GkE!XG?o!B>x1{2sgv?DPhl)c<^GxV^o7F?>|EAzw*$k=S+hqC5u_e zJC`!YCPqFcM9-!4scF{bm3^k3WnHL)kvAi(5pH;khZpL5CXN#OXp_^;^jM3R3-IbU zz4JSRKV80l!8(x*&_114`|UdxrN?dQ+s7<@cey2RF17?q_S~-4ra#(x7c`b3)UM5Y z>=$zmZu_@Ax32w<>+iq)&u@JFvmd|qt*`$0)O&CK-L4N_{rjz-zV+YMe)QIV-T3*t z|JQ+UefsAozw^~Ux%Pu^ee3cce)DU0fB4;(-~Njq-TD3h@;8Tm^!NX5>)-wJKh61< zfBUx)|NUn_?a1{t|JS|7{_gqqe+=2Q@TcN1$|1{35f4$$S!?NH!WwNm?0CRUq>Z^_ zs>S3v;y8LNo+2Gi&rxlryccB$)IT5qmnfmnODWfw5_*4>(yunYiW&!&2p)9tolXmjQPwxyA}_ z+Myk_m;cT0(-z($FF`t3el7i5(8emjn{qUua_-%AEKLnbG2V6n&n7ep{ijEzWtC8? zPrl8^tb|}Q?~R^s;gxvz%xMcQ9&g1nsr{Stgu|I2{YQ()B;_CGzV$dWtCw=WNNzzK zL)ZN@{*d&lMrsIk-PgKq?ns9t;u^vL?HBgwm~cn?8d$`8s^BN`S;SZ5?Z@GA9@i1( zh@WU_)yJ5zEiZ=G=!%Zi!0*<$bdohJooICnM_Y#_)fC#G2OQ z8!U2cHaIiU@)pyZX$<+Fk=&;!hen29+HizCX4%mx*6u9%i^~g{GfrOQ63;n}26=3} zRo>rjO`o2zhR;q|S2AYZn5Wt0vs2a;j1e{nH-ryWAMZEcv)pIBy392HS-Ak!)p&ZE zyc!RiG@Db;Z316=+ z9P*6XSG1hoYUJgE)NX}$F1H9v2|8-^F>;xQHdvq2du-<2%eL+Q%Xa-+pa1;zAAawr zpZ@UsKlzLQ=l}j&u;b5u_OqXT=chmY>4!i2#V=m|n}7Vtt=oV6y=TvV@Aob|`3K+F zbp8*%G3w?Iznl6U#^zNz} z%J0CvencFqIs&e6-9#4)Py?bR%5^TyJ-TqGxSniWsh{^we^1pP@V(0zRBLT|lvxfL z<^t}+3m>B&BCqX(zZ6X5I)mrqpNrnloS331Lmke9H`2#<2VOsOGQ)7SGW;NMiZq^( zuK&`&bWL|0<^hHX2b^BU+S~7O4`Ge=dDtWV;W!Jgmx8khZ=&dek-p5n0#_^Wwd&{* z*^SxR_1yP2(hsuh;bqoza;0^>u+F+%T4$ZEa9z5(-Yq?^ZebQ#i*=?hz1!;P)|Ky@ ze%AtcY!N*k{9sA&G59Rmx+qu@24^DRPMmym0xXUVLPukETuge}aB|t?p;O~};n}EH zKUf2@VG&bRqkDNhaGkRS=d?ENx(Q0b`j;(RMI>l)`&*qEk z!fo^1+?yU?&!D$%+mP39F>f9YbdT&B>*iPBM6X`41fE6g!Ww#%Ew|Lgl~!_@nwt~c z51(7fHJ9G}=$!fUhgp1lZ~E_$N1Ooe;eRKn8%cmUzGWlu36@y1gt5q@Q^jTI9qWaIlN>Yx1an$si+>B_4Bmsny{VcDRqH^YJn34nNW2 zumcSF;$!XW!7(je>4{nO@h)rk@d3B3^P0cv%|pMT%_|M@32;E&(3A%F6| zb^kvww-?Pzw^10PsILT+3*$OL{GM8-=+-i^csA1B~wAf|(e&5+|$&=`X z2V2lW*SIBmsKr9NS6T=Ri5+gS=mD-hN7hwNRAoo8;pWOJvZx?%b^X^~%*}6abhrd7ZU;pVJC;j+;{BxPN|F?C0>XSFJ zUii-ER|YJY{EHAh%EIUZ!WEB;Xj_<~IvVjC)zt_~v|pSh{&;uh~-5W5OKjld~*&f|`b7 z3oW&G85$2h0GLw9EUi5JhD^9b27Y`#btux!B6vxGSUI($^4v?fZi|-) zBfhu@JG6M*#_^U1JjTNn>0BPS5#Q0a_6e7&(8$`+542S%Qh$T*z?0+;ZmhK)H@8_&EzI)lakj;}@jpw?V9wf@uIBHL zKZO^QoJ1cJ=8y)_%OdcX2>6m1Qf~>ab0uWNOUOOPc`V#XfHkF)si}u63TNW*Q!U~% z$`mL!;4la*O5=|u@ycS#62O;&1L&EDKbAkN*|KI0=QA*jHM8oO6XfT zyR059t%6kc1&%p z!&GledL3lcg{>4_sB|X3k9t#5FO{NRDlu;WT!mhF*YQ6-z3H%~VArhH9%U;=S&o*a zBf%QD6WUoJ9!v(F)mJL{ywa<)?+@N{coYBbGgkbBntdVnyG81e$UM4Em-o_7^?+NdFKxH* z)>#%rlPQJ+hc=Ltr`JY$$6^apUmV)D)Ph@=a1EPp0dn~I*}j%p*8SR%e>?rnPkJ8v zy-z|NZh%Jz)>*r2NBFLuv}51=?7#ozPyXQ{4*j;^&Dl@h?6CO7OFs%v9Po=a9ZIYX znX*FshGMu%F}x&9f64&*m-?1zJ5GPBIJlAmODgBlgO;BAF)*fj$rx*1&wTe4)G1JZ zpWuH}LOseHGRHVVqI#TM<0djRN%u%OH;1dhtE_* zPPe$B#Br5^I_h{>JU-)Ne*(=$-b@YGx~w$0wGK&Ze|niUUW7BBUux~?(c9_lW@~$5 zizT+fsaH&~Ts(|6O>NP~J6Rr@THW;aSnMW(yz4C zOdV?SLaNZ*oSp^t2xmNu(OS!|VvmO}_4qmsD|pThc*>bI=J*JhQhJ^`i=)%6^4d~| z9bGQ3v#w`XxuxADYEZ5$wzk*l>%v;+g||FmKI%{l(b|KW$F`UM*%4~(d7W<5j5KjA zE?qO+B9Av(USkP<3mG=*7USSa7@P@^lZb&a%7cgdP(wuKHZ};3!@lUFXinf!Y9!p| z3Aim8i!^$YxK0e;M);GOK-QX!TC1l6Hy$qC4c!usqhrYhBP`j1XF&~UaM2TJlS8bK z`xf0&CTSEt`AHyq4)!KuuLK*9gte36MF^4A8Qdne{@Shyr@2=8)q~ zuANFg4F7|9%z<6x0m!lytmB$N&z3mYA}*7pE-^~IVr(S&cGX!e8f^La^J%Wf74M(5 zB>Gn|9)JFh8TirsE)&t|n7NsW2AhL!CJpTo^7)UD$;`snN&en->j$@~`~E#Ee(8Ya z99eAsH;+19E%d>8^SyM);-6iyBsHQXJ6mfxU7Zbm(c=5i{NOploie-~@fl^EJ$|EH zKpXYU;N0Z()y%A;F6Z=o3!mg(ea9r;8`{y%iPr9cZzF#5t9n}VD~GMeXYd%X1^|B20OtCg8U7nGc%L6sKoi*s^*s%cGh6 z9!qv#X6!sly#%;ZL_hT4*3p)_)ndcH`I620t8b&1ea|Ys|0-B>!#e!MhgSOG(^hhv zSriAE7X+u#I%g#FaOUy9W!`uO{HtCjJ^zotz!|3hlcMEY|qqEBrLwb5Kl*U?*J4c7qvXVSqE%%2T$ZSYUy-hK{#A?GK+ z`!HNZSR#xGz-a>T7GX{r-&N1ib}|1);fv1I@gO={n4gtJO`tMo!Wmr$GU*ZcNx2Ib16qlwcL^S*rOV8W834$3Ig&!+=?pkUkht^p2@y%9pc&$a&&9pXn0&VIvZ!OGySvNk* zefT|x)AJAR&NWo^_tMJb&jdg-PWdeI>gZB!`Mg!0;9B-Pv(;WaYEk<2 zhfZ_5k+C)Uz{+pBI0IjMuHbmU>R-?r=J69RJ^0uL&;nU=- z9q;falblJ$5O^+{VFvFfgN#JRV`SAP(C6jVL-y$R?_0MYyzM+2VNTI=`z-&)R?EFe zHt`wsJ^Y+Fa{$VZuCUlCa%Q+mSP`dBV`<$P*P^YQzYclK|Gho42adzx$Go2#tjCxl_xzFIw~I+yC^Nj5E^4j=cBss~y(N_*n+M zPQ+c>aP5tPCGtt)>$o;?y_Z*#SWljxzg1hj_Y_)#_6t9v%g2xfrN)|m=F+#a@GG<} zEQ#>h7Dl+^!V0iQo{RT9y}me&pG=uvPm8!qjGyOz2Cq{%hU+0eCjdtIXHjcS&-zUI zWEOD`s#(g?PYTK1=9O`6hsP9gdav!#lI)r00z@mB94ChJX3(1F9J!EU`$^ci(Qp;Sp=Bar8tb$0+%ouH=Xd6B(VZS}4O|0yRdSzB9)TK=TS@6%DDF} zW4?67mQgl{+Kdz#*a*BN3}(d8$C}A)blEt?s?ceKH;FObEZB?M3i_W3Tf||K)Ol!I z94ASQt8hn}ns+P(N75qhqy1W!@>=Q9XrKSwzNmno2k2HuG4w1W>1eDSmm zdF`C_eC4Q(c>9t~x_{G}o@NH{Woq}~Zl!0?$EXp>p3F=y^e%tPc*{e_E2OtUWa%*S zQuJ8H_Ych#mmW;!d64CfBx5xK?@7Jy>35eiiaN6ui^r`{7GH3M1mo9Y}Q-Gf@jw3BCpA2*7PoK6SfAoRlH>vO5 zvEcnPmj3QtX15%)ysPMcZ=JB{duQQG@Dcp_DD}O{CdZD^uLeD>0-h?Yas3A9A)xKl znU$7*V6kO^mzt9nxXmn~%bU%I{}#Tn)4I@mvx$sz>0z#caGM~R^0cT?P{<-Rj)32kYrVqA`tEX8BT1o=X zC^3+pOC7-(xQj5xtA`Pv(PQPy!ab=0!lP-;1yq6wXgXxfx-S}QvGt>`?OtwWTe-e$o@;$}phF#9Oiy3x__m-So|S~SETeCZd>7TxcpgsE z;z`zR(_HI}UtMwreMejcOetE(?A)pJ!JMeNy*l#V>c^ABD*{jY(UZE49yN{RJZnR6 zu0raQO6apAT?#E|7&*Fufui+mgPAu74J#=3oS%jM9@-Z|BZGwZ2iR|buH z)@*7tGx_~9;A>g4AH^R+m)i;VA={QsMl1|2O#0q^d+diFSkE8acm7R}AG~9s56)Qu zcu@Sp0Smu<%6#XR(O-#rn@tEx1Xz`sQtvVTg z%p)~H=AhH>V^Edluw?Xx=L{yJN-vqhX$|lQ@Mb1?qa|?674*JcO(tXeAl7j4CE)W) z{)VS{U-)umzyG4u{Mmggee1d<_cK>w|1Rg*I8H+@Kv*Np3AeyqcCWJpT7-O>)cGCY z%4QyOpN2nQ`P>=u^jF+Eaguoicq+xrI12EcD=4iZbQ$Z8DUGq(RB_Nlp#)T!oPZe zFTw?B;kx!q!;+Sk%lBGbBn01+u2#f%UKpd}4u3dTT3Z&i6`_TXTgmRZ4|vZ6>JVlz zM+&bE%n-H+yIgh|ToG>(t^|0FZvlNlHjr&b4++9Qefa(16KgGw*P9K$)NJJp=6hz5 zZ!Tl@T9?)2p=S-V@`X=W2kQPR@oj?i2#J#IO7pu&Cv#rE)5YL3@E6tfi_56aKd&n6 zd>Y}6!y~XK33hhdHs9*`?w9EI-nqoek8iN(2J}JU44K)~3OL?c^jUHy>3!5_@Er`J zF@@2S)2HWHXL3mO_!?cFq^A?Leu<`bR{Ll-YuA@v&TW}VR$F0Z)fHCLvCc}+kdqaq z)|O)dYERoF$Tr|RNmEn)xfbuH6zq)9kKRvz&*DY>+~T9>XM}zN{uRpMbs*E!p8Lxx z@(A1u4sK@!;%Cj8H%g6dSF}N{hrXWl5^BPW0#`b(8f}&H(bm`&wxr=U<+JMsT@$>+i(${%6 zDXxD_tI!Vd&#G@N#mAUtUGFf%?&&Sogx*<$7APFhx{>#(r8AgQtN+iQ3G^p}XKv=2 zjL(wVNRDVe+ zB#+~Dy|~|H1Iq57dYC;^Can;ED?si*xROEkL6}p>=OV=KuXWz4C+K@mF6RDu8}Y{< zS#Poey?*en!<$Zj_`0jRDMnKZzkkkr7nU=Z5B-@LeA3X8m&whYTH?GKhc&9j0dLg% zv*fAGR?g?phrU^~ncT<=N36@;*4{M9Yg~8nZIU;b8~W5HYftX2@s0D=_z^R1KDq4{ zAAiqBO6fH?m3s%gy1*uKb<6r#;KB^+_xVM)bp7NcIXUp}YVOL$EEp5za&p(1&OL z2(H2ZlfCy2uJgXnJ$E7ry`5fwgM&_h0Eluxu=gT~O(Z4u-h1!8_uj=`MTsIsb=k7I zWXX~xS+cCSq-=^eb8mL`CfQ`N+2rQ>yPxL=zO?K~<|ebr+&JSu-Z=#aAb0@0&-;|` z^BrWtedLc%tg$@K@rie@TH?DmtmKVrRzcQFxq!lL8!d10c&j*d%xP#@!}0Jptb$k2 zNxFS0UxPU*@&Wlv$%M{F2b;z9G`@Y}><-5(a@l#L%s^z%3NV0d+-`b@(8+UW40U?i zLxWq%^ zviD40x^9aOPjUONN@v2e;WDN4GM81;U6Y7gqAY1OjkT7nq?4vNZWXodtgNQes+;Pp zvLhH>&)yxpB_I84MRdkA(G8|u^To&TiMBqDZ$Hs#Wu2~WbeS>vFzF-cRp8tgM58Js zyWz*T3Ub6cRau}HJwTnA0qVtlu%@63{13eG_pG#Xw6TOb-QYFCmeQ&8(lEEzVewF_ z=a8lr#lso&+&&xnvicdjYR;A7HC^yWlM~1af-5obLl_~P ziS%jjIE-*anKWr>!WMCyVjc@)ggb2-8yyXkdRr6MAStdr%B69UZ`0RM*1Vv#%&Jz8 zupUoswvvl8EO~CKb-x9dxwh^;&Xm!CU&S6ehcQcsx8V)krj|LT#QISVX9`!K?=Bfi zHgCKo*03L92iICFN052s=eBexdK!A*OnSP9H#%M;z0A|iggw&H^z{q68z6_d%QWVTbQ^+yBk{@v3phmRMX zS!H8>@}Bki$y+8)qb#%zWuY^Vld*gCkOj#H`nICGY)03`x2Yxj)^Khk*Ebuj^Lge- zFRcWBxPAslqDR;Xjn3x07cv2z4Q{*W0cfzdF$Oh(E(a)Nq_CQV09S=5v zKlNdI2>eMKz{k24!o8Vu>BAhsDEfUyw|97xGb3eL6VWQbo!ptsR?K6^)dH@=)^JWa zM9;$saz;nklL`(>Kg&I_&XONJ?R2#AkMCHoXRkXRBb?D8P7_=_pM4Hft<%|)cqps6 zHe??JJ13&M@kGd?DSsxs$zaAR{c-j`OdrW>(9af6bXX+JNS@neg~!009SbcR{X}!R z$`9mDe53^1_~b-U}HtaslB@70(=ZIHP|nykn{D{P-Qsf?vFe$RUx9|K&GR;5GOA{=pe!hEFT zEO;+^UYte#yts_8#Rt|nj~@IHMv0>cWAt@|UnRWfetr%Gc#pc@3Qw&&!VY+_Jhp|8 zttN*~Cbi@`+4c+YSLXW@PwjR`;br_!{$|uI6F$1qVNHO~)8U?j>m;8$WS#Ef@m}3! z74V*BGHxYY7bK?-!lPyX)_^9fq5H9g98x>3ft4kbhNgMUygIbB&iF9kVKs9SmGH1Q zer=NPw}PBfoZMIdKP3jHh{p(LinenNvWfqCdIU`iP8BFc4gy93j$ zY#(|C8GtDL@!|GmmH#q!VeF?C5rKSyd1K8e(%t8Mf=8?k3CcYa5BbBY?Kb`I9;PLxKN~Bv4tB; z+c->X(s?uDGr_*}hTzTUegXJX1aGNFE2@~yj5k`DI8HgeZPkm&o=@pzl_zG|;Fk{D z&{vMqmyExSHWC86^YOfbXG1w498!H_{o(xXnVTgE)G%@)w zVR((6FD8ekT!6GQVUWjj%9&*m&Qy_YbI-wr^f~!-LKlFa$y4;k>_H>Dxx(R0x0@TS z6S?zRct{mFh6?($@AH{^SX0Awa48(L0-ax6Mp#n1eWK$yN&NM)om_8$Il>+tarR$E zM}UcRduc{qM}iLH(y84YU#db&^!GxGg-14SpKSeKJ#X#bzhE^VoVOs|GEO_=?<0HN zI5OBP=^CEsvd-$JQ8qvvCmXIM{E1yzYq?;Jf72v;;_El8FFKlsGrA4EdCIa*udsYN z34#~M)$g6;ycKoFh?k^pYOo||vk=gI3VAd}e#j?|+jgkNKZMzrwGHy?)*bUwIO3 z@T$uOqz&i`k6CT)P9L}2ao`hLTJivSi^*KKPKOsRn~X*VelkZBST_f3nMRio9^Q0* zCJWgI#GH+Ij`)sns1V%fh=)>p>x6~3FTg(2r`e6GYg%Q zuOSRk79k5CCXDVLJFt>I^DXR{CnNd90Oq*Jw1G#`?kb->36^fQ{hz-72fwK}qwl+Z z<&^&}eM>r7ViP%XdHFo{gDJuv`7J(tdJlVqCE_c>o;H7;Y|13`YrGt3VR}v&qt_H~ zm}0Gm*t-k16p~X(&cdjUR)fY@cV*{Yx!I)--xhGjkg(dS<;lV&|Eu z0%yc!BJi8A!<*&sn>MZ^?1{sDI=;y7HM<<^Zyk02Uh&jNt&pE}8Twiw-8JoJK4J}U z8evTh`I{tjg~6V567*nC4A&u*@S?`$ldKvoPP$v=qETpJ{CzDNYX#&VHQ!&s|Dkv{ zzh}(J1j!&5@m$e-I2+tSJR-bN9uE1|r9-S9J);J!@q=mVI}@fv3S*APh`$J5;>Cql zR90+N^)*%rk14Jwv3A|)Q)Y%WNCqgf3j8ATmB$RW^swBic&$Cl(cOnQtdZxhSr=hU z`6)DcvO|^Rq$}v)iLn6S#g96CX<9NI4UL(}sXgKHo57f4*7Jp(me!Zv)JAkTa(dc16OeWWM=Tjl zCV3dyFfc;d0O3qI{)P`Mh~mp6;4U$^OCh~r;w8$R30uOw(45fL#9=(2M)!q7n!Rz@ z1pm?N_4&dpWeKFa`MS^xK9K9B`Se-e!x_hEF0DpG#U~>Z7GRHd#oWFQYntF&I;s!C zw>FP;xKg@fk_lU+qlwEDuN&nai`z(7ORVMRK8alQICNO>MZ3ZZmoSsJY=~8o(Gp)0 zr&0FV2iC+!Hd$A6`%d3EYi08D$pF#YOHNIA;^sKf7KAm*K4&i* zZtZXFHy=7%&f*c)`2H2gYlJbLjur;LGU-^$z07WxW8`M(kBOaRHe)+Jjj#r+P-a<& zFvYvo^WNcMif+C8!W<8un$Xvp-o9c@@7-`%)BNT|{1p8lNU>JQ<6n-SIjGphv@v_;}7#`eWDO4=(3#V^trp zfsgHl4>IQ!e*UmUUO8p4Z=JRBFP^u+({%cfN$YX*iksie7(~}0I1`vZ+wmLa1pdt_JcWV-27(aowN5n zq7pI+hkx+lr@zTKv->;GUC%)$)}fr3@FjORy()Mb_pwDBMgBbeMLZ`0rg-;V7L9CK zlG&G%UF>N;Ku_)-GEeMgOp+T<(4|}=o^pC4d(YvX%jg$eL$CK?v`)P7I6PN}uqLzv z-E8k-a{l-*!lSF`qhO9Ortr#ki?SP77!y2z&%URP(`ZkohcnGDp0!dkt3j?QLWBAL zkU5JE@5bJgarB09UIA}v<_)zva3nd6{}Znf?`gzesaS~5kG9vkYq9m*w!~VBQFJaDvu8zcvepZgRTfQ7E5uGSdPRANN zro5)gO7LLfB}Mo#6&3+^q?LIXQ(0GSNjm)lbRLK4R}Ufz&F*Pk`J3u~Y87+F>#Q2hrIeg>Wmo?8do^2RgiS@{4qSc!?9po-?x3^fgEe{RGlk5V3u8JzgOt)!KS^=~^>mPx&LE$R zXCu6E`7^Ews@Nyl<2-Y)?_aZWW??kTnS5zK9h>Z6=GrU=t`eYEGZ#-Qf73*6$B?D$ zK~{k4+L>Hikf%u9KI%Hsve4ubZ=7~nG+~XWqgDLy4xY_k%c0jGXA`;F^JE{uiNFr7 zw=XdBbq`bYT-CL;4r{#UbgSpR#~#*r&*`>N9OvZ|=w>&p{=I8XKP$bpi7Yt!6~17} z6=pl{^0)ll5=(rGj0~J6aDJ*qo`M&AKtI9f>L5F1WuG0f4cu7&9fh;LeNStIaH(9ePk z=2~FEZ2rdZSC_#t=YSsz&^W;ydHMnL3}KL;xyqb-*di?}$T=dL?m}s6zBMzgjEr>6 z?b94&Cr)j#oY^DDjat`?euC>oHYr{N_x&g#lbSphh&ozNr z;xnb!4>~ORP0ay#*m&uaw+jlHUCp4&T{ACE1LHOyF5~zLI+=KlaK_Wrq@9)QoaJ(9 z$`E*m%d7GJCBd5H$u(BYds>7}oMeWf_~KSe^7Ae{wcd5>M)oand?vwbbco9ccVb8B zf!MhKt(o6hxQev1=$STuM%*Tb?kVpkjAo{N0MghrN25cS6F!87FmI$qMv@O2(#2v= z^s>~7sa6GN5nt&*MxY9hr~~{(d4VcA)yn3vZw0@n>(MpVW!F**v!kVut_kP)^Ltjf znXcaj?0v^CtRYuj4Cj-VQv_d0GRt1V^}CMB(d-pq_lo9m3W_5ZFHJa&Oq!VUV89n) zP8GPK=Y%uT(W*MsSQ$N>IZvPuOz-BhV-fg~Zz0~8Foq+-OpAZ%K+7gen@<-@{bPNs z_h`Hm^t%|kTqQh4_>yFXM;u0+rU;BF0&j{sR9Hz%O`DFEs>Cm;ah{C4nNa`s4qKEf zlh+?3pR11-ll>LWC>IcVyrT_z;h+g)>hG+@`)snj-c|TUWWeD_ftFHs5x`~O7{ZzM zXoYo)hjHGe1A9h)hc)tSHS%0sUk%R(yH&OE9-fyzCX6ZL z{VjwO6}mnf@Cgjkp|2C;>q-L*E$Y{%n~^u`_S7aztVYWn!2h>57)!UXbTna2EjjIq z{nH(95w4W)ooeO#*ki+e@t2yzbFK0a*G^!NxQ#p-$7|N`yM<2^M_-iIrqAhoXeoWK z%q0zLv?QIy`u8$w!_KQIo!!U!-aTQDeD67Tbo%gy6+OG%?H14sXBN4aFn&z|I-3sX z*TA_mWe<5?vtI21qV~&N_|w~^{Em!PbZEnb8|PP_ybY)wMvVtyK~0ji7+Oz2b~RW({ks$!x?=IVbG~BKRN21vwu@> z`yO2LcMmZy5`eEnnNt#HDL@yK_oBH<;YtSQ)XYax%*T*t>dky1dRmnd7>-kXW0%#xaLS6V@3g@FMSOe_vj~s5oPd83 zy94Nz&Y{07uUmUM54rxN7bi}SUJ^~Md>;9#g-_r);O*k!R4jhNS`RF>-e>8TT7nPz z1lK3%wd#|Jts{p+&Mdxqs(`coRdwvUf!BaJI!fp#&}}ieQ`XAA0R{!Y zz(8*@0AP%-2j^b2GGUE$vyusIS!Qt>aUA!tN9wHZ!hDA@!kH+20cqXK*@qg!ngR$8@(8+1)1QoLbNeYB(1sC-=4*G$7^AqL0Bpo?uP~oy_Y$llJ9uWpEey zG}6!2Qgqk68C-Hao28{`4j?fLy=c%Om@G zks-vt7tYi%N0TDst6Z~iM0inqm^>kzrf}5=yu=9(XT)dpoNkpB@GvL3h}kIe2W9v> z4eX+cFnc5aU;jpAaGmAiU8Pmgi`SX!310K?hqv7fXUFeew{9Qav@$XR+Le|=wyc0I z&%j=KNVYS(j%Fs^ES;UDY4jc``|Pmh4q2(^_gDsV%s%>^zv!!rQ`gcb5-q@9VQc=v@d-}GoaeDSbHI-7@4&Cl$y)SH*Aj!Zx!nXVMRX#C6^ z=76fvEBjfB{DGfqqx^knuJ7WJzr5Uv;5X4%S6J|a^$u&qYZB;af$yPhe7N4iA8oeg zYipPrA#*pkljAhP8R1L8Vm!$;C-z=E z{xw7KwaCAcx%ZR3^O32@Lxa!f`qsxeB6Rz(6`}u?(s7qJk(~KRb~v3n>Ud3HKA5S8D!7{Q;WujPG9tubbyENuEvV6?L95i+h7z*63!^ z;*@bqoZe=qzxrhUZz{fc-}kDQu6-F zH|x8M9+H7{9(QZC>LGaiqsct?Wk$SbBias`W-@)*v&h<#;R}%Q3zDsH$5wh;(8h#4 z($RuE*2n!D$fmD^vo6CUh3h0PZg=`v0rRxQ*LT51`MqZUN97)}!n@{L<5LI7`5)kS zYa-hAqqIdCs4WRAh zfJu1+xkhHb-;ZY(;aaAc>zJ|)Gp!On9VJr`=~88JaJFO!JcdJfQ^DQ~KaNj4(!70OifyhHgg@R!Cxc+zNR6?7K2@7v;Vrkbo;oLoRfcQB_v zdLFu2Y?wOzl>>m&^sA}P=I2xnZb8GI7oksqVmC|PM`pq+;UkJ9tPn^yM2bcf4GHxu3z?q;6! zaen5S-^ai9_o>3mZ?vvxR;hjLtbxY}Ka!irS@q#LPA@Co$eb{KjBdqmyc~e?XO7o^ zO+~9YmnfeG9*O4^FmIE`%ug*D8iV!CC`!NYoar6pcp1JXq+RsIEyY7#!L=Cqw*vB)Im?+7C5z)j*UedphkS63<)MH0=zdTREf+1N^pjgw z^7Ls-e-wRl)l&Y}cf+ahV9?FnY|YBWXw_u$ zOYvg3-US2H$tm3|yaNtNR?Owp9z(m|if4f5(g0?ZUE7b|J=|r|vUIIV#;kDvV*Z_J z4p)RNg|~iUvDVhIK^=k@fY!!2RTnaz%BsI z*C=1s`S9xhG2-av|9#e#Bkw%(`FEfDyTALp!~gZq|NQWO`^&#P{1<=ww-?^~KmPEI z{ojA*tEKP0^rJa%-2U<8*Ps5g;m=?At6{HQ`@1=B-u>^bPapY38P@}vlZ_r&X5uma zb$I1qjc+a2anlAfpGC(5{gY{2m*=1(#riXs)t~d>2y%>Mn4)B$YRUe$Y@TKbdRB6l z&~*mBWTSm4=d3Q83_2sSwA+SEa%@BoD*$u+>|##Pi55dkbG{Axl7%nQ&no%cIDf;r zaFN_TbhqL22j)`Qe_NcWcQ9vx8Xp5=Fa;^{lbPfDTqgM^_=( zlbsA$w5-VCNH`vG_@WFzxG-wfa29E1(#gbcgfHSU!X(}5aasFHtL=&x0%s`&cd9!# zSvzqS4q=O4Q%^Rnp);=mv-EkXZk?>QBeNV;XmjwDa^AaAIE{3&4v(^Hpihfc@SX~D z#BYkYUWg5AZqv%>win(Mq>8~v@DUDEJP=Kb^P>;EDW-?y;hQ^c=u1cNW{%)(GE1}h zaqC1Ty&V~{VzjJaM=}Sz4|S9A*x@q58Xe*^I$GzCKsTH0GS2d9ltXJrPP$_D!_3ik zb~>2L1)z_Kk7&+DzKiff8D{6#+{Y8j**?`O$(jjcI3jYowRC zTRvWSa3)-cYbkhJKDodGGRom`oO8*CXwD`)m^qLRt~Sge54B>X>wWI<+!3pL`=Vu#vB*BZ_E)gR^K67aVP-@% zFYhN45Ia5RK9-21c)UgX!b5u|-sd#l^Sb?~ac8I1y>Q5q%mg)Qw&rE_z|g~)yO>-r z7_Ql|Y`Tj42f*n!);SF=c4v{}Hu3Lnu`=>!&0k(NVNLrl*dOyHS~s4JxJ~*FdTn4Ro&Jw~$Bc_Oo~C!d}m{GnlvozXT1N1f)TuhrwZ%T7xRY?x=mUwsB> z`OVBU|N8g+@TJ}Vn2%QWKn>kyN%Dp*KDRd2!8-TpZhao@Zw;+YXlHG_sf1b2a8<&h^n_NB1#tQqJ)+74)IZ$W z+V^X9IkcMooWJpvB3yH8_A(C6lyX}Hmno>j)8{A#WBm9S;c>0joB53)aG61O4_I{h zAh5X6n%A)xhdI$2-v7oa10258PU>T+$#gKVqos*#VrtSrYes`@oYJ42({$>&-d4ir#u^{wGD6Uu?dos zuHQbfw zW|5b=z0aCoJxkvUy9W*}w3e@5b9f`a#`A0(*1UP#vNqCZvSqX-ud+Yjo=)arh`3F` zYI;-2LM!X+eca@9XD+&BiG zVW$As*=0BAWP`8Bo6)T>Mi~RmX=;anj^Ff5^Ea{L)cdb}FOzQ9hv;5<^uXHx>-f8` zO#kM`|5w~U`s$4nLC%E_(oK;?9yhl~h53ijb0SZHb5odJ!VvpB!XvulHQ*_9=lluI z#KH@0bf9nmqXZiEkT?w9vcT*2H5S!U^6oqKn4 zxFIYNR*07fH^guBap`8_COY(-Fvfe_zNy|C;V*h!8T|nrz!%|+zJ|Dx{w?JV68F6R z1U&+k-5VUnDC1nlPPuji;Rb!tnDAptA0<gwuLOh$lNQRa+N)5wW~A&nEkl!?qgvj0IxGhDL6_&)AdkDJIY z3VRx-J#3xGVF+7vv|-I8>%t6lYQbaHf!tO*G{U5E1mKPMN^)dp*Ao!vN-o@CPaBu< z^30y*CVxh+5Ar(kp<28N@fi=j|?~5Mf#cY%)%OR7wKZ2ey01vnCPNG4s#m77-5Z`k1a+g1|QVN8Kdha2p=PT|d0RKFM=VL(2rC3-Amx@AcE9@%hT0wdK#A;G8<# z;ZO4E?N)Mo7v0qOp!7I<_##g8O{X5DzzmBielyJBjbejv9ST z&wcawCg%Lo%i-(5Wg>4Jw(xBpLuPbH7Di zWaru+y<-Evc$?fYb4Lp}=aU5x-jtm@>To8w6rG!bQZ?$C2N|<}eU(DA8SITc5aoSg4JwDdJE_|(JR(b1$%c502bBsN4 zdmXkYXXfRa)oZ4G0h*uD=QZ3uW9Pp9yzqa;`S;)B-~93?zuR=;nQQ;|`+xAe6aPKF z{=fEXo_XVTL({Uyf05m_%<}OK($PDFGdUcYXgq%MNb%mB^ZPIt$PsK|Ua&phJNJwF zlMn8U=g^e{%!v#pS2z$%;x?BVM&XUJ0L64KhIY{_zvGdyVc_*5TdU<29P+l&=$vh26j7ydE${*i}R(ps21K9#iYG zW%6k%z?x!aa3jq8N4w$+fgvSm8&TfR1lUprUP~v7(*;lj?j#2{(AUM>8`u5ibc%G| zGt2s4rRV${`HCK;t`n_!Aw6NM>5ksOd=a{Yvb^PF)O56?vp7Y!pfD&!_d)Xv4zAA~ zw;^xQOlL$Vbjq%D(sZRysPjtp=PYA?DCfR$ly8n7rW3Z<0mRYir;{3G`fXnS!x+e_%uy zPbG@C65=+1Clw~E>>Ce9VNU2lW@i2L;7L2{{n0J!49@iX=(anGz>Z9?+dqA%Wid;W z25;2dX4?3kmPU?GnKbRON#kq9F0Zk=+jPk;#KYM@m-df-$!k3C#_^hWPFmI;dYjI2 zoqbDPGuxd<*a+mTx zlP!)i$5XKEQ7hOq%wl)Ym6)e#_s$M$_cpT$&o8sYC%Y~6!>dj^6TXPk=&|SBm6}^Owoxgj@O9W6rI}Yutr!S zT#+_b{?rlY?JG+r|6hG-`k1gq{6)P3!WbQgKL76T{%g;jzkU6`Ok+I%*4>g0bBF$q z3}!ScRy}3`vbGPD6riDnEvplK^PD?#;TC@WUW2J}xCQ$F$h!$=!kxL!hu4VHl+byT zz>84^pr98$F6@R5vePq)Z&Oa*EO~gg<&R*$VGpud`dvA;&E?Co*ngbK9<;ogI9~@% ziEfoFdc4%JnN1gER#lKbe{io|)H2{QITc|GCSz9GuC1r6wxz+EdeVCZ=7@`k!$<>b zCNm+75w_GecW8SajBy|5R@_85Bkb_-Mz7V^kq^`3;Xdx)P00z4^s6n}>M;xNLRD7mvF?{6LRjCuXY%8hNcj$83j z@GdIwVsgn7Jy_+lilt-?7LzG`oGi#-c2Nytj_1)T^FPLpvnSXo+K)T{-S4qc&FmBG zZ?$OSDd7^`3eDh*yqlI8gV@W-xg8&(D_#CNy5LK6#PjaV&KK`F-BzNF#vfrmX#n4^ zFa%B`?xJ1*c{b_`(EN>j8O`FT*IBw*`I5ob{pKc@H*0-b-H2n+I+!h<0q( z(^zJVrggCno5xz0qbsZvNB!Xi?Biv|&~cZE&a+V#&CO}*mRx|#ooz;6BOl=92Bevl z?w$&V5f1@p@RSOfyA0t!#mI6CXY$Eo2d6PpG@qOlJ2=z(q8oH$#_7rihc(IusN>o5 zY!c7yAqxvut-x>O>tyjcZnj4GGdNP-y0Q4)lif^b!M4djVw8qPa;L+zCH;L?A#{Yk;X}^u`YZgYnzA!~Tzi!20 zghRS7olMVb*QU6TKCeBz>Bi4~Snyli_?O|vzvg{<=A-Xqc3(CAA0Dcq*OF`PAU<_A zxhG-HgLH`Net-;a2ECWr6%jmzV#_Y){LkSdyWm6j3)AJ5L{qCC&&(vAO>7j`evi{R zgB}spTn*S$x`cDVhB0*F&4fuVFnTG$gPUPW$0v~r$*f>`AtRO zTbzH}Z<%O$X~p@L7SCfRLCE2ZG&5zE+x2SUoZHEoCk(OPLm##tkMy~(ef_#_CLED& z=AP$P+L&_AnyG2($~nJJSF38Ob@-yMU7y0IAZw;fwD3l^MeGbM#}h9`&kJ=ZHeX#F zye&aHEVc-JGQt<}8Qo8!m6b8)Ar2!h(~iCG$yvSesla3A56i%Z61w6} z3k|IUU+OKZJ6&tT$a+mCd%Oh9TiM@==8%P+izhLLJ^>ElO;%Sr<3=(c!+xp+9!d!s zXE|ApGCY?ux(>=0JZ$CD$ve*-VD(D|F>8YsNA~%fIHUX3WVwq+f+>$F^NbfmCQUP- znxm0^CVUYFDUVjooQ^!5GCH_4pD8ZW@oDC)c09)4Io)N;nb)VQJ~|TaGa7GeN*8OT zPp`|dmF^H;D4#5UMjS>sBAk)mFMQD)O?>%q$7!5@!#s_iYdB0tHy;<46pUf^2`(c{ zkxq7>*T6SI_$qoFMOzC_=N!oQ{}9(O0rD*3GQt?|R`-kU>_$6dZkpVL4=hpsOx{e| zMEnQ%kskZ^%y2mY@te>Idd$f}=N+7DJ%9B2eXLRDxhJ^O4gASx&rKe)I~`v+WzFm` z7T#2lD=xgi-Ys-BkKYJigeBkPG#=*s%Jb~|NxgTyEfer6y_?M0#F-P#noEBqJwI8q zdpoR&oSSJCZ*O%uXZbaWS65l}hX<|c%L|Ufcp92=&&ml1Yjm4=h3kkKOJjCf97UYQ9pH_0H0flzb=ZTBmMtx9JNXJ;o2$-2@F|bZj;t-r`jZV1ry2Ms zpV+8B`2k!A9Sq&fKbM}f^{ZSDT5JbBB;blTj5v$#$M(@jLOwuxS<#7&?tYYBO?fyz zwDwL{k6VXZr^zd{?afqPO!)xehu4j%`5JK=uV2Q)9dVoJe*R6e%<^_NfBg2R|C)2> zZ(sW_#-raEabVeBr{PCua*oX4di;S>pJn3Bn9@<%E3+H^U&-2l)^58Lf)rFQ* z$?KE!23JJgV{w~8Iy9x7<+rwTdYQU46KLP!GRie4$+hN@F^iAwZ=Lq9v;0Zy0Upq5 zIsKS{fC~s?3c!|}>ZoNgE0RlQD7PVIIo#&dgKHcQCG(uNmYED#xQ4t}1AUY&_$~wJ zqeQv3Rksc;rzqNN)>j3}hFtEE-Gk;k# z9KU_;2)tx8|LUaE%!Dz*GvSLe(uK^;1o=KA%&(N`T+D2YI7+y+!~)==uqDL%R|tR6 z$MjejQ#LYXb@ZlG&~FnahgH0AfK~AKsM`?TDdIIby(%oLebjP$l{oHFIEx$=xDtmO z_#b1wb1Xjnbo`NN=uorSc}b?VYRLdAnn^DE3G!cPa3TCPKmTq3A3VgIO)lBCjNavz z)1TQU^iLoBG)C`@@T3&IOxV(Zp5|eWuqcV2?v9b*+ekXtX3_hDb|xK7cq6V;$2q(h z3@aul(*5dshcn8X#SYLnzW)h!IpC>0PS?$2cv5&Xv1z@m`p6vX!fckXruFDDYd*5X z;fOqc9h%iFr7uAFWqJQ$W@N-=>d@Gvn~DE)Il9ss*e4y~??K|7m38^6{>kKlmk|5x>!#P3gCfvIhoV0{)i|mSnOcNBJ|y zZNM6F8}-uo_mXpl;(+U zH#s@cV$UtM!k3oQjlll7yGyL_qwVk-W^wKv;x*FFggbh!{PQE0abdj61*Gpp8^p88 zy+c-+zJY>6;O`!^N_zIBlZnR&XOsgF)`U;ZA+DH01?c ze*pQkPS;LY`O}Bp45qTp$~x!FBlpKljkt@lWWpRzM{_s>#z;34zKF{-p4<0}(_ej> z_gn1v7h}i2xMOs|mHmH~!#Og&k=?Cz5qB#dBW#g3lZ!_!>=6bP^sV9CUxc0&ayTRH zOx#AelU*LRJp7c*5;%wMcV#vN?MxlcQ7|Sl0v!XN*8d2zAY?u=z?TQeisg^y9NUkq zE`F^%|AI#5Z_vr|Q}7rtE|2dkuZdk5?fEyso9y;s%P93b{VXVK)1HB5`YXw}74Mx) zANe?TG!L@Q=v{q=KWg>8J2~!B0dI-bSJ3s<#p(ujvpTS+L)R8-9Ne3(=@Ay8dpEe2 znKybYl^1=mh4V4H+mhtU^!jz)9eJwt{rxl}j7jYdL$9pLnO_sa|-zz(d z%U3__c#Jf&#C&u|da9~7qK%QhbMCSB6q$z9+f30vghv{Tm$IFtlu zN_bA3sG4)W_=|R@>GKlIr3c5eH(+)T>w09q>uVOyh|3fn8Ef(FXjt&F2-;bE4A~IQ zgJqZ5L(RNzN9KP!aQ+o9alHV0r`_i>($U0Y)Y}}MtvTjF4r|1F#DRoSsl%Lu(8|PP zgdJ`#Czz7YoKR%mU^vV$ceq@@Jq(hU<7ektgqchqvsYQ{Hz+5I?C~1)JhvkoAU!R> zY-Wr(F?Bh+d^5g{<~h^p4A5+ic#Us|&Yx&R?4L=S!ffZR>G!cle5Ui)?CazRe)qhE z+0EJchp${>b#dSLRmk+jVcuhX@R|U!!Zys);(`2@bm%GO~ zbUFF=x8ZrAfqK5|%7_y+%nAHHHGuUr7H_?^CtzIA@reGeva za+Aw4`bI6jlh%w6Vq`X1>M=ua^Cl$Yvqvjl7{AaG~yTD<81IJ6Fp5iGwEl_n#IO)E!YpOp3JhJzOo03 z*}H^??jK18jdQoMWnt#r{akD3bB-?P#Cg6mc{i{o3mr*ZM!H#MrT!gsB|IWwlQIDz z&9H0M9N)C##r4*Sy?L$7d4?b78h=u6D_cm<+Pd-9@#u1Ed~&sQu9Ii?v(Bq0SkoA~lgYPLaej^W;Cu|WL^_pOiF^$5Rw3{x z!h2Imr*O@9`W~5u3G;u@b5T5*nh9O3h24%FH%ze9mPyWsX=cY(lJ1YHzkMH?w^QW?9Q|`m;{6!|^;>CGeyLFSz;o z25V&3Ny^>dc<*+DdtT3_;2Nn@VA1hKXq5}B{muzij(=PNzfi|bDLtMgW65oFBkuu@ zXV;@$Dkn$Qpo~MDM_5zNe&u%aIPasY7EPqra%v}f9C#mQcej?E^tT>o&nP~Pa?PPl zgRS`Jcnj0p7{*Tu4{2|HdLWB#XlLO;OFg^aDlU^X+Rw}!{6&6$5>V}=x2#_ zPdJ}OeP$s#XOumYr=tvju%-iDmPy{nFdQWtp5-HRChuQpqfMmwHEEc&p5F71SAX(l`EN1i z-yUOL`u=;R?1leD8XQ4}~V(zwptU$i>Gjh+GpNWqlZ#lX*`d(-fYnKHdzrG+)sx2aomErCOTl^ML>SzwNMO9}HnRnvM~0!*r)yR2vt-}4Oowhegw=wab0 zovdlc1ZyE*)%EIH@}}q`s|Q$Q8`{?_{1bGuz{6D*;x>A6u2tWnbMNMA3!fy{dYnFh zGm9+=*2wo)rrFKPkT;WdCa*^Gn(}VMV}v*2KaGc%pu@5^mJD(pSq1SF`8B?AZJb74 zjB)|e(B#{Q@8~tcpa6Rg%HSiyng~A5L-Y)4ADV|X>Uq|#G+|B-*?>%TIpwZq9udsS zWXH66orNn|d~U%GvS@2YGgr?!_1tR9zO>$&;4K}&la{Z(?QlhS<8hl#+>iVKZ1~ZO zR`b>K%=sUL2h6~)(X7YHU(J`Hr3r78gATESKp8dh8E-D930|O`XpL`QcJFEJjm<6( zkO^lk*f7$3n$w5JMvw5`KEK@QXOSE9SKa}4KHliE&C<*~tP!vA?h9{(HF>WxYft7` zTqf^jd?4^9`)RHRURrAYV|0)0h2tE9Go6|3a?THppf?R2Eq4w0%R`4-&2oa?7!=nMEZV2w1hoN46Ond4X1Id2~C zH-|E4!kz5NLzvH`4`l>1|8ynRJ#)h8Vcs5QCpVYI%P5@k@Fxku6 z?0AhAfG=c@!4qWxbgS7Je}l9yGFRlCL&(m3d(wbk8uMFP6XHvYjk#4cZXVJLt;3@04jjwzY z+|@kb88D0P$kZvgknW#s!ySh?;7$WOA*+r|vkI;`#d+%XPO%XEp%0ejJH4`uuH+ha z{v@aOu#&apJTw!-++~6u67iXOX5dphCt2q+ORV83t~Iv|LCY9GUs7+bHJY49BmFFP zil52NHE8*C?VXvA#y{Jl=gE&veKS#YY?dh+P zFOxxzOxO~b+TUqrdE^s>C3(yOytF1u_%8hkvH87ALOG5}=4bKo>?kImXK>@u0^cAJ&c_nN(fImsWs z>M%w))AUsv-guZJtm*o@Z(5Z8&GuitVC6r&ZLv=-yZ1oZ0QJ#mhEupAd=Y<9Uz&Cf zsINwvSS~!p%MLU@OU@V1$MtOD`*e7keF3N08#=SM%LNE)0-NaCz%z-$If|};>u2eE zxxLV$pKQDD$#|JF-6|LGO>U$6>PAaj$vn|Puhh zre!n7la8L6vj%)#OgAaNBU#G^^1J>h_`|#$94imblTH>UhdJ2#-+SFg{rm^awxaDZ z%PHSRU7W?2_E_CncnP^Pc{G~U%$hXFb!`?bLXQJqq@^jB7CIYyPb5NPUi0!lB14-@jme-aKjjUOi&nzjNGLJ~-pB zsQHugmiqohYX+|xz9WrlTbp)vNg5&CM!Zhgb8)pbGfUS9#}UuzaBQB{9b=A#`8?r{ zI8T^8)eqL-xwQ*e3=gVu6?=x@GbQWkbC?bnoz&5)wxUD9Gjw#sr*A?V3-1_ix%0Zy zY0%G#r}48!KlAsiw7C2QbhF?wx~&e;wa0Dn5PgZ)S6LameG*&7G8Y4<0as#VCcMnE z*9qWq0|#c(fk%D`tt{(d`hW0aKDSXez=uYcxq{u9=hwhrrjkKJs{?P8Z_Z#Iw|E}?fN!3$ z^nLR!8?Gi?@s1Rn#yj*}cj3$@SFHX=FVXjW#Y%o~ooq7xJRO{xr-`4L=MH58#Bao1 zwBuPHQ)WP1CCGeco32LA`K>FC(`ff*yO-!r2dhE{=){}TmmV^Fs7)i8uV<$&oTdn$ zK7^K)w`-)uzQ^yxy)3{tZ^duKYm^W0W^D9W9!=Ujc+#89G=ed?&(AaeoBYgP+-Na& zujOvT+uVbWcAh?;73?yf2{waG8B57YGe4C{M&G}iuBsJu*evSLV~*tmEzFLCA>gkc z&n|6n4}0S0Us(B9FImpSq=jh%Q)(id;XZ~AWe=&JxX=R%I7skwg|CPT4Uw-Ge81wIgG2j3FuT#at zJK@3OrGqK*V5FUSnX+&CHOd3HOf#7(Ki)|m*<*SBe&$BRTf|?am1UI%9iIs_v-=8u zqd6MQ)JR{8FpC))!?jQ=GxvM>d!}P1joo1W5%kz_EgHnbh%sLh0cV6O(#quf3va}0 z0(@NeH0XP$x-qjkmk9RmD z?W`mCu6@ovGT8Z3$)~YjD>|YBejS}b$J=lwc9~rg;EcnXBeN`Wei0rndfI7bC(zI0 z(q~;tKbx>7m%fe?;j*7OzoHP1g@^TIsirTK?`?WO31O z(8!c?c6$Vdb>h4Uzv1HrV14dgc8k&Nti$6o!Wm(VZo6?#jedC1n!bL;3O~MNv6uJZ zt8l%6CgyP%-HNk#zKr;dkDeO!Knr^U+t{I?>jYkxdKK*qjFEoU^v+d_bG;Hi1TR{L z#s?G+IhW~8I#&K+x$-+AG$ zev2>vKKSCjuZu43{o4o8pp;`4&g5|p&*pqCZ$=y@G@``{;4{J>`7>GMVDr(bLhYsORfZUgEb)*#*SVk?~$Q$RhCY@cS>FU2PLcYyIIpy_@22Q1Uzh&C=<#V*bp>x33@KtC zM}+G(=gD}Oa_?3+BP`M(zee7F>hvmWUNhbrz=jT7|H^}rzh642fgWeNI`LoXIEP6y z69x%i^jr{+gv*cCr#fSZ$SW?!T5rD8LE)cD_-lgM=)C1-PW zvPG{MM>qU0@uuO*8uAfsx|-uL!WQ)P2>QBkCV2oq ze>s>wq8?u@Xo1np4KW)dUL)O1j}y#^I!=SO)#V&J!7of_-ho*?a3+HPuPy-1Y!;p- z14kCO!|lBmXE$W%Bs19HP2}tXI(^YTpI*l-;8Y9jn_`tx4nYbgSuBU1;$Y?3?E2CoIZipH2}! zGht21ey+#a&G%3X8qBQ0F6-?1HqlG#@D{jc-;4iD79fq^8Fe}bF08bSi)$?Vne7f| z(zng9bb4pAZqRe_!_aDMTiyV;_%r$}Vg+n;he0#r}r>Q1;CjG1!UnzKW7Jd=#QzL;Y{Exy`Y!S zKA&Dh55Y3aUQZ?utyGwkxr%Had^T(CBkVFA3eVxa-Z|0=4zp8W7v0a?&*bBIyC1jm z7dBdFc2%bh<67+6j{Ck%_D*_puJ1wHW_EuIzn9>R<}-8f|AjZ25`r2=};s!TLUb#oFQ7WR9UPx~KQ0YW=-IKxa& zbS5|}?F^4bxij&ZdVHGb7QFI@@!pg>n@pzesijs$jzQX)@&Mv7;WNzS;f=|!5%vgg z{QEVZK@RI09gAR5=)@e0oW=)-d->Ob*_*~WtVkyVmbuKTa>h zk5Mi_`7_Pcgz;+%xkjkki*5%85>|Ow)A`aia#HgwjjVhcIh6|Vz~eRrygsmypBMW% z^YCYcGud#XEVyC%!G&aj=UN8(TISVFR=_MyCfF4E{2Ki<-?3J3W&nJqkn2!aK*4H$4tOU~cu~Que)b@L^AC<}blK&s8`I494jLFZqWu9)U&5oo z74K;JA=ftdFev=}ZO*6hzrWUUpQTfV-=)xH&hH1w1DqkB@zP#*Ul=0%NMC@qNj^V! zEBU+~Tz72(|G*%<)_;7W!=5xUCBd`&PQHAA9X3-fjo#hLpMJ|>jXIxmkFK`LuV1$M z7tUG_I8Dj14Gvo}M$xH;_b(ok_87el+}Ex&?Xry&}J$n*CxyXWW7t(O7Fs%It>|Hbvq z;Prca#dXc#!-(eyTO#Dk{0(LJEno+}OPrs5*@k%*m_RfMW!0MC4h_PZOK_XhO$UvQfs zJ2UgA&?7UO{k`y)tUh$Ofh`@jgOxmvqMdmjO^S?iSFo!avxrSkt+4Fz9nqM&a_;6@ zr{ahQ)2y4V^Tpj={37^8-Cm&G3E*s_1#B+o(9@hAokJ4-X2RKJ9#)a2x;df(-;?26M#8vqgBW*B38XkpENk_)I#=&;^;H@o+?bjJ$tgkFZ7= zfGqS^>1Vnxe&g{P?LUjXKwssZt?U@%eWRD5^4Tp;H%nvw*L9%nVa`Qa=NbL1?;?6t z$)-hKT47li@t6*=2YC;@)F;T5of-o-n*cAHYXxttu&U3G+t8mpXHWd>h5NW8{E?29 z_tFCMJ;#3CXX%PTKl2@hFWy{e#dpbpabNf&t|MNPyB$C4AhSr|jN>$i*e#>iT$<(h zj{n3YW=iR|25T}`47K#f`ncWz2$tHaJ*}wizcwYbC{v-XLzWDv$eKwc5j|Z4P zkwzv>Oq!YIFWu}vkK4EnJ`6lY*|Tis*t4pmj;Dyb2utL>2wQ|R%9zD^l2rw7iXYbO zUK1T$>`^9S$rR~@(y>_Sn?M9=hlKY%?ykQpQE$n%xJ5=O}`-@3*y)Kjxd*q zR}(nJwb^($<*|`?`DhksV-aS!J$+0Zrqh?#$;sZdo5HRtwNq=6k$@p`3ua+ytLU`nfXXPM@9jx5vD|*TwuW?oNv*5qGSMLoL_}0 zdR|<{)7Qjvg7`VU9h%D+Ww|Tx0v@G*wI{l(cG1v7qug?G%S6Xhlr0l>xU3m|jIgB; zY>1Lg4wF$1&1vgIE8fh{1zb{oAUuDFwTF)k{O&EQ``{wp*>X#A{u9nT{NWw2a*q}8 z`Dyr^ned_agc5q7A@Svs09M%W|&KYJc~aljX8XIZnE6F9&%4zJb6!{lL#t}nOv%eyUe z-wexuUp0RFN%L(TMQ1UYo9XO~1!H_$;9+FYrsApp(O>+ZpZ=GB_?r%&{>^_G_xykR zy&cE@^yAyBfA970P5bfP|Jv^3eZMHU3GOp@S+i?~jXA#AX1{cnoHH677$a^|{`paB z_~MfJUPZHh`>=K9|5t(b6?=Ax!wzAHutl6Df~FR|wZw|>afC&rq;v9r!tW(Gc*&$+JXr2`UH=(m zaMSVHl`(6}nSm={i#&hfk7j7}IHzklJtg=f;7I|VzVxyH8kxFf)Mw`PGl#ezWfrD% z899B;P|X=-@wuZp@6f+Gi`>yTy!x~B4o(?h4-Ia$f+OrpL%#?yk1i}Jn@Da6Tu}xf zG63(L48Alq;Z4zFbn8C`4h^O^5{;|r2HL=!4pc zKQOAj1zv_%z-bDu~BIL~Sz!+go0bYx6MOY(FQ@8-V0?aAh2p-?l&Qka^6Gd(%< zHwZg~E4jKJy2oXNBg!^=dpN`U;l;d0T{Pl2IwEA!eTQeTTWm4c7ZWTSZ8vsj6MJ-8 z&=A+`A_k)dU>tmBf^TnX?{-9#a7Wtia#SfseS<- z3tm^g0G9%LBINml^st4m%(a>qw!7!sy|C3fy?WG2-Z^J^XE)QWhF|v-J7V6tXyLoZ zEORDvvKwdfu}xO_?hWR4`L|}nD`)dOb2Rd2LO!Sm|&P97adFRD{?*IDR z=l^Xo0pEH5&G)iu53G#NH*vx z?~U{NJ-tj^#={-?FiEuStf|Zk4CI!|sfH~61JdBY}7Ucg>K<=vIBIk)aWP0E!%8|+Iuj2Yn`k3zP z(DU;Di`gd?yUi>EIe^GDvQOZUa3*_QZ>OKdo}FQ_*SS`_muZ&w()2lg{#Q>q9@FEe z&syi7-b6Qh&V)TV*JoJTT&`Q6nq^JsW{TN`DSh> z%b&-52^yMz8M_#l^@889Q+0Sd%Ugg}zU5*5&s;B~eWjFzX6B}NFI^)u;0yRPfw^P| zr+0Q)vs~scBXAYhKQpiAeeFzhn>BQeq;^lSf%xH3Va!tttm2i8*6sD9*6G{y?BXM| zzIxDcn-;i@@@A29_%vu|Z5)R8jdQJz5c8cbn+Ct~?SiY^<2|{n*~?4zJa0PqqCNn8 z8uc@4rpDn1dzk}tD@Y$xpQiM*=#s~*5WOl%&MUSJofA$JU&S6ze%3{BouFoIq`T3n z*6==9L*}fyL}YavULGXw8|Yov5`yJlX-N8lWqfgh7`cD3cYyxF%M z)`-vKo+0b~6g|P8UbRPl^lfs(PgxGx?BL#sR?quWuoDlATzR*5ZdfI=Pkz3y;Er() zON1xV&~#K^<7dL(fDU0(#$>wh;6d^83oM)65!pxQTOPTD^sQWrk;m}!ehFvPeWsqx zf{i1s^xP7gcjd6nm_7S1fA+JV{ZF&K@4owP_rL%9zkl)0AAI)zB%fMlS(m1eCu5Hs z{X^-?=}9=nT+s!(2;j^7>bgf+qyDBv^6zBW*)_C_@*cTR6 zUpangU<(~4=nW}$f64O~XHj-pS>+hBr(yES@rU_0hw^`A?lOTsT(Xh>%O>^<%1@XCr&b*SSM@5;z1ucxLwh$KHEK zcX{9E-{&-d_V{jX34s^_ArL|!5F5O~17l+wgPCS8vq9`B_D1Zz_cj<0@WKW>uoF9u z9mh$Urp>Rkm)5 zqr)dh*o(;D+_4c>^T}e1-_zfU-&kjPFEW#Urre76O}5NUU_X2&3++8Lg+Ay>oQsE- zTJo?`=G)Nw(a`+d`tfd}d$GHF5S#@J@=fHLe&v(s;GEZX(l0^ZrB2y-&c=JvjWHAT1YH(mU!rSBMQY0~abqj`Wc-qHHP3WqnP=T=xt z=0EBmX10!5n$Q~j0j}Zez;l#O6ZSZNMi>OYNu1Wh;Z2D1Xx!KbEt;QaGG4#D80E`+ zTt6hzS1o@=xn=PfWdt1FfHSG{pK&v~nd{+C^sff>GiTR;GH2=dE}>y$pkE+wuyTkM z9-3pNbS;dYR__i^ww9$E&G* zbFcX}GK&iSlrf_jpmREANOx;=bUwIMVc`?=Edd^$ee)0;fjQAPc3I@WG|SvImTRkd z4p-#+d-sJi!WZdhwRh3Q3}^CfBex5miCfJa&q_1{W}?zAE{9J%W;Gus^NHS;H0cpH z`&qJfyiHg*$G-aMPq+M`bH}$m|Nh^7RW|*j^EcDBzwmVpy02@rX<%`i_<0=UTHq>~ z?w$O7lUq*4ixb|YaGjNVoZR5SQSN@hX*5T0Mp*#iO5v%6PDhhBBaCSdFKlsiv1K2c z2!AZM2VdWBeLs8Cp7`>*o2^kkAoJCoE+dfr_5u7Tup3RS+n4WH&-Y(uR&1T?bQadc z_kY+5r;W6izWB80+rE~&&;9?0J+o%dy49dt8><0#i7KRHrYIe3sp`p$CvPTyMxMVs z8Fd0U-{!W4CVrDdw_<>EZ-%ZDne9(%+0bH|kq79;T=)yj*bhVdnLyrhI5Q!A=utsG z4Z&?w@#D0MIgXu~4VaBetDFo+rURVwRTLeE@w5A~14-Tl*N9y6W-#OE@a2B|e{d$y zj@I!7mS?MVJ{(;zwv zS6ina?6d5{?BjsXz>7fsNejuE9>KHNgT?^X1UI7dz;BWkFmHd548f%(*jsq*Ec1GLAGlSP8jLJS=@l;@IbgMd9gZRdQ&jAa0BPyIgeK9XLvNJ zBhaLJ7hA%8=%)BQ!Wnf1NIMgsQAR-bYfphgpvkB18e;ipXWzjX4{Pq+!f%8(ZO*K; z2I`nxi|)$YXxi@a&a)BLB=c`Nz5~9*vnMHPU`O*YZNit%O!+f;|H_=H z&#VF7iS#n@l~it1;R;#ItYmYpPF;w9Jr`cX4z|J-=!Hwj&2#+|p2&>*tS9Jd>tT(^ zgSXl}+Z_$a(WlY_lYxJqv1YK999v;Y;Dt0cww!l&S;n<( zR!Ejv+F1Y$s(WHNotnq&zIRVp>(}>K!yAY2-PgE(qZ!zwf2Y}dXRX<_V^(}+pEbL< z#fs14Nt{?rj&Hg>dS;_Ndalwso~Anzd``koOJdH|cMvUYDc(9q;OJaSCX11@ZGzQ; zr`LkZCyYirt8qcQ_s0ee)8^)T4>PHERzmTs5<2TpPFjP z`^S=-WRDqhH1cSa1yDXf88hi*!XIIbcL-y|e~Qr?g)!cdwv!wRx^L$*tL?ta+w4KU zA3edFW(Xey7{)gOL;&!76W-F^R` zj6dy0PbE{*Gz0FUeP!9MCsVVSuGb9A@w&~to-=VBb!qC>;Sc#oKRDyVA5UP0Kk{rh zt38Q%Y`hp9nWM>xpqWW8%cg%wnptQlf1_}j#Ha4F zG&9*T=;!ftO9nU6`(44zBKzIbA4U7eHwuz__Ay5jhnJKw@_uWveYO>IO{rP`a0T8X zb26Iw7rr=7!);r-YjagSz`Gs2Uv>Gm}lGbpbtrQ}3nI znLPO9d#v^mGQ-Tqgg4S_eqbQG7AHDSM&7^t8Rg8BDQkFmoHgL@OZXAq$vKKXLg7o& z;s>oB+$FN7kHeY(nwpP)ukJCvwo4VRXQp~ySsCUM@?}Lg>Ckv*g$1up#}|0OBIoe! zFD}Oaoo~5kC$h75v^74*9`%EKPW15<<87o@;6=b&!ZVm@B;Oo_vq(3K%;DTKj#=+9 zV9jX!n}J{lye8`LhF0@F`h@WJUH%zAtRC~~;xn<#(u7BLvJCp!#A}2z89dIOz-~3X z8IQ|ot|k>dFT8?X-F#1lDdI5F&75|2o7;HLd6?6htXFG#4(c95%ZJ-U@Mol{$)8Dt zYwA`xfY2QLKsq(KGzZbjO%uAN8K{=W;C;@JahiyVXos@8G$sqYqHUrgdJ&1 z@nwWFTxX=ArSRuRjeTD4?zbk){TE-`WsTn2Y-umDCz#v&@MV;1E_izvdz1IMT)+djE?T|!4_V3$ zW-V`HjQpKMz6XV5p&jOYa2^l-0{+e^%YJDi^NW@6o+H-z{qxr9^#f#@=Q>{|rec8k z$(_Y5XU1n0d9VX?o^eFY>0>n?X=TyRaZN!cUm3Lc-euNl_Vae~^7$|S)N^aam+uUV z8V`=_9c|&amRjzON(;U;*W!1uFKico6L5InDso`6x-(NlpBb5E`Tt39nZyNj!QtO{ zeoYgy(D^5s?*e;T9OLis$U=uT4Gx!E>Q;2h+mB0*RamF1d+qTru2}{hHObrYvd&jB zdq%DZ?u5nbR-12Kj1M@)g80fh;%2ZrX?{O`-}-aCQ>CBz z@c z=NkD(b=9teW4yD((#}k!4{@g5_gba3zp&ieo>+*7JKx%}|D)~6#nzTt>{h4dyQ7TX zbvP-rjZaK| z573{2E++0GPNQ34jh8Pg_SCZ)nXnK2C7cv+3i4*EByx|J21r z*5KM2w6iKsBOj*ZgI(m9t8&f$mnU1T(H$+eqPxSGymRolBX~qFE;8NEK0`k4{5;FX zvnk~7HD^8ZmgRJPfHQ&dWPPV~MH^~gbswJN2WOmbGprRkQ8YxfwOWtXx0;>V7rK@1 zE;O`y+xZ@>0u$+@@eN@2&B*&K4PPc>L`TaQMX&PIZdP|LSvlnaIP_X_4=`y7{Rc|#n$!4QOkX6y%k;CX`QbhvAnl7T4S)ID?CNn z<_;g8v8>DMtn`E9u6L!udqxgdFRC~SA5s6>F)dfG;FE<{hC!?{*SfUSuf2@SR!oEA+1a} zBK^$E1n6~fn5vF5bTQ^Nm2K90g*U+`+FKSrOxlnq-Qi)4IE}DJxKnrbNXunjH-|ag zOm36d3lSmnp2iGvX!~UJ<{6es#zt5ppGFuX?JR(nrffhIT6z>3dNi}vQA3#_egVH0 zZLAR9(Hx9vf<~6iu8X+A%wf}!B)zN^p6oquF{^w7J$5xc6r1o(xS##nJS(_7-#YTQ z*p8ksVaT@~t+@`>^YxEUw1#wNc=v@TsT;{q<5Onsp$l#I5c0v#I=-Xl^_=)lfP7i% zuD;HLktZWRM!ZHoO=Qb6E(ahj&A*J?@-8xJC&{_u{|jTpZG<_>G$${C_kk_Kn#8$e zZFw#40{Mp9Jv8Dmtv+C<{inz1oIl{a|0Hy=TI1*@od1Bs7U4_!nNb!x(9eo4EVO#( zrdrA=`b^Hwvpl$1>cZ|-$0B@+xy+G(H_AGPXTojpZNk&L;@2?m2%kwD)WTxvViU)S z?!{cyjBZwMCtbMAb=KdB?!JU9_9XgSM&4`60Mst;&UFTJo1?*+X>?A*X@oP`WZwc$ z7g=QGGi1yv9L{(=#(6W%aGv*%CmXNn)2Xch- zubvZ*G@%bJ10EbA6C7ZFLulp`zlSq=k9bbqeN!!qe!1jz>^z~9RXCGzevyTCPjvU& zzkATyzkA5KzJJy_ffMTVQts^DTj%Y5aseIRKLh5#UEnPqr)k7qmh_tk?%<2?M;Idv z(vd_?I+?!D%y;%$<}2$h^)ipq$&_stzJxCqlBm{+ORdl4jbHEn$>Pc!pyM0;m+=yk_m;4uFCrIi)9 zk4wZW&m2{SFBv15j~mznorHW2*dmM()(Cg%v;U#?!m*Z3S7vA=zBW6E(&ob5nJ)<8 z=N7QjsPH8+_vmB^%+MrqNJ|Uo@w|RcM-$g^c{H@Gq?u^(=pE0&D6szmT_yIR&spn36L00mo;A zJ;EIEn{atoi_B(+3a=~oEDuL>opJr}YWlT=M=DEB297zKI`kj<=%)(Mah5Wm)FK>t z^B<>=d$8rfXY%L3$-o))1w@$bOefds@@40j{+?duVTgAt3=+VIpSWs)24(<_uj$AX`}ZedCS*KN|x#BY2&C(H?*BWrz(UYrf1=(Q~4=h>RSBQhal z>7^OYbsL@A6(7Iyvu`_>=()qc`ccfo?;rmA$TfaG;EQ(@zkdLHBxlca!kXaad8Rx- z+VxfLNO@>yHKW{~%WrVp?P9Hs#~X0tA@cb$I$ zGDUHV!5O%Wc#Uu-k@?5iX>@t82Su7%EZ$85{%!_6B*pvb)&OT>2eq{t>_+yH^J=kw zj@^HQ`L~l3EzA))GsP0%bCfKY5o2E*6iaQR`T&~i(9LH z+S(S|qcJ?Ng#~t!^SX^Q1sCR6U>80aoJh~fv&lX=iqD_V6%Lb3c3D{fc{I8&{Y-kA z=4%|*%z=k;KVbmfpS_!K4l3ci#9TS&Bk>vGjCR|kuE8T2+r3`3e z!kpvWCoGR1=Scrn_&6P{(W#kt{C^KGJZwoj01rMr<&LJN*L4VMy!QxOis3_rXXpPP z-cIoeItAQJV!qpjnmqOaG{3H#L&5F|-Pl2ok3)B+<}f3}$wlH1*5-Fi*|I|BZ(HrG z;v{*@r{<7@4@_a#2{X5ze^asx-v!>1zPz8q8Xy0z_>G4(y3L`ZI_u~R>&To(HnSip zaGG|n?X>Kd$q0~TkWVA5>2Uq9b-gL9xnK{0B@c3Y-+L$N+1}x_wYG4cmT;Tm+c+b9 z@i3-3?r09Q{s$)=7U}iC8=EY7?HJbw5IVO6?U=q#@@B#q9SP(F66sQlCQ}#9EKRLP z*!6+07SHuT3VK!ow{iVSZPRCOkNW2MXvybqm$tmQ^EdKgJbcluhcDi9!kGs8J>|8O zYs~9|H~N_Hl|_!vXhu^$jBcf)Nk7X!GQ;tg@ESB~a76gh>Kbw1ckKKIlJv(~zs8#OUV?X%i&o6%SbHDrezZQ2UkDu_1Mui3JtxR$m zfLe3_2y2u%ivefU1)#^yvq3|1-2mW@%bW39pj%TgMx6o7S>H=f@>BPtmpuWtaDJr+ zU4D!*0K%9&G_od3=*p^?WVO-E(#z?%B)1;h6MtsaXl9|8TE^wI^kU4hx-X-no?Kw@ z^wImaO|-z42^L}|Ac@_#&a+{McrtSf@l(ml4+YB(OtG@F>+xo0TaEU0$x+rpznNg| zUR-ObXVKzLO|tf%9pv0hN7nj2cQi8LiH9j3hw*U6!xj%~^t$(6>1V_0R{B|RcVCA!4bL$%s^|9g$J4IzWt0a7AvlCUP0eu6moO~O!mOF1_PXT0u!Ao;T-JeV-&f%KsrnazBRzM<}xOisZ6 zIP+IW&b@;-4bIS0d3KJq z#pg)j9F#cvUW=j6G+}Tja)W#?@#@5BQs5}5?6wJ^p{cW3hju<|hfVXPWS=T0J3l6i z>{*@dW5@+?JwV5?utbkNJQ45Fdz3-b+)Of>p?i(IahntH=sjq8m+--e`ub?z|{iB=DLhoEVG(P>{tr(eN0$C+M?%^q1eRy3)$wH%su(wnm&3glk{_C zS3nefd<|#!{w?R`J2N%=Kf7^X^4Leejz&KST%2veSLR#f?WOc~p<(uE%VMB&~ zo!PX$sn1NjMR-z!`5EQT)CZtW8SxnL8Sxllia3rkW`5=~lRDAa4EOQT!ICxzZDmjo z(~OMsW55=d0f5g4Z-g_#n9>z9@&6}SGIO~#nXReyOlNEU(oW}h`ndkpA*=~7hn7S~ zu=6Rwm@t}}pV^v3b{r;=4G1j9<2X3gvQKdxNq2hB&(6}%GR|ty9qpU`u(dtEnhuW{ zmUd|-+0oS&s$^#e+1<9cbute(JUpq6Gaj~huX&HfVLYsn-!C3h53NjCBCHX=5&j5! zlo5!mBKN@a8GEX*L^%NYG4g1XX;vOUSpex~Ifs~&L?cs%tP%OQWOkd$>(^s(moWIG zoU<|k!XU?GPL*598|$ry-{k?&&@z_MOIkq=ZBi$92xn5}$-5zg0rsSlg-#yT z+M*t#YxRjH7V}&Qv*^rl-o~0t^!3m@bkyhR;itzehc2|1XlE&K&m?@CAm^{*vx^*t z{2`plJoy5gtgR)Iffa5vJvZO-&oMiG0e@pnRgOGmEj?;Wm}w##-QetuJD5~>ZUKCm z-#Kt5yqG-)|zOw-=OpHHWn3=b1sC} zcsSzS3VWoP$)8bofP6Ib zOO^CByvfWZT3Pmub$(-z=rxxm17GCP2wTKmltD{JKT`%kTqnriq;BgR z9_cz{$KB!0W~N?SXi?8Ii`^Q(t!rKOr!ZUjAahPHbhJG9-8ZpDTt?g`OwO&& z8MxXmvgd2box@d>YmT6iDGT5{8Zag_75_$gXJ%{M>u77jA?a*!>;VnZ*_^YT&g$DZ zquaV$m`BGmlWyjxmnM__iG@r0TD*7;GZW$|9!F^dS1IGMFh?3#a9v+ZAY%}PW)n52 zH8{;Voc^1{@tx@L!h2#TT*6r9?FTitT2D0Meast<1jEXiyWBF+3eW`WU0-YIoC8z% zT7!#wlV4~9-(ZFYeMtIQT;DQ0e0F^;>T9XY{VRVaKBG*4aHjb(y79<%2}8tRlra;I zBs>rHk}=CzGte|MHiY{X>*i519(Fkd-Sr&!8PFbvEB*xADmo8 zCa%)5)xCp$*6#J)*5%qk_N^SXP8_B0?6d4EWO6Ul^LA#wrJZCJ^ES6>e)E_$x^dXr z;K!75h~r346RrqnLN|6>_Irn2PEGiec5^?T`vQ9Pr#MdI{QujYjq(9$~zmEOw5C8p* zFFvs$H%?gOcsVns%$=@>doW8AJ~oZMqgj@-8=r{2+h~4Y6UZC**s&%YNt*GfMUz+5 z;bR6NNQSiT!6|p}MVgtXo27zJoi8jGZ~3$O4tM{*@AUmnJoCy0ODIOaZ&}qbqg!>F zsY6rTM%d&08SqArg)@n88F3roj{KQ$&z2T=wA8YgiE)`SWtQ>$rI+PS8)Eg@S=V9- zJ}R17v*pvQcoo-rWB{V>X=$|{Z%^MKJ&7;xvc$@<_>nX4DXWeke}{UUu#qe?d_Kgv zJ#vw2y1neK-Twmn^wwC9pS);~eR;t$UZpD#f4|^|ThPcRn}0VQ>O0BoZ$aPKKh=tl zuEJ+u$t^Q}{B4VqRL7I*c;oRE?>Rm8-tS?L_nI)o<1)e;WzFrK5f>M`>$ruMDXZYOR`pAz%YF&5LASysA|{k=;px^I!CoaUSfkI|vLnRj1U zquI^cXUDVanQO`=WZ%FS;fQcW*#MV6!=sUQCe2K`nqC(k=@9QxF0D3L-;f@dCR`_H z;O%Q?T1&1K^5*xntnv5Lo%%S}AYd2gmLxI)1?XJDnJV3j8BFfypCb!}PL_FspEW%+ zP0r6D&(__d&;sN6|9vy>aYxb=dKfCuz1ETaE~mSHN=I_aBG;^ZK z75ISsZlqqG%g%Xb>+$Im;Wfeu-voSs+edgl`saLRmzcrSPR-0|y|_ji%J1!XE7>-~ z3hDCputb_!6+S)ea76ectns`Wai3JWFXNsATPKm_ro*89`3>X^r(5QJaszbel%Co^ z-Wg8HZR^wP-MKc7{c$tQX1Dd884z0;a4c5mVS1Dm5?LrdYkhI zlRBWYwIHu1tWge4x#k9VG@h4}OEx+I4wZkETmX8R@@2vr>1g4L%Pi&cO6S=`(ZLg0 z2zMUO&wD&R7Q4yBX+py8dHkGbKWrH@AF<6hUVQXFIp2nV@o)b;`QrcclMm;7_0GSh zqd$bVjb;}nSOu0y@2d595!VmQW#OqL&w}^T;grgCiXKPd=_T?1$a7K7OgyF#twa8d z$8W;y2{`#s4%CZSk#g9d8k)C<7oJOuGQ|ShyokMm+$^04V3I-Wlm; z>H$!9bC5hh<|um0z!m9a;xNiC=S&*p<}q6?Ew@sR0&u2e{>6Y ze;N$9w8Qx^$()bGV{|JHALJaL%&c2%1%AvPI%(K-pZ)F{dmMbxQSjMT3mv7e_N7_w zaW?ZXG0c`F%)*1GU!&;}dW^sp9nFrcxQ#U{toZmJ&Xx&(s^f}>Dc~=WQ?E5<{b}^mp?7*0;&X(Gpmpi7Y{-NomPHYWW{-b@7i(0yTz4)vc2dxS5VuaSP{@CY2r zTHnhWF!!0iYdmwZ!!4iQ|F&?{c3@52g*~kSdFNE-I1?Uf#P?>v9gGpawB@{*eHy)# z{^yJnoU^ZNvQ{?^TKD%3aZb9|YV~OXjqYD>l23Gy>cAzziUovbdiHPXt|FB91Q0^MLE+~N9W z$Qq`S{mo~#)AMw6+X?>AmP}gyjRO|Cw8Fw*N8wF=SI9)S`0z!GhtH(brx2#ARQMvC zNu+Z_m{XT-O3iF0tRR0g;a-`^J{mwhV zx*cEnbt3aP@#D#t%52_MN5Ddz&+X{4G9A*4Vy|)8tO0<9_;3_zeB4i#gxR|6e-AahZ%c!>wj%W4g#o zEJZUfXlB|e8@a?zTj31ejPqsiW8~F{*Qkd{-ei5UnMFU?=`zYea$6~9r&|3VRyvHS z{q8c0#?MVC@5LM!|L$#kX?kRt!x-UAb*w3cM|qgxaU0!gCQ~@$z2@PGhdtHbtJkEX z$&V4Akv}6&qwKS0YNVSvULy}iz6^ehutl6knB!Z*tOfWXTv2veoJE~w$}S6c#B0QH z)X%JpK>E?aWO2BrdxM^wPmWo~Pw`f(ahVv-;Wb*36{PP)do7dME#`lg?(3(D(1Px< z^tH?`>YNOgco^f|dRXIl4f>3NpB={d(&Qpf@bYvlK9PSg1{crv=Lth4+Ymk;2+ zkFJ2o9J+E=KF;6&7;DKnD|<^nYki!Y)zLX{*`Ag?nb$e5ga)^>Hs_W*oM{8Tl%d&_ zknfGJ9A+_<_Ag+ravs?*@I{C4Mz4v}_~y_h z!)re9CUFwIY|IX2Fee-JEITRaRLLY)+x*=v?2Q12;WWw2(J14rxf*#k!E%0Xcr{t8 z2U+?uez);sioh7*hPaA%=&^EVG3*kO{+5cC>tRdvTV>QT*3d0YZ;`sev&pSQHfY}i z-w&?KJ)CJwPM`sEA1w|opg)P6{+Xrx&TnvmIg;pK(q954U+=T5%vgg^jydFFZ}a&J;%2{H0O8H$HY+*CgSmdC&HDu z(f6=_lsqFoe`r-dZt4D@Q%3Xt$?%@2fn~qv|BK6LHdFj(^G8>I^j-h|yYKt+V$rYv z{okJGfNx);Zop-jm1C~j15n3hob_1#jB)_#25`JaxiYwn@&L}C>0U(7KRbm-aD7TY zrnpRXtkG^6hcWp7MJvc3p_!?dxkd}Tf@%2Lw=>MbnOyd<%8PLs06Le%YZ5mzk8+l7 z)>k)M@>X=DBltC2@DrKms`tqTdmPP7Ga@n5*ugiQeG(h#Rk@8X)j3RcjPYI<{uCW& zE|WeP4?7&T&@Ize2N?3F9Ksc8Xwu5$*|>ZFJjbtVzmbzryoJ)9kA zPc?J?dW7>ty=8Pkl1a#}U{+<{I6BSSIE8(q&M_NbDW6gK51BGkT z@BsR-(LkLqa|us?`Naq}Zrq-67PFV#L2H<+JI(LR$0scY4Zjw>{IL_kmw9OTbGW8n z@t7q}hL?6fj1vngJyVis^wf=?Jz^$jBqC9P`S$rh{p&& zvR_?6Kh0KmE6+xq0@BlTzvVl7Tt-@WB%JbQbPC=1@J}YX`Np)1iDHJ#BCO%@<|g<^R6> zo0@qY2JBF0neat=nLL^VG&E%d#A}2vn*Udp+4(f+X`#nk zS>8Sp{F`ua{bM&M1v6I&?e08@Ku^*xt zN5QMROgR8~GV)@S0dW0(o5#Rw##r#s3s&^mF6;5-i}utHE?9e3s|Hq+$)xW$xMuhr z4@Q_G4Ds;9!yAvwc+Y#-)8g22YfZ;Y8Nb_QTyM7}XDWOVe-T&FY^HiIBH= zXu{mGUK38~V}vzc20(h5`T&GI(tG?%*ui*syyG>&HS`ECWj+utqgfgCmnmD80ltX4 zXl_Q>q7DFIj)y;`udKB8%=vrRBCHX{H2wZ|Iug*(H}|s+htXm}CyfQrh z($_YTMOtBTM<$?Soocfj;*frh509Tw;IfU#na#K!`D~- zOf#IqoegzE^gVZW$fUqp7qoGcNuG^zon@g*5xgoQ?2AyhS+xVT^FY-9LukK~BxX z5b0*p+4P#S1M0L9=ICSfSQ$3)oz$0@+1W9Ljz$EtbkT(<7xaa6j4Ux^zT#a6j#}8ca+M&w->|DP2<152`^XX!y7s{J+2`)n$ zn?RQu*%0Yx^8AG((#GV)h|}m+zQ6ir^qTycxY1o~#2fqm=|B5F@4o)$#~1H={>FRn zE(mtWcX=}L7MD3=ZbrBAU4%8#&yqSeaK4Ou8+BzSvx7#5UQcBQZZ2~$;xTUia$*&q z@#Zq?&K&NZFI_g%X=dtYj(e2Ok8w{})+<~)!DECmI+}txA^Jl6(plg+u5W1_nU@U% zz?qTu(2vhp*H2Ec=a^lX6?7QTvs>$_w(tY;Q`I=kAG_~ii-$dp4pp#+ULBibEO#UM zYxb|CuX_qkg101YqGJc%i)Lh)`B#?NJA^aJoPASc({m|n>4Zl^6Ao#P(}$mtfIl4p zSDK!nH}m$~rSL_wG4f;_ufaPJrYN_Z!LBHA9N~~OHRZ%Qe7N7?iu{<`x5&4GF*>A| zCGvT;Ke^D_gDI`{Otg;s$UHL_Sew4j?B%`ObNRcO3q{vU#Ji8hzfhLh)6G1b5!Mu5 znCCD@&*^pL10u(sr$2xW5^yjXoJ``}9rIiv=b|#VAI;6yjHYjsuQhY+Gn@zb9K>I4 zV@%7sM0NCev3>YK5tl*7GOW=DIcZgnHZUZ;gn(xi!R(R`}!x>>s@U7)^ z`O_JL=hE=tC_EVO1CEutk@;8nOxjj?HIJkBSGRLQWh{bwxa)? z+*$Sa2y66l!WuoFy>%2>1Uw-8mUhR{zjS~#9=9o?3oQ-5JhYrSouz1~fl87~^sP+&Y~MoDrsk=zP#jO^}XlJyzCP`dOI#!jAVZKkS`j{?Ki+gXMTM z;1s!K&AbR>0!!Gf$^R)nBh5^>B0N!UIfl%cpPe`j*~z9kP0eD)Fo%`$To?P|AAU9T z5B)!Ppa1W}7w>z&`{cnbQ3cG)kXf!iALF#Lf)s~0%9?53Ux)6C(dhvb zi}#{KnKI4Ch{MQ}@o-1C^8a(!m0M&A`(%4F-^aCT>uU$BA)LMOt2-Uu2y?ROVbZK- z-OKDD*7X{_%5}fL&a&TJ#JmjNMxT4E^{}U{&Xm6F25)IKIu=-joSJY$9LDov{t(s( zXCnAKsra`!=mx3i7`a=)!p+ZF_PSo^@m#-de%2bWZ>#av!B)&Up_IKH?GKh)8Cpgg zX6(ui&ak4R)2%V{WYX8<|Emi?9h$99&AY>E#An2D)Ug>@{HXI}lv8%z3)s@|1pNei z(I$9Ky_p`?1UJ&nj}PNpPM(KzySPnY^V8N5uR@q2j7elZBy?e_o0EyF#CITbTK3{H zE89PvT`*&;A@gmzZM%1x!<)KzM`?883VZ6oYoZ>gPyb3jT2yn_3E*LkZatjwFh-A+ zQB!X~7>*UhH}aE3NF*~C2e*hBRsyf-!W=vpIsaj_vS+O=T3O~gI+7Rna9C4!AA3$l z;=!|bH;tWEne5aN&S-YOH5tN8^4W0*$*;e(&=Q!5$#{?73ph-J4-eeInc`a~;1|8< zfNspS26IXW*qjz-n|=a5 z-#D@e1-IB=$(&6Z9bU=IT*{*f(1jVID^uLYHx4b0x&8>gikDgbCUyuvYf?1hGUhRO1({xUQ25sj zw&c}l#_T_cxXk4g@MfmN9c2Q9z;55nvg!%o7fhRUwJM?!u zK6p9oooBx7_J!9EeHqKXhyXK~;x5WHI}HubUpkuS_X}r2WXUwA)Mg=i@~VN>@>m60 z-UHSU{r%##*ROutzkm0+|9*V⪚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

=Od@A`Y?_7fj3rHLYgM1; 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 O2K*TCW8n7^1OFGi+^Tp0 literal 0 HcmV?d00001 diff --git a/sdl3.c3l/manifest.json b/sdl3.c3l/manifest.json new file mode 100644 index 0000000..58ccf98 --- /dev/null +++ b/sdl3.c3l/manifest.json @@ -0,0 +1,9 @@ +{ + "provides": "sdl3", + "targets": { + "linux-x64": { + "dependencies": [], + "linked-libraries": ["SDL3", "c"] + } + } +} diff --git a/sdl3.c3l/project.json b/sdl3.c3l/project.json new file mode 100644 index 0000000..4b817f2 --- /dev/null +++ b/sdl3.c3l/project.json @@ -0,0 +1,14 @@ +{ + "langrev": "1", + "warnings": ["no-unused"], + "dependency-search-paths": [".."], + "dependencies": ["sdl3"], + "authors": ["Alessandro Mauri ", "Sam Lantinga "], + "version": "0.1.0", + "sources": [], + "output": "build", + "target": "linux-x64", + "features": [], + "cpu": "generic", + "opt": "O0" +} diff --git a/sdl3.c3l/sdl3_audio.c3i b/sdl3.c3l/sdl3_audio.c3i new file mode 100644 index 0000000..92c11d4 --- /dev/null +++ b/sdl3.c3l/sdl3_audio.c3i @@ -0,0 +1,3 @@ +module sdl3::sdl; + +typedef AudioDeviceID = uint; \ No newline at end of file diff --git a/sdl3.c3l/sdl3_blendmode.c3i b/sdl3.c3l/sdl3_blendmode.c3i new file mode 100644 index 0000000..636434c --- /dev/null +++ b/sdl3.c3l/sdl3_blendmode.c3i @@ -0,0 +1,35 @@ +module sdl3::sdl; + +typedef BlendMode = uint; + +const BlendMode BLENDMODE_NONE = 0x00000000; +const BlendMode BLENDMODE_BLEND = 0x00000001; +const BlendMode BLENDMODE_BLEND_PREMULTIPLIED = 0x00000010; +const BlendMode BLENDMODE_ADD = 0x00000002; +const BlendMode BLENDMODE_ADD_PREMULTIPLIED = 0x00000020; +const BlendMode BLENDMODE_MOD = 0x00000004; +const BlendMode BLENDMODE_MUL = 0x00000008; +const BlendMode BLENDMODE_INVALID = 0x7FFFFFFF; + +typedef BlendOperation = CInt; + +const BlendOperation BLENDOPERATION_ADD = 0x1; +const BlendOperation BLENDOPERATION_SUBTRACT = 0x2; +const BlendOperation BLENDOPERATION_REV_SUBTRACT = 0x3; +const BlendOperation BLENDOPERATION_MINIMUM = 0x4; +const BlendOperation BLENDOPERATION_MAXIMUM = 0x5; + +typedef BlendFactor = CInt; + +const BlendFactor BLENDFACTOR_ZERO = 0x1; +const BlendFactor BLENDFACTOR_ONE = 0x2; +const BlendFactor BLENDFACTOR_SRC_COLOR = 0x3; +const BlendFactor BLENDFACTOR_ONE_MINUS_SRC_COLOR = 0x4; +const BlendFactor BLENDFACTOR_SRC_ALPHA = 0x5; +const BlendFactor BLENDFACTOR_ONE_MINUS_SRC_ALPHA = 0x6; +const BlendFactor BLENDFACTOR_DST_COLOR = 0x7; +const BlendFactor BLENDFACTOR_ONE_MINUS_DST_COLOR = 0x8; +const BlendFactor BLENDFACTOR_DST_ALPHA = 0x9; +const BlendFactor BLENDFACTOR_ONE_MINUS_DST_ALPHA = 0xA; + +extern fn BlendMode compose_custom_blend_mode(BlendFactor srcColorFactor, BlendFactor dstColorFactor, BlendOperation colorOperation, BlendFactor srcAlphaFactor, BlendFactor dstAlphaFactor, BlendOperation alphaOperation) @extern("SDL_ComposeCustomBlendMode"); diff --git a/sdl3.c3l/sdl3_camera.c3i b/sdl3.c3l/sdl3_camera.c3i new file mode 100644 index 0000000..9abedbe --- /dev/null +++ b/sdl3.c3l/sdl3_camera.c3i @@ -0,0 +1,3 @@ +module sdl3::sdl; + +typedef CameraID = uint; \ No newline at end of file diff --git a/sdl3.c3l/sdl3_error.c3i b/sdl3.c3l/sdl3_error.c3i new file mode 100644 index 0000000..803b864 --- /dev/null +++ b/sdl3.c3l/sdl3_error.c3i @@ -0,0 +1,11 @@ +module sdl3::sdl; + +extern fn bool set_error(ZString fmt, ...) @extern("SDL_SetError"); +// extern fn bool set_error_v(SDL_PRINTF_FORMAT_STRING ZString fmt, va_list ap) SDL_PRINTF_VARARG_FUNCV(1) @extern("SDL_SetErrorV"); +extern fn bool out_of_memory() @extern("SDL_OutOfMemory"); +extern fn ZString get_error() @extern("SDL_GetError"); +extern fn bool clear_error() @extern("SDL_ClearError"); + +macro unsupported() => set_error("That operation is not supported"); +macro invalid_param_error(param) => set_error("Parameter '%s' is invalid", param); + diff --git a/sdl3.c3l/sdl3_events.c3i b/sdl3.c3l/sdl3_events.c3i new file mode 100644 index 0000000..dcb1646 --- /dev/null +++ b/sdl3.c3l/sdl3_events.c3i @@ -0,0 +1,604 @@ +module sdl3::sdl; + +alias EventType = uint; + +const EventType EVENT_FIRST = 0; + +const EventType EVENT_QUIT = 0x100; +const EventType EVENT_TERMINATING = 0x101; +const EventType EVENT_LOW_MEMORY = 0x102; +const EventType EVENT_WILL_ENTER_BACKGROUND = 0x103; +const EventType EVENT_DID_ENTER_BACKGROUND = 0x104; +const EventType EVENT_WILL_ENTER_FOREGROUND = 0x105; +const EventType EVENT_DID_ENTER_FOREGROUND = 0x106; +const EventType EVENT_LOCALE_CHANGED = 0x107; +const EventType EVENT_SYSTEM_THEME_CHANGED = 0x108; + +const EventType EVENT_DISPLAY_ORIENTATION = 0x151; +const EventType EVENT_DISPLAY_ADDED = 0x152; +const EventType EVENT_DISPLAY_REMOVED = 0x153; +const EventType EVENT_DISPLAY_MOVED = 0x154; +const EventType EVENT_DISPLAY_DESKTOP_MODE_CHANGED = 0x155; +const EventType EVENT_DISPLAY_CURRENT_MODE_CHANGED = 0x156; +const EventType EVENT_DISPLAY_CONTENT_SCALE_CHANGED = 0x157; +const EventType EVENT_DISPLAY_FIRST = EVENT_DISPLAY_ORIENTATION; +const EventType EVENT_DISPLAY_LAST = EVENT_DISPLAY_CONTENT_SCALE_CHANGED; + +const EventType EVENT_WINDOW_SHOWN = 0x202; +const EventType EVENT_WINDOW_HIDDEN = 0x203; +const EventType EVENT_WINDOW_EXPOSED = 0x204; +const EventType EVENT_WINDOW_MOVED = 0x205; +const EventType EVENT_WINDOW_RESIZED = 0x206; +const EventType EVENT_WINDOW_PIXEL_SIZE_CHANGED = 0x207; +const EventType EVENT_WINDOW_METAL_VIEW_RESIZED = 0x208; +const EventType EVENT_WINDOW_MINIMIZED = 0x208; +const EventType EVENT_WINDOW_MAXIMIZED = 0x209; +const EventType EVENT_WINDOW_RESTORED = 0x20a; +const EventType EVENT_WINDOW_MOUSE_ENTER = 0x20b; +const EventType EVENT_WINDOW_MOUSE_LEAVE = 0x20c; +const EventType EVENT_WINDOW_FOCUS_GAINED = 0x20d; +const EventType EVENT_WINDOW_FOCUS_LOST = 0x20e; +const EventType EVENT_WINDOW_CLOSE_REQUESTED = 0x20f; +const EventType EVENT_WINDOW_HIT_TEST = 0x210; +const EventType EVENT_WINDOW_ICCPROF_CHANGED = 0x211; +const EventType EVENT_WINDOW_DISPLAY_CHANGED = 0x212; +const EventType EVENT_WINDOW_DISPLAY_SCALE_CHANGED = 0x213; +const EventType EVENT_WINDOW_SAFE_AREA_CHANGED = 0x214; +const EventType EVENT_WINDOW_OCCLUDED = 0x215; +const EventType EVENT_WINDOW_ENTER_FULLSCREEN = 0x216; +const EventType EVENT_WINDOW_LEAVE_FULLSCREEN = 0x217; +const EventType EVENT_WINDOW_DESTROYED = 0x218; +const EventType EVENT_WINDOW_HDR_STATE_CHANGED = 0x219; +const EventType EVENT_WINDOW_FIRST = EVENT_WINDOW_SHOWN; +const EventType EVENT_WINDOW_LAST = EVENT_WINDOW_HDR_STATE_CHANGED; + +const EventType EVENT_KEY_DOWN = 0x300; +const EventType EVENT_KEY_UP = 0x301; +const EventType EVENT_TEXT_EDITING = 0x302; +const EventType EVENT_TEXT_INPUT = 0x303; +const EventType EVENT_KEYMAP_CHANGED = 0x304; +const EventType EVENT_KEYBOARD_ADDED = 0x305; +const EventType EVENT_KEYBOARD_REMOVED = 0x306; +const EventType EVENT_TEXT_EDITING_CANDIDATES = 0x307; + +const EventType EVENT_MOUSE_MOTION = 0x400; +const EventType EVENT_MOUSE_BUTTON_DOWN = 0x401; +const EventType EVENT_MOUSE_BUTTON_UP = 0x402; +const EventType EVENT_MOUSE_WHEEL = 0x403; +const EventType EVENT_MOUSE_ADDED = 0x404; +const EventType EVENT_MOUSE_REMOVED = 0x405; + +const EventType EVENT_JOYSTICK_AXIS_MOTION = 0x600; +const EventType EVENT_JOYSTICK_BALL_MOTION = 0x601; +const EventType EVENT_JOYSTICK_HAT_MOTION = 0x602; +const EventType EVENT_JOYSTICK_BUTTON_DOWN = 0x603; +const EventType EVENT_JOYSTICK_BUTTON_UP = 0x604; +const EventType EVENT_JOYSTICK_ADDED = 0x605; +const EventType EVENT_JOYSTICK_REMOVED = 0x606; +const EventType EVENT_JOYSTICK_BATTERY_UPDATED = 0x607; +const EventType EVENT_JOYSTICK_UPDATE_COMPLETE = 0x608; + +const EventType EVENT_GAMEPAD_AXIS_MOTION = 0x650; +const EventType EVENT_GAMEPAD_BUTTON_DOWN = 0x651; +const EventType EVENT_GAMEPAD_BUTTON_UP = 0x652; +const EventType EVENT_GAMEPAD_ADDED = 0x653; +const EventType EVENT_GAMEPAD_REMOVED = 0x654; +const EventType EVENT_GAMEPAD_REMAPPED = 0x655; +const EventType EVENT_GAMEPAD_TOUCHPAD_DOWN = 0x656; +const EventType EVENT_GAMEPAD_TOUCHPAD_MOTION = 0x657; +const EventType EVENT_GAMEPAD_TOUCHPAD_UP = 0x658; +const EventType EVENT_GAMEPAD_SENSOR_UPDATE = 0x659; +const EventType EVENT_GAMEPAD_UPDATE_COMPLETE = 0x65a; +const EventType EVENT_GAMEPAD_STEAM_HANDLE_UPDATED = 0x65b; + +const EventType EVENT_FINGER_DOWN = 0x700; +const EventType EVENT_FINGER_UP = 0x701; +const EventType EVENT_FINGER_MOTION = 0x702; +const EventType EVENT_FINGER_CANCELED = 0x703; + + +const EventType EVENT_CLIPBOARD_UPDATE = 0x900; + +const EventType EVENT_DROP_FILE = 0x1000; +const EventType EVENT_DROP_TEXT = 0x1001; +const EventType EVENT_DROP_BEGIN = 0x1002; +const EventType EVENT_DROP_COMPLETE = 0x1003; +const EventType EVENT_DROP_POSITION = 0x1004; + +const EventType EVENT_AUDIO_DEVICE_ADDED = 0x1100; +const EventType EVENT_AUDIO_DEVICE_REMOVED = 0x1101; +const EventType EVENT_AUDIO_DEVICE_FORMAT_CHANGED = 0x1102; + +const EventType EVENT_SENSOR_UPDATE = 0x1200; + +const EventType EVENT_PEN_PROXIMITY_IN = 0x1300; +const EventType EVENT_PEN_PROXIMITY_OUT = 0x1301; +const EventType EVENT_PEN_DOWN = 0x1302; +const EventType EVENT_PEN_UP = 0x1303; +const EventType EVENT_PEN_BUTTON_DOWN = 0x1304; +const EventType EVENT_PEN_BUTTON_UP = 0x1305; +const EventType EVENT_PEN_MOTION = 0x1306; +const EventType EVENT_PEN_AXIS = 0x1307; + +const EventType EVENT_CAMERA_DEVICE_ADDED = 0x1400; +const EventType EVENT_CAMERA_DEVICE_REMOVED = 0x1401; +const EventType EVENT_CAMERA_DEVICE_APPROVED = 0x1402; +const EventType EVENT_CAMERA_DEVICE_DENIED = 0x1403; + +const EventType EVENT_RENDER_TARGETS_RESET = 0x2000; +const EventType EVENT_RENDER_DEVICE_RESET = 0x2001; +const EventType EVENT_RENDER_DEVICE_LOST = 0x2002; + +const EventType EVENT_PRIVATE0 = 0x4000; +const EventType EVENT_PRIVATE1 = 0x4001; +const EventType EVENT_PRIVATE2 = 0x4002; +const EventType EVENT_PRIVATE3 = 0x4003; + +const EventType EVENT_POLL_SENTINEL = 0x7F00; +const EventType EVENT_USER = 0x8000; +const EventType EVENT_LAST = 0xFFFF; +const EventType EVENT_ENUM_PADDING = 0x7FFFFFFF; + + +struct CommonEvent { + uint type; + uint reserved; + ulong timestamp; +} + +struct DisplayEvent { + EventType type; + uint reserved; + ulong timestamp; + DisplayID displayID; + int data1; + int data2; +} + +struct WindowEvent { + EventType type; + uint reserved; + ulong timestamp; + WindowID windowID; + int data1; + int data2; +} + +struct KeyboardDeviceEvent { + EventType type; + uint reserved; + ulong timestamp; + KeyboardID which; +} + +struct KeyboardEvent { + EventType type; + uint reserved; + ulong timestamp; + WindowID windowID; + KeyboardID which; + Scancode scancode; + Keycode key; + Keymod mod; + ushort raw; + bool down; + bool repeat; +} + +struct TextEditingEvent { + EventType type; + uint reserved; + ulong timestamp; + WindowID windowID; + ZString text; + int start; + int length; +} + +struct TextEditingCandidatesEvent { + EventType type; + uint reserved; + ulong timestamp; + WindowID windowID; + ZString* candidates; + int num_candidates; + int selected_candidate; + bool horizontal; + char padding1; + char padding2; + char padding3; +} + +struct TextInputEvent { + EventType type; + uint reserved; + ulong timestamp; + WindowID windowID; + ZString text; +} + +struct MouseDeviceEvent { + EventType type; + uint reserved; + ulong timestamp; + MouseID which; +} + +struct MouseMotionEvent { + EventType type; + uint reserved; + ulong timestamp; + WindowID windowID; + MouseID which; + MouseButtonFlags state; + float x; + float y; + float xrel; + float yrel; +} + +struct MouseButtonEvent { + EventType type; + uint reserved; + ulong timestamp; + WindowID windowID; + MouseID which; + char button; + bool down; + char clicks; + char padding; + float x; + float y; +} + +struct MouseWheelEvent { + EventType type; + uint reserved; + ulong timestamp; + WindowID windowID; + MouseID which; + float x; + float y; + MouseWheelDirection direction; + float mouse_x; + float mouse_y; + int integer_x; + int integer_y; +} + +struct JoyAxisEvent { + EventType type; + uint reserved; + ulong timestamp; + JoystickID which; + char axis; + char padding1; + char padding2; + char padding3; + short value; + ushort padding4; +} + +struct JoyBallEvent { + EventType type; + uint reserved; + ulong timestamp; + JoystickID which; + char ball; + char padding1; + char padding2; + char padding3; + short xrel; + short yrel; +} + +struct JoyHatEvent { + EventType type; + uint reserved; + ulong timestamp; + JoystickID which; + char hat; + char value; + char padding1; + char padding2; +} + +struct JoyButtonEvent { + EventType type; + uint reserved; + ulong timestamp; + JoystickID which; + char button; + bool down; + char padding1; + char padding2; +} + +struct JoyDeviceEvent { + EventType type; + uint reserved; + ulong timestamp; + JoystickID which; +} + +struct JoyBatteryEvent { + EventType type; + uint reserved; + ulong timestamp; + JoystickID which; + PowerState state; + int percent; +} + +struct GamepadAxisEvent { + EventType type; + uint reserved; + ulong timestamp; + JoystickID which; + char axis; + char padding1; + char padding2; + char padding3; + short value; + ushort padding4; +} + + +struct GamepadButtonEvent { + EventType type; + uint reserved; + ulong timestamp; + JoystickID which; + char button; + bool down; + char padding1; + char padding2; +} + + +struct GamepadDeviceEvent { + EventType type; + uint reserved; + ulong timestamp; + JoystickID which; +} + +struct GamepadTouchpadEvent { + EventType type; + uint reserved; + ulong timestamp; + JoystickID which; + int touchpad; + int finger; + float x; + float y; + float pressure; +} + +struct GamepadSensorEvent { + EventType type; + uint reserved; + ulong timestamp; + JoystickID which; + int sensor; + float[3] data; + ulong sensor_timestamp; +} + +struct AudioDeviceEvent { + EventType type; + uint reserved; + ulong timestamp; + AudioDeviceID which; + bool recording; + char padding1; + char padding2; + char padding3; +} + +struct CameraDeviceEvent { + EventType type; + uint reserved; + ulong timestamp; + CameraID which; +} + + +struct RenderEvent { + EventType type; + uint reserved; + ulong timestamp; + WindowID windowID; +} + + +struct TouchFingerEvent { + EventType type; + uint reserved; + ulong timestamp; + TouchID touchID; + FingerID fingerID; + float x; + float y; + float dx; + float dy; + float pressure; + WindowID windowID; +} + +struct PenProximityEvent { + EventType type; + uint reserved; + ulong timestamp; + WindowID windowID; + PenID which; +} + +struct PenMotionEvent { + EventType type; + uint reserved; + ulong timestamp; + WindowID windowID; + PenID which; + PenInputFlags pen_state; + float x; + float y; +} + +struct PenTouchEvent { + EventType type; + uint reserved; + ulong timestamp; + WindowID windowID; + PenID which; + PenInputFlags pen_state; + float x; + float y; + bool eraser; + bool down; +} + +struct PenButtonEvent { + EventType type; + uint reserved; + ulong timestamp; + WindowID windowID; + PenID which; + PenInputFlags pen_state; + float x; + float y; + char button; + bool down; +} + +struct PenAxisEvent { + EventType type; + uint reserved; + ulong timestamp; + WindowID windowID; + PenID which; + PenInputFlags pen_state; + float x; + float y; + PenAxis axis; + float value; +} + +struct DropEvent { + EventType type; + uint reserved; + ulong timestamp; + WindowID windowID; + float x; + float y; + ZString source; + ZString data; +} + +struct ClipboardEvent { + EventType type; + uint reserved; + ulong timestamp; + bool owner; + int num_mime_types; + ZString* mime_types; +} + +struct SensorEvent { + EventType type; + uint reserved; + ulong timestamp; + SensorID which; + float[6] data; + ulong sensor_timestamp; +} + +struct QuitEvent { + EventType type; + uint reserved; + ulong timestamp; +} + +struct UserEvent { + uint type; + uint reserved; + ulong timestamp; + WindowID windowID; + int code; + void* data1; + void* data2; +} + +union Event { + uint type; + CommonEvent common; + DisplayEvent display; + WindowEvent window; + KeyboardDeviceEvent kdevice; + KeyboardEvent key; + TextEditingEvent edit; + TextEditingCandidatesEvent edit_candidates; + TextInputEvent text; + MouseDeviceEvent mdevice; + MouseMotionEvent motion; + MouseButtonEvent button; + MouseWheelEvent wheel; + JoyDeviceEvent jdevice; + JoyAxisEvent jaxis; + JoyBallEvent jball; + JoyHatEvent jhat; + JoyButtonEvent jbutton; + JoyBatteryEvent jbattery; + GamepadDeviceEvent gdevice; + GamepadAxisEvent gaxis; + GamepadButtonEvent gbutton; + GamepadTouchpadEvent gtouchpad; + GamepadSensorEvent gsensor; + AudioDeviceEvent adevice; + CameraDeviceEvent cdevice; + SensorEvent sensor; + QuitEvent quit; + UserEvent user; + TouchFingerEvent tfinger; + PenProximityEvent pproximity; + PenTouchEvent ptouch; + PenMotionEvent pmotion; + PenButtonEvent pbutton; + PenAxisEvent paxis; + RenderEvent render; + DropEvent drop; + ClipboardEvent clipboard; + char[128] padding; +} + +extern fn void pump_events() @extern("SDL_PumpEvents"); + + +enum EventAction : inline CInt { + ADDEVENT, + PEEKEVENT, + GETEVENT +} + +extern fn int peep_events(Event* events, int numevents, EventAction action, uint minType, uint maxType) @extern("SDL_PeepEvents"); +extern fn bool has_event(uint type) @extern("SDL_HasEvent"); +extern fn bool has_events(uint minType, uint maxType) @extern("SDL_HasEvents"); +extern fn void flush_event(uint type) @extern("SDL_FlushEvent"); +extern fn void flush_events(uint minType, uint maxType) @extern("SDL_FlushEvents"); +extern fn bool poll_event(Event* event) @extern("SDL_PollEvent"); +extern fn bool wait_event(Event* event) @extern("SDL_WaitEvent"); +extern fn bool wait_event_timeout(Event* event, int timeoutMS) @extern("SDL_WaitEventTimeout"); +extern fn bool push_event(Event* event) @extern("SDL_PushEvent"); + +alias EventFilter = fn bool(void* userdata, Event* event); + +extern fn void set_event_filter(EventFilter filter, void* userdata) @extern("SDL_SetEventFilter"); +extern fn bool get_event_filter(EventFilter *filter, void** userdata) @extern("SDL_GetEventFilter"); +extern fn bool add_event_watch(EventFilter filter, void* userdata) @extern("SDL_AddEventWatch"); +extern fn void remove_event_watch(EventFilter filter, void* userdata) @extern("SDL_RemoveEventWatch"); +extern fn void filter_events(EventFilter filter, void* userdata) @extern("SDL_FilterEvents"); +extern fn void set_event_enabled(uint type, bool enabled) @extern("SDL_SetEventEnabled"); +extern fn bool event_enabled(uint type) @extern("SDL_EventEnabled"); +extern fn uint register_events(int numevents) @extern("SDL_RegisterEvents"); +extern fn Window* get_window_from_event(Event* event) @extern("SDL_GetWindowFromEvent"); + diff --git a/sdl3.c3l/sdl3_gpu.c3i b/sdl3.c3l/sdl3_gpu.c3i new file mode 100644 index 0000000..e6e365e --- /dev/null +++ b/sdl3.c3l/sdl3_gpu.c3i @@ -0,0 +1,861 @@ +module sdl3::sdl; + +/* SDL3_gpu.h ported to C3 */ + +// these are opaque in C +typedef GPUDevice = void; +typedef GPUBuffer = void; +typedef GPUTransferBuffer = void; +typedef GPUTexture = void; +typedef GPUSampler = void; +typedef GPUShader = void; +typedef GPUComputePipeline = void; +typedef GPUGraphicsPipeline = void; +typedef GPUCommandBuffer = void; +typedef GPURenderPass = void; +typedef GPUComputePass = void; +typedef GPUCopyPass = void; +typedef GPUFence = void; + +/* ----- */ +/* Enums */ +/* ----- */ + +enum GPUPrimitiveType : inline CInt { + GPU_PRIMITIVETYPE_TRIANGLELIST, + GPU_PRIMITIVETYPE_TRIANGLESTRIP, + GPU_PRIMITIVETYPE_LINELIST, + GPU_PRIMITIVETYPE_LINESTRIP, + GPU_PRIMITIVETYPE_POINTLIST +} + +enum GPULoadOp : inline CInt { + GPU_LOADOP_LOAD, + GPU_LOADOP_CLEAR, + GPU_LOADOP_DONT_CARE +} + +enum GPUStoreOp : inline CInt { + GPU_STOREOP_STORE, + GPU_STOREOP_DONT_CARE, + GPU_STOREOP_RESOLVE, + GPU_STOREOP_RESOLVE_AND_STORE +} + + +enum GPUIndexElementSize : inline CInt { + GPU_INDEXELEMENTSIZE_16BIT, + GPU_INDEXELEMENTSIZE_32BIT +} + +enum GPUTextureFormat : inline CInt { + GPU_TEXTUREFORMAT_INVALID, + /* Unsigned Normalized Float Color Formats */ + GPU_TEXTUREFORMAT_A8_UNORM, + GPU_TEXTUREFORMAT_R8_UNORM, + GPU_TEXTUREFORMAT_R8G8_UNORM, + GPU_TEXTUREFORMAT_R8G8B8A8_UNORM, + GPU_TEXTUREFORMAT_R16_UNORM, + GPU_TEXTUREFORMAT_R16G16_UNORM, + GPU_TEXTUREFORMAT_R16G16B16A16_UNORM, + GPU_TEXTUREFORMAT_R10G10B10A2_UNORM, + GPU_TEXTUREFORMAT_B5G6R5_UNORM, + GPU_TEXTUREFORMAT_B5G5R5A1_UNORM, + GPU_TEXTUREFORMAT_B4G4R4A4_UNORM, + GPU_TEXTUREFORMAT_B8G8R8A8_UNORM, + /* Compressed Unsigned Normalized Float Color Formats */ + GPU_TEXTUREFORMAT_BC1_RGBA_UNORM, + GPU_TEXTUREFORMAT_BC2_RGBA_UNORM, + GPU_TEXTUREFORMAT_BC3_RGBA_UNORM, + GPU_TEXTUREFORMAT_BC4_R_UNORM, + GPU_TEXTUREFORMAT_BC5_RG_UNORM, + GPU_TEXTUREFORMAT_BC7_RGBA_UNORM, + /* Compressed Signed Float Color Formats */ + GPU_TEXTUREFORMAT_BC6H_RGB_FLOAT, + /* Compressed Unsigned Float Color Formats */ + GPU_TEXTUREFORMAT_BC6H_RGB_UFLOAT, + /* Signed Normalized Float Color Formats */ + GPU_TEXTUREFORMAT_R8_SNORM, + GPU_TEXTUREFORMAT_R8G8_SNORM, + GPU_TEXTUREFORMAT_R8G8B8A8_SNORM, + GPU_TEXTUREFORMAT_R16_SNORM, + GPU_TEXTUREFORMAT_R16G16_SNORM, + GPU_TEXTUREFORMAT_R16G16B16A16_SNORM, + /* Signed Float Color Formats */ + GPU_TEXTUREFORMAT_R16_FLOAT, + GPU_TEXTUREFORMAT_R16G16_FLOAT, + GPU_TEXTUREFORMAT_R16G16B16A16_FLOAT, + GPU_TEXTUREFORMAT_R32_FLOAT, + GPU_TEXTUREFORMAT_R32G32_FLOAT, + GPU_TEXTUREFORMAT_R32G32B32A32_FLOAT, + /* Unsigned Float Color Formats */ + GPU_TEXTUREFORMAT_R11G11B10_UFLOAT, + /* Unsigned Integer Color Formats */ + GPU_TEXTUREFORMAT_R8_UINT, + GPU_TEXTUREFORMAT_R8G8_UINT, + GPU_TEXTUREFORMAT_R8G8B8A8_UINT, + GPU_TEXTUREFORMAT_R16_UINT, + GPU_TEXTUREFORMAT_R16G16_UINT, + GPU_TEXTUREFORMAT_R16G16B16A16_UINT, + GPU_TEXTUREFORMAT_R32_UINT, + GPU_TEXTUREFORMAT_R32G32_UINT, + GPU_TEXTUREFORMAT_R32G32B32A32_UINT, + /* Signed Integer Color Formats */ + GPU_TEXTUREFORMAT_R8_INT, + GPU_TEXTUREFORMAT_R8G8_INT, + GPU_TEXTUREFORMAT_R8G8B8A8_INT, + GPU_TEXTUREFORMAT_R16_INT, + GPU_TEXTUREFORMAT_R16G16_INT, + GPU_TEXTUREFORMAT_R16G16B16A16_INT, + GPU_TEXTUREFORMAT_R32_INT, + GPU_TEXTUREFORMAT_R32G32_INT, + GPU_TEXTUREFORMAT_R32G32B32A32_INT, + /* SRGB Unsigned Normalized Color Formats */ + GPU_TEXTUREFORMAT_R8G8B8A8_UNORM_SRGB, + GPU_TEXTUREFORMAT_B8G8R8A8_UNORM_SRGB, + /* Compressed SRGB Unsigned Normalized Color Formats */ + GPU_TEXTUREFORMAT_BC1_RGBA_UNORM_SRGB, + GPU_TEXTUREFORMAT_BC2_RGBA_UNORM_SRGB, + GPU_TEXTUREFORMAT_BC3_RGBA_UNORM_SRGB, + GPU_TEXTUREFORMAT_BC7_RGBA_UNORM_SRGB, + /* Depth Formats */ + GPU_TEXTUREFORMAT_D16_UNORM, + GPU_TEXTUREFORMAT_D24_UNORM, + GPU_TEXTUREFORMAT_D32_FLOAT, + GPU_TEXTUREFORMAT_D24_UNORM_S8_UINT, + GPU_TEXTUREFORMAT_D32_FLOAT_S8_UINT, + /* Compressed ASTC Normalized Float Color Formats*/ + GPU_TEXTUREFORMAT_ASTC_4X4_UNORM, + GPU_TEXTUREFORMAT_ASTC_5X4_UNORM, + GPU_TEXTUREFORMAT_ASTC_5X5_UNORM, + GPU_TEXTUREFORMAT_ASTC_6X5_UNORM, + GPU_TEXTUREFORMAT_ASTC_6X6_UNORM, + GPU_TEXTUREFORMAT_ASTC_8X5_UNORM, + GPU_TEXTUREFORMAT_ASTC_8X6_UNORM, + GPU_TEXTUREFORMAT_ASTC_8X8_UNORM, + GPU_TEXTUREFORMAT_ASTC_10X5_UNORM, + GPU_TEXTUREFORMAT_ASTC_10X6_UNORM, + GPU_TEXTUREFORMAT_ASTC_10X8_UNORM, + GPU_TEXTUREFORMAT_ASTC_10X10_UNORM, + GPU_TEXTUREFORMAT_ASTC_12X10_UNORM, + GPU_TEXTUREFORMAT_ASTC_12X12_UNORM, + /* Compressed SRGB ASTC Normalized Float Color Formats*/ + GPU_TEXTUREFORMAT_ASTC_4X4_UNORM_SRGB, + GPU_TEXTUREFORMAT_ASTC_5X4_UNORM_SRGB, + GPU_TEXTUREFORMAT_ASTC_5X5_UNORM_SRGB, + GPU_TEXTUREFORMAT_ASTC_6X5_UNORM_SRGB, + GPU_TEXTUREFORMAT_ASTC_6X6_UNORM_SRGB, + GPU_TEXTUREFORMAT_ASTC_8X5_UNORM_SRGB, + GPU_TEXTUREFORMAT_ASTC_8X6_UNORM_SRGB, + GPU_TEXTUREFORMAT_ASTC_8X8_UNORM_SRGB, + GPU_TEXTUREFORMAT_ASTC_10X5_UNORM_SRGB, + GPU_TEXTUREFORMAT_ASTC_10X6_UNORM_SRGB, + GPU_TEXTUREFORMAT_ASTC_10X8_UNORM_SRGB, + GPU_TEXTUREFORMAT_ASTC_10X10_UNORM_SRGB, + GPU_TEXTUREFORMAT_ASTC_12X10_UNORM_SRGB, + GPU_TEXTUREFORMAT_ASTC_12X12_UNORM_SRGB, + /* Compressed ASTC Signed Float Color Formats*/ + GPU_TEXTUREFORMAT_ASTC_4X4_FLOAT, + GPU_TEXTUREFORMAT_ASTC_5X4_FLOAT, + GPU_TEXTUREFORMAT_ASTC_5X5_FLOAT, + GPU_TEXTUREFORMAT_ASTC_6X5_FLOAT, + GPU_TEXTUREFORMAT_ASTC_6X6_FLOAT, + GPU_TEXTUREFORMAT_ASTC_8X5_FLOAT, + GPU_TEXTUREFORMAT_ASTC_8X6_FLOAT, + GPU_TEXTUREFORMAT_ASTC_8X8_FLOAT, + GPU_TEXTUREFORMAT_ASTC_10X5_FLOAT, + GPU_TEXTUREFORMAT_ASTC_10X6_FLOAT, + GPU_TEXTUREFORMAT_ASTC_10X8_FLOAT, + GPU_TEXTUREFORMAT_ASTC_10X10_FLOAT, + GPU_TEXTUREFORMAT_ASTC_12X10_FLOAT, + GPU_TEXTUREFORMAT_ASTC_12X12_FLOAT +} + +typedef GPUTextureUsageFlags = uint; + +const GPUTextureUsageFlags GPU_TEXTUREUSAGE_SAMPLER = (1 << 0); +const GPUTextureUsageFlags GPU_TEXTUREUSAGE_COLOR_TARGET = (1 << 1); +const GPUTextureUsageFlags GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET = (1 << 2); +const GPUTextureUsageFlags GPU_TEXTUREUSAGE_GRAPHICS_STORAGE_READ = (1 << 3); +const GPUTextureUsageFlags GPU_TEXTUREUSAGE_COMPUTE_STORAGE_READ = (1 << 4); +const GPUTextureUsageFlags GPU_TEXTUREUSAGE_COMPUTE_STORAGE_WRITE = (1 << 5); +const GPUTextureUsageFlags GPU_TEXTUREUSAGE_COMPUTE_STORAGE_SIMULTANEOUS_READ_WRITE = (1 << 6); + +enum GPUTextureType : inline CInt { + GPU_TEXTURETYPE_2D, + GPU_TEXTURETYPE_2D_ARRAY, + GPU_TEXTURETYPE_3D, + GPU_TEXTURETYPE_CUBE, + GPU_TEXTURETYPE_CUBE_ARRAY +} + +enum GPUSampleCount : inline CInt { + GPU_SAMPLECOUNT_1, + GPU_SAMPLECOUNT_2, + GPU_SAMPLECOUNT_4, + GPU_SAMPLECOUNT_8 +} + +enum GPUCubeMapFace : inline CInt { + GPU_CUBEMAPFACE_POSITIVEX, + GPU_CUBEMAPFACE_NEGATIVEX, + GPU_CUBEMAPFACE_POSITIVEY, + GPU_CUBEMAPFACE_NEGATIVEY, + GPU_CUBEMAPFACE_POSITIVEZ, + GPU_CUBEMAPFACE_NEGATIVEZ +} + +typedef GPUBufferUsageFlags = uint; + +const GPUBufferUsageFlags GPU_BUFFERUSAGE_VERTEX = (1 << 0); +const GPUBufferUsageFlags GPU_BUFFERUSAGE_INDEX = (1 << 1); +const GPUBufferUsageFlags GPU_BUFFERUSAGE_INDIRECT = (1 << 2); +const GPUBufferUsageFlags GPU_BUFFERUSAGE_GRAPHICS_STORAGE_READ = (1 << 3); +const GPUBufferUsageFlags GPU_BUFFERUSAGE_COMPUTE_STORAGE_READ = (1 << 4); +const GPUBufferUsageFlags GPU_BUFFERUSAGE_COMPUTE_STORAGE_WRITE = (1 << 5); + + +enum GPUTransferBufferUsage : inline CInt { + GPU_TRANSFERBUFFERUSAGE_UPLOAD, + GPU_TRANSFERBUFFERUSAGE_DOWNLOAD +} + +enum GPUShaderStage : inline CInt { + GPU_SHADERSTAGE_VERTEX, + GPU_SHADERSTAGE_FRAGMENT +} + +typedef GPUShaderFormat = uint; +const GPUShaderFormat GPU_SHADERFORMAT_INVALID = 0; +const GPUShaderFormat GPU_SHADERFORMAT_PRIVATE = (1 << 0); +const GPUShaderFormat GPU_SHADERFORMAT_SPIRV = (1 << 1); +const GPUShaderFormat GPU_SHADERFORMAT_DXBC = (1 << 2); +const GPUShaderFormat GPU_SHADERFORMAT_DXIL = (1 << 3); +const GPUShaderFormat GPU_SHADERFORMAT_MSL = (1 << 4); +const GPUShaderFormat GPU_SHADERFORMAT_METALLIB = (1 << 5); + +enum GPUVertexElementFormat : inline CInt { + GPU_VERTEXELEMENTFORMAT_INVALID, + + /* 32-bit Signed Integers */ + GPU_VERTEXELEMENTFORMAT_INT, + GPU_VERTEXELEMENTFORMAT_INT2, + GPU_VERTEXELEMENTFORMAT_INT3, + GPU_VERTEXELEMENTFORMAT_INT4, + + /* 32-bit Unsigned Integers */ + GPU_VERTEXELEMENTFORMAT_UINT, + GPU_VERTEXELEMENTFORMAT_UINT2, + GPU_VERTEXELEMENTFORMAT_UINT3, + GPU_VERTEXELEMENTFORMAT_UINT4, + + /* 32-bit Floats */ + GPU_VERTEXELEMENTFORMAT_FLOAT, + GPU_VERTEXELEMENTFORMAT_FLOAT2, + GPU_VERTEXELEMENTFORMAT_FLOAT3, + GPU_VERTEXELEMENTFORMAT_FLOAT4, + + /* 8-bit Signed Integers */ + GPU_VERTEXELEMENTFORMAT_BYTE2, + GPU_VERTEXELEMENTFORMAT_BYTE4, + + /* 8-bit Unsigned Integers */ + GPU_VERTEXELEMENTFORMAT_UBYTE2, + GPU_VERTEXELEMENTFORMAT_UBYTE4, + + /* 8-bit Signed Normalized */ + GPU_VERTEXELEMENTFORMAT_BYTE2_NORM, + GPU_VERTEXELEMENTFORMAT_BYTE4_NORM, + + /* 8-bit Unsigned Normalized */ + GPU_VERTEXELEMENTFORMAT_UBYTE2_NORM, + GPU_VERTEXELEMENTFORMAT_UBYTE4_NORM, + + /* 16-bit Signed Integers */ + GPU_VERTEXELEMENTFORMAT_SHORT2, + GPU_VERTEXELEMENTFORMAT_SHORT4, + + /* 16-bit Unsigned Integers */ + GPU_VERTEXELEMENTFORMAT_USHORT2, + GPU_VERTEXELEMENTFORMAT_USHORT4, + + /* 16-bit Signed Normalized */ + GPU_VERTEXELEMENTFORMAT_SHORT2_NORM, + GPU_VERTEXELEMENTFORMAT_SHORT4_NORM, + + /* 16-bit Unsigned Normalized */ + GPU_VERTEXELEMENTFORMAT_USHORT2_NORM, + GPU_VERTEXELEMENTFORMAT_USHORT4_NORM, + + /* 16-bit Floats */ + GPU_VERTEXELEMENTFORMAT_HALF2, + GPU_VERTEXELEMENTFORMAT_HALF4 +} + +enum GPUVertexInputRate : inline CInt { + GPU_VERTEXINPUTRATE_VERTEX, + GPU_VERTEXINPUTRATE_INSTANCE +} + +enum GPUFillMode : inline CInt { + GPU_FILLMODE_FILL, + GPU_FILLMODE_LINE +} + +enum GPUCullMode : inline CInt { + GPU_CULLMODE_NONE, + GPU_CULLMODE_FRONT, + GPU_CULLMODE_BACK +} + +enum GPUFrontFace : inline CInt { + GPU_FRONTFACE_COUNTER_CLOCKWISE, + GPU_FRONTFACE_CLOCKWISE +} + +enum GPUCompareOp : inline CInt { + GPU_COMPAREOP_INVALID, + GPU_COMPAREOP_NEVER, + GPU_COMPAREOP_LESS, + GPU_COMPAREOP_EQUAL, + GPU_COMPAREOP_LESS_OR_EQUAL, + GPU_COMPAREOP_GREATER, + GPU_COMPAREOP_NOT_EQUAL, + GPU_COMPAREOP_GREATER_OR_EQUAL, + GPU_COMPAREOP_ALWAYS +} + +enum GPUStencilOp : inline CInt { + GPU_STENCILOP_INVALID, + GPU_STENCILOP_KEEP, + GPU_STENCILOP_ZERO, + GPU_STENCILOP_REPLACE, + GPU_STENCILOP_INCREMENT_AND_CLAMP, + GPU_STENCILOP_DECREMENT_AND_CLAMP, + GPU_STENCILOP_INVERT, + GPU_STENCILOP_INCREMENT_AND_WRAP, + GPU_STENCILOP_DECREMENT_AND_WRAP +} + +enum GPUBlendOp : inline CInt +{ + GPU_BLENDOP_INVALID, + GPU_BLENDOP_ADD, + GPU_BLENDOP_SUBTRACT, + GPU_BLENDOP_REVERSE_SUBTRACT, + GPU_BLENDOP_MIN, + GPU_BLENDOP_MAX +} + +enum GPUBlendFactor : inline CInt { + GPU_BLENDFACTOR_INVALID, + GPU_BLENDFACTOR_ZERO, + GPU_BLENDFACTOR_ONE, + GPU_BLENDFACTOR_SRC_COLOR, + GPU_BLENDFACTOR_ONE_MINUS_SRC_COLOR, + GPU_BLENDFACTOR_DST_COLOR, + GPU_BLENDFACTOR_ONE_MINUS_DST_COLOR, + GPU_BLENDFACTOR_SRC_ALPHA, + GPU_BLENDFACTOR_ONE_MINUS_SRC_ALPHA, + GPU_BLENDFACTOR_DST_ALPHA, + GPU_BLENDFACTOR_ONE_MINUS_DST_ALPHA, + GPU_BLENDFACTOR_CONSTANT_COLOR, + GPU_BLENDFACTOR_ONE_MINUS_CONSTANT_COLOR, + GPU_BLENDFACTOR_SRC_ALPHA_SATURATE +} + +typedef GPUColorComponentFlags = char; +const GPUColorComponentFlags GPU_COLORCOMPONENT_R = (1 << 0); +const GPUColorComponentFlags GPU_COLORCOMPONENT_G = (1 << 1); +const GPUColorComponentFlags GPU_COLORCOMPONENT_B = (1 << 2); +const GPUColorComponentFlags GPU_COLORCOMPONENT_A = (1 << 3); + +enum GPUFilter : inline CInt { + GPU_FILTER_NEAREST, + GPU_FILTER_LINEAR +} + +enum GPUSamplerMipmapMode : inline CInt { + GPU_SAMPLERMIPMAPMODE_NEAREST, + GPU_SAMPLERMIPMAPMODE_LINEAR +} + +enum GPUSamplerAddressMode : inline CInt { + GPU_SAMPLERADDRESSMODE_REPEAT, + GPU_SAMPLERADDRESSMODE_MIRRORED_REPEAT, + GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE +} + +enum GPUPresentMode : inline CInt { + GPU_PRESENTMODE_VSYNC, + GPU_PRESENTMODE_IMMEDIATE, + GPU_PRESENTMODE_MAILBOX +} + +enum GPUSwapchainComposition : inline CInt { + GPU_SWAPCHAINCOMPOSITION_SDR, + GPU_SWAPCHAINCOMPOSITION_SDR_LINEAR, + GPU_SWAPCHAINCOMPOSITION_HDR_EXTENDED_LINEAR, + GPU_SWAPCHAINCOMPOSITION_HDR10_ST2084 +} + +/* ---------- */ +/* Structures */ +/* ---------- */ + +struct GPUViewport { + float x; + float y; + float w; + float h; + float min_depth; + float max_depth; +} + +struct GPUTextureTransferInfo { + GPUTransferBuffer* transfer_buffer; + uint offset; + uint pixels_per_row; + uint rows_per_layer; +} + +struct GPUTransferBufferLocation { + GPUTransferBuffer* transfer_buffer; + uint offset; +} + +struct GPUTextureLocation { + GPUTexture* texture; + uint mip_level; + uint layer; + uint x; + uint y; + uint z; +} + +struct GPUTextureRegion { + GPUTexture* texture; + uint mip_level; + uint layer; + uint x; + uint y; + uint z; + uint w; + uint h; + uint d; +} + +struct GPUBlitRegion { + GPUTexture* texture; + uint mip_level; + uint layer_or_depth_plane; + uint x; + uint y; + uint w; + uint h; +} + +struct GPUBufferLocation { + GPUBuffer* buffer; + uint offset; +} + +struct GPUBufferRegion { + GPUBuffer* buffer; + uint offset; + uint size; +} + +struct GPUIndirectDrawCommand { + uint num_vertices; + uint num_instances; + uint first_vertex; + uint first_instance; +} + +struct GPUIndexedIndirectDrawCommand { + uint num_indices; + uint num_instances; + uint first_index; + int vertex_offset; + uint first_instance; +} + +struct GPUIndirectDispatchCommand { + uint groupcount_x; + uint groupcount_y; + uint groupcount_z; +} + +struct GPUSamplerCreateInfo { + GPUFilter min_filter; + GPUFilter mag_filter; + GPUSamplerMipmapMode mipmap_mode; + GPUSamplerAddressMode address_mode_u; + GPUSamplerAddressMode address_mode_v; + GPUSamplerAddressMode address_mode_w; + float mip_lod_bias; + float max_anisotropy; + GPUCompareOp compare_op; + float min_lod; + float max_lod; + bool enable_anisotropy; + bool enable_compare; + char padding1; + char padding2; + PropertiesID props; +} + +struct GPUVertexBufferDescription { + uint slot; + uint pitch; + GPUVertexInputRate input_rate; + uint instance_step_rate; +} + +struct GPUVertexAttribute { + uint location; + uint buffer_slot; + GPUVertexElementFormat format; + uint offset; +} + +struct GPUVertexInputState { + GPUVertexBufferDescription* vertex_buffer_descriptions; + uint num_vertex_buffers; + GPUVertexAttribute* vertex_attributes; + uint num_vertex_attributes; +} + +struct GPUStencilOpState { + GPUStencilOp fail_op; + GPUStencilOp pass_op; + GPUStencilOp depth_fail_op; + GPUCompareOp compare_op; +} + +struct GPUColorTargetBlendState { + GPUBlendFactor src_color_blendfactor; + GPUBlendFactor dst_color_blendfactor; + GPUBlendOp color_blend_op; + GPUBlendFactor src_alpha_blendfactor; + GPUBlendFactor dst_alpha_blendfactor; + GPUBlendOp alpha_blend_op; + GPUColorComponentFlags color_write_mask; + bool enable_blend; + bool enable_color_write_mask; + char padding1; + char padding2; +} + + +struct GPUShaderCreateInfo { + isz code_size; + char* code; + ZString entrypoint; + GPUShaderFormat format; + GPUShaderStage stage; + uint num_samplers; + uint num_storage_textures; + uint num_storage_buffers; + uint num_uniform_buffers; + PropertiesID props; +} + +struct GPUTextureCreateInfo { + GPUTextureType type; + GPUTextureFormat format; + GPUTextureUsageFlags usage; + uint width; + uint height; + uint layer_count_or_depth; + uint num_levels; + GPUSampleCount sample_count; + PropertiesID props; +} + +struct GPUBufferCreateInfo { + GPUBufferUsageFlags usage; + uint size; + PropertiesID props; +} + +struct GPUTransferBufferCreateInfo { + GPUTransferBufferUsage usage; + uint size; + PropertiesID props; +} + +struct GPURasterizerState { + GPUFillMode fill_mode; + GPUCullMode cull_mode; + GPUFrontFace front_face; + float depth_bias_constant_factor; + float depth_bias_clamp; + float depth_bias_slope_factor; + bool enable_depth_bias; + bool enable_depth_clip; + char padding1; + char padding2; +} + +struct GPUMultisampleState { + GPUSampleCount sample_count; + uint sample_mask; + bool enable_mask; + char padding1; + char padding2; + char padding3; +} + +struct GPUDepthStencilState { + GPUCompareOp compare_op; + GPUStencilOpState back_stencil_state; + GPUStencilOpState front_stencil_state; + char compare_mask; + char write_mask; + bool enable_depth_test; + bool enable_depth_write; + bool enable_stencil_test; + char padding1; + char padding2; + char padding3; +} + +struct GPUColorTargetDescription { + GPUTextureFormat format; + GPUColorTargetBlendState blend_state; +} + +struct GPUGraphicsPipelineTargetInfo { + GPUColorTargetDescription* color_target_descriptions; + uint num_color_targets; + GPUTextureFormat depth_stencil_format; + bool has_depth_stencil_target; + char padding1; + char padding2; + char padding3; +} + +struct GPUGraphicsPipelineCreateInfo { + GPUShader* vertex_shader; + GPUShader* fragment_shader; + GPUVertexInputState vertex_input_state; + GPUPrimitiveType primitive_type; + GPURasterizerState rasterizer_state; + GPUMultisampleState multisample_state; + GPUDepthStencilState depth_stencil_state; + GPUGraphicsPipelineTargetInfo target_info; + PropertiesID props; +} + +struct GPUComputePipelineCreateInfo { + isz code_size; + char* code; + char* entrypoint; + GPUShaderFormat format; + uint num_samplers; + uint num_readonly_storage_textures; + uint num_readonly_storage_buffers; + uint num_readwrite_storage_textures; + uint num_readwrite_storage_buffers; + uint num_uniform_buffers; + uint threadcount_x; + uint threadcount_y; + uint threadcount_z; + PropertiesID props; +} + +struct GPUColorTargetInfo { + GPUTexture* texture; + uint mip_level; + uint layer_or_depth_plane; + FColor clear_color; + GPULoadOp load_op; + GPUStoreOp store_op; + GPUTexture *resolve_texture; + uint resolve_mip_level; + uint resolve_layer; + bool cycle; + bool cycle_resolve_texture; + char padding1; + char padding2; +} + +struct GPUDepthStencilTargetInfo { + GPUTexture* texture; + float clear_depth; + GPULoadOp load_op; + GPUStoreOp store_op; + GPULoadOp stencil_load_op; + GPUStoreOp stencil_store_op; + bool cycle; + char clear_stencil; + char padding1; + char padding2; +} + +struct GPUBlitInfo { + GPUBlitRegion source; + GPUBlitRegion destination; + GPULoadOp load_op; + FColor clear_color; + FlipMode flip_mode; + GPUFilter filter; + bool cycle; + char padding1; + char padding2; + char padding3; +} + +struct GPUBufferBinding { + GPUBuffer* buffer; + uint offset; +} + +struct GPUTextureSamplerBinding { + GPUTexture* texture; + GPUSampler* sampler; +} + +struct SDL_GPUStorageBufferReadWriteBinding { + GPUBuffer* buffer; + bool cycle; + char padding1; + char padding2; + char padding3; +} + +struct GPUStorageTextureReadWriteBinding { + GPUTexture* texture; + uint mip_level; + uint layer; + bool cycle; + char padding1; + char padding2; + char padding3; +} + +/* --------- */ +/* Functions */ +/* --------- */ + +const ZString PROP_GPU_DEVICE_CREATE_DEBUGMODE_BOOLEAN = "SDL.gpu.device.create.debugmode"; +const ZString PROP_GPU_DEVICE_CREATE_PREFERLOWPOWER_BOOLEAN = "SDL.gpu.device.create.preferlowpower"; +const ZString PROP_GPU_DEVICE_CREATE_NAME_STRING = "SDL.gpu.device.create.name"; +const ZString PROP_GPU_DEVICE_CREATE_SHADERS_PRIVATE_BOOLEAN = "SDL.gpu.device.create.shaders.private"; +const ZString PROP_GPU_DEVICE_CREATE_SHADERS_SPIRV_BOOLEAN = "SDL.gpu.device.create.shaders.spirv"; +const ZString PROP_GPU_DEVICE_CREATE_SHADERS_DXBC_BOOLEAN = "SDL.gpu.device.create.shaders.dxbc"; +const ZString PROP_GPU_DEVICE_CREATE_SHADERS_DXIL_BOOLEAN = "SDL.gpu.device.create.shaders.dxil"; +const ZString PROP_GPU_DEVICE_CREATE_SHADERS_MSL_BOOLEAN = "SDL.gpu.device.create.shaders.msl"; +const ZString PROP_GPU_DEVICE_CREATE_SHADERS_METALLIB_BOOLEAN = "SDL.gpu.device.create.shaders.metallib"; +const ZString PROP_GPU_DEVICE_CREATE_D3D12_SEMANTIC_NAME_STRING = "SDL.gpu.device.create.d3d12.semantic"; +const ZString PROP_GPU_COMPUTEPIPELINE_CREATE_NAME_STRING = "SDL.gpu.computepipeline.create.name"; +const ZString PROP_GPU_GRAPHICSPIPELINE_CREATE_NAME_STRING = "SDL.gpu.graphicspipeline.create.name"; +const ZString PROP_GPU_SAMPLER_CREATE_NAME_STRING = "SDL.gpu.sampler.create.name"; +const ZString PROP_GPU_SHADER_CREATE_NAME_STRING = "SDL.gpu.shader.create.name"; +const ZString PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_R_FLOAT = "SDL.gpu.texture.create.d3d12.clear.r"; +const ZString PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_G_FLOAT = "SDL.gpu.texture.create.d3d12.clear.g"; +const ZString PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_B_FLOAT = "SDL.gpu.texture.create.d3d12.clear.b"; +const ZString PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_A_FLOAT = "SDL.gpu.texture.create.d3d12.clear.a"; +const ZString PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_DEPTH_FLOAT = "SDL.gpu.texture.create.d3d12.clear.depth"; +const ZString PROP_GPU_TEXTURE_CREATE_D3D12_CLEAR_STENCIL_NUMBER = "SDL.gpu.texture.create.d3d12.clear.stencil"; +const ZString PROP_GPU_TEXTURE_CREATE_NAME_STRING = "SDL.gpu.texture.create.name"; +const ZString PROP_GPU_BUFFER_CREATE_NAME_STRING = "SDL.gpu.buffer.create.name"; +const ZString PROP_GPU_TRANSFERBUFFER_CREATE_NAME_STRING = "SDL.gpu.transferbuffer.create.name"; + + +extern fn bool gpu_supports_shader_formats(GPUShaderFormat format_flags, ZString name) @extern("SDL_GPUSupportsShaderFormats"); +extern fn bool gpu_supports_properties(PropertiesID props) @extern("SDL_GPUSupportsProperties"); +extern fn GPUDevice* create_gpu_device(GPUShaderFormat format_flags, bool debug_mode, ZString name) @extern("SDL_CreateGPUDevice"); +extern fn GPUDevice* create_gpu_device_with_properties(PropertiesID props) @extern("SDL_CreateGPUDeviceWithProperties"); +extern fn void destroy_gpu_device(GPUDevice* device) @extern("SDL_DestroyGPUDevice"); +extern fn int get_num_gpu_drivers() @extern("SDL_GetNumGPUDrivers"); +extern fn ZString get_gpu_driver(int index) @extern("SDL_GetGPUDriver"); +extern fn ZString get_gpu_device_driver(GPUDevice* device) @extern("SDL_GetGPUDeviceDriver"); +extern fn GPUShaderFormat get_gpu_shader_formats(GPUDevice* device) @extern("SDL_GetGPUShaderFormats"); +extern fn GPUComputePipeline* create_gpu_compute_pipeline(GPUDevice* device, GPUComputePipelineCreateInfo* createinfo) @extern("SDL_CreateGPUComputePipeline"); +extern fn GPUGraphicsPipeline* create_gpu_graphics_pipeline(GPUDevice* device, GPUGraphicsPipelineCreateInfo* createinfo) @extern("SDL_CreateGPUGraphicsPipeline"); +extern fn GPUSampler* create_gpu_sampler(GPUDevice* device, GPUSamplerCreateInfo* createinfo) @extern("SDL_CreateGPUSampler"); +extern fn GPUShader* create_gpu_shader(GPUDevice* device, GPUShaderCreateInfo* createinfo) @extern("SDL_CreateGPUShader"); +extern fn GPUTexture* create_gpu_texture(GPUDevice* device, GPUTextureCreateInfo* createinfo) @extern("SDL_CreateGPUTexture"); +extern fn GPUBuffer* create_gpu_buffer(GPUDevice* device, GPUBufferCreateInfo* createinfo) @extern("SDL_CreateGPUBuffer"); +extern fn GPUTransferBuffer* create_gpu_transfer_buffer(GPUDevice* device, GPUTransferBufferCreateInfo *createinfo) @extern("SDL_CreateGPUTransferBuffer"); +extern fn void set_gpu_buffer_name(GPUDevice* device, GPUBuffer* buffer, ZString text) @extern("SDL_SetGPUBufferName"); +extern fn void set_gpu_texture_name(GPUDevice* device, GPUTexture* texture, ZString text) @extern("SDL_SetGPUTextureName"); +extern fn void insert_gpu_debug_label(GPUCommandBuffer* command_buffer, ZString text) @extern("SDL_InsertGPUDebugLabel"); +extern fn void push_gpu_debug_group(GPUCommandBuffer* command_buffer, ZString name) @extern("SDL_PushGPUDebugGroup"); +extern fn void pop_gpu_debug_group(GPUCommandBuffer* command_buffer) @extern("SDL_PopGPUDebugGroup"); +extern fn void release_gpu_texture(GPUDevice* device, GPUTexture* texture) @extern("SDL_ReleaseGPUTexture"); +extern fn void release_gpu_sampler(GPUDevice* device, GPUSampler* sampler) @extern("SDL_ReleaseGPUSampler"); +extern fn void release_gpu_buffer(GPUDevice* device, GPUBuffer* buffer) @extern("SDL_ReleaseGPUBuffer"); +extern fn void release_gpu_transfer_buffer(GPUDevice* device, GPUTransferBuffer* transfer_buffer) @extern("SDL_ReleaseGPUTransferBuffer"); +extern fn void release_gpu_compute_pipeline(GPUDevice* device, GPUComputePipeline* compute_pipeline) @extern("SDL_ReleaseGPUComputePipeline"); +extern fn void release_gpu_shader(GPUDevice* device, GPUShader* shader) @extern("SDL_ReleaseGPUShader"); +extern fn void release_gpu_graphics_pipeline(GPUDevice* device, GPUGraphicsPipeline* graphics_pipeline) @extern("SDL_ReleaseGPUGraphicsPipeline"); +extern fn GPUCommandBuffer* acquire_gpu_command_buffer(GPUDevice* device) @extern("SDL_AcquireGPUCommandBuffer"); +extern fn void push_gpu_vertex_uniform_data(GPUCommandBuffer* command_buffer, uint slot_index, void* data, uint length) @extern("SDL_PushGPUVertexUniformData"); +extern fn void push_gpu_fragment_uniform_data(GPUCommandBuffer* command_buffer, uint slot_index, void* data, uint length) @extern("SDL_PushGPUFragmentUniformData"); +extern fn void push_gpu_compute_uniform_data(GPUCommandBuffer* command_buffer, uint slot_index, void* data, uint length) @extern("SDL_PushGPUComputeUniformData"); +extern fn GPURenderPass* begin_gpu_render_pass(GPUCommandBuffer* command_buffer, GPUColorTargetInfo* color_target_infos, uint num_color_targets, GPUDepthStencilTargetInfo* depth_stencil_target_info) @extern("SDL_BeginGPURenderPass"); +extern fn void bind_gpu_graphics_pipeline(GPURenderPass* render_pass, GPUGraphicsPipeline* graphics_pipeline) @extern("SDL_BindGPUGraphicsPipeline"); +extern fn void set_gpu_viewport(GPURenderPass* render_pass, GPUViewport* viewport) @extern("SDL_SetGPUViewport"); +extern fn void set_gpu_scissor(GPURenderPass* render_pass, Rect* scissor) @extern("SDL_SetGPUScissor"); +extern fn void set_gpu_blend_constants(GPURenderPass* render_pass, FColor blend_constants) @extern("SDL_SetGPUBlendConstants"); +extern fn void set_gpu_stencil_reference(GPURenderPass* render_pass, char reference) @extern("SDL_SetGPUStencilReference"); +extern fn void bind_gpu_vertex_buffers(GPURenderPass* render_pass, uint first_slot, GPUBufferBinding* bindings, uint num_bindings) @extern("SDL_BindGPUVertexBuffers"); +extern fn void bind_gpu_index_buffer(GPURenderPass* render_pass, GPUBufferBinding* binding, GPUIndexElementSize index_element_size) @extern("SDL_BindGPUIndexBuffer"); +extern fn void bind_gpu_vertex_samplers(GPURenderPass* render_pass, uint first_slot, GPUTextureSamplerBinding* texture_sampler_bindings, uint num_bindings) @extern("SDL_BindGPUVertexSamplers"); +extern fn void bind_gpu_vertex_storage_textures(GPURenderPass* render_pass, uint first_slot,GPUTexture* *storage_textures, uint num_bindings) @extern("SDL_BindGPUVertexStorageTextures"); +extern fn void bind_gpu_vertex_storage_buffers(GPURenderPass* render_pass, uint first_slot,GPUBuffer* *storage_buffers, uint num_bindings) @extern("SDL_BindGPUVertexStorageBuffers"); +extern fn void bind_gpu_fragment_samplers(GPURenderPass* render_pass, uint first_slot, GPUTextureSamplerBinding* texture_sampler_bindings, uint num_bindings) @extern("SDL_BindGPUFragmentSamplers"); +extern fn void bind_gpu_fragment_storage_textures(GPURenderPass* render_pass, uint first_slot,GPUTexture* *storage_textures, uint num_bindings) @extern("SDL_BindGPUFragmentStorageTextures"); +extern fn void bind_gpu_fragment_storage_buffers(GPURenderPass* render_pass, uint first_slot,GPUBuffer* *storage_buffers, uint num_bindings) @extern("SDL_BindGPUFragmentStorageBuffers"); +extern fn void draw_gpu_indexed_primitives(GPURenderPass* render_pass, uint num_indices, uint num_instances, uint first_index, int vertex_offset, uint first_instance) @extern("SDL_DrawGPUIndexedPrimitives"); +extern fn void draw_gpu_primitives(GPURenderPass* render_pass, uint num_vertices, uint num_instances, uint first_vertex, uint first_instance) @extern("SDL_DrawGPUPrimitives"); +extern fn void draw_gpu_primitives_indirect(GPURenderPass* render_pass,GPUBuffer* buffer, uint offset, uint draw_count) @extern("SDL_DrawGPUPrimitivesIndirect"); +extern fn void draw_gpu_indexed_primitives_indirect(GPURenderPass* render_pass,GPUBuffer* buffer, uint offset, uint draw_count) @extern("SDL_DrawGPUIndexedPrimitivesIndirect"); +extern fn void end_gpu_render_pass(GPURenderPass* render_pass) @extern("SDL_EndGPURenderPass"); +extern fn GPUComputePass* begin_gpu_compute_pass(GPUCommandBuffer* command_buffer, GPUStorageTextureReadWriteBinding* storage_texture_bindings, uint num_storage_texture_bindings, SDL_GPUStorageBufferReadWriteBinding *storage_buffer_bindings, uint num_storage_buffer_bindings) @extern("SDL_BeginGPUComputePass"); +extern fn void bind_gpu_compute_pipeline(GPUComputePass* compute_pass, GPUComputePipeline* compute_pipeline) @extern("SDL_BindGPUComputePipeline"); +extern fn void bind_gpu_compute_samplers(GPUComputePass* compute_pass, uint first_slot, GPUTextureSamplerBinding* texture_sampler_bindings, uint num_bindings) @extern("SDL_BindGPUComputeSamplers"); +extern fn void bind_gpu_compute_storage_textures(GPUComputePass* compute_pass, uint first_slot, GPUTexture* *storage_textures, uint num_bindings) @extern("SDL_BindGPUComputeStorageTextures"); +extern fn void bind_gpu_compute_storage_buffers(GPUComputePass* compute_pass, uint first_slot, GPUBuffer* *storage_buffers, uint num_bindings) @extern("SDL_BindGPUComputeStorageBuffers"); +extern fn void dispatch_gpu_compute(GPUComputePass* compute_pass, uint groupcount_x, uint groupcount_y, uint groupcount_z) @extern("SDL_DispatchGPUCompute"); +extern fn void dispatch_gpu_compute_indirect(GPUComputePass* compute_pass, GPUBuffer* buffer, uint offset) @extern("SDL_DispatchGPUComputeIndirect"); +extern fn void end_gpu_compute_pass(GPUComputePass* compute_pass) @extern("SDL_EndGPUComputePass"); +extern fn void* map_gpu_transfer_buffer(GPUDevice* device, GPUTransferBuffer* transfer_buffer,bool cycle) @extern("SDL_MapGPUTransferBuffer"); +extern fn void unmap_gpu_transfer_buffer(GPUDevice* device, GPUTransferBuffer* transfer_buffer) @extern("SDL_UnmapGPUTransferBuffer"); +extern fn GPUCopyPass* begin_gpu_copy_pass(GPUCommandBuffer* command_buffer) @extern("SDL_BeginGPUCopyPass"); +extern fn void upload_to_gpu_texture(GPUCopyPass* copy_pass, GPUTextureTransferInfo* source, GPUTextureRegion* destination,bool cycle) @extern("SDL_UploadToGPUTexture"); +extern fn void upload_to_gpu_buffer(GPUCopyPass* copy_pass, GPUTransferBufferLocation* source, GPUBufferRegion* destination,bool cycle) @extern("SDL_UploadToGPUBuffer"); +extern fn void copy_gpu_texture_to_texture(GPUCopyPass* copy_pass, GPUTextureLocation* source, GPUTextureLocation* destination, uint w, uint h, uint d,bool cycle) @extern("SDL_CopyGPUTextureToTexture"); +extern fn void copy_gpu_buffer_to_buffer(GPUCopyPass* copy_pass, GPUBufferLocation* source, GPUBufferLocation* destination, uint size,bool cycle) @extern("SDL_CopyGPUBufferToBuffer"); +extern fn void download_from_gpu_texture(GPUCopyPass* copy_pass, GPUTextureRegion* source, GPUTextureTransferInfo* destination) @extern("SDL_DownloadFromGPUTexture"); +extern fn void download_from_gpu_buffer(GPUCopyPass* copy_pass, GPUBufferRegion* source, GPUTransferBufferLocation* destination) @extern("SDL_DownloadFromGPUBuffer"); +extern fn void end_gpu_copy_pass(GPUCopyPass* copy_pass) @extern("SDL_EndGPUCopyPass"); +extern fn void generate_mipmaps_for_gpu_texture(GPUCommandBuffer* command_buffer,GPUTexture* texture) @extern("SDL_GenerateMipmapsForGPUTexture"); +extern fn void blit_gpu_texture(GPUCommandBuffer* command_buffer, GPUBlitInfo* info) @extern("SDL_BlitGPUTexture"); +extern fn bool window_supports_gpu_swapchain_composition(GPUDevice* device, Window* window, GPUSwapchainComposition swapchain_composition) @extern("SDL_WindowSupportsGPUSwapchainComposition"); +extern fn bool window_supports_gpu_present_mode(GPUDevice* device, Window* window, GPUPresentMode present_mode) @extern("SDL_WindowSupportsGPUPresentMode"); +extern fn bool claim_window_for_gpu_device(GPUDevice* device, Window* window) @extern("SDL_ClaimWindowForGPUDevice"); +extern fn void release_window_from_gpu_device(GPUDevice* device, Window* window) @extern("SDL_ReleaseWindowFromGPUDevice"); +extern fn bool set_gpu_swapchain_parameters(GPUDevice* device, Window* window, GPUSwapchainComposition swapchain_composition, GPUPresentMode present_mode) @extern("SDL_SetGPUSwapchainParameters"); +extern fn bool set_gpu_allowed_frames_in_flight(GPUDevice* device, uint allowed_frames_in_flight) @extern("SDL_SetGPUAllowedFramesInFlight"); +extern fn GPUTextureFormat get_gpu_swapchain_texture_format(GPUDevice* device, Window* window) @extern("SDL_GetGPUSwapchainTextureFormat"); +extern fn bool acquire_gpu_swapchain_texture(GPUCommandBuffer* command_buffer,Window* window,GPUTexture* *swapchain_texture, uint *swapchain_texture_width, uint *swapchain_texture_height) @extern("SDL_AcquireGPUSwapchainTexture"); +extern fn bool wait_for_gpu_swapchain(GPUDevice* device, Window* window) @extern("SDL_WaitForGPUSwapchain"); +extern fn bool wait_and_acquire_gpu_swapchain_texture(GPUCommandBuffer* command_buffer,Window* window,GPUTexture* *swapchain_texture, uint *swapchain_texture_width, uint *swapchain_texture_height) @extern("SDL_WaitAndAcquireGPUSwapchainTexture"); +extern fn bool submit_gpu_command_buffer(GPUCommandBuffer* command_buffer) @extern("SDL_SubmitGPUCommandBuffer"); +extern fn GPUFence* submit_gpu_command_buffer_and_acquire_fence(GPUCommandBuffer* command_buffer) @extern("SDL_SubmitGPUCommandBufferAndAcquireFence"); +extern fn bool cancel_gpu_command_buffer(GPUCommandBuffer* command_buffer) @extern("SDL_CancelGPUCommandBuffer"); +extern fn bool wait_for_gpu_idle(GPUDevice* device) @extern("SDL_WaitForGPUIdle"); +extern fn bool wait_for_gpu_fences(GPUDevice* device, bool wait_all,GPUFence* *fences, uint num_fences) @extern("SDL_WaitForGPUFences"); +extern fn bool query_gpu_fence(GPUDevice* device, GPUFence* fence) @extern("SDL_QueryGPUFence"); +extern fn void release_gpu_fence(GPUDevice* device, GPUFence* fence) @extern("SDL_ReleaseGPUFence"); +extern fn uint gpu_texture_format_texel_block_size(GPUTextureFormat format) @extern("GPUTextureFormatTexelBlockSize"); +extern fn bool gpu_texture_supports_format(GPUDevice* device, GPUTextureFormat format, GPUTextureType type, GPUTextureUsageFlags usage) @extern("SDL_GPUTextureSupportsFormat"); +extern fn bool gpu_texture_supports_sample_count(GPUDevice* device, GPUTextureFormat format, GPUSampleCount sample_count) @extern("SDL_GPUTextureSupportsSampleCount"); +extern fn uint calculate_gpu_texture_format_size(GPUTextureFormat format, uint width, uint height, uint depth_or_layer_count) @extern("SDL_CalculateGPUTextureFormatSize"); + + diff --git a/sdl3.c3l/sdl3_hints.c3i b/sdl3.c3l/sdl3_hints.c3i new file mode 100644 index 0000000..50490c7 --- /dev/null +++ b/sdl3.c3l/sdl3_hints.c3i @@ -0,0 +1,260 @@ + +module sdl3::sdl; + +const ZString HINT_ALLOW_ALT_TAB_WHILE_GRABBED = "SDL_ALLOW_ALT_TAB_WHILE_GRABBED"; +const ZString HINT_ANDROID_ALLOW_RECREATE_ACTIVITY = "SDL_ANDROID_ALLOW_RECREATE_ACTIVITY"; +const ZString HINT_ANDROID_BLOCK_ON_PAUSE = "SDL_ANDROID_BLOCK_ON_PAUSE"; +const ZString HINT_ANDROID_LOW_LATENCY_AUDIO = "SDL_ANDROID_LOW_LATENCY_AUDIO"; +const ZString HINT_ANDROID_TRAP_BACK_BUTTON = "SDL_ANDROID_TRAP_BACK_BUTTON"; +const ZString HINT_APP_ID = "SDL_APP_ID"; +const ZString HINT_APP_NAME = "SDL_APP_NAME"; +const ZString HINT_APPLE_TV_CONTROLLER_UI_EVENTS = "SDL_APPLE_TV_CONTROLLER_UI_EVENTS"; +const ZString HINT_APPLE_TV_REMOTE_ALLOW_ROTATION = "SDL_APPLE_TV_REMOTE_ALLOW_ROTATION"; +const ZString HINT_AUDIO_ALSA_DEFAULT_DEVICE = "SDL_AUDIO_ALSA_DEFAULT_DEVICE"; +const ZString HINT_AUDIO_ALSA_DEFAULT_PLAYBACK_DEVICE = "SDL_AUDIO_ALSA_DEFAULT_PLAYBACK_DEVICE"; +const ZString HINT_AUDIO_ALSA_DEFAULT_RECORDING_DEVICE = "SDL_AUDIO_ALSA_DEFAULT_RECORDING_DEVICE"; +const ZString HINT_AUDIO_CATEGORY = "SDL_AUDIO_CATEGORY"; +const ZString HINT_AUDIO_CHANNELS = "SDL_AUDIO_CHANNELS"; +const ZString HINT_AUDIO_DEVICE_APP_ICON_NAME = "SDL_AUDIO_DEVICE_APP_ICON_NAME"; +const ZString HINT_AUDIO_DEVICE_SAMPLE_FRAMES = "SDL_AUDIO_DEVICE_SAMPLE_FRAMES"; +const ZString HINT_AUDIO_DEVICE_STREAM_NAME = "SDL_AUDIO_DEVICE_STREAM_NAME"; +const ZString HINT_AUDIO_DEVICE_STREAM_ROLE = "SDL_AUDIO_DEVICE_STREAM_ROLE"; +const ZString HINT_AUDIO_DISK_INPUT_FILE = "SDL_AUDIO_DISK_INPUT_FILE"; +const ZString HINT_AUDIO_DISK_OUTPUT_FILE = "SDL_AUDIO_DISK_OUTPUT_FILE"; +const ZString HINT_AUDIO_DISK_TIMESCALE = "SDL_AUDIO_DISK_TIMESCALE"; +const ZString HINT_AUDIO_DRIVER = "SDL_AUDIO_DRIVER"; +const ZString HINT_AUDIO_DUMMY_TIMESCALE = "SDL_AUDIO_DUMMY_TIMESCALE"; +const ZString HINT_AUDIO_FORMAT = "SDL_AUDIO_FORMAT"; +const ZString HINT_AUDIO_FREQUENCY = "SDL_AUDIO_FREQUENCY"; +const ZString HINT_AUDIO_INCLUDE_MONITORS = "SDL_AUDIO_INCLUDE_MONITORS"; +const ZString HINT_AUTO_UPDATE_JOYSTICKS = "SDL_AUTO_UPDATE_JOYSTICKS"; +const ZString HINT_AUTO_UPDATE_SENSORS = "SDL_AUTO_UPDATE_SENSORS"; +const ZString HINT_BMP_SAVE_LEGACY_FORMAT = "SDL_BMP_SAVE_LEGACY_FORMAT"; +const ZString HINT_CAMERA_DRIVER = "SDL_CAMERA_DRIVER"; +const ZString HINT_CPU_FEATURE_MASK = "SDL_CPU_FEATURE_MASK"; +const ZString HINT_JOYSTICK_DIRECTINPUT = "SDL_JOYSTICK_DIRECTINPUT"; +const ZString HINT_FILE_DIALOG_DRIVER = "SDL_FILE_DIALOG_DRIVER"; +const ZString HINT_DISPLAY_USABLE_BOUNDS = "SDL_DISPLAY_USABLE_BOUNDS"; +const ZString HINT_EMSCRIPTEN_ASYNCIFY = "SDL_EMSCRIPTEN_ASYNCIFY"; +const ZString HINT_EMSCRIPTEN_CANVAS_SELECTOR = "SDL_EMSCRIPTEN_CANVAS_SELECTOR"; +const ZString HINT_EMSCRIPTEN_KEYBOARD_ELEMENT = "SDL_EMSCRIPTEN_KEYBOARD_ELEMENT"; +const ZString HINT_ENABLE_SCREEN_KEYBOARD = "SDL_ENABLE_SCREEN_KEYBOARD"; +const ZString HINT_EVDEV_DEVICES = "SDL_EVDEV_DEVICES"; +const ZString HINT_EVENT_LOGGING = "SDL_EVENT_LOGGING"; +const ZString HINT_FORCE_RAISEWINDOW = "SDL_FORCE_RAISEWINDOW"; +const ZString HINT_FRAMEBUFFER_ACCELERATION = "SDL_FRAMEBUFFER_ACCELERATION"; +const ZString HINT_GAMECONTROLLERCONFIG = "SDL_GAMECONTROLLERCONFIG"; +const ZString HINT_GAMECONTROLLERCONFIG_FILE = "SDL_GAMECONTROLLERCONFIG_FILE"; +const ZString HINT_GAMECONTROLLERTYPE = "SDL_GAMECONTROLLERTYPE"; +const ZString HINT_GAMECONTROLLER_IGNORE_DEVICES = "SDL_GAMECONTROLLER_IGNORE_DEVICES"; +const ZString HINT_GAMECONTROLLER_IGNORE_DEVICES_EXCEPT = "SDL_GAMECONTROLLER_IGNORE_DEVICES_EXCEPT"; +const ZString HINT_GAMECONTROLLER_SENSOR_FUSION = "SDL_GAMECONTROLLER_SENSOR_FUSION"; +const ZString HINT_GDK_TEXTINPUT_DEFAULT_TEXT = "SDL_GDK_TEXTINPUT_DEFAULT_TEXT"; +const ZString HINT_GDK_TEXTINPUT_DESCRIPTION = "SDL_GDK_TEXTINPUT_DESCRIPTION"; +const ZString HINT_GDK_TEXTINPUT_MAX_LENGTH = "SDL_GDK_TEXTINPUT_MAX_LENGTH"; +const ZString HINT_GDK_TEXTINPUT_SCOPE = "SDL_GDK_TEXTINPUT_SCOPE"; +const ZString HINT_GDK_TEXTINPUT_TITLE = "SDL_GDK_TEXTINPUT_TITLE"; +const ZString HINT_HIDAPI_LIBUSB = "SDL_HIDAPI_LIBUSB"; +const ZString HINT_HIDAPI_LIBUSB_WHITELIST = "SDL_HIDAPI_LIBUSB_WHITELIST"; +const ZString HINT_HIDAPI_UDEV = "SDL_HIDAPI_UDEV"; +const ZString HINT_GPU_DRIVER = "SDL_GPU_DRIVER"; +const ZString HINT_HIDAPI_ENUMERATE_ONLY_CONTROLLERS = "SDL_HIDAPI_ENUMERATE_ONLY_CONTROLLERS"; +const ZString HINT_HIDAPI_IGNORE_DEVICES = "SDL_HIDAPI_IGNORE_DEVICES"; +const ZString HINT_IME_IMPLEMENTED_UI = "SDL_IME_IMPLEMENTED_UI"; +const ZString HINT_IOS_HIDE_HOME_INDICATOR = "SDL_IOS_HIDE_HOME_INDICATOR"; +const ZString HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS = "SDL_JOYSTICK_ALLOW_BACKGROUND_EVENTS"; +const ZString HINT_JOYSTICK_ARCADESTICK_DEVICES = "SDL_JOYSTICK_ARCADESTICK_DEVICES"; +const ZString HINT_JOYSTICK_ARCADESTICK_DEVICES_EXCLUDED = "SDL_JOYSTICK_ARCADESTICK_DEVICES_EXCLUDED"; +const ZString HINT_JOYSTICK_BLACKLIST_DEVICES = "SDL_JOYSTICK_BLACKLIST_DEVICES"; +const ZString HINT_JOYSTICK_BLACKLIST_DEVICES_EXCLUDED = "SDL_JOYSTICK_BLACKLIST_DEVICES_EXCLUDED"; +const ZString HINT_JOYSTICK_DEVICE = "SDL_JOYSTICK_DEVICE"; +const ZString HINT_JOYSTICK_ENHANCED_REPORTS = "SDL_JOYSTICK_ENHANCED_REPORTS"; +const ZString HINT_JOYSTICK_FLIGHTSTICK_DEVICES = "SDL_JOYSTICK_FLIGHTSTICK_DEVICES"; +const ZString HINT_JOYSTICK_FLIGHTSTICK_DEVICES_EXCLUDED = "SDL_JOYSTICK_FLIGHTSTICK_DEVICES_EXCLUDED"; +const ZString HINT_JOYSTICK_GAMEINPUT = "SDL_JOYSTICK_GAMEINPUT"; +const ZString HINT_JOYSTICK_GAMECUBE_DEVICES = "SDL_JOYSTICK_GAMECUBE_DEVICES"; +const ZString HINT_JOYSTICK_GAMECUBE_DEVICES_EXCLUDED = "SDL_JOYSTICK_GAMECUBE_DEVICES_EXCLUDED"; +const ZString HINT_JOYSTICK_HIDAPI = "SDL_JOYSTICK_HIDAPI"; +const ZString HINT_JOYSTICK_HIDAPI_COMBINE_JOY_CONS = "SDL_JOYSTICK_HIDAPI_COMBINE_JOY_CONS"; +const ZString HINT_JOYSTICK_HIDAPI_GAMECUBE = "SDL_JOYSTICK_HIDAPI_GAMECUBE"; +const ZString HINT_JOYSTICK_HIDAPI_GAMECUBE_RUMBLE_BRAKE = "SDL_JOYSTICK_HIDAPI_GAMECUBE_RUMBLE_BRAKE"; +const ZString HINT_JOYSTICK_HIDAPI_JOY_CONS = "SDL_JOYSTICK_HIDAPI_JOY_CONS"; +const ZString HINT_JOYSTICK_HIDAPI_JOYCON_HOME_LED = "SDL_JOYSTICK_HIDAPI_JOYCON_HOME_LED"; +const ZString HINT_JOYSTICK_HIDAPI_LUNA = "SDL_JOYSTICK_HIDAPI_LUNA"; +const ZString HINT_JOYSTICK_HIDAPI_NINTENDO_CLASSIC = "SDL_JOYSTICK_HIDAPI_NINTENDO_CLASSIC"; +const ZString HINT_JOYSTICK_HIDAPI_PS3 = "SDL_JOYSTICK_HIDAPI_PS3"; +const ZString HINT_JOYSTICK_HIDAPI_PS3_SIXAXIS_DRIVER = "SDL_JOYSTICK_HIDAPI_PS3_SIXAXIS_DRIVER"; +const ZString HINT_JOYSTICK_HIDAPI_PS4 = "SDL_JOYSTICK_HIDAPI_PS4"; +const ZString HINT_JOYSTICK_HIDAPI_PS4_REPORT_INTERVAL = "SDL_JOYSTICK_HIDAPI_PS4_REPORT_INTERVAL"; +const ZString HINT_JOYSTICK_HIDAPI_PS5 = "SDL_JOYSTICK_HIDAPI_PS5"; +const ZString HINT_JOYSTICK_HIDAPI_PS5_PLAYER_LED = "SDL_JOYSTICK_HIDAPI_PS5_PLAYER_LED"; +const ZString HINT_JOYSTICK_HIDAPI_SHIELD = "SDL_JOYSTICK_HIDAPI_SHIELD"; +const ZString HINT_JOYSTICK_HIDAPI_STADIA = "SDL_JOYSTICK_HIDAPI_STADIA"; +const ZString HINT_JOYSTICK_HIDAPI_STEAM = "SDL_JOYSTICK_HIDAPI_STEAM"; +const ZString HINT_JOYSTICK_HIDAPI_STEAM_HOME_LED = "SDL_JOYSTICK_HIDAPI_STEAM_HOME_LED"; +const ZString HINT_JOYSTICK_HIDAPI_STEAMDECK = "SDL_JOYSTICK_HIDAPI_STEAMDECK"; +const ZString HINT_JOYSTICK_HIDAPI_STEAM_HORI = "SDL_JOYSTICK_HIDAPI_STEAM_HORI"; +const ZString HINT_JOYSTICK_HIDAPI_SWITCH = "SDL_JOYSTICK_HIDAPI_SWITCH"; +const ZString HINT_JOYSTICK_HIDAPI_SWITCH_HOME_LED = "SDL_JOYSTICK_HIDAPI_SWITCH_HOME_LED"; +const ZString HINT_JOYSTICK_HIDAPI_SWITCH_PLAYER_LED = "SDL_JOYSTICK_HIDAPI_SWITCH_PLAYER_LED"; +const ZString HINT_JOYSTICK_HIDAPI_VERTICAL_JOY_CONS = "SDL_JOYSTICK_HIDAPI_VERTICAL_JOY_CONS"; +const ZString HINT_JOYSTICK_HIDAPI_WII = "SDL_JOYSTICK_HIDAPI_WII"; +const ZString HINT_JOYSTICK_HIDAPI_WII_PLAYER_LED = "SDL_JOYSTICK_HIDAPI_WII_PLAYER_LED"; +const ZString HINT_JOYSTICK_HIDAPI_XBOX = "SDL_JOYSTICK_HIDAPI_XBOX"; +const ZString HINT_JOYSTICK_HIDAPI_XBOX_360 = "SDL_JOYSTICK_HIDAPI_XBOX_360"; +const ZString HINT_JOYSTICK_HIDAPI_XBOX_360_PLAYER_LED = "SDL_JOYSTICK_HIDAPI_XBOX_360_PLAYER_LED"; +const ZString HINT_JOYSTICK_HIDAPI_XBOX_360_WIRELESS = "SDL_JOYSTICK_HIDAPI_XBOX_360_WIRELESS"; +const ZString HINT_JOYSTICK_HIDAPI_XBOX_ONE = "SDL_JOYSTICK_HIDAPI_XBOX_ONE"; +const ZString HINT_JOYSTICK_HIDAPI_XBOX_ONE_HOME_LED = "SDL_JOYSTICK_HIDAPI_XBOX_ONE_HOME_LED"; +const ZString HINT_JOYSTICK_IOKIT = "SDL_JOYSTICK_IOKIT"; +const ZString HINT_JOYSTICK_LINUX_CLASSIC = "SDL_JOYSTICK_LINUX_CLASSIC"; +const ZString HINT_JOYSTICK_LINUX_DEADZONES = "SDL_JOYSTICK_LINUX_DEADZONES"; +const ZString HINT_JOYSTICK_LINUX_DIGITAL_HATS = "SDL_JOYSTICK_LINUX_DIGITAL_HATS"; +const ZString HINT_JOYSTICK_LINUX_HAT_DEADZONES = "SDL_JOYSTICK_LINUX_HAT_DEADZONES"; +const ZString HINT_JOYSTICK_MFI = "SDL_JOYSTICK_MFI"; +const ZString HINT_JOYSTICK_RAWINPUT = "SDL_JOYSTICK_RAWINPUT"; +const ZString HINT_JOYSTICK_RAWINPUT_CORRELATE_XINPUT = "SDL_JOYSTICK_RAWINPUT_CORRELATE_XINPUT"; +const ZString HINT_JOYSTICK_ROG_CHAKRAM = "SDL_JOYSTICK_ROG_CHAKRAM"; +const ZString HINT_JOYSTICK_THREAD = "SDL_JOYSTICK_THREAD"; +const ZString HINT_JOYSTICK_THROTTLE_DEVICES = "SDL_JOYSTICK_THROTTLE_DEVICES"; +const ZString HINT_JOYSTICK_THROTTLE_DEVICES_EXCLUDED = "SDL_JOYSTICK_THROTTLE_DEVICES_EXCLUDED"; +const ZString HINT_JOYSTICK_WGI = "SDL_JOYSTICK_WGI"; +const ZString HINT_JOYSTICK_WHEEL_DEVICES = "SDL_JOYSTICK_WHEEL_DEVICES"; +const ZString HINT_JOYSTICK_WHEEL_DEVICES_EXCLUDED = "SDL_JOYSTICK_WHEEL_DEVICES_EXCLUDED"; +const ZString HINT_JOYSTICK_ZERO_CENTERED_DEVICES = "SDL_JOYSTICK_ZERO_CENTERED_DEVICES"; +const ZString HINT_JOYSTICK_HAPTIC_AXES = "SDL_JOYSTICK_HAPTIC_AXES"; +const ZString HINT_KEYCODE_OPTIONS = "SDL_KEYCODE_OPTIONS"; +const ZString HINT_KMSDRM_DEVICE_INDEX = "SDL_KMSDRM_DEVICE_INDEX"; +const ZString HINT_KMSDRM_REQUIRE_DRM_MASTER = "SDL_KMSDRM_REQUIRE_DRM_MASTER"; +const ZString HINT_LOGGING = "SDL_LOGGING"; +const ZString HINT_MAC_BACKGROUND_APP = "SDL_MAC_BACKGROUND_APP"; +const ZString HINT_MAC_CTRL_CLICK_EMULATE_RIGHT_CLICK = "SDL_MAC_CTRL_CLICK_EMULATE_RIGHT_CLICK"; +const ZString HINT_MAC_OPENGL_ASYNC_DISPATCH = "SDL_MAC_OPENGL_ASYNC_DISPATCH"; +const ZString HINT_MAC_OPTION_AS_ALT = "SDL_MAC_OPTION_AS_ALT"; +const ZString HINT_MAC_SCROLL_MOMENTUM = "SDL_MAC_SCROLL_MOMENTUM"; +const ZString HINT_MAIN_CALLBACK_RATE = "SDL_MAIN_CALLBACK_RATE"; +const ZString HINT_MOUSE_AUTO_CAPTURE = "SDL_MOUSE_AUTO_CAPTURE"; +const ZString HINT_MOUSE_DOUBLE_CLICK_RADIUS = "SDL_MOUSE_DOUBLE_CLICK_RADIUS"; +const ZString HINT_MOUSE_DOUBLE_CLICK_TIME = "SDL_MOUSE_DOUBLE_CLICK_TIME"; +const ZString HINT_MOUSE_DEFAULT_SYSTEM_CURSOR = "SDL_MOUSE_DEFAULT_SYSTEM_CURSOR"; +const ZString HINT_MOUSE_EMULATE_WARP_WITH_RELATIVE = "SDL_MOUSE_EMULATE_WARP_WITH_RELATIVE"; +const ZString HINT_MOUSE_FOCUS_CLICKTHROUGH = "SDL_MOUSE_FOCUS_CLICKTHROUGH"; +const ZString HINT_MOUSE_NORMAL_SPEED_SCALE = "SDL_MOUSE_NORMAL_SPEED_SCALE"; +const ZString HINT_MOUSE_RELATIVE_MODE_CENTER = "SDL_MOUSE_RELATIVE_MODE_CENTER"; +const ZString HINT_MOUSE_RELATIVE_SPEED_SCALE = "SDL_MOUSE_RELATIVE_SPEED_SCALE"; +const ZString HINT_MOUSE_RELATIVE_SYSTEM_SCALE = "SDL_MOUSE_RELATIVE_SYSTEM_SCALE"; +const ZString HINT_MOUSE_RELATIVE_WARP_MOTION = "SDL_MOUSE_RELATIVE_WARP_MOTION"; +const ZString HINT_MOUSE_RELATIVE_CURSOR_VISIBLE = "SDL_MOUSE_RELATIVE_CURSOR_VISIBLE"; +const ZString HINT_MOUSE_TOUCH_EVENTS = "SDL_MOUSE_TOUCH_EVENTS"; +const ZString HINT_MUTE_CONSOLE_KEYBOARD = "SDL_MUTE_CONSOLE_KEYBOARD"; +const ZString HINT_NO_SIGNAL_HANDLERS = "SDL_NO_SIGNAL_HANDLERS"; +const ZString HINT_OPENGL_LIBRARY = "SDL_OPENGL_LIBRARY"; +const ZString HINT_EGL_LIBRARY = "SDL_EGL_LIBRARY"; +const ZString HINT_OPENGL_ES_DRIVER = "SDL_OPENGL_ES_DRIVER"; +const ZString HINT_OPENVR_LIBRARY = "SDL_OPENVR_LIBRARY"; +const ZString HINT_ORIENTATIONS = "SDL_ORIENTATIONS"; +const ZString HINT_POLL_SENTINEL = "SDL_POLL_SENTINEL"; +const ZString HINT_PREFERRED_LOCALES = "SDL_PREFERRED_LOCALES"; +const ZString HINT_QUIT_ON_LAST_WINDOW_CLOSE = "SDL_QUIT_ON_LAST_WINDOW_CLOSE"; +const ZString HINT_RENDER_DIRECT3D_THREADSAFE = "SDL_RENDER_DIRECT3D_THREADSAFE"; +const ZString HINT_RENDER_DIRECT3D11_DEBUG = "SDL_RENDER_DIRECT3D11_DEBUG"; +const ZString HINT_RENDER_VULKAN_DEBUG = "SDL_RENDER_VULKAN_DEBUG"; +const ZString HINT_RENDER_GPU_DEBUG = "SDL_RENDER_GPU_DEBUG"; +const ZString HINT_RENDER_GPU_LOW_POWER = "SDL_RENDER_GPU_LOW_POWER"; +const ZString HINT_RENDER_DRIVER = "SDL_RENDER_DRIVER"; +const ZString HINT_RENDER_LINE_METHOD = "SDL_RENDER_LINE_METHOD"; +const ZString HINT_RENDER_METAL_PREFER_LOW_POWER_DEVICE = "SDL_RENDER_METAL_PREFER_LOW_POWER_DEVICE"; +const ZString HINT_RENDER_VSYNC = "SDL_RENDER_VSYNC"; +const ZString HINT_RETURN_KEY_HIDES_IME = "SDL_RETURN_KEY_HIDES_IME"; +const ZString HINT_ROG_GAMEPAD_MICE = "SDL_ROG_GAMEPAD_MICE"; +const ZString HINT_ROG_GAMEPAD_MICE_EXCLUDED = "SDL_ROG_GAMEPAD_MICE_EXCLUDED"; +const ZString HINT_RPI_VIDEO_LAYER = "SDL_RPI_VIDEO_LAYER"; +const ZString HINT_SCREENSAVER_INHIBIT_ACTIVITY_NAME = "SDL_SCREENSAVER_INHIBIT_ACTIVITY_NAME"; +const ZString HINT_SHUTDOWN_DBUS_ON_QUIT = "SDL_SHUTDOWN_DBUS_ON_QUIT"; +const ZString HINT_STORAGE_TITLE_DRIVER = "SDL_STORAGE_TITLE_DRIVER"; +const ZString HINT_STORAGE_USER_DRIVER = "SDL_STORAGE_USER_DRIVER"; +const ZString HINT_THREAD_FORCE_REALTIME_TIME_CRITICAL = "SDL_THREAD_FORCE_REALTIME_TIME_CRITICAL"; +const ZString HINT_THREAD_PRIORITY_POLICY = "SDL_THREAD_PRIORITY_POLICY"; +const ZString HINT_TIMER_RESOLUTION = "SDL_TIMER_RESOLUTION"; +const ZString HINT_TOUCH_MOUSE_EVENTS = "SDL_TOUCH_MOUSE_EVENTS"; +const ZString HINT_TRACKPAD_IS_TOUCH_ONLY = "SDL_TRACKPAD_IS_TOUCH_ONLY"; +const ZString HINT_TV_REMOTE_AS_JOYSTICK = "SDL_TV_REMOTE_AS_JOYSTICK"; +const ZString HINT_VIDEO_ALLOW_SCREENSAVER = "SDL_VIDEO_ALLOW_SCREENSAVER"; +const ZString HINT_VIDEO_DISPLAY_PRIORITY = "SDL_VIDEO_DISPLAY_PRIORITY"; +const ZString HINT_VIDEO_DOUBLE_BUFFER = "SDL_VIDEO_DOUBLE_BUFFER"; +const ZString HINT_VIDEO_DRIVER = "SDL_VIDEO_DRIVER"; +const ZString HINT_VIDEO_DUMMY_SAVE_FRAMES = "SDL_VIDEO_DUMMY_SAVE_FRAMES"; +const ZString HINT_VIDEO_EGL_ALLOW_GETDISPLAY_FALLBACK = "SDL_VIDEO_EGL_ALLOW_GETDISPLAY_FALLBACK"; +const ZString HINT_VIDEO_FORCE_EGL = "SDL_VIDEO_FORCE_EGL"; +const ZString HINT_VIDEO_MAC_FULLSCREEN_SPACES = "SDL_VIDEO_MAC_FULLSCREEN_SPACES"; +const ZString HINT_VIDEO_MAC_FULLSCREEN_MENU_VISIBILITY = "SDL_VIDEO_MAC_FULLSCREEN_MENU_VISIBILITY"; +const ZString HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS = "SDL_VIDEO_MINIMIZE_ON_FOCUS_LOSS"; +const ZString HINT_VIDEO_OFFSCREEN_SAVE_FRAMES = "SDL_VIDEO_OFFSCREEN_SAVE_FRAMES"; +const ZString HINT_VIDEO_SYNC_WINDOW_OPERATIONS = "SDL_VIDEO_SYNC_WINDOW_OPERATIONS"; +const ZString HINT_VIDEO_WAYLAND_ALLOW_LIBDECOR = "SDL_VIDEO_WAYLAND_ALLOW_LIBDECOR"; +const ZString HINT_VIDEO_WAYLAND_MODE_EMULATION = "SDL_VIDEO_WAYLAND_MODE_EMULATION"; +const ZString HINT_VIDEO_WAYLAND_MODE_SCALING = "SDL_VIDEO_WAYLAND_MODE_SCALING"; +const ZString HINT_VIDEO_WAYLAND_PREFER_LIBDECOR = "SDL_VIDEO_WAYLAND_PREFER_LIBDECOR"; +const ZString HINT_VIDEO_WAYLAND_SCALE_TO_DISPLAY = "SDL_VIDEO_WAYLAND_SCALE_TO_DISPLAY"; +const ZString HINT_VIDEO_WIN_D3DCOMPILER = "SDL_VIDEO_WIN_D3DCOMPILER"; +const ZString HINT_VIDEO_X11_EXTERNAL_WINDOW_INPUT = "SDL_VIDEO_X11_EXTERNAL_WINDOW_INPUT"; +const ZString HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR = "SDL_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR"; +const ZString HINT_VIDEO_X11_NET_WM_PING = "SDL_VIDEO_X11_NET_WM_PING"; +const ZString HINT_VIDEO_X11_NODIRECTCOLOR = "SDL_VIDEO_X11_NODIRECTCOLOR"; +const ZString HINT_VIDEO_X11_SCALING_FACTOR = "SDL_VIDEO_X11_SCALING_FACTOR"; +const ZString HINT_VIDEO_X11_VISUALID = "SDL_VIDEO_X11_VISUALID"; +const ZString HINT_VIDEO_X11_WINDOW_VISUALID = "SDL_VIDEO_X11_WINDOW_VISUALID"; +const ZString HINT_VIDEO_X11_XRANDR = "SDL_VIDEO_X11_XRANDR"; +const ZString HINT_VITA_ENABLE_BACK_TOUCH = "SDL_VITA_ENABLE_BACK_TOUCH"; +const ZString HINT_VITA_ENABLE_FRONT_TOUCH = "SDL_VITA_ENABLE_FRONT_TOUCH"; +const ZString HINT_VITA_MODULE_PATH = "SDL_VITA_MODULE_PATH"; +const ZString HINT_VITA_PVR_INIT = "SDL_VITA_PVR_INIT"; +const ZString HINT_VITA_RESOLUTION = "SDL_VITA_RESOLUTION"; +const ZString HINT_VITA_PVR_OPENGL = "SDL_VITA_PVR_OPENGL"; +const ZString HINT_VITA_TOUCH_MOUSE_DEVICE = "SDL_VITA_TOUCH_MOUSE_DEVICE"; +const ZString HINT_VULKAN_DISPLAY = "SDL_VULKAN_DISPLAY"; +const ZString HINT_VULKAN_LIBRARY = "SDL_VULKAN_LIBRARY"; +const ZString HINT_WAVE_FACT_CHUNK = "SDL_WAVE_FACT_CHUNK"; +const ZString HINT_WAVE_CHUNK_LIMIT = "SDL_WAVE_CHUNK_LIMIT"; +const ZString HINT_WAVE_RIFF_CHUNK_SIZE = "SDL_WAVE_RIFF_CHUNK_SIZE"; +const ZString HINT_WAVE_TRUNCATION = "SDL_WAVE_TRUNCATION"; +const ZString HINT_WINDOW_ACTIVATE_WHEN_RAISED = "SDL_WINDOW_ACTIVATE_WHEN_RAISED"; +const ZString HINT_WINDOW_ACTIVATE_WHEN_SHOWN = "SDL_WINDOW_ACTIVATE_WHEN_SHOWN"; +const ZString HINT_WINDOW_ALLOW_TOPMOST = "SDL_WINDOW_ALLOW_TOPMOST"; +const ZString HINT_WINDOW_FRAME_USABLE_WHILE_CURSOR_HIDDEN = "SDL_WINDOW_FRAME_USABLE_WHILE_CURSOR_HIDDEN"; +const ZString HINT_WINDOWS_CLOSE_ON_ALT_F4 = "SDL_WINDOWS_CLOSE_ON_ALT_F4"; +const ZString HINT_WINDOWS_ENABLE_MENU_MNEMONICS = "SDL_WINDOWS_ENABLE_MENU_MNEMONICS"; +const ZString HINT_WINDOWS_ENABLE_MESSAGELOOP = "SDL_WINDOWS_ENABLE_MESSAGELOOP"; +const ZString HINT_WINDOWS_GAMEINPUT = "SDL_WINDOWS_GAMEINPUT"; +const ZString HINT_WINDOWS_RAW_KEYBOARD = "SDL_WINDOWS_RAW_KEYBOARD"; +const ZString HINT_WINDOWS_FORCE_SEMAPHORE_KERNEL = "SDL_WINDOWS_FORCE_SEMAPHORE_KERNEL"; +const ZString HINT_WINDOWS_INTRESOURCE_ICON = "SDL_WINDOWS_INTRESOURCE_ICON"; +const ZString HINT_WINDOWS_INTRESOURCE_ICON_SMALL = "SDL_WINDOWS_INTRESOURCE_ICON_SMALL"; +const ZString HINT_WINDOWS_USE_D3D9EX = "SDL_WINDOWS_USE_D3D9EX"; +const ZString HINT_WINDOWS_ERASE_BACKGROUND_MODE = "SDL_WINDOWS_ERASE_BACKGROUND_MODE"; +const ZString HINT_X11_FORCE_OVERRIDE_REDIRECT = "SDL_X11_FORCE_OVERRIDE_REDIRECT"; +const ZString HINT_X11_WINDOW_TYPE = "SDL_X11_WINDOW_TYPE"; +const ZString HINT_X11_XCB_LIBRARY = "SDL_X11_XCB_LIBRARY"; +const ZString HINT_XINPUT_ENABLED = "SDL_XINPUT_ENABLED"; +const ZString HINT_ASSERT = "SDL_ASSERT"; +const ZString HINT_PEN_MOUSE_EVENTS = "SDL_PEN_MOUSE_EVENTS"; +const ZString HINT_PEN_TOUCH_EVENTS = "SDL_PEN_TOUCH_EVENTS"; + + +enum HintPriority : inline CInt { + SDL_HINT_DEFAULT, + SDL_HINT_NORMAL, + SDL_HINT_OVERRIDE +} + +extern fn bool set_hint_with_priority(ZString name, ZString value, HintPriority priority) @extern("SDL_SetHintWithPriority"); +extern fn bool set_hint(ZString name, ZString value) @extern("SDL_SetHint"); +extern fn bool reset_hint(ZString name) @extern("SDL_ResetHint"); +extern fn void reset_hints() @extern("SDL_ResetHints"); +extern fn ZString get_hint(ZString name) @extern("SDL_GetHint"); +extern fn bool get_hint_boolean(ZString name, bool default_value) @extern("SDL_GetHintBoolean"); + +alias HintCallback = fn void(void *userdata, ZString name, ZString oldValue, ZString newValue); + +extern fn bool add_hint_callback(ZString name, HintCallback callback, void *userdata) @extern("SDL_AddHintCallback"); +extern fn void remove_hint_callback(ZString name, HintCallback callback, void *userdata) @extern("SDL_RemoveHintCallback"); diff --git a/sdl3.c3l/sdl3_init.c3i b/sdl3.c3l/sdl3_init.c3i new file mode 100644 index 0000000..3e03836 --- /dev/null +++ b/sdl3.c3l/sdl3_init.c3i @@ -0,0 +1,47 @@ +module sdl3::sdl; + +typedef InitFlags = uint; + +const InitFlags INIT_AUDIO = 0x00000010; +const InitFlags INIT_VIDEO = 0x00000020; +const InitFlags INIT_JOYSTICK = 0x00000200; +const InitFlags INIT_HAPTIC = 0x00001000; +const InitFlags INIT_GAMEPAD = 0x00002000; +const InitFlags INIT_EVENTS = 0x00004000; +const InitFlags INIT_SENSOR = 0x00008000; +const InitFlags INIT_CAMERA = 0x00010000; + +enum AppResult : inline CInt { + APP_CONTINUE, + APP_SUCCESS, + APP_FAILURE +} + +alias AppInit_func = fn AppResult(void **appstate, int argc, char[]* argv); +alias AppIterate_func = fn AppResult(void *appstate); +alias AppEvent_func = fn AppResult(void *appstate, Event *event); +alias AppQuit_func = fn void(void *appstate, AppResult result); + + +extern fn bool init(InitFlags flags) @extern("SDL_Init"); +extern fn bool init_sub_system(InitFlags flags) @extern("SDL_InitSubSystem"); +extern fn void quit_sub_system(InitFlags flags) @extern("SDL_QuitSubSystem"); +extern fn InitFlags was_init(InitFlags flags) @extern("SDL_WasInit"); +extern fn void quit() @extern("SDL_Quit"); +extern fn bool is_main_thread() @extern("SDL_IsMainThread"); + +alias MainThreadCallback = fn void(void *userdata); + +extern fn bool run_on_main_thread(MainThreadCallback callback, void *userdata, bool wait_complete) @extern("SDL_RunOnMainThread"); +extern fn bool set_app_metadata(ZString appname, ZString appversion, ZString appidentifier) @extern("SDL_SetAppMetadata"); +extern fn bool set_app_metadata_property(ZString name, ZString value) @extern("SDL_SetAppMetadataProperty"); + +const ZString PROP_APP_METADATA_NAME_STRING = "SDL.app.metadata.name"; +const ZString PROP_APP_METADATA_VERSION_STRING = "SDL.app.metadata.version"; +const ZString PROP_APP_METADATA_IDENTIFIER_STRING = "SDL.app.metadata.identifier"; +const ZString PROP_APP_METADATA_CREATOR_STRING = "SDL.app.metadata.creator"; +const ZString PROP_APP_METADATA_COPYRIGHT_STRING = "SDL.app.metadata.copyright"; +const ZString PROP_APP_METADATA_URL_STRING = "SDL.app.metadata.url"; +const ZString PROP_APP_METADATA_TYPE_STRING = "SDL.app.metadata.type"; + +extern fn ZString get_app_metadata_property(ZString name) @extern("SDL_GetAppMetadataProperty"); diff --git a/sdl3.c3l/sdl3_iostream.c3i b/sdl3.c3l/sdl3_iostream.c3i new file mode 100644 index 0000000..75adec0 --- /dev/null +++ b/sdl3.c3l/sdl3_iostream.c3i @@ -0,0 +1,3 @@ +module sdl3::sdl; + +typedef IOStream = void; \ No newline at end of file diff --git a/sdl3.c3l/sdl3_joystick.c3i b/sdl3.c3l/sdl3_joystick.c3i new file mode 100644 index 0000000..83e63af --- /dev/null +++ b/sdl3.c3l/sdl3_joystick.c3i @@ -0,0 +1,155 @@ +module sdl3::sdl; + +typedef Joystick = void; +typedef JoystickID = uint; + +enum JoystickType : inline CInt { + JOYSTICK_TYPE_UNKNOWN, + JOYSTICK_TYPE_GAMEPAD, + JOYSTICK_TYPE_WHEEL, + JOYSTICK_TYPE_ARCADE_STICK, + JOYSTICK_TYPE_FLIGHT_STICK, + JOYSTICK_TYPE_DANCE_PAD, + JOYSTICK_TYPE_GUITAR, + JOYSTICK_TYPE_DRUM_KIT, + JOYSTICK_TYPE_ARCADE_PAD, + JOYSTICK_TYPE_THROTTLE, + JOYSTICK_TYPE_COUNT +} + +typedef JoystickConnectionState = CInt; + +const JoystickConnectionState JOYSTICK_CONNECTION_INVALID = -1; +const JoystickConnectionState JOYSTICK_CONNECTION_UNKNOWN = 0; +const JoystickConnectionState JOYSTICK_CONNECTION_WIRED = 1; +const JoystickConnectionState JOYSTICK_CONNECTION_WIRELESS = 2; + +const int JOYSTICK_AXIS_MAX = 32767; +const int JOYSTICK_AXIS_MIN = -32768; + +extern fn void lock_joysticks() @extern("SDL_LockJoysticks"); +extern fn void unlock_joysticks() @extern("SDL_UnlockJoysticks"); +extern fn bool has_joystick() @extern("SDL_HasJoystick"); +extern fn JoystickID* get_joysticks(int *count) @extern("SDL_GetJoysticks"); +extern fn ZString get_joystick_name_for_id(JoystickID instance_id) @extern("SDL_GetJoystickNameForID"); +extern fn ZString get_joystick_path_for_id(JoystickID instance_id) @extern("SDL_GetJoystickPathForID"); +extern fn int get_joystick_player_index_for_id(JoystickID instance_id) @extern("SDL_GetJoystickPlayerIndexForID"); +// extern fn SDL_GUID get_joystick_guid_for_id(JoystickID instance_id) @extern("SDL_GetJoystickGUIDForID"); +extern fn ushort get_joystick_vendor_for_id(JoystickID instance_id) @extern("SDL_GetJoystickVendorForID"); +extern fn ushort get_joystick_product_for_id(JoystickID instance_id) @extern("SDL_GetJoystickProductForID"); +extern fn ushort get_joystick_product_version_for_id(JoystickID instance_id) @extern("SDL_GetJoystickProductVersionForID"); +extern fn JoystickType get_joystick_type_for_id(JoystickID instance_id) @extern("SDL_GetJoystickTypeForID"); +extern fn Joystick* open_joystick(JoystickID instance_id) @extern("SDL_OpenJoystick"); +extern fn Joystick* get_joystick_from_id(JoystickID instance_id) @extern("SDL_GetJoystickFromID"); +extern fn Joystick* get_joystick_from_player_index(int player_index) @extern("SDL_GetJoystickFromPlayerIndex"); + +struct VirtualJoystickTouchpadDesc { + ushort nfingers; + ushort[3] padding; +} + +struct VirtualJoystickSensorDesc { + SensorType type; + float rate; +} + +alias VirtualJoystickUpdate = fn void(void *userdata); +alias VirtualJoystickSetPlayerIndex = fn void(void *userdata, int player_index); +alias VirtualJoystickRumble = fn bool(void *userdata, ushort low_frequency_rumble, ushort high_frequency_rumble); +alias VirtualJoystickRumbleTriggers = fn bool(void *userdata, ushort left_rumble, ushort right_rumble); +alias VirtualJoystickSetLED = fn bool(void *userdata, char red, char green, char blue); +alias VirtualJoystickSendEffect = fn bool(void *userdata, void *data, int size); +alias VirtualJoystickSetSensorsEnabled = fn bool(void *userdata, bool enabled); +alias VirtualJoystickCleanup = fn void(void *userdata); + +struct VirtualJoystickDesc { + uint version; + ushort type; + ushort padding; + ushort vendor_id; + ushort product_id; + ushort naxes; + ushort nbuttons; + ushort nballs; + ushort nhats; + ushort ntouchpads; + ushort nsensors; + ushort[2] padding2; + uint button_mask; + uint axis_mask; + ZString name; + VirtualJoystickTouchpadDesc* touchpads; + VirtualJoystickSensorDesc* sensors; + + void *userdata; + VirtualJoystickUpdate update; + VirtualJoystickSetPlayerIndex set_player_index; + VirtualJoystickRumble rumble; + VirtualJoystickRumbleTriggers rumble_triggers; + VirtualJoystickSetLED set_led; + VirtualJoystickSendEffect send_effect; + VirtualJoystickSetSensorsEnabled set_sensors_enabled; + VirtualJoystickCleanup cleanup; +} + +extern fn JoystickID attach_virtual_joystick(VirtualJoystickDesc *desc) @extern("SDL_AttachVirtualJoystick"); +extern fn bool detach_virtual_joystick(JoystickID instance_id) @extern("SDL_DetachVirtualJoystick"); +extern fn bool is_joystick_virtual(JoystickID instance_id) @extern("SDL_IsJoystickVirtual"); +extern fn bool set_joystick_virtual_axis(Joystick* joystick, int axis, short value) @extern("SDL_SetJoystickVirtualAxis"); +extern fn bool set_joystick_virtual_ball(Joystick* joystick, int ball, short xrel, short yrel) @extern("SDL_SetJoystickVirtualBall"); +extern fn bool set_joystick_virtual_button(Joystick* joystick, int button, bool down) @extern("SDL_SetJoystickVirtualButton"); +extern fn bool set_joystick_virtual_hat(Joystick* joystick, int hat, char value) @extern("SDL_SetJoystickVirtualHat"); +extern fn bool set_joystick_virtual_touchpad(Joystick* joystick, int touchpad, int finger, bool down, float x, float y, float pressure) @extern("SDL_SetJoystickVirtualTouchpad"); +extern fn bool send_joystick_virtual_sensor_data(Joystick* joystick, SensorType type, ulong sensor_timestamp, float *data, int num_values) @extern("SDL_SendJoystickVirtualSensorData"); +extern fn PropertiesID get_joystick_properties(Joystick* joystick) @extern("SDL_GetJoystickProperties"); + +const ZString PROP_JOYSTICK_CAP_MONO_LED_BOOLEAN = "SDL.joystick.cap.mono_led"; +const ZString PROP_JOYSTICK_CAP_RGB_LED_BOOLEAN = "SDL.joystick.cap.rgb_led"; +const ZString PROP_JOYSTICK_CAP_PLAYER_LED_BOOLEAN = "SDL.joystick.cap.player_led"; +const ZString PROP_JOYSTICK_CAP_RUMBLE_BOOLEAN = "SDL.joystick.cap.rumble"; +const ZString PROP_JOYSTICK_CAP_TRIGGER_RUMBLE_BOOLEAN = "SDL.joystick.cap.trigger_rumble"; + +extern fn ZString get_joystick_name(Joystick* joystick) @extern("SDL_GetJoystickName"); +extern fn ZString get_joystick_path(Joystick* joystick) @extern("SDL_GetJoystickPath"); +extern fn int get_joystick_player_index(Joystick* joystick) @extern("SDL_GetJoystickPlayerIndex"); +extern fn bool set_joystick_player_index(Joystick* joystick, int player_index) @extern("SDL_SetJoystickPlayerIndex"); +//extern fn SDL_GUID get_joystick_guid(Joystick* joystick) @extern("SDL_GetJoystickGUID"); +extern fn ushort get_joystick_vendor(Joystick* joystick) @extern("SDL_GetJoystickVendor"); +extern fn ushort get_joystick_product(Joystick* joystick) @extern("SDL_GetJoystickProduct"); +extern fn ushort get_joystick_product_version(Joystick* joystick) @extern("SDL_GetJoystickProductVersion"); +extern fn ushort get_joystick_firmware_version(Joystick* joystick) @extern("SDL_GetJoystickFirmwareVersion"); +extern fn ZString get_joystick_serial(Joystick* joystick) @extern("SDL_GetJoystickSerial"); +extern fn JoystickType get_joystick_type(Joystick* joystick) @extern("SDL_GetJoystickType"); +//extern fn void get_joystick_guid_info(SDL_GUID guid, ushort *vendor, ushort *product, ushort *version, ushort *crc16) @extern("SDL_GetJoystickGUIDInfo"); +extern fn bool joystick_connected(Joystick* joystick) @extern("SDL_JoystickConnected"); +extern fn JoystickID get_joystick_id(Joystick* joystick) @extern("SDL_GetJoystickID"); +extern fn int get_num_joystick_axes(Joystick* joystick) @extern("SDL_GetNumJoystickAxes"); +extern fn int get_num_joystick_balls(Joystick* joystick) @extern("SDL_GetNumJoystickBalls"); +extern fn int get_num_joystick_hats(Joystick* joystick) @extern("SDL_GetNumJoystickHats"); +extern fn int get_num_joystick_buttons(Joystick* joystick) @extern("SDL_GetNumJoystickButtons"); +extern fn void set_joystick_events_enabled(bool enabled) @extern("SDL_SetJoystickEventsEnabled"); +extern fn bool joystick_events_enabled() @extern("SDL_JoystickEventsEnabled"); +extern fn void update_joysticks() @extern("SDL_UpdateJoysticks"); +extern fn short get_joystick_axis(Joystick* joystick, int axis) @extern("SDL_GetJoystickAxis"); +extern fn bool get_joystick_axis_initial_state(Joystick* joystick, int axis, short *state) @extern("SDL_GetJoystickAxisInitialState"); +extern fn bool get_joystick_ball(Joystick* joystick, int ball, int *dx, int *dy) @extern("SDL_GetJoystickBall"); +extern fn char get_joystick_hat(Joystick* joystick, int hat) @extern("SDL_GetJoystickHat"); + +const ushort HAT_CENTERED = 0x00; +const ushort HAT_UP = 0x01; +const ushort HAT_RIGHT = 0x02; +const ushort HAT_DOWN = 0x04; +const ushort HAT_LEFT = 0x08; +const ushort HAT_RIGHTUP = (HAT_RIGHT|HAT_UP); +const ushort HAT_RIGHTDOWN = (HAT_RIGHT|HAT_DOWN); +const ushort HAT_LEFTUP = (HAT_LEFT|HAT_UP); +const ushort HAT_LEFTDOWN = (HAT_LEFT|HAT_DOWN); + +extern fn bool get_joystick_button(Joystick* joystick, int button) @extern("SDL_GetJoystickButton"); +extern fn bool rumble_joystick(Joystick* joystick, ushort low_frequency_rumble, ushort high_frequency_rumble, uint duration_ms) @extern("SDL_RumbleJoystick"); +extern fn bool rumble_joystick_triggers(Joystick* joystick, ushort left_rumble, ushort right_rumble, uint duration_ms) @extern("SDL_RumbleJoystickTriggers"); +extern fn bool set_joystick_led(Joystick* joystick, char red, char green, char blue) @extern("SDL_SetJoystickLED"); +extern fn bool send_joystick_effect(Joystick* joystick, void *data, int size) @extern("SDL_SendJoystickEffect"); +extern fn void close_joystick(Joystick* joystick) @extern("SDL_CloseJoystick"); +extern fn JoystickConnectionState get_joystick_connection_state(Joystick* joystick) @extern("SDL_GetJoystickConnectionState"); +extern fn PowerState get_joystick_power_info(Joystick* joystick, int *percent) @extern("SDL_GetJoystickPowerInfo"); diff --git a/sdl3.c3l/sdl3_keyboard.c3i b/sdl3.c3l/sdl3_keyboard.c3i new file mode 100644 index 0000000..acfe43b --- /dev/null +++ b/sdl3.c3l/sdl3_keyboard.c3i @@ -0,0 +1,55 @@ +module sdl3::sdl; + +typedef KeyboardID = uint; + +extern fn bool has_keyboard() @extern("SDL_HasKeyboard"); +extern fn KeyboardID* get_keyboards(int *count) @extern("SDL_GetKeyboards"); +extern fn ZString get_keyboard_name_for_id(KeyboardID instance_id) @extern("SDL_GetKeyboardNameForID"); +extern fn Window* get_keyboard_focus() @extern("SDL_GetKeyboardFocus"); +extern fn bool* get_keyboard_state(int *numkeys) @extern("SDL_GetKeyboardState"); +extern fn void reset_keyboard() @extern("SDL_ResetKeyboard"); +extern fn Keymod get_mod_state() @extern("SDL_GetModState"); +extern fn void set_mod_state(Keymod modstate) @extern("SDL_SetModState"); +extern fn Keycode get_key_from_scancode(Scancode scancode, Keymod modstate, bool key_event) @extern("SDL_GetKeyFromScancode"); +extern fn Scancode get_scancode_from_key(Keycode key, Keymod *modstate) @extern("SDL_GetScancodeFromKey"); +extern fn bool set_scancode_name(Scancode scancode, ZString name) @extern("SDL_SetScancodeName"); +extern fn ZString get_scancode_name(Scancode scancode) @extern("SDL_GetScancodeName"); +extern fn Scancode get_scancode_from_name(ZString name) @extern("SDL_GetScancodeFromName"); +extern fn ZString get_key_name(Keycode key) @extern("SDL_GetKeyName"); +extern fn Keycode get_key_from_name(ZString name) @extern("SDL_GetKeyFromName"); +extern fn bool start_text_input(Window* window) @extern("SDL_StartTextInput"); + +enum TextInputType : inline CInt { + SDL_TEXTINPUT_TYPE_TEXT, + SDL_TEXTINPUT_TYPE_TEXT_NAME, + SDL_TEXTINPUT_TYPE_TEXT_EMAIL, + SDL_TEXTINPUT_TYPE_TEXT_USERNAME, + SDL_TEXTINPUT_TYPE_TEXT_PASSWORD_HIDDEN, + SDL_TEXTINPUT_TYPE_TEXT_PASSWORD_VISIBLE, + SDL_TEXTINPUT_TYPE_NUMBER, + SDL_TEXTINPUT_TYPE_NUMBER_PASSWORD_HIDDEN, + SDL_TEXTINPUT_TYPE_NUMBER_PASSWORD_VISIBLE +} + +enum Capitalization : inline CInt { + SDL_CAPITALIZE_NONE, + SDL_CAPITALIZE_SENTENCES, + SDL_CAPITALIZE_WORDS, + SDL_CAPITALIZE_LETTERS +} + +extern fn bool start_text_input_with_properties(Window* window, PropertiesID props) @extern("SDL_StartTextInputWithProperties"); + +const ZString PROP_TEXTINPUT_TYPE_NUMBER = "SDL.textinput.type"; +const ZString PROP_TEXTINPUT_CAPITALIZATION_NUMBER = "SDL.textinput.capitalization"; +const ZString PROP_TEXTINPUT_AUTOCORRECT_BOOLEAN = "SDL.textinput.autocorrect"; +const ZString PROP_TEXTINPUT_MULTILINE_BOOLEAN = "SDL.textinput.multiline"; +const ZString PROP_TEXTINPUT_ANDROID_INPUTTYPE_NUMBER = "SDL.textinput.android.inputtype"; + +extern fn bool text_input_active(Window* window) @extern("SDL_TextInputActive"); +extern fn bool stop_text_input(Window* window) @extern("SDL_StopTextInput"); +extern fn bool clear_composition(Window* window) @extern("SDL_ClearComposition"); +extern fn bool set_text_input_area(Window* window, Rect* rect, int cursor) @extern("SDL_SetTextInputArea"); +extern fn bool get_text_input_area(Window* window, Rect* rect, int *cursor) @extern("SDL_GetTextInputArea"); +extern fn bool has_screen_keyboard_support() @extern("SDL_HasScreenKeyboardSupport"); +extern fn bool screen_keyboard_shown(Window* window) @extern("SDL_ScreenKeyboardShown"); diff --git a/sdl3.c3l/sdl3_keycode.c3i b/sdl3.c3l/sdl3_keycode.c3i new file mode 100644 index 0000000..cf1f976 --- /dev/null +++ b/sdl3.c3l/sdl3_keycode.c3i @@ -0,0 +1,286 @@ +module sdl3::sdl; + +typedef Keycode = uint; + + +const Keycode K_EXTENDED_MASK = (1 << 29); +const Keycode K_SCANCODE_MASK = (1 << 30); +macro Keycode @scancode_to_keycode(Scancode $x) => ($x | K_SCANCODE_MASK); + +const Keycode K_UNKNOWN = 0x00000000; +const Keycode K_RETURN = 0x0000000d; +const Keycode K_ESCAPE = 0x0000001b; +const Keycode K_BACKSPACE = 0x00000008; +const Keycode K_TAB = 0x00000009; +const Keycode K_SPACE = 0x00000020; +const Keycode K_EXCLAIM = 0x00000021; +const Keycode K_DBLAPOSTROPHE = 0x00000022; +const Keycode K_HASH = 0x00000023; +const Keycode K_DOLLAR = 0x00000024; +const Keycode K_PERCENT = 0x00000025; +const Keycode K_AMPERSAND = 0x00000026; +const Keycode K_APOSTROPHE = 0x00000027; +const Keycode K_LEFTPAREN = 0x00000028; +const Keycode K_RIGHTPAREN = 0x00000029; +const Keycode K_ASTERISK = 0x0000002a; +const Keycode K_PLUS = 0x0000002b; +const Keycode K_COMMA = 0x0000002c; +const Keycode K_MINUS = 0x0000002d; +const Keycode K_PERIOD = 0x0000002e; +const Keycode K_SLASH = 0x0000002f; +const Keycode K_0 = 0x00000030; +const Keycode K_1 = 0x00000031; +const Keycode K_2 = 0x00000032; +const Keycode K_3 = 0x00000033; +const Keycode K_4 = 0x00000034; +const Keycode K_5 = 0x00000035; +const Keycode K_6 = 0x00000036; +const Keycode K_7 = 0x00000037; +const Keycode K_8 = 0x00000038; +const Keycode K_9 = 0x00000039; +const Keycode K_COLON = 0x0000003a; +const Keycode K_SEMICOLON = 0x0000003b; +const Keycode K_LESS = 0x0000003c; +const Keycode K_EQUALS = 0x0000003d; +const Keycode K_GREATER = 0x0000003e; +const Keycode K_QUESTION = 0x0000003f; +const Keycode K_AT = 0x00000040; +const Keycode K_LEFTBRACKET = 0x0000005b; +const Keycode K_BACKSLASH = 0x0000005c; +const Keycode K_RIGHTBRACKET = 0x0000005d; +const Keycode K_CARET = 0x0000005e; +const Keycode K_UNDERSCORE = 0x0000005f; +const Keycode K_GRAVE = 0x00000060; +const Keycode K_A = 0x00000061; +const Keycode K_B = 0x00000062; +const Keycode K_C = 0x00000063; +const Keycode K_D = 0x00000064; +const Keycode K_E = 0x00000065; +const Keycode K_F = 0x00000066; +const Keycode K_G = 0x00000067; +const Keycode K_H = 0x00000068; +const Keycode K_I = 0x00000069; +const Keycode K_J = 0x0000006a; +const Keycode K_K = 0x0000006b; +const Keycode K_L = 0x0000006c; +const Keycode K_M = 0x0000006d; +const Keycode K_N = 0x0000006e; +const Keycode K_O = 0x0000006f; +const Keycode K_P = 0x00000070; +const Keycode K_Q = 0x00000071; +const Keycode K_R = 0x00000072; +const Keycode K_S = 0x00000073; +const Keycode K_T = 0x00000074; +const Keycode K_U = 0x00000075; +const Keycode K_V = 0x00000076; +const Keycode K_W = 0x00000077; +const Keycode K_X = 0x00000078; +const Keycode K_Y = 0x00000079; +const Keycode K_Z = 0x0000007a; +const Keycode K_LEFTBRACE = 0x0000007b; +const Keycode K_PIPE = 0x0000007c; +const Keycode K_RIGHTBRACE = 0x0000007d; +const Keycode K_TILDE = 0x0000007e; +const Keycode K_DELETE = 0x0000007f; +const Keycode K_PLUSMINUS = 0x000000b1; +const Keycode K_CAPSLOCK = 0x40000039; +const Keycode K_F1 = 0x4000003a; +const Keycode K_F2 = 0x4000003b; +const Keycode K_F3 = 0x4000003c; +const Keycode K_F4 = 0x4000003d; +const Keycode K_F5 = 0x4000003e; +const Keycode K_F6 = 0x4000003f; +const Keycode K_F7 = 0x40000040; +const Keycode K_F8 = 0x40000041; +const Keycode K_F9 = 0x40000042; +const Keycode K_F10 = 0x40000043; +const Keycode K_F11 = 0x40000044; +const Keycode K_F12 = 0x40000045; +const Keycode K_PRINTSCREEN = 0x40000046; +const Keycode K_SCROLLLOCK = 0x40000047; +const Keycode K_PAUSE = 0x40000048; +const Keycode K_INSERT = 0x40000049; +const Keycode K_HOME = 0x4000004a; +const Keycode K_PAGEUP = 0x4000004b; +const Keycode K_END = 0x4000004d; +const Keycode K_PAGEDOWN = 0x4000004e; +const Keycode K_RIGHT = 0x4000004f; +const Keycode K_LEFT = 0x40000050; +const Keycode K_DOWN = 0x40000051; +const Keycode K_UP = 0x40000052; +const Keycode K_NUMLOCKCLEAR = 0x40000053; +const Keycode K_KP_DIVIDE = 0x40000054; +const Keycode K_KP_MULTIPLY = 0x40000055; +const Keycode K_KP_MINUS = 0x40000056; +const Keycode K_KP_PLUS = 0x40000057; +const Keycode K_KP_ENTER = 0x40000058; +const Keycode K_KP_1 = 0x40000059; +const Keycode K_KP_2 = 0x4000005a; +const Keycode K_KP_3 = 0x4000005b; +const Keycode K_KP_4 = 0x4000005c; +const Keycode K_KP_5 = 0x4000005d; +const Keycode K_KP_6 = 0x4000005e; +const Keycode K_KP_7 = 0x4000005f; +const Keycode K_KP_8 = 0x40000060; +const Keycode K_KP_9 = 0x40000061; +const Keycode K_KP_0 = 0x40000062; +const Keycode K_KP_PERIOD = 0x40000063; +const Keycode K_APPLICATION = 0x40000065; +const Keycode K_POWER = 0x40000066; +const Keycode K_KP_EQUALS = 0x40000067; +const Keycode K_F13 = 0x40000068; +const Keycode K_F14 = 0x40000069; +const Keycode K_F15 = 0x4000006a; +const Keycode K_F16 = 0x4000006b; +const Keycode K_F17 = 0x4000006c; +const Keycode K_F18 = 0x4000006d; +const Keycode K_F19 = 0x4000006e; +const Keycode K_F20 = 0x4000006f; +const Keycode K_F21 = 0x40000070; +const Keycode K_F22 = 0x40000071; +const Keycode K_F23 = 0x40000072; +const Keycode K_F24 = 0x40000073; +const Keycode K_EXECUTE = 0x40000074; +const Keycode K_HELP = 0x40000075; +const Keycode K_MENU = 0x40000076; +const Keycode K_SELECT = 0x40000077; +const Keycode K_STOP = 0x40000078; +const Keycode K_AGAIN = 0x40000079; +const Keycode K_UNDO = 0x4000007a; +const Keycode K_CUT = 0x4000007b; +const Keycode K_COPY = 0x4000007c; +const Keycode K_PASTE = 0x4000007d; +const Keycode K_FIND = 0x4000007e; +const Keycode K_MUTE = 0x4000007f; +const Keycode K_VOLUMEUP = 0x40000080; +const Keycode K_VOLUMEDOWN = 0x40000081; +const Keycode K_KP_COMMA = 0x40000085; +const Keycode K_KP_EQUALSAS400 = 0x40000086; +const Keycode K_ALTERASE = 0x40000099; +const Keycode K_SYSREQ = 0x4000009a; +const Keycode K_CANCEL = 0x4000009b; +const Keycode K_CLEAR = 0x4000009c; +const Keycode K_PRIOR = 0x4000009d; +const Keycode K_RETURN2 = 0x4000009e; +const Keycode K_SEPARATOR = 0x4000009f; +const Keycode K_OUT = 0x400000a0; +const Keycode K_OPER = 0x400000a1; +const Keycode K_CLEARAGAIN = 0x400000a2; +const Keycode K_CRSEL = 0x400000a3; +const Keycode K_EXSEL = 0x400000a4; +const Keycode K_KP_00 = 0x400000b0; +const Keycode K_KP_000 = 0x400000b1; +const Keycode K_THOUSANDSSEPARATOR = 0x400000b2; +const Keycode K_DECIMALSEPARATOR = 0x400000b3; +const Keycode K_CURRENCYUNIT = 0x400000b4; +const Keycode K_CURRENCYSUBUNIT = 0x400000b5; +const Keycode K_KP_LEFTPAREN = 0x400000b6; +const Keycode K_KP_RIGHTPAREN = 0x400000b7; +const Keycode K_KP_LEFTBRACE = 0x400000b8; +const Keycode K_KP_RIGHTBRACE = 0x400000b9; +const Keycode K_KP_TAB = 0x400000ba; +const Keycode K_KP_BACKSPACE = 0x400000bb; +const Keycode K_KP_A = 0x400000bc; +const Keycode K_KP_B = 0x400000bd; +const Keycode K_KP_C = 0x400000be; +const Keycode K_KP_D = 0x400000bf; +const Keycode K_KP_E = 0x400000c0; +const Keycode K_KP_F = 0x400000c1; +const Keycode K_KP_XOR = 0x400000c2; +const Keycode K_KP_POWER = 0x400000c3; +const Keycode K_KP_PERCENT = 0x400000c4; +const Keycode K_KP_LESS = 0x400000c5; +const Keycode K_KP_GREATER = 0x400000c6; +const Keycode K_KP_AMPERSAND = 0x400000c7; +const Keycode K_KP_DBLAMPERSAND = 0x400000c8; +const Keycode K_KP_VERTICALBAR = 0x400000c9; +const Keycode K_KP_DBLVERTICALBAR = 0x400000ca; +const Keycode K_KP_COLON = 0x400000cb; +const Keycode K_KP_HASH = 0x400000cc; +const Keycode K_KP_SPACE = 0x400000cd; +const Keycode K_KP_AT = 0x400000ce; +const Keycode K_KP_EXCLAM = 0x400000cf; +const Keycode K_KP_MEMSTORE = 0x400000d0; +const Keycode K_KP_MEMRECALL = 0x400000d1; +const Keycode K_KP_MEMCLEAR = 0x400000d2; +const Keycode K_KP_MEMADD = 0x400000d3; +const Keycode K_KP_MEMSUBTRACT = 0x400000d4; +const Keycode K_KP_MEMMULTIPLY = 0x400000d5; +const Keycode K_KP_MEMDIVIDE = 0x400000d6; +const Keycode K_KP_PLUSMINUS = 0x400000d7; +const Keycode K_KP_CLEAR = 0x400000d8; +const Keycode K_KP_CLEARENTRY = 0x400000d9; +const Keycode K_KP_BINARY = 0x400000da; +const Keycode K_KP_OCTAL = 0x400000db; +const Keycode K_KP_DECIMAL = 0x400000dc; +const Keycode K_KP_HEXADECIMAL = 0x400000dd; +const Keycode K_LCTRL = 0x400000e0; +const Keycode K_LSHIFT = 0x400000e1; +const Keycode K_LALT = 0x400000e2; +const Keycode K_LGUI = 0x400000e3; +const Keycode K_RCTRL = 0x400000e4; +const Keycode K_RSHIFT = 0x400000e5; +const Keycode K_RALT = 0x400000e6; +const Keycode K_RGUI = 0x400000e7; +const Keycode K_MODE = 0x40000101; +const Keycode K_SLEEP = 0x40000102; +const Keycode K_WAKE = 0x40000103; +const Keycode K_CHANNEL_INCREMENT = 0x40000104; +const Keycode K_CHANNEL_DECREMENT = 0x40000105; +const Keycode K_MEDIA_PLAY = 0x40000106; +const Keycode K_MEDIA_PAUSE = 0x40000107; +const Keycode K_MEDIA_RECORD = 0x40000108; +const Keycode K_MEDIA_FAST_FORWARD = 0x40000109; +const Keycode K_MEDIA_REWIND = 0x4000010a; +const Keycode K_MEDIA_NEXT_TRACK = 0x4000010b; +const Keycode K_MEDIA_PREVIOUS_TRACK = 0x4000010c; +const Keycode K_MEDIA_STOP = 0x4000010d; +const Keycode K_MEDIA_EJECT = 0x4000010e; +const Keycode K_MEDIA_PLAY_PAUSE = 0x4000010f; +const Keycode K_MEDIA_SELECT = 0x40000110; +const Keycode K_AC_NEW = 0x40000111; +const Keycode K_AC_OPEN = 0x40000112; +const Keycode K_AC_CLOSE = 0x40000113; +const Keycode K_AC_EXIT = 0x40000114; +const Keycode K_AC_SAVE = 0x40000115; +const Keycode K_AC_PRINT = 0x40000116; +const Keycode K_AC_PROPERTIES = 0x40000117; +const Keycode K_AC_SEARCH = 0x40000118; +const Keycode K_AC_HOME = 0x40000119; +const Keycode K_AC_BACK = 0x4000011a; +const Keycode K_AC_FORWARD = 0x4000011b; +const Keycode K_AC_STOP = 0x4000011c; +const Keycode K_AC_REFRESH = 0x4000011d; +const Keycode K_AC_BOOKMARKS = 0x4000011e; +const Keycode K_SOFTLEFT = 0x4000011f; +const Keycode K_SOFTRIGHT = 0x40000120; +const Keycode K_CALL = 0x40000121; +const Keycode K_ENDCALL = 0x40000122; +const Keycode K_LEFT_TAB = 0x20000001; +const Keycode K_LEVEL5_SHIFT = 0x20000002; +const Keycode K_MULTI_KEY_COMPOSE = 0x20000003; +const Keycode K_LMETA = 0x20000004; +const Keycode K_RMETA = 0x20000005; +const Keycode K_LHYPER = 0x20000006; +const Keycode K_RHYPER = 0x20000007; + +typedef Keymod = ushort; + +const Keymod KMOD_NONE = 0x0000; +const Keymod KMOD_LSHIFT = 0x0001; +const Keymod KMOD_RSHIFT = 0x0002; +const Keymod KMOD_LEVEL5 = 0x0004; +const Keymod KMOD_LCTRL = 0x0040; +const Keymod KMOD_RCTRL = 0x0080; +const Keymod KMOD_LALT = 0x0100; +const Keymod KMOD_RALT = 0x0200; +const Keymod KMOD_LGUI = 0x0400; +const Keymod KMOD_RGUI = 0x0800; +const Keymod KMOD_NUM = 0x1000; +const Keymod KMOD_CAPS = 0x2000; +const Keymod KMOD_MODE = 0x4000; +const Keymod KMOD_SCROLL = 0x8000; +const Keymod KMOD_CTRL = (KMOD_LCTRL | KMOD_RCTRL); +const Keymod KMOD_SHIFT = (KMOD_LSHIFT | KMOD_RSHIFT); +const Keymod KMOD_ALT = (KMOD_LALT | KMOD_RALT); +const Keymod KMOD_GUI = (KMOD_LGUI | KMOD_RGUI); diff --git a/sdl3.c3l/sdl3_mouse.c3i b/sdl3.c3l/sdl3_mouse.c3i new file mode 100644 index 0000000..8ab9bda --- /dev/null +++ b/sdl3.c3l/sdl3_mouse.c3i @@ -0,0 +1,72 @@ +module sdl3::sdl; + +typedef MouseID = uint; + +typedef Cursor = void; + +enum SystemCursor : inline CInt { + SYSTEM_CURSOR_DEFAULT, + SYSTEM_CURSOR_TEXT, + SYSTEM_CURSOR_WAIT, + SYSTEM_CURSOR_CROSSHAIR, + SYSTEM_CURSOR_PROGRESS, + SYSTEM_CURSOR_NWSE_RESIZE, + SYSTEM_CURSOR_NESW_RESIZE, + SYSTEM_CURSOR_EW_RESIZE, + SYSTEM_CURSOR_NS_RESIZE, + SYSTEM_CURSOR_MOVE, + SYSTEM_CURSOR_NOT_ALLOWED, + SYSTEM_CURSOR_POINTER, + SYSTEM_CURSOR_NW_RESIZE, + SYSTEM_CURSOR_N_RESIZE, + SYSTEM_CURSOR_NE_RESIZE, + SYSTEM_CURSOR_E_RESIZE, + SYSTEM_CURSOR_SE_RESIZE, + SYSTEM_CURSOR_S_RESIZE, + SYSTEM_CURSOR_SW_RESIZE, + SYSTEM_CURSOR_W_RESIZE, + SYSTEM_CURSOR_COUNT +} + +enum MouseWheelDirection : inline CInt { + SDL_MOUSEWHEEL_NORMAL, + SDL_MOUSEWHEEL_FLIPPED +} + +typedef MouseButtonFlags = uint; + +const MouseButtonFlags BUTTON_LEFT = 1; +const MouseButtonFlags BUTTON_MIDDLE = 2; +const MouseButtonFlags BUTTON_RIGHT = 3; +const MouseButtonFlags BUTTON_X1 = 4; +const MouseButtonFlags BUTTON_X2 = 5; + +macro MouseButtonFlags @button_mask(MouseButtonFlags $x) => (1 << (($x)-1)); +const MouseButtonFlags BUTTON_LMASK = @button_mask(BUTTON_LEFT); +const MouseButtonFlags BUTTON_MMASK = @button_mask(BUTTON_MIDDLE); +const MouseButtonFlags BUTTON_RMASK = @button_mask(BUTTON_RIGHT); +const MouseButtonFlags BUTTON_X1MASK = @button_mask(BUTTON_X1); +const MouseButtonFlags BUTTON_X2MASK = @button_mask(BUTTON_X2); + +extern fn bool has_mouse() @extern("SDL_HasMouse"); +extern fn MouseID* get_mice(int *count) @extern("SDL_GetMice"); +extern fn ZString get_mouse_name_for_id(MouseID instance_id) @extern("SDL_GetMouseNameForID"); +extern fn Window* get_mouse_focus() @extern("SDL_GetMouseFocus"); +extern fn MouseButtonFlags get_mouse_state(float *x, float *y) @extern("SDL_GetMouseState"); +extern fn MouseButtonFlags get_global_mouse_state(float *x, float *y) @extern("SDL_GetGlobalMouseState"); +extern fn MouseButtonFlags get_relative_mouse_state(float *x, float *y) @extern("SDL_GetRelativeMouseState"); +extern fn void warp_mouse_in_window(Window* window, float x, float y) @extern("SDL_WarpMouseInWindow"); +extern fn bool warp_mouse_global(float x, float y) @extern("SDL_WarpMouseGlobal"); +extern fn bool set_window_relative_mouse_mode(Window* window, bool enabled) @extern("SDL_SetWindowRelativeMouseMode"); +extern fn bool get_window_relative_mouse_mode(Window* window) @extern("SDL_GetWindowRelativeMouseMode"); +extern fn bool capture_mouse(bool enabled) @extern("SDL_CaptureMouse"); +extern fn Cursor* create_cursor(char *data, char *mask, int w, int h, int hot_x, int hot_y) @extern("SDL_CreateCursor"); +extern fn Cursor* create_color_cursor(Surface *surface, int hot_x, int hot_y) @extern("SDL_CreateColorCursor"); +extern fn Cursor* create_system_cursor(SystemCursor id) @extern("SDL_CreateSystemCursor"); +extern fn bool set_cursor(Cursor* cursor) @extern("SDL_SetCursor"); +extern fn Cursor* get_cursor() @extern("SDL_GetCursor"); +extern fn Cursor* get_default_cursor() @extern("SDL_GetDefaultCursor"); +extern fn void destroy_cursor(Cursor* cursor) @extern("SDL_DestroyCursor"); +extern fn bool show_cursor() @extern("SDL_ShowCursor"); +extern fn bool hide_cursor() @extern("SDL_HideCursor"); +extern fn bool cursor_visible() @extern("SDL_CursorVisible"); diff --git a/sdl3.c3l/sdl3_pen.c3i b/sdl3.c3l/sdl3_pen.c3i new file mode 100644 index 0000000..7177f3c --- /dev/null +++ b/sdl3.c3l/sdl3_pen.c3i @@ -0,0 +1,27 @@ +module sdl3::sdl; + +typedef PenID = uint; + +const MouseID PEN_MOUSEID = ((MouseID)-2); +const TouchID PEN_TOUCHID = ((TouchID)-2); + +typedef PenInputFlags = uint; + +const PenInputFlags PEN_INPUT_DOWN = (1 << 0); +const PenInputFlags PEN_INPUT_BUTTON_1 = (1 << 1); +const PenInputFlags PEN_INPUT_BUTTON_2 = (1 << 2); +const PenInputFlags PEN_INPUT_BUTTON_3 = (1 << 3); +const PenInputFlags PEN_INPUT_BUTTON_4 = (1 << 4); +const PenInputFlags PEN_INPUT_BUTTON_5 = (1 << 5); +const PenInputFlags PEN_INPUT_ERASER_TIP = (1 << 30); + +enum PenAxis : inline CInt { + SDL_PEN_AXIS_PRESSURE, + SDL_PEN_AXIS_XTILT, + SDL_PEN_AXIS_YTILT, + SDL_PEN_AXIS_DISTANCE, + SDL_PEN_AXIS_ROTATION, + SDL_PEN_AXIS_SLIDER, + SDL_PEN_AXIS_TANGENTIAL_PRESSURE, + SDL_PEN_AXIS_COUNT +} diff --git a/sdl3.c3l/sdl3_pixels.c3i b/sdl3.c3l/sdl3_pixels.c3i new file mode 100644 index 0000000..bfa3ea8 --- /dev/null +++ b/sdl3.c3l/sdl3_pixels.c3i @@ -0,0 +1,290 @@ +module sdl3::sdl; + +const char ALPHA_OPAQUE = 255; +const char ALPHA_TRANSPARENT = 0; +const float ALPHA_OPAQUE_FLOAT = 1.0; +const float ALPHA_TRANSPARENT_FLOAT = 0.0; + +enum PixelType : inline CInt { + PIXELTYPE_UNKNOWN, + PIXELTYPE_INDEX1, + PIXELTYPE_INDEX4, + PIXELTYPE_INDEX8, + PIXELTYPE_PACKED8, + PIXELTYPE_PACKED16, + PIXELTYPE_PACKED32, + PIXELTYPE_ARRAYU8, + PIXELTYPE_ARRAYU16, + PIXELTYPE_ARRAYU32, + PIXELTYPE_ARRAYF16, + PIXELTYPE_ARRAYF32, + PIXELTYPE_INDEX2 +} + +enum SDL_BitmapOrder : inline CInt { + BITMAPORDER_NONE, + BITMAPORDER_4321, + BITMAPORDER_1234 +} + +enum PackedOrder : inline CInt { + PACKEDORDER_NONE, + PACKEDORDER_XRGB, + PACKEDORDER_RGBX, + PACKEDORDER_ARGB, + PACKEDORDER_RGBA, + PACKEDORDER_XBGR, + PACKEDORDER_BGRX, + PACKEDORDER_ABGR, + PACKEDORDER_BGRA +} + +enum ArrayOrder : inline CInt { + ARRAYORDER_NONE, + ARRAYORDER_RGB, + ARRAYORDER_RGBA, + ARRAYORDER_ARGB, + ARRAYORDER_BGR, + ARRAYORDER_BGRA, + ARRAYORDER_ABGR +} + +enum PackedLayout : inline CInt { + PACKEDLAYOUT_NONE, + PACKEDLAYOUT_332, + PACKEDLAYOUT_4444, + PACKEDLAYOUT_1555, + PACKEDLAYOUT_5551, + PACKEDLAYOUT_565, + PACKEDLAYOUT_8888, + PACKEDLAYOUT_2101010, + PACKEDLAYOUT_1010102 +} + +// TODO: a bunch of pixleformat related macros here i don't want to bother implementing + +typedef PixelFormat = CInt; + +const PixelFormat PIXELFORMAT_UNKNOWN = 0; +const PixelFormat PIXELFORMAT_INDEX1LSB = 0x11100100; +const PixelFormat PIXELFORMAT_INDEX1MSB = 0x11200100; +const PixelFormat PIXELFORMAT_INDEX2LSB = 0x1c100200; +const PixelFormat PIXELFORMAT_INDEX2MSB = 0x1c200200; +const PixelFormat PIXELFORMAT_INDEX4LSB = 0x12100400; +const PixelFormat PIXELFORMAT_INDEX4MSB = 0x12200400; +const PixelFormat PIXELFORMAT_INDEX8 = 0x13000801; +const PixelFormat PIXELFORMAT_RGB332 = 0x14110801; +const PixelFormat PIXELFORMAT_XRGB4444 = 0x15120c02; +const PixelFormat PIXELFORMAT_XBGR4444 = 0x15520c02; +const PixelFormat PIXELFORMAT_XRGB1555 = 0x15130f02; +const PixelFormat PIXELFORMAT_XBGR1555 = 0x15530f02; +const PixelFormat PIXELFORMAT_ARGB4444 = 0x15321002; +const PixelFormat PIXELFORMAT_RGBA4444 = 0x15421002; +const PixelFormat PIXELFORMAT_ABGR4444 = 0x15721002; +const PixelFormat PIXELFORMAT_BGRA4444 = 0x15821002; +const PixelFormat PIXELFORMAT_ARGB1555 = 0x15331002; +const PixelFormat PIXELFORMAT_RGBA5551 = 0x15441002; +const PixelFormat PIXELFORMAT_ABGR1555 = 0x15731002; +const PixelFormat PIXELFORMAT_BGRA5551 = 0x15841002; +const PixelFormat PIXELFORMAT_RGB565 = 0x15151002; +const PixelFormat PIXELFORMAT_BGR565 = 0x15551002; +const PixelFormat PIXELFORMAT_RGB24 = 0x17101803; +const PixelFormat PIXELFORMAT_BGR24 = 0x17401803; +const PixelFormat PIXELFORMAT_XRGB8888 = 0x16161804; +const PixelFormat PIXELFORMAT_RGBX8888 = 0x16261804; +const PixelFormat PIXELFORMAT_XBGR8888 = 0x16561804; +const PixelFormat PIXELFORMAT_BGRX8888 = 0x16661804; +const PixelFormat PIXELFORMAT_ARGB8888 = 0x16362004; +const PixelFormat PIXELFORMAT_RGBA8888 = 0x16462004; +const PixelFormat PIXELFORMAT_ABGR8888 = 0x16762004; +const PixelFormat PIXELFORMAT_BGRA8888 = 0x16862004; +const PixelFormat PIXELFORMAT_XRGB2101010 = 0x16172004; +const PixelFormat PIXELFORMAT_XBGR2101010 = 0x16572004; +const PixelFormat PIXELFORMAT_ARGB2101010 = 0x16372004; +const PixelFormat PIXELFORMAT_ABGR2101010 = 0x16772004; +const PixelFormat PIXELFORMAT_RGB48 = 0x18103006; +const PixelFormat PIXELFORMAT_BGR48 = 0x18403006; +const PixelFormat PIXELFORMAT_RGBA64 = 0x18204008; +const PixelFormat PIXELFORMAT_ARGB64 = 0x18304008; +const PixelFormat PIXELFORMAT_BGRA64 = 0x18504008; +const PixelFormat PIXELFORMAT_ABGR64 = 0x18604008; +const PixelFormat PIXELFORMAT_RGB48_FLOAT = 0x1a103006; +const PixelFormat PIXELFORMAT_BGR48_FLOAT = 0x1a403006; +const PixelFormat PIXELFORMAT_RGBA64_FLOAT = 0x1a204008; +const PixelFormat PIXELFORMAT_ARGB64_FLOAT = 0x1a304008; +const PixelFormat PIXELFORMAT_BGRA64_FLOAT = 0x1a504008; +const PixelFormat PIXELFORMAT_ABGR64_FLOAT = 0x1a604008; +const PixelFormat PIXELFORMAT_RGB96_FLOAT = 0x1b10600c; +const PixelFormat PIXELFORMAT_BGR96_FLOAT = 0x1b40600c; +const PixelFormat PIXELFORMAT_RGBA128_FLOAT = 0x1b208010; +const PixelFormat PIXELFORMAT_ARGB128_FLOAT = 0x1b308010; +const PixelFormat PIXELFORMAT_BGRA128_FLOAT = 0x1b508010; +const PixelFormat PIXELFORMAT_ABGR128_FLOAT = 0x1b608010; +const PixelFormat PIXELFORMAT_YV12 = 0x32315659; +const PixelFormat PIXELFORMAT_IYUV = 0x56555949; +const PixelFormat PIXELFORMAT_YUY2 = 0x32595559; +const PixelFormat PIXELFORMAT_UYVY = 0x59565955; +const PixelFormat PIXELFORMAT_YVYU = 0x55595659; +const PixelFormat PIXELFORMAT_NV12 = 0x3231564e; +const PixelFormat PIXELFORMAT_NV21 = 0x3132564e; +const PixelFormat PIXELFORMAT_P010 = 0x30313050; +const PixelFormat PIXELFORMAT_EXTERNAL_OES = 0x2053454f; +const PixelFormat PIXELFORMAT_MJPG = 0x47504a4d; + // FIXME: this only works in little-endian systems +const PixelFormat PIXELFORMAT_RGBA32 = PIXELFORMAT_ABGR8888; +const PixelFormat PIXELFORMAT_ARGB32 = PIXELFORMAT_BGRA8888; +const PixelFormat PIXELFORMAT_BGRA32 = PIXELFORMAT_ARGB8888; +const PixelFormat PIXELFORMAT_ABGR32 = PIXELFORMAT_RGBA8888; +const PixelFormat PIXELFORMAT_RGBX32 = PIXELFORMAT_XBGR8888; +const PixelFormat PIXELFORMAT_XRGB32 = PIXELFORMAT_BGRX8888; +const PixelFormat PIXELFORMAT_BGRX32 = PIXELFORMAT_XRGB8888; +const PixelFormat PIXELFORMAT_XBGR32 = PIXELFORMAT_RGBX8888; + + +enum ColorType : inline CInt { + COLOR_TYPE_UNKNOWN, + COLOR_TYPE_RGB, + COLOR_TYPE_YCBCR +} + +enum ColorRange : inline CInt { + COLOR_RANGE_UNKNOWN, + COLOR_RANGE_LIMITED, + COLOR_RANGE_FULL +} + +typedef ColorPrimaries = CInt; + +const ColorPrimaries COLOR_PRIMARIES_UNKNOWN = 0; +const ColorPrimaries COLOR_PRIMARIES_BT709 = 1; +const ColorPrimaries COLOR_PRIMARIES_UNSPECIFIED = 2; +const ColorPrimaries COLOR_PRIMARIES_BT470M = 4; +const ColorPrimaries COLOR_PRIMARIES_BT470BG = 5; +const ColorPrimaries COLOR_PRIMARIES_BT601 = 6; +const ColorPrimaries COLOR_PRIMARIES_SMPTE240 = 7; +const ColorPrimaries COLOR_PRIMARIES_GENERIC_FILM = 8; +const ColorPrimaries COLOR_PRIMARIES_BT2020 = 9; +const ColorPrimaries COLOR_PRIMARIES_XYZ = 10; +const ColorPrimaries COLOR_PRIMARIES_SMPTE431 = 11; +const ColorPrimaries COLOR_PRIMARIES_SMPTE432 = 12; +const ColorPrimaries COLOR_PRIMARIES_EBU3213 = 22; +const ColorPrimaries COLOR_PRIMARIES_CUSTOM = 31; + +typedef TransferCharacteristics = CInt; + +const TransferCharacteristics TRANSFER_CHARACTERISTICS_UNKNOWN = 0; +const TransferCharacteristics TRANSFER_CHARACTERISTICS_BT709 = 1; +const TransferCharacteristics TRANSFER_CHARACTERISTICS_UNSPECIFIED = 2; +const TransferCharacteristics TRANSFER_CHARACTERISTICS_GAMMA22 = 4; +const TransferCharacteristics TRANSFER_CHARACTERISTICS_GAMMA28 = 5; +const TransferCharacteristics TRANSFER_CHARACTERISTICS_BT601 = 6; +const TransferCharacteristics TRANSFER_CHARACTERISTICS_SMPTE240 = 7; +const TransferCharacteristics TRANSFER_CHARACTERISTICS_LINEAR = 8; +const TransferCharacteristics TRANSFER_CHARACTERISTICS_LOG100 = 9; +const TransferCharacteristics TRANSFER_CHARACTERISTICS_LOG100_SQRT10 = 10; +const TransferCharacteristics TRANSFER_CHARACTERISTICS_IEC61966 = 11; +const TransferCharacteristics TRANSFER_CHARACTERISTICS_BT1361 = 12; +const TransferCharacteristics TRANSFER_CHARACTERISTICS_SRGB = 13; +const TransferCharacteristics TRANSFER_CHARACTERISTICS_BT2020_10BIT = 14; +const TransferCharacteristics TRANSFER_CHARACTERISTICS_BT2020_12BIT = 15; +const TransferCharacteristics TRANSFER_CHARACTERISTICS_PQ = 16; +const TransferCharacteristics TRANSFER_CHARACTERISTICS_SMPTE428 = 17; +const TransferCharacteristics TRANSFER_CHARACTERISTICS_HLG = 18; +const TransferCharacteristics TRANSFER_CHARACTERISTICS_CUSTOM = 31; + +typedef MatrixCoefficients = CInt; + +const MatrixCoefficients MATRIX_COEFFICIENTS_IDENTITY = 0; +const MatrixCoefficients MATRIX_COEFFICIENTS_BT709 = 1; +const MatrixCoefficients MATRIX_COEFFICIENTS_UNSPECIFIED = 2; +const MatrixCoefficients MATRIX_COEFFICIENTS_FCC = 4; +const MatrixCoefficients MATRIX_COEFFICIENTS_BT470BG = 5; +const MatrixCoefficients MATRIX_COEFFICIENTS_BT601 = 6; +const MatrixCoefficients MATRIX_COEFFICIENTS_SMPTE240 = 7; +const MatrixCoefficients MATRIX_COEFFICIENTS_YCGCO = 8; +const MatrixCoefficients MATRIX_COEFFICIENTS_BT2020_NCL = 9; +const MatrixCoefficients MATRIX_COEFFICIENTS_BT2020_CL = 10; +const MatrixCoefficients MATRIX_COEFFICIENTS_SMPTE2085 = 11; +const MatrixCoefficients MATRIX_COEFFICIENTS_CHROMA_DERIVED_NCL = 12; +const MatrixCoefficients MATRIX_COEFFICIENTS_CHROMA_DERIVED_CL = 13; +const MatrixCoefficients MATRIX_COEFFICIENTS_ICTCP = 14; +const MatrixCoefficients MATRIX_COEFFICIENTS_CUSTOM = 31; + + +typedef ChromaLocation = CInt; + +const ChromaLocation CHROMA_LOCATION_NONE = 0; +const ChromaLocation CHROMA_LOCATION_LEFT = 1; +const ChromaLocation CHROMA_LOCATION_CENTER = 2; +const ChromaLocation CHROMA_LOCATION_TOPLEFT = 3; + + +// TODO: a bunch color space related macros are omitted + +typedef Colorspace = CInt; + +const Colorspace COLORSPACE_UNKNOWN = 0; +const Colorspace COLORSPACE_SRGB = 0x120005a0; +const Colorspace COLORSPACE_SRGB_LINEAR = 0x12000500; +const Colorspace COLORSPACE_HDR10 = 0x12002600; +const Colorspace COLORSPACE_JPEG = 0x220004c6; +const Colorspace COLORSPACE_BT601_LIMITED = 0x211018c6; +const Colorspace COLORSPACE_BT601_FULL = 0x221018c6; +const Colorspace COLORSPACE_BT709_LIMITED = 0x21100421; +const Colorspace COLORSPACE_BT709_FULL = 0x22100421; +const Colorspace COLORSPACE_BT2020_LIMITED = 0x21102609; +const Colorspace COLORSPACE_BT2020_FULL = 0x22102609; +const Colorspace COLORSPACE_RGB_DEFAULT = COLORSPACE_SRGB; +const Colorspace COLORSPACE_YUV_DEFAULT = COLORSPACE_JPEG; + +struct Color { + char r; + char g; + char b; + char a; +} + +struct FColor { + float r; + float g; + float b; + float a; +} + +struct Palette { + int ncolors; + Color* colors; + uint version; + int refcount; +} + +struct PixelFormatDetails { + PixelFormat format; + char bits_per_pixel; + char bytes_per_pixel; + char[2] padding; + uint rmask; + uint gmask; + uint bmask; + uint amask; + char rbits; + char gbits; + char bbits; + char abits; + char rshift; + char gshift; + char bshift; + char ashift; +} + +extern fn ZString get_pixel_format_name(PixelFormat format) @extern("SDL_GetPixelFormatName"); +extern fn bool get_masks_for_pixel_format(PixelFormat format, int *bpp, uint *rmask, uint *gmask, uint *bmask, uint *amask) @extern("SDL_GetMasksForPixelFormat"); +extern fn PixelFormat get_pixel_format_for_masks(int bpp, uint rmask, uint gmask, uint bmask, uint amask) @extern("SDL_GetPixelFormatForMasks"); +extern fn PixelFormatDetails* get_pixel_format_details(PixelFormat format) @extern("SDL_GetPixelFormatDetails"); +extern fn Palette* create_palette(int ncolors) @extern("SDL_CreatePalette"); +extern fn bool set_palette_colors(Palette* palette, Color* colors, int firstcolor, int ncolors) @extern("SDL_SetPaletteColors"); +extern fn void destroy_palette(Palette* palette) @extern("SDL_DestroyPalette"); +extern fn uint map_rgb(PixelFormatDetails *format, Palette* palette, char r, char g, char b) @extern("SDL_MapRGB"); +extern fn uint map_rgba(PixelFormatDetails *format, Palette* palette, char r, char g, char b, char a) @extern("SDL_MapRGBA"); +extern fn void get_rgb(uint pixel, PixelFormatDetails *format, Palette* palette, char *r, char *g, char *b) @extern("SDL_GetRGB"); +extern fn void get_rgba(uint pixel, PixelFormatDetails *format, Palette* palette, char *r, char *g, char *b, char *a) @extern("SDL_GetRGBA"); diff --git a/sdl3.c3l/sdl3_power.c3i b/sdl3.c3l/sdl3_power.c3i new file mode 100644 index 0000000..9f6f7e2 --- /dev/null +++ b/sdl3.c3l/sdl3_power.c3i @@ -0,0 +1,12 @@ +module sdl3::sdl; + +typedef PowerState = CInt; + +const PowerState POWERSTATE_ERROR = -1; +const PowerState POWERSTATE_UNKNOWN = 0; +const PowerState POWERSTATE_ON_BATTERY = 1; +const PowerState POWERSTATE_NO_BATTERY = 2; +const PowerState POWERSTATE_CHARGING = 3; +const PowerState POWERSTATE_CHARGED = 4; + +extern fn PowerState get_power_info(int *seconds, int *percent) @extern("SDL_GetPowerInfo"); diff --git a/sdl3.c3l/sdl3_properties.c3i b/sdl3.c3l/sdl3_properties.c3i new file mode 100644 index 0000000..fd663fa --- /dev/null +++ b/sdl3.c3l/sdl3_properties.c3i @@ -0,0 +1,40 @@ +module sdl3::sdl; + +typedef PropertiesID = uint; + +enum PropertyType : inline CInt { + PROPERTY_TYPE_INVALID, + PROPERTY_TYPE_POINTER, + PROPERTY_TYPE_STRING, + PROPERTY_TYPE_NUMBER, + PROPERTY_TYPE_FLOAT, + PROPERTY_TYPE_BOOLEAN +} + +extern fn PropertiesID get_global_properties() @extern("SDL_GetGlobalProperties"); +extern fn PropertiesID create_properties() @extern("SDL_CreateProperties"); +extern fn bool copy_properties(PropertiesID src, PropertiesID dst) @extern("SDL_CopyProperties"); +extern fn bool lock_properties(PropertiesID props) @extern("SDL_LockProperties"); +extern fn void unlock_properties(PropertiesID props) @extern("SDL_UnlockProperties"); + +alias CleanupPropertyCallback = fn void(void* userdata, void* value); + +extern fn bool set_pointer_property_with_cleanup(PropertiesID props, ZString name, void* value, CleanupPropertyCallback cleanup, void* userdata) @extern("SDL_SetPointerPropertyWithCleanup"); +extern fn bool set_pointer_property(PropertiesID props, ZString name, void* value) @extern("SDL_SetPointerProperty"); +extern fn bool set_string_property(PropertiesID props, ZString name, ZString value) @extern("SDL_SetStringProperty"); +extern fn bool set_number_property(PropertiesID props, ZString name, long value) @extern("SDL_SetNumberProperty"); +extern fn bool set_float_property(PropertiesID props, ZString name, float value) @extern("SDL_SetFloatProperty"); +extern fn bool set_boolean_property(PropertiesID props, ZString name, bool value) @extern("SDL_SetBooleanProperty"); +extern fn bool has_property(PropertiesID props, ZString name) @extern("SDL_HasProperty"); +extern fn PropertyType get_property_type(PropertiesID props, ZString name) @extern("SDL_GetPropertyType"); +extern fn void* get_pointer_property(PropertiesID props, ZString name, void* default_value) @extern("SDL_GetPointerProperty"); +extern fn ZString get_string_property(PropertiesID props, ZString name, ZString default_value) @extern("SDL_GetStringProperty"); +extern fn long get_number_property(PropertiesID props, ZString name, long default_value) @extern("SDL_GetNumberProperty"); +extern fn float get_float_property(PropertiesID props, ZString name, float default_value) @extern("SDL_GetFloatProperty"); +extern fn bool get_boolean_property(PropertiesID props, ZString name, bool default_value) @extern("SDL_GetBooleanProperty"); +extern fn bool clear_property(PropertiesID props, ZString name) @extern("SDL_ClearProperty"); + +alias EnumeratePropertiesCallback = fn void(void* userdata, PropertiesID props, ZString name); + +extern fn bool enumerate_properties(PropertiesID props, EnumeratePropertiesCallback callback, void* userdata) @extern("SDL_EnumerateProperties"); +extern fn void destroy_properties(PropertiesID props) @extern("SDL_DestroyProperties"); diff --git a/sdl3.c3l/sdl3_rect.c3i b/sdl3.c3l/sdl3_rect.c3i new file mode 100644 index 0000000..b2ca24a --- /dev/null +++ b/sdl3.c3l/sdl3_rect.c3i @@ -0,0 +1,86 @@ +module sdl3::sdl; + +struct Point { + int x; + int y; +} + +struct FPoint { + float x; + float y; +} + + +struct Rect { + int x, y; + int w, h; +} + + +struct FRect { + float x; + float y; + float w; + float h; +} + + +macro void rect_to_f_rect(Rect* rect, FRect* frect) +{ + frect.x = (float)rect.x; + frect.y = (float)rect.y; + frect.w = (float)rect.w; + frect.h = (float)rect.h; +} + +macro bool point_in_rect(Point* p, Rect* r) +{ + return ( p && r && (p.x >= r.x) && (p.x < (r.x + r.w)) && + (p.y >= r.y) && (p.y < (r.y + r.h)) ) ? true : false; +} + +macro bool rect_empty(Rect* r) +{ + return ((!r) || (r.w <= 0) || (r.h <= 0)) ? true : false; +} + +macro bool rects_equal(Rect* a, Rect* b) +{ + return (a && b && (a.x == b.x) && (a.y == b.y) && + (a.w == b.w) && (a.h == b.h)) ? true : false; +} + +extern fn bool has_rect_intersection(Rect* a , Rect* b) @extern("SDL_HasRectIntersection"); +extern fn bool get_rect_intersection(Rect* a , Rect* b, Rect* result) @extern("SDL_GetRectIntersection"); +extern fn bool get_rect_union(Rect* a , Rect* b, Rect* result) @extern("SDL_GetRectUnion"); +extern fn bool get_rect_enclosing_points(Point* points, int count, Rect* clip, Rect* result) @extern("SDL_GetRectEnclosingPoints"); +extern fn bool get_rect_and_line_intersection(Rect* rect, int* x1, int* y1, int* x2, int* y2) @extern("SDL_GetRectAndLineIntersection"); + +macro bool point_in_rect_float(FPoint* p, FRect *r) +{ + return ( p && r && (p.x >= r.x) && (p.x <= (r.x + r.w)) && + (p.y >= r.y) && (p.y <= (r.y + r.h)) ) ? true : false; +} + +macro bool rect_empty_float(FRect* r) +{ + return ((!r) || (r.w < 0.0f) || (r.h < 0.0f)) ? true : false; +} + +macro bool rects_equal_epsilon(FRect* a, FRect* b, float epsilon) +{ + return (a && b && ((a == b) || + ((fabsf(a.x - b.x) <= epsilon) && + (fabsf(a.y - b.y) <= epsilon) && + (fabsf(a.w - b.w) <= epsilon) && + (fabsf(a.h - b.h) <= epsilon)))) + ? true : false; +} + +macro bool rects_equal_float(FRect* a, FRect* b) => rects_equal_epsilon(a, b, FLT_EPSILON); + +extern fn bool has_rect_intersection_float(FRect* a , FRect* b) @extern("SDL_HasRectIntersectionFloat"); +extern fn bool get_rect_intersection_float(FRect* a , FRect* b, FRect* result) @extern("SDL_GetRectIntersectionFloat"); +extern fn bool get_rect_union_float(FRect* a , FRect* b, FRect* result) @extern("SDL_GetRectUnionFloat"); +extern fn bool get_rect_enclosing_points_float(FPoint* points, int count, FRect* clip, FRect* result) @extern("SDL_GetRectEnclosingPointsFloat"); +extern fn bool get_rect_and_line_intersection_float(FRect* rect, float* x1, float* y1, float* x2, float* y2) @extern("SDL_GetRectAndLineIntersectionFloat"); \ No newline at end of file diff --git a/sdl3.c3l/sdl3_renderer.c3i b/sdl3.c3l/sdl3_renderer.c3i new file mode 100644 index 0000000..8af212f --- /dev/null +++ b/sdl3.c3l/sdl3_renderer.c3i @@ -0,0 +1,216 @@ +module sdl3::sdl; + +const ZString SOFTWARE_RENDERER = "software"; + +struct Vertex { + FPoint position; + FColor color; + FPoint tex_coord; +} + +enum TextureAccess : inline CInt { + TEXTUREACCESS_STATIC, + TEXTUREACCESS_STREAMING, + TEXTUREACCESS_TARGET +} + +enum RendererLogicalPresentation { + LOGICAL_PRESENTATION_DISABLED, + LOGICAL_PRESENTATION_STRETCH, + LOGICAL_PRESENTATION_LETTERBOX, + LOGICAL_PRESENTATION_OVERSCAN, + LOGICAL_PRESENTATION_INTEGER_SCALE +} + +typedef Renderer = void; +typedef Texture = void; + +extern fn int get_num_render_drivers() @extern("SDL_GetNumRenderDrivers"); +extern fn ZString get_render_driver(int index) @extern("SDL_GetRenderDriver"); +extern fn bool create_window_and_renderer(ZString title, int width, int height, WindowFlags window_flags, Window **window, Renderer **renderer) @extern("SDL_CreateWindowAndRenderer"); +extern fn Renderer* create_renderer(Window* window, ZString name) @extern("SDL_CreateRenderer"); +extern fn Renderer* create_renderer_with_properties(PropertiesID props) @extern("SDL_CreateRendererWithProperties"); + +const ZString PROP_RENDERER_CREATE_NAME_STRING = "SDL.renderer.create.name"; +const ZString PROP_RENDERER_CREATE_WINDOW_POINTER = "SDL.renderer.create.window"; +const ZString PROP_RENDERER_CREATE_SURFACE_POINTER = "SDL.renderer.create.surface"; +const ZString PROP_RENDERER_CREATE_OUTPUT_COLORSPACE_NUMBER = "SDL.renderer.create.output_colorspace"; +const ZString PROP_RENDERER_CREATE_PRESENT_VSYNC_NUMBER = "SDL.renderer.create.present_vsync"; +const ZString PROP_RENDERER_CREATE_VULKAN_INSTANCE_POINTER = "SDL.renderer.create.vulkan.instance"; +const ZString PROP_RENDERER_CREATE_VULKAN_SURFACE_NUMBER = "SDL.renderer.create.vulkan.surface"; +const ZString PROP_RENDERER_CREATE_VULKAN_PHYSICAL_DEVICE_POINTER = "SDL.renderer.create.vulkan.physical_device"; +const ZString PROP_RENDERER_CREATE_VULKAN_DEVICE_POINTER = "SDL.renderer.create.vulkan.device"; +const ZString PROP_RENDERER_CREATE_VULKAN_GRAPHICS_QUEUE_FAMILY_INDEX_NUMBER = "SDL.renderer.create.vulkan.graphics_queue_family_index"; +const ZString PROP_RENDERER_CREATE_VULKAN_PRESENT_QUEUE_FAMILY_INDEX_NUMBER = "SDL.renderer.create.vulkan.present_queue_family_index"; + +extern fn Renderer* create_software_renderer(Surface *surface) @extern("SDL_CreateSoftwareRenderer"); +extern fn Renderer* get_renderer(Window* window) @extern("SDL_GetRenderer"); +extern fn Window* get_render_window(Renderer* renderer) @extern("SDL_GetRenderWindow"); +extern fn ZString get_renderer_name(Renderer* renderer) @extern("SDL_GetRendererName"); +extern fn PropertiesID get_renderer_properties(Renderer* renderer) @extern("SDL_GetRendererProperties"); + +const ZString PROP_RENDERER_NAME_STRING = "SDL.renderer.name"; +const ZString PROP_RENDERER_WINDOW_POINTER = "SDL.renderer.window"; +const ZString PROP_RENDERER_SURFACE_POINTER = "SDL.renderer.surface"; +const ZString PROP_RENDERER_VSYNC_NUMBER = "SDL.renderer.vsync"; +const ZString PROP_RENDERER_MAX_TEXTURE_SIZE_NUMBER = "SDL.renderer.max_texture_size"; +const ZString PROP_RENDERER_TEXTURE_FORMATS_POINTER = "SDL.renderer.texture_formats"; +const ZString PROP_RENDERER_OUTPUT_COLORSPACE_NUMBER = "SDL.renderer.output_colorspace"; +const ZString PROP_RENDERER_HDR_ENABLED_BOOLEAN = "SDL.renderer.HDR_enabled"; +const ZString PROP_RENDERER_SDR_WHITE_POINT_FLOAT = "SDL.renderer.SDR_white_point"; +const ZString PROP_RENDERER_HDR_HEADROOM_FLOAT = "SDL.renderer.HDR_headroom"; +const ZString PROP_RENDERER_D3D9_DEVICE_POINTER = "SDL.renderer.d3d9.device"; +const ZString PROP_RENDERER_D3D11_DEVICE_POINTER = "SDL.renderer.d3d11.device"; +const ZString PROP_RENDERER_D3D11_SWAPCHAIN_POINTER = "SDL.renderer.d3d11.swap_chain"; +const ZString PROP_RENDERER_D3D12_DEVICE_POINTER = "SDL.renderer.d3d12.device"; +const ZString PROP_RENDERER_D3D12_SWAPCHAIN_POINTER = "SDL.renderer.d3d12.swap_chain"; +const ZString PROP_RENDERER_D3D12_COMMAND_QUEUE_POINTER = "SDL.renderer.d3d12.command_queue"; +const ZString PROP_RENDERER_VULKAN_INSTANCE_POINTER = "SDL.renderer.vulkan.instance"; +const ZString PROP_RENDERER_VULKAN_SURFACE_NUMBER = "SDL.renderer.vulkan.surface"; +const ZString PROP_RENDERER_VULKAN_PHYSICAL_DEVICE_POINTER = "SDL.renderer.vulkan.physical_device"; +const ZString PROP_RENDERER_VULKAN_DEVICE_POINTER = "SDL.renderer.vulkan.device"; +const ZString PROP_RENDERER_VULKAN_GRAPHICS_QUEUE_FAMILY_INDEX_NUMBER = "SDL.renderer.vulkan.graphics_queue_family_index"; +const ZString PROP_RENDERER_VULKAN_PRESENT_QUEUE_FAMILY_INDEX_NUMBER = "SDL.renderer.vulkan.present_queue_family_index"; +const ZString PROP_RENDERER_VULKAN_SWAPCHAIN_IMAGE_COUNT_NUMBER = "SDL.renderer.vulkan.swapchain_image_count"; +const ZString PROP_RENDERER_GPU_DEVICE_POINTER = "SDL.renderer.gpu.device"; + +extern fn bool get_render_output_size(Renderer* renderer, int *w, int *h) @extern("SDL_GetRenderOutputSize"); +extern fn bool get_current_render_output_size(Renderer* renderer, int *w, int *h) @extern("SDL_GetCurrentRenderOutputSize"); +extern fn Texture* create_texture(Renderer* renderer, PixelFormat format, TextureAccess access, int w, int h) @extern("SDL_CreateTexture"); +extern fn Texture* create_texture_from_surface(Renderer* renderer, Surface *surface) @extern("SDL_CreateTextureFromSurface"); +extern fn Texture* create_texture_with_properties(Renderer* renderer, PropertiesID props) @extern("SDL_CreateTextureWithProperties"); + +const ZString PROP_TEXTURE_CREATE_COLORSPACE_NUMBER = "SDL.texture.create.colorspace"; +const ZString PROP_TEXTURE_CREATE_FORMAT_NUMBER = "SDL.texture.create.format"; +const ZString PROP_TEXTURE_CREATE_ACCESS_NUMBER = "SDL.texture.create.access"; +const ZString PROP_TEXTURE_CREATE_WIDTH_NUMBER = "SDL.texture.create.width"; +const ZString PROP_TEXTURE_CREATE_HEIGHT_NUMBER = "SDL.texture.create.height"; +const ZString PROP_TEXTURE_CREATE_SDR_WHITE_POINT_FLOAT = "SDL.texture.create.SDR_white_point"; +const ZString PROP_TEXTURE_CREATE_HDR_HEADROOM_FLOAT = "SDL.texture.create.HDR_headroom"; +const ZString PROP_TEXTURE_CREATE_D3D11_TEXTURE_POINTER = "SDL.texture.create.d3d11.texture"; +const ZString PROP_TEXTURE_CREATE_D3D11_TEXTURE_U_POINTER = "SDL.texture.create.d3d11.texture_u"; +const ZString PROP_TEXTURE_CREATE_D3D11_TEXTURE_V_POINTER = "SDL.texture.create.d3d11.texture_v"; +const ZString PROP_TEXTURE_CREATE_D3D12_TEXTURE_POINTER = "SDL.texture.create.d3d12.texture"; +const ZString PROP_TEXTURE_CREATE_D3D12_TEXTURE_U_POINTER = "SDL.texture.create.d3d12.texture_u"; +const ZString PROP_TEXTURE_CREATE_D3D12_TEXTURE_V_POINTER = "SDL.texture.create.d3d12.texture_v"; +const ZString PROP_TEXTURE_CREATE_METAL_PIXELBUFFER_POINTER = "SDL.texture.create.metal.pixelbuffer"; +const ZString PROP_TEXTURE_CREATE_OPENGL_TEXTURE_NUMBER = "SDL.texture.create.opengl.texture"; +const ZString PROP_TEXTURE_CREATE_OPENGL_TEXTURE_UV_NUMBER = "SDL.texture.create.opengl.texture_uv"; +const ZString PROP_TEXTURE_CREATE_OPENGL_TEXTURE_U_NUMBER = "SDL.texture.create.opengl.texture_u"; +const ZString PROP_TEXTURE_CREATE_OPENGL_TEXTURE_V_NUMBER = "SDL.texture.create.opengl.texture_v"; +const ZString PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_NUMBER = "SDL.texture.create.opengles2.texture"; +const ZString PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_UV_NUMBER = "SDL.texture.create.opengles2.texture_uv"; +const ZString PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_U_NUMBER = "SDL.texture.create.opengles2.texture_u"; +const ZString PROP_TEXTURE_CREATE_OPENGLES2_TEXTURE_V_NUMBER = "SDL.texture.create.opengles2.texture_v"; +const ZString PROP_TEXTURE_CREATE_VULKAN_TEXTURE_NUMBER = "SDL.texture.create.vulkan.texture"; + +extern fn PropertiesID get_texture_properties(Texture* texture) @extern("SDL_GetTextureProperties"); + +const ZString PROP_TEXTURE_COLORSPACE_NUMBER = "SDL.texture.colorspace"; +const ZString PROP_TEXTURE_FORMAT_NUMBER = "SDL.texture.format"; +const ZString PROP_TEXTURE_ACCESS_NUMBER = "SDL.texture.access"; +const ZString PROP_TEXTURE_WIDTH_NUMBER = "SDL.texture.width"; +const ZString PROP_TEXTURE_HEIGHT_NUMBER = "SDL.texture.height"; +const ZString PROP_TEXTURE_SDR_WHITE_POINT_FLOAT = "SDL.texture.SDR_white_point"; +const ZString PROP_TEXTURE_HDR_HEADROOM_FLOAT = "SDL.texture.HDR_headroom"; +const ZString PROP_TEXTURE_D3D11_TEXTURE_POINTER = "SDL.texture.d3d11.texture"; +const ZString PROP_TEXTURE_D3D11_TEXTURE_U_POINTER = "SDL.texture.d3d11.texture_u"; +const ZString PROP_TEXTURE_D3D11_TEXTURE_V_POINTER = "SDL.texture.d3d11.texture_v"; +const ZString PROP_TEXTURE_D3D12_TEXTURE_POINTER = "SDL.texture.d3d12.texture"; +const ZString PROP_TEXTURE_D3D12_TEXTURE_U_POINTER = "SDL.texture.d3d12.texture_u"; +const ZString PROP_TEXTURE_D3D12_TEXTURE_V_POINTER = "SDL.texture.d3d12.texture_v"; +const ZString PROP_TEXTURE_OPENGL_TEXTURE_NUMBER = "SDL.texture.opengl.texture"; +const ZString PROP_TEXTURE_OPENGL_TEXTURE_UV_NUMBER = "SDL.texture.opengl.texture_uv"; +const ZString PROP_TEXTURE_OPENGL_TEXTURE_U_NUMBER = "SDL.texture.opengl.texture_u"; +const ZString PROP_TEXTURE_OPENGL_TEXTURE_V_NUMBER = "SDL.texture.opengl.texture_v"; +const ZString PROP_TEXTURE_OPENGL_TEXTURE_TARGET_NUMBER = "SDL.texture.opengl.target"; +const ZString PROP_TEXTURE_OPENGL_TEX_W_FLOAT = "SDL.texture.opengl.tex_w"; +const ZString PROP_TEXTURE_OPENGL_TEX_H_FLOAT = "SDL.texture.opengl.tex_h"; +const ZString PROP_TEXTURE_OPENGLES2_TEXTURE_NUMBER = "SDL.texture.opengles2.texture"; +const ZString PROP_TEXTURE_OPENGLES2_TEXTURE_UV_NUMBER = "SDL.texture.opengles2.texture_uv"; +const ZString PROP_TEXTURE_OPENGLES2_TEXTURE_U_NUMBER = "SDL.texture.opengles2.texture_u"; +const ZString PROP_TEXTURE_OPENGLES2_TEXTURE_V_NUMBER = "SDL.texture.opengles2.texture_v"; +const ZString PROP_TEXTURE_OPENGLES2_TEXTURE_TARGET_NUMBER = "SDL.texture.opengles2.target"; +const ZString PROP_TEXTURE_VULKAN_TEXTURE_NUMBER = "SDL.texture.vulkan.texture"; + +extern fn Renderer* get_renderer_from_texture(Texture* texture) @extern("SDL_GetRendererFromTexture"); +extern fn bool get_texture_size(Texture* texture, float *w, float *h) @extern("SDL_GetTextureSize"); +extern fn bool set_texture_color_mod(Texture* texture, char r, char g, char b) @extern("SDL_SetTextureColorMod"); +extern fn bool set_texture_color_mod_float(Texture* texture, float r, float g, float b) @extern("SDL_SetTextureColorModFloat"); +extern fn bool get_texture_color_mod(Texture* texture, char* r, char* g, char* b) @extern("SDL_GetTextureColorMod"); +extern fn bool get_texture_color_mod_float(Texture* texture, float *r, float *g, float *b) @extern("SDL_GetTextureColorModFloat"); +extern fn bool set_texture_alpha_mod(Texture* texture, char alpha) @extern("SDL_SetTextureAlphaMod"); +extern fn bool set_texture_alpha_mod_float(Texture* texture, float alpha) @extern("SDL_SetTextureAlphaModFloat"); +extern fn bool get_texture_alpha_mod(Texture* texture, char* alpha) @extern("SDL_GetTextureAlphaMod"); +extern fn bool get_texture_alpha_mod_float(Texture* texture, float *alpha) @extern("SDL_GetTextureAlphaModFloat"); +extern fn bool set_texture_blend_mode(Texture* texture, BlendMode blendMode) @extern("SDL_SetTextureBlendMode"); +extern fn bool get_texture_blend_mode(Texture* texture, BlendMode *blendMode) @extern("SDL_GetTextureBlendMode"); +extern fn bool set_texture_scale_mode(Texture* texture, ScaleMode scaleMode) @extern("SDL_SetTextureScaleMode"); +extern fn bool get_texture_scale_mode(Texture* texture, ScaleMode *scaleMode) @extern("SDL_GetTextureScaleMode"); +extern fn bool update_texture(Texture* texture, Rect* rect, void* pixels, int pitch) @extern("SDL_UpdateTexture"); +extern fn bool update_yuv_texture(Texture* texture, Rect* rect, char* yplane, int ypitch, char* uplane, int upitch, char* vplane, int vpitch) @extern("SDL_UpdateYUVTexture"); +extern fn bool update_nv_texture(Texture* texture, Rect* rect, char* yplane, int ypitch, char* u_vplane, int u_vpitch) @extern("SDL_UpdateNVTexture"); +extern fn bool lock_texture(Texture* texture, Rect* rect, void **pixels, int *pitch) @extern("SDL_LockTexture"); +extern fn bool lock_texture_to_surface(Texture* texture, Rect* rect, Surface **surface) @extern("SDL_LockTextureToSurface"); +extern fn void unlock_texture(Texture* texture) @extern("SDL_UnlockTexture"); +extern fn bool set_render_target(Renderer* renderer, Texture* texture) @extern("SDL_SetRenderTarget"); +extern fn Texture* get_render_target(Renderer* renderer) @extern("SDL_GetRenderTarget"); +extern fn bool set_render_logical_presentation(Renderer* renderer, int w, int h, RendererLogicalPresentation mode) @extern("SDL_SetRenderLogicalPresentation"); +extern fn bool get_render_logical_presentation(Renderer* renderer, int *w, int *h, RendererLogicalPresentation *mode) @extern("SDL_GetRenderLogicalPresentation"); +extern fn bool get_render_logical_presentation_rect(Renderer* renderer, FRect *rect) @extern("SDL_GetRenderLogicalPresentationRect"); +extern fn bool render_coordinates_from_window(Renderer* renderer, float window_x, float window_y, float *x, float *y) @extern("SDL_RenderCoordinatesFromWindow"); +extern fn bool render_coordinates_to_window(Renderer* renderer, float x, float y, float *window_x, float *window_y) @extern("SDL_RenderCoordinatesToWindow"); +extern fn bool convert_event_to_render_coordinates(Renderer* renderer, Event *event) @extern("SDL_ConvertEventToRenderCoordinates"); +extern fn bool set_render_viewport(Renderer* renderer, Rect* rect) @extern("SDL_SetRenderViewport"); +extern fn bool get_render_viewport(Renderer* renderer, Rect* rect) @extern("SDL_GetRenderViewport"); +extern fn bool render_viewport_set(Renderer* renderer) @extern("SDL_RenderViewportSet"); +extern fn bool get_render_safe_area(Renderer* renderer, Rect* rect) @extern("SDL_GetRenderSafeArea"); +extern fn bool set_render_clip_rect(Renderer* renderer, Rect* rect) @extern("SDL_SetRenderClipRect"); +extern fn bool get_render_clip_rect(Renderer* renderer, Rect* rect) @extern("SDL_GetRenderClipRect"); +extern fn bool render_clip_enabled(Renderer* renderer) @extern("SDL_RenderClipEnabled"); +extern fn bool set_render_scale(Renderer* renderer, float scaleX, float scaleY) @extern("SDL_SetRenderScale"); +extern fn bool get_render_scale(Renderer* renderer, float *scaleX, float *scaleY) @extern("SDL_GetRenderScale"); +extern fn bool set_render_draw_color(Renderer* renderer, char r, char g, char b, char a) @extern("SDL_SetRenderDrawColor"); +extern fn bool set_render_draw_color_float(Renderer* renderer, float r, float g, float b, float a) @extern("SDL_SetRenderDrawColorFloat"); +extern fn bool get_render_draw_color(Renderer* renderer, char* r, char* g, char* b, char* a) @extern("SDL_GetRenderDrawColor"); +extern fn bool get_render_draw_color_float(Renderer* renderer, float *r, float *g, float *b, float *a) @extern("SDL_GetRenderDrawColorFloat"); +extern fn bool set_render_color_scale(Renderer* renderer, float scale) @extern("SDL_SetRenderColorScale"); +extern fn bool get_render_color_scale(Renderer* renderer, float *scale) @extern("SDL_GetRenderColorScale"); +extern fn bool set_render_draw_blend_mode(Renderer* renderer, BlendMode blendMode) @extern("SDL_SetRenderDrawBlendMode"); +extern fn bool get_render_draw_blend_mode(Renderer* renderer, BlendMode *blendMode) @extern("SDL_GetRenderDrawBlendMode"); +extern fn bool render_clear(Renderer* renderer) @extern("SDL_RenderClear"); +extern fn bool render_point(Renderer* renderer, float x, float y) @extern("SDL_RenderPoint"); +extern fn bool render_points(Renderer* renderer, FPoint* points, int count) @extern("SDL_RenderPoints"); +extern fn bool render_line(Renderer* renderer, float x1, float y1, float x2, float y2) @extern("SDL_RenderLine"); +extern fn bool render_lines(Renderer* renderer, FPoint* points, int count) @extern("SDL_RenderLines"); +extern fn bool render_rect(Renderer* renderer, FRect* rect) @extern("SDL_RenderRect"); +extern fn bool render_rects(Renderer* renderer, FRect* rects, int count) @extern("SDL_RenderRects"); +extern fn bool render_fill_rect(Renderer* renderer, FRect* rect) @extern("SDL_RenderFillRect"); +extern fn bool render_fill_rects(Renderer* renderer, FRect* rects, int count) @extern("SDL_RenderFillRects"); +extern fn bool render_texture(Renderer* renderer, Texture* texture, FRect* srcrect, FRect* dstrect) @extern("SDL_RenderTexture"); +extern fn bool render_texture_rotated(Renderer* renderer, Texture* texture, FRect* srcrect, FRect* dstrect, double angle, FPoint* center, FlipMode flip) @extern("SDL_RenderTextureRotated"); +extern fn bool render_texture_affine(Renderer* renderer, Texture* texture, FRect* srcrect, FPoint* origin, FPoint* right, FPoint* down) @extern("SDL_RenderTextureAffine"); +extern fn bool render_texture_tiled(Renderer* renderer, Texture* texture, FRect* srcrect, float scale, FRect* dstrect) @extern("SDL_RenderTextureTiled"); +extern fn bool render_texture9_grid(Renderer* renderer, Texture* texture, FRect* srcrect, float left_width, float right_width, float top_height, float bottom_height, float scale, FRect* dstrect) @extern("SDL_RenderTexture9Grid"); +extern fn bool render_geometry(Renderer* renderer, Texture* texture, Vertex* vertices, int num_vertices, int* indices, int num_indices) @extern("SDL_RenderGeometry"); +extern fn bool render_geometry_raw(Renderer* renderer, Texture* texture, float* xy, int xy_stride, FColor* color, int color_stride, float* uv, int uv_stride, int num_vertices, void* indices, int num_indices, int size_indices) @extern("SDL_RenderGeometryRaw"); +extern fn Surface* render_read_pixels(Renderer* renderer, Rect* rect) @extern("SDL_RenderReadPixels"); +extern fn bool render_present(Renderer* renderer) @extern("SDL_RenderPresent"); +extern fn void destroy_texture(Texture* texture) @extern("SDL_DestroyTexture"); +extern fn void destroy_renderer(Renderer* renderer) @extern("SDL_DestroyRenderer"); +extern fn bool flush_renderer(Renderer* renderer) @extern("SDL_FlushRenderer"); +extern fn void* get_render_metal_layer(Renderer* renderer) @extern("SDL_GetRenderMetalLayer"); +extern fn void* get_render_metal_command_encoder(Renderer* renderer) @extern("SDL_GetRenderMetalCommandEncoder"); +extern fn bool add_vulkan_render_semaphores(Renderer* renderer, uint wait_stage_mask, long wait_semaphore, long signal_semaphore) @extern("SDL_AddVulkanRenderSemaphores"); +extern fn bool set_render_v_sync(Renderer* renderer, int vsync) @extern("SDL_SetRenderVSync"); + +const int RENDERER_VSYNC_DISABLED = 0; +const int RENDERER_VSYNC_ADAPTIVE = -1; + +extern fn bool get_render_v_sync(Renderer* renderer, int* vsync) @extern("SDL_GetRenderVSync"); + +const int DEBUG_TEXT_FONT_CHARACTER_SIZE = 8; + +extern fn bool render_debug_text(Renderer* renderer, float x, float y, ZString str) @extern("SDL_RenderDebugText"); +extern fn bool render_debug_text_format(Renderer* renderer, float x, float y, ZString fmt, ...) @extern("SDL_RenderDebugTextFormat"); + diff --git a/sdl3.c3l/sdl3_scancode.c3i b/sdl3.c3l/sdl3_scancode.c3i new file mode 100644 index 0000000..28f4da9 --- /dev/null +++ b/sdl3.c3l/sdl3_scancode.c3i @@ -0,0 +1,253 @@ +module sdl3::sdl; + +typedef Scancode = CInt; + +const Scancode SCANCODE_UNKNOWN = 0; +const Scancode SCANCODE_A = 4; +const Scancode SCANCODE_B = 5; +const Scancode SCANCODE_C = 6; +const Scancode SCANCODE_D = 7; +const Scancode SCANCODE_E = 8; +const Scancode SCANCODE_F = 9; +const Scancode SCANCODE_G = 10; +const Scancode SCANCODE_H = 11; +const Scancode SCANCODE_I = 12; +const Scancode SCANCODE_J = 13; +const Scancode SCANCODE_K = 14; +const Scancode SCANCODE_L = 15; +const Scancode SCANCODE_M = 16; +const Scancode SCANCODE_N = 17; +const Scancode SCANCODE_O = 18; +const Scancode SCANCODE_P = 19; +const Scancode SCANCODE_Q = 20; +const Scancode SCANCODE_R = 21; +const Scancode SCANCODE_S = 22; +const Scancode SCANCODE_T = 23; +const Scancode SCANCODE_U = 24; +const Scancode SCANCODE_V = 25; +const Scancode SCANCODE_W = 26; +const Scancode SCANCODE_X = 27; +const Scancode SCANCODE_Y = 28; +const Scancode SCANCODE_Z = 29; +const Scancode SCANCODE_1 = 30; +const Scancode SCANCODE_2 = 31; +const Scancode SCANCODE_3 = 32; +const Scancode SCANCODE_4 = 33; +const Scancode SCANCODE_5 = 34; +const Scancode SCANCODE_6 = 35; +const Scancode SCANCODE_7 = 36; +const Scancode SCANCODE_8 = 37; +const Scancode SCANCODE_9 = 38; +const Scancode SCANCODE_0 = 39; +const Scancode SCANCODE_RETURN = 40; +const Scancode SCANCODE_ESCAPE = 41; +const Scancode SCANCODE_BACKSPACE = 42; +const Scancode SCANCODE_TAB = 43; +const Scancode SCANCODE_SPACE = 44; +const Scancode SCANCODE_MINUS = 45; +const Scancode SCANCODE_EQUALS = 46; +const Scancode SCANCODE_LEFTBRACKET = 47; +const Scancode SCANCODE_RIGHTBRACKET = 48; +const Scancode SCANCODE_BACKSLASH = 49; +const Scancode SCANCODE_NONUSHASH = 50; +const Scancode SCANCODE_SEMICOLON = 51; +const Scancode SCANCODE_APOSTROPHE = 52; +const Scancode SCANCODE_GRAVE = 53; +const Scancode SCANCODE_COMMA = 54; +const Scancode SCANCODE_PERIOD = 55; +const Scancode SCANCODE_SLASH = 56; +const Scancode SCANCODE_CAPSLOCK = 57; +const Scancode SCANCODE_F1 = 58; +const Scancode SCANCODE_F2 = 59; +const Scancode SCANCODE_F3 = 60; +const Scancode SCANCODE_F4 = 61; +const Scancode SCANCODE_F5 = 62; +const Scancode SCANCODE_F6 = 63; +const Scancode SCANCODE_F7 = 64; +const Scancode SCANCODE_F8 = 65; +const Scancode SCANCODE_F9 = 66; +const Scancode SCANCODE_F10 = 67; +const Scancode SCANCODE_F11 = 68; +const Scancode SCANCODE_F12 = 69; +const Scancode SCANCODE_PRINTSCREEN = 70; +const Scancode SCANCODE_SCROLLLOCK = 71; +const Scancode SCANCODE_PAUSE = 72; +const Scancode SCANCODE_INSERT = 73; +const Scancode SCANCODE_HOME = 74; +const Scancode SCANCODE_PAGEUP = 75; +const Scancode SCANCODE_DELETE = 76; +const Scancode SCANCODE_END = 77; +const Scancode SCANCODE_PAGEDOWN = 78; +const Scancode SCANCODE_RIGHT = 79; +const Scancode SCANCODE_LEFT = 80; +const Scancode SCANCODE_DOWN = 81; +const Scancode SCANCODE_UP = 82; +const Scancode SCANCODE_NUMLOCKCLEAR = 83; +const Scancode SCANCODE_KP_DIVIDE = 84; +const Scancode SCANCODE_KP_MULTIPLY = 85; +const Scancode SCANCODE_KP_MINUS = 86; +const Scancode SCANCODE_KP_PLUS = 87; +const Scancode SCANCODE_KP_ENTER = 88; +const Scancode SCANCODE_KP_1 = 89; +const Scancode SCANCODE_KP_2 = 90; +const Scancode SCANCODE_KP_3 = 91; +const Scancode SCANCODE_KP_4 = 92; +const Scancode SCANCODE_KP_5 = 93; +const Scancode SCANCODE_KP_6 = 94; +const Scancode SCANCODE_KP_7 = 95; +const Scancode SCANCODE_KP_8 = 96; +const Scancode SCANCODE_KP_9 = 97; +const Scancode SCANCODE_KP_0 = 98; +const Scancode SCANCODE_KP_PERIOD = 99; +const Scancode SCANCODE_NONUSBACKSLASH = 100; +const Scancode SCANCODE_APPLICATION = 101; +const Scancode SCANCODE_POWER = 102; +const Scancode SCANCODE_KP_EQUALS = 103; +const Scancode SCANCODE_F13 = 104; +const Scancode SCANCODE_F14 = 105; +const Scancode SCANCODE_F15 = 106; +const Scancode SCANCODE_F16 = 107; +const Scancode SCANCODE_F17 = 108; +const Scancode SCANCODE_F18 = 109; +const Scancode SCANCODE_F19 = 110; +const Scancode SCANCODE_F20 = 111; +const Scancode SCANCODE_F21 = 112; +const Scancode SCANCODE_F22 = 113; +const Scancode SCANCODE_F23 = 114; +const Scancode SCANCODE_F24 = 115; +const Scancode SCANCODE_EXECUTE = 116; +const Scancode SCANCODE_HELP = 117; +const Scancode SCANCODE_MENU = 118; +const Scancode SCANCODE_SELECT = 119; +const Scancode SCANCODE_STOP = 120; +const Scancode SCANCODE_AGAIN = 121; +const Scancode SCANCODE_UNDO = 122; +const Scancode SCANCODE_CUT = 123; +const Scancode SCANCODE_COPY = 124; +const Scancode SCANCODE_PASTE = 125; +const Scancode SCANCODE_FIND = 126; +const Scancode SCANCODE_MUTE = 127; +const Scancode SCANCODE_VOLUMEUP = 128; +const Scancode SCANCODE_VOLUMEDOWN = 129; +const Scancode SCANCODE_KP_COMMA = 133; +const Scancode SCANCODE_KP_EQUALSAS400 = 134; +const Scancode SCANCODE_INTERNATIONAL1 = 135; +const Scancode SCANCODE_INTERNATIONAL2 = 136; +const Scancode SCANCODE_INTERNATIONAL3 = 137; +const Scancode SCANCODE_INTERNATIONAL4 = 138; +const Scancode SCANCODE_INTERNATIONAL5 = 139; +const Scancode SCANCODE_INTERNATIONAL6 = 140; +const Scancode SCANCODE_INTERNATIONAL7 = 141; +const Scancode SCANCODE_INTERNATIONAL8 = 142; +const Scancode SCANCODE_INTERNATIONAL9 = 143; +const Scancode SCANCODE_LANG1 = 144; +const Scancode SCANCODE_LANG2 = 145; +const Scancode SCANCODE_LANG3 = 146; +const Scancode SCANCODE_LANG4 = 147; +const Scancode SCANCODE_LANG5 = 148; +const Scancode SCANCODE_LANG6 = 149; +const Scancode SCANCODE_LANG7 = 150; +const Scancode SCANCODE_LANG8 = 151; +const Scancode SCANCODE_LANG9 = 152; +const Scancode SCANCODE_ALTERASE = 153; +const Scancode SCANCODE_SYSREQ = 154; +const Scancode SCANCODE_CANCEL = 155; +const Scancode SCANCODE_CLEAR = 156; +const Scancode SCANCODE_PRIOR = 157; +const Scancode SCANCODE_RETURN2 = 158; +const Scancode SCANCODE_SEPARATOR = 159; +const Scancode SCANCODE_OUT = 160; +const Scancode SCANCODE_OPER = 161; +const Scancode SCANCODE_CLEARAGAIN = 162; +const Scancode SCANCODE_CRSEL = 163; +const Scancode SCANCODE_EXSEL = 164; +const Scancode SCANCODE_KP_00 = 176; +const Scancode SCANCODE_KP_000 = 177; +const Scancode SCANCODE_THOUSANDSSEPARATOR = 178; +const Scancode SCANCODE_DECIMALSEPARATOR = 179; +const Scancode SCANCODE_CURRENCYUNIT = 180; +const Scancode SCANCODE_CURRENCYSUBUNIT = 181; +const Scancode SCANCODE_KP_LEFTPAREN = 182; +const Scancode SCANCODE_KP_RIGHTPAREN = 183; +const Scancode SCANCODE_KP_LEFTBRACE = 184; +const Scancode SCANCODE_KP_RIGHTBRACE = 185; +const Scancode SCANCODE_KP_TAB = 186; +const Scancode SCANCODE_KP_BACKSPACE = 187; +const Scancode SCANCODE_KP_A = 188; +const Scancode SCANCODE_KP_B = 189; +const Scancode SCANCODE_KP_C = 190; +const Scancode SCANCODE_KP_D = 191; +const Scancode SCANCODE_KP_E = 192; +const Scancode SCANCODE_KP_F = 193; +const Scancode SCANCODE_KP_XOR = 194; +const Scancode SCANCODE_KP_POWER = 195; +const Scancode SCANCODE_KP_PERCENT = 196; +const Scancode SCANCODE_KP_LESS = 197; +const Scancode SCANCODE_KP_GREATER = 198; +const Scancode SCANCODE_KP_AMPERSAND = 199; +const Scancode SCANCODE_KP_DBLAMPERSAND = 200; +const Scancode SCANCODE_KP_VERTICALBAR = 201; +const Scancode SCANCODE_KP_DBLVERTICALBAR = 202; +const Scancode SCANCODE_KP_COLON = 203; +const Scancode SCANCODE_KP_HASH = 204; +const Scancode SCANCODE_KP_SPACE = 205; +const Scancode SCANCODE_KP_AT = 206; +const Scancode SCANCODE_KP_EXCLAM = 207; +const Scancode SCANCODE_KP_MEMSTORE = 208; +const Scancode SCANCODE_KP_MEMRECALL = 209; +const Scancode SCANCODE_KP_MEMCLEAR = 210; +const Scancode SCANCODE_KP_MEMADD = 211; +const Scancode SCANCODE_KP_MEMSUBTRACT = 212; +const Scancode SCANCODE_KP_MEMMULTIPLY = 213; +const Scancode SCANCODE_KP_MEMDIVIDE = 214; +const Scancode SCANCODE_KP_PLUSMINUS = 215; +const Scancode SCANCODE_KP_CLEAR = 216; +const Scancode SCANCODE_KP_CLEARENTRY = 217; +const Scancode SCANCODE_KP_BINARY = 218; +const Scancode SCANCODE_KP_OCTAL = 219; +const Scancode SCANCODE_KP_DECIMAL = 220; +const Scancode SCANCODE_KP_HEXADECIMAL = 221; +const Scancode SCANCODE_LCTRL = 224; +const Scancode SCANCODE_LSHIFT = 225; +const Scancode SCANCODE_LALT = 226; +const Scancode SCANCODE_LGUI = 227; +const Scancode SCANCODE_RCTRL = 228; +const Scancode SCANCODE_RSHIFT = 229; +const Scancode SCANCODE_RALT = 230; +const Scancode SCANCODE_RGUI = 231; +const Scancode SCANCODE_MODE = 257; +const Scancode SCANCODE_SLEEP = 258; +const Scancode SCANCODE_WAKE = 259; +const Scancode SCANCODE_CHANNEL_INCREMENT = 260; +const Scancode SCANCODE_CHANNEL_DECREMENT = 261; +const Scancode SCANCODE_MEDIA_PLAY = 262; +const Scancode SCANCODE_MEDIA_PAUSE = 263; +const Scancode SCANCODE_MEDIA_RECORD = 264; +const Scancode SCANCODE_MEDIA_FAST_FORWARD = 265; +const Scancode SCANCODE_MEDIA_REWIND = 266; +const Scancode SCANCODE_MEDIA_NEXT_TRACK = 267; +const Scancode SCANCODE_MEDIA_PREVIOUS_TRACK = 268; +const Scancode SCANCODE_MEDIA_STOP = 269; +const Scancode SCANCODE_MEDIA_EJECT = 270; +const Scancode SCANCODE_MEDIA_PLAY_PAUSE = 271; +const Scancode SCANCODE_MEDIA_SELECT = 272; +const Scancode SCANCODE_AC_NEW = 273; +const Scancode SCANCODE_AC_OPEN = 274; +const Scancode SCANCODE_AC_CLOSE = 275; +const Scancode SCANCODE_AC_EXIT = 276; +const Scancode SCANCODE_AC_SAVE = 277; +const Scancode SCANCODE_AC_PRINT = 278; +const Scancode SCANCODE_AC_PROPERTIES = 279; +const Scancode SCANCODE_AC_SEARCH = 280; +const Scancode SCANCODE_AC_HOME = 281; +const Scancode SCANCODE_AC_BACK = 282; +const Scancode SCANCODE_AC_FORWARD = 283; +const Scancode SCANCODE_AC_STOP = 284; +const Scancode SCANCODE_AC_REFRESH = 285; +const Scancode SCANCODE_AC_BOOKMARKS = 286; +const Scancode SCANCODE_SOFTLEFT = 287; +const Scancode SCANCODE_SOFTRIGHT = 288; +const Scancode SCANCODE_CALL = 289; +const Scancode SCANCODE_ENDCALL = 290; +const Scancode SCANCODE_RESERVED = 400; +const Scancode SCANCODE_COUNT = 512; diff --git a/sdl3.c3l/sdl3_sensor.c3i b/sdl3.c3l/sdl3_sensor.c3i new file mode 100644 index 0000000..e7a42d8 --- /dev/null +++ b/sdl3.c3l/sdl3_sensor.c3i @@ -0,0 +1,32 @@ +module sdl3::sdl; + +typedef Sensor = void; +typedef SensorID = uint; + +const float STANDARD_GRAVITY = 9.80665; + +typedef SensorType = CInt; + +const SensorType SENSOR_INVALID = -1; +const SensorType SENSOR_UNKNOWN = 0; +const SensorType SENSOR_ACCEL = 1; +const SensorType SENSOR_GYRO = 2; +const SensorType SENSOR_ACCEL_L = 3; +const SensorType SENSOR_GYRO_L = 4; +const SensorType SENSOR_ACCEL_R = 5; +const SensorType SENSOR_GYRO_R = 6; + +extern fn SensorID* get_sensors(int *count) @extern("SDL_GetSensors"); +extern fn ZString get_sensor_name_for_id(SensorID instance_id) @extern("SDL_GetSensorNameForID"); +extern fn SensorType get_sensor_type_for_id(SensorID instance_id) @extern("SDL_GetSensorTypeForID"); +extern fn int get_sensor_non_portable_type_for_id(SensorID instance_id) @extern("SDL_GetSensorNonPortableTypeForID"); +extern fn Sensor* open_sensor(SensorID instance_id) @extern("SDL_OpenSensor"); +extern fn Sensor* get_sensor_from_id(SensorID instance_id) @extern("SDL_GetSensorFromID"); +extern fn PropertiesID get_sensor_properties(Sensor* sensor) @extern("SDL_GetSensorProperties"); +extern fn ZString get_sensor_name(Sensor* sensor) @extern("SDL_GetSensorName"); +extern fn SensorType get_sensor_type(Sensor* sensor) @extern("SDL_GetSensorType"); +extern fn int get_sensor_non_portable_type(Sensor* sensor) @extern("SDL_GetSensorNonPortableType"); +extern fn SensorID get_sensor_id(Sensor* sensor) @extern("SDL_GetSensorID"); +extern fn bool get_sensor_data(Sensor* sensor, float *data, int num_values) @extern("SDL_GetSensorData"); +extern fn void close_sensor(Sensor* sensor) @extern("SDL_CloseSensor"); +extern fn void update_sensors() @extern("SDL_UpdateSensors"); diff --git a/sdl3.c3l/sdl3_stdinc.c3i b/sdl3.c3l/sdl3_stdinc.c3i new file mode 100644 index 0000000..726d435 --- /dev/null +++ b/sdl3.c3l/sdl3_stdinc.c3i @@ -0,0 +1,288 @@ +module sdl3::sdl; + +// #include + +//#define SDL_FOURCC(A, B, C, D) \ +// ((SDL_static_cast(uint, SDL_static_cast(Uint8, (A))) << 0) | \ +// (SDL_static_cast(uint, SDL_static_cast(Uint8, (B))) << 8) | \ +// (SDL_static_cast(uint, SDL_static_cast(Uint8, (C))) << 16) | \ +// (SDL_static_cast(uint, SDL_static_cast(Uint8, (D))) << 24)) + + +const float FLT_EPSILON = 1.1920928955078125e-07; + + +//#define SDL_INIT_INTERFACE(iface) \ +// do { \ +// SDL_zerop(iface); \ +// (iface)->version = sizeof(*(iface)); \ +// } while (0) + +alias FunctionPointer = fn void(); + +extern fn void* malloc(isz size) @extern("SDL_malloc"); +extern fn void* calloc(isz nmemb, isz size) @extern("SDL_calloc"); +extern fn void* realloc(void* mem, isz size) @extern("SDL_realloc"); +extern fn void free(void* mem) @extern("SDL_free"); + +alias Malloc_func = fn void*(isz size); +alias Calloc_func = fn void*(isz nmemb, isz size); +alias Realloc_func = fn void*(void* mem, isz size); +alias Free_func = fn void(void* mem); + +extern fn void get_original_memory_functions(Malloc_func* malloc_func, Calloc_func* calloc_func, Realloc_func* realloc_func, Free_func* free_func) @extern("SDL_GetOriginalMemoryFunctions"); +extern fn void get_memory_functions(Malloc_func* malloc_func, Calloc_func* calloc_func, Realloc_func* realloc_func, Free_func* free_func) @extern("SDL_GetMemoryFunctions"); +extern fn bool set_memory_functions(Malloc_func malloc_func, Calloc_func calloc_func, Realloc_func realloc_func, Free_func free_func) @extern("SDL_SetMemoryFunctions"); + +extern fn void* aligned_alloc(isz alignment, isz size) @extern("SDL_aligned_alloc"); +extern fn void aligned_free(void* mem) @extern("SDL_aligned_free"); +extern fn int get_num_allocations() @extern("SDL_GetNumAllocations"); + +typedef Environment = void; + +extern fn Environment* get_environment() @extern("SDL_GetEnvironment"); +extern fn Environment* create_environment(bool populated) @extern("SDL_CreateEnvironment"); +extern fn ZString get_environment_variable(Environment* env, ZString name) @extern("SDL_GetEnvironmentVariable"); +extern fn ZString* get_environment_variables(Environment* env) @extern("SDL_GetEnvironmentVariables"); +extern fn bool set_environment_variable(Environment* env, ZString name, ZString value, bool overwrite) @extern("SDL_SetEnvironmentVariable"); +extern fn bool unset_environment_variable(Environment* env, ZString name) @extern("SDL_UnsetEnvironmentVariable"); +extern fn void destroy_environment(Environment* env) @extern("SDL_DestroyEnvironment"); +extern fn ZString getenv(ZString name) @extern("SDL_getenv"); +extern fn ZString getenv_unsafe(ZString name) @extern("SDL_getenv_unsafe"); +extern fn int setenv_unsafe(ZString name, ZString value, int overwrite) @extern("SDL_setenv_unsafe"); +extern fn int unsetenv_unsafe(ZString name) @extern("SDL_unsetenv_unsafe"); + +alias CompareCallback = fn int(void* a, void* b); + +extern fn void qsort(void* base, isz nmemb, isz size, CompareCallback compare) @extern("SDL_qsort"); +extern fn void* bsearch(void* key, void* base, isz nmemb, isz size, CompareCallback compare) @extern("SDL_bsearch"); + +alias CompareCallback_r = fn int(void* userdata, void* a, void* b); + +extern fn void qsort_r(void* base, isz nmemb, isz size, CompareCallback_r compare, void* userdata) @extern("SDL_qsort_r"); +extern fn void* bsearch_r(void* key, void* base, isz nmemb, isz size, CompareCallback_r compare, void* userdata) @extern("SDL_bsearch_r"); +extern fn int abs(int x) @extern("SDL_abs"); + +macro min(x, y) => x < y ? x : y; +macro max(x, y) => x > y ? x : y; +macro clamp(x, a, b) => x < a ? a : (x > b ? b : x); + +extern fn int isalpha(int x) @extern("SDL_isalpha"); +extern fn int isalnum(int x) @extern("SDL_isalnum"); +extern fn int isblank(int x) @extern("SDL_isblank"); +extern fn int iscntrl(int x) @extern("SDL_iscntrl"); +extern fn int isdigit(int x) @extern("SDL_isdigit"); +extern fn int isxdigit(int x) @extern("SDL_isxdigit"); +extern fn int ispunct(int x) @extern("SDL_ispunct"); +extern fn int isspace(int x) @extern("SDL_isspace"); +extern fn int isupper(int x) @extern("SDL_isupper"); +extern fn int islower(int x) @extern("SDL_islower"); +extern fn int isprint(int x) @extern("SDL_isprint"); +extern fn int isgraph(int x) @extern("SDL_isgraph"); +extern fn int toupper(int x) @extern("SDL_toupper"); +extern fn int tolower(int x) @extern("SDL_tolower"); +extern fn ushort crc16(ushort crc, void* data, isz len) @extern("SDL_crc16"); +extern fn uint crc32(uint crc, void* data, isz len) @extern("SDL_crc32"); +extern fn uint murmur3_32(void* data, isz len, uint seed) @extern("SDL_murmur3_32"); +extern fn void* memcpy(void* dst, void* src, isz len) @extern("SDL_memcpy"); + +macro copyp(dst, src) => memcpy(dst, src, sizeof(*(src))); + +extern fn void* memmove(void* dst,void* src, isz len) @extern("SDL_memmove"); +extern fn void* memset(void* dst, int c, isz len) @extern("SDL_memset"); +extern fn void* memset4(void* dst, uint val, isz dwords) @extern("SDL_memset4"); +extern fn int memcmp(void* s1, void* s2, isz len) @extern("SDL_memcmp"); +extern fn isz wcslen(WString wstr) @extern("SDL_wcslen"); +extern fn isz wcsnlen(WString wstr, isz maxlen) @extern("SDL_wcsnlen"); +extern fn isz wcslcpy(WString dst, WString src, isz maxlen) @extern("SDL_wcslcpy"); +extern fn isz wcslcat(WString dst, WString src, isz maxlen) @extern("SDL_wcslcat"); +extern fn WString wcsdup(WString wstr) @extern("SDL_wcsdup"); +extern fn WString wcsstr(WString haystack, WString needle) @extern("SDL_wcsstr"); +extern fn WString wcsnstr(WString haystack, WString needle, isz maxlen) @extern("SDL_wcsnstr"); +extern fn int wcscmp(WString str1, WString str2) @extern("SDL_wcscmp"); +extern fn int wcsncmp(WString str1, WString str2, isz maxlen) @extern("SDL_wcsncmp"); +extern fn int wcscasecmp(WString str1, WString str2) @extern("SDL_wcscasecmp"); +extern fn int wcsncasecmp(WString str1, WString str2, isz maxlen) @extern("SDL_wcsncasecmp"); +extern fn long wcstol(WString str, WString *endp, int base) @extern("SDL_wcstol"); +extern fn isz strlen(ZString str) @extern("SDL_strlen"); +extern fn isz strnlen(ZString str, isz maxlen) @extern("SDL_strnlen"); +extern fn isz strlcpy(ZString dst, ZString src, isz maxlen) @extern("SDL_strlcpy"); +extern fn isz utf8strlcpy(ZString dst, ZString src, isz dst_bytes) @extern("SDL_utf8strlcpy"); +extern fn isz strlcat(ZString dst, ZString src, isz maxlen) @extern("SDL_strlcat"); +extern fn ZString strdup(ZString str) @extern("SDL_strdup"); +extern fn ZString strndup(ZString str, isz maxlen) @extern("SDL_strndup"); +extern fn ZString strrev(ZString str) @extern("SDL_strrev"); +extern fn ZString strupr(ZString str) @extern("SDL_strupr"); +extern fn ZString strlwr(ZString str) @extern("SDL_strlwr"); +extern fn ZString strchr(ZString str, int c) @extern("SDL_strchr"); +extern fn ZString strrchr(ZString str, int c) @extern("SDL_strrchr"); +extern fn ZString strstr(ZString haystack, ZString needle) @extern("SDL_strstr"); +extern fn ZString strnstr(ZString haystack, ZString needle, isz maxlen) @extern("SDL_strnstr"); +extern fn ZString strcasestr(ZString haystack, ZString needle) @extern("SDL_strcasestr"); +extern fn ZString strtok_r(ZString str, ZString delim, ZString* saveptr) @extern("SDL_strtok_r"); +extern fn isz utf8strlen(ZString str) @extern("SDL_utf8strlen"); +extern fn isz utf8strnlen(ZString str, isz bytes) @extern("SDL_utf8strnlen"); +extern fn ZString itoa(int value, ZString str, int radix) @extern("SDL_itoa"); +extern fn ZString uitoa(uint value, ZString str, int radix) @extern("SDL_uitoa"); +extern fn ZString ltoa(long value, ZString str, int radix) @extern("SDL_ltoa"); +extern fn ZString ultoa(ulong value, ZString str, int radix) @extern("SDL_ultoa"); +extern fn int atoi(ZString str) @extern("SDL_atoi"); +extern fn double atof(ZString str) @extern("SDL_atof"); +extern fn long strtol(ZString str, ZString* endp, int base) @extern("SDL_strtol"); +extern fn ulong strtoul(ZString str, ZString* endp, int base) @extern("SDL_strtoul"); +extern fn double strtod(ZString str, ZString* endp) @extern("SDL_strtod"); +extern fn int strcmp(ZString str1, ZString str2) @extern("SDL_strcmp"); +extern fn int strncmp(ZString str1, ZString str2, isz maxlen) @extern("SDL_strncmp"); +extern fn int strcasecmp(ZString str1, ZString str2) @extern("SDL_strcasecmp"); +extern fn int strncasecmp(ZString str1, ZString str2, isz maxlen) @extern("SDL_strncasecmp"); +extern fn ZString strpbrk(ZString str, ZString breakset) @extern("SDL_strpbrk"); + +const ushort INVALID_UNICODE_CODEPOINT = 0xFFFD; + +extern fn uint step_utf8(ZString *pstr, isz *pslen) @extern("SDL_StepUTF8"); +extern fn uint step_back_utf8(ZString start, ZString *pstr) @extern("SDL_StepBackUTF8"); +extern fn ZString ucs4_to_utf8(uint codepoint, ZString dst) @extern("SDL_UCS4ToUTF8"); +extern fn int sscanf(ZString text, ZString fmt, ...) @extern("SDL_sscanf"); +// extern fn int SDLCALL SDL_vsscanf(ZString text, ZString fmt, va_list ap) SDL_SCANF_VARARG_FUNCV(2); +extern fn int snprintf(ZString text, isz maxlen, ZString fmt, ...) @extern("SDL_snprintf"); +extern fn int swprintf(WString text, isz maxlen, WString fmt, ...) @extern("SDL_swprintf"); +// extern fn int vsnprintf(ZString text, isz maxlen, ZString fmt, va_list ap) SDL_PRINTF_VARARG_FUNCV(3) @extern("SDL_vsnprintf"); +// extern fn int vswprintf(WString text, isz maxlen, WString fmt, va_list ap) SDL_WPRINTF_VARARG_FUNCV(3) @extern("SDL_vswprintf"); +extern fn int asprintf(ZString* strp, ZString fmt, ...) @extern("SDL_asprintf"); +// extern fn int vasprintf(ZString* strp, ZString fmt, va_list ap) SDL_PRINTF_VARARG_FUNCV(2) @extern("SDL_vasprintf"); +extern fn void srand(ulong seed) @extern("SDL_srand"); +extern fn int rand(int n) @extern("SDL_rand"); +extern fn float randf() @extern("SDL_randf"); +extern fn uint rand_bits() @extern("SDL_rand_bits"); +extern fn int rand_r(ulong *state, int n) @extern("SDL_rand_r"); +extern fn float randf_r(ulong *state) @extern("SDL_randf_r"); +extern fn uint rand_bits_r(ulong *state) @extern("SDL_rand_bits_r"); + +const double PI_D = 3.141592653589793238462643383279502884; +const float PI_F = 3.141592653589793238462643383279502884; + +extern fn double acos(double x) @extern("SDL_acos"); +extern fn float acosf(float x) @extern("SDL_acosf"); +extern fn double asin(double x) @extern("SDL_asin"); +extern fn float asinf(float x) @extern("SDL_asinf"); +extern fn double atan(double x) @extern("SDL_atan"); +extern fn float atanf(float x) @extern("SDL_atanf"); +extern fn double atan2(double y, double x) @extern("SDL_atan2"); +extern fn float atan2f(float y, float x) @extern("SDL_atan2f"); +extern fn double ceil(double x) @extern("SDL_ceil"); +extern fn float ceilf(float x) @extern("SDL_ceilf"); +extern fn double copysign(double x, double y) @extern("SDL_copysign"); +extern fn float copysignf(float x, float y) @extern("SDL_copysignf"); +extern fn double cos(double x) @extern("SDL_cos"); +extern fn float cosf(float x) @extern("SDL_cosf"); +extern fn double exp(double x) @extern("SDL_exp"); +extern fn float expf(float x) @extern("SDL_expf"); +extern fn double fabs(double x) @extern("SDL_fabs"); +extern fn float fabsf(float x) @extern("SDL_fabsf"); +extern fn double floor(double x) @extern("SDL_floor"); +extern fn float floorf(float x) @extern("SDL_floorf"); +extern fn double trunc(double x) @extern("SDL_trunc"); +extern fn float truncf(float x) @extern("SDL_truncf"); +extern fn double fmod(double x, double y) @extern("SDL_fmod"); +extern fn float fmodf(float x, float y) @extern("SDL_fmodf"); +extern fn int isinf(double x) @extern("SDL_isinf"); +extern fn int isinff(float x) @extern("SDL_isinff"); +extern fn int isnan(double x) @extern("SDL_isnan"); +extern fn int isnanf(float x) @extern("SDL_isnanf"); +extern fn double log(double x) @extern("SDL_log"); +extern fn float logf(float x) @extern("SDL_logf"); +extern fn double log10(double x) @extern("SDL_log10"); +extern fn float log10f(float x) @extern("SDL_log10f"); +extern fn double modf(double x, double *y) @extern("SDL_modf"); +extern fn float modff(float x, float *y) @extern("SDL_modff"); +extern fn double pow(double x, double y) @extern("SDL_pow"); +extern fn float powf(float x, float y) @extern("SDL_powf"); +extern fn double round(double x) @extern("SDL_round"); +extern fn float roundf(float x) @extern("SDL_roundf"); +extern fn long lround(double x) @extern("SDL_lround"); +extern fn long lroundf(float x) @extern("SDL_lroundf"); +extern fn double scalbn(double x, int n) @extern("SDL_scalbn"); +extern fn float scalbnf(float x, int n) @extern("SDL_scalbnf"); +extern fn double sin(double x) @extern("SDL_sin"); +extern fn float sinf(float x) @extern("SDL_sinf"); +extern fn double sqrt(double x) @extern("SDL_sqrt"); +extern fn float sqrtf(float x) @extern("SDL_sqrtf"); +extern fn double tan(double x) @extern("SDL_tan"); +extern fn float tanf(float x) @extern("SDL_tanf"); + +typedef Iconv = void*; + +extern fn Iconv iconv_open(ZString tocode, ZString fromcode) @extern("SDL_iconv_open"); +extern fn int iconv_close(Iconv cd) @extern("SDL_iconv_close"); +extern fn isz iconv(Iconv cd, ZString *inbuf, isz *inbytesleft, ZString* outbuf, isz *outbytesleft) @extern("SDL_iconv"); + +const isz ICONV_ERROR = (isz)-1; +const isz ICONV_E2BIG = (isz)-2; +const isz ICONV_EILSEQ = (isz)-3; +const isz ICONV_EINVAL = (isz)-4; + +extern fn ZString iconv_string(ZString tocode, ZString fromcode, ZString inbuf, isz inbytesleft) @extern("SDL_iconv_string"); + +macro iconv_utf8_locale(s) => iconv_string("", "UTF-8", s, strlen(s)+1); +macro iconv_utf8_ucs2(s) => (ushort *)iconv_string("UCS-2", "UTF-8", s, strlen(s)+1); +macro iconv_utf8_ucs4(s) => (uint *)iconv_string("UCS-4", "UTF-8", s, strlen(s)+1); +macro iconv_wchar_utf8(s) => iconv_string("UTF-8", "WCHAR_T", (ZString)s, (wcslen(s)+1)*sizeof(short)); + +// TODO: remove these from the pool +// #define SDL_malloc malloc +// #define SDL_calloc calloc +// #define SDL_realloc realloc +// #define SDL_free free +// #ifndef SDL_memcpy +// #define SDL_memcpy memcpy +// #endif +// #ifndef SDL_memmove +// #define SDL_memmove memmove +// #endif +// #ifndef SDL_memset +// #define SDL_memset memset +// #endif +// #define SDL_memcmp memcmp +// #define SDL_strlcpy strlcpy +// #define SDL_strlcat strlcat +// #define SDL_strlen strlen +// #define SDL_wcslen wcslen +// #define SDL_wcslcpy wcslcpy +// #define SDL_wcslcat wcslcat +// #define SDL_strdup strdup +// #define SDL_wcsdup wcsdup +// #define SDL_strchr strchr +// #define SDL_strrchr strrchr +// #define SDL_strstr strstr +// #define SDL_wcsstr wcsstr +// #define SDL_strtok_r strtok_r +// #define SDL_strcmp strcmp +// #define SDL_wcscmp wcscmp +// #define SDL_strncmp strncmp +// #define SDL_wcsncmp wcsncmp +// #define SDL_strcasecmp strcasecmp +// #define SDL_strncasecmp strncasecmp +// #define SDL_strpbrk strpbrk +// #define SDL_sscanf sscanf +// #define SDL_vsscanf vsscanf +// #define SDL_snprintf snprintf +// #define SDL_vsnprintf vsnprintf +// #endif + +macro bool size_mul_check_overflow(isz a, isz b, isz *ret) +{ + if (a != 0 && b > isz.max / a) { + return false; + } + *ret = a * b; + return true; +} + +macro bool size_add_check_overflow(isz a, isz b, isz *ret) +{ + if (b > isz.max - a) { + return false; + } + *ret = a + b; + return true; +} diff --git a/sdl3.c3l/sdl3_surface.c3i b/sdl3.c3l/sdl3_surface.c3i new file mode 100644 index 0000000..c8ba92b --- /dev/null +++ b/sdl3.c3l/sdl3_surface.c3i @@ -0,0 +1,88 @@ +module sdl3::sdl; + +typedef SurfaceFlags = uint; + +const SurfaceFlags SURFACE_PREALLOCATED = 0x00000001; +const SurfaceFlags SURFACE_LOCK_NEEDED = 0x00000002; +const SurfaceFlags SURFACE_LOCKED = 0x00000004; +const SurfaceFlags SURFACE_SIMD_ALIGNED = 0x00000008; + +typedef ScaleMode = CInt; + +const ScaleMode SCALEMODE_INVALID = -1; +const ScaleMode SCALEMODE_NEAREST = 0; +const ScaleMode SCALEMODE_LINEAR = 0; + +enum FlipMode : inline CInt { + FLIP_NONE, + FLIP_HORIZONTAL, + FLIP_VERTICAL +} + +typedef Surface = void; + +extern fn Surface* create_surface(int width, int height, PixelFormat format) @extern("SDL_CreateSurface"); +extern fn Surface* create_surface_from(int width, int height, PixelFormat format, void *pixels, int pitch) @extern("SDL_CreateSurfaceFrom"); +extern fn void destroy_surface(Surface* surface) @extern("SDL_DestroySurface"); +extern fn PropertiesID get_surface_properties(Surface* surface) @extern("SDL_GetSurfaceProperties"); + +const ZString PROP_SURFACE_SDR_WHITE_POINT_FLOAT = "SDL.surface.SDR_white_point"; +const ZString PROP_SURFACE_HDR_HEADROOM_FLOAT = "SDL.surface.HDR_headroom"; +const ZString PROP_SURFACE_TONEMAP_OPERATOR_STRING = "SDL.surface.tonemap"; +const ZString PROP_SURFACE_HOTSPOT_X_NUMBER = "SDL.surface.hotspot.x"; +const ZString PROP_SURFACE_HOTSPOT_Y_NUMBER = "SDL.surface.hotspot.y"; + +extern fn bool set_surface_colorspace(Surface* surface, Colorspace colorspace) @extern("SDL_SetSurfaceColorspace"); +extern fn Colorspace get_surface_colorspace(Surface* surface) @extern("SDL_GetSurfaceColorspace"); +extern fn Palette* create_surface_palette(Surface* surface) @extern("SDL_CreateSurfacePalette"); +extern fn bool set_surface_palette(Surface* surface, Palette* palette) @extern("SDL_SetSurfacePalette"); +extern fn Palette* get_surface_palette(Surface* surface) @extern("SDL_GetSurfacePalette"); +extern fn bool add_surface_alternate_image(Surface* surface, Surface* image) @extern("SDL_AddSurfaceAlternateImage"); +extern fn bool surface_has_alternate_images(Surface* surface) @extern("SDL_SurfaceHasAlternateImages"); +extern fn Surface* * get_surface_images(Surface* surface, int *count) @extern("SDL_GetSurfaceImages"); +extern fn void remove_surface_alternate_images(Surface* surface) @extern("SDL_RemoveSurfaceAlternateImages"); +extern fn bool lock_surface(Surface* surface) @extern("SDL_LockSurface"); +extern fn void unlock_surface(Surface* surface) @extern("SDL_UnlockSurface"); +extern fn Surface* load_bmp_io(IOStream *src, bool closeio) @extern("SDL_LoadBMP_IO"); +extern fn Surface* load_bmp(ZString file) @extern("SDL_LoadBMP"); +extern fn bool save_bmp_io(Surface* surface, IOStream *dst, bool closeio) @extern("SDL_SaveBMP_IO"); +extern fn bool save_bmp(Surface* surface, ZString file) @extern("SDL_SaveBMP"); +extern fn bool set_surface_rle(Surface* surface, bool enabled) @extern("SDL_SetSurfaceRLE"); +extern fn bool surface_has_rle(Surface* surface) @extern("SDL_SurfaceHasRLE"); +extern fn bool set_surface_color_key(Surface* surface, bool enabled, uint key) @extern("SDL_SetSurfaceColorKey"); +extern fn bool surface_has_color_key(Surface* surface) @extern("SDL_SurfaceHasColorKey"); +extern fn bool get_surface_color_key(Surface* surface, uint *key) @extern("SDL_GetSurfaceColorKey"); +extern fn bool set_surface_color_mod(Surface* surface, char r, char g, char b) @extern("SDL_SetSurfaceColorMod"); +extern fn bool get_surface_color_mod(Surface* surface, char *r, char *g, char *b) @extern("SDL_GetSurfaceColorMod"); +extern fn bool set_surface_alpha_mod(Surface* surface, char alpha) @extern("SDL_SetSurfaceAlphaMod"); +extern fn bool get_surface_alpha_mod(Surface* surface, char *alpha) @extern("SDL_GetSurfaceAlphaMod"); +extern fn bool set_surface_blend_mode(Surface* surface, BlendMode blendMode) @extern("SDL_SetSurfaceBlendMode"); +extern fn bool get_surface_blend_mode(Surface* surface, BlendMode *blendMode) @extern("SDL_GetSurfaceBlendMode"); +extern fn bool set_surface_clip_rect(Surface* surface, Rect* rect) @extern("SDL_SetSurfaceClipRect"); +extern fn bool get_surface_clip_rect(Surface* surface, Rect* rect) @extern("SDL_GetSurfaceClipRect"); +extern fn bool flip_surface(Surface* surface, FlipMode flip) @extern("SDL_FlipSurface"); +extern fn Surface* duplicate_surface(Surface* surface) @extern("SDL_DuplicateSurface"); +extern fn Surface* scale_surface(Surface* surface, int width, int height, ScaleMode scaleMode) @extern("SDL_ScaleSurface"); +extern fn Surface* convert_surface(Surface* surface, PixelFormat format) @extern("SDL_ConvertSurface"); +extern fn Surface* convert_surface_and_colorspace(Surface* surface, PixelFormat format, Palette* palette, Colorspace colorspace, PropertiesID props) @extern("SDL_ConvertSurfaceAndColorspace"); +extern fn bool convert_pixels(int width, int height, PixelFormat src_format, void* src, int src_pitch, PixelFormat dst_format, void *dst, int dst_pitch) @extern("SDL_ConvertPixels"); +extern fn bool convert_pixels_and_colorspace(int width, int height, PixelFormat src_format, Colorspace src_colorspace, PropertiesID src_properties, void* src, int src_pitch, PixelFormat dst_format, Colorspace dst_colorspace, PropertiesID dst_properties, void *dst, int dst_pitch) @extern("SDL_ConvertPixelsAndColorspace"); +extern fn bool premultiply_alpha(int width, int height, PixelFormat src_format, void* src, int src_pitch, PixelFormat dst_format, void *dst, int dst_pitch, bool linear) @extern("SDL_PremultiplyAlpha"); +extern fn bool premultiply_surface_alpha(Surface* surface, bool linear) @extern("SDL_PremultiplySurfaceAlpha"); +extern fn bool clear_surface(Surface* surface, float r, float g, float b, float a) @extern("SDL_ClearSurface"); +extern fn bool fill_surface_rect(Surface* dst, Rect* rect, uint color) @extern("SDL_FillSurfaceRect"); +extern fn bool fill_surface_rects(Surface* dst, Rect* rects, int count, uint color) @extern("SDL_FillSurfaceRects"); +extern fn bool blit_surface(Surface* src, Rect* srcrect, Surface* dst, Rect* dstrect) @extern("SDL_BlitSurface"); +extern fn bool blit_surface_unchecked(Surface* src, Rect* srcrect, Surface* dst, Rect* dstrect) @extern("SDL_BlitSurfaceUnchecked"); +extern fn bool blit_surface_scaled(Surface* src, Rect* srcrect, Surface* dst, Rect* dstrect, ScaleMode scaleMode) @extern("SDL_BlitSurfaceScaled"); +extern fn bool blit_surface_unchecked_scaled(Surface* src, Rect* srcrect, Surface* dst, Rect* dstrect, ScaleMode scaleMode) @extern("SDL_BlitSurfaceUncheckedScaled"); +extern fn bool stretch_surface(Surface* src, Rect* srcrect, Surface* dst, Rect* dstrect, ScaleMode scaleMode) @extern("SDL_StretchSurface"); +extern fn bool blit_surface_tiled(Surface* src, Rect* srcrect, Surface* dst, Rect* dstrect) @extern("SDL_BlitSurfaceTiled"); +extern fn bool blit_surface_tiled_with_scale(Surface* src, Rect* srcrect, float scale, ScaleMode scaleMode, Surface* dst, Rect* dstrect) @extern("SDL_BlitSurfaceTiledWithScale"); +extern fn bool blit_surface9_grid(Surface* src, Rect* srcrect, int left_width, int right_width, int top_height, int bottom_height, float scale, ScaleMode scaleMode, Surface* dst, Rect* dstrect) @extern("SDL_BlitSurface9Grid"); +extern fn uint map_surface_rgb(Surface* surface, char r, char g, char b) @extern("SDL_MapSurfaceRGB"); +extern fn uint map_surface_rgba(Surface* surface, char r, char g, char b, char a) @extern("SDL_MapSurfaceRGBA"); +extern fn bool read_surface_pixel(Surface* surface, int x, int y, char *r, char *g, char *b, char *a) @extern("SDL_ReadSurfacePixel"); +extern fn bool read_surface_pixel_float(Surface* surface, int x, int y, float *r, float *g, float *b, float *a) @extern("SDL_ReadSurfacePixelFloat"); +extern fn bool write_surface_pixel(Surface* surface, int x, int y, char r, char g, char b, char a) @extern("SDL_WriteSurfacePixel"); +extern fn bool write_surface_pixel_float(Surface* surface, int x, int y, float r, float g, float b, float a) @extern("SDL_WriteSurfacePixelFloat"); diff --git a/sdl3.c3l/sdl3_touch.c3i b/sdl3.c3l/sdl3_touch.c3i new file mode 100644 index 0000000..fae7837 --- /dev/null +++ b/sdl3.c3l/sdl3_touch.c3i @@ -0,0 +1,26 @@ +module sdl3::sdl; + +typedef TouchID = ulong; +typedef FingerID = ulong; + +typedef TouchDeviceType = CInt; + +const TouchDeviceType TOUCH_DEVICE_INVALID = -1; +const TouchDeviceType TOUCH_DEVICE_DIRECT = 0; +const TouchDeviceType TOUCH_DEVICE_INDIRECT_ABSOLUTE = 1; +const TouchDeviceType TOUCH_DEVICE_INDIRECT_RELATIVE = 2; + +struct Finger { + FingerID id; + float x; + float y; + float pressure; +} + +const MouseID TOUCH_MOUSEID = ((MouseID)-1); +const TouchID MOUSE_TOUCHID = ((TouchID)-1); + +extern fn TouchID* get_touch_devices(int *count) @extern("SDL_GetTouchDevices"); +extern fn ZString get_touch_device_name(TouchID touchID) @extern("SDL_GetTouchDeviceName"); +extern fn TouchDeviceType get_touch_device_type(TouchID touchID) @extern("SDL_GetTouchDeviceType"); +extern fn Finger** get_touch_fingers(TouchID touchID, int *count) @extern("SDL_GetTouchFingers"); diff --git a/sdl3.c3l/sdl3_video.c3i b/sdl3.c3l/sdl3_video.c3i new file mode 100644 index 0000000..6f09ce6 --- /dev/null +++ b/sdl3.c3l/sdl3_video.c3i @@ -0,0 +1,357 @@ +module sdl3::sdl; + +typedef DisplayID = uint; +typedef WindowID = uint; + + +const ZString PROP_GLOBAL_VIDEO_WAYLAND_WL_DISPLAY_POINTER = "SDL.video.wayland.wl_display"; + +enum SystemTheme : inline CInt { + SYSTEM_THEME_UNKNOWN, + SYSTEM_THEME_LIGHT, + SYSTEM_THEME_DARK +} + +typedef DisplayModeData = void; + +struct DisplayMode { + DisplayID displayID; + PixelFormat format; + int w; + int h; + float pixel_density; + float refresh_rate; + int refresh_rate_numerator; + int refresh_rate_denominator; + DisplayModeData *internal; +} + +enum DisplayOrientation : inline CInt { + ORIENTATION_UNKNOWN, + ORIENTATION_LANDSCAPE, + ORIENTATION_LANDSCAPE_FLIPPED, + ORIENTATION_PORTRAIT, + ORIENTATION_PORTRAIT_FLIPPED +} + +typedef Window = void; +typedef WindowFlags = ulong; + +const WindowFlags WINDOW_FULLSCREEN = 0x0000000000000001; +const WindowFlags WINDOW_OPENGL = 0x0000000000000002; +const WindowFlags WINDOW_OCCLUDED = 0x0000000000000004; +const WindowFlags WINDOW_HIDDEN = 0x0000000000000008; +const WindowFlags WINDOW_BORDERLESS = 0x0000000000000010; +const WindowFlags WINDOW_RESIZABLE = 0x0000000000000020; +const WindowFlags WINDOW_MINIMIZED = 0x0000000000000040; +const WindowFlags WINDOW_MAXIMIZED = 0x0000000000000080; +const WindowFlags WINDOW_MOUSE_GRABBED = 0x0000000000000100; +const WindowFlags WINDOW_INPUT_FOCUS = 0x0000000000000200; +const WindowFlags WINDOW_MOUSE_FOCUS = 0x0000000000000400; +const WindowFlags WINDOW_EXTERNAL = 0x0000000000000800; +const WindowFlags WINDOW_MODAL = 0x0000000000001000; +const WindowFlags WINDOW_HIGH_PIXEL_DENSITY = 0x0000000000002000; +const WindowFlags WINDOW_MOUSE_CAPTURE = 0x0000000000004000; +const WindowFlags WINDOW_MOUSE_RELATIVE_MODE = 0x0000000000008000; +const WindowFlags WINDOW_ALWAYS_ON_TOP = 0x0000000000010000; +const WindowFlags WINDOW_UTILITY = 0x0000000000020000; +const WindowFlags WINDOW_TOOLTIP = 0x0000000000040000; +const WindowFlags WINDOW_POPUP_MENU = 0x0000000000080000; +const WindowFlags WINDOW_KEYBOARD_GRABBED = 0x0000000000100000; +const WindowFlags WINDOW_VULKAN = 0x0000000010000000; +const WindowFlags WINDOW_METAL = 0x0000000020000000; +const WindowFlags WINDOW_TRANSPARENT = 0x0000000040000000; +const WindowFlags WINDOW_NOT_FOCUSABLE = 0x0000000080000000; + + +const uint WINDOWPOS_UNDEFINED_MASK = 0x1FFF0000; +const uint WINDOWPOS_CENTERED_MASK = 0x2FFF0000; + +macro uint @windowpos_undefined_display($x) => WINDOWPOS_UNDEFINED_MASK|$x; +macro bool @windowpos_isundefined($x) => ($x&0xFFFF0000) == WINDOWPOS_UNDEFINED_MASK; +macro uint @windowpos_centered_display($x) => WINDOWPOS_CENTERED_MASK|$x; +macro bool @windowpos_iscentered($x) => ($x&0xFFFF0000) == WINDOWPOS_CENTERED_MASK; + +const uint WINDOWPOS_UNDEFINED = @windowpos_undefined_display(0); +const uint WINDOWPOS_CENTERED = @windowpos_centered_display(0); + + +enum FlashOperation : inline CInt { + FLASH_CANCEL, + FLASH_BRIEFLY, + FLASH_UNTIL_FOCUSED +} + +typedef GLContext = void*; +typedef EGLDisplay = void*; +typedef EGLConfig = void*; +typedef EGLSurface = void*; +typedef EGLAttrib = ulong; // FIXME: this is not correct for all platforms +typedef EGLint = int; + +//alias EGLAttribArrayCallback = fn SDL_EGLAttrib*(void* userdata); +//alias EGLIntArrayCallback = fn SDL_EGLint*(void* userdata, EGLDisplay display, EGLConfig config); + +enum GLAttr : inline CInt { + GL_RED_SIZE, + GL_GREEN_SIZE, + GL_BLUE_SIZE, + GL_ALPHA_SIZE, + GL_BUFFER_SIZE, + GL_DOUBLEBUFFER, + GL_DEPTH_SIZE, + GL_STENCIL_SIZE, + GL_ACCUM_RED_SIZE, + GL_ACCUM_GREEN_SIZE, + GL_ACCUM_BLUE_SIZE, + GL_ACCUM_ALPHA_SIZE, + GL_STEREO, + GL_MULTISAMPLEBUFFERS, + GL_MULTISAMPLESAMPLES, + GL_ACCELERATED_VISUAL, + GL_RETAINED_BACKING, + GL_CONTEXT_MAJOR_VERSION, + GL_CONTEXT_MINOR_VERSION, + GL_CONTEXT_FLAGS, + GL_CONTEXT_PROFILE_MASK, + GL_SHARE_WITH_CURRENT_CONTEXT, + GL_FRAMEBUFFER_SRGB_CAPABLE, + GL_CONTEXT_RELEASE_BEHAVIOR, + GL_CONTEXT_RESET_NOTIFICATION, + GL_CONTEXT_NO_ERROR, + GL_FLOATBUFFERS, + GL_EGL_PLATFORM +} + +typedef GLProfile = uint; + +const GLProfile GL_CONTEXT_PROFILE_CORE = 0x0001; +const GLProfile GL_CONTEXT_PROFILE_COMPATIBILITY = 0x0002; +const GLProfile GL_CONTEXT_PROFILE_ES = 0x0004; + +typedef GLContextFlag = uint; + +const GLContextFlag GL_CONTEXT_DEBUG_FLAG = 0x0001; +const GLContextFlag GL_CONTEXT_FORWARD_COMPATIBLE_FLAG = 0x0002; +const GLContextFlag GL_CONTEXT_ROBUST_ACCESS_FLAG = 0x0004; +const GLContextFlag GL_CONTEXT_RESET_ISOLATION_FLAG = 0x0008; + +typedef GLContextReleaseFlag = uint; + +const GLContextReleaseFlag GL_CONTEXT_RELEASE_BEHAVIOR_NONE = 0x0000; +const GLContextReleaseFlag GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH = 0x0001; + +typedef GLContextResetNotification = uint; + +const GLContextResetNotification GL_CONTEXT_RESET_NO_NOTIFICATION = 0x0000; +const GLContextResetNotification GL_CONTEXT_RESET_LOSE_CONTEXT = 0x0001; + +extern fn int get_num_video_drivers() @extern("SDL_GetNumVideoDrivers"); +extern fn ZString get_video_driver(int index) @extern("SDL_GetVideoDriver"); +extern fn ZString get_current_video_driver() @extern("SDL_GetCurrentVideoDriver"); +extern fn SystemTheme get_system_theme() @extern("SDL_GetSystemTheme"); +extern fn DisplayID * get_displays(int *count) @extern("SDL_GetDisplays"); +extern fn DisplayID get_primary_display() @extern("SDL_GetPrimaryDisplay"); +extern fn PropertiesID get_display_properties(DisplayID displayID) @extern("SDL_GetDisplayProperties"); + +const ZString PROP_DISPLAY_HDR_ENABLED_BOOLEAN = "SDL.display.HDR_enabled"; +const ZString PROP_DISPLAY_KMSDRM_PANEL_ORIENTATION_NUMBER = "SDL.display.KMSDRM.panel_orientation"; + +extern fn ZString get_display_name(DisplayID displayID) @extern("SDL_GetDisplayName"); +extern fn bool get_display_bounds(DisplayID displayID, Rect* rect) @extern("SDL_GetDisplayBounds"); +extern fn bool get_display_usable_bounds(DisplayID displayID, Rect* rect) @extern("SDL_GetDisplayUsableBounds"); +extern fn DisplayOrientation get_natural_display_orientation(DisplayID displayID) @extern("SDL_GetNaturalDisplayOrientation"); +extern fn DisplayOrientation get_current_display_orientation(DisplayID displayID) @extern("SDL_GetCurrentDisplayOrientation"); +extern fn float get_display_content_scale(DisplayID displayID) @extern("SDL_GetDisplayContentScale"); +extern fn DisplayMode** get_fullscreen_display_modes(DisplayID displayID, int *count) @extern("SDL_GetFullscreenDisplayModes"); +extern fn bool get_closest_fullscreen_display_mode(DisplayID displayID, int w, int h, float refresh_rate, bool include_high_density_modes, DisplayMode*closest) @extern("SDL_GetClosestFullscreenDisplayMode"); +extern fn DisplayMode* get_desktop_display_mode(DisplayID displayID) @extern("SDL_GetDesktopDisplayMode"); +extern fn DisplayMode* get_current_display_mode(DisplayID displayID) @extern("SDL_GetCurrentDisplayMode"); +extern fn DisplayID get_display_for_point(Point *point) @extern("SDL_GetDisplayForPoint"); +extern fn DisplayID get_display_for_rect(Rect *rect) @extern("SDL_GetDisplayForRect"); +extern fn DisplayID get_display_for_window(Window *window) @extern("SDL_GetDisplayForWindow"); +extern fn float get_window_pixel_density(Window *window) @extern("SDL_GetWindowPixelDensity"); +extern fn float get_window_display_scale(Window *window) @extern("SDL_GetWindowDisplayScale"); +extern fn bool set_window_fullscreen_mode(Window *window, DisplayMode* mode) @extern("SDL_SetWindowFullscreenMode"); +extern fn DisplayMode* get_window_fullscreen_mode(Window *window) @extern("SDL_GetWindowFullscreenMode"); +extern fn void* get_window_icc_profile(Window *window, isz* size) @extern("SDL_GetWindowICCProfile"); +extern fn PixelFormat get_window_pixel_format(Window *window) @extern("SDL_GetWindowPixelFormat"); +extern fn Window** get_windows(int *count) @extern("SDL_GetWindows"); +extern fn Window* create_window(ZString title, int w, int h, WindowFlags flags) @extern("SDL_CreateWindow"); +extern fn Window* create_popup_window(Window *parent, int offset_x, int offset_y, int w, int h, WindowFlags flags) @extern("SDL_CreatePopupWindow"); +extern fn Window* create_window_with_properties(PropertiesID props) @extern("SDL_CreateWindowWithProperties"); + +const ZString PROP_WINDOW_CREATE_ALWAYS_ON_TOP_BOOLEAN = "SDL.window.create.always_on_top"; +const ZString PROP_WINDOW_CREATE_BORDERLESS_BOOLEAN = "SDL.window.create.borderless"; +const ZString PROP_WINDOW_CREATE_FOCUSABLE_BOOLEAN = "SDL.window.create.focusable"; +const ZString PROP_WINDOW_CREATE_EXTERNAL_GRAPHICS_CONTEXT_BOOLEAN = "SDL.window.create.external_graphics_context"; +const ZString PROP_WINDOW_CREATE_FLAGS_NUMBER = "SDL.window.create.flags"; +const ZString PROP_WINDOW_CREATE_FULLSCREEN_BOOLEAN = "SDL.window.create.fullscreen"; +const ZString PROP_WINDOW_CREATE_HEIGHT_NUMBER = "SDL.window.create.height"; +const ZString PROP_WINDOW_CREATE_HIDDEN_BOOLEAN = "SDL.window.create.hidden"; +const ZString PROP_WINDOW_CREATE_HIGH_PIXEL_DENSITY_BOOLEAN = "SDL.window.create.high_pixel_density"; +const ZString PROP_WINDOW_CREATE_MAXIMIZED_BOOLEAN = "SDL.window.create.maximized"; +const ZString PROP_WINDOW_CREATE_MENU_BOOLEAN = "SDL.window.create.menu"; +const ZString PROP_WINDOW_CREATE_METAL_BOOLEAN = "SDL.window.create.metal"; +const ZString PROP_WINDOW_CREATE_MINIMIZED_BOOLEAN = "SDL.window.create.minimized"; +const ZString PROP_WINDOW_CREATE_MODAL_BOOLEAN = "SDL.window.create.modal"; +const ZString PROP_WINDOW_CREATE_MOUSE_GRABBED_BOOLEAN = "SDL.window.create.mouse_grabbed"; +const ZString PROP_WINDOW_CREATE_OPENGL_BOOLEAN = "SDL.window.create.opengl"; +const ZString PROP_WINDOW_CREATE_PARENT_POINTER = "SDL.window.create.parent"; +const ZString PROP_WINDOW_CREATE_RESIZABLE_BOOLEAN = "SDL.window.create.resizable"; +const ZString PROP_WINDOW_CREATE_TITLE_STRING = "SDL.window.create.title"; +const ZString PROP_WINDOW_CREATE_TRANSPARENT_BOOLEAN = "SDL.window.create.transparent"; +const ZString PROP_WINDOW_CREATE_TOOLTIP_BOOLEAN = "SDL.window.create.tooltip"; +const ZString PROP_WINDOW_CREATE_UTILITY_BOOLEAN = "SDL.window.create.utility"; +const ZString PROP_WINDOW_CREATE_VULKAN_BOOLEAN = "SDL.window.create.vulkan"; +const ZString PROP_WINDOW_CREATE_WIDTH_NUMBER = "SDL.window.create.width"; +const ZString PROP_WINDOW_CREATE_X_NUMBER = "SDL.window.create.x"; +const ZString PROP_WINDOW_CREATE_Y_NUMBER = "SDL.window.create.y"; +const ZString PROP_WINDOW_CREATE_COCOA_WINDOW_POINTER = "SDL.window.create.cocoa.window"; +const ZString PROP_WINDOW_CREATE_COCOA_VIEW_POINTER = "SDL.window.create.cocoa.view"; +const ZString PROP_WINDOW_CREATE_WAYLAND_SURFACE_ROLE_CUSTOM_BOOLEAN = "SDL.window.create.wayland.surface_role_custom"; +const ZString PROP_WINDOW_CREATE_WAYLAND_CREATE_EGL_WINDOW_BOOLEAN = "SDL.window.create.wayland.create_egl_window"; +const ZString PROP_WINDOW_CREATE_WAYLAND_WL_SURFACE_POINTER = "SDL.window.create.wayland.wl_surface"; +const ZString PROP_WINDOW_CREATE_WIN32_HWND_POINTER = "SDL.window.create.win32.hwnd"; +const ZString PROP_WINDOW_CREATE_WIN32_PIXEL_FORMAT_HWND_POINTER = "SDL.window.create.win32.pixel_format_hwnd"; +const ZString PROP_WINDOW_CREATE_X11_WINDOW_NUMBER = "SDL.window.create.x11.window"; + +extern fn WindowID get_window_id(Window* window) @extern("SDL_GetWindowID"); +extern fn Window* get_window_from_id(WindowID id) @extern("SDL_GetWindowFromID"); +extern fn Window* get_window_parent(Window* window) @extern("SDL_GetWindowParent"); +extern fn PropertiesID get_window_properties(Window* window) @extern("SDL_GetWindowProperties"); + +const ZString PROP_WINDOW_SHAPE_POINTER = "SDL.window.shape"; +const ZString PROP_WINDOW_HDR_ENABLED_BOOLEAN = "SDL.window.HDR_enabled"; +const ZString PROP_WINDOW_SDR_WHITE_LEVEL_FLOAT = "SDL.window.SDR_white_level"; +const ZString PROP_WINDOW_HDR_HEADROOM_FLOAT = "SDL.window.HDR_headroom"; +const ZString PROP_WINDOW_ANDROID_WINDOW_POINTER = "SDL.window.android.window"; +const ZString PROP_WINDOW_ANDROID_SURFACE_POINTER = "SDL.window.android.surface"; +const ZString PROP_WINDOW_UIKIT_WINDOW_POINTER = "SDL.window.uikit.window"; +const ZString PROP_WINDOW_UIKIT_METAL_VIEW_TAG_NUMBER = "SDL.window.uikit.metal_view_tag"; +const ZString PROP_WINDOW_UIKIT_OPENGL_FRAMEBUFFER_NUMBER = "SDL.window.uikit.opengl.framebuffer"; +const ZString PROP_WINDOW_UIKIT_OPENGL_RENDERBUFFER_NUMBER = "SDL.window.uikit.opengl.renderbuffer"; +const ZString PROP_WINDOW_UIKIT_OPENGL_RESOLVE_FRAMEBUFFER_NUMBER = "SDL.window.uikit.opengl.resolve_framebuffer"; +const ZString PROP_WINDOW_KMSDRM_DEVICE_INDEX_NUMBER = "SDL.window.kmsdrm.dev_index"; +const ZString PROP_WINDOW_KMSDRM_DRM_FD_NUMBER = "SDL.window.kmsdrm.drm_fd"; +const ZString PROP_WINDOW_KMSDRM_GBM_DEVICE_POINTER = "SDL.window.kmsdrm.gbm_dev"; +const ZString PROP_WINDOW_COCOA_WINDOW_POINTER = "SDL.window.cocoa.window"; +const ZString PROP_WINDOW_COCOA_METAL_VIEW_TAG_NUMBER = "SDL.window.cocoa.metal_view_tag"; +const ZString PROP_WINDOW_OPENVR_OVERLAY_ID = "SDL.window.openvr.overlay_id"; +const ZString PROP_WINDOW_VIVANTE_DISPLAY_POINTER = "SDL.window.vivante.display"; +const ZString PROP_WINDOW_VIVANTE_WINDOW_POINTER = "SDL.window.vivante.window"; +const ZString PROP_WINDOW_VIVANTE_SURFACE_POINTER = "SDL.window.vivante.surface"; +const ZString PROP_WINDOW_WIN32_HWND_POINTER = "SDL.window.win32.hwnd"; +const ZString PROP_WINDOW_WIN32_HDC_POINTER = "SDL.window.win32.hdc"; +const ZString PROP_WINDOW_WIN32_INSTANCE_POINTER = "SDL.window.win32.instance"; +const ZString PROP_WINDOW_WAYLAND_DISPLAY_POINTER = "SDL.window.wayland.display"; +const ZString PROP_WINDOW_WAYLAND_SURFACE_POINTER = "SDL.window.wayland.surface"; +const ZString PROP_WINDOW_WAYLAND_VIEWPORT_POINTER = "SDL.window.wayland.viewport"; +const ZString PROP_WINDOW_WAYLAND_EGL_WINDOW_POINTER = "SDL.window.wayland.egl_window"; +const ZString PROP_WINDOW_WAYLAND_XDG_SURFACE_POINTER = "SDL.window.wayland.xdg_surface"; +const ZString PROP_WINDOW_WAYLAND_XDG_TOPLEVEL_POINTER = "SDL.window.wayland.xdg_toplevel"; +const ZString PROP_WINDOW_WAYLAND_XDG_TOPLEVEL_EXPORT_HANDLE_STRING = "SDL.window.wayland.xdg_toplevel_export_handle"; +const ZString PROP_WINDOW_WAYLAND_XDG_POPUP_POINTER = "SDL.window.wayland.xdg_popup"; +const ZString PROP_WINDOW_WAYLAND_XDG_POSITIONER_POINTER = "SDL.window.wayland.xdg_positioner"; +const ZString PROP_WINDOW_X11_DISPLAY_POINTER = "SDL.window.x11.display"; +const ZString PROP_WINDOW_X11_SCREEN_NUMBER = "SDL.window.x11.screen"; +const ZString PROP_WINDOW_X11_WINDOW_NUMBER = "SDL.window.x11.window"; + +extern fn WindowFlags get_window_flags(Window* window) @extern("SDL_GetWindowFlags"); +extern fn bool set_window_title(Window* window, ZString title) @extern("SDL_SetWindowTitle"); +extern fn ZString get_window_title(Window* window) @extern("SDL_GetWindowTitle"); +extern fn bool set_window_icon(Window* window, Surface *icon) @extern("SDL_SetWindowIcon"); +extern fn bool set_window_position(Window* window, int x, int y) @extern("SDL_SetWindowPosition"); +extern fn bool get_window_position(Window* window, int *x, int *y) @extern("SDL_GetWindowPosition"); +extern fn bool set_window_size(Window* window, int w, int h) @extern("SDL_SetWindowSize"); +extern fn bool get_window_size(Window* window, int *w, int *h) @extern("SDL_GetWindowSize"); +extern fn bool get_window_safe_area(Window* window, Rect *rect) @extern("SDL_GetWindowSafeArea"); +extern fn bool set_window_aspect_ratio(Window* window, float min_aspect, float max_aspect) @extern("SDL_SetWindowAspectRatio"); +extern fn bool get_window_aspect_ratio(Window* window, float *min_aspect, float *max_aspect) @extern("SDL_GetWindowAspectRatio"); +extern fn bool get_window_borders_size(Window* window, int *top, int *left, int *bottom, int *right) @extern("SDL_GetWindowBordersSize"); +extern fn bool get_window_size_in_pixels(Window* window, int *w, int *h) @extern("SDL_GetWindowSizeInPixels"); +extern fn bool set_window_minimum_size(Window* window, int min_w, int min_h) @extern("SDL_SetWindowMinimumSize"); +extern fn bool get_window_minimum_size(Window* window, int *w, int *h) @extern("SDL_GetWindowMinimumSize"); +extern fn bool set_window_maximum_size(Window* window, int max_w, int max_h) @extern("SDL_SetWindowMaximumSize"); +extern fn bool get_window_maximum_size(Window* window, int *w, int *h) @extern("SDL_GetWindowMaximumSize"); +extern fn bool set_window_bordered(Window* window, bool bordered) @extern("SDL_SetWindowBordered"); +extern fn bool set_window_resizable(Window* window, bool resizable) @extern("SDL_SetWindowResizable"); +extern fn bool set_window_always_on_top(Window* window, bool on_top) @extern("SDL_SetWindowAlwaysOnTop"); +extern fn bool show_window(Window* window) @extern("SDL_ShowWindow"); +extern fn bool hide_window(Window* window) @extern("SDL_HideWindow"); +extern fn bool raise_window(Window* window) @extern("SDL_RaiseWindow"); +extern fn bool maximize_window(Window* window) @extern("SDL_MaximizeWindow"); +extern fn bool minimize_window(Window* window) @extern("SDL_MinimizeWindow"); +extern fn bool restore_window(Window* window) @extern("SDL_RestoreWindow"); +extern fn bool set_window_fullscreen(Window* window, bool fullscreen) @extern("SDL_SetWindowFullscreen"); +extern fn bool sync_window(Window* window) @extern("SDL_SyncWindow"); +extern fn bool window_has_surface(Window* window) @extern("SDL_WindowHasSurface"); +extern fn Surface* get_window_surface(Window* window) @extern("SDL_GetWindowSurface"); +extern fn bool set_window_surface_v_sync(Window* window, int vsync) @extern("SDL_SetWindowSurfaceVSync"); + +const int WINDOW_SURFACE_VSYNC_DISABLED = 0; +const int WINDOW_SURFACE_VSYNC_ADAPTIVE = -1; + +extern fn bool get_window_surface_v_sync(Window* window, int *vsync) @extern("SDL_GetWindowSurfaceVSync"); +extern fn bool update_window_surface(Window* window) @extern("SDL_UpdateWindowSurface"); +extern fn bool update_window_surface_rects(Window* window, Rect* rects, int numrects) @extern("SDL_UpdateWindowSurfaceRects"); +extern fn bool destroy_window_surface(Window* window) @extern("SDL_DestroyWindowSurface"); +extern fn bool set_window_keyboard_grab(Window* window, bool grabbed) @extern("SDL_SetWindowKeyboardGrab"); +extern fn bool set_window_mouse_grab(Window* window, bool grabbed) @extern("SDL_SetWindowMouseGrab"); +extern fn bool get_window_keyboard_grab(Window* window) @extern("SDL_GetWindowKeyboardGrab"); +extern fn bool get_window_mouse_grab(Window* window) @extern("SDL_GetWindowMouseGrab"); +extern fn Window* get_grabbed_window() @extern("SDL_GetGrabbedWindow"); +extern fn bool set_window_mouse_rect(Window* window, Rect* rect) @extern("SDL_SetWindowMouseRect"); +extern fn Rect* get_window_mouse_rect(Window* window) @extern("SDL_GetWindowMouseRect"); +extern fn bool set_window_opacity(Window* window, float opacity) @extern("SDL_SetWindowOpacity"); +extern fn float get_window_opacity(Window* window) @extern("SDL_GetWindowOpacity"); +extern fn bool set_window_parent(Window* window, Window* parent) @extern("SDL_SetWindowParent"); +extern fn bool set_window_modal(Window* window, bool modal) @extern("SDL_SetWindowModal"); +extern fn bool set_window_focusable(Window* window, bool focusable) @extern("SDL_SetWindowFocusable"); +extern fn bool show_window_system_menu(Window* window, int x, int y) @extern("SDL_ShowWindowSystemMenu"); + +enum HitTestResult : inline CInt{ + HITTEST_NORMAL, + HITTEST_DRAGGABLE, + HITTEST_RESIZE_TOPLEFT, + HITTEST_RESIZE_TOP, + HITTEST_RESIZE_TOPRIGHT, + HITTEST_RESIZE_RIGHT, + HITTEST_RESIZE_BOTTOMRIGHT, + HITTEST_RESIZE_BOTTOM, + HITTEST_RESIZE_BOTTOMLEFT, + HITTEST_RESIZE_LEFT +} + +alias HitTest = fn HitTestResult(Window *win, Point *area, void *data); + +extern fn bool set_window_hit_test(Window *window, HitTest callback, void *callback_data) @extern("SDL_SetWindowHitTest"); +extern fn bool set_window_shape(Window *window, Surface *shape) @extern("SDL_SetWindowShape"); +extern fn bool flash_window(Window *window, FlashOperation operation) @extern("SDL_FlashWindow"); +extern fn void destroy_window(Window *window) @extern("SDL_DestroyWindow"); + +extern fn bool screen_saver_enabled() @extern("SDL_ScreenSaverEnabled"); +extern fn bool enable_screen_saver() @extern("SDL_EnableScreenSaver"); +extern fn bool disable_screen_saver() @extern("SDL_DisableScreenSaver"); + +extern fn bool gl_load_library(ZString path) @extern("SDL_GL_LoadLibrary"); +extern fn FunctionPointer gl_get_proc_address(ZString proc) @extern("SDL_GL_GetProcAddress"); +extern fn FunctionPointer egl_get_proc_address(ZString proc) @extern("SDL_EGL_GetProcAddress"); +extern fn void gl_unload_library() @extern("SDL_GL_UnloadLibrary"); +extern fn bool gl_extension_supported(ZString extension) @extern("SDL_GL_ExtensionSupported"); +extern fn void gl_reset_attributes() @extern("SDL_GL_ResetAttributes"); +extern fn bool gl_set_attribute(GLAttr attr, int value) @extern("SDL_GL_SetAttribute"); +extern fn bool gl_get_attribute(GLAttr attr, int *value) @extern("SDL_GL_GetAttribute"); +extern fn GLContext gl_create_context(Window* window) @extern("SDL_GL_CreateContext"); +extern fn bool gl_make_current(Window* window, GLContext context) @extern("SDL_GL_MakeCurrent"); +extern fn Window* gl_get_current_window() @extern("SDL_GL_GetCurrentWindow"); +extern fn GLContext gl_get_current_context() @extern("SDL_GL_GetCurrentContext"); +extern fn EGLDisplay egl_get_current_display() @extern("SDL_EGL_GetCurrentDisplay"); +extern fn EGLConfig egl_get_current_config() @extern("SDL_EGL_GetCurrentConfig"); +extern fn EGLSurface egl_get_window_surface(Window* window) @extern("SDL_EGL_GetWindowSurface"); +//extern fn void EGL_SetAttributeCallbacks(EGLAttribArrayCallback platformAttribCallback, EGLIntArrayCallback surfaceAttribCallback, EGLIntArrayCallback contextAttribCallback, void *userdata) @extern("SDL_EGL_SetAttributeCallbacks"); + +extern fn bool gl_set_swap_interval(int interval) @extern("SDL_GL_SetSwapInterval"); +extern fn bool gl_get_swap_interval(int *interval) @extern("SDL_GL_GetSwapInterval"); +extern fn bool gl_swap_window(Window *window) @extern("SDL_GL_SwapWindow"); +extern fn bool gl_destroy_context(GLContext context) @extern("SDL_GL_DestroyContext"); diff --git a/shaders/source/RawTriangle.vert.glsl b/shaders/source/RawTriangle.vert.glsl new file mode 100644 index 0000000..e885d0d --- /dev/null +++ b/shaders/source/RawTriangle.vert.glsl @@ -0,0 +1,29 @@ +#version 450 core + +// Explicitly set the output location for Vulkan +layout(location = 0) out vec4 vColor; + +void main() { + // Initialize with default values + vec2 pos = vec2(0.0); + vec4 color = vec4(0.0); + + // Use Vulkan's gl_VertexIndex instead of gl_VertexID + switch(gl_VertexIndex) { + case 0: + pos = vec2(-1.0, -1.0); + color = vec4(1.0, 0.0, 0.0, 1.0); + break; + case 1: + pos = vec2(1.0, -1.0); + color = vec4(0.0, 1.0, 0.0, 1.0); + break; + case 2: + pos = vec2(0.0, 1.0); + color = vec4(0.0, 0.0, 1.0, 1.0); + break; + } + + gl_Position = vec4(pos, 0.0, 1.0); + vColor = color; +} \ No newline at end of file diff --git a/shaders/source/SolidColor.frag.glsl b/shaders/source/SolidColor.frag.glsl new file mode 100644 index 0000000..e721e78 --- /dev/null +++ b/shaders/source/SolidColor.frag.glsl @@ -0,0 +1,9 @@ +#version 450 core + +layout(location = 0) in vec4 Color; // Explicit location for fragment input +layout(location = 0) out vec4 FragColor; // Explicit location for fragment output + +void main() +{ + FragColor = Color; +} \ No newline at end of file diff --git a/test/gpu_triangle.c3 b/test/gpu_triangle.c3 new file mode 100644 index 0000000..c57f695 --- /dev/null +++ b/test/gpu_triangle.c3 @@ -0,0 +1,240 @@ +import std::io; +import sdl3::sdl; +import std::io::file; +import std::core::mem; + +const int WINDOW_WIDTH = 1200; +const int WINDOW_HEIGHT = 800; +const ZString WINDOW_TITLE = "Basic Triangle"; + + +fn GPUShader* load_shader(GPUDevice* device, ZString filename, GPUShaderStage stage, uint sampler_count, uint uniform_buffer_count, uint storage_buffer_count, uint storage_texture_count) +{ + //if(!SDL_GetPathInfo(filename, null)) { + // io::eprintf("File (%s) does not exist.\n", filename); + // return null; + //} + + if (!file::is_file(filename.str_view())) { + io::eprintf("File %s is not a file\n", filename); + return null; + } + + ZString entrypoint; + GPUShaderFormat backend_formats = sdl::get_gpu_shader_formats(device); + GPUShaderFormat format = sdl::GPU_SHADERFORMAT_INVALID; + if (backend_formats & sdl::GPU_SHADERFORMAT_SPIRV) { + format = sdl::GPU_SHADERFORMAT_SPIRV; + entrypoint = "main"; + } + + + usz code_size = file::get_size(filename.str_view())!!; + char[] code = mem::new_array(char, code_size+1); + file::load_buffer(filename.str_view(), code)!!; + + GPUShaderCreateInfo shader_info = { + .code = code.ptr, + .code_size = code.len, + .entrypoint = entrypoint, + .format = format, + .stage = stage, + .num_samplers = sampler_count, + .num_uniform_buffers = uniform_buffer_count, + .num_storage_buffers = storage_buffer_count, + .num_storage_textures = storage_texture_count + }; + + GPUShader* shader = sdl::create_gpu_shader(device, &shader_info); + + if (shader == null) { + io::eprintf("ERROR: SDL_CreateGPUShader failed: %s\n", sdl::get_error()); + sdl::free(code); + return null; + } + sdl::free(code); + return shader; +} + + +fn void print_info() +{ + int render_drivers = sdl::get_num_render_drivers(); + io::printf("Number of render drivers: %d\n", render_drivers)!!; + + for (int i = 0; i < render_drivers; i++) { + io::printf("Render driver #%d: %s\n", i, sdl::get_render_driver(i))!!; + } + + int video_drivers = sdl::get_num_video_drivers(); + io::printf("Number of video drivers: %d\n", video_drivers)!!; + + for (int i = 0; i < video_drivers; i++) { + io::printf("Video driver #%d: %s\n", i, sdl::get_video_driver(i))!!; + } + + io::printf("Current video driver: %s\n", sdl::get_current_video_driver())!!; +} + + +fn void handle_event(Event event, bool* quit) { + switch (event.type) { + case sdl::EVENT_QUIT: { + *quit = true; + } break; + case sdl::EVENT_KEY_DOWN: { + switch (event.key.key) { + case sdl::K_Q: { + *quit = true; + } break; + case sdl::K_W: { + + } break; + case sdl::K_S: { + + } break; + case sdl::K_D: { + + } break; + } + } break; + } +} + + +fn int main() { + sdl::set_hint(sdl::HINT_VIDEO_DRIVER, "wayland"); + + if (!sdl::init(sdl::INIT_VIDEO)) { + io::eprintf("ERROR: SDL_Init failed: %s\n", sdl::get_error()); + return 1; + } + + Window* window; + window = sdl::create_window(WINDOW_TITLE, WINDOW_WIDTH, WINDOW_HEIGHT, sdl::WINDOW_VULKAN); + + if (window == null) { + io::eprintf("ERROR: SDL_CreateWindow failed: %s\n", sdl::get_error()); + return 1; + } + + sdl::set_window_position(window, sdl::WINDOWPOS_CENTERED, sdl::WINDOWPOS_CENTERED); + + GPUDevice* device = sdl::create_gpu_device(sdl::GPU_SHADERFORMAT_SPIRV, true, null); + + if (device == null) { + io::eprintf("ERROR: SDL_CreateGPUDevice failed: %s\n", sdl::get_error()); + return 1; + } + + ZString device_driver = sdl::get_gpu_device_driver(device); + io::printf("OK: Created device with driver %s\n", device_driver)!!; + + if (!sdl::claim_window_for_gpu_device(device, window)) { + io::eprintf("ERROR: SDL_ClaimWindowForGPUDevice failed: %s\n", sdl::get_error()); + return 1; + } + + + // Load shaders + create fill/line pipeline + GPUShader* shader_vert = load_shader(device, "shaders/compiled/RawTriangle.vert.spv", GPU_SHADERSTAGE_VERTEX, 0, 0, 0, 0); + if (shader_vert == null) { + io::eprintf("ERROR: LoadShader failed \n"); + return 1; + } + + GPUShader* shader_frag = load_shader(device, "shaders/compiled/SolidColor.frag.spv", GPU_SHADERSTAGE_FRAGMENT, 0, 0, 0, 0); + if (shader_vert == null) { + io::eprintf("ERROR: LoadShader failed \n"); + return 1; + } + + GPUGraphicsPipelineCreateInfo pipeline_info = { + .target_info = { + .num_color_targets = 1, + .color_target_descriptions = (GPUColorTargetDescription[]){{ + .format = sdl::get_gpu_swapchain_texture_format(device, window) + }}, + }, + .primitive_type = GPUPrimitiveType.GPU_PRIMITIVETYPE_TRIANGLELIST, + .vertex_shader = shader_vert, + .fragment_shader = shader_frag, + }; + + GPUGraphicsPipeline* pipeline_fill; + GPUGraphicsPipeline* pipeline_line; + + pipeline_info.rasterizer_state.fill_mode = GPU_FILLMODE_FILL; + pipeline_fill = sdl::create_gpu_graphics_pipeline(device, &pipeline_info); + if (pipeline_fill == null) { + io::eprintf("ERROR: SDL_CreateGPUGraphicsPipeline failed: %s\n", sdl::get_error()); + return -1; + } + + pipeline_info.rasterizer_state.fill_mode = GPU_FILLMODE_LINE; + pipeline_line = sdl::create_gpu_graphics_pipeline(device, &pipeline_info); + if (pipeline_line == null) { + io::eprintf("ERROR: SDL_CreateGPUGraphicsPipeline failed: %s\n", sdl::get_error()); + return -1; + } + + sdl::release_gpu_shader(device, shader_vert); + sdl::release_gpu_shader(device, shader_frag); + + const FColor COLOR_WHITE = (FColor) { 1.0f, 1.0f, 1.0f, 1.0f }; + const FColor COLOR_BLACK = (FColor) { 0.0f, 0.0f, 0.0f, 1.0f }; + const FColor COLOR_RED = (FColor) { 1.0f, 0.0f, 0.0f, 1.0f }; + const FColor COLOR_GREEN = (FColor) { 0.0f, 1.0f, 0.0f, 1.0f }; + const FColor COLOR_BLUE = (FColor) { 0.0f, 0.0f, 1.0f, 1.0f }; + const FColor COLOR_CYAN = (FColor) { 0.0f, 1.0f, 1.0f, 1.0f }; + const FColor COLOR_YELLOW = (FColor) { 1.0f, 1.0f, 0.0f, 1.0f }; + const FColor COLOR_PINK = (FColor) { 1.0f, 0.0f, 1.0f, 1.0f }; + + print_info(); + + bool quit = false; + while (!quit) { + Event event; + if (sdl::poll_event(&event)) handle_event(event, &quit); + GPUCommandBuffer* cmdbuf = sdl::acquire_gpu_command_buffer(device); + if (cmdbuf == null) { + io::eprintf("ERROR: SDL_AcquireGPUCommandBuffer failed: %s\n", sdl::get_error()); + break; + } + + GPUTexture* swapchain_texture; + if (!sdl::wait_and_acquire_gpu_swapchain_texture(cmdbuf, window, &swapchain_texture, null, null)) { + io::eprintf("ERROR: SDL_WaitAndAcquireGPUSwapchainTexture failed: %s\n", sdl::get_error()); + break; + } + + if (swapchain_texture == null) { + io::eprintf("ERROR: swapchain_texture is null\n"); + sdl::submit_gpu_command_buffer(cmdbuf); + break; + } + + GPUColorTargetInfo color_target_info; + color_target_info.texture = swapchain_texture; + color_target_info.clear_color = COLOR_BLACK; + color_target_info.load_op = GPULoadOp.GPU_LOADOP_CLEAR; + color_target_info.store_op = GPUStoreOp.GPU_STOREOP_STORE; + + GPURenderPass* render_pass = sdl::begin_gpu_render_pass(cmdbuf, &color_target_info, 1, null); + sdl::bind_gpu_graphics_pipeline(render_pass, pipeline_fill); + sdl::draw_gpu_primitives(render_pass, 3, 1, 0, 0); + sdl::end_gpu_render_pass(render_pass); + + sdl::submit_gpu_command_buffer(cmdbuf); + } + + sdl::release_gpu_graphics_pipeline(device, pipeline_fill); + sdl::release_gpu_graphics_pipeline(device, pipeline_line); + + sdl::release_window_from_gpu_device(device, window); + sdl::destroy_window(window); + sdl::destroy_gpu_device(device); + sdl::quit(); + + return 0; +} \ No newline at end of file diff --git a/test/lettuce.c3 b/test/lettuce.c3 new file mode 100644 index 0000000..82d7107 --- /dev/null +++ b/test/lettuce.c3 @@ -0,0 +1,63 @@ +import std::io; +import sdl3::sdl; + +fn int main() { + sdl::init(sdl::INIT_VIDEO); + + Window* win = sdl::create_window("SDL3 Image", 640, 480, 0); + if (win == null) { + io::eprintfn("SDL_CreateWindow Error: %s", sdl::get_error()); + sdl::quit(); + return 1; + } + + Renderer* ren = sdl::create_renderer(win, null); + if (ren == null) { + io::eprintfn("SDL_CreateRenderer Error: %s", sdl::get_error()); + sdl::destroy_window(win); + sdl::quit(); + return 1; + } + + Surface* bmp = sdl::load_bmp("lettuce.bmp"); + if (bmp == null) { + io::eprintfn("SDL_LoadBMP Error: %s", sdl::get_error()); + sdl::destroy_renderer(ren); + sdl::destroy_window(win); + sdl::quit(); + return 1; + } + + Texture* tex = sdl::create_texture_from_surface(ren, bmp); + sdl::destroy_surface(bmp); + + if (tex == null) { + io::eprintfn("SDL_CreateTextureFromSurface Error: %s", sdl::get_error()); + sdl::destroy_renderer(ren); + sdl::destroy_window(win); + sdl::quit(); + return 1; + } + + Event e; + bool quit = false; + + while (!quit) { + while (sdl::poll_event(&e)) { + if (e.type == sdl::EVENT_QUIT) { + quit = true; + } + } + + sdl::render_clear(ren); + sdl::render_texture(ren, tex, null, null); + sdl::render_present(ren); + } + + sdl::destroy_texture(tex); + sdl::destroy_renderer(ren); + sdl::destroy_window(win); + sdl::quit(); + + return 0; +} diff --git a/test/test_enum.c3 b/test/test_enum.c3 new file mode 100644 index 0000000..bb80fab --- /dev/null +++ b/test/test_enum.c3 @@ -0,0 +1,162 @@ +enum OtherEnum : int +{ + ABC, + DEF, + GHI +} + +enum EventType : (inline int val) +{ + SDL_EVENT_FIRST = 0, + + SDL_EVENT_QUIT = 0x100, + + SDL_EVENT_TERMINATING, + SDL_EVENT_LOW_MEMORY, + SDL_EVENT_WILL_ENTER_BACKGROUND, + SDL_EVENT_DID_ENTER_BACKGROUND, + SDL_EVENT_WILL_ENTER_FOREGROUND, + SDL_EVENT_DID_ENTER_FOREGROUND, + + SDL_EVENT_LOCALE_CHANGED, + + SDL_EVENT_SYSTEM_THEME_CHANGED, + + SDL_EVENT_DISPLAY_ORIENTATION = 0x151, + SDL_EVENT_DISPLAY_ADDED, + SDL_EVENT_DISPLAY_REMOVED, + SDL_EVENT_DISPLAY_MOVED, + SDL_EVENT_DISPLAY_DESKTOP_MODE_CHANGED, + SDL_EVENT_DISPLAY_CURRENT_MODE_CHANGED, + SDL_EVENT_DISPLAY_CONTENT_SCALE_CHANGED, + SDL_EVENT_DISPLAY_FIRST = SDL_EVENT_DISPLAY_ORIENTATION, + SDL_EVENT_DISPLAY_LAST = SDL_EVENT_DISPLAY_CONTENT_SCALE_CHANGED, + + SDL_EVENT_WINDOW_SHOWN = 0x202, + SDL_EVENT_WINDOW_HIDDEN, + SDL_EVENT_WINDOW_EXPOSED, + SDL_EVENT_WINDOW_MOVED, + SDL_EVENT_WINDOW_RESIZED, + SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED, + SDL_EVENT_WINDOW_METAL_VIEW_RESIZED, + SDL_EVENT_WINDOW_MINIMIZED, + SDL_EVENT_WINDOW_MAXIMIZED, + SDL_EVENT_WINDOW_RESTORED, + SDL_EVENT_WINDOW_MOUSE_ENTER, + SDL_EVENT_WINDOW_MOUSE_LEAVE, + SDL_EVENT_WINDOW_FOCUS_GAINED, + SDL_EVENT_WINDOW_FOCUS_LOST, + SDL_EVENT_WINDOW_CLOSE_REQUESTED, + SDL_EVENT_WINDOW_HIT_TEST, + SDL_EVENT_WINDOW_ICCPROF_CHANGED, + SDL_EVENT_WINDOW_DISPLAY_CHANGED, + SDL_EVENT_WINDOW_DISPLAY_SCALE_CHANGED, + SDL_EVENT_WINDOW_SAFE_AREA_CHANGED, + SDL_EVENT_WINDOW_OCCLUDED, + SDL_EVENT_WINDOW_ENTER_FULLSCREEN, + SDL_EVENT_WINDOW_LEAVE_FULLSCREEN, + SDL_EVENT_WINDOW_DESTROYED, + SDL_EVENT_WINDOW_HDR_STATE_CHANGED, + SDL_EVENT_WINDOW_FIRST = SDL_EVENT_WINDOW_SHOWN, + SDL_EVENT_WINDOW_LAST = SDL_EVENT_WINDOW_HDR_STATE_CHANGED, + + SDL_EVENT_KEY_DOWN = 0x300, + SDL_EVENT_KEY_UP, + SDL_EVENT_TEXT_EDITING, + SDL_EVENT_TEXT_INPUT, + SDL_EVENT_KEYMAP_CHANGED, + SDL_EVENT_KEYBOARD_ADDED, + SDL_EVENT_KEYBOARD_REMOVED, + SDL_EVENT_TEXT_EDITING_CANDIDATES, + + SDL_EVENT_MOUSE_MOTION = 0x400, + SDL_EVENT_MOUSE_BUTTON_DOWN, + SDL_EVENT_MOUSE_BUTTON_UP, + SDL_EVENT_MOUSE_WHEEL, + SDL_EVENT_MOUSE_ADDED, + SDL_EVENT_MOUSE_REMOVED, + + SDL_EVENT_JOYSTICK_AXIS_MOTION = 0x600, + SDL_EVENT_JOYSTICK_BALL_MOTION, + SDL_EVENT_JOYSTICK_HAT_MOTION, + SDL_EVENT_JOYSTICK_BUTTON_DOWN, + SDL_EVENT_JOYSTICK_BUTTON_UP, + SDL_EVENT_JOYSTICK_ADDED, + SDL_EVENT_JOYSTICK_REMOVED, + SDL_EVENT_JOYSTICK_BATTERY_UPDATED, + SDL_EVENT_JOYSTICK_UPDATE_COMPLETE, + + SDL_EVENT_GAMEPAD_AXIS_MOTION = 0x650, + SDL_EVENT_GAMEPAD_BUTTON_DOWN, + SDL_EVENT_GAMEPAD_BUTTON_UP, + SDL_EVENT_GAMEPAD_ADDED, + SDL_EVENT_GAMEPAD_REMOVED, + SDL_EVENT_GAMEPAD_REMAPPED, + SDL_EVENT_GAMEPAD_TOUCHPAD_DOWN, + SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION, + SDL_EVENT_GAMEPAD_TOUCHPAD_UP, + SDL_EVENT_GAMEPAD_SENSOR_UPDATE, + SDL_EVENT_GAMEPAD_UPDATE_COMPLETE, + SDL_EVENT_GAMEPAD_STEAM_HANDLE_UPDATED, + + SDL_EVENT_FINGER_DOWN = 0x700, + SDL_EVENT_FINGER_UP, + SDL_EVENT_FINGER_MOTION, + SDL_EVENT_FINGER_CANCELED, + + + SDL_EVENT_CLIPBOARD_UPDATE = 0x900, + + SDL_EVENT_DROP_FILE = 0x1000, + SDL_EVENT_DROP_TEXT, + SDL_EVENT_DROP_BEGIN, + SDL_EVENT_DROP_COMPLETE, + SDL_EVENT_DROP_POSITION, + + SDL_EVENT_AUDIO_DEVICE_ADDED = 0x1100, + SDL_EVENT_AUDIO_DEVICE_REMOVED, + SDL_EVENT_AUDIO_DEVICE_FORMAT_CHANGED, + + SDL_EVENT_SENSOR_UPDATE = 0x1200, + + SDL_EVENT_PEN_PROXIMITY_IN = 0x1300, + SDL_EVENT_PEN_PROXIMITY_OUT, + SDL_EVENT_PEN_DOWN, + SDL_EVENT_PEN_UP, + SDL_EVENT_PEN_BUTTON_DOWN, + SDL_EVENT_PEN_BUTTON_UP, + SDL_EVENT_PEN_MOTION, + SDL_EVENT_PEN_AXIS, + + SDL_EVENT_CAMERA_DEVICE_ADDED = 0x1400, + SDL_EVENT_CAMERA_DEVICE_REMOVED, + SDL_EVENT_CAMERA_DEVICE_APPROVED, + SDL_EVENT_CAMERA_DEVICE_DENIED, + + SDL_EVENT_RENDER_TARGETS_RESET = 0x2000, + SDL_EVENT_RENDER_DEVICE_RESET, + SDL_EVENT_RENDER_DEVICE_LOST, + + SDL_EVENT_PRIVATE0 = 0x4000, + SDL_EVENT_PRIVATE1, + SDL_EVENT_PRIVATE2, + SDL_EVENT_PRIVATE3, + + SDL_EVENT_POLL_SENTINEL = 0x7F00, + + SDL_EVENT_USER = 0x8000, + + SDL_EVENT_LAST = 0xFFFF, + + SDL_EVENT_ENUM_PADDING = 0x7FFFFFFF +} + +import std::io; + + +fn int main() +{ + EventType ev = SDL_EVENT_WINDOW_RESIZED; + io::printfn("%d == %d", SDL_EVENT_WINDOW_RESIZED, ev); + return 0; +} \ No newline at end of file