From 7cda29724547b598a6c063cf2fa908dab21f73fb Mon Sep 17 00:00:00 2001 From: "fix94.1" Date: Sun, 6 Jan 2013 18:33:29 +0000 Subject: [PATCH] -some small compression corrections --- data/custombanner.bin | Bin 10636 -> 7021 bytes data/save.bin | Bin 8432 -> 6891 bytes data/stub.bin | Bin 4132 -> 2530 bytes resources/wiiflow_game_booter/source/lz77.c | 8 +- resources/wiiflow_game_booter/source/lz77.h | 4 +- source/banner/AnimatedBanner.h | 2 +- source/channel/nand_save.cpp | 4 +- source/homebrew/homebrew.cpp | 12 +- source/unzip/lz77.c | 387 +++++++++----------- source/unzip/lz77.h | 68 ++-- 10 files changed, 230 insertions(+), 255 deletions(-) diff --git a/data/custombanner.bin b/data/custombanner.bin index 57af5d62efe8278f5bb32313fbdd8d012a5707f1..e9d0d130cac4779521b35d1deb0fc5fd72e17d22 100644 GIT binary patch literal 7021 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 o;C(%_wt?97hdOM*1%P<2Z(r>jNV(^b literal 8432 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 Ubd77GWrF3dzvZ6dfE9xO4Tf|gfB*mh diff --git a/data/stub.bin b/data/stub.bin index 6c1e3eb544abcb57425413065aac6d6726205e96..0fffaf070d597eacbc7997ff1432485e127c8793 100644 GIT binary patch literal 2530 zcmYL~4@?`^9mjuXJJ|fmY-*>Fn%3`p#&^V~K4ZXk?1(ea#+jpGVpDfxD#y+g7-`}J zvO3|24@^WOTH(~K(i9R%NgSo5B~@BQ6Dv^Bzw4r8O{=u)ADohnWYH9=q*6AQ+?-9* zo<2|C_kLgfetOdTJ-tGM3cw4X3Iv;K!RvYQNw`0F7E-~m>?sHi=A7jP%m7;fGrL&< zfaQw4K@MgW{61-lCLGxi&2uQq_evqP6(HrNSBLJ4~1xF_(~N%NX{evSn}{D5BuYZqE%2+A>ml=DcP2JkuYYfgmZ49Z8kCMRlfB5jt9dT831mHW6h zqTcK#EBA5fQIjhx_i1*a(cph1yJ~hLK~Lgug98_Tf&>Qe5-xu1aiey&R)9??4y|tp z@CyMD1XJ=@@Z`!YI5_bq{2f#A`Dj16cR{5bQDwqNBE^Xlz5`PLc z$WX&d@+v?9ANf}*$jWd;>CZ9)pup|^3#|G#2{nAe?|q3TvrR)5;4NQd`%JQ4z(5lh z&}Ih?DqbP=r_$VY#A%Z6L9r@%91(aOAHA9F5FSbQBKba)|70Ih?ni1g#B!3s+C@J4 zeTvWtye7JoLMV1qFJCSjrj`($-CCd26H zc1BQBG8w?uetdIVjz`2T3dbNIB*k>W!LRo72Z?bEv}YU~AUtr%Q-i52#e$_id-m_J z6&vPH>VzbHyE4?TS~hA85sNg>Vunjr&ahl% zxVa^^l-U=h)w`wrqTUoXEC+L>lF#_P$9pU4I0x*f)z+!+NACJWxA-mNs*uw}ZMXd1 z__k5;j=#nqSkdZ-D&ii+?zo#<3*l0WQ{YO6juVlhM4T>)v*)f)8t>hFdZ;-SZBdC2cJ%xyQOW!b%{=Ga#;@e zBE?v{j3k3bYY$WohpxdaZmD{`^jQqIx3ME@5hr;Aad&WEc~ue*Y{8&i^ByReu6fk; z9VKHz-@&YZ@!q>9(K(sF;oi5UOA4g!I9;J;b^l=1e~pbxR)9Gs{;7J=q2?&YKP5XU zEFtcV^l~~pY%pjmiDJXZ10{T)e&;cQzKLE$HAgm;%3U{511JDXR~rKOZf2Jh>Z@>MYN+tU;uGek?vX-d?+m6&4y^#!xKbdo`aQMFP*wj zI;C(`Aw5r!M&+-o+ieR1zI?+n4v)CRM*+hZR{HCpum&2>9hDGKe%2J-H5F6|*&CQF zNX)@D6?IB_sCl&%FFFXZ$(zyG`?sT~jWq`_{M@Cd&sDx?oZgVcj6U2L@aQeA4?{_^ zbjH|h9j1&IHD*3)m_Cd~{$PSA{})@7&$uAkx4teKOKtG1Bb9DmbVcplgx&=BD0q%R zu|gOJneo$dL013}1ZIYi12%{&6|rO2E3SMV!?>@bp%cXp<88y5O=SyCQ*Bb7fP9Kc z=7Qoy{|)`{LF4ik(1biJ5_6&0a)fDta9@ot+DG{MxjF0upO`t6Tqw=#3M^!fqoNON zJ9C-WpfWI%c>$T8c#BmdR=qbc#Mt5NhVBSz(2GA=V`FfgVaC865+ucrSg%A==@OV; zVOhg-nP?(`l)@-|3(IwlO`xS-v~)Dhc#cxym+W-0ty{>Yr1cI~9J7?!P~bqFN$8~N z$y=57<)#736~~AF%dhSWxtW|akWV;qKh1**N{s(Q?fF4kSVs- zX?XCRaZ1Vn#o}J8_Ri<$+aY1|f?#`?Slra*zo55wY;3rc$nVJh9eRuDqxE`Ifp7## zBY8xu?3B=1XO99+Kuukbd*wqC@u_$?fLIg{J3qF~DriM&+Sr;prt; zNaYq173!;QkeMSf+CJ+St1^k)D)O7^C6;(MO<)s5lh-)?m3gSsc>d4kkzeA*xliEy zM^8+VX?KyrC;oF6v$K;D=HYy%dc<*q5)$nIC@};Ehx}zEmqYcq0?F%j(2h4UXi=%KE7-H%Nv(z;HF>x%=RmKoqqDgp;>^chDBb+l^FMX&T{3QTQ zUm`BZ`qbvQWWv{clJ!+aMo}`&#%cR>B(7lXz{agh@XAbw`gKa$)Jk5blxuJj`(vw} z;#Pm8h_^cIGIea>w$ZnG)scMk@^3dh|dHyk%kbma@I1h^=h@vIj_B%@(bVJKCt(`k4 vRF+q>)VZ^}g_CS=Yu&LY!W6bix?4JTboNB@w?pfm9b89GXAj!m=BNJ+{{c!p literal 4132 zcmb7HeM}qY8Gp`p-~h8Zog0}#gGrcT8X{7SNJlZsk>w9FqAArJQE5|i?2HntG$l)z zj_`snm}rffN=~V?rUgRQ#8RY8YNhUvNegw=rfSt8b<--fTiZG7x`C=mRAo{&0=M6D zcQ(`sZD;AH_r2$yulMwmxL)b9w4bXs+pwe zp;%m}S#ipnWgf+(-9ir=V%VEKK$M7Tv{}>r2{EvYXQ^2+!^HBMo}(g-^#{^faSsp# zwg4gEKA;ZR3Iv|QdmspG0YboiKpn94DO-1xOcEqr782kAynqkb1e5{gfDBXsl|U8X z2daT@0pFG`+dgXKiJCauc)cZ#!*&K30-j4dcJu&6#{(pe!*&K30-kexP&9fVYUUi- zQ;>PSL}nPg&%6F=Vry%kl7w0$OZfUo!0CjHQ) za6DU{ieFirRdnmNxa!S5np(m(+rd$T1r=3yf^ z@frmtE`bN~!uTvJ1TX}g0!DyQ0Dfq?$F6T-{4I8Gn7z2A`Sx&pw}hUb%QSraLh(@1VtX-=iEW zmMhAa)&^#iNYxr_1G(ERG^vsI=!rc*SL%~xgK32tDCPyVlF&?wdp&;?LyiqQH(WzH zjWUg&ZJ*a{-s-ljkGRefTnEf!*IfCkQ*+jm{j57WOW(llwqYl=^ zs6fx8nOW@o|5-e1jav0gcK! z$E-!jo#)sUWDEUMYKP_b=1pq1A}aG^{;2Tn4EIsb-)R?TcU!Ah`7G}Hf4Q_zQx_LWowk0@ z^Hk9zs^hEgO3^lKl$|op_b}6Mv-ue44{KA2d_sgS|%18)gO1j1X+rA&23+#de);59`jP?DL(5zE53U zb`5Okx9c-}tHex|+jG`jd)|7-iOtIC0iCwBq-mQv3m@!yS$SL}78TxW>-tYA{Vzt(<&XltO&zH5ww-n@mS?IW>O=*}&n&>Vv+%8p zf;}2^R8Xkpf~`L>vbWn9+1~B;uXLl^T0W2bxIMgl9DDTe@+IH~_nZ1FY6T7TvHUdf zvP%oQv>~j>u`NfK!vol({%=2+nw(eFNs9KEAtg2J3G(bPhl}S73Vqqg;MshE&ns25 zPvVTjIO9}a?VPgScl`}<9?go#enqn;TTFZxOp@QGB_sP$8?D@5W5`7sxkw`yY2+e} zT%?f;^j#zRE`pwEM&Io&?K}QvLcQ&Ro(<@g|GO-P1?ni%jJT`~AIZEh>cQaK-DT8{!z6Q18H-Ujl^dG*{%%n{x=5f!v z)_3mA;d63M(hEC2MDJ4PBprmV%{+&=r}=vtF?jl9(#PL*L7abm@8^5onAyU7iSd`1 zudijADlvQbzN*IadGI@P^v)Sjyes+6;J81DJJ#)`AY>1nOOeFS=$o~;gZFNCDeO_y z%y3QIjFN94#d5RG`T2aAiX9()VCA-_5pjSMA8- zu7Umk9Jh5PBj#7hFpshjF*8RfocRScD&<(qiSH*F>wY}vu*UH0!+OAkKIp$knITEZ z0skZwz502x7dbWXEAHz04s?0e>AK?T zYAwjYhrH_p%N2Z(T{&`n;2dw*gN43A3=g?+n#X<<;v~7x_{LcIH)t>K&Dq}#zSQeq zpa)lOa=viphdBQ3_e;RJXI3!#R!_Tpzm0+q|J&rK+0&(scX9qMxO`Kt4$Q#SGnjGw z|L03}$7gM8sy)ZESgEQV7zxK7#(a--sG$F#_6er #include #include "homebrew.h" +#include "banner/AnimatedBanner.h" #include "gecko/gecko.hpp" #define EXECUTE_ADDR ((u8 *)0x91000000) @@ -110,9 +111,16 @@ void writeStub() /* Clear potential homebrew channel stub */ memset((void*)0x80001800, 0, 0x1800); + /* Extract our stub */ + u32 StubSize = 0; + u8 *Stub = DecompressCopy(stub_bin, stub_bin_size, &StubSize); + /* Copy our own stub into memory */ - memcpy((void*)0x80001800, stub_bin, stub_bin_size); - DCFlushRange((void*)0x80001800, stub_bin_size); + memcpy((void*)0x80001800, Stub, StubSize); + DCFlushRange((void*)0x80001800, StubSize); + + /* And free the memory again */ + free(Stub); } void BootHomebrew() diff --git a/source/unzip/lz77.c b/source/unzip/lz77.c index 629ef421..1f499fcf 100644 --- a/source/unzip/lz77.c +++ b/source/unzip/lz77.c @@ -1,210 +1,177 @@ -/******************************************************************************* - * lz77.c - * - * Copyright (c) 2009 The Lemon Man - * Copyright (c) 2009 Nicksasa - * Copyright (c) 2009 WiiPower - * - * Distributed under the terms of the GNU General Public License (v2) - * See http://www.gnu.org/licenses/gpl-2.0.txt for more info. - * - * Description: - * ----------- - * - ******************************************************************************/ -#include -#include -#include -#include -#include "lz77.h" -#include "loader/utils.h" -#include "memory/mem2.hpp" - -u32 packBytes(int a, int b, int c, int d) -{ - return (d << 24) | (c << 16) | (b << 8) | (a); -} - -s32 __decompressLZ77_11(const u8 *in, const u32 inputLen, u8 **output, u32 *outputLen) -{ - int x, y; - - u8 *out = NULL; - - u32 compressedPos = 0x4; - u32 decompressedPos = 0x0; - u32 decompressedSize = 0; - - decompressedSize = packBytes(in[0], in[1], in[2], in[3]) >> 8; - - if (!decompressedSize) - { - decompressedSize = packBytes(in[4], in[5], in[6], in[7]); - compressedPos += 0x4; - } - - //printf("Decompressed size : %i\n", decompressedSize); - - out = MEM2_memalign(32, decompressedSize); - if (out == NULL) - { - printf("Out of memory\n"); - return -1; - } - - while (compressedPos < inputLen && decompressedPos < decompressedSize) - { - u8 byteFlag = in[compressedPos]; - compressedPos++; - - for (x = 7; x >= 0; x--) - { - if ((byteFlag & (1 << x)) > 0) - { - u8 first = in[compressedPos]; - u8 second = in[compressedPos + 1]; - - u32 pos, copyLen; - - if (first < 0x20) - { - u8 third = in[compressedPos + 2]; - - if (first >= 0x10) - { - u32 fourth = in[compressedPos + 3]; - - pos = (u32)(((third & 0xF) << 8) | fourth) + 1; - copyLen = (u32)((second << 4) | ((first & 0xF) << 12) | (third >> 4)) + 273; - - compressedPos += 4; - } else - { - pos = (u32)(((second & 0xF) << 8) | third) + 1; - copyLen = (u32)(((first & 0xF) << 4) | (second >> 4)) + 17; - - compressedPos += 3; - } - } else - { - pos = (u32)(((first & 0xF) << 8) | second) + 1; - copyLen = (u32)(first >> 4) + 1; - - compressedPos += 2; - } - - for (y = 0; y < (int)copyLen; y++) - { - out[decompressedPos + y] = out[decompressedPos - pos + y]; - } - - decompressedPos += copyLen; - } else - { - out[decompressedPos] = in[compressedPos]; - - decompressedPos++; - compressedPos++; - } - - if (compressedPos >= inputLen || decompressedPos >= decompressedSize) - break; - } - } - *output = out; - *outputLen = decompressedSize; - return 0; -} - -s32 __decompressLZ77_10(const u8 *in, u8 **output, u32 *outputLen) -{ - int x, y; - u8 *out = NULL; - - u32 compressedPos = 0; - u32 decompressedSize = 0x4; - u32 decompressedPos = 0; - - decompressedSize = packBytes(in[0], in[1], in[2], in[3]) >> 8; - - //int compressionType = (packBytes(in[0], in[1], in[2], in[3]) >> 4) & 0xF; - - //printf("Decompressed size : %i\n", decompressedSize); - - out = MEM2_memalign(32, decompressedSize); - if (out == NULL) - { - printf("Out of memory\n"); - return -1; - } - - compressedPos += 0x4; - - while (decompressedPos < decompressedSize) - { - u8 flag = *(u8*)(in + compressedPos); - compressedPos += 1; - - for (x = 0; x < 8; x++) - { - if (flag & 0x80) - { - u8 first = in[compressedPos]; - u8 second = in[compressedPos + 1]; - - u16 pos = (u16)((((first << 8) + second) & 0xFFF) + 1); - u8 copyLen = (u8)(3 + ((first >> 4) & 0xF)); - - for (y = 0; y < copyLen; y++) - { - out[decompressedPos + y] = out[decompressedPos - pos + (y % pos)]; - } - - compressedPos += 2; - decompressedPos += copyLen; - } else - { - out[decompressedPos] = in[compressedPos]; - compressedPos += 1; - decompressedPos += 1; - } - - flag <<= 1; - - if (decompressedPos >= decompressedSize) - break; - } - } - - *output = out; - *outputLen = decompressedSize; - return 0; -} - -int isLZ77compressed(const u8 *buffer) -{ - if((buffer[0] == LZ77_0x10_FLAG) || (buffer[0] == LZ77_0x11_FLAG)) - return 1; - return 0; -} - -int decompressLZ77content(const u8 *buffer, const u32 length, u8 **output, u32 *outputLen) -{ - int ret; - switch (buffer[0]) - { - case LZ77_0x10_FLAG: - //printf("LZ77 variant 0x10 compressed content...unpacking may take a while...\n"); - ret = __decompressLZ77_10(buffer, output, outputLen); - break; - case LZ77_0x11_FLAG: - //printf("LZ77 variant 0x11 compressed content...unpacking may take a while...\n"); - ret = __decompressLZ77_11(buffer, length, output, outputLen); - break; - default: - //printf("Not compressed ...\n"); - ret = -1; - break; - } - return ret; -} +/******************************************************************************* + * lz77.c + * + * Copyright (c) 2009 The Lemon Man + * Copyright (c) 2009 Nicksasa + * Copyright (c) 2009 WiiPower + * + * Distributed under the terms of the GNU General Public License (v2) + * See http://www.gnu.org/licenses/gpl-2.0.txt for more info. + * + * Description: + * ----------- + * + ******************************************************************************/ +#include +#include +#include "lz77.h" +#include "memory/mem2.hpp" + +static inline u32 packBytes(int a, int b, int c, int d) +{ + return (d << 24) | (c << 16) | (b << 8) | (a); +} + +static int __decompressLZ77_11(const u8 *in, u32 inputLen, u8 **output, u32 *outputLen) +{ + int x = 0; + u32 y = 0; + u32 compressedPos = 0x4; + u32 decompressedPos = 0; + u32 decompressedSize = packBytes(in[0], in[1], in[2], in[3]) >> 8; + if(decompressedSize == 0) + { + decompressedSize = packBytes(in[4], in[5], in[6], in[7]); + compressedPos += 0x4; + } + //printf("Decompressed size : %i\n", decompressedSize); + + u8 *out = (u8*)MEM2_alloc(decompressedSize); + if(out == NULL) + { + //printf("Out of memory\n"); + return -1; + } + + while(compressedPos < inputLen && decompressedPos < decompressedSize) + { + u8 byteFlag = in[compressedPos]; + compressedPos++; + + for(x = 7; x >= 0; x--) + { + if((byteFlag & (1 << x)) > 0) + { + u8 first = in[compressedPos]; + u8 second = in[compressedPos + 1]; + + u32 pos, copyLen; + if(first < 0x20) + { + u8 third = in[compressedPos + 2]; + if(first >= 0x10) + { + u32 fourth = in[compressedPos + 3]; + pos = (u32)(((third & 0xF) << 8) | fourth) + 1; + copyLen = (u32)((second << 4) | ((first & 0xF) << 12) | (third >> 4)) + 273; + compressedPos += 4; + } + else + { + pos = (u32)(((second & 0xF) << 8) | third) + 1; + copyLen = (u32)(((first & 0xF) << 4) | (second >> 4)) + 17; + compressedPos += 3; + } + } + else + { + pos = (u32)(((first & 0xF) << 8) | second) + 1; + copyLen = (u32)(first >> 4) + 1; + compressedPos += 2; + } + for(y = 0; y < copyLen; y++) + out[decompressedPos + y] = out[decompressedPos - pos + y]; + decompressedPos += copyLen; + } + else + { + out[decompressedPos] = in[compressedPos]; + decompressedPos++; + compressedPos++; + } + if(compressedPos >= inputLen || decompressedPos >= decompressedSize) + break; + } + } + *output = out; + *outputLen = decompressedSize; + return 0; +} + +static int __decompressLZ77_10(const u8 *in, u8 **output, u32 *outputLen) +{ + int x = 0; + u32 y = 0; + u32 compressedPos = 0x4; + u32 decompressedPos = 0; + u32 decompressedSize = packBytes(in[0], in[1], in[2], in[3]) >> 8; + //printf("Decompressed size : %i\n", decompressedSize); + + u8 *out = (u8*)MEM2_alloc(decompressedSize); + if(out == NULL) + { + //printf("Out of memory\n"); + return -1; + } + + while(decompressedPos < decompressedSize) + { + u8 byteFlag = in[compressedPos]; + compressedPos ++; + + for(x = 0; x < 8; ++x) + { + if(byteFlag & 0x80) + { + u8 first = in[compressedPos]; + u8 second = in[compressedPos + 1]; + u16 pos = (u16)((((first << 8) + second) & 0xFFF) + 1); + u8 copyLen = (u8)(3 + ((first >> 4) & 0xF)); + for(y = 0; y < copyLen; y++) + out[decompressedPos + y] = out[decompressedPos - pos + (y % pos)]; + compressedPos += 2; + decompressedPos += copyLen; + } + else + { + out[decompressedPos] = in[compressedPos]; + compressedPos += 1; + decompressedPos += 1; + } + byteFlag <<= 1; + if(decompressedPos >= decompressedSize) + break; + } + } + *output = out; + *outputLen = decompressedSize; + return 0; +} + +int isLZ77compressed(const u8 *buffer) +{ + if((buffer[0] == LZ77_0x10_FLAG) || (buffer[0] == LZ77_0x11_FLAG)) + return 1; + return 0; +} + +int decompressLZ77content(const u8 *buffer, u32 length, u8 **output, u32 *outputLen) +{ + int ret = 0; + switch(buffer[0]) + { + case LZ77_0x10_FLAG: + //printf("LZ77 variant 0x10 compressed content...unpacking may take a while...\n"); + ret = __decompressLZ77_10(buffer, output, outputLen); + break; + case LZ77_0x11_FLAG: + //printf("LZ77 variant 0x11 compressed content...unpacking may take a while...\n"); + ret = __decompressLZ77_11(buffer, length, output, outputLen); + break; + default: + //printf("Not compressed ...\n"); + ret = -1; + break; + } + return ret; +} diff --git a/source/unzip/lz77.h b/source/unzip/lz77.h index 6afc4468..45c189a5 100644 --- a/source/unzip/lz77.h +++ b/source/unzip/lz77.h @@ -1,34 +1,34 @@ -/******************************************************************************* - * lz77.h - * - * Copyright (c) 2009 The Lemon Man - * Copyright (c) 2009 Nicksasa - * Copyright (c) 2009 WiiPower - * - * Distributed under the terms of the GNU General Public License (v2) - * See http://www.gnu.org/licenses/gpl-2.0.txt for more info. - * - * Description: - * ----------- - * - ******************************************************************************/ - -#ifndef _LZ77_MODULE -#define _LZ77_MODULE - -#define LZ77_0x10_FLAG 0x10 -#define LZ77_0x11_FLAG 0x11 - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -int isLZ77compressed(const u8 *buffer); -int decompressLZ77content(const u8 *buffer, const u32 length, u8 **output, u32 *outputLen); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif - +/******************************************************************************* + * lz77.h + * + * Copyright (c) 2009 The Lemon Man + * Copyright (c) 2009 Nicksasa + * Copyright (c) 2009 WiiPower + * + * Distributed under the terms of the GNU General Public License (v2) + * See http://www.gnu.org/licenses/gpl-2.0.txt for more info. + * + * Description: + * ----------- + * + ******************************************************************************/ + +#ifndef _LZ77_MODULE +#define _LZ77_MODULE + +#define LZ77_0x10_FLAG 0x10 +#define LZ77_0x11_FLAG 0x11 + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +int isLZ77compressed(const u8 *buffer); +int decompressLZ77content(const u8 *buffer, u32 length, u8 **output, u32 *outputLen); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif +