From 660c5fe5ffc7609c8026083f3f710190241c38b3 Mon Sep 17 00:00:00 2001 From: akasaka Date: Sat, 28 Sep 2024 23:06:22 +0900 Subject: [PATCH] Compressed music format --- data/music/001_caramelldansen.pomf | Bin 738 -> 746 bytes data/music/002_duvet.pomf | Bin 533 -> 541 bytes data/music/003_haruhi_no_omoi.pomf | Bin 278 -> 286 bytes data/music/004_hishoku.pomf | Bin 458 -> 466 bytes data/music/005_like_the_wind.pomf | Bin 673 -> 681 bytes data/music/006_waiting_freqs.pomf | Bin 373 -> 381 bytes data/music/007_the_way.pomf | Bin 1028 -> 1036 bytes data/music/008_guitar_hero.pomf | Bin 3138 -> 3146 bytes data/music/009_shabon.pomf | Bin 2248 -> 2256 bytes data/music/010_steiner.pomf | Bin 1453 -> 1461 bytes data/music/011_towa.pomf | Bin 2578 -> 2586 bytes data/music/012_mermaid_girl.pomf | Bin 1458 -> 1466 bytes data/music/013_eye_opener.pomf | Bin 1583 -> 1591 bytes data/music/014_truth.pomf | Bin 1043 -> 1051 bytes data/music/015_wpip.pomf | Bin 598 -> 606 bytes data/music/016_am_arise.pomf | Bin 553 -> 561 bytes data/music/017_bouken.pomf | Bin 1108 -> 1116 bytes data/music/018_gentle_jena.pomf | Bin 2108 -> 2116 bytes data/music/019_gammapolisz.pomf | Bin 1268 -> 1276 bytes data/music/020_ark.pomf | Bin 2108 -> 2116 bytes data/music/021_skibidi.pomf | Bin 3883 -> 3891 bytes data/music/022_kamippoina.pomf | Bin 14064 -> 2460 bytes data/music/023_re_sublimity.pomf | Bin 6688 -> 1036 bytes data/music/024_in_the_80s.pomf | Bin 1563 -> 1571 bytes data/music/025_shake_it.pomf | Bin 14008 -> 2401 bytes data/music/026_en_elmegyek.pomf | Bin 3558 -> 3566 bytes data/music/027_scatman.pomf | Bin 6878 -> 840 bytes data/music/028_stasis.pomf | Bin 10108 -> 1349 bytes data/music/029_stars.pomf | Bin 10343 -> 1318 bytes data/music/030_scar_tissue.pomf | Bin 6478 -> 754 bytes data/music/031_space_harrier.pomf | Bin 11433 -> 1108 bytes data/music/032_take_on_me.pomf | Bin 10853 -> 2685 bytes data/music/033_my_name_is_nobody.pomf | Bin 18103 -> 4273 bytes helper/elf2pomf.py | 65 ++++-- include/miniz_ext.h | 54 +++++ include/sound/pomf.h | 12 +- src/miniz_ext.cpp | 277 ++++++++++++++++++++++++++ src/sound/melodies.cpp | 55 ++++- 38 files changed, 446 insertions(+), 17 deletions(-) create mode 100644 include/miniz_ext.h create mode 100644 src/miniz_ext.cpp diff --git a/data/music/001_caramelldansen.pomf b/data/music/001_caramelldansen.pomf index 14096be9e12f8e741582802585586671525849c1..aea34e7750f55b9b06469260bce6642a0acc4a22 100644 GIT binary patch delta 26 hcmaFF`ihk`z&|&QaUyHx#;g)14%d7)1y_GJ1ps#R2m1g3 delta 22 ccmaFG`iPY^z&|&QVIphh#-aiy76u>y098o^<^TWy diff --git a/data/music/002_duvet.pomf b/data/music/002_duvet.pomf index f7ea4df959131488015af3074199d3fe413c92a5..baae05cd177fd3c12f7a2ee27e4337318e583005 100644 GIT binary patch delta 30 lcmbQrGM9xdz&|&Qk#VAq!bCNXjakbXIb8GI6kPq?6aa+x2yg%Z delta 26 gcmbQsGL?lbz&|&QfpMaa!bCNXjYW$YSr~u-0AX|nTL1t6 diff --git a/data/music/003_haruhi_no_omoi.pomf b/data/music/003_haruhi_no_omoi.pomf index 978451bc768e61ce9898d8f8cdda8beca50e6fa4..3325befc698696a156861c86fb8bf56126cdb5a9 100644 GIT binary patch delta 25 gcmbQnG>?fjz&|&QaUyHx#HwThz&|&QVIphh#G)lE3_t(?Lqi2x diff --git a/data/music/004_hishoku.pomf b/data/music/004_hishoku.pomf index 2f3656988f11af6e2ca34cec35e14ec330bf5eb1..c8b2c6534ccb059cc258018652d9073281a110ea 100644 GIT binary patch delta 32 ncmX@be2JMgz&|&QaUyFbW5{GiM%j%Wc8naZ`EClX{%#5Yn*Rv3 delta 22 ccmcb_e2SShz&|&QVIphh#-a#D76u>y08m>6nE(I) diff --git a/data/music/005_like_the_wind.pomf b/data/music/005_like_the_wind.pomf index 5a56e35fe4f66e63c1a1a3eeb97a6121fb92b888..3be3cc4036f153c8a61fa76a2ed17ad1a7c9a0ed 100644 GIT binary patch delta 37 tcmZ3;x{{SOz&|&QaUyFblQz@D2ARq08SiXPVYFoAaLsp9aP@an007a03bgy07%#cBLDyZ diff --git a/data/music/006_waiting_freqs.pomf b/data/music/006_waiting_freqs.pomf index 9caa10f92391d2afe8ec7c93be0e235baddde33d..493648d200ce7f73e3185ac0858a087f40412256 100644 GIT binary patch delta 26 hcmey$^p}Y>z&|&QaUyHx#w>P54%d7)1y_GJ1pswn2dw}A delta 22 ccmey%^p%My095V;m;e9( diff --git a/data/music/007_the_way.pomf b/data/music/007_the_way.pomf index 200cc7832a75af9f781ac246913dd9249dc801cd..17c3973c615ed134db1c7d6ca78bc5ba14fcbb59 100644 GIT binary patch delta 37 scmZqS=;7cE@Xt+SWDLnjRR~Y4oaiVyQO#px)-+}g*L*hxSARDJ0L^F$&Hw-a delta 33 ncmeC-XyM=u@Xt+SU<}DfRR~Y4oaiVyQO#px(IjRT1|R?cpk@fU diff --git a/data/music/008_guitar_hero.pomf b/data/music/008_guitar_hero.pomf index 34a4d683b62f3be2b2f273525da6676fa0e083f6..455d48efb0b202cb5a80714b697fd94240dc2011 100644 GIT binary patch delta 37 tcmX>kaY}+Mz&|&Qk#VAh!bCL>rZe1=_p?WAJW|EY;hOKJ;Og(D008CX3%>vW delta 26 gcmX>laY%wKz&|&QfpMaR!bCNXjYSu@Sr~u-0B{`#AOHXW diff --git a/data/music/009_shabon.pomf b/data/music/009_shabon.pomf index c2f85172a8866efe06994db8cfc3a7cd68ad725a..29864c46a005d3485d619ebf47daaf8e328926d0 100644 GIT binary patch delta 50 zcmX>hctMaSz&|&Qkuf+UF)2T9qNCJAH4mmBj!Deglh3p8PtIrM+PFc4gTpo7O~KXQ GO#uLnk`BB8 delta 32 mcmca0ctVgTz&|&QfiXBEF)2T9qNCJAHII!&VH_+BKmY)%<_QG= diff --git a/data/music/010_steiner.pomf b/data/music/010_steiner.pomf index ab3de6a216c1401b89f8f121a43df03b1612e40e..2afb6e3cb3cdd224ef60fb2f6b5470e8859c008e 100644 GIT binary patch delta 26 hcmZ3>y_K6az&|&QaUyHx#w>eQ4%d7)1y_GJ1psT22WtQT delta 22 ccmdnWy_TCbz&|&QVIphh#v*H076u>y08AzYRsaA1 diff --git a/data/music/011_towa.pomf b/data/music/011_towa.pomf index 1302dbcf4f696888d88fb7e5c52adf4ff00def6b..dc4010d289fca684931e80de4261be3127400877 100644 GIT binary patch delta 26 hcmbOvGE0Otz&|&QaUyHx#;hfr9Ip9p3ay08JYOWdHyG diff --git a/data/music/013_eye_opener.pomf b/data/music/013_eye_opener.pomf index 5ce6647cac4f0daff444987ead5f877938e39c88..30f82d814a34db6d86bfa8499a6d317203f818bf 100644 GIT binary patch delta 30 lcmZ3_vz>=6z&|&Qk#VAx!bCNXjadg-Ib8GI6kPq?6abFh2;cw! delta 26 gcmdnavz~`7z&|&QfpMah!bCNXjYWG|Sr~u-0BM>A%K!iX diff --git a/data/music/014_truth.pomf b/data/music/014_truth.pomf index ae8c7ccad354dd5ce6f8d4454081aaf96394fa2e..ba03f0abd66cc3ab8ea261fb317135e3280269b3 100644 GIT binary patch delta 30 lcmbQtF`I)ez&|&Qk#VA-!bCNXjaf^XIb8GI6kPq?6aa<02zdYi delta 26 gcmbQuF`0ucz&|&QfpMat!bCNXjYSKYSr~u-0AdsdWB>pF diff --git a/data/music/015_wpip.pomf b/data/music/015_wpip.pomf index b2b88de459a06c2cd90d8d5ded37118bc6128f7f..876928990c9ba239af13e03d313728a7b3d5025c 100644 GIT binary patch delta 30 lcmcb{a*u^Az&|&Qk#VAh!bCNXjae@kIb8GI6kPq?6abf02|oY; delta 26 gcmcb|a*c&8z&|&QfpMaR!bCNXjYUrwSr~u-0C1HDDgXcg diff --git a/data/music/016_am_arise.pomf b/data/music/016_am_arise.pomf index 1be5789c221fe6ffe6fadeb495332c1373a43059..a503ce995bf76cbcf4e8357621b221b7a06316ab 100644 GIT binary patch delta 30 lcmZ3LjV8( diff --git a/data/music/018_gentle_jena.pomf b/data/music/018_gentle_jena.pomf index 8816d2e15dcbba402b3d830b256545844d46552a..faaa6511aa7f0b124c5f4cf0d4d43cff1f08c218 100644 GIT binary patch delta 26 hcmdlZa72JLz&|&QaUyHx#;kMf9Ip9p3aiut$J3z&|&QVIphh#-dZ~EDS&Z08?284*&oF diff --git a/data/music/019_gammapolisz.pomf b/data/music/019_gammapolisz.pomf index 160d6b47f46a0f96839bee7de89ccad04180c1a0..7246c13d3666833235e374666d0d365379e26e23 100644 GIT binary patch delta 30 lcmeyu`G=D&z&|&Qk#VA)!bCNXjah9h9Ip9p3ahGoi0JJ>{dH?_b delta 22 ccmX>iut$J3z&|&QVIphh#-dZ~EDS&Z08?284*&oF diff --git a/data/music/021_skibidi.pomf b/data/music/021_skibidi.pomf index 1fe859dadf2fb3d496af51c32a131ea975bfe9d2..97c9a42c7075a5fca77c3bcf8db6c63cb97e9004 100644 GIT binary patch delta 26 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 literal 6688 zcmeI0KWkM%5XCnyK`gJJh26Ck0@un;USlC4M%30uh$5)5FrfGiEEQ}lY{bICTEy>= zUd6`R*4jP4i95T)eJ}3?6$7TY?CzYMoj+%0_vOmgy<2JJ>h}7z-J5ss+`IGeaT@vC z*t)*8vDL5l2LVU+YU$zb<%@4mr?j%B*{hY5PMpkxGy0r6ooUi32+kyH4$X6{&m1$;rf0Cytb?NzEn$z*@mL;N5>Tc&x4|kncA2Ycs z>Osd(0^cuS3_`#NIx_ND$=vRVcD&CYqd;-mc)!^mlwpe-q|++v7c~ffU(PkCja7BV z{0L#tzaAk^&&-r9A0g$ff2x>@IX;5V)%1NUl`Y*Vtw{j{=|rg>%2N=9FBL8bX6;C4 z#lKcPq^`~=jEy)c9mRdgmYTW23=X1>f?(+#X1H$)M*2OYtD_4ziq36;lWHhtGgI9? zUXooawZk2PGv%@g;LdSqF2VN8&>?nt;Y_wCxhe@}9$-}ocdB#}JQ6QHmAPAP;VTt!`Bnl(_4Ax*>zj>5UrV(y*x4j&D>kPT(CQeb8%J01ETQ`ZFH1-2l{d@B7>*o;=q??#is&V3M$z9xy^)kvEH0JO?PXUh zf8DqCxmDq?Pc|C~2?XF^c+l+8b?n}Z;Yks=`(o!% z-Z|Ah9Ryx8I%vSi&0K0#kt`q}upiV}xe{dB@GgJM+&oAf4=RmF_w>bDmY&bk=>z@f z(x{Wa(>&N0+)%|MkiS#W)^_L&6X?jPQegtsstKOu(Nt!bAP>^yP5!LPH6HXGfn^8Q z6FP0{g|IRpIF8$qL^z{B0HeUchg7Qc^g5?%=42W#U1`8!spEpB0SvDkJX0yX({U)} z7ShP#houNeV;R{6M53g=0yCwl7O9j(NX1ykc|mB0MF=BlA~o zh47oH!l6(0q0chd?ucM@y|KeBetY@IzE}`Av?xIW6XizaT7blZh?+AjcuDMMdP!|< zWR`@`Re=BkH)d+#$eFQ%5pAr@%R{o{f7eS@dWd~#Zh;#IFo&!9hqP)|T2b9cxu)LBNIElp`@x(XjmbjpKKoS7X7=XWdd#>0GWIE~Wl}a?#OcyuEV^y*~l2jyzrf diff --git a/data/music/024_in_the_80s.pomf b/data/music/024_in_the_80s.pomf index b5b3dbf407b739b01e80f3f6573ab04196d933ec..51d99e9e4e136cd22326355abcc5b81eeba236cf 100644 GIT binary patch delta 26 hcmbQuvzUi9z&|&QaUyHx#;moh9Ip9p3aQq?5lD@271X;E5^^W<54bf1j0-nzlUn6l>mXJK5rAtSb;e@Ui9@$AR*;|k7r$`n~2lKR8 zayguhN`Nz(-Sfy))l-l8Wn9vn)9f3XJql6g!fKC=b!P%^Ng(j0`p;#Fs{eK{cdw)% zZY3i~AR~*yjGX1YpEE*mnE=mje}0XFLW2KP9DJ<;YkA*y{QW2&Pvq6Rc_+w9D*`1U zAd8D7?MtCOi?Tr6QVas%#YZ^`EQIJh3)vD0y#};2DtykivXtJ-#ZYk-1@SB>%v>h$ z17Ds{Mw5Az0h;T_Fk^`j82xs0Hap5e)tnf0AG5{yB@|bKIoj@ADE4LXeq08b+WDB5*hnW5xg6aF<_cWBA+FeOW%wsS@#fqGiwx!X11$q*X5NVV=sL}s$> z_%G@t2OP=VJq;O|q)>+pf6!S8m7)rm`ff%%rX`Kqi;%&KKx%`Af)FT8j=~e;d?G{& z4s?+KOGX9&BxRO|1|z{!YbdNxs*|`RaT!$*(^~~C7#+}(XY(muf{HH{0Fh&rhoneT4?vief9qZwJY0hT#fU5X zS`uje2+Ntf5w;*oJicW?@dC3Sg#p}b3_>PVfK#%+7)e+Z(Nqyg45jW?TJ_Oso)uaY zlnhl08wW_BS>{H>`wSrAhTaIJABB*l5DPAyQ#(^KaUpn!SmBG`$U+f2C$x`bBE)r^ zE`{cV+$pG_BrQPze|%Rc^FpHnuP~FCxCK1I;;-pFbg-KC3772(GVK%!jrbn)puI(R zVSth^N1JjFH3GD|5k+egemCecm=c7IyVFa%9a(PO75GhoAJY{(vT+1p9maJfiqu3E(iB{je_j=!U-O^h=B`wMc19JN zGY_F1J^Xf#0!yrk21U!YkiXl3!h$SNM#@Ksk38uV8X)x5TN@Jr*0D4~%0%n|WviU)@P#I01Twmi6%p+Ywn z4aQzv6jrDQP+v!4I_0ZL$58^jPiUcaz0W+B4*@L&=R$@(gA{Wu3TzF0KXMDeIO16o z`~~Z&e@BKULW9m#nk=rebPxKBqb^GvWyFRVNYq$(i-XssmNLPaz>mLIP*=N0qn64X z-dk+l60&_EqeSe~Tl!^+BtVhoPgW9Aa8D;egCC14ZY(XCbK?#ni5!NlOkt(x5f2|Nl%uUpC-81_6n`~k;%O!T%$>Vdodq(FPS{ zf1Fjb7@-T9K`pZk^+%Mz3L4!@xp@v*l4gxv?u+2q02I2ImhfV?jEElWBNCUbLD>VS z4v(dtXv&Ct8SNhKeHUh4*ti`5w&)&4LIv~Ly=Zs`9xT53ksG{p6juN zCO_1`w9AVJ|gZvJ%7Iyun7wPJA&2AZunL(qSGfT8lw#*CbM zm3tH{M9=noiV(9WeFuxIG&K(q>FFZ1bAJwo48Z(?FCDhVQ6UF_R4BC9*}de=30^`Y z%bsQ|`E-#!&06V9$=+UN8Jh5wf0EI{?ASu!Gc^5*ukegqv_OQE99>Jky#x83ARB5W z_6rfzHJvH_rNk8-VpFdssS6v>H+8mw7d}bkphKW&q52e`*fH7__z&@6xrO7kTNODd zdowP+)))8lxH$RZ4tPDfK{nv;>_9g1gI~pZ`JpajPz?+1V0e7JkYLcpf1y4~C$dCbAG%9yp@QCCqG-rdMM^HQbCqlA6rmN_M}niA5P3Yp(d zuszb^hINm_EC`1`WE5;&f4cB9q9qXawmE2mhhxN=YN9Vvjmsfr5A(39t(9OjuoBG5 ztp#bNWCtQpZsMh~r$`*_E=6NWa+SQ*${{g7FKJLVn-E8d%+w|{XWAgL(62)J<(mz7 zB(A`}%QqVsLYoa-0nM>dU#i6*9NiY9XSa$L^GQx|wRGWhq08T83vXs1MQ=tRMNdW` D>zYO_ literal 14008 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 diff --git a/data/music/026_en_elmegyek.pomf b/data/music/026_en_elmegyek.pomf index 5e9e147f0c9d6faaeff46489180a576aaf85fbaf..e8dd5c3ec055a9813997600c19bc4ee057bc1a34 100644 GIT binary patch delta 30 lcmaDR{Z5)Kz&|&Qk#VA)!bCNXjae1E9Ip9p3as2Id2X>3Ke0S!|9=NT*a|-c7d~NoQ-g{z}d_> zJF0K{{BeI=|CoLbX9x9d@+W-y7Cy1vd3~Gmrx17YJwD}2OiGFX%kcZJB0@b-lcWHg zMmG*Fz9#^^4ZmwHB}}g17V41vjsbcZ?i^A*Zs8H&x$;(l9BmGhQ@ClV4ElR7sUv{e z)JmYNfSjh*ipwY?_%6whJH3HNPb%bT3EyrOK2U#iiJM2jO~exuZD&RO2+-FocnASn zmiG?z=)K9RiU9o7?Y)NV*?TE}4!55~9R#e?r%V8R`I6Qt75CvRrD76oC3^u?D&`TH z?OKgJqnO`DRD3Ox0y)|pOb*~?`tk#Oa0$$ZN$m_M3m_XlG%lk&&Byjsm|4gX(4wpa zUY37_C5(A`da$4#yfW4f3*7^;PD{819(2JbIfIGHghtbJ)eh3p8XQB^1&k}4p(0+T z0(uU+u<8ei$*|f(VziUmoIzp+iJ|5iBqrfwkeFs6dn|Mh#BK=4N=J@>{W?(^hu~Hr zLfgk|SHZW8#zt(!?g&qH3tZvp`^P8}a*=-naP}J82}-)xT6o$pEg>Z7?KO#((kLD# zNv%lJJ%L-=Q(J;3EZUbDkY8R{R*2?}kk@guv$Z+AzW%Y}MoGLku}8;EYWkjLrF>&K zk#x-t+j?+#u)7C`LuLoZS%P+Ou>V?kSsI=FXKB2nN4a<^Bqli(vL$#+&z7!9mB}?=xn4(00BQ?};xkN`QVOg7(`gGT+A8fBMn-+#g3-4(kR|3BPcWp8F6MQ=tRMNdW`^#x@V literal 6878 zcmeHL!D0KcXlBV$Tm!G?{xR8>Q`M=-Lw7v=%DKD?(dx(?HyNb<@NaRI8Fw| zLET#4{rY9FwKv!re;d5C$9^9bAx^%(8y()Ss@^s0zH{BGKB}iTG5R!ART!a#67HeS z-aW71ZKH(}ZlUJ5w`ie+4b<7Y+xBV&@2ge&8E#r5+^{PCL+b!7d#donsv%p@C7$6O zdRZdsaMvma_=x|1pg5s^p%+RzzytK61PG68t)WHG5BM)#02=WsY@tTsI$S@n;h-QratYpaf_Y+0s%8`nPAjS_eQKMS{>`3H$cr>u9Q$$R!&vPsEe} zuDsQhJKRCa_{>Od&3Rz8?9DfIBoWVuwgyd{!CO$9O5V5$su5hXpa}V zcqAwpr!No>$Pt5rh+W4!>Nl4u-k5VrNtgBs&?vrWwlaJC=$-d+3G{_bH7LYFB^|k` zS|XPy9ekmt)0aBGDKcMZGXPia+LP?*Rv;)wyZ3akf@T2T9YSlXHxl|Lmd*^o=*^(O zB``o?u=0YltF5wuZWL}f5B~(9G+9RD>eP{hpv+LrI0Wrm9oec^#8B!{8QQZj)F)wm zp14MUi24er7%@3AB8p*d6AY2qj$tmbZ^vvOO~k|sJ7{HYl_mORifK>p%M^1SH?jz~ zOfl|Y?rKUHYvylV61`?HAeRz-c5c5A128-&QO(ZrD|RBOR$=|*tjw^4fVXN-6`IM0 zgR^Ag<8ZI=UTVODCaw?O`_Nj^9_Kj`iBnY(pb*zM&QWL?%D{Oj!Gi&Oh?W4dOGjr{ zS2JKn*9GqqP_0PnQUe>7UejP5_rBvG5*Mpgo$7`DMk)*+GYv zC31K|E?ic+Fiuc0E;DK;Hod3Fc%~X=xM_h`WL$E|!EEnw4s?{{S+t}s7;+_X;T_uJ zo5mH&9EV3lZIF`VP^8Gt0C;R{UUVoZQZBbGWyo=e2PJ)oklQXgxfyYb$rh7bI4Dg+ zXjer>86oxCGzf KK93I~H2Dwu=A~Hx diff --git a/data/music/028_stasis.pomf b/data/music/028_stasis.pomf index bede398b8ee6d8f1201bf9899c1dd5b47f91862d..3ea6cc1bb73dcee66211316d41b20a0037ad7669 100644 GIT binary patch delta 1272 zcmVoNt7q_`>m0i|9*OVf5YW! zh{CX96c%An99b~D%N&g?;2Q;9ekh$Qw491+F!=M4bJbpRF?myTx;xF^>e#hcUgK4> zTfKIX$e|#z8;iV;MaXZ3tA%U*_PotlHz3`KG~5eAa!1NZ99;qQnB16Bj!Y2z3>w{nELWsfCppTZyTy0*rA&eG-XPBypHpFYG$uUig%z zN${)Djn4B1u)8AhU<<^D%4Xsb<$W|KmJbH^G%itzVwXu_@z8hLU^8&C8J{sO7%e58d=-HpZ`4i!1= zr4!ZpFkH=4JPcQv(1+pL8Muexs&X#1smi(3uqw&DP-*#4anCqhBGL4#3r74PASee~!26hK{EPmgFGwBGl(1Qas{hHTxRnjLj}q4npNLRnnVgOogSz zkBW84Vd*W2u#%6hK-Oh|fR0l2Kr>BxewxKcHamTG7oK zPvO&AeWU5BgNnad)|YemKdY+@s^p2h-DP;u5_>wqj5jJe(QECA zd&EH1%`&z0^nsy9KIm86ARpz5N3(=)s@%guVnuJmW+1JTPIW$fJZJ@i1pk6V#B3#+L1Av|Nh iJA&op?T)V02R?sq(U}hju>JsLZ)PAxZ$=Xec7kTC#*hft(^`%t{nAG)9U=gc27qMG6||sGz2$ zp`nL5T?+mHKLGd@-1j-ly>|}h&d%D70Ldfm=c+dB}v+EBZopyU4ou52;_@rxI z_a8n!d31Ju_Vi>teQ-zV#N}sMj*Zqe?xBl~$e?HK|oj5{bqy*w4;t+=Hh=~6!;QM2aU@-12E; z2Qle>d#US&!^A(nm&BM^Z=|ooXX(~!Ws!L+JsnagYm(!D6AqA9nz=kKh{cm z(P7%i1D6qC$sFD5f-Ac5MgnBK654+!8f6aR$3N1yC`MkT*oHfq7;S=9Sza*zBw`s| zx#{~BF$UiI`|0qFRtpSNat(JA@%U@z{aUMHpuAQY*ov0PaliFD-I^>E$n(rCW(`=;yRy4h9D4%aI6rW4ls{d5mp5i4z}edsD;?VzBmh^IR! zBUbz38gw6ZTRM78a-P2?&&`wc#cn!F=lj`AEGmmg$<#&N!4RU^NMDE z;)rb^31uoiHD07l0huF2X4^)s?3F;_EoM2m5R*9w)mJ+#Q|x51q9kEVAx?VGiyuuDsL}akYbw?tj?ud6iDzQ~o!uvFd zFLciL10-?;7tOa28$Jb~63W(ofs3!0&Z8=wA;KbO8)gEko28>l&5I&XG*vml=omne zriama&0=wv}RG)q^| z{L5tlI{NWeGE0r(D1A1YWB1a%Nf)FU@`@saS~F@&S*k6dV_HT2D+r46=(nm66<;q( zUNaBf(JFnq{wv*e4a)Y2gOL!ip)KUd@**~>EMh}m$U%y>@I@R=XjmC>gn*8dArWy~ zyj~7O9P)@A1tUcfho^J(cDJF(vqdpi^fAG=4=r0hKe*2JnUPAVR$Wsv?>n+uhj&*{mb)4HxOd1U$so+Cq3@=fqZ|JzMS! z9-n-$Q)olUxBDbT1-5FAF>QrbnwOCPkIH$iRl1&SK|m#H37Z_|>87X>K{8s~g_TxI z%vyj?^1R-NZ96`oT@5Nbpkk^b7~!J@McUeABQ+Bon}@Ji>wNN=Rl)49CQBL+ZA z1VjluZDi&(b+cv!BSi!+jN26RP8}|RXw#;(=_-? zDJRmJJDy)%94HZW1o8Bg%IK{myW^pVc|%%} Wpa|tCl5)had7!Uc56(_UE&c+G{Z)ei diff --git a/data/music/029_stars.pomf b/data/music/029_stars.pomf index aa22e30a239459ed1dbc51863c066ded8bd3b4ea..660ad7a1aaa308d50b89bafddf3aa700a5253b88 100644 GIT binary patch delta 1241 zcmV;~1Sb3EP^Jn7P)}`U0RfRPAdx0Qe_C3o1ONc>CjbELTD@))K@c8a!jJe72T~}} zrEozcBqPz|4n>g=vJf3b(ouk{NK`3k=`HaFyn|EGq~;0SM53agb<53cZf1A9bGvsj ziWI!XW%qXGn{Q@k=kC@S+ysD!x9ZF8-TLzUetjv<>r44(05JZ2ryg$A!!h8*e@C3y zE9%}9dj~~Qn0k}J|AmLbZ^rkM!nw%r5RZC~*+wR3KxBc3d8-=rNDW1(H~xHMRgM5~ zLZK)IQQZS$qOTz^baU_J*y!ZUi-@5v_Y#CmHRxc28s36(QU9qcX-3Z0JoG~b7j>k$xZI+408s&V@i=;&DCyIQ64q=)%8r@8Weh`2Y7UL=!pVBBS z476IUtfI+ZGVbtd8Vq@iLSd!Z_x zvK;Ox5M)zh7ks+Zq|!J-R;3ZpC`v?5jEk$qBS`t?35$cY`XMzClcEt)6W`hks8$PS zV*$W>#=-EGiR!})V!E*~>kq{^@Za_k;CGs4yKz5>6n$RQ**(+{|4IxbTdrYsh> zGWVr^#PAlX1XPwb^SxbGaD*e9uK5zJK4tJ*XoMA{+tXm)=-LdhMNyP*{ITak9DeKx ziW2D-un1EZKatzde+(FYIE{7&e!!w?VXR;{fYeEm$>8693c8q*TR7^$Petemq0S&k zsbOYHq3)&kAT@&W_5uzQ8}TTKOd2Cmn-BVPR#EF&$W)p^1J#4j6&13?zP$QEmKiW= zn`)M1u&HLAg9*2|hN<#ZK`@aUoERZ$V-bM}UL+))@@0*If1uw}w(9spNvp7yxBwoe zm-`J~B6IL0zvQA&$Qi}UW^+0QRFO`Dp*OLxCeSTenGymK&o~KVufTuPa9lpL;bkxY z{OLmu$)oI1j3VTQ;r{hB)Wl+S!udwCLXu~pL@r->JI7pAHex6eFpGw_`mHV`jDI)O zVkV{T>XkNGf9`-SMX*=B-S$DL5qlas8Yt(vfIrqb7tTWw zIXpu`4wNS3tO{39jC+JmxwqtAWcRosD_TSYS*V|DbP5MT_A9JLY*VUeq-hY!fVWp8F6MQ=tRMNdW` Dgv(8m literal 10343 zcmeHNJ&Pqp6s_s;3qP+31)J!SnbJ#Ck3&)Maz7wpol?b83Um(uX_vv#|0 zw}X9BcgrsQo1L{z(fRl81XwS}UXga|0bAK?VYpENS|JP^+W$%#&t*APm{^UHWXv7?`LQ9)*n^ zZ#M|-@@xyCDJZ7JQZ5iJVNz57$o|P+SxXt4(GjM$yABg{bnn^4lMt!WpPmD7a7RJM zU?0z+j8?>Z&7L{lfwhQ78eUp{GQ}%az{~d8;DPQEyyDT{KgZjRLNpO0^$t$b8!_i)DIv?(sOf za7ap04Ib10t9doDS-7x?vqcXSqgIZy(9$Dg3|!;ZzWi;gNCi37DlzyDfs10yW%tW~3U&fVu-)$9BzVMLg+u zRk{2uP}PX_&Z=EiuKGNr~>SW72P6J#G9(r3|cgnKxrErpOHeSU|TI> zg%GJti8!yHIM3s0T*@vt4;8D7f4=5cgDiDP?(+7>1OeZRH6?*` zgb!&kz^w~h@T|$DY;ElIRUvVvULgVQ0^X!C^vlJgNmr{3a~YXVA-C+P=?XQw`WE;# zZtau0W4mOu0*y+r@6nCFI6X{Jba)9@ShHVqiK3#<+faS7K)J7SYUe@aQD$(3XVo+Y zx@E_XkxP4=-1v=eh0SZX-GB!wRnm97IGzSC1S$sh;@6yL$nQgUUxt2!c~ zfKrTIc7}y#m*5u^`pi&PKiEYIdH946i9VJo!*`m&!ZnC-5}~Sv2xMvHCb$NZ1*$P~ z+>Oa~NzOqvRDnwrvax<1R@o~Q?|>fXyimlytdNE2j_dO8FJub^bM3FH*(S}ds+pId zkltE|840tc+@Q2@)v}stIn!4iTTn1iWjx-o(U}HZ+yt$N7fO{%>Dr8Q%VS)Y=F55$ zAnaB}2>zb3Z<}fAxuuE=jthjULJgZu05ykAvf^jJo*4@~FF|9O1{vcw$i5VXPVXq* zFa{*bjFFFLvP6 zr*VBq{Ak;kBU6(-2GSN7ep0JE#>bQ@-qO(niU0~)c&P`MZ=fj;C#_Hm)HI3&BZ`79 zzDcuB6HQq$aaKX+aqsGZ1>eEq7pF*<9YRPAe->CFJL61;feN0}JuT`s7$nU! zP@3$&ed2tk*Tn>_{4qKTs6E-RCvhH*JJ?mi;>WrbLm(8H(geBI11f`%gR+BPoB1*h zGwA&23t+-~uJIY{{8`C%n8g=BGHY;V}MlhMerF=Rm$Uh#ZY-hT4}w74xE8y z#}<(Mn?RDK(~S->4X-A7D364sGkqt60r8lBfrb`N z=os@8gKF6qj~ISy*%#wVp%Q)tKRIrLX_c%9RU*d4^cd?rLTz8u9!y#1`?eG|Un5Z+ e)l0eqi1Qg5RY4iX#shlYmn}m|CwFdU-24vh#-WS= diff --git a/data/music/030_scar_tissue.pomf b/data/music/030_scar_tissue.pomf index 1aa14db7debc11d348e649e131697e4d7bf4d145..f3d0a1c2816e5a64dfb10faeecd223ec169ba0d6 100644 GIT binary patch delta 673 zcmV;S0$%;jGV%omP)}`U0RfRdAdx0Qe_C2}0ssKm7ytn6SG`WdFc7wz7BQBg8$($b zI)#Z1b!9;+%E$vSb?C|)AhtdL5>lnU4H9$4j))Z@bs%?1?qcUIKdn?M5f7GQe|Ns0 z@7${$m}J~qW6n;J#RW`Pr^(cN>m~C|kgR4lgY?!W-&>oiJ(OVCd7^6gZOWf0f3bwm z5s3ZR{L>J4WQ(|TrS8qFvp1&|Uyk}x8=OYD6Q6r^d=s-b1AA>a`eXx{YG|~`` z#H2`iHKPaduxtWGFhO)8-N7f6Rq8KPluo^viWp^KA%+CYiWvq&kISZ>TyWbCh6x5HehibIqYs;t2Fb7fS}hz~#0*Zzv`L=$Chvw< z0ZTzkb$S4&%T}j{aFT+W%v8#%&nAvSW>g0$Gh>Loml>38m!1ZN(-hYgSUOr27^YFG zGE~qmm;bWVR+`~jsRh<#f1_2siI3oQWja$Kt z57%+GCQ^F3H=7##lOu4GJ~4JFieM>12?1hpJ2;hV z^p{7aSjp&9fXcDqX93y?2oGGSsy*C z?``kZcQ(h*$MxE1XJ@oKsc+P?_>N`m?XTYbbfu~~=dp9YQ&pEP$l@wqH!sSo`>reR z+dWx5lv9#)4`iWxT!AgzBZu*BiKzZJVO3G~Nhxn|dKsd=LlHlrM~Qim=u}&Ak9r|M z>7Yngrkpnaj&H>nd`{YS#Sisp1&-k9_ZaK0c@(4mr3NK`UEaoT)cvyR`RR5Kd=h+m}%v>Cd#{Q4$2!G0w8vPm9jmCWST*}n}H4^emR>M zMpE*?*#areRuYin*FdPZk5U|o^PE;;k8y5Z9ZTlQhl$D)iD6fXouyO`?CNP0I_Nc( zl@XVW^u$qqX{5N3!6LMep0{hJ9K^+<3GgvAMOjePt%7bvUXA>;-kKuxm;gc)t%@8G zxL9-Tb(Z2O|Nlhywv--cpHY&KRrLJK0?Gfa@o#MfArbM#SytvF?SMOpD7uij;BrMS>EGsO&EPZ`821RP9@{LN5e z5i%*$(*rsm9OIpyoygYo7soq?v zX=ZMTtnxrG*PsM#Y!B)T=Ms)|t_vW8GX`+GSYUyN0NtW^8=Z@TI<=7)YNH5c6V5Es*q5a(WFV zCqcG&A2-2w`1IdRJ!;O3@OM>BG?s8Tz{unmN9m>6wu H)cE)bVe+bs diff --git a/data/music/031_space_harrier.pomf b/data/music/031_space_harrier.pomf index 6de8b595ad00425c69ea748d038ca46310c79010..4dbf740a6865a27a67eac40e5ad6e0c57af18ba0 100644 GIT binary patch delta 1029 zcmV+g1p51_S=0yyP)}`U0RfReAdx0Qe_C4B0{{RsEC2xQT0L*nKoDKuT|yF4I7O(P zh60I`Q>6mAL4pP$N_5wxqDp~;C{TJ7(NU(LO2IFH6Kx8*{DCVd(m+8=i)R*l*LyST zo%7yZV;9!gJM-S#*{`{eWLuTjpG2txu+lfBbp%#+Qd-A5rIkM_Z!f@QFa-+&f6&U` zgY`X{3(7zRNX|xRzt7_7%|(m+P>XDj=;GqC85wY;aLZIXfXRJ3Lb4BwU`}VO#*O__^I^9oJ#mHXT;H-CBq!=A(soRNsnX ze-ZRAJf3rGR0q8gWY)L{QY1m?e@^~*3f9p}IR`bfS4_!rxLR1va9NAaKbB_9#e&w+ z>4+TE9A7b|oTFceOkN%gs!5Igop}AsBAGBm!FcEbw;XQNF~J@LIwj2pYdLdDi-)^* zn2x0uHa5Wd#!i~z_nrqT*{|>pMiuDMs6sy81Lt=oUh!q8LZK`KHSeZPf6JV@lx1S^ z-Lz@_s1r+BCKlgK8`cn770jme)4;BRirMb}tm!l%iYXHAH{mf?zX0WI&?ruz!3+gP z;AQzC-s9l{o~cXJVdCL+>lXqFJ80o46@;gIg!5%4h1Yw|O(2mo0A~zQKCdFQ3pEPh zVr6$;HMEREJEa~4j@OmOf2PUcDHVi=J&F$MWc)P)pWjpw+9hD#*Adpcc6gm#j>DC~ zCZb)gMTx>;d(935MPk;RZuvQ!Jip{PuBr&_LV-FiR1UBowVygkJb11%Jf>+0n!#a{ zpE4ZzbuHtRL&i?uLZ@N#a3j2+T82p&$6+FdNln>r;S0R|7T#~+e^o@kg{yuG2l6gk z_=E$UHDx#nLyl>~Lg5;q+2Bsc=g?|4^GkR18wyU9^_7$a8H*GDS687>8ih)j z9HsdSzP5;W8W|ggb;B#p8Ijqa-6`a+#P96H9~kg*{#Wo1Wp8F6MQ=tRMNdW`x+>&| literal 11433 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 diff --git a/data/music/033_my_name_is_nobody.pomf b/data/music/033_my_name_is_nobody.pomf index 1b41b1f42d423f14e949d4d284e745009c3a6bee..d566e61932797adcc25a9a92662cb73b63c12e07 100644 GIT binary patch delta 4220 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 S+WiM*Z)PAxZ$=Bl&; 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%0Dkp|Q@&KMbKUs`HHO8F zt1@}xD890X&TWUe6OR>2kTewvt(6z7o0c$O)+z!lx1y>LxXD~%UrE(y^(E$91ke}J zELd1Af2Q&M8kp)nMF5+_$~eF=TMUO*uZd@5VKhuT!GDfE3vfn7*jBza6FD))UaWEU zPf9z}sD8~l;hEJ&3w8SzfhJ$^RwRYJA!))>pm@O-E{8{Cp6bs2 zyUL<4kZCj`^LtG^yD(hM;P|>V&fV&Z%u0`^wr(~FnFQ&>p1d*F zeX=AA`3Kn+q_T?U(8VsC+NQd53Ai2YiQ{3IYEHvc=}GV-2n#E|1vMSr!MK1kD?bF! zgrrxv7-g*H-0@xwtp?m1m7oU%l2spUlBvyg&>if%%K&%|E4&(q3IXVLb)SALA-~ML dr7GCu1CyJ9P12vB^9pD9xi`LW>kAY8{{_)by+;55 diff --git a/helper/elf2pomf.py b/helper/elf2pomf.py index 61c6e5e..0b5b9b2 100644 --- a/helper/elf2pomf.py +++ b/helper/elf2pomf.py @@ -3,6 +3,22 @@ from elftools.elf.elffile import ELFFile from sys import argv import pdb +import zlib + +FS_BLKSZ = 4096 + +def compress_bytes(data, level = 5): + assert(zlib.MAX_WBITS == 15) + compress = zlib.compressobj( + level, + zlib.DEFLATED, + -zlib.MAX_WBITS, + zlib.DEF_MEM_LEVEL, + 0 + ) + rslt = compress.compress(data) + rslt += compress.flush() + return rslt INNAME=argv[1] OUTNAME=argv[2] @@ -66,17 +82,42 @@ track_data[offset + 3] = idx_le[3] cur_sample_index += 1 +def create_pomf(compressed): + global samples_indexed, track_data, header + out = bytearray(header) + for s in samples_indexed: + sdata = bytearray(s['header']) + bytearray(s['data']) + orig_size_le = len(sdata).to_bytes(4, byteorder = 'little') + if compressed: + sdata = compress_bytes(sdata) + size_le = len(sdata).to_bytes(4, byteorder = 'little') + out += (b'saZZ' if compressed else b'saMP') + out += (size_le) + out += (orig_size_le) + out += (sdata) + orig_size_le = (len(track_data)).to_bytes(4, byteorder = 'little') + if compressed: + track_data = compress_bytes(track_data) + size_le = (len(track_data)).to_bytes(4, byteorder = 'little') + out += (b'tuZZ' if compressed else b'tuNE') + out += (size_le) + out += (orig_size_le) + out += (track_data) + out += (b'eof EoF EOF ') + return out + +uncomp = create_pomf(False) +comp = create_pomf(True) + +sz_uncomp_blocks = len(uncomp) // FS_BLKSZ + 1 +sz_comp_blocks = len(comp) // FS_BLKSZ + 1 + outf = open(OUTNAME, 'wb') -outf.write(header) -for s in samples_indexed: - outf.write(b'saMP') - size_le = (len(s['header']) + len(s['data'])).to_bytes(4, byteorder = 'little') - outf.write(size_le) - outf.write(s['header']) - outf.write(s['data']) -outf.write(b'tuNE') -size_le = (len(track_data)).to_bytes(4, byteorder = 'little') -outf.write(size_le) -outf.write(track_data) -outf.write(b'eof \x00\x00\x00\x00') +if sz_comp_blocks < sz_uncomp_blocks: + print("Compression saves",(sz_uncomp_blocks - sz_comp_blocks),"of 4K FS blocks: from",sz_uncomp_blocks,"to",sz_comp_blocks) + outf.write(comp) +else: + outf.write(uncomp) + +outf.close() \ No newline at end of file diff --git a/include/miniz_ext.h b/include/miniz_ext.h new file mode 100644 index 0000000..b711efc --- /dev/null +++ b/include/miniz_ext.h @@ -0,0 +1,54 @@ +#include + +// MiniZ extra functions that are not present in the ROM + + +// Flush values. For typical usage you only need MZ_NO_FLUSH and MZ_FINISH. The other values are for advanced use (refer to the zlib docs). +enum { MZ_NO_FLUSH = 0, MZ_PARTIAL_FLUSH = 1, MZ_SYNC_FLUSH = 2, MZ_FULL_FLUSH = 3, MZ_FINISH = 4, MZ_BLOCK = 5 }; + +// Return status codes. MZ_PARAM_ERROR is non-standard. +enum { MZ_OK = 0, MZ_STREAM_END = 1, MZ_NEED_DICT = 2, MZ_ERRNO = -1, MZ_STREAM_ERROR = -2, MZ_DATA_ERROR = -3, MZ_MEM_ERROR = -4, MZ_BUF_ERROR = -5, MZ_VERSION_ERROR = -6, MZ_PARAM_ERROR = -10000 }; + +// Compression levels: 0-9 are the standard zlib-style levels, 10 is best possible compression (not zlib compatible, and may be very slow), MZ_DEFAULT_COMPRESSION=MZ_DEFAULT_LEVEL. +enum { MZ_NO_COMPRESSION = 0, MZ_BEST_SPEED = 1, MZ_BEST_COMPRESSION = 9, MZ_UBER_COMPRESSION = 10, MZ_DEFAULT_LEVEL = 6, MZ_DEFAULT_COMPRESSION = -1 }; + +// Window bits +#define MZ_DEFAULT_WINDOW_BITS 15 + +// Heap allocation callbacks. +// Note that mz_alloc_func parameter types purpsosely differ from zlib's: items/size is size_t, not unsigned long. +typedef void *(*mz_alloc_func)(void *opaque, size_t items, size_t size); +typedef void (*mz_free_func)(void *opaque, void *address); +typedef void *(*mz_realloc_func)(void *opaque, void *address, size_t items, size_t size); + +struct mz_internal_state; + +// Compression/decompression stream struct. +typedef struct mz_stream_s { + const unsigned char *next_in; // pointer to next byte to read + unsigned int avail_in; // number of bytes available at next_in + mz_ulong total_in; // total number of bytes consumed so far + + unsigned char *next_out; // pointer to next byte to write + unsigned int avail_out; // number of bytes that can be written to next_out + mz_ulong total_out; // total number of bytes produced so far + + char *msg; // error msg (unused) + struct mz_internal_state *state; // internal state, allocated by zalloc/zfree + + mz_alloc_func zalloc; // optional heap allocation function (defaults to malloc) + mz_free_func zfree; // optional heap free function (defaults to free) + void *opaque; // heap alloc function user pointer + + int data_type; // data_type (unused) + mz_ulong adler; // adler32 of the source or uncompressed data + mz_ulong reserved; // not used +} mz_stream; + +typedef mz_stream *mz_streamp; + +/* Single-call decompression. */ +/* Returns MZ_OK on success, or one of the error codes from mz_inflate() on failure. */ +int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len); +int mz_uncompress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong *pSource_len); +const char *mz_error(int err); \ No newline at end of file diff --git a/include/sound/pomf.h b/include/sound/pomf.h index f14cb8b..6c9b1c1 100644 --- a/include/sound/pomf.h +++ b/include/sound/pomf.h @@ -27,22 +27,32 @@ Format in a nutshell: - rle_sample_t followed by .length bytes of sample data - if magic is 'tuNE': - .size bytes of melody_item_t data + - if magic is 'saZZ' or 'tuZZ': + - contents of 'saMP' or 'tuNE' respectively, compressed with DEFLATE with a -15 bit window. + `size` shows the length of the compressed data, `realsize` the length of the target buffer for uncompression. ] POMFChunk(size = 0, magic = ASCII 'eof ') + +Version history: + 1.0: Initial version + 1.1: Add primitive compression support (saZZ, tuZZ chunks) */ #define POMF_MAGIC_FILE 0x666D4F50 // 'POmf' little-endian #define POMF_MAGIC_SAMPLE 0x504D6173 // 'saMP' +#define POMF_MAGIC_SAMPLE_COMPRESSED 0x5A5A6173 // 'saZZ' #define POMF_MAGIC_TRACK 0x454E7574 // 'tuNE' +#define POMF_MAGIC_TRACK_COMPRESSED 0x5A5A7574 // 'tuZZ' #define POMF_MAGIC_END 0x20666F65 // 'eof ' #define POMF_CURVER_MAJ (1) -#define POMF_CURVER_MIN (0) +#define POMF_CURVER_MIN (1) #define POMF_CURVER ((POMF_CURVER_MAJ << 8) | (POMF_CURVER_MIN)) struct POMFChunkHeader { const uint32_t magic; const uint32_t size; + const uint32_t realsize; }; struct __attribute__((packed)) POMFHeader { diff --git a/src/miniz_ext.cpp b/src/miniz_ext.cpp new file mode 100644 index 0000000..cdf598c --- /dev/null +++ b/src/miniz_ext.cpp @@ -0,0 +1,277 @@ +#include +#include +#include + +typedef struct +{ + tinfl_decompressor m_decomp; + mz_uint m_dict_ofs, m_dict_avail, m_first_call, m_has_flushed; + int m_window_bits; + mz_uint8 m_dict[TINFL_LZ_DICT_SIZE]; + tinfl_status m_last_status; +} inflate_state; + + +void mz_free(void *p) +{ + free(p); +} + +void *miniz_def_alloc_func(void *opaque, size_t items, size_t size) +{ + (void)opaque, (void)items, (void)size; + return malloc(items * size); +} +void miniz_def_free_func(void *opaque, void *address) +{ + (void)opaque, (void)address; + free(address); +} +void *miniz_def_realloc_func(void *opaque, void *address, size_t items, size_t size) +{ + (void)opaque, (void)address, (void)items, (void)size; + return realloc(address, items * size); +} + +int mz_inflateInit2(mz_streamp pStream, int window_bits) +{ + inflate_state *pDecomp; + if (!pStream) + return MZ_STREAM_ERROR; + if ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS)) + return MZ_PARAM_ERROR; + + pStream->data_type = 0; + pStream->adler = 0; + pStream->msg = NULL; + pStream->total_in = 0; + pStream->total_out = 0; + pStream->reserved = 0; + if (!pStream->zalloc) + pStream->zalloc = miniz_def_alloc_func; + if (!pStream->zfree) + pStream->zfree = miniz_def_free_func; + + pDecomp = (inflate_state *)pStream->zalloc(pStream->opaque, 1, sizeof(inflate_state)); + if (!pDecomp) + return MZ_MEM_ERROR; + + pStream->state = (struct mz_internal_state *)pDecomp; + + tinfl_init(&pDecomp->m_decomp); + pDecomp->m_dict_ofs = 0; + pDecomp->m_dict_avail = 0; + pDecomp->m_last_status = TINFL_STATUS_NEEDS_MORE_INPUT; + pDecomp->m_first_call = 1; + pDecomp->m_has_flushed = 0; + pDecomp->m_window_bits = window_bits; + + return MZ_OK; +} + +int mz_inflateInit(mz_streamp pStream) +{ + return mz_inflateInit2(pStream, -MZ_DEFAULT_WINDOW_BITS); +} + +int mz_inflateReset(mz_streamp pStream) +{ + inflate_state *pDecomp; + if (!pStream) + return MZ_STREAM_ERROR; + + pStream->data_type = 0; + pStream->adler = 0; + pStream->msg = NULL; + pStream->total_in = 0; + pStream->total_out = 0; + pStream->reserved = 0; + + pDecomp = (inflate_state *)pStream->state; + + tinfl_init(&pDecomp->m_decomp); + pDecomp->m_dict_ofs = 0; + pDecomp->m_dict_avail = 0; + pDecomp->m_last_status = TINFL_STATUS_NEEDS_MORE_INPUT; + pDecomp->m_first_call = 1; + pDecomp->m_has_flushed = 0; + /* pDecomp->m_window_bits = window_bits */; + + return MZ_OK; +} + +int mz_inflate(mz_streamp pStream, int flush) +{ + inflate_state *pState; + mz_uint n, first_call, decomp_flags = TINFL_FLAG_COMPUTE_ADLER32; + size_t in_bytes, out_bytes, orig_avail_in; + tinfl_status status; + + if ((!pStream) || (!pStream->state)) + return MZ_STREAM_ERROR; + if (flush == MZ_PARTIAL_FLUSH) + flush = MZ_SYNC_FLUSH; + if ((flush) && (flush != MZ_SYNC_FLUSH) && (flush != MZ_FINISH)) + return MZ_STREAM_ERROR; + + pState = (inflate_state *)pStream->state; + if (pState->m_window_bits > 0) + decomp_flags |= TINFL_FLAG_PARSE_ZLIB_HEADER; + orig_avail_in = pStream->avail_in; + + first_call = pState->m_first_call; + pState->m_first_call = 0; + if (pState->m_last_status < 0) + return MZ_DATA_ERROR; + + if (pState->m_has_flushed && (flush != MZ_FINISH)) + return MZ_STREAM_ERROR; + pState->m_has_flushed |= (flush == MZ_FINISH); + + if ((flush == MZ_FINISH) && (first_call)) + { + /* MZ_FINISH on the first call implies that the input and output buffers are large enough to hold the entire compressed/decompressed file. */ + decomp_flags |= TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF; + in_bytes = pStream->avail_in; + out_bytes = pStream->avail_out; + status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pStream->next_out, pStream->next_out, &out_bytes, decomp_flags); + pState->m_last_status = status; + pStream->next_in += (mz_uint)in_bytes; + pStream->avail_in -= (mz_uint)in_bytes; + pStream->total_in += (mz_uint)in_bytes; + pStream->adler = tinfl_get_adler32(&pState->m_decomp); + pStream->next_out += (mz_uint)out_bytes; + pStream->avail_out -= (mz_uint)out_bytes; + pStream->total_out += (mz_uint)out_bytes; + + if (status < 0) + return MZ_DATA_ERROR; + else if (status != TINFL_STATUS_DONE) + { + pState->m_last_status = TINFL_STATUS_FAILED; + return MZ_BUF_ERROR; + } + return MZ_STREAM_END; + } + /* flush != MZ_FINISH then we must assume there's more input. */ + if (flush != MZ_FINISH) + decomp_flags |= TINFL_FLAG_HAS_MORE_INPUT; + + if (pState->m_dict_avail) + { + n = std::min(pState->m_dict_avail, pStream->avail_out); + memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n); + pStream->next_out += n; + pStream->avail_out -= n; + pStream->total_out += n; + pState->m_dict_avail -= n; + pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1); + return ((pState->m_last_status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK; + } + + for (;;) + { + in_bytes = pStream->avail_in; + out_bytes = TINFL_LZ_DICT_SIZE - pState->m_dict_ofs; + + status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pState->m_dict, pState->m_dict + pState->m_dict_ofs, &out_bytes, decomp_flags); + pState->m_last_status = status; + + pStream->next_in += (mz_uint)in_bytes; + pStream->avail_in -= (mz_uint)in_bytes; + pStream->total_in += (mz_uint)in_bytes; + pStream->adler = tinfl_get_adler32(&pState->m_decomp); + + pState->m_dict_avail = (mz_uint)out_bytes; + + n = std::min(pState->m_dict_avail, pStream->avail_out); + memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n); + pStream->next_out += n; + pStream->avail_out -= n; + pStream->total_out += n; + pState->m_dict_avail -= n; + pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1); + + if (status < 0) + return MZ_DATA_ERROR; /* Stream is corrupted (there could be some uncompressed data left in the output dictionary - oh well). */ + else if ((status == TINFL_STATUS_NEEDS_MORE_INPUT) && (!orig_avail_in)) + return MZ_BUF_ERROR; /* Signal caller that we can't make forward progress without supplying more input or by setting flush to MZ_FINISH. */ + else if (flush == MZ_FINISH) + { + /* The output buffer MUST be large to hold the remaining uncompressed data when flush==MZ_FINISH. */ + if (status == TINFL_STATUS_DONE) + return pState->m_dict_avail ? MZ_BUF_ERROR : MZ_STREAM_END; + /* status here must be TINFL_STATUS_HAS_MORE_OUTPUT, which means there's at least 1 more byte on the way. If there's no more room left in the output buffer then something is wrong. */ + else if (!pStream->avail_out) + return MZ_BUF_ERROR; + } + else if ((status == TINFL_STATUS_DONE) || (!pStream->avail_in) || (!pStream->avail_out) || (pState->m_dict_avail)) + break; + } + + return ((status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK; +} + +int mz_inflateEnd(mz_streamp pStream) +{ + if (!pStream) + return MZ_STREAM_ERROR; + if (pStream->state) + { + pStream->zfree(pStream->opaque, pStream->state); + pStream->state = NULL; + } + return MZ_OK; +} +int mz_uncompress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong *pSource_len) +{ + mz_stream stream; + int status; + memset(&stream, 0, sizeof(stream)); + + /* In case mz_ulong is 64-bits (argh I hate longs). */ + if ((*pSource_len | *pDest_len) > 0xFFFFFFFFU) + return MZ_PARAM_ERROR; + + stream.next_in = pSource; + stream.avail_in = (mz_uint32)*pSource_len; + stream.next_out = pDest; + stream.avail_out = (mz_uint32)*pDest_len; + + status = mz_inflateInit(&stream); + if (status != MZ_OK) + return status; + + status = mz_inflate(&stream, MZ_FINISH); + *pSource_len = *pSource_len - stream.avail_in; + if (status != MZ_STREAM_END) + { + mz_inflateEnd(&stream); + return ((status == MZ_BUF_ERROR) && (!stream.avail_in)) ? MZ_DATA_ERROR : status; + } + *pDest_len = stream.total_out; + + return mz_inflateEnd(&stream); +} + +int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len) +{ + return mz_uncompress2(pDest, pDest_len, pSource, &source_len); +} + +const char *mz_error(int err) +{ + static struct + { + int m_err; + const char *m_pDesc; + } s_error_descs[] = + { + { MZ_OK, "" }, { MZ_STREAM_END, "stream end" }, { MZ_NEED_DICT, "need dictionary" }, { MZ_ERRNO, "file error" }, { MZ_STREAM_ERROR, "stream error" }, { MZ_DATA_ERROR, "data error" }, { MZ_MEM_ERROR, "out of memory" }, { MZ_BUF_ERROR, "buf error" }, { MZ_VERSION_ERROR, "version error" }, { MZ_PARAM_ERROR, "parameter error" } + }; + mz_uint i; + for (i = 0; i < sizeof(s_error_descs) / sizeof(s_error_descs[0]); ++i) + if (s_error_descs[i].m_err == err) + return s_error_descs[i].m_pDesc; + return NULL; +} diff --git a/src/sound/melodies.cpp b/src/sound/melodies.cpp index fad71d5..9adf355 100644 --- a/src/sound/melodies.cpp +++ b/src/sound/melodies.cpp @@ -6,6 +6,7 @@ #include #include #include +#include static char LOG_TAG[] = "MUDB"; @@ -107,6 +108,7 @@ class PomfMelodySequence: public MelodySequence { POMFChunkHeader chunk = { 0 }; rle_sample_t * cur_samp = nullptr; size_t r = 0; + size_t total = 0; bool reading = true; f = fopen(path, "rb"); @@ -135,14 +137,19 @@ class PomfMelodySequence: public MelodySequence { exists = true; do { - r = fread(&chunk, 1, sizeof(POMFChunkHeader), f); - if(r != sizeof(POMFChunkHeader)) { + total = 0; + while(total < sizeof(POMFChunkHeader) && r > 0) { + r = fread(((void*)&chunk) + total, 1, sizeof(POMFChunkHeader) - total, f); + total += r; + } + if(total != sizeof(POMFChunkHeader)) { ESP_LOGE(TAG, "ChunkHead read error, wanted %i bytes, got %i", sizeof(POMFChunkHeader), r); goto bail; } switch(chunk.magic) { case POMF_MAGIC_SAMPLE: + case POMF_MAGIC_SAMPLE_COMPRESSED: cur_samp = (rle_sample_t*) malloc(sizeof(rle_sample_t)); if(cur_samp == nullptr) { ESP_LOGE(TAG, "OOM allocating sample header"); @@ -155,7 +162,7 @@ class PomfMelodySequence: public MelodySequence { reading = false; goto bail; } - size_t total = 0; + total = 0; while(total < chunk.size && r > 0) { r = fread(((void*)cur_samp) + total, 1, chunk.size - total, f); total += r; @@ -166,6 +173,14 @@ class PomfMelodySequence: public MelodySequence { goto bail; } else { ESP_LOGV(TAG, "saMP read %i bytes", total); + if(chunk.magic == POMF_MAGIC_SAMPLE_COMPRESSED) { + cur_samp = (rle_sample_t*) decompress_emplace(cur_samp, chunk.size, chunk.realsize); + if(cur_samp == nullptr) { + reading = false; + goto bail; + } + ESP_LOGV(TAG, "saZZ decompressed to %i bytes", chunk.realsize); + } // Fix the data pointer to point after the header cur_samp->rle_data = (const uint8_t *) &cur_samp[1]; ESP_LOGI(TAG, "saMP @ 0x%x: SR=%i, root=%i, len=%i, mode=%i, data=0x%x", cur_samp, cur_samp->sample_rate, cur_samp->root_frequency, cur_samp->length, cur_samp->mode, cur_samp->rle_data); @@ -175,6 +190,7 @@ class PomfMelodySequence: public MelodySequence { } break; case POMF_MAGIC_TRACK: + case POMF_MAGIC_TRACK_COMPRESSED: if(array_ != nullptr) { ESP_LOGE(TAG, "Multiple tuNE chunks, wtf!!"); reading = false; @@ -186,7 +202,7 @@ class PomfMelodySequence: public MelodySequence { reading = false; goto bail; } - size_t total = 0; + total = 0; while(total < chunk.size && r > 0) { r = fread(((void*)array_) + total, 1, chunk.size - total, f); total += r; @@ -196,6 +212,16 @@ class PomfMelodySequence: public MelodySequence { reading = false; goto bail; } else { + if(chunk.magic == POMF_MAGIC_TRACK_COMPRESSED) { + array_ = (melody_item_t*) decompress_emplace((void*) array_, chunk.size, chunk.realsize); + if(array_ == nullptr) { + reading = false; + goto bail; + } else { + total = chunk.realsize; + ESP_LOGV(TAG, "tuZZ decompressed to %i bytes", chunk.realsize); + } + } num_rows_ = total / sizeof(melody_item_t); ESP_LOGV(TAG, "tuNE read %i rows in %i bytes", num_rows_, total); for(int i = 0; i < num_rows_; i++) { @@ -269,6 +295,27 @@ class PomfMelodySequence: public MelodySequence { std::vector samples = {}; int num_rows_ = 0; + void * decompress_emplace(void * compressed_data, uint32_t src_size, uint32_t decomp_size) { + unsigned long dst_sz = decomp_size; + void * dest = malloc(dst_sz); + if(dest == nullptr) { + ESP_LOGE(TAG, "OOM allocating decompression buffer of %i bytes", dst_sz); + return nullptr; + } + + int rslt = mz_uncompress((unsigned char*)dest, &dst_sz, (unsigned char*) compressed_data, src_size); + + free(compressed_data); + + if(rslt != MZ_OK) { + free(dest); + ESP_LOGE(TAG, "Decompress error %i: %s", rslt, mz_error(rslt)); + return nullptr; + } + + return dest; + } + void unload_samples() { for(auto i: samples) { free(i);