From 1517f2caeab47133ca372785c4ab32f73fd91d66 Mon Sep 17 00:00:00 2001 From: Julia <145168563+julia-aph@users.noreply.github.com> Date: Mon, 1 Apr 2024 17:39:21 -0500 Subject: [PATCH] input almost working,, yay --- checksums.txt | 2 +- objects/controller.o | Bin 2126 -> 0 bytes objects/ctrl.o | Bin 0 -> 4825 bytes objects/gametime.o | Bin 0 -> 1217 bytes objects/input.o | Bin 2134 -> 1519 bytes objects/main.o | Bin 4047 -> 3089 bytes objects/term.o | Bin 0 -> 2369 bytes objects/tetr.o | Bin 0 -> 1800 bytes objects/win.o | Bin 3511 -> 1239 bytes objects/winhandler.o | Bin 0 -> 3667 bytes source/io/ctrl.c | 300 ++++++++++++++++--------------- source/io/ctrl.h | 58 +++--- source/io/input.c | 48 +++-- source/io/input.h | 8 +- source/io/platforms/winhandler.c | 12 +- source/io/term.c | 3 +- source/main.c | 26 ++- test.exe | Bin 80047 -> 80992 bytes 18 files changed, 252 insertions(+), 205 deletions(-) delete mode 100644 objects/controller.o create mode 100644 objects/ctrl.o create mode 100644 objects/gametime.o create mode 100644 objects/term.o create mode 100644 objects/tetr.o create mode 100644 objects/winhandler.o diff --git a/checksums.txt b/checksums.txt index 09411bb..49259eb 100644 --- a/checksums.txt +++ b/checksums.txt @@ -1 +1 @@ -{"source\\main.c": "3d2369e9333b52142cb9f019e877e434", "source\\io\\controller.c": "4459cc302f4b70b072f39b43e87a0c08", "source\\io\\input.c": "d3336a096a3ac2d792292d84dd20fb8f", "source\\io\\platforms\\win.c": "4eb14343a9cb40a7f6a9d9e43329c46e", "source\\io\\platforms\\winio.c": "b3a5e9d8f2e8ab4ec38d14007e4fc3f4"} \ No newline at end of file +{"source\\main.c": "82d4037af47edc6a1ef16f061e8980c2", "source\\game\\gametime.c": "40eedcb0dd0e0ebd42a09860aeb24517", "source\\game\\tetr.c": "fee38bad904b2053644fddf0ba08cd5e", "source\\io\\ctrl.c": "a838d22152710a4be156b5c90c41863c", "source\\io\\input.c": "aca98b0ac5983206b3fad774dc4d6146", "source\\io\\term.c": "b8fa47ec18810973c2123e7ec3a3cec6", "source\\io\\platforms\\win.c": "5f8d684bbaae885edf7505a1d90d91e8", "source\\io\\platforms\\winhandler.c": "b0c21fa0370350172987a3ec39be1d20"} \ No newline at end of file diff --git a/objects/controller.o b/objects/controller.o deleted file mode 100644 index 6eb90111144d85f162b7bc1cf340dce29cc1305e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2126 zcmbtV&ubGw6rRndnuD?t6e_6fp`ey_TWc-i4~W*Kj+=YYTw?i zaIJl@V*UWGu4wI$_!in=MZ5HBMLV~U<=V|ErhF9}cFPUD#2lGLTC?`nT-`XUF#gtD zrsZD@UP;y{30Ic1XH0um-D9p+%vHPk@biZYWe+dZG?0AGTvoiugJ!FPvw-oBUS33s zY}t&@H!|aMDeJ$Q;iZ4ImXMb6%zHzLsV%XdsH)&XJbXHUeLfm#Ay)ZMP4(MF69(yN z$cBdg2;B-H{T)L6MLL4J?P%ytz|=;hb;u!L(p`{az@!gDP63lX2{{W)`aI+!FzG9h z3@{Dr{re*VF*eZOe?Z?gXy*rpJBRyv_0s;nR9|oBwY1}QPNuV+MQfr%AHQbjTz!06 zKk8WN30FTemd{vDu|s$E?$-D0HF}J0f4^-2+aXalf_bZlFfk3Hg7r}hhD?^7R3G7`odwdRmntSWs;xj&Ik7VxN^n#`f%Z!;RZ?&XiKwDtEtecsR>YxQ8eXcf z;Lb@zl@@D9B}Ww(aTC&;lUzX}S9(j5yCKo6^xl@-U5V~VuaUKL7AzV+>x^Ai(o=cY znabrX$4CpFW;ziKh3QO1U;I7>EcdKEX?guhF%ibciu3_q_X>tAx)JK#CbJV3b#Rl} z2aEc-$xw}{o14rq7(K*LGV1JR4E@nle>a(1V5rNR%mXmg>w*csHX!k(^cx8O?FU~P z@~l;j;47p4DJJm3M7|($?F*RLu r?ex_EHEicIQ`bEL{o}6&luLm_>tHt)1rC-<*^`A-%0FLUuXn;<7A;wy diff --git a/objects/ctrl.o b/objects/ctrl.o new file mode 100644 index 0000000000000000000000000000000000000000..e4e2a9fe175669b5a111ed52ccae548d2fbafab4 GIT binary patch literal 4825 zcmb7IZ)jWB6~D4%M@d@brCrcQ*1aqlxL~VFmZtXFY_j9G+@x`*HB%C3JXyBnT8m<9 z(i3$;LY=4%z9<5-b)~Qt%IMf1GUgA(HeqzK7iN=B&bKo1!3z`=><=z0t5!UFzjLp2 z^(33Fd+>D6{hf2qJ^$``PcM3N2czq44`bh!l#BVS*r+9G^%L01SgV7v2al=wUJM2c z_W7a_D`Jz|jtsD1!PlQoZ^yG^VI3J}@1o3Yu)m8>6w zluOmhk-i6zvtO_;@XQfA!dMW~TV-D>9Fhy2JIk-HHa9TF^S2Lx&Aox^96H_wpj7;T&M`<8h0#trkQ8DaL8QGnd|YwFCX21MM!$C=mE&H z=9)uFK5u$ci;&^jyN2G$FP6l;K@n=6Fuk4`vw09}J=3Ol!rXw#>vvq_keDkDkT==8 zek?o#14ns2aWDxhVQHx4v@rdrMNd1nY3FmxE-vOlwwx48cgR{=FUMS{or@(%G{9^O zP9^ByDroYmp1>CNf>|PcE6*VcrFxBX*t%3*-9lUCLVoVJ$3@VMaFi$Mr3pW?%-I!uo?;;l*DLaqU z^5bk6<}7Vvzdv;&dNH-3cx z0Y@daiEU6Nxd3id%-lm4xm-;$l%kTlMWLHAZ5m=}0#0HHqy^TP&7PT%F(`sANl%Ab zCW1|qWvi+ddHHAXg`(T6vijL4sA4V_wf%^YvcGOG4^*PI43xpm|7>mw^V6L9DQv~w zyQ->WJtI11>5+7pQcHee)q@QbpD+l6t6Tydv7 zb}}Aro)1#4p#zD}nMg@!nTuwb>6NRr&NCBm4R)AD=9_Xh9cXGdTQYm>!gQ)veh8$b z)#cnMI-BLnP$Y~FW&RXwoiBb!Hg}jM&-h_wk(Vz}2AQg}?A<_Z+{9A1m`8fNlpX^i zGY~Q_96Gc9B|^3m!QMJvw-IG~ysZ5;U%i>VRbP$FPMWNAPp&v7|8F1vPW!;e%#E#1 zp~g{nbx!rbDb>`<+4@{%w#2j7N-VQOWrlJEUjjI+vf-$nD65MU&Z#=~ip830<~f;U z6crB6Je`|=Bic3RriFkl=O$=iKP(G)%j-U`Uw6K4U8VX^P*|7`tyRnK6J!hM8b_7F zgpGPtH?~(5Qa0qd7hSg~)h$sK{Tk{fOww2^YivM0);RT6oyM_io6OoLSEz`r$xwF8 zSHk;MlnO9t%)N|44!UQl#1ZRiMSi*D9aClYzmsQcBA)4h`;CJ2b#z07oQ`A=H(HnI zge^a6Ucqb&#|sVx$m^L_ITrV`|8QX9%0ArKd2b@<+OAzy>VbOP7L{_dZB~^R$-d~# z1s}t%&9XCov4-rbZhq3MMmN18;PfK0XbY&4Y@uDx%g?VzzgJ9pS~aRip_f{>K>47A z5UK`LT0zn?%rgTDJu`pGi^6z|>P#Sq*=t2+^;YB|o-H|F|3S9YaP67#g0&-Ca#&BU z9Mvg@NpYOHl~y}4M+j0w=1*T+4Qi%Unk>gXe0?oWu)~f+j=`) z(N!-~!7DoIN1HsQuaACk_2IsUySY3%acuU1rtvJILfwVNKjEg=Ng7vi2SC%f*NMo1 zrtu}bSHWdD9>7!l0%#g7+(V#gTyDY$n#MzTMIQrA*NjJSYCqOr7ZFrG-n zqL8zLHPRLN{`hcoi@XB0Jn0PgU$l(<$Bf}jB9XLGj6~`&X$CuS{P=f`mY(?ViF0k| zjvg^a+mD8i9%;)Aq^!2&NIE{+mW~az8vU7g!ZP|V8(pc`z>sB}i3~?$sdTH6diH7K z(06=?eSW2{1G)JYNEhqZ)OAf=MOMBcxi>X632MK@K0po>_d`uBf>PX7jr~hg44G2g z=Rm2ootk=4bA`r!p{aK@_Ym@TKw8kLsi%<7gA(&;3RCt3ZYR8}P*}jeCNcW+qPSGA zih5FWy&9tmR$N1KX(xrXXsT6nDYS}9Rj#OZ&3!>*0ZnylF4x#;P0=|}Hvd>-^u$$~ z>0~HwpT?q^8q(Z^#*&({GD}LQ}UicT!_-YU*vxeMe*OY3hB={hh{c zYide!KhW5$rv9wCbP!{h(Y3M3*sG568CH<~#ou;$Iheud?V$eRku-%#_Ae?n8!hUwhfVWWasM6!7b>5%Sr-VxUbx z<_|Ue%4D!iz{9F!(prH~KazaC0#HRs`sX#sZ!uFg9lUbo3PbUn z98PAeuFT+IEX9UUZ{c_}Hf%9Uet0AmradGb8I7k|hCbfJ!WUzgE2JI%>B!}@6(6{0 n-ys~1UrL6!xH>2NP5*P literal 0 HcmV?d00001 diff --git a/objects/gametime.o b/objects/gametime.o new file mode 100644 index 0000000000000000000000000000000000000000..82eb46f1f839a2d1fef021e79c38c17861a213a6 GIT binary patch literal 1217 zcmZ`(&1(};5TEUCHG;4as^s9|9Rk*ptg(%u6ohCAS&>3eL%h^AA1~=blZM?bra6dE z5JC`&M^FA8UQE@4f(8Exp@)KDPo9i3?`_gen-0v!oB7Sm%erj~v2U2NkjfhE z^SB}6-Us))f(ZiWOyi>HUkEVcns~qLo%Hx5bpcg;2CiuKew+Iz%_kQj#+5=x-LXKXi z0>1v@i?2UFteg7l0gBcD3#KLonXg~Ne%MpQjwwZUJP@Qr)cMG=rYiUYg#9FB2Y$*~ zB!NVF5BX}KKcJ2w6Y-;?2hsw_udlDM#SOcaFC|NvH0!KptV}w&TXno-d&jjqNtbUW zSY_AV_E=?)J#=_=%VST=tr~aS1at1)W_MSNWg{gk-bA&4tidKqdKC>0P|^%EWPnS^ zs<5RM!86@b6;k>rPg+zcZNPziJ?t7B_p&iVs;A6{XEfZiRhn0RUQlbthg0&$W^*O@zBH`;Ys$3ce`Dn hM{wJ`YBjhQ_FIL+EN9*xm($1;fIgncS1=c>)(>m@mua=;GS>Ti z#%ksNVuUilj)G?h+K{+{DPHSN>D2eJA3`#?pCgS@jr!(8yf86e$>~_0fr~tX=j?CEw@m5NX%PPWmxkQxsShTd>pY~I_h69!ONequFOzaQA5*oil z&jq7~vl#@QnV!DKZ_YX1%wl$NVw^W8CyEo}+4YJqvh`ZSX=WSt>Ig5dJFej6SA5F1 zE31Ofm%OU&H%7RB_ZGi1W{es+B!i4WFG5qyf~DP3jPCrBM9*L^OSA@iMWQCG;%xyb z-a8=0`vydHrr00YA&FqvDX0!_i0B^AOCRM@(M*J>A{C`vDtbLaJc=4Cj%#B^@~_L- z3(fKB>%yogS7ZkQq@h>)=r8Lb*Wja5mmC?t0ZVtFJn@%+Qs^4p3HAT6#9skw8okF} z@fU!auO}zg{d8u!cHwxF0L43>+DO-^_mdLudU=YHL%p7q;Add;{^{DIWH6ZBkGwcT zR`(rGtb{J|*i9$)P?BdFy-=vRu40jgWKK5|)#yKQWrPV54V$168 zn8-df3bKk9vEWM}NB5LVdkt+UR89*?4*?Z&=rNZBg#=wl>ON?Wo5<`THON4x>i1nK=X(aV+JeOgakl!GfB&m8l z>o|jKVXlmRrQU$2z~Q1C_97%n63KY6-|rUq{np7(g-^Jj-Rq|T{|NlfLait`L4L_k zCiyZ@DL}9K_Dv<{sr!UhUTD;vi@Nh8wfPZR)1%bgp*0?{-Jq2}wM&0={1VjDcke>q z2)HzVZ@1gvzMEHH{?(%D@dq`14{*Ju9)}SuUH9> z@C%RKDfPySC>W^s(`XrJ>U!Ha)vA1Qt7Tky`Zl%zAlcNft9SJ4m0fA0&h~d>Ht)Y~ zw|U*v)r<6gbrZcop66-pCN8Mkpi-Sm4Z8DKre1jqIjKow{{Vmv>cy7&HtaRGJ@5nR z0rgT5NUY3b?KE%0hMW2dt?;cR=;=27jAPq-HVdZ}93vbzv?B^-?9IA=f8!1B1M6J~ z138JRw!}GY^@kNczR}f`g3h;&MM3-#1^I|wbIF{^weZ* z)v#G?*~rHnb8%eDu3Ae>%dTl>Y|~g|+PO?2XWGuVW>0*qeL4|85y!2#ybt;?424_* zeSo7M1N3u%?g2W&t&c!s1q#pcU5@rZzsHdR`5xsc2?(Pr6HnM~_3;WrX@Y@f@f%$~reSA&_{(=swwcML4baRa{{c1_e+d8p diff --git a/objects/main.o b/objects/main.o index b3ddca73e1456918cc70094fc57fab5234a8b077..e580177a2f3fe7bc71c1d1e6826e311ec15b1ee6 100644 GIT binary patch literal 3089 zcmai0Ur1zC7(dq;%l@H)ftBsvTDKiRXU$C7Uh?0t$I`HLaH*DY9Ixx(I5W&#cU349 z_tsv98$Kja^sxIDv=2g%e<~VtK_7ZB2=XDw-iEdZD}sfU?Dw5B_s+dac))Xh-|zc- zzWdGfj=ujOqm`^+tU(|@3+mdmF0kAd{fsp#jQ#Y0l+WN$S^scwG^$5kc2&UNl)DJP zcGjN{j%2f5_P8`hb{TKLIhg%$EZ%T?aN299!mhVi8=zS2thqgy_S)4#lYm_d?n;YX z$nJcr5S^_b==!mE{q5laKL5u(D7kgJexFXWPvvGfz|B2wZgMNM*s)pzew{XMZWM4Z zo(tXN=J$NzcLlclT*>o=d?nu~`1!`3Uz#-B;Z}FO3I*Ik1>s`VkZYmG+*uc4O5qBy z`JA#jDa_CwY*B=rX7{8VJ3JRApPggzEo1ob@UVE1hdmcD($JKWY@d`Q&vQ${B^Syc z%L5MgxWO%>S>(fzv31&V*)HjbZ-%;Zg%s$PsHkI&TsmBBTM)q%zVIz&sJMCy zx%S<;NI))%N54%Oj}jFX21SID;}AuZa^bagBp3NmE^#84T@|{_I##hU@9)jl`~FW~ zJ_wET+^z7w2(s2G*q{IAUr_5%2L|YnLtV`1_Ha=j-zTf$vy*QS5s%N`p(%-6-dwa7 z5{RW>IT(O$LeX}r+ zd53@c39YqPT;>8Q)#d+G`yNtGv$AFd4+^qD@{g=6O){-86<0hzK!H`j7rVM%Rs((U z;4^RqDaT7l-V)BXHx345JDG>B6B8<5oA2YOm)PoV`;+XE!E z6F^e?p`-m0h`Q@%Ujv;I=vScA0{sP~3RI4pOH>E+jNk%5&k1xM=n;V~06i9#4sL?U+YiN@0r+Bd{*Gn3jRUK=)L+q`2Fj#u2nz$=!Xu_^NE z(ld$vR3afcJB}0BiDTGK4)f75=B9^vUAsoXi=3USFKRzWV$xH(^TsRP^tLAs2`e6E z1CpGN`q|l8H=NLBBC*t{mSu!S;>po0i%!S0MN&Y?Mk0~e_(WEph)iY~N*&ZPlbusz zjLyF3bk}$^Q{?pw)jX()b1>yLgu`G;nhqgX>RNUv8rNA7_auP_^k_!!N#dgH)l@tw F(SP$LY}x<- literal 4047 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 N1VON=Wf{h|(tmK%8}vKf-Rr}f716(< z`es~2`K*X$%`1^>iP$xT@dzN=2F@-S|J98lW(+x5{3x6iao!YBMne#V!jXp%!qwl$ z=bq}^PA9kc!);SFd*4897%gdhMutquXw$aZv?X{$L~fHJu`?_R4WPE*RFElRqLK$O zQxu*9VZn33>uTAqVj&jK?h5`&d3Soe)otF5$W$Wsa$qz;Hfro%eT|N?^Nf+R@r<3> zKdtQR%AUgnMskf&tBVKXSNYBvwRHBr`@*QXFRHtS6mlne`P<)VqvrAIKgPhH_dTAB zHjYF^)opRL3lrzvma+Nz?ZE-OZS8e3aJP-k$8c|LL3F1pI$EL{dJzr180B*v@sZDr zz2Vr+LEs0FxV5*9J}9>tyOwr0_wH)9J|o0ex`a1WO>*~EW$>`VW^m$(?CC?b6!OTP zwp33^S!_tn=?I7B=%i}pzQ484aS}RW)os!_P1)iGAxg)$Q6maRs`GBs*!Zq| z|3Ai<37k27a`42!DcmY*T$-N#+REjNE0?Z~U7MV+)~62Zz+it%D^6! zKB`OkvR(91H%gVN=x`TV-Kf1(Ecvi#yggv-M;`iNU>B6<@M&nsnZ=HgoPEZp@R3%M zBjcZI)(4oCOjAIlrQ#%SXiA#mq-}5dFtd6;z4@$S0sl>{3IpBim6!PE;LzF;PCIT(%VO1l)=YGwXfZ>1-V$$^O}K)t54f)`4OnZ4ex5f)-m~O< zr!atct2I3mpoPmXxqPk06KnF-8vo$mh(7+w-p%5ZQ^Mb`=S|CbQ;{|YYy6o%{gmdi zCfgP3@P5Ube3SuM@2~P1bfJ6KD*H2ya74mNMzOSBFc=|U?*~d@Fsd+h!LjJQK+n+l&t7^T7>hVs4^YhvMqQ8<{r%G^6o+mnD|eEmtQ~uh zbtbEOb1T+IVmoJXa+c$ErYPIMK*{6B*(%hiPw#>WP0qqcEfbh4E!iiJ}u{8l$@-M literal 3511 zcmbVOU2GIp6u#5l!a{3ijgS;n9Iy`v?OLHU#rUwbEL@C@3(E$K*0SwR=}Nn8cBi3j z{3&b~JDIFD8WMdl^5jp#Ltn5!OxPBZ!UM5}2V>-+KA3FaU$MbKC|y`ntQllA!9Y*3-Vju(aEwvgzpYpcy;QLt?K>)u z>llT9!RKq8r2t_(^Q-7Zx%n&4+}F6-&eiwwcqH>M zSmPMfEa56&@4Bj^9Y4DNq#VOEc%dE z?Pl1E_>hqaS`UZIM{xX#H*o&{vSx)AGV?y;Bp&Jqzrbi_UQvg>6u_%yzXy;Tin!2b zlR+O3ST!-peG)v$MR(1f%j;F%7^GiP*hyT3hF6&CMx3K3&2U zIpqe=6RF(gx#6I2TH)3qs^s&iIO=frL%d{#D3ZPQ?!>?= znxt1go)Nylo^XWk6icc=OCA}XD0%6Khby>fu!9x7!OaHjf5?yZ6mSLXkmHIKx`Tq= zD;DaRYB(zym))!grRkReKYg77?c6Xysvm5CrgcJ)+mMB6oL@53zxGvu>`(5i+%BX5 z8i59JxyZ|=_--g%E7kVvSK!^ETg5~Zzq`PU<+UAbzBVF;;`5aHc6mKY7)K?1*oED^ z8y9rSyc^3rYqpitC}G8oy(Oh&1>7FUTZP>3&H6n)rILZCeNu8CI-fYLJ@;cS$B*WV z_*K~RUzq8?l;)iXZ;d_o1HS}J^A~7#4ovfH{Eh(A+<~Tj6PV_o(HI@TG!NjeFZ?I# zw{A6n7UMu;yFKsSygx^&SQq*KCRC*FN3EfkSp@jt{E#hf}t>X4A4d$EYA z!-~3QNoPM+)I&>56byCH64MTb`e=!vlT$ZI1|A+v_VgOmQ<6CvOHi0ZXGzBW%}a;$ zDAaLOMN7l|y$j>3M#KHBE6%PI+aPQ1?_9Jt>4(Ik-{*%qK3E&c@g`E12(AFh8zf?yq3H6i$0c%TE?Dd$0`tb;JN2gSxX#kL(Q;DnZ@~rEor;TPS9fn( zcN4NM3rswb?ui*~9fh^ahnAK^S5Hez!IipN;f!QaOc5h)`y;8wlpZs5s;O9Or!M?! rU{Vy(4Y!w)Jgmp!HY@7VrCemhwn5zf?o=d^JkhDY*7~;IX0X2j+Li-U diff --git a/objects/winhandler.o b/objects/winhandler.o new file mode 100644 index 0000000000000000000000000000000000000000..0fb62c50b4a4562017666e6f38172b868632afd4 GIT binary patch literal 3667 zcmbVPZ){Ul6n}4hbrpu~h$M@Du);LVY~6q{r(&`(p4`PPPDY&~Shn_!)otz4zJ@_0 z3@e70m&SeZlQ9yah8REa!8lk*?0`5hBrfp_AtWp&CWG-|E=u}gQh(>(*Vor=A;z1$ zcYpVH&OP^>bI-kfjeJ@zQG02PB)!OyA_a79ROeW{&buY4R>tEI;|=KiQrDqCq*w2C z=&c4@q^@kBFPU`8e9nP|$4GCq)Zi#&w;wB2Zjl;V0wXK+_92XimVX;Dh3h3s^=RE2 zB3#=j{A;Oiw1*sY;eC4*y&yCGVCnmQW_0?DV3irHVy5b2#uPJ=AxX;5u=G{`!7By5 zix2Yod{Jg_C2P#mxqPbp0!^EDUqEuD(z&f%G)aPsq~tV1VPed?Q`tvYX_!`*zAR2Q zgG)|lPi4KIXR&GnJnlwZRV*`9jc_^<;BU-yF|*sl40VAS!5jkh|J+h0c_)Go2=^O4 zQ(YhnmuYyq%j2C;AM~elPp3SVt}+hWRqy`?`}$I6>BpkvcXEEcLH;=2uR zhh3VBKFsHNUCgVGQu_*O^PA0X*b(y>YEH~sM-+Tk3gy)-Hsj>|b5s+V@2k&H&-Z(l z8CSRkb4)_bP4e2Rxs0ucL!BsrYb-q{!_T>P<60}P$POdhVf@0pUtca`Q?q3qa<-$A z58W8LX$Dv(^X`95V(F}xP0cB=qs+lmiPc2rHX1ct9Rt>&n|`vWa)s<0othULy9 zDHo6wEQ@nt%!n|p4p#x{^=&#gW6(Qow)zZpoMnPzSn&**zV%N&e_Flc{ZYM>UXVY@ zruK@wk5k?`oci6(G8I1HGg#srGmv*!G_kUYm5o*(#&q@gnb<9s>Eefk8QjRcjFYG4 zWK+F~q`ac$ydS^LFQVlUin=gvvyA4U(h%2M%c8eZ^(}gRo%G^&)}r^lseW%gzj2b~ zi_BY_o!(>8w>YtaUxMsjNZnlATy7 zbCU+R9gz2Nd8PZCO4sA^28l+N{e-YX@$qP_K7zgi5B1;Ssj~W8=&SKi|1x&J!Rr46 z-U&?o<}xG=nEI=D=(mabJBlP70H*#dHfac$+RXa!lt8m>d)nGw^>68n#`g5o^)xm5 zN1K~MO^tP_a6+#ei6^6@bxCcY*58+k4(a~BqyAk9Ej*z6yL)31Es?DCCwA2Mw{8z? z3y@=I&sdKlH3L11N0D0bUe6JEDbNWZ`VCg3(>C{+jV{^fI?!`?6zL-ueNhlP3nZ*e z06ovSdq9*YMY@4#U*PC(Aj+d6$%tN{^)}iLB&>V@w2A8_Z0;n`X3pUyJ%PssI|bwc zdXjUrXF}?;5lMuU))Z38i$H!`O8yFNi;Ze+DJ4`$8*M~66_$6}T#Jo%+fvH2nA>3^ zstPf8pUu5%qXV||kj+JGG+;}qhJ@u28|k(*&>tPrFrxM_FG+{xBhlCZYGp`E1j2%+ zx7UI)cGM*o`2xbMNc@QSAjHNZ_tYqdlqs5p@e-^g3@U|Wa zk!W(HR}T*q##nIIP&_=yS9H1+3Pp!ULZO0pO^w_?!S2!YZarf8C#bfB)~jn&nZ12O z8h5r;5~6NRxBTslM>LS3@W5bF9}EpAEseceZ^TmJemG{9ShUoMdn2Ccj>ZlTX>av? asD*WDL?3_$k #include #include #include @@ -5,10 +6,11 @@ #include #include #include +#include #include "fumotris.h" -#define IO_BUF_SIZE 8 +#define IO_BUF_SIZE 16 enum InputType { KEY, @@ -19,8 +21,8 @@ enum InputType { }; struct InputRecord { - enum InputType type; u16 id; + u8 type; union { struct { @@ -35,7 +37,7 @@ struct InputRecord { } joystick; } data; - double timestamp; + struct timespec timestamp; }; struct InputBuffer { @@ -53,8 +55,6 @@ struct InputBuffer NewInputBuffer() } struct Axis { - u8 type; - union { struct { u32 value; @@ -70,8 +70,8 @@ struct Axis { } joystick; } data; - double last_pressed; - double last_released; + struct timespec last_pressed; + struct timespec last_released; }; enum KeyCode { @@ -112,208 +112,220 @@ hashtype Hash(void *item, size_t size) struct ident { u16 id; - enum InputType type; + u8 type; }; -hashtype hash_ident(u16f id, enum InputType type) +hashtype hash_ident(u16f value, u8f type) { - struct ident obj = { id, type }; - return Hash(&obj, sizeof(struct ident)); + struct ident id = { value, type }; + return Hash(&id, sizeof(struct ident)); } -struct code_bkt { +struct bkt { hashtype hash; - u16 code; - struct Axis axis; -}; - -struct bind_bkt { - hashtype hash; - u16 bind; + u16 value; + u8 type; struct Axis *axis; }; +struct dict { + size_t capacity; + size_t filled; + struct bkt *bkts; +}; + struct Ctrl { - struct { - size_t capacity; - size_t filled; - struct code_bkt *bkts; - } codes; - - struct { - size_t capacity; - size_t filled; - struct bind_bkt *bkts; - } binds; + struct dict codes; + struct dict binds; + pthread_t thread; pthread_mutex_t mutex; }; typedef struct Ctrl Ctrl; -Ctrl NewCtrl(struct code_bkt *codes, size_t c, struct bind_bkt *binds, size_t b) +Ctrl NewCtrl(struct bkt *codes, struct Axis *axes, size_t c, struct bkt *binds, size_t b) { - memset(codes, 0, sizeof(struct code_bkt) * c); - memset(binds, 0, sizeof(struct bind_bkt) * b); + memset(codes, 0, sizeof(struct bkt) * c); + memset(axes, 0, sizeof(struct Axis) * c); + memset(binds, 0, sizeof(struct bkt) * b); + + for (size_t i = 0; i < c; i++) { + codes[i].axis = &axes[i]; + } Ctrl ctrl; + + ctrl.codes.capacity = c; + ctrl.codes.filled = 0; ctrl.codes.bkts = codes; + + ctrl.binds.capacity = b; + ctrl.binds.filled = 0; ctrl.binds.bkts = binds; + ctrl.mutex = PTHREAD_MUTEX_INITIALIZER; return ctrl; } -void CtrlPoll(struct InputBuffer *buf) +struct bkt *get_bkt(struct dict *dict, size_t i) { - for (size_t i = 0; i < buf->count; i++) { - struct InputRecord *rec = &buf->records[i]; + assert(i < dict->capacity); + return &dict->bkts[i]; +} - switch (rec->type) { - case KEY: - key_update(); - break; - case AXIS: - axis_update(); - break; - case JOYSTICK: - joystick_update(); - break; +void set_bkt(struct bkt *bkt, hashtype hash, u16f value, u8f type) +{ + bkt->hash = hash; + bkt->value = value; + bkt->type = type; +} + +size_t wrap(size_t x, size_t wrap) +{ + return x % (SIZE_MAX - wrap + 1); +} + +bool find_or_set(struct dict *dict, struct bkt **out, u16f value, u8f type) +{ + hashtype hash = hash_ident(value, type); + const size_t index = hash % dict->capacity; + + size_t i = index; + while (i != wrap(index - 1, dict->capacity)) { + struct bkt *bkt = get_bkt(dict, i); + + if (bkt->hash == 0) { + set_bkt(bkt, hash, value, type); + dict->filled += 1; + *out = bkt; + return false; } - } -} -struct ctrl_bkt *get_code_bkt(Ctrl *ctrl, size_t i) -{ - assert(i < ctrl->codes.capacity); - return &ctrl->codes.bkts[i]; -} - -struct ctrl_bkt *get_bind_bkt(Ctrl *ctrl, size_t i) -{ - assert(i < ctrl->binds.capacity); - return &ctrl->binds.bkts[i]; -} - -struct code_bkt *find_code_or_set_empty(Ctrl *ctrl, u16 code, ) -{ - const size_t index = hash % ctrl->codes.capacity; - size_t i = index; - - while (i != index - 1) { - struct code_bkt *bkt = get_code_bkt(ctrl, i); - if (bkt->hash == search) - return bkt; - if (bkt->hash == 0) - return bkt; + if (bkt->value == value and bkt->type == type) { + *out = bkt; + return true; + } - i = (i + 1) % ctrl->codes.capacity; + i = (i + 1) % dict->capacity; } + + *out = nullptr; + return false; +} + +struct bkt *find(struct dict *dict, u16f value, u8f type) +{ + hashtype hash = hash_ident(value, type); + const size_t index = hash % dict->capacity; + + size_t i = index; + while (i != wrap(index - 1, dict->capacity)) { + struct bkt *bkt = get_bkt(dict, i); + if (bkt->hash == 0) + goto next; + + if (bkt->value == value and bkt->type == type) { + return bkt; + } +next: + i = (i + 1) % dict->capacity; + }; + return nullptr; } -struct ctrl_bkt *find_bind(Ctrl *ctrl, hashtype hash, hashtype search) +struct Axis *find_axis(struct dict *dict, u16f value, u8f type) { - const size_t index = hash % ctrl->binds.capacity; - size_t i = index; - - while (i != index - 1) { - struct bind_bkt *bkt = get_bind_bkt(ctrl, i); - if (bkt->hash == 0) - return bkt; - - i = (i + 1) % ctrl->binds.capacity; - } - return nullptr; -} - -bool CtrlMap(Ctrl *ctrl, u16f bind, u16f code, enum InputType type) -{ - if (ctrl->binds.filled == ctrl->binds.capacity) - return false; - - struct code_bkt *code_bkt = find_code_or_set_empty(ctrl, code, type); - assert(code_bkt != nullptr); - - hashtype bind_hash = hash_ident(bind, type); - struct bind_bkt *bind_bkt = find_bind(ctrl, bind_hash, bind_hash); - bind_bkt->hash = bind_hash; - bind_bkt->bind = bind; - bind_bkt->axis = &code_bkt->axis; - - ctrl->binds.filled += 1; - - return true; -} - -struct Axis *find_bind_axis(Ctrl *ctrl, u16f bind, enum InputType type) -{ - hashtype bind_hash = hash_ident(bind, KEY); - struct ctrl_bkt *bind_bkt = find_bind(ctrl, bind_hash, bind_hash); - if (bind_bkt == nullptr) + struct bkt *bkt = find(dict, value, type); + if (bkt == nullptr) return nullptr; - return &get_bkt(ctrl, bind_bkt->index)->axis; + return bkt->axis; +} + +bool CtrlMap(Ctrl *ctrl, u16f code, u16f bind, u8f type) +{ + assert(ctrl->codes.filled < ctrl->codes.capacity); + assert(ctrl->binds.filled < ctrl->binds.capacity); + + struct bkt *code_bkt; + find_or_set(&ctrl->codes, &code_bkt, code, type); + assert(code_bkt != nullptr); + + struct bkt *bind_bkt; + bool bind_existed = find_or_set(&ctrl->binds, &bind_bkt, bind, type); + assert(bind_bkt != nullptr); + + if(bind_existed and bind_bkt->axis == code_bkt->axis) + return false; + + bind_bkt->axis = code_bkt->axis; + return true; } struct Axis *CtrlGet(Ctrl *ctrl, u16f code, u8f type) { -= struct ctrl_bkt *code_bkt = find_code(ctrl, code, type); + struct bkt *code_bkt = find(&ctrl->codes, code, type); if (code_bkt == nullptr) return nullptr; - return &code_bkt->axis; + return code_bkt->axis; } -bool CtrlUpdateKey(Ctrl *ctrl, struct InputRecord *record) +void update_key(struct Axis *axis, struct InputRecord *record) { - struct Axis *axis = find_bind_axis(ctrl, record->id, KEY); - if (axis == nullptr) - return false; - - if (record->data.key.is_down) { + if (record->data.key.is_down) axis->last_pressed = record->timestamp; - } else { + else axis->last_released = record->timestamp; - } - axis->data.axis.value = record->data.key.is_down; - return true; + axis->data.key.is_down = record->data.key.is_down; } -bool CtrlUpdateAxis(Ctrl *ctrl, struct InputRecord *record) +void update_axis(struct Axis *axis, struct InputRecord *record) { - struct Axis *axis = find_bind_axis(ctrl, record->id, AXIS); - if (axis == nullptr) - return false; - axis->data.axis.value = record->data.axis.value; axis->last_pressed = record->timestamp; - - return true; } -bool CtrlUpdateJoystick(Ctrl *ctrl, struct InputRecord *record) +void update_joystick(struct Axis *axis, struct InputRecord *record) { - struct Axis *axis = find_bind_axis(ctrl, record->id, JOYSTICK); - if (axis == nullptr) - return false; - axis->data.joystick.x = record->data.joystick.x; axis->data.joystick.y = record->data.joystick.y; axis->last_pressed = record->timestamp; - - return true; } -bool CtrlUpdateWindow(Ctrl *ctrl, struct InputRecord *record) +bool CtrlPoll(Ctrl *ctrl, struct InputBuffer *buf) { - struct Axis *axis = find_bind_axis(ctrl, record->id, WINDOW); - if (axis == nullptr) - return false; + pthread_mutex_lock(&buf->mutex); + pthread_mutex_lock(&ctrl->mutex); - axis->data.joystick.x = record->data.joystick.x; - axis->data.joystick.y = record->data.joystick.y; - axis->last_pressed = record->timestamp; + for (size_t i = 0; i < buf->count; i++) { + struct InputRecord *rec = &buf->records[i]; + struct Axis *axis = find_axis(&ctrl->binds, rec->id, rec->type); + if (axis == nullptr) + continue; + + switch (rec->type) { + case KEY: + update_key(axis, rec); + break; + case AXIS: + update_axis(axis, rec); + break; + case JOYSTICK: + case WINDOW: + update_joystick(axis, rec); + break; + default: + return false; + } + } + + buf->count = 0; + pthread_mutex_unlock(&buf->mutex); + pthread_mutex_unlock(&ctrl->mutex); return true; } \ No newline at end of file diff --git a/source/io/ctrl.h b/source/io/ctrl.h index d13c3c5..0ace76e 100644 --- a/source/io/ctrl.h +++ b/source/io/ctrl.h @@ -6,10 +6,11 @@ #include #include #include +#include #include "fumotris.h" -#define IO_BUF_SIZE 8 +#define IO_BUF_SIZE 16 enum InputType { KEY, @@ -20,8 +21,8 @@ enum InputType { }; struct InputRecord { - enum InputType type; u16 id; + u8 type; union { struct { @@ -36,7 +37,7 @@ struct InputRecord { } joystick; } data; - double timestamp; + struct timespec timestamp; }; struct InputBuffer { @@ -63,8 +64,8 @@ struct Axis { } joystick; } data; - double last_pressed; - double last_released; + struct timespec last_pressed; + struct timespec last_released; }; enum KeyCode { @@ -90,37 +91,42 @@ enum JoystickCode { typedef u32 hashtype; -struct ctrl_bkt { - hashtype bind_hash; - u16 bind; - size_t index; +struct bkt { + hashtype hash; + u16 value; + u8 type; + struct Axis *axis; +}; - hashtype code_hash; - u16 code; - - struct Axis axis; +struct dict { + size_t capacity; + size_t filled; + struct bkt *bkts; }; struct Ctrl { - size_t capacity; - size_t filled; - struct ctrl_bkt *bkts; + struct dict codes; + struct dict binds; + pthread_t thread; pthread_mutex_t mutex; }; typedef struct Ctrl Ctrl; -Ctrl NewCtrl(struct ctrl_bkt *bkts_prealloc, size_t capacity); +#define NEW_CTRL(CTRL, CODES, BINDS) \ + struct bkt NEW_CTRL_CODES[CODES]; \ + struct bkt NEW_CTRL_BINDS[BINDS]; \ + struct Axis NEW_CTRL_AXES[CODES]; \ + CTRL = NewCtrl( \ + NEW_CTRL_CODES, \ + NEW_CTRL_AXES, CODES, \ + NEW_CTRL_BINDS, BINDS \ + ); \ -bool CtrlMap(Ctrl *ctrl, u16f bind, u16f code, enum InputType type); +Ctrl NewCtrl(struct bkt *codes, struct Axis *axes, size_t c, struct bkt *binds, size_t b); -struct Axis *CtrlGet(Ctrl *ctrl, u16f code, enum InputType type); +bool CtrlMap(Ctrl *ctrl, u16f code, u16f bind, u8f type); -bool CtrlUpdateKey(Ctrl *ctrl, struct InputRecord *record); - -bool CtrlUpdateAxis(Ctrl *ctrl, struct InputRecord *record); - -bool CtrlUpdateJoystick(Ctrl *ctrl, struct InputRecord *record); - -bool CtrlUpdateWindow(Ctrl *ctrl, struct InputRecord *record); +struct Axis *CtrlGet(Ctrl *ctrl, u16f code, u8f type); +bool CtrlPoll(Ctrl *ctrl, struct InputBuffer *buf); \ No newline at end of file diff --git a/source/io/input.c b/source/io/input.c index f017283..8713d82 100644 --- a/source/io/input.c +++ b/source/io/input.c @@ -12,36 +12,52 @@ #include "win.h" #endif -#define IO_BUF_SIZE 8 - struct input_args { Ctrl *ctrl; - struct InputBuffer *in_buf; + struct InputBuffer *buf; + pthread_mutex_t mutex; }; void *block_input(void *args_ptr) { struct input_args *args = args_ptr; Ctrl *ctrl = args->ctrl; - struct InputBuffer *in_buf = args->in_buf; + struct InputBuffer *buf = args->buf; + printf("RECIEVED BUF: %u, %u\n", args->ctrl, args->buf); -input_loop: - bool success; + while (true) { + printf("\tIN LOOP\n"); + bool success; - #ifdef _WIN32 - success = WindowsBlockInput(&in_buf); - #endif + #ifdef _WIN32 + success = WindowsBlockInput(buf); + #endif - if (!success) - exit(1); + printf("%llu\n", buf->records[0].timestamp.tv_sec); + + if (!success) { + printf("winfail"); + exit(1); + } + } - goto input_loop; return nullptr; } -void StartInput(Ctrl *ctrl) +void StartInput(Ctrl *ctrl, struct InputBuffer *buf) { - pthread_t input_thread; - pthread_create(&input_thread, nullptr, block_input, ctrl); - //pthread_join(input_thread, nullptr); + printf("START INPUT:%u\n", buf); + struct input_args args = { + .ctrl = ctrl, + .buf = buf, + .mutex = PTHREAD_MUTEX_INITIALIZER + }; + pthread_mutex_lock(&args.mutex); + pthread_create(&ctrl->thread, nullptr, block_input, &args); + pthread_mutex_destroy(); +} + +void JoinInput(Ctrl *ctrl) +{ + pthread_join(ctrl->thread, nullptr); } \ No newline at end of file diff --git a/source/io/input.h b/source/io/input.h index 1a75c3b..3253074 100644 --- a/source/io/input.h +++ b/source/io/input.h @@ -8,10 +8,6 @@ #include "ctrl.h" #include "fumotris.h" -struct InputBuffer { - struct InputRecord records[IO_BUF_SIZE]; - size_t count; - pthread_mutex_t mutex; -}; +void StartInput(Ctrl *ctrl, struct InputBuffer *buf); -void StartInput(Ctrl *ctrl); \ No newline at end of file +void JoinInput(Ctrl *ctrl); \ No newline at end of file diff --git a/source/io/platforms/winhandler.c b/source/io/platforms/winhandler.c index 343c9a6..b3b901c 100644 --- a/source/io/platforms/winhandler.c +++ b/source/io/platforms/winhandler.c @@ -5,6 +5,7 @@ #include #include #include +#include #include "fumotris.h" #include "gametime.h" @@ -103,14 +104,20 @@ bool dispatch_record(struct InputRecord *record, INPUT_RECORD win_record) bool WinBlockInput(struct InputBuffer *buf) { + printf("\twin blocked: %u\n", buf); size_t win_size = IO_BUF_SIZE - buf->count; + printf("\twhar\n"); INPUT_RECORD win_buf[win_size]; DWORD count; + printf("\treading in..\n"); if (!ReadConsoleInput(windows.input_handle, win_buf, win_size, &count)) return false; + printf("\read done\n"); - double now = GetTime(); + struct timespec now; + timespec_get(&now, TIME_UTC); + pthread_mutex_lock(&buf->mutex); for (size_t i = 0; i < count; i++) { @@ -133,11 +140,12 @@ bool WinWait(double seconds) { LARGE_INTEGER duration; duration.QuadPart = (u64)(-10000000.0 * seconds); - if (!SetWaitableTimer(windows.timer, &duration, 0, NULL, NULL, FALSE)) return false; + printf("about to wait..\n"); DWORD result = WaitForSingleObject(windows.timer, INFINITE); + printf("waitforsingle\n"); if (result != WAIT_OBJECT_0) return false; diff --git a/source/io/term.c b/source/io/term.c index 2871b56..d920236 100644 --- a/source/io/term.c +++ b/source/io/term.c @@ -71,7 +71,8 @@ size_t TermBufToChars(struct TermBuf *term, char *buf, size_t max_chars) u8f last_bg = 0; u8f last_fg = 0; - size_t filled = snprintf(buf, max_chars, "\x1b[H\x1b[0m"); + //size_t filled = snprintf(buf, max_chars, "\x1b[H\x1b[0m"); + size_t filled = snprintf(buf, max_chars, "\x1b[0m"); for(size_t y = 0; y < term->hgt; y++) { for(size_t x = 0; x < term->wid; x++) { diff --git a/source/main.c b/source/main.c index e519d90..7541a47 100644 --- a/source/main.c +++ b/source/main.c @@ -51,7 +51,7 @@ u8 I[16] = { 0, 0, 0, 0 }; -void Loop(Ctrl *ctrl) +void Loop(Ctrl *ctrl, struct InputBuffer *in_buf) { struct TermBuf term = NewTermBuf(20, 20); struct CharBlk4 term_blks[term.area]; @@ -73,15 +73,16 @@ void Loop(Ctrl *ctrl) falling.blks = falling_blks; for (int i = 0; i < 7779997; i++) { - + CtrlPoll(ctrl, in_buf); + printf("polled\n"); TetrMapToTermBuf(&board, &term); TetrMapToTermBuf(&falling, &term); - size_t size = TermBufToChars(&term, out, out_max); - puts(out); + TermBufToChars(&term, out, out_max); + //puts(out); - WindowsWait(0.1); + printf("%u\n", WindowsWait(0.01)); } } @@ -89,8 +90,8 @@ int main() { WindowsInit(); - struct ctrl_bkt bkts[13]; - Ctrl ctrl = NewCtrl(bkts, 13); + Ctrl ctrl; + NEW_CTRL(ctrl, 13, 13); for (size_t i = 0; i < 9; i++) { CtrlMap(&ctrl, key_binds[i], key_codes[i], KEY); @@ -103,8 +104,15 @@ int main() printf("set controls\n"); - StartInput(&ctrl); - Loop(&ctrl); + struct InputBuffer in_buf = { + .count = 0, + .mutex = PTHREAD_MUTEX_INITIALIZER + }; + + StartInput(&ctrl, &in_buf); + Loop(&ctrl, &in_buf); + + JoinInput(&ctrl); return 0; } \ No newline at end of file diff --git a/test.exe b/test.exe index 8c36f1ff72a6855f9b2e50973bf5a929d951dfa7..5c5a00c470ed5b27af5aa948436c9b6f8e5899c4 100644 GIT binary patch literal 80992 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 delta 23696 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 KYj=<0_x>+8{NiN*