From bdaa199ecb74e832b4346f211563c13b139ea611 Mon Sep 17 00:00:00 2001 From: Zack Buhman Date: Sun, 24 Mar 2024 21:51:37 +0800 Subject: [PATCH] vdp2: add color_calculation_ratio --- Makefile | 8 + res/forest.data | Bin 0 -> 76800 bytes res/forest.data.pal | Bin 0 -> 48 bytes res/forest.pattern | Bin 0 -> 2400 bytes res/forest.tile | 3 + res/forest.xcf | Bin 0 -> 41048 bytes res/haohmaru.data | Bin 0 -> 13728 bytes res/haohmaru.data.pal | Bin 0 -> 48 bytes res/haohmaru.xcf | Bin 0 -> 5416 bytes scsp/fm.cpp | 2 +- scsp/sound_cpu__midi.cpp | 6 +- tools/tile.py | 68 +++++++ vdp1/normal_sprite_color_bank.cpp | 4 +- vdp2/color_calculation_ratio.cpp | 328 ++++++++++++++++++++++++++++++ vdp2/nbg0_16color.cpp | 4 +- 15 files changed, 415 insertions(+), 8 deletions(-) create mode 100644 res/forest.data create mode 100644 res/forest.data.pal create mode 100644 res/forest.pattern create mode 100644 res/forest.tile create mode 100644 res/forest.xcf create mode 100644 res/haohmaru.data create mode 100644 res/haohmaru.data.pal create mode 100644 res/haohmaru.xcf create mode 100644 tools/tile.py create mode 100644 vdp2/color_calculation_ratio.cpp diff --git a/Makefile b/Makefile index fc3607d..c531058 100644 --- a/Makefile +++ b/Makefile @@ -27,6 +27,12 @@ include $(LIB)/common.mk %.data.o: %.data $(BUILD_BINARY_O) +%.pattern.o: %.pattern + $(BUILD_BINARY_O) + +%.tile.o: %.tile + $(BUILD_BINARY_O) + %.bin.o: %.bin $(BUILD_BINARY_O) @@ -45,6 +51,8 @@ vdp2/nbg0.elf: vdp2/nbg0.o res/butterfly.data.o res/butterfly.data.pal.o vdp2/nbg0_16color.elf: vdp2/nbg0_16color.o res/kirby.data.o res/kirby.data.pal.o +vdp2/color_calculation_ratio.elf: vdp2/color_calculation_ratio.o res/mai00.data.o res/mai.data.pal.o res/haohmaru.data.o res/haohmaru.data.pal.o res/forest.data.pal.o res/forest.pattern.o res/forest.tile.o + vdp1/polygon.elf: vdp1/polygon.o vdp1/cube.elf: vdp1/cube.o $(LIBGCC) vdp1/cube2.elf: vdp1/cube2.o diff --git a/res/forest.data b/res/forest.data new file mode 100644 index 0000000000000000000000000000000000000000..6e8f15f547e662c098ec429929f77d8c988d8009 GIT binary patch literal 76800 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 JMNZe0{|6-*1;79R literal 0 HcmV?d00001 diff --git a/res/forest.data.pal b/res/forest.data.pal new file mode 100644 index 0000000000000000000000000000000000000000..15855a2b48d0de0f807e9f6778213342c1e32d5c GIT binary patch literal 48 zcmV-00MGvbLO=jYMF3q^0A*bMC20VBc>s@u0IZk)YHkR|r4;15Cg!b^@5RUN#_j6U G=JeOMDi|;T literal 0 HcmV?d00001 diff --git a/res/forest.pattern b/res/forest.pattern new file mode 100644 index 0000000000000000000000000000000000000000..aebad97da333f92dd00fce5d96c7551a7be73c82 GIT binary patch literal 2400 zcmV~$0{{>P6a~PCpKaT=ZQHhO+qP|MtF5*g;#RX!Tg_&TwRQ)95R5=HB?6p)I=@RMjg~eJ=8}7G(;mbMiVqeGc-pFv_vbk zMjNz6JG4g!bVMg~Mi+ENH*`l2^h7W8Mj!M=KlH}{48$M|#t;m}Fbu~CjKnC6#u$vn zIE=>xOvEHi#uQA&G)%_~%)~6r#vIJWJj}-eEW{!##u6;WGAzdmti&p;#u}`}I;_VA zY{VvP#ujYFHf+ZZ?8GkY#vbg&KJ3Q<9K<0U#t|IFF&xJUoWv=d#u+?;Cvg_%@D!fL zd0fCVcor9N3D4nqynq*R8CP%>*Ki#-@Dg6eP29pOconbVb-aN$@fP03J9roG;eC97 z5AhK`#%@fE(tH~1Fc;d}gmAMq1@#xM94zu|Y>#{>LNtl$$n4Bq?lBt-QX_%Jjn4TG!k(rp8S(ugCn4LM8 zlew6id6<{^n4bk$kcC*7MOc)@SezwTlBHOhWmuNwSe_MFk(F4PRalkPSe-RkleJiz zby%16Sf35pkd4@wP1uyp*qklclC9X9ZP=FW*q$BOk)7C?UD%b~*quGtlfBrReb|@% z*q;M9kb^jwLpYSfIGiImlA}19V>p)MIGz(Yk&`%?Q#h5=IGr;%le0LRb2yjtIG+o+ zkc+sOOSqKFxST7vlB>9yYq*x{xSkuhk(;=gTey|mxScz=le@T^d$^bTxSt1jkcW7f zM|hOSc$_DAlBal@XZQr4`Rldg8`3B$QTYQ`E@Lj&g_xS-ol~QSy zQCXE!c~wwFRZ?YDQB_q_b=6Q!)lzNMQC-zjeKk-+HBw_WQByTjbG1-QwNh)fQCqcB zdv#Dpby8<_QCD?SclA(D^-^#3QD5~_e+|$;4bor@(NGQ3aE;JNjnZh1(O8Yscumkm zP10md(Ns;-bj{FA&C+bm(Ok{bd@ayIEz)8w(NZnba;?xxt1mzU1wEr@ zby1h}oSxSUdQq2kMOSrA*L6cL>1Ey2Exn>w^_pJS8+uc3>21BEclDm$*9ZDgAL(P= z)*XGKPjy%K^qD@_7y43P>1%zXZ}pwN*AMzpKj~-vqF?o!e%F0H&>#9!f9Y@iqkr{K zkMy4&8>VGDoWKd4$cdfANuA8eox&-d%Bh{kX`RmLoxvHM$(fzSS)I+1UBfk9%e7s{bzRT( z-M|gq$c^2^P2J4R-NG&1%B|hTZQai8-N7B*$(`NBUER&y-NQZI%e~#lecjLfJ-`D! z$b&t^Lp{vHJ;EbB%A-BTV?EB}J;4(_$&)?BQ$5YoJ;O6S%d$mMPK$6U-dO#_YJ?~mwnT>{EA=o zYku8t_)Wj%xBZUa^?QEbANWIm_Z>Kln%g z#fA~-T<-h%p|Mf#Z@_&9D2!_HDksuOAqDUM`B55RxMyV(r zWuk19i}Fz+Dn_NK995!fREz3SBWgyis2z2pZq$qV(I6T|qi7sWqG>dX=FuWrMyqHY zZK7?oi}ukWI!34H99^Pobc^oMBYH-!=pB8cZ}f})F(3xUpcouOVrUGD;V~jc#;6z_ zV`6NKi}5ibCdQqLsZp@4Mu^<-4qF5YDVreXk<*_1G#;RBy zYhrDzi}kS~HpZsd99v>*Y>Vx&BX-8F*d2RfZ|sZxaUc%Hp*S2z;%FR;<8dNR#;N}S D""#2"""""292*2)2ҙ2Қ22-2="2#2"#"""#""""""""":"""*"*ꪝ/#??#>*jjj˪ʪʪfgoffgΦffofffvgff陯ޙkfjfffffffff뙩yzzffffffffffffffffeVVUeVVUeVVUeVVUeVVUeUVUeUVUeeVUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUeUUUeUUUeUUUeUUUeUUUeUUUeUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUVUiVUVUiVUVUiUeUeYiUeYݛٙޙyy""*9"*""*9"*2"*'"*"3922VffffeeUeVUUeVUUUeUUUeUUUeUUVeUUVUUUVUUUU%%URURUU6RURUV%U%U%RUURU%URRUUUUUUVUUUVUUUVUUUVUUUVUUUVUUUf%UUfeUfeUfeUfeUfeUfeUieUieUiݙٙٙٙٙٙݙݙݙݙݙݙݙݟݟݟݟݟݟݟݟݙݙݙݙݙݙݙٙٙٙٙٙy۹ݙݙݙݙݙݙݙ"""22"""י"יٙٙٙ"""#2""""""3""""#-"""""""""2"""22 "2 "#""32""""""""""""#ͪ"#"#""#2""##":""*:#":""22""""""*"!:"*"""*"""*ݪ*ݺ着߯ݫfffffffiffifffffffffffgV홙iffffffffffffffffffffffffffffffffffffffffeeUeeeUeeeUeeeUeeeUefUUefUUefUUeUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUeYiUeYUeYiUeYUeYiUeYUVYiUVYݙݙݙݻ۾ݻ۩ιݷyy"""'""""")""""-"""*"fUeUeUeU+eU9UU:fUU-fUUVUUUeUUUeUUUeUUUeUUUeUUUeUUUeUUUU%UURUUUU5UUUeUUUUUUeUUU%UUUUUU%UUfRUUfRUUfU%UfUQVfURffUUfUURVeUiUUiUUiUUiUViUViUViUViٙݹݙݙݙݙݙݙݙݙߝݟߝݝݝݾݺߙ}ۻ}ۻ}ۻ߻驙ݙݙݙݙݙݙݙٙٙٙٙٙٙٙٙ""""""2"""2*"*"""-?:߫,Ӻ̽Ң9:š¹šɩڪڪ"""ꪪۯݭݪݙݙݙݙݙݙݙݙiiiiiiiiffifffifffifffffUUefUUefUUefUUefUUefUUefUUefUUeUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUfUUUfUUUfUUVYUVYUVYUVYUVYUVUUVUUVUݙݙݙݙݙݙݙͻݻٙٙٙיٙ"2*!3+22;2*"fUU"fUU"fUU"&UU"&UU"&UU"&UU""UUeUUUeUUUeUUUeUUUeUUUeUUUeUUUeUUUU%UUUeUUU%UUUeUUUUUUeUUU%UUUUUUUUV6UUV&UUVRUUfVUUffUUffUUffUUffUViUViUVi%ViaViUURUV)yٙٹיݹ뻚ݺݙݙݙݙݙٙٙٙٙٙyٙ"2!*"""#"""""+"""""""""":˯ڪ着着着着ݪʪݬݪݪͪܬݙݙݙݙݙݙݙݙiiiiiiiifffffffffUUefUUefUUefUUefUUefUUefUUefUUeUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUeUUUeUUUeUUUeUUUeUUUeUUUUUUUUUUUfUUUfUUUfUUUfUUUfeUUVeUUVeUUVeUVUUVUUVUUVUUeUUeUUeUUeUYݙݙݙݙݙݙݙۻۻݻݻݻ"f*f!f+f2f;f2f*f""UU""UU""%Ub"%Ub"Ve""VU"#&Ub"%eUUUeUUUeUUUeUUUeUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUefUUefUUefUUefUUefUUefUUefZUefUVUV)UVUVUVUVUVUYܙ))͝ݝݙڙݙݙy""#22#""""9#2""22"#".#"2<""*""ͪꪪ̪̪ݪ쪻ݬʪߺݙݙݙݙݙʻ˻ifffffffffUUefUUefUUefUUefUUeeeUeeeUeeeUVUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUVeUUVeUUVeUUVeUUVeUUVeUUVfUUVfUeUYUeUYUeUYUeUYUeUYUefiUefiUefiݙۻۻ߻߫ۻ2ff&fff"ffeffeffeffefUUUb""Uf""Uf""Ueb"UeR"Uef"Uee"UeURUUUUUUUU%UUU%UUU"UUU"eUU"%UU"%UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUefUVefUVUfUVUfUVUfUfUfUeUfUeUfUYUYUYUYUYUYUYU:s+*"!"+#"""2*2"222""2""""""#)""""#9"#9"*"!"+""+****"̪̪̬Ϭ̬̬̬ʪʪʪʪʪʪ̪̪̬ϫʪʪ̪̪̪̪ʻffffffffeeUVeeUVeeUVeeUVeeUVeeUUefUUUfUUUUUUUUUUUUUUUUUUUUUUeUUUeUUUeUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUVfUUVfUUVfUUVfUUVfUUVfUUUfUUUfUefiUefiUefiUefiUefeUeVeUeVeUeVeۻffiffffffUfUfUffUbzfUfffUbffUfffUUeURUeUUVUUUVUUUVUUUVUUUeUUUeUUU""UU""UU""%UR"%UR""UR""%U""%R"""UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUeUfUeUfUeUfUeUfUeUfUeUfUeUfUeVfUUUUUUUU"""2""""""""""2""")"##")22")"9************̬̬̬̬̬̬̬ʪʪʪʪʪʪʪ̪̼̪̪̪̪̪̪̪̪ffffffffefUUefUUefUUVfUUVfUUVfUUVfUUVfUUeUUUVUUUVUUUVUUUVUUUVUUUUeUUUeUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUfUUUfUUUfUUUVUUUVUUUVUUUVUUUUeeVeeeVeeeVeeVVeeVVeeVVeeVUeeVUe߿ݙݙݙڙۙffffffffffffffifififfiffbeUffeUfeUfeUveVfeUfeUffeUeUUUeUUUeUUUeUUUUUUUUUUUUUUURUUUU%""R5""U%&"Q5%SU%%RR%%UU%UUR%%U%UUU"UUU"UU"%UU""UU#"&UR2"UU"#%UeVfUeVfUeffUeffUUffUUffUUffUUffUUUUUiUfUfiUfiy"""3"2"32"*3""!:##"*)***ʪ***,ə̬̬̪̪̪̪̪̼̬ͪ̚̚ܪ̺̪̪̪̪̪ʻffffffffVfUUVfUUVfUVfUUVfUeVeUUVeUUVeUUUeUUUeUUUeUUUeUUUeUUUeUUUeUUUeUUUUUUUUUUUUUUVeUUVeUUVeUUVeUUVeUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUeVUefUeefUeffUeffUefVUefVUefVUefYYYYYYUUګffffffffffiffffffffffffffffffffffeUffeUffeRffeUfffUf"%ec""5f"%""UUR"%UR#%U%#"U%""%#""UU""R%"%RU%UUR5%UU%UUQfUUUUUR""%"""%""""UR""UU""UUR"UUV"UUURUUZUUUUUUUUUUUff"Uff#"ff""f"#!&R"""UR""UU""UfiUfiUfUfiUf%i")2""fii""#22""22#""""""""")""#"2"9"̙̙̙̙̪̪̪̪̪̚̚̚ʪʪʪݪݪߪڪ̬̬̪̪̪̪̪̪̪ʪʬʪ˹˚ʩʫʫeeeeeeeefeUUfeUUfeUUfeUUfeUUfeUUfeUUfeUUUeUUUUUUUUUUUUUUUUUUUUUUUUUUUUUVeUUVeUUVeUUVeUUVeUUVeUUVeUUVeUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUefUUVfUUVfUUVfUUVfUUVfUUVfUUUVUfeYeYeYeYfYfUfffffffffffffffaff"fR""f"""""%f"""ffb"ffb""ffS2Re"1%R2%RUSRfU%U"5e""Ue"RSe%c5eU"!#"eUS"""""""U""""R"%RR"%U""%e""%e2"%U""UUUUeU%UUU%UUUUUUUUUUUUUUUUUUUUUUUUUUUUUf2UUfeUUVeUUVeUUVUUUVUUUVUUUVU#"""""""U"""Ug"2Ua2)Uf")Vb!)Vfb9"6ff"""""""""""&""2""f#&"fiif""""""""#2"""""2"3""""""""""")2"""""""""""""""2)3)9{̻̻ʪʪʪ߭ݭݭݪߪڪ̪̚əʙ˙eeeefefefefefeUUfeUUfeUUfeUUfeUUfeUUfeUUfeUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUVeUUVeUUVeUUVeUUVeUVVeUVVeUUVeUUUUUUUUUUUUUUUUUUUUUUUUUUeUUUeUUUUUUVUUUVUUUVUUUVUUUVUUUVUUUVUUUUfUfUfUfUefefeYfeY&c%S&baefgffr!#2""#"""""""b""%6b2Rfe2"e"2"""""#2U""%%"UR%""S%"""5"%S%UU"R"%S2"%%R""b##"&f"""eR"&UV5eUV%%%Vb"262"R""&f"""""""&UUUUUUUUUUUUwvuUUUgUwwUUUUUUUUUUUUVUUUVUWUVUuUVUUUVUUUVUUVfUUVWeVfb&Vfc&ViiVifVffVfbfVfbfVfbfbbVffbVfbbVfiiYfbiffbiffbif""fifffff)ffifiəə̙ə̙˙ݪݭݭܪʙʙəʫffefefffefffefffefffefffefffefeUUfeUUfeUUfeUUfeUUfeUUfeUUfeUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUVfUUVfUUVkUUVfUUVfUUVfUUVfUUffUUeUUUeUUUfUUUfUUUfUUUfeUUVeUUVeUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUfeYfeYfVeVfVeVfVeUfVeVfVeUVeUfiffifffffffffifffiffffffifififfffb##fffb"fff"&g2"'fS""f#ffw"b"fc5"%"e"%U%"RR%"RR"U"RR2"RR""R%""5""""""""2"""%!2#%"""Sb""Rf""R""""""""""""""""""""""""#""""U""%UeUUUeveU&#aU&f"U23"U"""Re"%2eU""UUvWUUWfUUVeUUVef5VebeVeb&""b&2"UfbfUfffUfbfUfgfUV`fUVffUVbf"%fffafiffffafffVff`vffffffiffffffffifffifffifffifififfiffffiffffbfffffifififfifffiffefffffffffffiiiܬݬݪ̪̪̪̪ڽڧyڹyͪߪͪǪ٪ީ̙̪̪ffffeffeffeffefefffffffffffeUUfeUUfeUUfeUUfeUUfeUUfeUUfeUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUURffUUffeUffeUffeeffe"ff""&b"""b2"VeUUVfUUUfUURfUU"eU"R#U"R%"%"5#UUUUUUUUUUUUUUUUUUUUUUUUU"UU%"UUUfUUfUUfUUVUUVUUUeYUUeYUUeYffffffiViifiififffiffiffffiff&fff3""R2""R"""%fb""b&""'f""fcR"%""%%"""%"""%"""U"""""!S"&"""%U"R""U""""2""""""""""R""&R"#"""#2"""R"""""%"2"%"""!2"""""""""""""eUR"&R""&""&""""""""""""&""""2Ub2b"b"b"&Uvf&Vef"f2f"""&"""6UU"""%bf%UffeUffeUffeUfffffffffffffffffffffffffffifffffffffffffffffffiffffffffffifffffffffffffffiffffffffffffffffiffffffffffffffffffffiffiffifffifffiffffifffiffffffffffffifffifffffffffifffffifffffffffffffffiiffifififf۪ʪʪ̪wʪwʪywwwzwwwywwwwwwwywzfiffiffffffffffffffffffffffffffffffffffffffffffffffffffffffeUUfeUUfeUUfeUUfeUUfUUUfUUUfUUUUUURUUUUUUURUUb"UR#"U""6U""&U""'""b%"&b"ff""ff"#wfg"fvR"fr5"ffU"UR%##"fU%"VU%%"U#R"U"""U""%U""USURUUUUUUUU"%UU""UU""UU"""UR"R%U"UUUUUUUUUUUUUUUUUUUU%UUU"UUU"UUUYYYfViUVifUViUUVffffffffffffifffffffifffffffff6Vf""#V2""&R""!r"&b""b&""b6""c"b"""""""""""""""U""U"%"%UR"""""""&""""%R"2b&"5UU""U"RUR&R"#2R"%"2""%U"""U"""%""""""""""R"""%"""""b"""#2""b""""2"""2""b"""eUURV""%"%UV"%UV"%UV"&UV"!V!1UR"%"2"%"R"ffffffffffffffff"&ff#&ff"fff&fffffffffffffffiffiffffffffffffbffffffffffffffffifffffffff2fffifffiiffffffffffffffffiffifffiffffffffffffffffffiffffffffffffiffffffffffffffffffffffffffffffffffffffffffiffiffffffifffffffffffffffffffififffiiffifffffffifffiffffffffffffffffffffffifffijfgwywwywwwwwygwfyywwwwwwwwwwywwzwwzwywwywwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwzwwwwwzywwwwyyywwyzywwgzywywwywwwwwwwwwwwwwwwwffwfwfffwfffvfffffffiffffifffffifffffffffffiffffffffifffifffffffifffffffffffffffffffaff"ff""fff"ffffeUUUeUUUeUQU"U"2%U%#%UU"UURUUUUUU"WUUUVUUU"UURUUU"%""22"""U""fcb&""b6""e&""V6RU"f%RUUU#"""&"""&"b#R""UV""U"UU""""R"fvV""v""fb2"R"U""""Q"""U"""%""""R"V"UUR""%R""UUU"UUU"UUUUUUUUUUU"eUU""%U"#"UUUViUUUUUUYUUUUUUUUUUUUUUUUUUUUffffffffffffffiffVifVffffffffiffiffiffffffffff"b2c"&"c"&"c1bb&b&ff"""f"""f""""""""""""""""#"""""%#&f%#b&""fb"""R2""%R"""%"""RU""6!R"bU%"6"Sf"""""%R""R36"Q"QUR""""""&ff"gS"&e5U&ar"!&e""&e"%VfU%R"cUR"&"R"2"R%2"RU2%"%R%""RR2"e"2"%b"""f""ffffffff&fff""Qf22%"""%""""2"""%fffcffe"ffc"ff#f%"6b"RR""RR""5""""R"""R"""#'"%fff%ffffb"%b"")fY""ff"2ff"ffffffffffffffbfffbffff"ffb2&fr""f3!f"""f""&f"&bfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffifffffefffffffafffbfffbfffbffffffffb&ff"&ff"&fi"&ff"&f"'b"fffffiffi6fffffffffffffifffsUiffififffffffffffbfwzgwwffwwffgyffffffgffffffffwyywzwwwywgwwwwwwwwyzwwvwwwwwwywwwwwzwwywwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwywwywwwwwwwwwwwwwywzwwywwwwwwwwwwwwwwwwwwwwwzwwwwwwwwwwwwwwwwwwwwwwwwwwwzywwzwwwwwviwwffyvffffffffffffffffffffffffffffffffffffffffiffffffffffffffffffffffffffiffiffffffffvfffifjVffffffffffffffffffffffffffffffffffb"fa""f#""f"""b"""c"""UUUR%UU"2eQ""UR""UR"%UR"UU""UR"""#e6"#6e%#R&%"2"%RR"""%"""%%"""U"2""c""Ub""U2""UUR2fR6"6Rb"RR3"%""""R"#"S""&fffb%"&bfff""R&""R&"""U""2UUb""U&"""6""2&"""&2""b""""""UR""UR"%V"#&e"""f""&"""&"""&%UUUUUUUUuUUUWUUUVUUU'UR"VUR"uW""VfffVfiUfiUffUfeUR&fU"""""""fiffffifffffffffffff6f3"b""f&""&f2#&"2%"""2"""c""&R"""2"2""U""""R""26ff&a"""fff%"""%"""""&f2&b"&bbRf&%"fb""""#"""#""""f"#ff%R%"&35S 3"MFV586Uc#fc#3""feR"S""""""""#"#UVg"5f5RSSR%"UUS"vUS%f2%&%R"%R2""""""""RU""U%"""&""""2"#U2"%SU6%U&"%6U""""""""""%S""R%""URUR"rR%#U%RR""%3"%R"6b""&fa5"ffb"&ff"&ff""""UU"""R"Sfff"R"""R"b""2"2!b"2fb5""&"UU6c#bf2agf&&gf6"'f6"bf&"bf6&U6&c2&"&ff""ff""ff2fa"&ff&fffeRf2R%fffffffffffffff6ffe"ffR"!b""""2"fffbfffbfffbfff"ff""r"""""""2""&b""&b""fb"1vfffff"""V""&c"""b&ff&9f""fr"#""""""R"""%""""ffb%ff5Rffb"fffffff&fffff5SfU5R2f6#&b&"fffb"vbb2eb""eR"%b#2%bffffffffffiUff""R!#UR""R"""2"""iwwwwgwfg"ff"vff%gfg&ffwywwywwwwwywwwwwgwfwwwwwwwffgfwwwwwwwwwwwwwwwwzwwwwwwwwgwwwwwwwwwzwwzwwwwwwwwwwwwywwwwwwwwwwwwwwwwwwwwwwwwwwwwfwvffwwwwwzfwwvfwvffwffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffiffffffffffffffffffffffbfcc#fffifffffffffffr"fb""f"""&""%fffffffffff&fff1fff1!fbS&f"&fb"b"2"fb""ff""r"2"#32"""'%"%R""R##U"""R"""R"""""""%"""R"""SUU"""%R"""UR""2U"&e4%RE"U%"%"U"""""3R"#"R%U%"R##"UfR""b"%U&"%"R""SV"R&"R2&&%R&cb""%&"#Rf""5&b"ReU"Rb"""U""""R""cR"f%R"b6fb&&2c"ef""""&%""&&""'bc2#"&""ff"&"""&f"3""e"c"#2"&#"""f b"&6"evb"&Vr"uf""fff"c"2c&fgf""""a""""fb""b&2"""vf"""f"#"f32"&fg&"&f&"""#""#%"""R"""UU""""R""U2""""""""""""""R""""""""""""""""%U""R&"%%R"%R"""#&&""b&""b5"&"V"&"&"&"b"&b""f"%R""RR""#"""R"""""""""""""U""%""#"%"")6"#"R&V"c%!Rc"c2b""#&"""6"2""e"""&"""6#2"2b%R"bRR"e"R"e"R"""""UR%"Q%""Vf"v#3"b""""""""""R"UU"""""""""#""""U""%"R"%"R"%"5Ube"#"%U2"""""""""""""#2"""f""&6#fv"Uc62"6fR%Qb2%U"R!Re"ffc2"R6c""%U"""""""f!"3'ef2rf#"%UR"2"fS%U"""b""fb""35USR#"R#"cUU"#"#"2""b""%""R"""U""""R"""%""&b"U3""#RR"U"2"c#%13&&"R#f"S%""&%""""&"""""""23"2#""""bfgf&b##26ff3""""%R"e2R"b""UQ2""5""b"R"f""S""UU"""""""""""""%U""%"R5S5RR""2UU3""#%#"%"R"%"2"%"5"%"#""R#""R#%"""%""6%"&bc"b&%"gvU"&f""&f"#%"&fffvfffffffb'ff""fg""&g2""fSf"&wwwvfffgfffvffffwff#fvg"wvcRfffUfgwwwfff'fffbff26gv2&gg2!gf2"gfwwwvfwvffffffff&ff"fb""vf""vf""ffffffffffffffeffffb&ff"!fb"#fb"ffffffffb""f"#!a""b"!f""&b""fr"ffffffff""&f"!vf"&ff#&ff"fff&ffffffffffffffbffb"ff##fb""fb2"f"2"f%S"UR"f"""&"""&"""&%U""R%""5R"%&'"ffffffff2ff5RffrR""UR"""55"""fbr"fSb3ff%&ff5fff2b"ff""ff5Rf2R%U"%"e"%"c"R"f"R"f%"1fR"&b"#"UUR""""""""""""""%U"#Q&""UR"b"""""""""U"""RU""%""""U""""""""%R"""%262fff"&##R"ffR"2"""""""""""""bS"Rc#"UVb%Rf2&S32#b"""""'b"""b"f""&Sffg"&R"USff"%U""R&"%%Pf%R##""""c"""&b"%f"&1"22c""""""""""""f12"U&b"#bb"&"b"&"b"b"b"b"b"b&""&f"23"#&2#"b""2c""&#""&"""&#""&f#""#b2"#&""#VR""V%""65""b"""b2""U""""U""UR"R"""%"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""2%"2R%"%"%"%#%"%"R"%"R""U""2""""""""""""""""""""&f""&"b""f6""2fbb"R&b"R"R%&"R%b"%Rf"#2"""(""2""""""f"""&"""c2""""""""""""""""2#"#"#" #"(3" BS""""""""UR"%""b""#eR"e"U"a5U"&!%"%UU"%"RUURfffR""#"""#"""1%""2R""S%""U5""%RV"""Sb""R"""U"""U"""2"UR""R%""%S"%"5"%"R"%"R"#""%R"""""""""""""f"""#2#""""&"""6""#R"""f""&bURc#fU"f6"""b""f"""#"""R2"#%R&b""bc2""""UR"%"RU%fe""c&5"&f""""#"UUU""#%U"R%%"a%R%"%"#"#"%"R"%"RR%U"%UUU""#""""&"""&UR"&R%"&%U"&""#""5SRf2#""eRR2b%R"&""#6""b&""b&""""%U"""""""""""&"""V""56%"#6R"""&&""b&""b6"""&""S6R""e""Sb""f"&"&ff%"ff"#&f"&Uc"%"V""e#S""U"""""2"f2"c2"VsR"6rR"r&""""""""""%Uff#"&""6&"b&&"vfb#%g""&f""ffUUf&f#f&"c&""b"""&""&""v&""v&""f&""fb""f""6"""&"#2f"b&f"fff"&f""2&&b2&fb"&f"2&f"""f"""f"""f"""f"""f#&cf"c&f"b&fUfSf"aVUV2""&"##2b"""#"""#""R#c%"%c""%b%U5b"RUb"%URR""UR""#R"""R2""%""3#"U23"%S3"RbR%&#%U""R%2fb"&"f#Sf6"&"cR6fU""2""b"ff"&e""!6f""U"""2#"""3%"fb"2""f""b2b#Uff2""%UU""""""""""""#%2f%"R&URRVU%!U"%#"R6"Q"%X"%UUc"S3b"%U"2""3"""%R""%%R""R%"U"2""Sf"UV"b"&"e2a2b"c2b"b&#"b&2"""""""""""""""""""&"""&"""&"""&#"""&b""b&2"b&"""&"""6"""b""bc""c&3"&b""#""f"""b""#6""""""""""""""&f"2Vcb"%#&""Uf"""""""""&"""""""""UR"""%R"SS"%"fb"&"b"cf""f#"""""""""""""""#"""" """""" 0 ""1!"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""#&"!6b"b2f&"""""##""""""""""""fff"""b"ff""""2"32""""""""""""""R%""%RR""#U2""Q%""%U"""%"""R""""R%%S%UU2""""""UU"U"""#5U"""R"""U"""""R"""%""UR""UR""RR""U""""2""""""""""""""UUUR%""%"eUU"""""""""""%"""R"""5""""R""""%""""R""""""R""U""""2"""""""""""""""""""""""&"b"&b"aab"b"b"b&""c+2"&b""""#U""%%UUR"""""""""""""""""""""""""RR"%"R"%"R"R"2"R2R"R&""2%""%R"""""""""""""""#"#""fb"#b""&b""#&6&""#f"""#""""#&""#""b"""b"""""""""""fb""2b#f# M"""8""#"""2""""""""""""2"""2""""""""""""""b"""""""#""#"""""""""""""""""""""%R"2"UU"""""""""""""""""""""""""Rb"U#"""2""""fb""b6""&b"""6"""""f""""#""#"&"2"&""""b"""c""""2""""2&fb"""b"2f""""""""""#"""3fffbf"""#2""""""""""""""""""""""""""#""&"2%S&"R#'VUR&ab""f&""#f"""2"b""%""&f"#b&""fb"%R#"#%""%"R"%&f%R"%UR"""""""""""""""#""""""ff""""""""#""""&""3b""&2""6"""b"""b"22b&""&fb"""b"""b"""b"""b"""b""""""""""%"""%""""""""""""""""""""UR#"R!35#2"""U"""R"""R""!b"""R"%S""""""&f""&"bR"fb%"""%""""R"""bb"#f2"##"""# 2""'&"#"v""gg""&b"""&"""&fb#2b&""ff""f"""r2""""""&"""b2""#"""""3#""fb#& R#`d"eC"fff"&""""ff"#""""#3""""""""""""b"2b&b"ff"&f"""b22"2""""""""""""""""""""""""""""""""""""""""""""""'"1 "0!  #30 0!"""""#""2#"""# 1"""""""" """2"23"""1!""""""""""""""2"""2"3"!"21""""#"""""""#""""!""" """"""""""""""" """3"""!""" """"""""""""""""""""""""""""""""""""UUUR##2%"UUS""""""""""""""""""""""""2""""%""""R""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""2""#""""""""""""""""2#2"# 0""200#!23#(2V&2h "!"""""""""""fffb""&"ffb"""""322"#"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""2"""0"""!""#""""""""""""""""""""""""# 2" "2 """"""""""""""""""""2"""""""""""""f"&"&"b#"""""""""""""""""""""32&"ffb"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""#""""&""""""#""1""2"""2""6b%b#ff"#R%""SC""4"#"""""#22b""f"""""2"""""2""" 2""# 2" """""b&""b&""6c"""""""#""""""""""""""""""""""""""""""""""#""""""# """"""""""""""""""""""""""""""""""""V"""%""#%""""""""""""""""""""fff3bb"f&ffbS""""#2#""""""""""""""ff"#&#"b"f"&2"""##""""""""""""fc"""&c"ff2&""2"32#""""""""""""""""""#"!32b"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""2""""""""""""3 b!12b&#1!'&"&""2#"!0a"b0032""2#"  ! 312""#!""#1"" "#01"#!"" 33 "#"2b2""0"#b2"#b"""#3!#b09`"3b###"2 `p1"b2#c#"bb3b3ib'"3""b"""#'""b"2#b&'""&"2r2`6&""""""""""""""!"""'"""!"""&"b"&"""b""#"""b"""b""""&#b""#b"&!a"#""""b"""""7r"r"f&#&2a&f6af6""""""""""&""r#%"#2bg&2b"&""f""""""""" """""""&"""2"""&"""%"b"2# """020b"1"b##"b"13b"1b"0""#3"""" "0"""" 2"1`" 3# #!" ""!"!1!""!"#"#""#32"""""""" ""10""22"# 2"""!2""""""""""""""""!3""!"#2"""""#&!"#""""'"#2'a#!2"&bb&1b"&1"""b&0 r2& a"&# "!b&!a#2"""'# 2!!0"&"""&"""""#'""! 22"7""#2"r"!6"!b"2"p&#" 2"""""""" """2"r"""""0b#"f!"""" 2""02"" "20#f " """"""""""""##"""""" ""2"""!" 3"# " 30 0! " #"0# 0 0# " 2  2 """2"" """#30 1""""""""""""""#!""" "023"r""!"# c"""b""""#""""""""2""""2""2"""b""""""""""""""""""""""""""""""""""""2""#""""b""2"""b"&"b"!2""&!b#""""2""&"""12#2&c"6 23c&#b""""""""""""""""#"""2"# 0&#""'#""""""""""""""""""""""!"2&#""!"&""""""##""#"""#"""""#"&"""2""b&2""""#""2""""""""""#""""""""b""2# 2"33""""""""""""b""""2""#b&"6"02 p&"&b0%p!&610""r"&2# "f!""f" 1b&b2!c00fb210"fcfi` 26i!6i!6c"""b""2"2"p"r#2#"2"b""!b2"219&  03"&2""&3""&36!"&02223""&""#&"3`92"2)""""""2)"" )"21 ""1"2a 3 i)" )" "3:#9  ") "#""a&"#&#"!"!"R!'"b!&"# b3R`0""6""""6"""&#""62""2#3"!""22!6b3b6b&&&b!&&"262 3'""23"bf"c&&"`f&" f"g!000101!"6"b"%"b"&""c3Q1p9b""b""#b"""p# 2##""""b"b1""#"""r"""`"""r#2"2"##""1# 9s# ""#"") q"&1#2"" "!2"#!"2""2"" #13 "0"""""""""""0022"&""3!"aaaqcbbr"bc2"c!!b`a6 111 #1#3112"""#2"""!##b&""b""b""""""#333" ""f 2f#""a""&2"1f""0f 2"b"""f&'"f02f&6"`2&"!&" """3'"#0a"&"&#!0 1q00'##b'""b"b"&"3&"""""3f""#&"&#"""2""2""""2"b"00b """"##2&b b"#&r""&b22""6bb"""`b20p"bcb"ccb2"#b"acb"b`b"""a" '"b!32b&""#&&c"2"b&&6"&"c2b2c#&"#"f1!3v1"b'bbf"%"""&"b"2"b"!1c!!!a "#a%"""&&""2&""33""%&#"&&"&2 &&2"&&2#&#)&12"""#ab`c1b#b#"cc"b"b"""1 `a31g"""b2""f2"b&"b"""pr"c3s3b"b"b#"#""c"0a&0&"3"&2&##2""0!#2#! "12#  )01a1!01"3 " 1!0""2b3"2 "2s3#p" &222b""32&""""b"&#1&3b'22` 6661a602"""b# ##3b""3b""0"2""b"!"``"!""#""#"!2"&'#2"2"2&0""!"""2""" #"" "#3#2310"""0"0#2"#3!  0"3!2!0"!""2&#&" "&!62&b `2&c'&bf"&##"#"2!2'#301!6& "6#""!"&&!"""!"""3 #" "2"3"!"2!""#!")"#"")192*#3"" )09#93 "#1""#"""0"#0c#2"" !`21b1!&2b"&2""&2b"& `b&s#&bb `ab&cc"""#2"&#""&"&'2""60&&1f&2!"2f%&2"&"""2'r"6&2"&`"ff32"bf""""!!"3 "b#3 2 2b2!c2 ""3" !"2#""0 "2"3"""p1100 3#"2#3#!"02!&""32 p"b!#b!2!&31"""!"90! """"#""""000a&&`&0"&6110 ""!0#&b6" `&"&2&q"1b"""b""""2"!b&"cb&ab "#3`#"!b"""b2"#"!"#2b"fv!a"'#&##6##""`  q`b300"#1 "#!"""#!&"###""3#""``b"# `""#b""#"""c3#2`!2b2 1!1c6&&#&2"p6 #c&p"a0 #b""cbf#S#fab'a``afWbaa&!"!b2""#"""b#2"b32c"6""" 1""2""""""""""2"b""#2""b6&"R  +"2" 1")")#"2""""b3b""""""""" 0#3#2&2"!3"7""""2bb&"2r"#b302`0b#b"#7""b&2"c!2"6#3a&a& 0a2"03302" 22"""0# !#" 0""0" "22 ""#3#3'"3" ""#!"!"#!)"##2# !9""2"`"3#202!02""#2f#2 f ""3"&1b""&c#&"&36"&66!!a`2"b!""b"#3"" p2 #a!0`26&#&1""3"3""&#"#3"" )")"23#2`"1"" vb1ca"2a3g```p2g`f"f""b"""br ab"#r""#""c""``r""&6!32"!qb"3" ab2a``b"2&c2&2"""" #" ##""2a3322 "! 02# 3 !"`p"a"`!g3"1 61612`&3!b2`6a ""2"b&s2ab&&1 "&"&"&b#b &2b"&"2&"&#2 2"3#!"""#2""32"#0"22"2 """""3&#1"&2&2&2#!`"b2"2b6#""&"""&#2#2"#" 6b2 &22b2 b  6P``!")# 2#"2!!3! !""!"#!""1""0321"!"""2"2" "#" """13!""""""""""#)"")"!3#33"92#!"20"#3r 2 222"!2"""2""""6 3" # &0""#1"""`1"b7#"b023b6#1b6#3b2"0""""#"""##3""""2#'&"3#2 ""2""&""""""#7"2"'" 0"0"c6"#c&"##6""""""#""332"#b&&&""2""&&6#6&6"671 """&&"""b"&## 6 c" "b#6#"&3b"&#b#b&23"!b& `&2b"& 1"&"2"""# 3""b c"2b2b""c2b"2b"b"b"b2""3&2""2&"&`a#aa#ab3!"2""2"!""03332 2!62!63#!122  3 ##02!!!#!2" "R"""b"&"#2&#c" #b'!b# 1"'!2v" &"3!"c2&"b&"c" #" 2bi"" `cb bcb"""#2b"b"b02"&2b#3"&b2r'"bc"#&b#c"`6a#00"3#&"2""2&2f&2&#"2b"&2f#&"`&2`b!2ab&3b&3`aQbf2cc&&202""#310003p0b&""#&"""&""#"b 6"r``f92 9202#12&&"""&6""&"1ap0`gr!v`!s&#"b2c""6b"b&a`aaaaPb3bb"b&c"c2"""&bc!`cqbc"cbb"b"2bb"3b""a"b2&b&"&b2"0"#2 ""0""0""0""!" 1#)#""2!"221)!29 2#"!2!b#2"b""3"""b"#b`""#! #" "#"#&&2"6!"&2##2#212'"62""#"###22#"3" "&""&"""""""""##"32 3 )2"!3)6"""2"26"p"& 2s&2b36""3"c'b" "#s&a`Q`csbbc)r&bbc&122"6"&"!12"6#)#6"�!"222&"""p""&"b"""`&"""""#""""### "3"2&# """2&"""1"" 0""3"020##"""""&"b""2"""""""2#!#2""0)b&6"""")b&&"""""2""2"""""#3"!)""""" 2!"0q##30 1"# 26 "!"1b&!bb&3 #"! 0""2""""""##32""7&# '#2'&"20""#22""2"!0 2"3#3####"#000""# "#""2"#32"00"""""#02 +  9"))""22)!01!3321"#2 " 2"""!a"1!0#3333""""3"" 2"`0bb`1a 3""")3")## !!3!  !2"102"#1! "  #3"""""""2" ""00!"# " 3"0 " 00"#"1" #"""#c6#a#`"#213"0"0"1!b"r"b##2"2#"##203"#2b"R""b"2"##""#""#3"""""#""&"&#f"""a0 r"22"""""""""""""cb""cf&##&6#f"0b&""b&#""&#""""b""#6""b&"b!""c6"""&"""&""""""&2c"#cf"e"""""""""""%""&&""&2"" """""""#"#3""# ""32b"b2" a1&20#& """""# 3 "2"& "6"0"2""""" 33301"#!""2"2""3"#22""!""2" """ """ ""2232""2"!'!# #2"" 1"""2"""#""2!"""2" " "# 2303!""#!" 3!#""" "#2"""" 2" 2#2#2" "# 239""962"26"&")"#)#"2"""""3"""""""6"""&"" &"##"""""""""""""!)"#" # )11) 0)22"""""3"""""b3""b)""")"""#"""9""")""")"""3"ib&#i""##2"")")3#")"""""""""")#)"""9")"#92)"#" 92)" 2#92"%#b"&#b"2#b"""""""""""""""""""""""&&###1"""&6#"&""""&""3&" 1#6"Rb"02#"0`"&3c2'!b"2#" )b&&"!26)b&)b6&)`66"""&"""6""""#))"")#2)3"")91" #)3" 3 9" ") " 1"""190"")"2"22"" "# ""2""! 0!2 2"#"""#""32""2"" """""02""2"1#2"32!"2#3!"#2!!#"#02 0 !1"""2""2"32""""2#0""2"23##""3"2"2"""" #)3)"9#"#""" 2""2""""""""""""#"#""" !11" !##2 !#2" 2" 2322 2  2#22 # "*!3"2"22" "" ""#"" "2""2"""""3!!"""""""" \ No newline at end of file diff --git a/res/forest.xcf b/res/forest.xcf new file mode 100644 index 0000000000000000000000000000000000000000..56bc6605c3c648fdcfc288c6477e25b5f106ff0e GIT binary patch literal 41048 zcmb`QTdXYUb&#w6>ZgwM6oHJ)`z8sGoXX3=jP8>kO5Ql)cC`f*S7eI2H@nn!M zk!`@1kb(p}A|4Ro)erE3-~k?x5D$O^0YrEJM??uqV#mQAdv0gWZC|^a?^}O$@7`z5 za1%3o@9zFDYps9%>-MkpSD%+(`NA*W`PyeccjvEs?BgFVilY1!f9~>|`2A&mOMXAW z?@{qbKUMtcKVJNWKU=)?=Qls}O7YjeUi_WES^VR_zx_*Jod3!{y!Ctk^26W#Cx7>? zfA{a-{FOI;@XhZ&_;uzS^IHnwCcpEa0i3`5cZ=T{zaqIky?5MG{Jzca_%dXD^s`_3 z!WUlp;#c_`RNVNPFTeDeufFv2cmC=tU;TwUf8tO5nNQnu6hmM6!e?H7>7y@y`IVpF zjs8b3e&wrQ|NKjLzVfBdzw+}x(!cn*mp}WZ&wuI5cV3K_kAC^(pZm<6kH!BV{}H-> z?g`x=zZ3u4{k5Cb#cHvH^ozW&me9UvF|ui@7LTYf*_ z`=9#j{Dt%U+AfE?={+yS3kUDtbMU@Dcz@^M{c!MpaqxaTc)#Mk_;&xbyb-tXe`tEo zOYtG!Z~2ec4<5Wflnk18|D}Jrd&e?9#d}56_3&T%ANlngiYfnn<5TfceB)>HtAF=% zcwha!+`jlye!cN}etrI*=hqj0Grzw0uk!21Kc8QJ|M&9iClzb{`{|4P`X^t^ub=*8 ze*JUr&#!;+Z{^pQzK~zPIMMgD3C`cBbNk<(UVr&t=g&pac1`NLb(89Xr zZYqDfZ944U)XjnsscxDDv%0QqHmOcAEqBz-th-F(s%Pr*T}IS&RpWXwzWac7tkXr+ zb$wg!aDaOZ+;vk9Ro9NQbXJaix9Y~(yN;>T*|=Jb%jK$imoYO5S=4DeR;x`1+0&Bt z=&I(T9#&(UI)<*gj-jijJL`w8ff1<*o|Lcvy2f&ux_T_TS=toC#GdMa?oBrY9QtaQ z4z4O)^>2oL1{OfTS|I1XwY$-52iUf%_MK(SyRfgGH6;@-hH){{KTF%v>19gIvd$wa zw)kQ>^!+Mzn-zmn0($?>QC-=W!wXyCG4QxcRZ1sAKQQLW12#&+y6XGt3Pc62#f0m)E2|1xXG56@IqYN!?Xufc zog?aDCZUJ@irR9~ty6_43WF6lYq;>(pyg_jp`d>?%UHwgsxH$o5s|ubyy#>-i-w$S z*-oQoka{($8aGQea4kV;+s}qgFH_u$l{EhAmqrkdE7tym4--N2G999L=F zvg2oJBw(xIq#IUE%ccSr;X_p?xUge68&Ueio(BH2C5o$p2L7vYHKU+1MkP4AMLV>- zF2|jo?;*0JRR-A$G7TD#7~9mBh||H)gmqeCR{%U@^t%-abkn4E4|RqdudB2?9M(*@ z9~+h0RUW1MmaJr(q_PQEcmm87W~@ACRH`b(B#3Jn;wGy$ENB{b3T2R1B_tu5#hD=< z4l6Mli~^KX1trGW9#oPiJzk~_XcH{Q2@koJeHsURKnmlE77mzhZBBaZ7vgCPuA)%FOl>fft{J5-Is zcBs;b0;Up{qpABL0jUlK1f&i=oh9fQdX;bwNohTkDumsE+jc;m*+A6&YFIhPOZTsid&#d>yn55LNFvPL37y?XT8jiY#akpr0)e`V;s&a)ktOohn0s}nTO4qF0e1`XKDkdDRu`!H9>mj=jj^g1u)U&HpeL%vcZLA6o zr2)={b?$)%m)P}@W@fl63mP%XvnP4mX(uXF-xf1LWFn z;()q88;ZcRgv||dH{dN9KC0F|A!lGjLLrgKZFbYdJ`(BbK)eDm+RVaYDn8PMrDInf zd)K%y#%~~jH@gnJB(7&OwD1|6n6xh41`|;kJr~f|Mv#HhBV@ox$T+>F^NfV|y?wPB zy8bDm)~pSfKtM7Njlp{Xl~BDJ)f6^VQZD;)Tt3U1&)6Mh*5H__F5yel|H5IpuHW}Yz~@EC~&P=302P6nT)GJ zcQzfTn--)5g)nR-ZXnNHVl&tgn@Mbi(~f02s1c`D)m~X;aFG8p@zd! zSkc@)ohb59r**kX$W;NodUym40jDH}*P(S!QfpvNt1fCbP&zx$M$^}sm~ z51>!b`GkvwU$7q#T6N79;zc+$)Pw}^S=z(&m+6#XgAMF) zndU~^rb&0`N^YZ4u{ljgltM7mVT)`&HylaLQ^D@FejMq5MZIwZ^s`9~C$bwIsS%{v zzG0aufTE_y&6#$njC1*mkkP;BkeO(LCFn%uRw+4+F*ZU;&?V^&VaydAK@AYTI2u>5PHsVXvAV5S*RU*P&QqQ^7dda zQ8Jt^?VHtt<8BW3GFb4|;79FMm{Gw9h!>oY`cO1B2Ldo;RSj4qg%N~pX_YEYM_t|T zhO!1iBpe6AglK`d>Q9IQ$%`%JCLv+Z!poIGZdt84JqnhMVij5w}<$eRTaqf`rBdsb{yj&t;{pAQAgPAIwKsa-V78=4X z>;d7%YB}pqiSaAE>I#|}&B>ay;|WV-Fp9@c0&9LA?qjzu+3ZNFW%1W)Hk zMnw({ky8+aQ^6E$kjRWDsv7+<*;MrpM)H^NY|$B4CC@ary8v~ukWHs6UI z&`N;i&J{D0oeMhb1SC6^yUX#CkZ?!~PM+|^?wbJ?+e$>)GtoY$qS*A2b%rxWmgKx} zcGcpHI1!bi_tpwCP2k6(PDxP%6@#STl1O6SnZ~ zktftq1tHSka9r-UWuDZK*;|m=+o|X+HV850z}~MH{Spi@1BR1OVr^3|9~VGcLfsaX zJ7|~HtEH>LqXcbJC&sqNJrKJPTU8k4OOzurb*6+!xL^^nghcJerxyfKu#TuD_cB{| zNGIloAOmZ;@6)uA(2AM5bsWMpOPCmIBK<^^v1|3zhavO`%DKvvWqU-#vnH!RTBkeH z7GX+P5Q6EyvG1DY6I}#89DlE77{W1*!MFCUVd4>SM|)V_jrP#FCN%rVzU5KFAQleR z_v1w|@DnK}Y0KfogU`k~A0S@7BpNV+ng$Zjv>)uw(Qsn=t7fv6UG;&E!vqJI!{#66 z;6m`Q>{`>Lu6ovZpxScc<#cm3)Ie~Klf>gb-5CU4b(Mr`GgYCNxq`c7$ZdWhFa12kad%<+f zK%>h)Z_!SF1ZO{?CtJ^+JMAfW=GfdtETONXhcp~hr3E|5r-LDv#uLoo;Pie%!00g* z8ifXM*A2#cJTkl{xEJ(UV~$n>LO#g>C<1nnz$e3{hC)Aam#3^5^&qXJ5x*JkYhz{* zL#%3+3ll)3LOqBR)*+ahh@ooE+lKrVy^pl@o`04cI%JImWrVmQTHtNFNXvDH4ILe@ zh5c89T1X;e-JD4=Kd`7JkS86nhcjo=1+i?uXegbfAnOoB*WcrKO?=7^XA>o$1T|8F zcwB+$Nfs>do&Z|5HRlqBw8TvesYoWuz%3~a0)(-p3JAMLvF!Q?eJX6=#R5zN`E%15 z&LwpiDe`%LhQ(gts%o6Yc9=J+HracV*Y&(#(~Hf*Zs8pkGklL+z3S%}+##8>)ya}b zI|O?m1U(!gh<2rSH{7baB~(12e>9B-18yHcUoVMwR~|mrq;hYtDu{xkE7@?~BQITd zylb@xbWT`ui#Bm4Y0f#;)t5@xKvE*F8aKxGs3PTLQM|aZ* zOHAer-T{FavRNHJab`E1KwOZ9wR}upbrgH{zoA-0Cbwxz8N(-h_>)($=aG>*0KJ)!10907nMR1+WtpXGw_^2fh=(YTCh* z_f=;Doz@pQb$Z_NfP^UT`Y-FDBLOVN+FXmmweMWh$ytemHclEtu-x}BZCH|{pesyY zL&|vv@|-d{wgcaWjT}xFw*QR5^h%fG+ZRJc%>50<%xy!IZV*<3pK4HtS@KbLr zJa-a`tPy=;jF@+t=XGORQhYQ@yWZ1vBoH~3XtCJs>yxMvSUtU(v%_Nvwp>0v4SzJ@ zXjf$FkZ|J63}-jIAsZUJt zJx3b!n#3X{0}g*4Z71d&#k~d1mkINng-q0*o(-7<^Gbg)w&;?LJLF_lG1=hVjXP*~ z*D*Rz(yJUbmz-ZsBV2*RoUF{%axUf03Qlfn7q!IUQEb5c`WEj*gIW*ghLK3yx1E_Tzd- z!#SPf5v`!1x_SkQiunI=YctNDFt&lfcHchLlY_`|RZs1?wypZ0AS8U5V#(zeghZ7( zn(-MJv3+AjJi5g}R$e6Q&Ni@dF`oYa#6+^bkl=ZbQnL zF1c`nzYz}C^l@l`1`7GHuGnUZvROU}*d-0mXh zw?liQn@_FYXW6xqQ{@!sA=!Hi)GYTsR0&B~cF{x3o=f^TkCLs#t8?sX$rw+R&TB67 zQN_%@HpZA$Uj)XMs|TF1xkV!Xg<$oq<>1G`P(ryj7;eezk_JR_7{W40UQQs+NK0`~ z0O8&bA+ZZtXNhwMyWQ0n0Fh;F0N92nZUMkGALJRWi0r9s6+uZs!TGtI0Uwzg19Er5 zIa|G$ySLyB5Zoj&X~wPrz!5Hx3^yZM5F-KmcBKJ{;g`vE@&=bvJh;X|jiX{&pF=TO z2`{O1j3=`nTLBk>`9gOH%}6J*!G#gXhfOjuMc7hxBkzOzD?pr(trQ_Fnf8zL5GojH zeCU8w3hu4?t+KJh^TxCl86ReE=^6N?MuSI=?I*Q}xscAXp3~`2ED(%ygNYqzr`BJA zgYqX_y>t=Kh{AGcq}NS{s<<5mM>%tDt7BC745);N^sShNBD1cxi8@L1h*mUNsN9G2 z`lcf;IA11GnXs}f(<6qkR9M4rPNv34HSxTOsulTI5L!Z}s1|&*)4N+M80mc$M#&0AM606%jOf@F#Mp}|VINqFSIs-aNktr%Ey7l?plWdyTqo=eaK zI1Z_t#*+z;tBb7Rl=18+YvI^vzPUCtTd!HZhGjQH3+|;^4$v(ZVnTF+uNrK*X&3i+ zTG42rsPqxp$6XyV3-E4M&Yb{o2DoOlt2J-KBr!Q@9k(S+pkeh98#cJ&>JZq#xMMYH z06WoDPUB94aFv-`1-v)YHV>g89SR=MC^1#*WhPl=YKO~>*bZnyF5DtMB0ey1>R;Oc zM_3n4B36!C2=9$Yy+xM+IgsNBNzfn`V8?k7Lt3T z>WIXhK)!sW!oe5?%}|5S0R>%PIc4((b++9=UgakXX8FL+qc4H0`EWt$4Usq_U^}to z81uID+NdXpKgepq(V!rSqP$TT%_7SLuRgMNa_%RBWbw{A!XRYsfynKVp$LzwJOd-R zf#jyj@vx<|U}fmL061Qm-`EpZ%V6}Dvk`~;#(F5xU@lMBM8n)-AnwNudehP?RK~ec zyx#Q^E89zOOc=`SgU;kZ(5rX(&J1OC%Gcf}(81>Uq;@%5P&XjLz?nxqmcR+TyAipZ z3sk%*q+B%%i=fq-AXiEkRL`z@Tazrg_R4(#67W}Do_`5jz=+&NUI&;B$0k#rT)VQI zNR=2=fz2ML5Y$<>;q*klJa-XbGL7kDuM=|i000M2aXAmsJs1|yxtp#*?o8KO>9v}+gTy`)i)p*4eg+h2 zpAuLojrgn^danZTF_KHW-Y39jY)N%+wB<|_PLbg(b}Bey+B31RgVl1m$8$9xy)R_u z0J^k_6k`*6QI@*7Uo<{F^jOfM|Ie4j-Dypz%neoHieCJ!Ey8L zS_h|AO;N>_glpQ9NuvK*c#=$1)R$8fFy4eW!y2|M5!I1N7<7T?VyP)F8ShLE2{ z;v2&Ma`<7d60(Qe3I0MP=B4@sZ;9yPi?@(I$Zzg|5UW63 z5J-P0My5~3sGr0RQ{~5rV;+Bka8OpH=Eu#|hZgeIK+`Dr!vTO5J4I z4jVZp9SlPh$(5#4D$6Aa+x6y#G)|GSFKO8d`b+ob6sFRmR9h2YXj?f&`L>@$6BHpgGo}>H2SmG+LjbU zSIeibwT-NK=`boqeMu!@vFxAQjX>>ppP$f8wf|Z-teP*puDaMmknlMR+(V@7aqaU# ze_#;emK5GIEARbrN5mR385Cp&Fwa`J<&G444WGzjQNLaF&r`+l4nSe$o6>Rsc;3ks zkLJw!Y8pdwu=h3*r5mc*%l=M4R?C~w zBbm~5Ig($ezC7OaF%2eIaq3y8i|LNJU@-=#s*#IUid16tPm_@6UI)NB^7dFEUG{>K zOZSwi{MtgHz;KK$O_x3@Wu<+-Z?>%5EuIf~;dac}?0YCx_1&{9(SiZDLBK0Pi-yMD zODH_>g*{(TG3vS4j?USF!DhrwRCG(K+flB7+5s1uDBK@WxzCM!V(Kx7DVU(-+y~^- zc43L0z0V)Z=o+XL90VOtW+3}PrUz&oyuE=(Fi=3+J?0F0~_+(_llXB7*E%i^$O zMhA5=_=)FRRMeeVJBIs+ogxFdKyho*j|;9KUl77*(~pFKR4%-n!T!ON@j2F4F3w1N zQ7_XZu({8>=EXV5GU{=SH709;i^YxZhH{E8q~g0Eg5!Y%US?)I7bF)^qIVQrX2hUK z2()!y>?+=exF3w?{MBMDOKtvBV4; zC|rG_jAeO$Ppl(>MXnh1gn?O|uWtJJ=;YuR67`-W!GJU(g34ylya zI%YMx4tIovQ}FhxcyxjlUC8&;hQs4Da=q(h36l-N!aUwiahJ9k zF;_m2RrR~KSO~Zp)h?*fQza({e611TeykBQOvU(WAcwGFLUYx)LwwZ|XEmt_w&ix2 zHe)WK9!zcmcWygEfJ96!#oW|Yqr;-nYzJwf+L4%cZY^_T)zMcSEg3tkN8N(}c{J5TaZIJ#bv!O!`K zLd8u=Z*lT-tzzS8=^m|Q6jr1e9I+cR(3qiaDdR|=C0tH1giw_Ka6BXl8u_~Ku~aoav4;q+rNC@p#6B`BO&4zj z=YtxsiXPmYsPdg0@?Bn%V%j@81V>~u^<)}I$C)C-z037L1h~V#C`+rAIWR zGl2dpGI$<1?seolS^xLF<3uc+p-#I;DA=*i1lv_}k7`Hk|E}*yIdGCW8S2%DFAN); zcFc9at5zS(JSOMJR}<_<9=4(BZp2lSQ`<>K4qMGD%=aUyHPumWYr*ZE5r<|0jS?Q0 zGOsm3;QvF5#)>3|0-M1ZCHbs9b+elM36ZP0JaOk9Z7>hHS^Y#cat}2b*enOkdq{0w zuI{=<)G5UHdC7Vb; z>{|0R9ZGTRnK>3A%z!&R=udNQw-k2OuCwD_=+u^J@IIzDIgF5ZP^~ob5F%~6xjcLu z=Gd5n{3t!4=VVm!^_sYS%ZS`(Jz`C+V~pC*VV}>PN8uuOd7T0e5y(i+lLUEWR+=Av zbGguUn4LEP!(^%erp+JnF0$kManKulBY9|zWEN=Z-ZF$Mi)_B>e^$V;*AkF)fTygN z3Bw-c843p^tH^+x;f?;BbUzgxNh6AG6p3q!(GF^&#&Hzo3#zRa6(o^9T&La)*hk){ zUy#kWqC?MuA^`JKZqklyX zUqn5l$ZH^xJQ6`Qz>*FnqXE3ud92>>BoG}W`7F=zfQ(uGxfL~MEFcrPfkb$RA*f~+ z;h1AdU?4Z;aQ2bDT)^AHQ2Q^C2k#NIF@|i8V97QGN6FF!JNY12e1w?kknY;gEUG|q z$9gPf1(#tdFyt|reFj~)3)~Tirl59~&aKJ_XkZM*Fz_DYFDq-a`s&@6THP=0sE+70XJUyh0qoe_Xztp*ghEgNnL_s?M0njA`!pczT zzMu**l6~6LFy@3^w3=us(4|^jw0_JRi?&p9feXMlBa_Npl8gaB83-}4kgX`Vua|Wp z8ORnSw6XyP0v6sl{%yG_mS9h?*2RO1Jx2O@8?dPw&)-$w0vNAde@BT<}d1v4w79S;tcq%yF7b3>lZ9l11H@$3(mlqRHL* z#7q6aEuh}XTadv3aWIn2poV8TI;zf?3{)Y1;Rw4C#Kjhb0$_!z0tEMoNckTK4mfhW zFa?PYQgjo=41U?Kh~=s%;-ezM0_&NK4mn5VGXoems3%%0^yC7wO0^Q0minyk9f$lw z|J-D8FtP;(5{C9t+_dJ3!E9kGYRXQ*QrWh4!)S;{n&5l3D~i1PdM{*-!46?yT4NNn zwUQ%+N)Iha75W*Y&>cv0y7-x;xH4D1qAc1!EP4!8d?z^SzV?a!HTptH(=9(3fXqIf zx!7s$>6A0diBHM6;`*kxOppj}^lP^q6XaL{b_NJ{(l<{R1tnTAZP_SV89AuNa0=vf z&&PRHJ(Jf#b5L)gpw!+Kd_%!iXRtxFMjAiDV!USH7uclryeeOWieB>7(lt=gB~_vR z2#r>WVNEdW_gO^JOXzesL8SV}WH5v=6GQGzfNk|5y7dG!xxIgt(q^UVYSXU#{;K`VaC;z9KK zZD_!pm6rv$QQ}IB=Ovx)<(9jDW${|Y_whN&X5KKTWH>`kScyG_6(z896QpQM5ZPWp zvV&P$DLC4;#nbTI7%X}CCE&QjulIWL`XZ$*g?Wc(cz=@ms zXy?m_h{WdBx#;f$l5N&-d<3GL+6(~rW(*=C;oRc)29GC?)0`Vbge5WF$aM=(zH$G6 z5#e%q8bJD@ULWr>Mq|Zo_mRM~?LG$dBcjROTDTA*@gg%+T=7bn69ge~(Vhd#H5E!p zlYD=(52uR2D9k57jLPUZ=1tG9PT$)R&(fAZ8tg-C$snI-sScxED86 zn4q+iYr#y64HY<~rhF!z9QQJMZm!cah`%etf*WJTEufmo0LNp;#Rb$tBOQ(gv+4|e zl4@ZnM3-88#%v-P-rZEA0)Sg+We-)uw1?qkF9pPd7%}FA%S2ZAyj$q)l~6~_FCH@w z%YHm`)iLpHBnX#Zt(8t0qZF51E`ffjDY={DQ|N|}Tys&v8F=n!f2?bogkcWWk%)xD z2OQ(6D#8bse4^8c!2m1`XSWc}BVu}Vo?_N-&9i%iNPQp9lbDMG8{J^hEqFp8nmOnDcI9m$SsSZ-iZbDq`(%Vvah8Or814p(G z;!YV6+#%=)M23ts00}OzuD2NKXg>1;I9JAxTmK-xjh65L^n@q&qF?x`I=voafXFMf z#a|f=Iu>hSLMRr|2-M&__d%@-jaWJY*btyv@6F%{7mZ1ku)KbGpn%{mWEk%w@Ijm; z-M$DTBxX8*DPC;i^vRPF7Mw+?55Y^va_OOz zX(s;^zrR%c3qJi}9r35QZgK2W^8*)xteA22mIUw-^~=cHqXAZSsh!@k(S$5UokSd2 za$CG`GUsYGnE-NI)+`fW%5#Hyr^!-_^YJ7^f15U^4KrTm`;U<~Z^`H$_gqLL_sAE2 z`sEK~e>?N^JWA&asRte`;8F};z12cf;?tqYwzTm4)P)_1?SQ7by6S#$;fv&aBHQR@l-A3yUJNRqXu;eelj*| z$|c;9_PZ;XhJ#={&XRXE58q&pA;@LSXsKcnQ2COJzM>J;!*Nrr#Dk{R3ph-Vp#Weh zK7kJ`qX(b-Aqxr}C0`^2Lh70cm@S{@{8Fx#BWQj=#L2f78CacE9R*de!tj85e)5k6 zkvk=W=5x_za{FgG?x09;;&KJDOQsKOE6cPN%Tm5!(A&~9rTVUwJ~buD}ZgSZjQX4ABgvvl8K z**F6;MuU}5AbdwFZ5TMcNEj$gDHFIK%-`%{-(ubVh>dZr%jN9J=AFq2ekYITP1|tl zZcFn3q)dpAh#7FvBnQxWhvyd=-Q0xa4LcQU@W`%52y{+~^=W}K(;XV$$!h$=&0z); z=F}YGc?Sr=Fb$xwAQL!~lVWFt#$iAn@Pk`q5O4AEzGJM6{GAyv_D9iV^vT zlby35M4!ehT1bbwVpcuJ zaGT|ZQwcbIK@w9jn@-5GzmL5!cq262RP*;hZO}Kp5Kfful~}(0MpwqSJ_Gdyei!MK zQ=x)Q=ZBdV%bv?uXly=|X@j3<4(V4a0!Cv z(uwC(Ob4d{J|F8Lks1bqoFghHNlu5*zAa!Rdc`T3^>UazVTcFWlK7AykfSnFi5zT8 z^jnqWY!g*UZe8)-j}0F1Npf%C*XU@?aa`4~@s ztsq-2&aIDhK)4MCb1xnk9szmE1G7m|j3@8~25s~3YOc&~q}PLZ?HL{VaBQp(ca0;l zo5KnG^X{il*YG_D+-r&nF%D7>79e)s8p~mgzb2upona_68%xOQe)dy_*7mmQy|A z7*-8r9*KED&j8W#`*fUWhKA6fz?{W-kHdy$&4eBS0GQQJ2*hbIW6K>+=4<@)1BfF~ zbxJavqY${rjT#d0y`7O$z{1V=mJ7P6eP}adtQx5SMxuDKgGtck^HpKFa4s})lp)ib z4I&StK|8?1O5T|UbMoqI5{%$8%_vP|T;QzBC_VEaN4f=u>+d7u?6$F~ zcy0)k&Ey<>#5A~^YF(Vd0|Ju;0+&0H9UzN>R|rpz*1;8c$zb2gJQw1f@4U*$#L$Z` zbB*qtM?}~FHN0bj9?jPsJ3WI3P!Ha53th0X&chYeGe(2c_{QU}i4Z5d{k+rpxk5fM z4&rGgBadq|2t)pS#F2H2m+SV>^?rIussP-*!gItPJ{6F{$-z(f4FicEGr(I+wdP_% zD#Xq*9=P@4;s4|(Z+9^X-0#ONlb*L>gS1saGG4GzlHu zZksmbA(#okW1ZS|cEjfc;T$YCjjGt1x`3bb%}^P??A}DRy>6VsFK*iIp{5M$qL5Phe0;ieXL1G3?K;y&z#9cn?q?l99f=hne#5sgfG}SoP}oAP zERu&FM%_=r00di@i^@#X0A@$QTatccZFr+WaNi@Rr%R^Ek~&`#=v&stPgLrB&XDhL zAa&{EI2;}IG1iRtgY*yViPkROc+$*=tZeS8+6WtnEW3}S7KpU?S^$>pCLy>6Tdx@^ z2WSO>IRO)r71`KRbc45V2oHd4qFl7*rspd`*`qsk>U&Mr4q` z$(oyZ>D z^5c3$Hn|0G7$dO?sKsQ{&3P3r(nR?@_Pb#jvdF+uFA?=c7xYjn!QtRYZ#uu`tfed% zi7_X4KtomEwo)=>--|2P6NzE1m#IpRdU65g;mcx^eaJd&gXUW1NUeU*&G3LL4Y5yD z@0AWohtzQ8amm2StWq1EIrb<7!{^!aC%#UBNmO2afv57-g@wa`9@fF(?~L&XkUlnO znCP4Qp%@i1w@o|9K)sp5Eq5|AtU&t7J>c=#5Jtx7=FndUa zi*cdF73Zj$F85Qv6dLNzyHmhKkkw*?8->V|zI>b1lne_8Vd=LZ62Wlf01S7+r?I6- z2a!gOqN?4PWeAg*7H|Ze5z!Y&*@a07ob{P0COs{LHAOQk%J)u@q||G|>N!z}jaYSP zH3G%Rl=C}UAgK}(DyItZUUx*aV$L8WL@5SSoDX<|C{%aYV0eUqj!2pT@8Q(0-IWD# z)~w>~`}z1w#lPW+ovQE{&s`hFkSU0BKL=X>DKZW$mG(4F_@-mvE=`On3!oLc8Wb;D z$P17)z<5w7e}fTH9r;LgG3bBW6arua4I|i$@~-y-L`h*fQ1Yf)3r3{qJpT|{%SUn% z7m~(nSy0%p%wF8f<#r)OiX&*noLB~D{VbPn#E^H4<2cKFVjJdDr$lR*#=@a(Q|9~y zl(E_Oum~Wo_$Sz0(2Vi003H=6_nMYek`G6^m|Fo!)}`v(Dxh1&5}6^v4CEMAl$~_j z7=FsMOMt0LxJ1c5DCIH$V#@SXo%mOxdGUe|b9u`&pO=0N6;@;@ql1U9=bQ~R`Gy&)N?`M##i5E8r#5Jkbt=(jAGLu4rB0^@8lO8 z=Q!k=;v!H7WSxg+B$v|uZF1zF( z&ybiicmOOm^B&P*+-3j)$Y*{L0Fz|3Kj{3rlXO)nreCMy2-0SHx6 zs@p0bI8?sTL_21ZWdoE>;xvVxWvXEuoIn?SRlyAv|DP$Fd3Wx)fi3{>$alrAUqQG3(=IWr5k3i*f@w==>&dN2~c!3+N#vfQROW%RXOlF@E z4b_U>(c_>l4CSCHW$^cP_z(nvhKa#UR(8oIBZfPRaE2f#x;R*9jRiwUD!(5L2PhK( z2$=zZ0k8%JYa`)Jg=LFrq=mr(=|)0=lwfs<7Ff(2!x^22)dOHj+lf*rJ9yq*3-<;K zb}DEUPNYuSo#eOGRwRVgYKdX?dB#CMU8i}elJEeWL7Boh)AG8tm)dkf;LzykeChoqRZj`s#Ku-#mC`z;~1JAVLVu&WL4=+VDk#2+zcgv zStQ=1Rff0ezp-o%jZ%&|f#=MNzrvu+O;AA)BNzj7q6)$!zI$J*kudtq)4DK04A~o} zyNqGc*dBL_|5N%cMz~D>5GsjTHGn9$OBGYOxZM``{Ois>a4s9|ijnMp1}4v`VHcEd zNL0a~T#1K(tJ&F9iC=w0N;PI4CK!`{u&@X*;+qMRUe$&4Kkn?U;5i};&G3!&z-n-X z(!&yjRBJ81`*H|4{Do;s$y*>}ZK1EmaPd=6XG!UISU;WY4dkkGK}`V2Z`F$Ck;37I zxkBzBA)(CGiDp%qvSXM^`e2M2;5R|g!EKyrS1hynQPMhJIEavTx_g5$c02D*!lF4RGW?i zEQFO~CUg>XI4j}FT@mkq;OnvBKHdAVX4|k$^xb8O>Y8IdM$|Yk#8ueC@NEe7yeWu z1-4E$uaHjeK^S%iv#AsZj}?3NYjUotGIvjPQ(0qKn>VZ6&59+uq0)zR5SFmR;yyu_ zgJp>287hSu@_9P4#HG4*=pQLnB_mEu#w~_sx}ex~#0kOINs)bs*$`HqqIf8%6IH26 zxSbk7{v$S#ek>7b8tu4eL4x4d;JF$ERZ6t>N5>9MgKXN6Glh_Ou0BFB&aJPxOa=p9 zN@Ib%FwGn+ogBr=!c2#A=-|9T7tP?)6im#E#A_{4yPlUqD z+G)Wtw)cd8xH$Hk^iNf62#vLdmDi5sI9Z@z2W^zC<(-On$(8{gx4^K1oFO0Il(kM( zWMUlFt0e4!5|UszFlIne@ac8rROdm9Lm3gxP_CkYh-HKtv2?zyjC;8XT9k}<_dwZq zjHE}-20^kaQoZdo00U4l;X*2Q3W%X;R5Ng*k+KpPoK~dVC|rn!B_HS_PajD{jRxYG zP2DD>)KT)7TXWK=^HEv!`=mBdCpC0ND6c-VtzMF#ySM<7P29$h(?uNM0+Wdgs8`eQ zGA>MpvriQ^(uFc1^prv;3k;HSlmo*ZS$#(YdZ+zv%NVy>pe~EEYH^N7hPhSxkKA>T zX7x@^X^!~->vhx$h(65Kx}Wly=gBk{=`NoLC+W+;0rv*o0Af0%AWG6bOaDm?2-HC4 z-vaaq14)XyMDwcoao*ApuPQIX_ITV*1qKz+)gzcB8_=x;FJTD>Dp_LA zj3!LzTihjsAqaX1JKQ1^3t7_0ysB4%!uY{|w&3u3Nf-jmbnK_r8`l3iTg5RFFv<(B zMn3K7ZC5px6pMrr@18zJqIDmS3t*ckaJEN&1hK|3h< zRnkt?4d(Il22dc`QbxbSM?prP zZqH3*dg5O=mo!T=qCP25H8~B3)q%45jUYjYh?DF??hzfBq=Yd`@)RG&a#vYAe&&i^ z6qDp2ztk10;vpEE&mU3o>o(}q?kki|GYALA19>ac#A@hiChg5~>sG16*kfM;p%?D&bnXj7x$MuZU;ZKsBV~Mn|4Bg)yMY&J@~0GZ_?A@&^u> z1CptF>l{jw;gWK>ANlKD^e11SQC=YEwtA}LhflAE?GF(Gmi$xfgOxEQB+3vfjtkr- zf^6FeF=B53fib3ulZ`b>0c$k~-}48225aVgO)inMzZ!ws$}gWE2^mqrn5>L!p+DuU zohg7&T*!ITNnl|VYj7xkICa<`ljR>&l3h@u6bAVTN_{+N`7C8-tWV_#VQoC(_kER(?MB^vWEGNsH{?=fMos<)a` zt(w6b=rC`}4HFHF;WqN62Z+{zWD46Pbm*3sjk5 zK+X?f{jq=S%(!mg*C=Q6o?)=6xk8G$`;>;OxRL%kq z`{{d{%t}Lw7Si$<7a7F&0LZd5m`Uuxj_@8bQgP~n_#gIj>?#PqoaWI%`asRP@F6bG zcS1LI(NjVp$*A&;Uh3&oL7B$JgR3mQ?F_MM+xedt_d;B*Hi9dT#mt7?dRi_E5WPSb zP?#!pT82my1Qox9n0q>8wJ?H-$^{E?GUGwu>kl*)yt?-?g%|0;;i|>*ONRu3K*VCVs9#3H|;E=If%8Ud-g77?I-%z}hKSC!un+FWhctvKBg zYNYfnHA`@crDWi@c;j>#sGyU2fMWrYuHSa3E0Fo986Cz+L6De3ls)jWWB);lnPa17 z%ePDhukE-yC)1`Z1lchjAdZYjCsoXy;Uk_P+h@#!QsCjS0sKK~n5^MpGNM-KUt(v$ zq1*j7W)Kn?0bch7>iKM91hir#cMdslbqbJQQ?h6eG9-nxbWsc?$8e%p9wc>=M;+Lu z__`X-_HIke3eB_>z`};ofxy@Mii%mh0u)n4(C&M>r3yWkl>sxh!gwfiyWqAJ@j^cJ zo0n9_1VWik&PjayI|k@V;3^BQPe2a?*yLRK(%YTr+gv8R^Z+gG!~v3a7t*9ZgXWcg zY|vr(u+3#KLdOFF;3El!W9%sh zR%%d6PTmjxF$u|Vn<|;Wy<;aRul6WYqz6Qysz=!NEvBlRm^h?Z=#VYeJpty$Xh(MQ z@f_mJTJvB8O6x3w*eqXB&SNMygmjLkDO%)&+=^7i&84{Y?_oI}pwk(8>4<-!4;0dE z#0OVgDRGX`kA9Z+}FCea0%hx zTJ;Q|f#O0`Bq5AZ0SyiUOvQ{;fP`SM!9%7Z3%t&oRz@0c`pTUQngnw;0jIt$$DgN? z31N_I*1Y6jR5Fx7?DG?he)Q@B-+9ZkVs0?>$0N^S`>DQU@hqr|7jg65ys2D(ApS&R z#Ragn+eovhiawA{b_2M`<>$8oDW99G$ zAtS+4M+zbm3j=S70YDqir=p~1Y@BMxjoOIXDR0I9z1qwuU^j1K9<)7*34tR@Tq5FYm_0#KiAR-!rd)9kYFW7Fe-4?!WgaUqXBm5`j{$_TPeVz#1}b*o zRjgJR7cH@#Q9eTuI)*|-OvM8xp{06184Yc-@)1ms#IPGV%!*X5=w4ONLtb105j4!> ze_xF2zsJr;Lok)`(~rQv=bmbm71-daPuJm^^d@ZmZ|c3FgI?d|xrXHV7%$tHg&Jf!*K*hGQ_e^K_18p`C4AG5GIb>+^GNafnYlCbs)|80^(e5389>Qt4 zr5l7CB2~pYtWP8t^I?!LG;l9jg150XG2XzD*B3Y#2q0oo9JD{~X7R|4Vs((_8NBzN zML>?@5hfpz$L68E+9^bW@FFBj8kirqmc$dMMPAiUR?55Yv7dQEz!#$fBMSg$>@+!I zaIyS6kh?74;D(oy01aArsw62POf*78Lm5B+~LWCZ7pxJzHZiZYy1BRk zYSyLLzhra3$+3zLP_j=HG0Gau+B*5hsHvC*)GIyA%7u zBC`~>q2ZQ?L<;bDF=A$mxE_pv!EUh0w@$H5$bX-f&D0&j(Ug!}?{BHP7Hl7(e(=6CreHCg>am;etu& zzw)c{1n&gNPiVIk&<8@8fi2>_kx(4+r_~r@hd9A>*$bBBZ7Vlb)Xao@7I3#itj(~n zPzd+N(oTs>uF5ES%B(X@1hZ(-8ZI*##=uVQQ!#-5eN_yQxGLwtQt>c&sQdFWlUBg{ zSPWfbrCT<_td2s*%;{3FPBqx6#f}^n{AQiz>_cMRkwk7)bV@R$W4(;w;FYC6AQ7=q z4pQMDT*l@nE|M1_5vGuPPdS-Q@k|D5R4zF4fhR|Z&2#XNRf33~3ZPzj2?gPkO!j%l z_r}o%m*4~BTb>2EujIjC$&+=MU!}mKobnkAW=LKN0USP``mYwAd(4tSbs6jHWn1srEBBzlXrN$jxVBqoRu=aV z5!ud+JP#8EJpas_YWBYUh4#Wvsru+FG?dfrN}UfKo0kS@ERw~iK>D&*_wq1 z4N}@hIOvd1P)UX)!Ey1B)C&apY>;Iwd`Q7pO8B6$IFvMw!d&2B7nwko0m{6p|hl2V~t4BLQ$-BH|Vb=LjfAL4tD}A7JDF!tV?#9|$Va z8dqUmC`$^t*KR>`usy&28X&@dL19qu+^n-0=g=2AfQDRx!|yo)2ep}dFcaHTSy~Jk zdX=rqi<4UniXVpOqcoGH(^RV%y{Yae|8`{8gGG9xI{hHF33j_~p=h~vFjvVHYW3lD znH;vmYn=d;aDIX59znI;LSwRmg;*M5u`0L#As%s&A}7YdREo8mfmI9h{g`N!!jjlE zteG$wBB5_Wv^VKoE!zd#`IK+=d&gMg&Kym08IO1KhM6fNk(1hos8&fGL0CExzT0FozQ?F|~XoCD1bG!+s z>KgBp4G|^i_?9;iR-Ck45{OCjP=bu08TI303hfY!M`Rra-JFbg!~xT@OYWH1(Ak6! zyD(paxa!#`u_1A4IpJQYr)PFKsO-N9;s{z48AKB-q+MVTr!bdAma8Pc!yvLVkQU^c zi8RPy7&vu30K-KwVdmio$nFow80NYF6xg_Z8XQ%GJm!H;21G3mim<$J>NWlJx*ohV~Wn;q9YycMcqd3F@&B}RXsT#>1Y8|nL6i+~N;vB5EthgplF Z_y)gU-&8FKLL^I&-4HQ literal 0 HcmV?d00001 diff --git a/res/haohmaru.data b/res/haohmaru.data new file mode 100644 index 0000000000000000000000000000000000000000..98478aeae2539d82811197eac64fa5c946b80026 GIT binary patch literal 13728 zcmeI2>yq*?4n)a?kPFQB{%^adTZ#z`1Or=J`(s=+!4O-=Ez7b4b2$8!KM(wQ;Lihp z9{BUXp9lVrJRNZ*FSAX4^6SREMNuj-bcJ*WOVA6BDfO7cp`qNM zlGEIefBXJzN_2*FJQf#5W%b|IeAYjtsJAqMvZ2O76xX!8effeC<|WFg5R}v{g8GLP zN5MMfD=1dQ@xj{oh++m3q#`|*ibB;d&L@K}_g5orb|nDQ=|~@mPk!ozLsun!-9A;D{88MnG$PTbbsi%k4pUeOL#GR`!Z) z4rAZ9r@pnMejbOeTOx1A>^F&t4(}k;R=q@_3@{QyEX?D)TrMDjLZjgD!S1H_cmV2! z1#_CVHO7vc&u1_OX5iwKdnXznVr~>}l?!)@5LsHgVxhE~p+2;>cykp)T_*(BgNn8$H$ zh`y#fO+sOvloYajrU!#AKe zIKqg->Y?Da&hB$mNEYFKUZ+tYwO?I#*o*AYLwmc;{R)W9AuvdrM|N}$T&yQ?%rZ!) z;uP{0$I&fCqqgog;f33sasweCDI!qc^H{k@FEx&r&_yVWEvE!F9D+{v2O@yK z8O(XqLV}^m2~e@MSBa2IPDb5@WWY|xxu*r=>B*B1+@?8;11McqC&+SEJ$8K4ke>l@ zx&jp|NxJYF$Qg`;S&#+nJRWZZZa6u?U@k{6K3w%}3*&tDf)!Jlj(o?DP~o^A z(nLh&w=INhai6tyo)a3T!CZS0?zT^+|sp*04Y78abDEXVm#tH)U36bAXvoC!f+aV8%eIg99^t)OeIL_r`aN^^jg!a3A9 z?zbL%(lwLzxxn=H7%4}E)f1fI3y#K#0|5m`iXtZ{v#M~i7e~u>QQ*Y%zoUmsr% zD!psUh9krRiAO8)jfy}lOT#+;vt z49Z{IPLrp{GRZaH6mv}Jcv56LMNktQU=VPbyoocv!8i_(!r=k{7)sNy??}@rW=wLH z<%dRJkO(&n1jZl|wh_T0%TR>j>ERoYb{r^{gCe~Xr=PT$GW`u8Fu0RepM!2O7)nkX zoMmDDplH_Oap*JGZ7~wHa(Z)mgy=ZHoF#`ApMVNR3`$_|Ti+53eVZIeh4Trhu|oo} z!89DF;BYORt_#1p)w_yvRod|dqw`gA+AT+6pCfwHbp`W-4NTZ+!Yq>0DDQ0aC?JDF zOunP&iiwd1<^ji(=oKc8ChF&>9<&B)^z*tA2{{e>0$1b^(TeLBL5j)t)u0h&Aq5&7PObvZ}%MV@{Vo%Pw`GDN}QFVj+@`?KCtr;!K8xo)8p^ zH7UH*fXG=`rbv`>bj*bOm8Nev0^JPEvoEuLRRFZbI(2%4=uhibs6Bcy*fL%De*>culh5hvSG08d3R46bSa`tsUuKHqLS zs){8afJtRC5ENt;&M#CAM+fQa$Q%X%N=$-y3fXdQJ5_NsMcZO?^ejJBAP7;iwIOYL zRGu84aMCvB3#X87C`%>haH}U=7v?3xoTzY3NgsjCS)(*o>g}WF=IP@%hm}+(DCFF5 z;t{uq*i?RTV!>`&JgtVD%XRT+X+Cdl($#NpNOTp7gwdd`9IcoNj^jr?l~JFzFE{vI z%q2O3P|EH5N^u;O9HBU`k3Mml4L!kNm$|pTdB3Jpb7F|%yaeT8R&iD^drN{wsR=#l z3m;!LV|i5NYfc?3*xuHnW8tHg@!8s{xXmmdlb(0tjyRM&d^G&9q$k9k$K4gA%{BGp zY3vOS7@c#68jeqnBCTh>U5@?-gAKrX^fOr;r+2<4D0hG5Xs{ xS(PTAHv=}t^V(dqQ2NFF+s?VuNr@I-`@l3n_9j>{l?B;-~Y7-{sUEjd{F=Z literal 0 HcmV?d00001 diff --git a/res/haohmaru.data.pal b/res/haohmaru.data.pal new file mode 100644 index 0000000000000000000000000000000000000000..297630ed8e536cb31a23eb4eee47056e8cfc110c GIT binary patch literal 48 zcmV-00MGvb{|Nv908#(|AP^v%002QLIdUlw{xKk|QXrdpV%>T<%&d$4#Ebsr#Qyc= G{`K`;n-#wR literal 0 HcmV?d00001 diff --git a/res/haohmaru.xcf b/res/haohmaru.xcf new file mode 100644 index 0000000000000000000000000000000000000000..19a2b55dd365ae43a8bb6bc1cd723b538142ae30 GIT binary patch literal 5416 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.vram.u32[(0 / 4)], 0, plane_offset(plane_a)); diff --git a/scsp/sound_cpu__midi.cpp b/scsp/sound_cpu__midi.cpp index f88de86..4e486c4 100644 --- a/scsp/sound_cpu__midi.cpp +++ b/scsp/sound_cpu__midi.cpp @@ -240,7 +240,7 @@ void v_blank_in_int() scu.reg.IMS = ~(IMS__SMPC | IMS__V_BLANK_IN); // flip planes; - vdp2.reg.MPABN0 = MPABN0__N0MPB(0) | MPABN0__N0MPA(plane_a + plane_ix); + vdp2.reg.MPCDN0 = MPCDN0__N0MPB(0) | MPCDN0__N0MPA(plane_a + plane_ix); //plane_ix = !plane_ix; // wait at least 300us, as specified in the SMPC manual. @@ -355,8 +355,8 @@ void main() 2-word: value of bit 5-0 * 0x4000 */ vdp2.reg.MPOFN = MPOFN__N0MP(0); // bits 8~6 - vdp2.reg.MPABN0 = MPABN0__N0MPB(0) | MPABN0__N0MPA(plane_a); // bits 5~0 - vdp2.reg.MPCDN0 = MPABN0__N0MPD(0) | MPABN0__N0MPC(0); // bits 5~0 + vdp2.reg.MPCDN0 = MPCDN0__N0MPB(0) | MPCDN0__N0MPA(plane_a); // bits 5~0 + vdp2.reg.MPCDN0 = MPCDN0__N0MPD(0) | MPCDN0__N0MPC(0); // bits 5~0 // zeroize character/cell data from 0 up to plane_a_offset fill(&vdp2.vram.u32[(0 / 4)], 0, plane_offset(plane_a)); diff --git a/tools/tile.py b/tools/tile.py new file mode 100644 index 0000000..60cfe3c --- /dev/null +++ b/tools/tile.py @@ -0,0 +1,68 @@ +import sys +import struct + +with open(sys.argv[1], 'rb') as f: + buf = f.read() + +stride = 320 + +def get_tile(buf, tx, ty): + tile = [] + for y in range(8): + row = [] + for x in range(8): + yy = ty * 8 + y + xx = tx * 8 + x + ix = yy * stride + xx + px = buf[ix] + row.append(px) + tile.append(tuple(row)) + return tuple(tile) + +def tile_input(buf): + tiles = [] + pattern = [] + + for ty in range(240 // 8): + for tx in range(320 // 8): + tile = get_tile(buf, tx, ty) + #if tile in tiles: + # pass + #else: + # tiles.append(tile) + #tile_ix = tiles.index(tile) + tiles.append(tile) + tile_ix = len(tiles) - 1 + pattern.append(tile_ix) + + return tiles, pattern + + +def emit_tile(tile): + for row in tile: + for ix in range(len(row) // 2): + a = row[ix * 2 + 0] + b = row[ix * 2 + 1] + c = ((a & 0xf) << 4) | ((b & 0xf) << 0) + yield c + +def emit_tiles(tiles): + for tile in tiles: + yield from emit_tile(tile) + +def emit_tile_data(tiles): + b = bytes(emit_tiles(tiles)) + with open(sys.argv[2], 'wb') as f: + f.write(b) + +def emit_pattern_data(pattern): + with open(sys.argv[3], 'wb') as f: + for ix in pattern: + assert ix < 1200, ix + b = struct.pack('>H', ix) + f.write(b) + +assert len(sys.argv) == 4, len(sys.argv) +tiles, pattern = tile_input(buf) +emit_tile_data(tiles) +emit_pattern_data(pattern) diff --git a/vdp1/normal_sprite_color_bank.cpp b/vdp1/normal_sprite_color_bank.cpp index 0daf77e..d4b9fc1 100644 --- a/vdp1/normal_sprite_color_bank.cpp +++ b/vdp1/normal_sprite_color_bank.cpp @@ -57,7 +57,7 @@ uint32_t character_pattern_table(const uint32_t top) // `table_size` is in bytes; divide by two to get uint16_t indicies. uint32_t buf_ix = 0; for (uint32_t table_ix = 0; table_ix < (table_size / 2); table_ix++) { - uint32_t tmp = buf[buf_ix]; + uint16_t tmp = buf[buf_ix]; table[table_ix] = (((tmp >> 8) & 0xff) << 8) | (((tmp >> 0) & 0xff) << 0); @@ -72,7 +72,7 @@ void main() { uint32_t color_address, character_address; uint32_t top = (sizeof (union vdp1_vram)); - uint32_t color_bank = 5; // completely random and arbitrary value + uint32_t color_bank = 0; // completely random and arbitrary value color_palette(color_bank); // For color bank color, COLR is concatenated bitwise with pixel data. See // Figure 6.17 in the VDP1 manual. diff --git a/vdp2/color_calculation_ratio.cpp b/vdp2/color_calculation_ratio.cpp new file mode 100644 index 0000000..1c8ed14 --- /dev/null +++ b/vdp2/color_calculation_ratio.cpp @@ -0,0 +1,328 @@ +#include +#include "vdp2.h" +#include "vdp1.h" + +#include "../common/vdp2_func.hpp" +#include "../common/copy.hpp" + +extern void * _mai_data_pal_start __asm("_binary_res_mai_data_pal_start"); +extern void * _mai_data_pal_size __asm("_binary_res_mai_data_pal_size"); + +extern void * _mai00_data_start __asm("_binary_res_mai00_data_start"); +extern void * _mai00_data_size __asm("_binary_res_mai00_data_size"); + +extern void * _haohmaru_data_pal_start __asm("_binary_res_haohmaru_data_pal_start"); +extern void * _haohmaru_data_pal_size __asm("_binary_res_haohmaru_data_pal_size"); + +extern void * _haohmaru_data_start __asm("_binary_res_haohmaru_data_start"); +extern void * _haohmaru_data_size __asm("_binary_res_haohmaru_data_size"); + +extern void * _forest_pattern_start __asm("_binary_res_forest_pattern_start"); +extern void * _forest_pattern_size __asm("_binary_res_forest_pattern_size"); + +extern void * _forest_tile_start __asm("_binary_res_forest_tile_start"); +extern void * _forest_tile_size __asm("_binary_res_forest_tile_size"); + +extern void * _forest_data_pal_start __asm("_binary_res_forest_data_pal_start"); +extern void * _forest_data_pal_size __asm("_binary_res_forest_data_pal_size"); + +inline constexpr uint16_t rgb15(const uint8_t * rgb24) +{ + return ((rgb24[2] >> 3) << 10) // blue + | ((rgb24[1] >> 3) << 5) // green + | ((rgb24[0] >> 3) << 0); // red +} + +void vdp2_color_palette(const uint32_t color_index_offset, + const uint8_t * buf, + const uint32_t buf_size) +{ + uint16_t * table = &vdp2.cram.u16[color_index_offset]; + + uint32_t buf_ix = 0; + for (uint32_t i = 0; i < (buf_size / 3); i++) { + table[i] = rgb15(&buf[buf_ix]); + buf_ix += 3; + } +} + +void vdp2_color_palette() +{ + { /* mai palette */ + const uint32_t buf_size = reinterpret_cast(&_mai_data_pal_size); + const uint8_t * buf = reinterpret_cast(&_mai_data_pal_start); + + vdp2_color_palette(0, buf, buf_size); + } + + { /* forest palette */ + const uint32_t buf_size = reinterpret_cast(&_forest_data_pal_size); + const uint8_t * buf = reinterpret_cast(&_forest_data_pal_start); + + vdp2_color_palette(16, buf, buf_size); + } + + { /* haohmaru palette */ + const uint32_t buf_size = reinterpret_cast(&_haohmaru_data_pal_size); + const uint8_t * buf = reinterpret_cast(&_haohmaru_data_pal_start); + + vdp2_color_palette(32, buf, buf_size); + } +} + +uint32_t character_pattern_table(const uint32_t top, const uint32_t * buf, const uint32_t buf_size) +{ + // Unlike vdp2 cell format, vdp1 sprites appear to be much more dimensionally + // flexible. The data is interpreted as a row-major packed array, where the + // row/horizontal stride is equal to the sprite width (as configured in the + // draw command). This is identical to how the input palette index data is + // structured, so there is no transformation to do here, only a plain memory + // copy. + + // Divide `buf_size` by two because this converts (indexed color) 8 bit pixels + // to 4 bit pixels. Round up to the nearest 0x20 (for an 8000 pixel/8000 byte + // image, this rounding is a no-op). + const uint32_t table_size = ((buf_size / 2) + 0x20 - 1) & (-0x20); + const uint32_t table_address = top - table_size; + uint16_t * table = &vdp1.vram.u16[(table_address / 2)]; + + // `table_size` is in bytes; divide by two to get uint16_t indicies. + uint32_t buf_ix = 0; + for (uint32_t table_ix = 0; table_ix < (table_size / 2); table_ix++) { + uint32_t tmp = buf[buf_ix]; + + table[table_ix] = (((tmp >> 24) & 0xf) << 12) + | (((tmp >> 16) & 0xf) << 8 ) + | (((tmp >> 8 ) & 0xf) << 4 ) + | (((tmp >> 0 ) & 0xf) << 0 ); + + buf_ix += 1; + } + + return table_address; +} + +uint32_t forest_cell_data(uint32_t top) +{ + const uint32_t buf_size = reinterpret_cast(&_forest_tile_size); + const uint32_t * buf = reinterpret_cast(&_forest_tile_start); + + // round to nearest multiple of 32 + const uint32_t table_size = ((buf_size) + 0x20 - 1) & (-0x20); + const uint32_t base_address = top - table_size; // in bytes + + copy(&vdp2.vram.u32[base_address / 4], buf, buf_size); + + return base_address; +} + +void forest_init() +{ + /* enable display of NBG0 */ + vdp2.reg.BGON = BGON__N0ON | BGON__N0TPON; + + /* set character format for NBG0 to palettized 16 color + set enable "cell format" for NBG0 + set character size for NBG0 to 1x1 cell */ + vdp2.reg.CHCTLA = CHCTLA__N0CHCN__16_COLOR + | CHCTLA__N0BMEN__CELL_FORMAT + | CHCTLA__N0CHSZ__1x1_CELL; + + /* plane size */ + vdp2.reg.PLSZ = PLSZ__N0PLSZ__1x1; + + /* map plane offset + 1-word: value of bit 6-0 * 0x2000 + 2-word: value of bit 5-0 * 0x4000 + */ + constexpr int plane_a = 0; + constexpr int plane_a_offset = plane_a * 0x4000; + + vdp2.reg.MPOFN = MPOFN__N0MP(0); // bits 8~6 + vdp2.reg.MPABN0 = MPABN0__N0MPB(plane_a) | MPABN0__N0MPA(plane_a); // bits 5~0 + vdp2.reg.MPCDN0 = MPCDN0__N0MPD(plane_a) | MPCDN0__N0MPC(plane_a); // bits 5~0 + + uint32_t top = (sizeof (union vdp2_vram)); + + uint32_t cell_top = top = forest_cell_data(0x080000); + uint32_t pattern_name = cell_top / 32; + + /* use 2-word (32-bit) pattern names */ + vdp2.reg.PNCN0 = PNCN0__N0PNB__2WORD; + + const uint32_t buf_size = reinterpret_cast(&_forest_pattern_size); + const uint16_t * buf = reinterpret_cast(&_forest_pattern_start); + + uint32_t * pattern = &vdp2.vram.u32[(plane_a_offset / 4)]; + uint32_t x = 0; + uint32_t y = 0; + for (uint32_t i = 0; i < (buf_size / 2); i++) { + pattern[y * 64 + x] = 1 << 16 | (buf[i] + (cell_top / 32)); + x++; + if (x >= 40) { + x = 0; + y++; + } + } +} + +void main() +{ + // Sega Saturn has 4 Mbit VRAM + vdp2.reg.VRSIZE = 0; + // Disable VRAM bank partitioning during CPU access + vdp2.reg.RAMCTL = 0; + + // Enable CPU access to VDP2 VRAM at all cycles + vdp2.reg.CYCA0 = 0xeeee'eeee; + vdp2.reg.CYCA1 = 0xeeee'eeee; // A1 is irrelevant because bank partitioning is not enabled yet + vdp2.reg.CYCB0 = 0xeeee'eeee; + vdp2.reg.CYCB1 = 0xeeee'eeee; // B1 is irrelevant because bank partitioning is not enabled yet + + // initialize VDP2 VRAM + vdp2_color_palette(); + forest_init(); + + // NBG0 Pattern Name Data read at T0 from bank A0 (0x000000 - 0x01ffff) + // NBG0 Character Pattern Data read at T0 from bank B1 (0x060000 - 0x07ffff) + // all other VDP2 VRAM accesses disabled + // + // This is because: + // - N0MPA / N0MPB / N0MPC / N0MPD are at addresses 0x000000 through 0x002000 (bank A0) + // - forest_cell_data ("Character Pattern Data" for NBG0) is at addresses 0x076a00 through 0x07ffff (bank B1) + vdp2.reg.CYCA0 = 0x0fff'ffff; + vdp2.reg.CYCA1 = 0xffff'ffff; + vdp2.reg.CYCB0 = 0xffff'ffff; + vdp2.reg.CYCB1 = 0x4fff'ffff; + + // Enable VRAM bank partitioning + vdp2.reg.RAMCTL = RAMCTL__VRAMD | RAMCTL__VRBMD; + + uint32_t mai_character_address; + uint32_t haohmaru_character_address; + uint32_t top = (sizeof (union vdp1_vram)); + + { /* mai */ + const uint32_t buf_size = reinterpret_cast(&_mai00_data_size); + const uint32_t * buf = reinterpret_cast(&_mai00_data_start); + top = mai_character_address = character_pattern_table(top, buf, buf_size); + } + + { /* haohmaru */ + const uint32_t buf_size = reinterpret_cast(&_haohmaru_data_size); + const uint32_t * buf = reinterpret_cast(&_haohmaru_data_start); + top = haohmaru_character_address = character_pattern_table(top, buf, buf_size); + } + + // DISP: Please make sure to change this bit from 0 to 1 during V blank. + vdp2.reg.TVMD = ( TVMD__DISP | TVMD__LSMD__NON_INTERLACE + | TVMD__VRESO__240 | TVMD__HRESO__NORMAL_320); + + // SPCTL__SPCCCS__EQUAL: only perform color calculation on Sprite (pixels) + // that have a priority number exactly equal ot SPCCN + // + // Sprite Data is Type 0 + vdp2.reg.SPCTL = SPCTL__SPCCCS__EQUAL + | SPCTL__SPCCN(1) + | SPCTL__SPTYPE(0); + + // Enable Sprite Color Calculation + vdp2.reg.CCCTL = CCCTL__SPCCEN; + + // VDP2 User's Manual: + // "When sprite data is in an RGB format, sprite register 0 is selected" + // "When the value of a priority number is 0h, it is read as transparent" + // + // From a VDP2 perspective: in VDP1 16-color lookup table mode, VDP1 is still + // sending RGB data to VDP2. This sprite color data as configured in + // `color_lookup_table` from a VDP2 priority perspective uses sprite register 0. + // + // The power-on value of PRISA is zero. Set the priority for sprite register 0 + // to some number greater than zero, so that the color data is not interpreted + // as "transparent". + vdp2.reg.PRISA = PRISA__S0PRIN(2) // Sprite register 0 PRIority Number + | PRISA__S1PRIN(1); + vdp2.reg.PRINA = PRINA__N0PRIN(1); + + /* TVM settings must be performed from the second H-blank IN interrupt after the + V-blank IN interrupt to the H-blank IN interrupt immediately after the V-blank + OUT interrupt. */ + // "normal" display resolution, 16 bits per pixel, 512x256 framebuffer + vdp1.reg.TVMR = TVMR__TVM__NORMAL; + + // swap framebuffers every 1 cycle; non-interlace + vdp1.reg.FBCR = 0; + + // during a framebuffer erase cycle, write the color "transparent" to each pixel + constexpr uint16_t black = 0x0000; + vdp1.reg.EWDR = black; + + // the EWLR/EWRR macros use somewhat nontrivial math for the X coordinates + // erase upper-left coordinate + vdp1.reg.EWLR = EWLR__16BPP_X1(0) | EWLR__Y1(0); + + // erase lower-right coordinate + vdp1.reg.EWRR = EWRR__16BPP_X3(319) | EWRR__Y3(239); + + vdp1.vram.cmd[0].CTRL = CTRL__JP__JUMP_NEXT | CTRL__COMM__SYSTEM_CLIP_COORDINATES; + vdp1.vram.cmd[0].LINK = 0; + vdp1.vram.cmd[0].XC = 319; + vdp1.vram.cmd[0].YC = 239; + + vdp1.vram.cmd[1].CTRL = CTRL__JP__JUMP_NEXT | CTRL__COMM__LOCAL_COORDINATE; + vdp1.vram.cmd[1].LINK = 0; + vdp1.vram.cmd[1].XA = 0; + vdp1.vram.cmd[1].YA = 0; + + vdp1.vram.cmd[2].CTRL = CTRL__JP__JUMP_NEXT | CTRL__COMM__NORMAL_SPRITE; + vdp1.vram.cmd[2].LINK = 0; + // The "end code" is 0xf, which is being used in the mai sprite palette. If + // both transparency and end codes are enabled, it seems there are only 14 + // usable colors in the 4-bit color mode. + vdp1.vram.cmd[2].PMOD = PMOD__ECD | PMOD__COLOR_MODE__COLOR_BANK_16; + // It appears Kronos does not correctly calculate the color address in the + // VDP1 debugger. Kronos will report FFFC when the actual color table address + // in this example is 7FFE0. + vdp1.vram.cmd[2].COLR = COLR__COLOR_BANK__TYPE0__PR(0) + | 0; + vdp1.vram.cmd[2].SRCA = mai_character_address >> 3; + vdp1.vram.cmd[2].SIZE = SIZE__X(72) | SIZE__Y(100); + vdp1.vram.cmd[2].XA = 100; + vdp1.vram.cmd[2].YA = 100; + + vdp1.vram.cmd[3].CTRL = CTRL__JP__JUMP_NEXT | CTRL__COMM__NORMAL_SPRITE; + vdp1.vram.cmd[3].LINK = 0; + // The "end code" is 0xf, which is being used in the mai sprite palette. If + // both transparency and end codes are enabled, it seems there are only 14 + // usable colors in the 4-bit color mode. + vdp1.vram.cmd[3].PMOD = PMOD__ECD | PMOD__COLOR_MODE__COLOR_BANK_16; + // It appears Kronos does not correctly calculate the color address in the + // VDP1 debugger. Kronos will report FFFC when the actual color table address + // in this example is 7FFE0. + vdp1.vram.cmd[3].COLR = COLR__COLOR_BANK__TYPE0__PR(1) + | 32; + vdp1.vram.cmd[3].SRCA = haohmaru_character_address >> 3; + vdp1.vram.cmd[3].SIZE = SIZE__X(104) | SIZE__Y(132); + vdp1.vram.cmd[3].XA = 120; + vdp1.vram.cmd[3].YA = 110; + + vdp1.vram.cmd[4].CTRL = CTRL__END; + + // start drawing (execute the command list) on every frame + vdp1.reg.PTMR = PTMR__PTM__FRAME_CHANGE; + + int dir = 1; + int ratio = 0; + while (1) { + v_blank_in(); + + // increment/decrement the color calculation ratio once every 4 frames + vdp2.reg.CCRSA = CCRSA__S0CCRT(ratio >> 2); + + ratio += dir; + if (ratio >= (32 << 2) || ratio < 0) { + dir = -dir; + ratio += dir; + } + } +} diff --git a/vdp2/nbg0_16color.cpp b/vdp2/nbg0_16color.cpp index 100d4f8..91a17d4 100644 --- a/vdp2/nbg0_16color.cpp +++ b/vdp2/nbg0_16color.cpp @@ -105,7 +105,7 @@ void main() vdp2.reg.MPOFN = MPOFN__N0MP(0); // bits 8~6 vdp2.reg.MPABN0 = MPABN0__N0MPB(0) | MPABN0__N0MPA(plane_a); // bits 5~0 - vdp2.reg.MPCDN0 = MPABN0__N0MPD(0) | MPABN0__N0MPC(0); // bits 5~0 + vdp2.reg.MPCDN0 = MPCDN0__N0MPD(0) | MPCDN0__N0MPC(0); // bits 5~0 uint32_t top = (sizeof (union vdp2_vram)); palette_data(); @@ -118,7 +118,7 @@ void main() /* use 2-word (32-bit) pattern names */ vdp2.reg.PNCN0 = PNCN0__N0PNB__2WORD; - fill(&vdp2.vram.u32[(plane_a_offset / 2)], pattern_name, plane_size); + fill(&vdp2.vram.u32[(plane_a_offset / 4)], pattern_name, plane_size); // both 1-word and 2-word have identical behavior; 2-word is enabled to reduce/focus suspicion. }