From 5b6664ffcef398ec1a5de83b9f7dabd1e0999072 Mon Sep 17 00:00:00 2001 From: Alexander Petrov Date: Wed, 12 Aug 2026 23:17:22 +0300 Subject: [PATCH] =?UTF-8?q?=D0=97=D0=B5=D1=80=D0=BA=D0=B0=D0=BB=D1=8C?= =?UTF-8?q?=D0=BD=D1=8B=D0=B5=20=D0=BA=D0=B0=D0=B4=D1=80=D1=8B=20=D0=BF?= =?UTF-8?q?=D0=B5=D1=80=D1=81=D0=BE=D0=BD=D0=B0=D0=B6=D0=B5=D0=B9=20?= =?UTF-8?q?=E2=80=94=20=D0=B3=D0=BE=D1=82=D0=BE=D0=B2=D1=8B=D0=BC=D0=B8=20?= =?UTF-8?q?=D1=84=D0=B0=D0=B9=D0=BB=D0=B0=D0=BC=D0=B8,=20=D0=B0=20=D0=BD?= =?UTF-8?q?=D0=B5=20=D1=80=D0=B0=D0=B7=D0=B2=D0=BE=D1=80=D0=BE=D1=82=D0=BE?= =?UTF-8?q?=D0=BC=20=D0=B2=20=D1=80=D0=B0=D0=BD=D1=82=D0=B0=D0=B9=D0=BC?= =?UTF-8?q?=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Замеры в MAME (такты Z80, кадр = 430 000) решили вопрос однозначно: загрузка 28 атласов Кида с HDD — 27 160 092 такта (1.26 с), 970 003 на страницу; разворот ОДНОЙ страницы на месте — 12 645 582 такта (0.59 с), т.е. 771 такт/байт. Даже идеальный вариант (копия accel'ом ~0.25 кадра + asm-реверс ~2.2 кадра) дал бы ~1.05 млн на страницу — то есть в лучшем случае сравнялся бы с чтением готового файла. На 34 страницы: 1.5 с загрузки против 20 с разворота. * Упаковщики пишут второй набор: vflip_cols/vflip_page в pop_pack_kid.py -> kid0_v.atl…kid27_v.atl, sword_v.atl; pop_pack_guard.py -> g0_v.atl…g4_v.atl ТОЛЬКО для обычного стража (на уровне 9 tbl_guard_type = 0; тень рисуется атласами Кида, скелет/визирь с переворотом не встречаются). * pop_vflip.c схлопнулся до таблицы «страница -> зеркальная пара»; весь побайтовый разворот и аллокация EMM удалены. * pop_vflip_load_all (банк 8) грузит набор ОДНИМ вызовом и откуда угодно — задел под загрузку ресурсов во время интро. Зовётся при старте и при смене уровня, если это POP_UPSIDE_LEVEL; чит U на других уровнях поднимает набор лениво (страховка в главном цикле). * Стартовый уровень стал параметром сборки: make LEVEL=N (-DFIRST_LEVEL). Проверено в MAME на уровне 9: переворот мгновенный, pop_flip_screen = 897 263 такта (2.1 кадра) — это сама копия экрана, загрузки в кадре больше нет. tests-host 6/6. --- applications/PoP/poc/res/guard/g0_v.atl | Bin 0 -> 9711 bytes applications/PoP/poc/res/guard/g1_v.atl | Bin 0 -> 10732 bytes applications/PoP/poc/res/guard/g2_v.atl | Bin 0 -> 10079 bytes applications/PoP/poc/res/guard/g3_v.atl | Bin 0 -> 5232 bytes applications/PoP/poc/res/guard/g4_v.atl | Bin 0 -> 1131 bytes applications/PoP/poc/res/kid/kid0_v.atl | Bin 0 -> 7263 bytes applications/PoP/poc/res/kid/kid10_v.atl | Bin 0 -> 5263 bytes applications/PoP/poc/res/kid/kid11_v.atl | Bin 0 -> 5915 bytes applications/PoP/poc/res/kid/kid12_v.atl | Bin 0 -> 6199 bytes applications/PoP/poc/res/kid/kid13_v.atl | Bin 0 -> 9521 bytes applications/PoP/poc/res/kid/kid14_v.atl | Bin 0 -> 5823 bytes applications/PoP/poc/res/kid/kid15_v.atl | Bin 0 -> 5387 bytes applications/PoP/poc/res/kid/kid16_v.atl | Bin 0 -> 3000 bytes applications/PoP/poc/res/kid/kid17_v.atl | Bin 0 -> 7389 bytes applications/PoP/poc/res/kid/kid18_v.atl | Bin 0 -> 5529 bytes applications/PoP/poc/res/kid/kid19_v.atl | Bin 0 -> 5872 bytes applications/PoP/poc/res/kid/kid1_v.atl | Bin 0 -> 7891 bytes applications/PoP/poc/res/kid/kid20_v.atl | Bin 0 -> 6326 bytes applications/PoP/poc/res/kid/kid21_v.atl | Bin 0 -> 7409 bytes applications/PoP/poc/res/kid/kid22_v.atl | Bin 0 -> 10223 bytes applications/PoP/poc/res/kid/kid23_v.atl | Bin 0 -> 9764 bytes applications/PoP/poc/res/kid/kid24_v.atl | Bin 0 -> 5932 bytes applications/PoP/poc/res/kid/kid25_v.atl | Bin 0 -> 6246 bytes applications/PoP/poc/res/kid/kid26_v.atl | Bin 0 -> 5390 bytes applications/PoP/poc/res/kid/kid27_v.atl | Bin 0 -> 932 bytes applications/PoP/poc/res/kid/kid2_v.atl | Bin 0 -> 8145 bytes applications/PoP/poc/res/kid/kid3_v.atl | Bin 0 -> 7043 bytes applications/PoP/poc/res/kid/kid4_v.atl | Bin 0 -> 9758 bytes applications/PoP/poc/res/kid/kid5_v.atl | Bin 0 -> 7809 bytes applications/PoP/poc/res/kid/kid6_v.atl | Bin 0 -> 5426 bytes applications/PoP/poc/res/kid/kid7_v.atl | Bin 0 -> 4085 bytes applications/PoP/poc/res/kid/kid8_v.atl | Bin 0 -> 9085 bytes applications/PoP/poc/res/kid/kid9_v.atl | Bin 0 -> 7885 bytes applications/PoP/poc/res/kid/sword_v.atl | Bin 0 -> 5168 bytes applications/PoP/roomtest/Makefile | 19 +++- applications/PoP/roomtest/pop_cdraw.c | 25 ++++ applications/PoP/roomtest/pop_guard.h | 5 + applications/PoP/roomtest/pop_kboot.c | 28 +++++ applications/PoP/roomtest/pop_kdraw.c | 7 ++ applications/PoP/roomtest/pop_kid.h | 2 + applications/PoP/roomtest/pop_tune.h | 5 + applications/PoP/roomtest/pop_vflip.c | 114 +++++-------------- applications/PoP/roomtest/pop_vflip.h | 49 ++++---- applications/PoP/roomtest/roomtest.c | 6 + applications/PoP/roomtest/roomtest_cold.c | 11 ++ applications/PoP/roomtest/tests-host/stubs.c | 12 ++ applications/PoP/toolchain/pop_pack_guard.py | 12 +- applications/PoP/toolchain/pop_pack_kid.py | 31 +++++ 48 files changed, 219 insertions(+), 107 deletions(-) create mode 100644 applications/PoP/poc/res/guard/g0_v.atl create mode 100644 applications/PoP/poc/res/guard/g1_v.atl create mode 100644 applications/PoP/poc/res/guard/g2_v.atl create mode 100644 applications/PoP/poc/res/guard/g3_v.atl create mode 100644 applications/PoP/poc/res/guard/g4_v.atl create mode 100644 applications/PoP/poc/res/kid/kid0_v.atl create mode 100644 applications/PoP/poc/res/kid/kid10_v.atl create mode 100644 applications/PoP/poc/res/kid/kid11_v.atl create mode 100644 applications/PoP/poc/res/kid/kid12_v.atl create mode 100644 applications/PoP/poc/res/kid/kid13_v.atl create mode 100644 applications/PoP/poc/res/kid/kid14_v.atl create mode 100644 applications/PoP/poc/res/kid/kid15_v.atl create mode 100644 applications/PoP/poc/res/kid/kid16_v.atl create mode 100644 applications/PoP/poc/res/kid/kid17_v.atl create mode 100644 applications/PoP/poc/res/kid/kid18_v.atl create mode 100644 applications/PoP/poc/res/kid/kid19_v.atl create mode 100644 applications/PoP/poc/res/kid/kid1_v.atl create mode 100644 applications/PoP/poc/res/kid/kid20_v.atl create mode 100644 applications/PoP/poc/res/kid/kid21_v.atl create mode 100644 applications/PoP/poc/res/kid/kid22_v.atl create mode 100644 applications/PoP/poc/res/kid/kid23_v.atl create mode 100644 applications/PoP/poc/res/kid/kid24_v.atl create mode 100644 applications/PoP/poc/res/kid/kid25_v.atl create mode 100644 applications/PoP/poc/res/kid/kid26_v.atl create mode 100644 applications/PoP/poc/res/kid/kid27_v.atl create mode 100644 applications/PoP/poc/res/kid/kid2_v.atl create mode 100644 applications/PoP/poc/res/kid/kid3_v.atl create mode 100644 applications/PoP/poc/res/kid/kid4_v.atl create mode 100644 applications/PoP/poc/res/kid/kid5_v.atl create mode 100644 applications/PoP/poc/res/kid/kid6_v.atl create mode 100644 applications/PoP/poc/res/kid/kid7_v.atl create mode 100644 applications/PoP/poc/res/kid/kid8_v.atl create mode 100644 applications/PoP/poc/res/kid/kid9_v.atl create mode 100644 applications/PoP/poc/res/kid/sword_v.atl diff --git a/applications/PoP/poc/res/guard/g0_v.atl b/applications/PoP/poc/res/guard/g0_v.atl new file mode 100644 index 0000000000000000000000000000000000000000..f2e09a14b532a0afdbb158b604a3af5c04b447ef GIT binary patch literal 9711 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 literal 0 HcmV?d00001 diff --git a/applications/PoP/poc/res/guard/g3_v.atl b/applications/PoP/poc/res/guard/g3_v.atl new file mode 100644 index 0000000000000000000000000000000000000000..0cc147a78a6932d836f2b51e20fe51b624c97d7d GIT binary patch literal 5232 zcmcgw%Z?j25FEi513@-GjNOYb2JD05TMj-4`GWvC=c6?8j6}&h`hk2%F8QHcn5uq| zO==_=&Vz^HbXRqg!!Aihe|$Oo_wD!L>D^{C41c`Xpbf*HFFw3x|I^El5A1*V z=HWg2-@bkImi=GfJ-%VTeE;~wp6zLPH{`DEcAaC*{J%-_yf%y0H_uylT%8^`M%tk{ zz3;bZ^xfm6JbfZ(cPbeyQf(M1rFmA4l9(H<1mp}#N|SL;S#f<9mT(d|%jtBAl$t7V za?dfAQkZAit#G#K^Jk;TSQuW$8pqLx1Y9{>Af(9|1U4aQf_QU0Q!r<=Y8k6K^sV8@cpYOiY=-<{czv-!I^I{B$1ue<#WBvl zfsS7jl&|N*N{wSPLNr*;XvcR}I@;lVyFH)RF~r=0LQ3k&8)GU2Bw|E-Cd(2b+eeZG zYH!18$__eUG!BO_-H~;$!$BeFcojlefRauBU||(X9rO&!elHV@(Bb_23}~+qMJyRX zJ{*7m+b4jk?gGhj;9;VVQ4Up1qVQ3&z5%YHG##13n$n+awotI@iLx+*{+Z=Taz0|(ja7|&Jo>EYZ1+X;%i8`HH_*fI z{>zlUTf)ezuT#eT5DHoa#YyGlJkRqd3eOU6QnDOC(jUe z2=91G!)@s{&$h)5=Tk_huYMQ81gA-U(H8K!%b=X1ezC$A%j{a7e4;#@hsl$-EPlDH zl*p6CAdi>6)1f251VJ7o%D~`-yPO3`n)(1y4NZUy(kdaoy&B%$)r?n{D;Q(ty;X`V zY~);s#HyeiF*wbr4`ZO_{w6gj(x??5FDRypTEq)V6-3Ey_iVqZ2Q3IiZsFsIYl4?I z%77FcDZ<2;*!7y9&4P&ni1GAh&r(<#E&(Z0d>Tn8WEh3cPI0D|h z$^d*c-o_A02Zr!*v8_ul3BZ z=6By6nBU;kwtvL`d|J;fO9j+3R=v=!l+MXTu_6`sqVlTK-m5>i=GCt+nw)VMl~brF z4c_|q$9`AzIm(|bOp*3_Rb6(NSvk&dyA&yims1uh$!JiRd`0ml)0O@mWK=A!q`)eJ i?FTVe9Bw>83kR!zJA>8j9`=$F?&x#(N)bWtn12H$ri;V? literal 0 HcmV?d00001 diff --git a/applications/PoP/poc/res/guard/g4_v.atl b/applications/PoP/poc/res/guard/g4_v.atl new file mode 100644 index 0000000000000000000000000000000000000000..a3850147eeb0aee25be2cad324b047b9a39fd289 GIT binary patch literal 1131 zcmcJOL2kn!5JgFr+2#OQXW1k429vJZ^&An z|B$(lXj^Iq9X?IZDCgW=wz@z%vOopr2nk%nrkc!%69VWWLO=~MDb;HV z1(A$xLa3Z29VbKzYm9nFTyj^u@Hz@>1*jhGe0d)lWydM;|KLE(yyW0hKwBVFZ%ri0bE@m7ZO_=^ zhTz3?yZdwXPn{~a=ht6;{_*AT-(PvZyrDJ{@a(2?^%BR-RpNO z|9-IY&+p%;{ih$^s^kn`4IhX3^Iqq9K5bh(;mV$I9Df@>m4<1$@|vb`Je^d<4SA4b zAq^8Sj^*Y$jc0+Ui;YtIXrkPYXP}=>jVv7)lIS>b8hm5|3Gj50(KanFj3qdZ*XvA< z7tu=yaJ?6G`F2YbKjfXJU@If-;ZM*7jM7J-g=ZhNL@xUE>jUE_L4ntt(hqO_xF=u_v8jd4A#h4dqp$t+^(9^(=n8n(u9BJIdTXT5hhKbp-g&G$tH~wHC5slGd5ugv>X!CLdEsYO|Xkoyj*&7 zVKOm53o9hNDsF zlP(wH6X-ZNvM9Ihxsk@TCwt+>CWpJFao@K z8ML4VV7?o32)mfnHn-owusio?ZayC8Uy-zc=s&r-djQT$!|H$mY{F?+3rn|T7>fpD+OgjEO8r@z&D4^<+ z?h=F}DuFfq)gzxH=rR$U{ZmLG);>cE#c09pxedtR$Gso-1o~VUS1m9=ahCP+t_&T$ z*DHehF>00(V|7A6jIBpBV=X0dMt1chLYig_xeFCbZUB3VZ&zZ9oLJ>`0a@}QWqWHD zSCB9)^+*`vfWD7$1m(<)q538Sf8VfihoC+b*9S3-up9nwo_XHgSjDrO)*9G0S-87d z0)HBr0X$I85z@TrMg3=&9=PuB3&}mf7PyO(L_|=49#P9oK{@kkQnef2w?D1gYW;DM z@Ka*GC4EHUrm1t14wfb=nbrM^ExoE-YsG6Za+G)E&OiX z!?=h8S%U^~?OHSL2&NhCgKxiN?to|ZX9VIX7fE5qY9xi7lZbN||6Y!n3#S~@{AOY; z%CXme<`{7y=>(g|BgaSxseA{$C31|8ncj-hz-;jIh%}hZBx4p>Yvvegl|A;+U!P!r z<}ORB7I0z6Xkdk_@2(E)&81=1D!4FLL0f{(FZMlGJF^aJGzdfXn?1D_V{$-UwKwX4 z#Yrc+Y9+DSx~e;2c*Y((Ki5|j z2`^$h`8>8~&N#`J&!0YAcmKZp?rxs0uDb5~t60B#eJlO8bWdGqETeG4FwgTagwXekas7$+gd-J8-&;#+0H?n1e>{hgV19<1I%q%> zbDYTa&(GsHg=}u-O`@bw<{7j0{fXQ-W^-sMAs7twFbHhPWs=i`0EPwgPBO1-SuNA1 z+{D^{3KqgNg)pG-S}XvzVgYDPtsPlCsk=hfH`%`=c5CCydoFg^2fa5S#4*OUVT`cY zad6r!J)Ao9fQy~O)X&jHa3qH0*i9kcPfuaf0<#l4ALD)=a_m$K+0U5-mSU$d_OTO? z+uyQt{VE+-I&LvnYDcwr;&xgxm_z9ubQb6-U!wR z@{lxxJoX8nx#)4xg5-Od$aa8e0G(!Pjykl010v=7G)9Wh42OR-Ew zhb%@hgv)%V6S7-)0>rY+ce!uI4U6^R0xeifN(;+g;;`TRlupoY3|%~fb0QZJCaUQU zj%S>VuP=0u9o68fGdR)oV+!3iM~qxNsyVO4E?HtDVkzC3pB6j6O2bmw7|j zw-!2vI4WWJ&dc6qOQ~}hPu7+9XK9PQE$Z$iHDg+^>1Dgt3F3E3J8OZ@oSV@TD3VSK zyPA=7$NN~cP`w;Qjjz!+h1zIgES}D z>LuCS$1qmN?NC?NcPGv4|BOM^d7-&=yg<`=)JCh;bd52iaW84wo{RSNC`iFhpEJ;w zfH}CS1$+JAG%eqRg{-WD(AcYKNBeRr4NxGKz2 zGX!;8TD&X<4Y$a+4Wp$7YmFE^h($ literal 0 HcmV?d00001 diff --git a/applications/PoP/poc/res/kid/kid11_v.atl b/applications/PoP/poc/res/kid/kid11_v.atl new file mode 100644 index 0000000000000000000000000000000000000000..5622703fe66ca25de3aeb9f843206d598f5f70ac GIT binary patch literal 5915 zcmcgwOODhq6wC-AMj8niV8j7HvmKbl?70CFCmBS?v+2%-xC95_JS>~4diL`tPSU*q zFZ``n&#~*-Nxpsk^7(T3_vzr7~Va*`M~ne^S8Gwe_y`7WBKdq`kv+cS1%t} zzItQji<_%YY%^UCABW@rNaJo?a}%Zj#5jI`%&2Laa^r~BGzDVDM+d3XL26ACF+0b^ z&In>_48ZINc|7jfA0ePmEig<0<4nT9#8Xfs5Oe%tkmDXi4)6*fft+MH0&_TMs3Zeq zlv}zcX1^x}T?s`*2@wW^vJyy$3L;+z`39+tH!SEs9O%+gzHM#yp!jwVl#F9Rt@Nd{rq z_B#OOw}LH16oPqG9>UX8$gz?yj}A12i;iL&uiTQ5k8BYmu_GQ*$jO~$)voY<07`v@ z(|YZyuyE107;qGkVX!&o^>FuZRE-Vco>WiQHbUBK11oPaZ2LK*C3P4#y@3~NW~*z= zkjCtSm_hO8V2Ow24k>eYusk)H_?m%(wKV9VBV1se!+Ao57K$q9B_5K;r0cv(4m)kF zrs8nk{{^E}(`Z}r?Ipgy2!TnvXg= z<#{+EERn4#^Lc2^=3K&MxM4HH(@luFn@PV46VWqsw5b(&F|A_yZm??6HNc#VeCJ9{ zK4wqg9Vv3EFtbA{PX)|ml2O1Vpv1^zG9Sf^D#cnu1^^ZoK7)nDhlw$Jo?LjxRwc&8 z7R<*Hcls*uj;)FeikJH>JjNBTC*T}HgR>&=P=8E>^S0PxKh!b>T)mKQx?&GzjoQF2k84_L{rE zcM&G{fC{99yteXfqBD%PMs`)$w{D^?Ib*%?Bn74`uUJ4aNc9srnlj<7$%-cUCVMx%19+Gu(drQ z6%a9}jQFt;UK*R1jpUmDi7g&~VwgZLCpeXLp0qG;M|>d|?p}A-WrM##cwqnX+OwLpSh3~++<+KEtpKo?|=>NRi-J}2b z{)+o=A1)uDf8T8$(W7mL+hIPl9eVjw4SATj`FWst=s3@N|9)mvcsLrM<2XK*tawb_6FoNOe>`&ZiZ_~46M(`qssA{XaYUR&1j5Fr{b(Zkd2`SfD{o9 zGWLLhs4)sSjvJ){p&|e)##q-FgpJ%>L%}3%8qsA`F|^L)dRpFmTiSgK$kh<(2d26{E=_Y9tMfRCj#yT{mtJb`Wb{wmbDx1PdPH& zU2K(Q0E#fq#^p;85|J5KcB;4Ri?puMq0b&`na+2!7PW#yq_cenOffiF)vSo}Svyn)8s zQvGT1!=?yQiQ#itD@4VT@(V(9lS~a*k(#908C?0bW|sW&Z(GPl z1yo4s=Zqt!aM9Z|Vhb`Bn$}=6hKoi#x1?Gp&`4OM zP3^QVT0=UeiJv8L&Xg?N??udLy!wb6uu6(Hsgxp9jkiU|UReO{JUX=mvTN&Rc+9Gx zz3%#`_@fTVMud|H8PL9<)FdInCTfw28fw&@or0Lr-z+mSri)0~@?=bsY8@6;mN}7E vPt0Ufu^Q9#hT)$W8)-speMTaNQ!Eibl(e;~Oe~C9@_54UD=;}(6N7&N?*?h| literal 0 HcmV?d00001 diff --git a/applications/PoP/poc/res/kid/kid13_v.atl b/applications/PoP/poc/res/kid/kid13_v.atl new file mode 100644 index 0000000000000000000000000000000000000000..1f9e0a7d8973fab4dd038e2211e391ef1d519664 GIT binary patch literal 9521 zcmchbO|H~95P*YN3=%>b7EeMgB+kG?g7w^BBu?@WonD}HR)|x~4Q4y%^VFa1D!a;w zksynX>*uSo9lPT6=fD4Y|6=*|*T2iFPtTq$%eUvRKjQu2j|aN{c=_f7%Afzd(Ea%IOguyBGv2V<6t>Q)L5UVX6$9G8Od{E*RooaLK%M% zQfk(h$&fsx0Z7!8$LJ;5cMMi?u$VcQU67D#qtzcl+<|Uo;nEr-``)f%92Zjln6kD{ z1=QV#Xr=(9yZM1Z$@5e+%X9XBkM_CU~!rh`br|0A76y;b$Rml~4xCX*pOQ?Jp z?@XCc2k#f9IH_lWn!Lwk6F8AbrKlZu7``q9ftych#_X4K0OB>psT`6qQ>y6e9^#&H z)-qAu&J>Us2ZD^$73GWc?9J&g>Q2N@qnAgW}b zhU3+#+Je(L1PYxga53t(;uvEn;1t&LK0Wrk zhowadMVAI@g!k^I&UyQt0@$uA$sv@rZ<2poh7)_kv!C4>LfuQES%&lK{H0kc|w>O0DLFw+2t43 zvfOjt*;(rEYAUJxm3q^=qK4fC0^eNzd~ecLq{NO+SQ4cyR8=m6!&1)BA=m3f`GZpu zTw(dEBhW1d{4A6%~4ThBMF1a=(Ls*N{zmDADK-y_5q^ zu@VoP=zpGw>tZl{ag|F*;Kf~>I~2kncGq$yj6ZPo4%@F%8V6Hi3S+LMarm~<5ph^a zdDQ&7uA}o{8=slM*KpFYYdbs*`U&zQaVM%q<(BJYl$J0iUocP2cd^=1Nv%4RN}1b3 zm&QvG=R|@3*(!k_v9 z;7WSrrR~!M6s?0{>hRFcb+J*$V)>&pc2O2A3#F1O{h)~mmbr;>2!Y5Tur={HZr`WQ ca}eTw{yZlMc{n!vP?`qhy)X=Fji(3kKRgU3aR2}S literal 0 HcmV?d00001 diff --git a/applications/PoP/poc/res/kid/kid14_v.atl b/applications/PoP/poc/res/kid/kid14_v.atl new file mode 100644 index 0000000000000000000000000000000000000000..e5c7157b5030e3e41b91bac810e9ac5b5c04a461 GIT binary patch literal 5823 zcmcJTOK#La5QZIzMIGQ~CSdN8bP1 z?+?6w{&2VFmB+DpXok6?ZRa#DUq{x7;nk3??>l!D1D)tR3@4L(v=YA8j!`- z;wT}qXk!=<#T8;eq@&S#j3}lc)jE+7SV4}><7{1TD7P&oiE^6pFN$A`*b- z6B^w2V6^A3S)ev~WUY>J)1jAC*G%X-so_+H%zs^~&Qd}pVcj6QG$yqD(JQl55$aBu zbb=5@k%jZ7YQ9_-EKs#t&+`0A&ENm$yL?MMS4m$lY(w>IKsGtE?hR&=H)HLlOIUz> zeJ=IfR?|HNK+<%aF?gG^XtXg~xfBq}?|hb-2zfze22Y`k1(A$!#M+8ZEC}3Z(qyFX zxuSI6%8G=kJ_Zs3Z}L|VE5&>so79aFqPCT~6kWMo^rp0v+n6Bq5l3J$067@ZN2UPC zIFam>z@d4Xee;DU*N0n@)IKTKtZlTlW=8buNl#3vHCFU%&Owjzz&Y-G<*HC87z`n- zAXs5~b6R4Ob2s$gY^&%4yygR7_7i0CSeF zR#rN}bj`>E=7E83Av;ha>CPrH%$HKoBWfDTUW>6gC}Mf%is=g9N@ln4ojGM=LAI8w zthH5!$YPp`6*T(e7l-pg}VMM{vVW^Ub_-zTu5?*#G4qRuPw zlFo@p5bM^X;QKSEtNf~)fg+;Io&as4yf0&@>$A>BB~HOK`Xaw)We5F!WMv*6J{_sz$&PwEl|A!$ft!XoJo=?osq?32M=6?FdXJ&fj z;S(oiF3JBBn7FR&CF5byzUoz*9>)ZnEq&ie&STmN!!+B^(Cvn%syY Ik$C|A0%}{UZvX%Q literal 0 HcmV?d00001 diff --git a/applications/PoP/poc/res/kid/kid15_v.atl b/applications/PoP/poc/res/kid/kid15_v.atl new file mode 100644 index 0000000000000000000000000000000000000000..fa2529bba0f4a610b0fdefe8a621194af6890854 GIT binary patch literal 5387 zcmcIn%Z}7Y5HtuOBqR=qhEYo(Atbcd{RIACrR6KQ&1%LzdFqGu3--*3pE41VkE*iW z?g44*;Ibn!v&xx~D1^KR>&<;r#9SyEEtSFV62d z|M&9zf%A`7=Z~EKczycBnd3CP8J6qgepzmNt8pCv8Sie#76mpE({REd$BY>Z=DS-4 zbO2K+gklllQz-?IFy5C*S7Hoq4~`Wg%R(y*ql%zK$O>}uv=n6ZEM?^obsL`|OFbF^xJ)cnEG){f;C79oWOIXh z09F^bVeBaC+n@nj*~7S^e#aPodo$cTwxXLb71%3wmb;qyohoz}O;%~*){qtB-FTn4 z7uTk8pUv9i>eqFA7QgDDuE1nW+48^zgf`NSC@mLFC2)tcv>OeCfjgLYb9Fq-l8FTf zG-SkI2xqf%U+QXZ8*n8UhRT^|;CMF=WnqL9PQq}B%5NhbGzwYSJyx-scfNN<62CZ{AfpAJAl1qs#`qmfmFxk{$YfJ&j)BI=%9%o5>Vv`)7?@@eHCU^hYy>fgSx|HDKYq8?bAF^x6D#OOy#1TZSBl zENun5QfHGQSH5|tFiPJ|09sJWzK31jwVpPc1+p0|%9f{r_M#YTp6L#Q2qo*d%n#SP z0=!o>d{*-{-jB$Ymp`6{PglC@N_RY>KV)*)A;=x;c+exv?s1nWhW{ztPnfMzunLAJ zRr1KHxrP7iVq&fAyk?cLQ9N4ySe$AiE7NQ`=*;X)T+_t72 FKLHK?y}ked literal 0 HcmV?d00001 diff --git a/applications/PoP/poc/res/kid/kid16_v.atl b/applications/PoP/poc/res/kid/kid16_v.atl new file mode 100644 index 0000000000000000000000000000000000000000..06cbd36cddd9194b8900991c590950feb8a943e4 GIT binary patch literal 3000 zcmchYTTUA>6ov;iQ41te5PJY#yM*qbQlGkvbjbKA@rKw$7twcEiTnTO;yE#fM3tze z*c1En@wwVRzJL4rW%&5^G;HoJE{0+A>H41I@5Rl6))=V?b#k-`ejU{eNi zNCDdJMVN1uW31z0Ig=r^k4ssWIHOP&sB|cTWFW~jctxpM%2WuH=^D-z`*RjULf28= z&k9sY^fNqwrZRg_vq87S$?M_%j2t^BF&J}ZMjOp(lJitcC_v8y%(cg4G`!{p#l?k& z^WIx?k2Vq7GyuftW! z&9IPwji8x3Igg_#kn)jm&S9~P$U(CH3x<-@O|Hy5~o6gFtQuL;XFrjH@*QOLu-L5i?6ck*&IPJuFaBxBv z)!K+PRL}Rr=i;a(=@%8nLJ^V-w>7(E&09X(9l?Z+U8Jnfy3qQ2Pt3ZlcB8#PS69PK zvAA*}UtAOc_Fve1aPabo? zg5jWXHB$tO5fg#zKyt6%qJ`Yau)>M@v{!HTKUV(`ej3}C7G}*#0pCmjcZK?JMu zBeW=^7&ABWj8-OeTi1TG3pc{Ht>TLBhkgI-#(`vRU0K1G>$?82elboAB@S*`1rXRu zj6*6E&FKvQypuj!AA}OjDEi18fNgsK_vJG%9a0}B=fJRBfq^2%F?EUtQ7k5y+X(>! zw`Gd1r4R>i6uq98H_Q8ZJ)D~(G2?bFIBMa%JU(8|A%u0gjPlw|TsXpM47~nul{`4b zY^2XPF?Q~C5}S1TH0*k4|MAgcyMh}?-7_CppDKET;*y^morh16rF1gn6f#$5#hQs1 zoXAcm1Mh{vjDqVVa_@QQOK*cJ8sB%mvY{4?(~7v-lEj%`B_AkQLHH30M@C-?qg@cx z69qmc$G6Wv3#5S?-OdPncCr}xv3Jirqf}$rb)WL0%h>919Q7OClKQ6pP%()yvYd_w zEB-i%O*(xNcJ&xKS2ZSW=+7u=X&&q_LfmL>cizFu>vI721KxX3XPI{-rUPXWf}5Uq z&|>R&xU_cm=N-))#TxU@e!;8AF53Ig^A0pLvEa@stuwB+WJL7Ue z=Hynj?sZdt%GuWcjI*36!`^aPcC9DTc@CanuC+<*+Kj1GdK*ej^R8f1vjB3xX$F-= zYxOLUd8*O7BhLc+p7tmb(t+|>pv)DaaJ>nA>vC@g7B}VAg4)s^MIjFpPt`1-=MWv7 zYG`6#!JUj9L+U*WO$N35DTIkX$gFe-soZ&d^>s#R_shFwhMU^(;51N2(0tP42RnAq z2ASw|^!k|emO)*L+dgN8E{kTnw%8uY2r)PaKY^h7x(IXIU_(_CZ58b~0C28naQAY(x<5ix?nwYv>{N?0~Gl z)iFK;DqD8zpW%2Q$;DIHY29e94DIlT0iw zwTqAk-9fo~KJ~k;l5!WTsUB7yh&M`Z^lELbiXpEAMf~te9Ay<}^96*?skt-^8m(dk=G}bn!|ip6JpiS0rTD zDdmfyveE+&%4CYSECyCgg3Ef6Z*d<1hp>_K)RrAY!ucg}(4ACD-sR=5I%Rf+r;a1O z&{VBFQW77pD1p_|+xd1>`PZW=q*8pjd1r>gL X$=of72>oxA3RDt(VipmP9%23k)HUbJ literal 0 HcmV?d00001 diff --git a/applications/PoP/poc/res/kid/kid18_v.atl b/applications/PoP/poc/res/kid/kid18_v.atl new file mode 100644 index 0000000000000000000000000000000000000000..b33360798048cf4373d67a4440d9cbe6b6bad17b GIT binary patch literal 5529 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 literal 0 HcmV?d00001 diff --git a/applications/PoP/poc/res/kid/kid20_v.atl b/applications/PoP/poc/res/kid/kid20_v.atl new file mode 100644 index 0000000000000000000000000000000000000000..5f9c5f203d8ce3827a8f295d5507d0955b98859e GIT binary patch literal 6326 zcmcJTU5?~56oqSqgg`<<>gnFX%ri@12S}`>TAkEWbvA@};{_pBz*5*lIOqP@_ue>3 z4boVxaw`6O?D(GRxcb*$e*WpZ%hxZzU7kOG_;9)W^^Mm5eEU(p|MC5c)c^kQB=zq< zYWv?$&!5Qu`Jy#v_ZbR6q6%;Wc zH)skS2xrh1fKMy7nMwJCrRJT#*|HDG?jR^-U;-6i)!9 zO+4k<@BwaJAIOL167M*!zZ5$*dQ&^Zuy{5ZSaX$S8!btrg3-A$WodRWmF*85v6K%2 zE{l;J(;EXbp`ky4bwedlGcl`1n59GniEWI&bttf8bR9AZ$+b8WtQx(fYNri@h4~11 zG~93yQ*)z-yJ*EXD@1{*&tpE6Kq=mhu6x%IA}U6=eAtC-3Lj734>hjVu~r>BajS}WA{9SWwqk2U+Vu@y$`9vu@>)=c0joye z*sjt4ABKEDAc7-pdPNQS@9Uq~eT;ZRE0*&?Q8+zg zoXN-}j28aZ6)yI}hWj$|^NjaC$oX}CYaBJRhvymN6Pq(u#zyl34+|C4;(&Y(0yr|E zg75eQD0w_m#sQ-{1=8D_Psq828Tr!Ao_dRzB!ur>jch^SL}cA$yt9LlKx;n;?Vp5< zgM2TBkph_JWc2j99+F57@kY8=wKdtyDBuq5aP^W&0@}m@l+kKpd>P;CPr@#u8=(g zJG|K@j7RQs5+#0MRF>P~4hGg5;VJ8)6gV`q#NSiFc#bI~4n8^ID9MBfGTyz^rziek zrqVTi4cLK!-7M_-D0aX_Ycd~D(xmK5!qmboc)Mu@+F zKOO%^D2Z;>Tr{iha9!)bsjoiFLr1E6w=PShaw5d_(?l5Of$woQ{K|VI z4Y)m@XMwnTlLWy^ddbL_90>kycuj#3gM&@T6Mw2EAs29-?DV$MV;N4}7q9r=MR=Nt zRI@(Y*3&ul=~tsm^=_?;rU!JVKm9xsFc6$sVNu@- z)fdf{K5BNq#`m$uNNOHWl3&Lmx7|4Sb%$d#l3&L@D}F^dYvEQL{W^S?&}GrDSk-FZRzoO}HrsJ{nY literal 0 HcmV?d00001 diff --git a/applications/PoP/poc/res/kid/kid21_v.atl b/applications/PoP/poc/res/kid/kid21_v.atl new file mode 100644 index 0000000000000000000000000000000000000000..deb1f2372318f986d1c500e94676b0e6524bc4cd GIT binary patch literal 7409 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 literal 0 HcmV?d00001 diff --git a/applications/PoP/poc/res/kid/kid23_v.atl b/applications/PoP/poc/res/kid/kid23_v.atl new file mode 100644 index 0000000000000000000000000000000000000000..f9326aa6be12260a3057f53233b113d1e392b1d2 GIT binary patch literal 9764 zcmdU#&yE~55XL(a2RLwo1BVeJn`BqYjXM`^9FcgEpzP$d>X+e|2gxJwHs-6pu5#Ja z4GM^DDeLO0pFdZ-?HbR(Z@>Qh;4!fMKZPb?

6UQm+<@S24BNM4-27@2BNI;|*1Iq& z!i_?i!C;Zu1;X-VL$@p?1d9IA6&aAjeigxN^Xpw@!nZD`pf5l z@Cna|2?>UT`3zv6?-PWTtktXJVpCvyp;xASB@spP4K(3j`lA;kKG69!Cg&I^I^vpP+RV@ti4V56`(yc^z8K z0Q{egIU$4zrv*UQG9y_42`Y>69MeRk4_0(234=7DDdU(xD@L>uQ;$PDUSO~phuW$+ zWoE3c4j~ynpp{b)_1D3)m`!V|GN>F3e;Cd`k_CsTx~LJqI|<3~T(hpQhNk()tJCX*7%~{!02BQf=OgWMoq{u%!lJ-~9^=wM5?U8O-Oxo@@ z3$wE)#sbu86$i6Ks6aEBkw)G9qF2BrcqK!Af^a3IxrDmcOz2lsR3;!aT)I6`6v0zE zL$`W+#Gr8Es{Nwp3_~a2BOPcSF>klK)pzhRM=?dV|1U%v-)70QzVL#ChgrOy&rQsS ziK7rft8P!(h80e0fPqXgAq8|v&|#5JowSO&h7Wapq}|=moE@=b9`REj1NC=yMX0zA zKe-{oNO|RCPCx(3lHmoZuB@;xd{@9 z4^xpqK)50~&PY!HR*3H!NFp(AK&*l(-hsYtR=||d3_KArTq1{YXVc0=iIPK!HE@ow z{WKkeow{At0N33cVT4FyzPG*KA#vGW&Fiwwl}lA)KxV0=#j*GSAj?djXoARF?n#YE z|N6fhl#`*UsY@lvBxE52aaZyBiIE5o-^dF?XB8}_@e8?d=!=VvJcRVx$ZnM)o6TG2 zN@2@?&Gf#iwPTFKQzfd-_+8w(hck z(5NDWzfEHB&#SC|dhx&vQ@8_i2BJVrEfc(DGXOYh$gWNjQBLf`UESJcdo$nHqLA{g z0~oZ51bP|MGS)_Q9j5uQ|-S1oe+FW literal 0 HcmV?d00001 diff --git a/applications/PoP/poc/res/kid/kid24_v.atl b/applications/PoP/poc/res/kid/kid24_v.atl new file mode 100644 index 0000000000000000000000000000000000000000..19c80a426b65c616f1382a549e7ca5d181185fbc GIT binary patch literal 5932 zcmcIoONu2o5Uep61`G{`*U-cCVivP#hF;i5@C^*UhBs~MvwG-4K7^0ro0KCWGo@60 zUOxt$%v4E{ktwMvQl)->{QldoABX?n{vMt$A3hAjzdw9_;{DGbKRxsQ`tj)t@4x)? z_?7pUhsPJ*$Dc3Xc>m|}@X9;wdAJPgv6TXx|C<%qx|D^;+uNHQ#Axh{0Ex0c&qUUB za&T$b{MSqn&ShC=BTl$S$`znO=V@w~F(;UhObVjrdF*J8E=!_0mGffLY=O;$N+6gI zOpw4U9D=3^;5?If1!x>#7~HU{2Z89=>PRWVkPm?gBdx~@o&g9LA+n(-TEjFsqpg|> zW~8ivu}?#&nRRtdD{JVEMHj(F@m4^eho>{m>|%C6B&qr_h7DNI2@N&e<`O!pI5Yx& z(~=xmVrVDp$(07m)N6`Cc*MYaT`3tHdu@3H(o7=7g*suX&6AUSz~KUmxD=473IT@8 zk%YAnW-bOKHB5YifqN*BV(Jt>i;T(>9eFw&4rHPJs3B%>b69v1p=SYH#pyHGdWlyt z#*&bcaIzSrBuq_rY~j`L9c&{Q{0TeQ0pT4eZ7MrvufK5HVtNg_kF(tAF!>5J*K5(7 zjGN~JJ;IImyuf#$Njj;s-Ja(o;x_Z0x2_^6HJQ!UJElX7)qI6blcMj0@-fVwL6a!} z4I`K0)@$88&1tS9ABvaLq{Jc3Yivylps2!^)bBoeEUx*GjAkAV7ken0RjDk^!am}7 zlM!=MpUbNj9t*3mHNv@pv-8lU`Gn_b`0^e4jp*~c&G=O3oI8S#wGM}^t$w?AI>7w_X_3exbg_9M-y{+)181Kfg}Ne`{-du|1MjqLNCbE5{-GVJ^Ype~iddPVIk zbYB&WMFXVUWQq>_PB+;6RBNFZ|B{<=EBbW%>7w(Rr@1NTjVY8>#PrS2jxjB_%R1ue zb^=HCXh69nB13X3EM05}PoD7F6ruLk$KmUF4YXObfKBVhR4UWvRJ(_bdpN6(a|j>p z^m~|yr-^mqA@{^B*uKFi!J8z$sgoLtI3&UsCg<5d5l-9k=w;ecyH`X==V;7_oS>97 zJ|>R%@jFywC}zp&u)`S_cCJl%l_XhZ?QS{dV-A|->4%CjoFNLbL=kXg8!l4CGJ`_~ z%t>USDF_$kiB2PtT+zNB5~(r{8a`a|JPt4Cx_4e4Hid4RO1=dT`r3vL@GW#NZ>?vC zZH7&MDjVRWdnb=)Z~VJiIvhbY_Ff?d4pbo|w^c?or_z5!wxd&u7624fvo-llFad$73%7>O(}t86jNad1USFs-)9%oK_! z8UMSq@e2&cx4LbGAqF#KE{G$E7&~XE+y+MJqBbHY=Gz3Xw93vOMPQhv zGsO$8W?+{>%yxtB4;H7cl`0}p?k~qCZgxEkulLu|-O{)9=5cbHPb>P+0DsV^ec7SQY@^A$4r(~6S>EhH zTkpXzg<-;>*)^yPtdypkGD?fmcPBBU>nARyM@VRlD|0ThCUd3^bf(A3O)PJU9559L KyCJn;#{ECF=p!8f literal 0 HcmV?d00001 diff --git a/applications/PoP/poc/res/kid/kid25_v.atl b/applications/PoP/poc/res/kid/kid25_v.atl new file mode 100644 index 0000000000000000000000000000000000000000..caece9ed90e029c12b420d841b9ec8993b34f108 GIT binary patch literal 6246 zcmcJTTaMf|5JhDK4h#hF*aHuc9T*);w6+ubMjU!K2~{_BhTcO3u!$D0rA zf4_Tp&;GxA?Y}*|ddo4}%jx5^|9sof>MZS8qT(c5Me|T%aarAx+2`}V)1f!=(6Qh5 zvoy}$_sf1Hl859xZ~Mx$mrIIt%=5e~i{8G&E=!&Q(%4I3F;^MH61<$3<#9i81-mW5 z?y_$%9F`vIMLz?+=yIL39zmp*E0&AD`Q&UvYG#s{v7b&Skg|r$5u`^+i2)R}4;t%1 zNAIRjBdzgSIDV}sXQCKmgbpp?stR!&FmnXWFnZZ!Q2eX5qrBJ`tB5drgkV@w@MG-R(Vt{yQVZ6dnI3K-E8qrXk4KyP6q?J zLyD`#De4h>SPI}VD0=7*NpAO2f`Z*o??(Id?KDa>52%{P*Hg7BS_TzkgAxs^hrt(d8dtTR z$?H1j7Z5Zizad*lRx74}G8J>{MsbVNLB-+PUkf(Sv|T30B3oKwAqq~c~7pt8_LWXzU|c~WiJ`D8O6 zruRQmU;0eSHP+D@1#zn-bnMZp@1Ye?1~tm}T4Ie=p&*-Z9%j_U$}rs-gH0Vc9i%&i zw||Hfbym^L(O#V`Spio1_bEUDaY?cOs}zr-FY8*F4Yc^U{6x`YSl3143=$)92hvz# z0CAqkX(kobf8X zCe@#G2)ZAAf%t6+bIO0diOLvHfP`g=H}$b#{Q0tTJ|~R7V^Lwmd}{QGQyre7@`Hg< gVfr9^gCG{4S2$eo)2g?2dmv9jTE=`r>KzN$cQGpZ6#xJL literal 0 HcmV?d00001 diff --git a/applications/PoP/poc/res/kid/kid26_v.atl b/applications/PoP/poc/res/kid/kid26_v.atl new file mode 100644 index 0000000000000000000000000000000000000000..82d69f1d183ce7e3cdf18c390a4dc4977f75b965 GIT binary patch literal 5390 zcmcJTOO6{i5Qf_bU>GpQ83phln1x|)yzweW2;c(*$w?GUw^kA_l#^wZ8_@q>FIG3% zk{rNXbQh~W79Uk?Qu^zU-+y~E{rK|F^!WMJt7&@t=~>?Yy?*|}`k!wfr2h5c-6z(c zem;EQ``5$!C%*sv<>P^GmdEMyRQJlV>{+sYxeEhzhc{Bh=30-rkCnVE1*L-gdwB_r zIus*IQ3@}Vpp*8<(z$^^xF;3QZKs_2rwqDr!I$)$w)d=7D6c)pfnXa<-2jl&`x zm#FRtBWg7dX(t`3FPi`umX%jhrV>gBd1Oo|%~!5QgCH5_I?Y!E(-rovslG5+$XAc$ z#-ov>n2AP7Kgmf)wE_1O(nIpqnGpe>>d|kCuiSpbf#QQTJpk;xlltRh6w`RQD;4Y)x01ct!dl z)bsRZ{|xcL+_N0YVwJtojW^?Q12Hqf5~%I@sAoZ3wk5xUTIa#aw-EW6y_xLebQ|(8 zz5yHDXXJh|>dnKe35iWxB|CPn@j-(zp(U|`>i5k3j#+7sndu>%T_isB0#r}p=2pAS z15u~#IKIxpVLFr7Lr8w4Rm84T(sm-Ty4~cU-c6tMOetLxQADuCLC0WWJM7kZQRb@y3Yh!-T7V? zXlqH5<}^vPbA(An@%{Al9T~7`+^VICF3q#_=vDjwK(viU9GD9XT%sj9St~Z%{WBv@ zg}kc898(i5o5JX^7AbElC=qB;K?&Ea$UlHAWjJdH=KNRm#Y}#Oz*G_g7F*}=Qn=U0Q>I?B= zj9Em%_{|y(y~apD8S#_t2T{z+?7`9Fcy=%FBSg3jh4!L72@(qQOofLPe=MN h*A%s0>~oGWVGW9GX=#E-wTHcm V?5j!MM|dKwt|tv(RSLdjA|F?VZCL;S literal 0 HcmV?d00001 diff --git a/applications/PoP/poc/res/kid/kid2_v.atl b/applications/PoP/poc/res/kid/kid2_v.atl new file mode 100644 index 0000000000000000000000000000000000000000..0969b6b52814ef2867211d7c3c8d79d8d31fa79f GIT binary patch literal 8145 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 bA1s(2SVOr0VWK|LbE5`p1`*Cq*rC4xZ*5U) literal 0 HcmV?d00001 diff --git a/applications/PoP/poc/res/kid/kid4_v.atl b/applications/PoP/poc/res/kid/kid4_v.atl new file mode 100644 index 0000000000000000000000000000000000000000..28ddd419c11be3b9b30a14dacd17c0d4f1249e98 GIT binary patch literal 9758 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 literal 0 HcmV?d00001 diff --git a/applications/PoP/poc/res/kid/kid7_v.atl b/applications/PoP/poc/res/kid/kid7_v.atl new file mode 100644 index 0000000000000000000000000000000000000000..afe4669ed5319154fbf8330500b58075c514ae68 GIT binary patch literal 4085 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 M_|bccs)5-40nfCo$^ZZW literal 0 HcmV?d00001 diff --git a/applications/PoP/poc/res/kid/kid9_v.atl b/applications/PoP/poc/res/kid/kid9_v.atl new file mode 100644 index 0000000000000000000000000000000000000000..606cab456868033a700235937432954fb06244db GIT binary patch literal 7885 zcmcIpOKu!T3~et0B!CeZSp)&3g>2adyznBqK~~uY$w?;AbYlW(`WQJwfZTEN9?7aA z>!$&1)k0lGz9L!tb@k}a-+%r2+vVlQf6M*dt5?hN=9{%jHYQ(_FyQ)6-?!#u)I=`#wXQ!3Sb2Vk3Ws zNPr?^U86WdWJ7BHB?AnyHV8Gs{%%_fa3aLqM#2^m>w1hvUc40$aXdDFi|N-#%a0lw z0g+7&!GfAy@lE&U&H;~~&nhEX#vo)tSRersi%*SF29WLf%FYrt@XzOrc4?$?v{& zidF+S8;nl!MdTF{WW!r@nYhzdP5O6G5ra%4GfO^~gYj5mWI!PiYcUN-FhY%gyr3KU0vTcGvZ&*WhkXm+O z#r80&U$IUgMD$yLo)K=DL)H!6eFlPb8J9ZsXnba-;4otJWmp))2cNgxU~2*tPtoQeDU$(GDTq{awv$C zS6nNpl#JTeRflb<+K6gxN`5S;MjidA>W3g{C+eQ$1w1LK*i9KECTAM3F^Tk~$l5Xl zMb{_3%FC-*<(VvdZB>`3kxjg;&~+Z7Brz$U1fZ3-5`Z#I&gN}o!$7T87>}38Jc~i+ zfjx6M$veTEs0w-_p|iRIa|Hzbrz1O(zK)nHy5%*^ur~O1`MBV|8ZGXwN?~-_MkIl#%Zsohnkk#d7-{LBkUoQh(1;ttLbI8j#LF94ClPSC?s-#d z%DC8b^b8DuUWeqI$UYh2fQ$fri=(MC5^Aqt+E7iOfTT%vQRdclwaMPz5E2LNqMU*4 zCp4GD!s&8DZ`+i5pVvuR!#(IgsFJz~Z4w!)Q-O8bSvU}llWQu41&&+L8E_x|{xwF4 z$7B;eT4$o1;L-GoPJ^vq5!HygSw8T-l0KeChLX-Cobe4KKeJ46sEex_MM~sxv5K0U zT2rM7HLK~InMk~;(kyJhPG=uxrC)?~bOK|YJi{84++EJ5BbQ?ZlV$|Bi@{k|@0@!0 z_&r$(vlddsuxV8{94IP$y|_u~n4MxrZHxf;XRrImC7%l|LC3x~T_&Me>88BXWPs9+ zoj~0l1KaS+3Iu9h0s9;$IRw3tLKnubZjUWywN;mL`>gn{++E={^RTFY(>;GEAi7`11E$C?8kSn9~*aZh6yb zE7FmjN+h9MF*(Ekgd|5D0Nat7g+Ot53uS^#-8$usemJC`aU>eD2T@OrTs-;s$hVaS z0)WTEArr`Fmg2uY91P D@eCPV literal 0 HcmV?d00001 diff --git a/applications/PoP/poc/res/kid/sword_v.atl b/applications/PoP/poc/res/kid/sword_v.atl new file mode 100644 index 0000000000000000000000000000000000000000..f4535476a99fc7007b5b073d78ae58f28d02f691 GIT binary patch literal 5168 zcmcgwy>b&V5SHyE=bs=u_Na4}hMGs9AuTf$R1ELIP|)DkHIG0+MF}&hsCfixhKeUR z_E)#7lg|k_D0f=zkG}m@(%pIT;`!4j*WuyY+fg$cjY7B`#WBhsqclNzJx*sR-;7g( z@@mqMd^SnvsDGZsOO&tA(u(x+nY$l?_?NlXc~Yk-#6RrF-f zkixmtqA)Be&~#>q0jy%r#EiQ%b~^0&Wi?qw!~r&f!TrtcFO?Kl2e}Hi zNrD!yS_(a95nHI`R0r(J!R0qzJk`RDgmWSZ=k4pg01I}4@iMHBt?6H9@wGwauGS+u zx^p}XoGxniBSjm}lnsE^;AW7qXG!5gR)k%ZzG5<1Lc0=FG08meFn{EnPWw!{qui}2 zWVVVOJIA2H6=4x}vF+Gpr)rOO+khVl*Dz1zM$&Y9_n=v(IQX{R>bK3?G5FpWq^Ao- z3RA5GfT)RlK((I1S60ztSSVNL#pUGI4Z4wd@}B1bZ%sK<^!tlgoC;(>H+001I|R<; zG)t1Xd5#7hH6UmP?nTG^vqLgr1T+>jk7wV{qy-3C!rx_t3MXp#4;H_vywRBnVsJBi zM26GqvBE$z{|8wV1FEc}mTGnM8h4@Yc01>8TeK84>~@7AhE4T3D#A{y7OaXwNaYY7 zVlM>t`(Bl3D(OMxeN$I{=@-YKPzH43H1e3S z=2v!rVcce@;P%a9+;&ej6x`jv8`Q{BW;)@vsJ3l)waFo2A;$~O7H1|={zMXTNJnlY aQ&;2h7n;BU0zzOL97s@JLZ#Zhef|JdTD)EW literal 0 HcmV?d00001 diff --git a/applications/PoP/roomtest/Makefile b/applications/PoP/roomtest/Makefile index 6934e28..71a17c0 100644 --- a/applications/PoP/roomtest/Makefile +++ b/applications/PoP/roomtest/Makefile @@ -42,6 +42,11 @@ EXTRA_FLAGS ?= --gfx 256 -I $(CURDIR)/../poc/res/bg --max-allocs $(ALLOCS) --ban # MAME = время фазы в растровых строках. PROF ?= 1 PROF_FLAGS := -DPROF_BORDER=$(PROF) +# Стартовый уровень (отладка): make LEVEL=9 — начать сразу с девятого. +# Дефолт держим на отлаживаемом сейчас уровне; для «настоящей» игры — LEVEL=1. +# Константа объявлена в pop_tune.h (её видят обе половины главного цикла). +LEVEL ?= 9 +PROF_FLAGS += -DFIRST_LEVEL=$(LEVEL) EXTRA_SRCS := pop_vflip.c pop_state.c pop_draw.c pop_tile.c pop_kid.c pop_level.c pop_geom.c pop_guard.c BG_DIR := $(CURDIR)/../poc/res/bg @@ -67,16 +72,26 @@ BG_DATA := $(foreach s,$(BG_SETS),\ # не рисуются (отрисовка пропускает незагруженную страницу). Палитра — # ЕДИНАЯ игровая (env+wall+kid). KID_PAGES := $(foreach n,0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27,$(KID_DIR)/kid$(n).atl) -KID_DATA := $(KID_PAGES) $(KID_DIR)/kid.pal $(KID_DIR)/sword.atl +# Зеркальный ПО ВЕРТИКАЛИ набор (зелье инверсии, уровень 9): те же спрайты с +# развёрнутыми колонками. Готовит упаковщик, а не рантайм — разворот +# страницы стоит 0.59 с против 0.045 с на её чтение с диска (замер MAME +# 2026-08-12, протокол в pop_vflip.c). +KID_VPAGES := $(foreach n,0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27,$(KID_DIR)/kid$(n)_v.atl) +KID_DATA := $(KID_PAGES) $(KID_VPAGES) $(KID_DIR)/kid.pal \ + $(KID_DIR)/sword.atl $(KID_DIR)/sword_v.atl # Таблицы анимации (кадры+seqtbl) — отдельный бинарь в EMM-странице, его # делает pop_extract_kid_data.py (не упаковщик спрайтов) — своё правило ниже. KID_BIN := $(KID_DIR)/kid_data.bin GUARD_DIR := $(CURDIR)/../poc/res/guard GUARD_DATA := $(GUARD_DIR)/g0.atl $(GUARD_DIR)/g1.atl $(GUARD_DIR)/g2.atl \ - $(GUARD_DIR)/g3.atl $(GUARD_DIR)/g4.atl + $(GUARD_DIR)/g3.atl $(GUARD_DIR)/g4.atl \ + $(GUARD_DIR)/g0_v.atl $(GUARD_DIR)/g1_v.atl $(GUARD_DIR)/g2_v.atl \ + $(GUARD_DIR)/g3_v.atl $(GUARD_DIR)/g4_v.atl # Скелет — ОТДЕЛЬНЫЙ набор спрайтов (SKEL.DAT в оригинале): его грузит # уровень 3 (tbl_guard_type == 2), кадров меньше (28 против 34). SKEL_DIR := $(CURDIR)/../poc/res/skel +# Зеркального набора у скелета НЕТ: зелье инверсии — уровень 9, там обычный +# страж (tbl_guard_type[9] = 0). См. pop_pack_guard.py. SKEL_DATA := $(SKEL_DIR)/g0.atl $(SKEL_DIR)/g1.atl $(SKEL_DIR)/g2.atl \ $(SKEL_DIR)/g3.atl diff --git a/applications/PoP/roomtest/pop_cdraw.c b/applications/PoP/roomtest/pop_cdraw.c index 7945bdc..14ef0ff 100644 --- a/applications/PoP/roomtest/pop_cdraw.c +++ b/applications/PoP/roomtest/pop_cdraw.c @@ -105,6 +105,31 @@ int pop_guard_load(void) __banked return 0; } +/* Зеркальный набор соперника — пара к pop_guard_load: те же страницы, но + * файлы *_v.atl (см. pop_vflip.h). Здесь, а не в загрузчике набора, + * потому что gp[] и выбор GUARD/SKEL живут именно тут. */ +int pop_guard_vflip_load(void) __banked +{ + static const char *const guard_v[GUARD_PAGES] = { + "GUARD\\g0_v.atl", "GUARD\\g1_v.atl", "GUARD\\g2_v.atl", + "GUARD\\g3_v.atl", "GUARD\\g4_v.atl" + }; + static const char *const skel_v[GUARD_PAGES] = { + "SKEL\\g0_v.atl", "SKEL\\g1_v.atl", "SKEL\\g2_v.atl", + "SKEL\\g3_v.atl", 0 + }; + const char *const *names; + int8_t type = pop_level_guard_type(pop_current_level); + uint8_t i; + if (type < 0 || !g_ok) return 0; /* соперников на уровне нет */ + names = (type == 2) ? skel_v : guard_v; + for (i = 0; i < GUARD_PAGES; i++) { + if (names[i] == 0) break; + if (pop_vflip_add(&gp[i], names[i]) != 0) return -1; + } + return 0; +} + void pop_guard_free(void) __banked { uint8_t i; diff --git a/applications/PoP/roomtest/pop_guard.h b/applications/PoP/roomtest/pop_guard.h index 0ac1d57..af9d118 100644 --- a/applications/PoP/roomtest/pop_guard.h +++ b/applications/PoP/roomtest/pop_guard.h @@ -236,6 +236,11 @@ uint8_t pop_guard_present(void); /* Атласы стража (GUARD\\g0..g4.atl) — грузить ДО initgraph, как Kid. * 0 — OK, -1 — ошибка (тогда страж просто не рисуется). */ int pop_guard_load(void) __banked; + +/* Зеркальный ПО ВЕРТИКАЛИ набор соперника (файлы *_v.atl) — для зелья + * инверсии; зовётся из pop_vflip_load_all (pop_vflip.h). Живёт рядом с + * pop_guard_load: там же gp[] и выбор GUARD/SKEL. */ +int pop_guard_vflip_load(void) __banked; void pop_guard_free(void) __banked; /* Вход в комнату: поднять стража из данных уровня (порт enter_guard, diff --git a/applications/PoP/roomtest/pop_kboot.c b/applications/PoP/roomtest/pop_kboot.c index df9cde2..e878cd7 100644 --- a/applications/PoP/roomtest/pop_kboot.c +++ b/applications/PoP/roomtest/pop_kboot.c @@ -14,6 +14,8 @@ #include "pop_kid.h" #include "_pop_kid.h" #include "kid_data.h" +#include "pop_vflip.h" +#include "pop_guard.h" /* pop_guard_vflip_load — зеркала соперника */ /* ISR-стаб W0-страницы (тот же приём, что atlas_load): при прерывании с * замапленной в W0 страницей CPU прыгает на 0x0038 → там обязан быть JP на @@ -56,3 +58,29 @@ void pop_kid_data_free(void) __banked { if (kdat_ok) { mem_free_block(kdat_blk); kdat_ok = 0; } } + +/* ---- Зеркальный набор (зелье инверсии, уровень 9) -------------------- * + * Грузится ОДНИМ вызовом и откуда угодно: со старта игры, из показа интро + * или при входе на уровень с зельем — см. pop_vflip.h. Внутри обычный + * atlas_load (он резидентный и сам мапит W3, банку это разрешено делать + * только через него). Идемпотентна. */ +int pop_vflip_load_all(void) __banked +{ + static const char *const kidv[KID_MAXPAGES] = { + "KID\\kid0_v.atl","KID\\kid1_v.atl","KID\\kid2_v.atl","KID\\kid3_v.atl", + "KID\\kid4_v.atl","KID\\kid5_v.atl","KID\\kid6_v.atl","KID\\kid7_v.atl", + "KID\\kid8_v.atl","KID\\kid9_v.atl","KID\\kid10_v.atl","KID\\kid11_v.atl", + "KID\\kid12_v.atl","KID\\kid13_v.atl","KID\\kid14_v.atl","KID\\kid15_v.atl", + "KID\\kid16_v.atl","KID\\kid17_v.atl","KID\\kid18_v.atl","KID\\kid19_v.atl", + "KID\\kid20_v.atl","KID\\kid21_v.atl","KID\\kid22_v.atl","KID\\kid23_v.atl", + "KID\\kid24_v.atl","KID\\kid25_v.atl","KID\\kid26_v.atl","KID\\kid27_v.atl" + }; + uint8_t i; + int res = 0; + if (pop_vflip_ready()) return 0; + for (i = 0; i < kid_npages; i++) + if (pop_vflip_add(&kidp[i], kidv[i]) != 0) res = -1; + if (pop_sword_vflip_load() != 0) res = -1; + if (pop_guard_vflip_load() != 0) res = -1; + return res; +} diff --git a/applications/PoP/roomtest/pop_kdraw.c b/applications/PoP/roomtest/pop_kdraw.c index f070810..d28a4ed 100644 --- a/applications/PoP/roomtest/pop_kdraw.c +++ b/applications/PoP/roomtest/pop_kdraw.c @@ -43,6 +43,13 @@ int pop_sword_load(void) __banked return 0; } +/* Зеркальная страница меча (зелье инверсии) — пара к pop_sword_load. */ +int pop_sword_vflip_load(void) __banked +{ + if (!sword_ok) return 0; + return pop_vflip_add(&swordp, "KID\\sword_v.atl"); +} + /* add_sword_to_objtable (seg006:1798). Клинок рисуется, если персонаж в * кадрах подъёма/ножен, ИЛИ держит меч, ИЛИ это ЖИВОЙ страж (у стража меч * в руке всегда, даже пока sword ещё sheathed). Страницу W0 оставляем diff --git a/applications/PoP/roomtest/pop_kid.h b/applications/PoP/roomtest/pop_kid.h index bbe1ef5..9ba6fba 100644 --- a/applications/PoP/roomtest/pop_kid.h +++ b/applications/PoP/roomtest/pop_kid.h @@ -48,6 +48,8 @@ void pop_kid_data_free(void) __banked; * Грузить ДО initgraph, как и страницы Kid. 0 — OK, -1 — ошибка (тогда * кадры рисуются без клинка). */ int pop_sword_load(void) __banked; +/* Зеркальная (вертикально) страница меча — для зелья инверсии. */ +int pop_sword_vflip_load(void) __banked; void pop_kid_free(void) __banked; /* Сама отрисовка клинка (pop_sword_draw) и блит спрайта chtab_2 по id diff --git a/applications/PoP/roomtest/pop_tune.h b/applications/PoP/roomtest/pop_tune.h index 3c1181c..f36b2bd 100644 --- a/applications/PoP/roomtest/pop_tune.h +++ b/applications/PoP/roomtest/pop_tune.h @@ -121,4 +121,9 @@ #define FIRST_LEVEL 1 #endif +/* Уровень с зельем инверсии (переворот экрана). По нему делается + * ПРЕДзагрузка зеркального набора спрайтов персонажей — чтобы пауза на + * чтение 34 страниц пришлась на загрузку уровня, а не на глоток зелья. */ +#define POP_UPSIDE_LEVEL 9 + #endif /* POP_TUNE_H */ diff --git a/applications/PoP/roomtest/pop_vflip.c b/applications/PoP/roomtest/pop_vflip.c index 4f97bf4..f4d0663 100644 --- a/applications/PoP/roomtest/pop_vflip.c +++ b/applications/PoP/roomtest/pop_vflip.c @@ -1,111 +1,55 @@ /* - * pop_vflip.c — ЗЕРКАЛЬНЫЕ ПО ВЕРТИКАЛИ копии страниц атласов персонажей + * pop_vflip.c — таблица «страница атласа -> её ВЕРТИКАЛЬНО ЗЕРКАЛЬНАЯ пара» * (зелье инверсии, уровень 9). См. pop_vflip.h. * - * Зачем отдельный набор страниц. Спрайты персонажей хранятся COLUMN-MAJOR - * (out[col*h + row], transpose_cols в pop_pack_kid.py) — ради БЕСПЛАТНОГО - * горизонтального флипа: accel копирует колонки, и порядок колонок задаётся - * знаком страйда. А вертикальное зеркало у такой раскладки — это разворот - * байтов ВНУТРИ колонки, чего accel не умеет: блок он копирует только - * вперёд. Значит перевёрнутые кадры надо готовить заранее. + * Сами зеркальные ленты делает упаковщик (`vflip_cols` в pop_pack_kid.py) и + * кладёт рядом с обычными: kid0_v.atl, sword_v.atl, g0_v.atl… Здесь остаётся + * только связать пары: зеркальный файл грузится обычным atlas_load, а его + * раскладка байт-в-байт совпадает с оригиналом — значит движку достаточно + * подменить НОМЕР СТРАНИЦЫ, которую он мапит в W0. * - * Устройство. Копия — ПОСТРАНИЧНАЯ и побайтово совпадает с оригиналом по - * раскладке: тот же заголовок .atl, тот же каталог, ленты на тех же - * смещениях; развёрнуты только сами пиксели. Поэтому вызывающему не нужно - * менять НИЧЕГО, кроме номера страницы, которую он мапит в W0 — все - * atlas_image-смещения и размеры кадров остаются прежними. + * Почему не считаем в рантайме (замеры MAME 2026-08-12, такты Z80): + * загрузка одной 16-КБ страницы с HDD — 970 003 такта (0.045 с); + * разворот той же страницы на месте — 12 645 582 такта (0.59 с). + * Даже идеальная конвертация (accel-копия + asm-реверс) даёт ~1.05 млн — + * то есть в лучшем случае сравнивается с чтением готового файла, а стоит + * asm-модуля. На все 34 страницы: 1.5 с загрузки против 20 с разворота. * - * Кэш ЛЕНИВЫЙ: страница зеркалится при первом обращении к ней в - * перевёрнутом виде (~16 КБ копирования = заметно, но однократно на кадр - * анимации), дальше отдаётся из таблицы. Держится до конца уровня; - * pop_vflip_reset освобождает всё (смена уровня / зелье выпито обратно — - * см. pop_vflip.h про то, почему НЕ освобождаем при каждом перевороте). - * - * РЕЗИДЕНТ, а не банк: функция маппит окно W3 (приёмник копии), а банковый - * код в нём же и исполняется — правило из _pop_level.h. + * РЕЗИДЕНТ: pop_vflip_page зовёт отрисовка персонажей (банк 4) на каждый + * спрайт — трамплин тут ни к чему, а кода всего ничего. */ #include -#include -#include #include #include "pop_vflip.h" -/* Раскладка .atl (sprite.h §Атласы): 0x100-байтовый заголовок, каталог с - * 0x68 — по 8 байт на ленту: [0..1] смещение ленты, дальше размеры. */ -#define ATL_DIR_OFF 0x68u -#define ATL_COUNT_OFF 0x04u /* число лент в заголовке */ - -/* Таблица кэша: страница-источник -> страница-копия. Персонажных атласов - * у нас 28 (Кид) + 5 (страж) + 1 (меч) = 34; берём с запасом. */ +/* Персонажных страниц: 28 (Кид) + 5 (страж) + 1 (меч) = 34; с запасом. */ #define VF_MAX 40 -static uint8_t vf_src[VF_MAX], vf_dst[VF_MAX], vf_blk[VF_MAX], vf_n; +static uint8_t vf_src[VF_MAX]; /* страница оригинала */ +static atlas_t vf_atl[VF_MAX]; /* зеркальный атлас (его page) */ +static uint8_t vf_n; -/* Развернуть ленту на месте В СТРАНИЦЕ-ПРИЁМНИКЕ (она замаплена в W3). - * off — смещение ленты от начала страницы; формат ленты: w, _, h, _, пиксели - * колонками по h байт. */ -static void flip_strip(uint16_t off) +int pop_vflip_add(const atlas_t *orig, const char *path) { - uint8_t *p = (uint8_t *)(0xC000u + off); - uint8_t w = p[0], h = p[2]; - uint8_t *col = p + 4; - uint8_t c; - - if (!w || !h) return; - for (c = 0; c < w; c++) { - uint8_t *a = col, *b = col + h - 1; - while (a < b) { uint8_t t = *a; *a++ = *b; *b-- = t; } - col += h; - } -} - -/* Сделать зеркальную копию страницы src. Возврат номера копии или 0. */ -static uint8_t make_flipped(uint8_t src) -{ - uint8_t blk, dst, saved, count, i; - uint16_t k; - const uint8_t *s; - uint8_t *d; - - blk = mem_alloc_pages(1); - if (!blk) return 0; - dst = mem_get_page(blk, 0); - - /* Побайтовая копия страницы: источник в W0 (0x0000-0x3FFF), приёмник в - * W3 (0xC000). Оба окна свободны для резидентного кода W1/W2. */ - saved = _io_page_w3; - gfx_w0_map(src); - sprinter_page_w3(dst); - s = (const uint8_t *)0x0000; - d = (uint8_t *)0xC000; - for (k = 0; k < 16384u; k++) d[k] = s[k]; - gfx_w0_unmap(); - - /* Развернуть пиксели каждой ленты — уже в приёмнике (он в W3). */ - count = ((const uint8_t *)0xC000)[ATL_COUNT_OFF]; - for (i = 0; i < count; i++) { - const uint8_t *e = (const uint8_t *)(0xC000u + ATL_DIR_OFF) + (uint16_t)i * 8; - uint16_t off = (uint16_t)(e[0] | ((uint16_t)e[1] << 8)); - if (off >= 0x100u && off < 0x4000u) flip_strip(off); - } - sprinter_page_w3(saved); - - if (vf_n < VF_MAX) { - vf_src[vf_n] = src; vf_dst[vf_n] = dst; vf_blk[vf_n] = blk; vf_n++; - } - return dst; + if (!orig || vf_n >= VF_MAX) return -1; + if (atlas_load(&vf_atl[vf_n], path) != 0) return -1; + vf_src[vf_n] = orig->page; + vf_n++; + return 0; } uint8_t pop_vflip_page(uint8_t src) { uint8_t i; for (i = 0; i < vf_n; i++) - if (vf_src[i] == src) return vf_dst[i]; - return make_flipped(src); + if (vf_src[i] == src) return vf_atl[i].page; + return 0; /* пары нет — рисуем обычным атласом */ } +uint8_t pop_vflip_ready(void) { return vf_n != 0; } + void pop_vflip_reset(void) { uint8_t i; - for (i = 0; i < vf_n; i++) mem_free_block(vf_blk[i]); + for (i = 0; i < vf_n; i++) atlas_free(&vf_atl[i]); vf_n = 0; } diff --git a/applications/PoP/roomtest/pop_vflip.h b/applications/PoP/roomtest/pop_vflip.h index a0f6687..3f239ca 100644 --- a/applications/PoP/roomtest/pop_vflip.h +++ b/applications/PoP/roomtest/pop_vflip.h @@ -1,37 +1,48 @@ /* - * pop_vflip.h — зеркальные по вертикали копии страниц атласов персонажей - * (зелье инверсии, уровень 9). Реализация и «почему постранично» — - * в pop_vflip.c. + * pop_vflip.h — ВЕРТИКАЛЬНО ЗЕРКАЛЬНЫЕ наборы спрайтов персонажей + * (зелье инверсии, уровень 9). Реализация и замеры — в pop_vflip.c. * * Кому нужно. Фон и все row-major спрайты переворачиваются даром (порядок - * строк = знак страйда, gfx_blit_*_vflip), а персонажи хранятся колонками — - * им нужен заранее развёрнутый набор пикселей. Отсюда правило вызывающего: + * строк = знак страйда, gfx_blit_*_vflip), а персонажи лежат КОЛОНКАМИ — + * у них даром получается горизонтальное зеркало, а вертикальное требует + * развернуть байты внутри колонки. Такой набор готовит упаковщик + * (kid0_v.atl, sword_v.atl, g0_v.atl…), а здесь он только грузится и + * связывается с оригиналом. Правило вызывающего: * * страница = pop_upside ? pop_vflip_page(a->page) : a->page; + * if (!страница) страница = a->page; // набор не загружен * - * и больше НИЧЕГО не меняется: смещения лент, размеры кадров, флип по - * горизонтали (знак страйда) остаются как были. + * Ни смещения лент, ни размеры кадров, ни горизонтальный флип при этом не + * меняются: зеркальный файл имеет ТУ ЖЕ раскладку, отличаются только пиксели. * - * Почему кэш не сбрасывается на каждом перевороте: зелье инверсии в - * оригинале переключает состояние туда-обратно (второе зелье, смерть Кида — - * seg000:1224), и держать 34 страницы EMM дешевле, чем перезеркаливать по - * 16 КБ при каждом переключении. Бюджет EMM это позволяет: свободно ~215 - * страниц из 256 (memory sprinter_emm_budget). Освобождаем на смене - * уровня — вместе с самими атласами. + * КОГДА ГРУЗИТЬ — на усмотрение приложения: pop_vflip_load_all можно звать + * где угодно (старт игры, показ интро, вход на уровень с зельем). До + * загрузки движок просто рисует неперевёрнутыми кадрами — это заметно, но + * не ломает ни кадр, ни физику. */ #ifndef POP_VFLIP_H #define POP_VFLIP_H #include +#include -/* Номер страницы с ВЕРТИКАЛЬНО ЗЕРКАЛЬНОЙ копией атласа src. Первый вызов - * для страницы делает копию (~16 КБ побайтно — ощутимо, но однократно), - * дальше отдаёт из кэша. 0 — не хватило EMM-страниц (вызывающий должен - * нарисовать обычным атласом: лучше неперевёрнутый кадр, чем пустота). */ +/* Загрузить зеркальный файл path и связать его с атласом orig. + * 0 — OK, -1 — файла нет / не хватило EMM / таблица полна. */ +int pop_vflip_add(const atlas_t *orig, const char *path); + +/* Страница-зеркало для страницы src; 0 — пары нет (набор не загружен). */ uint8_t pop_vflip_page(uint8_t src); -/* Освободить все копии (смена уровня). Атласы к этому моменту тоже - * перезагружаются, и старые копии стали бы мусором. */ +/* Загружен ли хоть один зеркальный атлас (чтобы не грузить дважды). */ +uint8_t pop_vflip_ready(void); + +/* Освободить весь набор (смена набора спрайтов соперника / уровня). */ void pop_vflip_reset(void); +/* Загрузить ВЕСЬ зеркальный набор: страницы Кида, меч и текущий набор + * соперника. Идемпотентна — повторный вызов ничего не делает. 0 — OK, + * -1 — что-то не загрузилось (движок останется на обычных кадрах). + * Живёт в банке 8 (pop_kboot.c): зовётся раз за игру/уровень. */ +int pop_vflip_load_all(void) __banked; + #endif /* POP_VFLIP_H */ diff --git a/applications/PoP/roomtest/roomtest.c b/applications/PoP/roomtest/roomtest.c index 4866b26..4366600 100644 --- a/applications/PoP/roomtest/roomtest.c +++ b/applications/PoP/roomtest/roomtest.c @@ -22,6 +22,7 @@ #include "pop_cdraw.h" /* общая отрисовка персонажей (слоты Кид/соперник) */ #include "pop_cheat.h" #include "pop_tune.h" +#include "pop_vflip.h" /* зеркальный набор персонажей (зелье инверсии) */ #include "roomtest_cold.h" /* холодная половина цикла — в банке */ __sfr __at (0xFE) io_border; @@ -340,6 +341,11 @@ int main(void) * рисуют зеркально сами. */ if (pop_upside_dirty) { pop_upside_dirty = 0; + /* Страховка для ЧИТА U на «неподготовленном» уровне и для + * случая, когда зелье выпито раньше предзагрузки: набор + * поднимается здесь же. На уровне 9 он уже загружен, и вызов + * не стоит ничего (pop_vflip_ready). */ + if (pop_upside && !pop_vflip_ready()) pop_vflip_load_all(); pop_flip_screen(); back = dbuf ? (uint8_t)(gfx_get_visible_page() ^ 1) : 0; gfx_set_draw_page(back); diff --git a/applications/PoP/roomtest/roomtest_cold.c b/applications/PoP/roomtest/roomtest_cold.c index f534dcc..48544d5 100644 --- a/applications/PoP/roomtest/roomtest_cold.c +++ b/applications/PoP/roomtest/roomtest_cold.c @@ -591,6 +591,12 @@ int pop_boot(void) __banked * pop_start_level. Управление: ←/→ бег, ↓ присед, ↑+→ прыжок с места, * Shift шаг, ESC — выход. Карта коллизии задана внутри enter_room. */ pop_start_level(); + /* Зеркальный набор персонажей — ТУТ ЖЕ, если стартуем сразу на уровне с + * зельем инверсии (make LEVEL=9). Иначе первый переворот утащил бы + * чтение 34 файлов (~1.5 с) прямо в кадр: пользователь видел «затык» в + * синей фазе профиля. Тот же вызов есть в смене уровня; функция + * идемпотентна и звать её можно откуда угодно (pop_vflip.h). */ + if (pop_current_level == POP_UPSIDE_LEVEL) pop_vflip_load_all(); gfx_set_draw_page(0); pop_char_draw(POP_CH_KID); pop_char_fore(POP_CH_KID); @@ -640,6 +646,11 @@ int pop_level_switch(void) __banked * перечитаются из НОВОЙ страницы), тайлы/стражи приезжают * из неё же, loose чистит enter_room. */ pop_start_level(); + /* Уровень с зельем инверсии — заранее поднять зеркальный + * набор персонажей (pop_vflip.h): 34 страницы читаются ~1.5 с, + * и делать это в момент глотка нельзя. Звать можно откуда + * угодно — функция идемпотентна. */ + if (pop_current_level == POP_UPSIDE_LEVEL) pop_vflip_load_all(); } return 0; } diff --git a/applications/PoP/roomtest/tests-host/stubs.c b/applications/PoP/roomtest/tests-host/stubs.c index 41438f2..2b5a47f 100644 --- a/applications/PoP/roomtest/tests-host/stubs.c +++ b/applications/PoP/roomtest/tests-host/stubs.c @@ -344,3 +344,15 @@ uint8_t pop_palace; * pop_map зовёт pop_mirror_draw из pop_check_mirror, поэтому символ нужен. */ void pop_mirror_draw(int clip_top) __banked { (void)clip_top; } void pop_mirror_heal(void) __banked { } + +/* ---- Зеркальный набор персонажей (зелье инверсии) -------------------- * + * В host-тестах графики нет: pop_kboot линкуется ради pop_kid_data_load, а + * его хвост (загрузка *_v.atl) заглушен — проверять там нечего, атласов в + * тесте не существует вовсе. */ +uint8_t pop_vflip_ready(void) { return 1; } /* «уже загружено» — грузить не станет */ +int pop_vflip_add(const void *orig, const char *path) +{ (void)orig; (void)path; return 0; } +uint8_t pop_vflip_page(uint8_t src) { return src; } +void pop_vflip_reset(void) { } +int pop_sword_vflip_load(void) __banked { return 0; } +int pop_guard_vflip_load(void) __banked { return 0; } diff --git a/applications/PoP/toolchain/pop_pack_guard.py b/applications/PoP/toolchain/pop_pack_guard.py index d95dce8..89215ff 100644 --- a/applications/PoP/toolchain/pop_pack_guard.py +++ b/applications/PoP/toolchain/pop_pack_guard.py @@ -19,7 +19,7 @@ from PIL import Image HERE = os.path.dirname(os.path.abspath(__file__)) sys.path.insert(0, HERE) import pop_pack_bg as B -from pop_pack_kid import transpose_cols +from pop_pack_kid import transpose_cols, vflip_page # Набор спрайтов соперника выбирается ТИПОМ УРОВНЯ (load_lev_spr, seg000:1092): # tbl_guard_type = {0 guard, 1 fat, 2 skeleton, 3 vizier, 4 shadow, −1 нет}. @@ -185,6 +185,16 @@ def main(): nm = f"g{pg}.atl" cnt, sz = B.pack_atlas(os.path.join(OUT_DIR, nm), pages.get(pg, {})) total += sz + # Зеркальный по вертикали набор — пара к kid*_v.atl (см. vflip_cols). + # ТОЛЬКО для обычного стража: зелье инверсии есть на уровне 9, а там + # tbl_guard_type = 0, то есть страж; скелет (уровень 3), визирь и + # жирный с переворотом не встречаются. Если чит U всё-таки включат + # на таком уровне, соперник нарисуется неперевёрнутым кадром — + # pop_vflip_page вернёт 0 (pop_vflip.h). + if SET_NAME == "GUARD": + _, szv = B.pack_atlas(os.path.join(OUT_DIR, f"g{pg}_v.atl"), + vflip_page(pages.get(pg, {}))) + total += szv print(f" {nm}: {len(pages.get(pg, {}))} спрайтов, каталог {cnt}, {sz} Б") write_pal_header(os.path.join(HERE, "..", "roomtest", "pop_guard_pal.h")) print(f"ИТОГО: {n} спрайтов стража, {max(pages)+1} EMM-страниц, {total} Б -> {OUT_DIR}") diff --git a/applications/PoP/toolchain/pop_pack_kid.py b/applications/PoP/toolchain/pop_pack_kid.py index 33ec649..60a9596 100644 --- a/applications/PoP/toolchain/pop_pack_kid.py +++ b/applications/PoP/toolchain/pop_pack_kid.py @@ -47,6 +47,31 @@ def transpose_cols(w, h, rowmajor): return bytes(out) +def vflip_cols(w, h, colmajor): + """COLUMN-MAJOR (out[col*h + row]) -> тот же формат, но кадр ЗЕРКАЛЕН ПО + ВЕРТИКАЛИ: внутри каждой колонки байты идут снизу вверх. + + Зачем отдельный набор. Спрайты персонажей лежат колонками ради + БЕСПЛАТНОГО горизонтального флипа (accel копирует колонки, направление + задаётся знаком страйда). Вертикальное зеркало у такой раскладки — это + разворот байтов ВНУТРИ колонки, а accel копирует блок только вперёд: + в рантайме это стоит ~0.6 с на страницу (замер MAME 2026-08-12), тогда + как ГОТОВАЯ страница читается с диска за 0.045 с. Поэтому зелье + инверсии (уровень 9) обслуживается вторым набором файлов *_v.atl. + Раскладка каталога у него та же — движку достаточно подменить номер + EMM-страницы (см. roomtest/pop_vflip.h).""" + out = bytearray(len(colmajor)) + for col in range(w): + b = col * h + out[b:b + h] = colmajor[b:b + h][::-1] + return bytes(out) + + +def vflip_page(page): + """{idx: (w,h,pix)} -> то же с зеркальными по вертикали пикселями.""" + return {i: (w, h, vflip_cols(w, h, pix)) for i, (w, h, pix) in page.items()} + + def load_kid(aidx): """Атлас-индекс aidx (== frame.image) -> res(401+aidx).png -> (w, h, 8bpp COLUMN-MAJOR). 0->0xFF, i->0x70+i. Пиксели транспонированы в колонки. @@ -149,6 +174,10 @@ def main(): total += sz names.append(nm) print(f" {nm}: {len(pages[pg])} спрайтов, каталог {cnt}, {sz} Б") + # Зеркальный по вертикали набор (зелье инверсии, уровень 9). + nmv = f"kid{pg}_v.atl" + _, szv = B.pack_atlas(os.path.join(OUT_DIR, nmv), vflip_page(pages[pg])) + total += szv else: names.append(None) print(f" (kid стр {pg}: пусто)") @@ -160,6 +189,8 @@ def main(): sw[i] = (w, h, pix) cnt, sz = B.pack_atlas(os.path.join(OUT_DIR, "sword.atl"), sw) total += sz + _, szv = B.pack_atlas(os.path.join(OUT_DIR, "sword_v.atl"), vflip_page(sw)) + total += szv print(f" sword.atl (chtab_0, id {SWORD_IDS[0]}..{SWORD_IDS[-1]}): " f"{len(sw)} спрайтов, каталог {cnt}, {sz} Б")