From c9b7cf70b42b2407e36f435d4892f6507e28277f Mon Sep 17 00:00:00 2001 From: giantpune Date: Thu, 30 Jul 2009 02:54:08 +0000 Subject: [PATCH] now if the name of installed channels is not in the database.txt, we try to fine it from inside the channel itself. first try the 00000000.app with the system language, then with english. if there is still no name for the title, look in banner.bin also made a kick-ass clone of the wii settings screen to adjust the normal wii settings. it is after all the channels. --- Makefile | 8 + data/certs.dat | Bin 0 -> 2560 bytes data/haxx.certs | Bin 0 -> 2560 bytes gui.pnproj | 2 +- gui.pnps | 2 +- source/menu.cpp | 3 +- source/prompts/TitleBrowser.cpp | 233 +++++++++++------------ source/svnrev.c | 2 +- source/wad/id.c | 210 +++++++++++++++++++++ source/wad/id.h | 38 ++++ source/wad/patchmii_core.c | 94 +++++++++ source/wad/patchmii_core.h | 63 +++++++ source/wad/sha1.c | 172 +++++++++++++++++ source/wad/sha1.h | 12 ++ source/wad/title.c | 325 ++++++++++++++------------------ source/wad/title.h | 22 +-- source/xml/xml.c | 2 +- 17 files changed, 860 insertions(+), 328 deletions(-) create mode 100644 data/certs.dat create mode 100644 data/haxx.certs create mode 100644 source/wad/id.c create mode 100644 source/wad/id.h create mode 100644 source/wad/patchmii_core.c create mode 100644 source/wad/patchmii_core.h create mode 100644 source/wad/sha1.c create mode 100644 source/wad/sha1.h diff --git a/Makefile b/Makefile index 9ec65392..132c4efd 100644 --- a/Makefile +++ b/Makefile @@ -20,6 +20,7 @@ SOURCES := source source/libwiigui source/images source/fonts source/sounds \ source/libwbfs source/unzip source/language source/mload source/patches \ source/usbloader source/xml source/network source/settings source/prompts \ source/ramdisc source/wad source/banner source/cheats source/homebrewboot +DATA := data INCLUDES := source #--------------------------------------------------------------------------------- @@ -150,6 +151,13 @@ language: $(wildcard $(PROJECTDIR)/Languages/*.lang) @echo $(notdir $<) $(bin2o) +%.certs.o : %.certs + @echo $(notdir $<) + $(bin2o) +%.dat.o : %.dat + @echo $(notdir $<) + $(bin2o) + export PATH := $(PROJECTDIR)/gettext-bin:$(PATH) diff --git a/data/certs.dat b/data/certs.dat new file mode 100644 index 0000000000000000000000000000000000000000..2184107db41e656e1a40ce57b3898fdebe9ab42e GIT binary patch literal 2560 zcmb`FS5y<&7KRfA0u05B!J&vW1se&{38EkpP*hN&p_jl=!~_H}Bot{9dRMBni9iTN z2sMCoLNC%(Vg#(AhY}((cxTp~d6>65djI{f*IDa)|HED%00;n3%c=67XZ5~Gnd;*X zeKR9WyF~UrD!ZjD$L0f0a9oZ{90uJ_d@DIW9H7)E+AKJF=9vEy2w#Vq&^mgsnCm43 zX4Wox1S2G633&OxEb?>$bBP7osm?QYxib~5UbEb2VPUpJpOexDjO+9)ogOJ$gAwA zP!@#xwJF?NxKM+{q`D z#>(EFQZ4SKn3`>A$jP*a7&j4itWQlhM3g7oGP8;Prj@S6-U8~%5jQQUivV6Dey>Up|#?p(jOMoB94KJ^IKY;&<0u2pR{+l!3*JQI3 zWLu5zn_roe>si<|3$htF)eIUu#M?89@ zibTG=x|F{ygUnnX&w3H(&8r@k+I8kziyEi7NSH2RU)bD@k^QL>!#A2^FcZ(B%Zgng zg`e_hi}M)L1;GK%jxdC>T8Purg*(Z%lV}Zm=c3E-#Z^lTgjO1*4$MBcxH66h0RNcp z$sgP`fCKw{q+fhpj*+wIME2&O9dcw)Ufl;pA<-;eQ1w18u*)+<2efRjMM3nBvMBr{&?B5!yS-viWdtHxjrwzy8(F<>1@!F0ASW z;|_jWOCAM3#PuJqo4r<8Fe7GdP8tihW8vqr34FA-U5| zE#UfxX>n7dgc%b5=vpMlxoe&S~52^*g^HE8-OBqGM0C#NW(j0rJUYq)bD z-bBsTPKbizK_iWC8l6l6cvsy@vHc}-en=KG$T$tv!Yb|7$hr;+#b zsbmgQ+$p@-RMjn&4mE#uL^Gc;-x!oHcMkD*pN!h!=N0k0DMZ!Miwyry5?Ok0Q1ZdK zIHsy|Wa=GoS+QuS#5g?jNBj?ZVo$pf$|&ZugYmo1#L(fx!Q^E2&$xw$3$4 zMh&9;L;wD|V{&Qeo;d^I#*gQj8Do`-x>u@+5lUe`t4aq=i5-?x0qFJG)|@(8T(ktV zn=iWT-qCz{0sZ|e8Kf2%P}l1G2iH53i`LVm)B_vWzSig=2H3R_XwBanOYsdqVr_y4-aE^avSJ62jR0g_fBrxWfPJ*$2sUd6h#Q)9(ffVDL6j z67wRVvs=5wEkzp?JJD5bRCeM}6y~Ie)wN~YUJZ}ft7z@FygpY4IiVpj-uL*dR9d;$ z4YWRs?a&H*8fHE2IKBUOw*B+>|HFSvi@*F=`)Bw6`eHZajg^DQS}_3!go5Zg&vW0@ zs{*1a$Evt@E3L_!mbqi$`&1J`C1qAe1$y~34Y|n1Io&2FIAMecdFV;9DgD&cbFF&Y zj<~q)wk%3AAgj6Bqk^oNl&=WreL#N>>uT3PhE58F0HgkvTiBXou{6rq@r<>v9w3SC z==*WktC{KAV50KYd{JjCjFEtP)8c?wRGN~w!KvV)>sPXR!V0Uh$hDSV7pc*(7W2L> z#${|y_MTCQI{AXQGPB-cc8vN~B>i1x2+>=-qdJ_e;TLGFvU^@7f|OO-cH|SEhgkx| l4R;5JEbUe{{fa&sEGgo literal 0 HcmV?d00001 diff --git a/data/haxx.certs b/data/haxx.certs new file mode 100644 index 0000000000000000000000000000000000000000..32dd50ca02361daeda4db661dc2813dbffa83839 GIT binary patch literal 2560 zcmb`I_g@l<8pfei)Z>T~b{v_jv?Z8Z%+gA zHMh7&t_G1>TDWl_nMZH;bNdVQKEHq8&--~l&+|S2AOPt9(vEgJh*7|23*&eD7)gf@ z1dtQhFS4hGR$F9Bo7+|-8I_2VnVy5yC*+dRol^$Fb+Z?lsl#Q8y4Nd+p-RDC%Swk$ zh^-dme(2Szrp#(ubc6)7gD;}^(eWI40sVtZsia02P}lO}jLZG8d8-Lh(xJ7RKP&YR zz3eK5!C+2o6{e1-ptbPKl(g?iMxJo|2 zZ7(Fzlye`JS&`Q*vW7zrsKy3K$}A5Fbn$6k z<|6B+bn6}Agh3+YnFqTq!DaC1~;BmG!9VPUL1P1qV z4B(fK_jJ8q6t#pZ?{QvlSIR^mcVyR;FyS25^}P75vK*TaILdK8DRC6^IPSCL^njmI zw`hal(76-73m|+oYE(K)pIV`2v-FFuC(`SdD*)Ehs_E-ioj)y=jbS>GWQ z#$&86GuTO+|8PX5(z{YjL4zM8m~9&2J9~D)E)nsnurcSEubYn$91JUa{$0B(O@vsE z?mzT_dhW&F%i$SFDXM0@t9f==YpJpz)TdeD(cI1Am^8DemUZSh6?;XEPJVKHQgK`- zQ=yJ9=ULf4=t32-P!;K@_Tn)f&@De|F4OCI@<~zxD@a=eSV>9- zfAPWR)(2w;fDgNUoQzDQ5wrM;U@bJbpALW_h^^-_&0|%**r`?TU0|Y_=sMl(-jY}K zx*msr=T%7Vk1$bU+3hRHdZRWzp=4IZ=D2D>7sbSMLqkrcCD5pzuw`{-qBgW7_O7XQ z#I9C~7JCDzE0fhO{vh%6SUa_OjQB?;Pnl%ZS_4Lq?Qg{Y^)kzQv&IvLq^&KyExx)Z z-~5LDoB#drzgXb@-Uk3+z2$FHf$yGPnv(0BTQ}wCaN|HxCb-4y=MJwmf`h6=?ohnI zV!1fa^8}S0IBWT+LxXe*;&BDst&gWX^|p1l8(Vt%quJN@-&P*Zpg&9t$g8nNoH)`G zE!k@%^0BzT%|{=8@(ZnF*A94VtZX28opR@Db(|(MSU{jm8q&$}q^B&aPncr-6e8@R zm>Yso0?Wv{F^#++3AYB_JEihPe!Rb$vnhj2TOCP%8|}%f9-P#EZnsg5(~vJrm$1ug z=)lPSQHJ3g$~5>G!=lTIT_=T{ac_=x@7D#v0ZtAugtA(owUJ!!9IC)FBFADGk;6fn_bAt zMIp^g?UVFgG;Q_~@OQDHeo_v&RV@3nBCL9~VHP4cx$A<_XN&G`AVH~Sc2}nhFdSU6cydt_IS=iugxtRdv zLee(*ICH@C2_J<4b$IFa2H?FFh`I-{TWpVdq)G%Ob#3RryC8t=SS7d1eKV$d>swE6 zMNV1xvc?p`efHzu|408_Hv8Rw>U-OSU7O?Ff>{eWb*Jr=wbzOoG-VkQ8tKN9nIBus zgqW$--aiy$tY%{?M8WZ(kw$k6Psam1%kL)I{1rCcFN^78oP}y(m9{HoUHSy0Sv%iR zJhMGclF)#JfaE7S2{_GD!*?8?)lbxT_h=bq*%$p&%{vL4DxQgX$2AHbH{AY`+kcRv zxv~~ko;R$epPL+MPLmRjHg@XwI180^P7b_|-Xg;T)W~zb9+o{{D4K@ry>S!q9>H$? z#cV(L0wP2zfx{Gc3~4Y?bxoo}&E6l=%wbH|`RB-8K)g60qjvO7Y0P#aQMKp_!}ps+ ey51+0d_WeCsp=G#bRS$?AQ~hw0#Dnk|NjFgps0xe literal 0 HcmV?d00001 diff --git a/gui.pnproj b/gui.pnproj index 58b282f6..509ea2e0 100644 --- a/gui.pnproj +++ b/gui.pnproj @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/gui.pnps b/gui.pnps index 9504be5f..be6e1712 100644 --- a/gui.pnps +++ b/gui.pnps @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/source/menu.cpp b/source/menu.cpp index 5c7fc04e..e2c863f8 100644 --- a/source/menu.cpp +++ b/source/menu.cpp @@ -44,6 +44,7 @@ #include "fatmounter.h" #include "buffer.h" #include "xml/xml.h" +#include "wad/title.h" #include "usbloader/wdvd.h" @@ -706,7 +707,7 @@ int MenuDiscList() if (Settings.godmode == 1) w.Append(&homebrewBtn); - if((Settings.hddinfo == hr12)||(Settings.hddinfo == hr24)) + if((Settings.hddinfo == hr12)||(Settings.hddinfo == hr24)) { w.Append(&clockTimeBack); w.Append(&clockTime); diff --git a/source/prompts/TitleBrowser.cpp b/source/prompts/TitleBrowser.cpp index 19e451e2..30ddbd57 100644 --- a/source/prompts/TitleBrowser.cpp +++ b/source/prompts/TitleBrowser.cpp @@ -2,7 +2,7 @@ * TitleBrowser * USB Loader GX 2009 * - * TitleBrowser.cpp + * TitleBrowser.cpp *giantpune* ***************************************************************************/ #include "language/gettext.h" #include "libwiigui/gui.h" @@ -45,6 +45,8 @@ int TitleBrowser(u32 type) FILE *f; char path[100]; + ISFS_Initialize(); + sprintf(path,"%s/config/database.txt",bootDevice); f = fopen(path, "r"); @@ -55,12 +57,6 @@ int TitleBrowser(u32 type) //exit(1); } - // Die if we can't handle this many - if (num_titles > 100){ - //printf("\tError! Too many titles! (%u)\n", num_titles); - //exit(1); - } - // Get titles of our requested type ret = getTitles_Type(type, titles, num_titles); if (ret < 0){ @@ -82,10 +78,11 @@ int TitleBrowser(u32 type) //exit(1); } - - + + //this array will hold all the names for the titles so we only have to get them one time + char name[num_titles+num_sys_titles][50]; - customOptionList options3(num_titles+num_sys_titles); + customOptionList options3(num_titles+num_sys_titles+1); //write the titles on the option browser u32 i = 0; @@ -95,45 +92,54 @@ int TitleBrowser(u32 type) while (i < num_titles){ //start from the beginning of the file each loop if (f)rewind(f); - char name[50]; + //char name[50]; char text[15]; - strcpy(name,"");//make sure name is empty - + strcpy(name[i],"");//make sure name is empty + u8 found=0; //set the title's name, number, ID to text sprintf(text, "%s", titleText(type, titles[i])); - //getTitle_Name(name, TITLE_ID(type, titles[i]), text); //get name from database cause i dont like the ADT function char line[200]; char tmp[50]; snprintf(tmp,50,tmp," "); - snprintf(name,sizeof(name),"Unknown Title"); + //snprintf(name[i],sizeof(name[i]),"Unknown Title"); - if (!f) { - sprintf(name,"Unknown--"); - } - else + if(f) { while (fgets(line, sizeof(line), f)) { if (line[0]== text[0]&& line[1]== text[1]&& line[2]== text[2]) { int j=0; + found=1; for(j=0;(line[j+4]!='\0' || j<51);j++) tmp[j]=line[j+4]; - snprintf(name,sizeof(name),"%s",tmp); - break; - + snprintf(name[i],sizeof(name[i]),"%s",tmp); + //break; + } + } + } + if(!found) + { + if (getName00(name[i], TITLE_ID(type, titles[i]),CONF_GetLanguage()*2)>=0) + found=2; + + if(!found) + { + if (getNameBN(name[i], TITLE_ID(type, titles[i]))>=0) + found=3; + + if(!found) + snprintf(name[i],sizeof(name[i]),"Unknown Title (%08x)",titles[i]); } - } - } //set the text to the option browser options3.SetName(i, "%s",text); - options3.SetValue(i, "%s",name); - //options3.SetValue(i, " (%08x)",titles[i]);//use this line to show the number to call to launch the channel + options3.SetValue(i, "%s",name[i]); + //options3.SetValue(i, " (%08x) %s",titles[i],name[i]);//use this line to show the number to call to launch the channel //move on to the next title i++; } @@ -142,49 +148,66 @@ int TitleBrowser(u32 type) while (i < num_titles+num_sys_titles){ //start from the beginning of the file each loop if (f)rewind(f); - char name[50]; + //char name[50]; char text[15]; - strcpy(name,"");//make sure name is empty - + strcpy(name[i],"");//make sure name is empty + u8 found=0; //set the title's name, number, ID to text sprintf(text, "%s", titleText(0x00010002, sys_titles[i-num_titles])); - //getTitle_Name(name, TITLE_ID(0x00010002, sys_titles[i-num_titles]), text); //get name from database cause i dont like the ADT function char line[200]; char tmp[50]; snprintf(tmp,50,tmp," "); - snprintf(name,sizeof(name),"Unknown Title"); - - if (!f) { - sprintf(name,"Unknown--"); - } - else + //snprintf(name[i],sizeof(name[i]),"Unknown Title"); + if(f) { while (fgets(line, sizeof(line), f)) { if (line[0]== text[0]&& line[1]== text[1]&& line[2]== text[2]) { int j=0; + found=1; for(j=0;(line[j+4]!='\0' || j<51);j++) tmp[j]=line[j+4]; - snprintf(name,sizeof(name),"%s",tmp); + snprintf(name[i],sizeof(name[i]),"%s",tmp); break; - } - + } + } + if(!found) + { + if (getName00(name[i], TITLE_ID(0x00010002, sys_titles[i-num_titles]))>=0) + found=2; + + if(!found) + { + if (getNameBN(name[i], TITLE_ID(0x00010002, sys_titles[i-num_titles]))>=0) + found=3; + + if(!found) + snprintf(name[i],sizeof(name[i]),"Unknown Title (%08x)",sys_titles[i-num_titles]); + } } - } //set the text to the option browser options3.SetName(i, "%s",text); - options3.SetValue(i, "%s",name); - //options3.SetValue(i, " (%08x)",titles[i]); + options3.SetValue(i, "%s",name[i]); + //options3.SetValue(i, " (%08x) %s",titles[i],name[i]);//use this line to show the number to call to launch the channel //move on to the next title i++; } + if(i == num_titles+num_sys_titles) + { options3.SetName(i, " "); + options3.SetValue(i, "%s",tr("Wii Settings")); + } + //we have all the titles we need so close the database and stop poking around in the wii + fclose(f); + //get rid of our footprints in there + Uninstall_FromTitle(TITLE_ID(1, 0)); + ISFS_Deinitialize(); bool exit = false; GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM, Settings.sfxvolume); @@ -231,7 +254,7 @@ int TitleBrowser(u32 type) if(num_titles > 9) scrollbaron = 1; - GuiCustomOptionBrowser optionBrowser3(396, 280, &options3, CFG.theme_path, "bg_options_gamesettings.png", bg_options_settings_png, num_titles>9?1:0, 200); + GuiCustomOptionBrowser optionBrowser3(396, 280, &options3, CFG.theme_path, "bg_options_gamesettings.png", bg_options_settings_png, num_titles+num_sys_titles>9?1:0, 200); optionBrowser3.SetPosition(0, 90); optionBrowser3.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); @@ -244,6 +267,8 @@ int TitleBrowser(u32 type) mainWindow->Append(&w); + + int tmp=num_titles+num_sys_titles; ResumeGui(); numtitle=num_titles; while(!exit) @@ -259,50 +284,25 @@ int TitleBrowser(u32 type) if(ret > -1) {//if a click happened - char name[50]; + //char name[50]; char text[15]; if (f)rewind(f); - strcpy(name,"");//make sure name is empty + //strcpy(name,"");//make sure name is empty if (ret"); - } - else - { - while (fgets(line, sizeof(line), f)) { - if (line[0]== text[0]&& - line[1]== text[1]&& - line[2]== text[2]) - { int j=0; - for(j=0;(line[j+4]!='\0' || j<51);j++) - - tmp[j]=line[j+4]; - snprintf(name,sizeof(name),"%s",tmp); - break; - } - } - } char temp[100]; //prompt to boot selected title - snprintf(temp, sizeof(temp), "%s : %s",text,name); + snprintf(temp, sizeof(temp), "%s : %s",text,name[ret]); int choice = WindowPrompt(tr("Boot?"), temp, tr("OK"), tr("Cancel")); if(choice) {//if they say yes //stop all this stuff before starting the channel - fclose(f); + CloseXMLDatabase(); ExitGUIThreads(); ShutdownAudio(); @@ -322,59 +322,46 @@ int TitleBrowser(u32 type) } else//if they clicked a system title { - //set the title's name, number, ID to text - sprintf(text, "%s", titleText(0x00010002, sys_titles[ret-num_titles])); - getTitle_Name(name, TITLE_ID(0x00010002, sys_titles[ret-num_titles]), text); - - //get name from database cause i dont like the ADT function - char line[200]; - char tmp[50]; - snprintf(tmp,50,tmp," "); - snprintf(name,sizeof(name),"Unknown Title"); - - if (!f) { - sprintf(name,"Unknown--"); - } - else - { - while (fgets(line, sizeof(line), f)) { - if (line[0]== text[0]&& - line[1]== text[1]&& - line[2]== text[2]) - { int j=0; - for(j=0;(line[j+4]!='\0' || j<51);j++) - - tmp[j]=line[j+4]; - snprintf(name,sizeof(name),"%s",tmp); - break; - } - } - } - char temp[100]; - //prompt to boot selected title - snprintf(temp, sizeof(temp), "%s : %s May not boot correctly if your System Menu is not up to date.",text,name); - int choice = WindowPrompt(tr("Boot?"), temp, tr("OK"), tr("Cancel")); - if(choice) {//if they say yes - - - //stop all this stuff before starting the channel - fclose(f); - CloseXMLDatabase(); - ExitGUIThreads(); - ShutdownAudio(); - StopGX(); + if(ret == tmp) + { + CloseXMLDatabase(); + ExitGUIThreads(); + ShutdownAudio(); + StopGX(); WII_Initialize(); - WII_LaunchTitle(TITLE_ID(0x00010002,sys_titles[ret-num_titles])); - //this really shouldn't be needed because the title will be booted - exit = true; - break; - } - else{ - //if they said no to booting the title - ret = -1; - optionBrowser3.ResetState(); - } + WII_ReturnToSettings(); + } + else + { + //set the title's name, number, ID to text + sprintf(text, "%s", titleText(0x00010002, sys_titles[ret-num_titles])); + + char temp[100]; + //prompt to boot selected title + snprintf(temp, sizeof(temp), "%s : %s May not boot correctly if your System Menu is not up to date.",text,name[ret]); + int choice = WindowPrompt(tr("Boot?"), temp, tr("OK"), tr("Cancel")); + if(choice) {//if they say yes + + + //stop all this stuff before starting the channel + + CloseXMLDatabase(); + ExitGUIThreads(); + ShutdownAudio(); + StopGX(); + WII_Initialize(); + WII_LaunchTitle(TITLE_ID(0x00010002,sys_titles[ret-num_titles])); + //this really shouldn't be needed because the title will be booted + exit = true; + break; + } + else{ + //if they said no to booting the title + ret = -1; + optionBrowser3.ResetState(); + } + } } } diff --git a/source/svnrev.c b/source/svnrev.c index 0ca73268..39029821 100644 --- a/source/svnrev.c +++ b/source/svnrev.c @@ -1,4 +1,4 @@ -#define SVN_REV "669M" +#define SVN_REV "672M" const char *GetRev() { diff --git a/source/wad/id.c b/source/wad/id.c new file mode 100644 index 00000000..fe77d02d --- /dev/null +++ b/source/wad/id.c @@ -0,0 +1,210 @@ +/*------------------------------------------------------------- + +id.c -- ES Identification code + +Copyright (C) 2008 tona +Unless other credit specified + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1.The origin of this software must not be misrepresented; you +must not claim that you wrote the original software. If you use +this software in a product, an acknowledgment in the product +documentation would be appreciated but is not required. + +2.Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3.This notice may not be removed or altered from any source +distribution. + +-------------------------------------------------------------*/ + +#include +#include +#include + +#include "id.h" +#include "patchmii_core.h" + +#include "certs_dat.h" + + +// Turn upper and lower into a full title ID +#define TITLE_ID(x,y) (((u64)(x) << 32) | (y)) +// Get upper or lower half of a title ID +#define TITLE_UPPER(x) ((u32)((x) >> 32)) +// Turn upper and lower into a full title ID +#define TITLE_LOWER(x) ((u32)(x)) + + +/* Debug functions adapted from libogc's es.c */ +//#define DEBUG_ES +//#define DEBUG_IDENT +#define ISALIGNED(x) ((((u32)x)&0x1F)==0) + +static u8 su_tmd[0x208] ATTRIBUTE_ALIGN(32); +static u8 su_tik[STD_SIGNED_TIK_SIZE] ATTRIBUTE_ALIGN(32); +int su_id_filled = 0; + + +/* Reads a file from ISFS to an array in memory */ +s32 ISFS_ReadFileToArray (const char *filepath, u8 *filearray, u32 max_size, u32 *file_size) { + s32 ret, fd; + static fstats filestats ATTRIBUTE_ALIGN(32); + + *file_size = 0; + ret = ISFS_Open(filepath, ISFS_OPEN_READ); + if (ret <= 0) + { + //printf("Error! ISFS_Open (ret = %d)\n", ret); + return -1; + } + + fd = ret; + + ret = ISFS_GetFileStats(fd, &filestats); + if (ret < 0) + { + //printf("Error! ISFS_GetFileStats (ret = %d)\n", ret); + return -1; + } + + *file_size = filestats.file_length; + + if (*file_size > max_size) + { + //printf("File is too large! Size: %u Max: %u", *file_size, max_size); + return -1; + } + + ret = ISFS_Read(fd, filearray, *file_size); + *file_size = ret; + if (ret < 0) + { + //printf("Error! ISFS_Read (ret = %d)\n", ret); + return -1; + } + else if (ret != filestats.file_length) + { + //printf("Error! ISFS_Read Only read: %d\n", ret); + return -1; + } + + ret = ISFS_Close(fd); + if (ret < 0) + { + //printf("Error! ISFS_Close (ret = %d)\n", ret); + return -1; + } + return 0; +} + +void Make_SUID(void){ + signed_blob *s_tmd, *s_tik; + tmd *p_tmd; + tik *p_tik; + + memset(su_tmd, 0, sizeof su_tmd); + memset(su_tik, 0, sizeof su_tik); + s_tmd = (signed_blob*)&su_tmd[0]; + s_tik = (signed_blob*)&su_tik[0]; + *s_tmd = *s_tik = 0x10001; + p_tmd = (tmd*)SIGNATURE_PAYLOAD(s_tmd); + p_tik = (tik*)SIGNATURE_PAYLOAD(s_tik); + + + strcpy(p_tmd->issuer, "Root-CA00000001-CP00000004"); + p_tmd->title_id = TITLE_ID(1,2); + + p_tmd->num_contents = 1; + + forge_tmd(s_tmd); + + strcpy(p_tik->issuer, "Root-CA00000001-XS00000003"); + p_tik->ticketid = 0x000038A45236EE5FLL; + p_tik->titleid = TITLE_ID(1,2); + + memset(p_tik->cidx_mask, 0xFF, 0x20); + forge_tik(s_tik); + + su_id_filled = 1; + +} + +s32 Identify(const u8 *certs, u32 certs_size, const u8 *idtmd, u32 idtmd_size, const u8 *idticket, u32 idticket_size) { + s32 ret; + u32 keyid = 0; + ret = ES_Identify((signed_blob*)certs, certs_size, (signed_blob*)idtmd, idtmd_size, (signed_blob*)idticket, idticket_size, &keyid); + /*if (ret < 0){ + switch(ret){ + case ES_EINVAL: + printf("Error! ES_Identify (ret = %d;) Data invalid!\n", ret); + break; + case ES_EALIGN: + printf("Error! ES_Identify (ret = %d;) Data not aligned!\n", ret); + break; + case ES_ENOTINIT: + printf("Error! ES_Identify (ret = %d;) ES not initialized!\n", ret); + break; + case ES_ENOMEM: + printf("Error! ES_Identify (ret = %d;) No memory!\n", ret); + break; + default: + printf("Error! ES_Identify (ret = %d)\n", ret); + break; + } + } + else + printf("OK!\n");*/ + return ret; +} + + +s32 Identify_SU(void) { + if (!su_id_filled) + Make_SUID(); + + //printf("\nIdentifying as SU..."); + //fflush(stdout); + return Identify(certs_dat, certs_dat_size, su_tmd, sizeof su_tmd, su_tik, sizeof su_tik); +} + +s32 Identify_SysMenu(void) { + s32 ret; + u32 sysmenu_tmd_size, sysmenu_ticket_size; + //static u8 certs[0xA00] ATTRIBUTE_ALIGN(32); + static u8 sysmenu_tmd[MAX_SIGNED_TMD_SIZE] ATTRIBUTE_ALIGN(32); + static u8 sysmenu_ticket[STD_SIGNED_TIK_SIZE] ATTRIBUTE_ALIGN(32); + + /*printf("\nPulling Certs..."); + ret = ISFS_ReadFileToArray ("/sys/certs.sys", certs, 0xA00, &certs_size); + if (ret < 0) { + printf("\tReading Certs failed!\n"); + return -1; + }*/ + + //printf("\nPulling Sysmenu TMD..."); + ret = ISFS_ReadFileToArray ("/title/00000001/00000002/content/title.tmd", sysmenu_tmd, MAX_SIGNED_TMD_SIZE, &sysmenu_tmd_size); + if (ret < 0) { + //printf("\tReading TMD failed!\n"); + return -1; + } + + //printf("\nPulling Sysmenu Ticket..."); + ret = ISFS_ReadFileToArray ("/ticket/00000001/00000002.tik", sysmenu_ticket, STD_SIGNED_TIK_SIZE, &sysmenu_ticket_size); + if (ret < 0) { + //printf("\tReading TMD failed!\n"); + return -1; + } + + //printf("\nIdentifying as SysMenu..."); + //fflush(stdout); + return Identify(certs_dat, certs_dat_size, sysmenu_tmd, sysmenu_tmd_size, sysmenu_ticket, sysmenu_ticket_size); +} diff --git a/source/wad/id.h b/source/wad/id.h new file mode 100644 index 00000000..067c3d08 --- /dev/null +++ b/source/wad/id.h @@ -0,0 +1,38 @@ +/*------------------------------------------------------------- + +id.h -- ES Identification code + +Copyright (C) 2008 tona +Unless other credit specified + +This software is provided 'as-is', without any express or implied +warranty. In no event will the authors be held liable for any +damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1.The origin of this software must not be misrepresented; you +must not claim that you wrote the original software. If you use +this software in a product, an acknowledgment in the product +documentation would be appreciated but is not required. + +2.Altered source versions must be plainly marked as such, and +must not be misrepresented as being the original software. + +3.This notice may not be removed or altered from any source +distribution. + +-------------------------------------------------------------*/ + +#ifndef _ID_H_ +#define _ID_H_ + +// Identify as the "super user" +s32 Identify_SU(void); + +// Identify as the system menu +s32 Identify_SysMenu(void); + +#endif diff --git a/source/wad/patchmii_core.c b/source/wad/patchmii_core.c new file mode 100644 index 00000000..02356956 --- /dev/null +++ b/source/wad/patchmii_core.c @@ -0,0 +1,94 @@ +/* patchmii_core -- low-level functions to handle the downloading, patching + and installation of updates on the Wii + + Copyright (C) 2008 bushing / hackmii.com + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, version 2. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "patchmii_core.h" +#include "sha1.h" + +#define ALIGN(a,b) ((((a)+(b)-1)/(b))*(b)) + +int http_status = 0; +int tmd_dirty = 0, tik_dirty = 0, temp_ios_slot = 0; + +// yeah, yeah, I know. +signed_blob *s_tmd = NULL, *s_tik = NULL, *s_certs = NULL; +static u8 tmdbuf[MAX_SIGNED_TMD_SIZE] ATTRIBUTE_ALIGN(0x20); +static u8 tikbuf[STD_SIGNED_TIK_SIZE] ATTRIBUTE_ALIGN(0x20); + + +void zero_sig(signed_blob *sig) { + u8 *sig_ptr = (u8 *)sig; + memset(sig_ptr + 4, 0, SIGNATURE_SIZE(sig)-4); +} + +void brute_tmd(tmd *p_tmd) { + u16 fill; + for(fill=0; fill<65535; fill++) { + p_tmd->fill3=fill; + sha1 hash; + // debug_printf("SHA1(%p, %x, %p)\n", p_tmd, TMD_SIZE(p_tmd), hash); + SHA1((u8 *)p_tmd, TMD_SIZE(p_tmd), hash);; + + if (hash[0]==0) { + // debug_printf("setting fill3 to %04hx\n", fill); + return; + } + } + printf("Unable to fix tmd :(\n"); + exit(4); +} + +void brute_tik(tik *p_tik) { + u16 fill; + for(fill=0; fill<65535; fill++) { + p_tik->padding=fill; + sha1 hash; + // debug_printf("SHA1(%p, %x, %p)\n", p_tmd, TMD_SIZE(p_tmd), hash); + SHA1((u8 *)p_tik, sizeof(tik), hash); + + if (hash[0]==0) return; + } + printf("Unable to fix tik :(\n"); + exit(5); +} + +void forge_tmd(signed_blob *s_tmd) { +// debug_printf("forging tmd sig"); + zero_sig(s_tmd); + brute_tmd(SIGNATURE_PAYLOAD(s_tmd)); +} + +void forge_tik(signed_blob *s_tik) { +// debug_printf("forging tik sig"); + zero_sig(s_tik); + brute_tik(SIGNATURE_PAYLOAD(s_tik)); +} + + diff --git a/source/wad/patchmii_core.h b/source/wad/patchmii_core.h new file mode 100644 index 00000000..47488af5 --- /dev/null +++ b/source/wad/patchmii_core.h @@ -0,0 +1,63 @@ +#ifndef _PATCHMII_CORE_ +#define _PATCHMII_CORE_ + + +//Patchmii functions +void patchmii_network_init(void); +// Call with version = 0 to get the latest version +// Set "patch" if you want to try to patch title contents +s32 patchmii_install(u32 in_title_h, u32 in_title_l, u32 in_version, u32 out_title_h, u32 out_title_l, u32 out_version, bool patch); +s32 install_temporary_ios(u32 base_ios, u32 base_ver); +s32 load_temporary_ios(void); +s32 cleanup_temporary_ios(void); + +//Tools +void forge_tmd(signed_blob *s_tmd); +void forge_tik(signed_blob *s_tik); + +void spinner(void); + +#define TEMP_IOS + +// Basic I/O. + +static inline u32 read32(u32 addr) +{ + u32 x; + asm volatile("lwz %0,0(%1) ; sync" : "=r"(x) : "b"(0xc0000000 | addr)); + return x; +} + +static inline void write32(u32 addr, u32 x) +{ + asm("stw %0,0(%1) ; eieio" : : "r"(x), "b"(0xc0000000 | addr)); +} + +// USB Gecko. + +void usb_flush(int chn); +int usb_sendbuffer(int chn,const void *buffer,int size); + +// Version string. + +extern const char version[]; + +// Debug: blink the tray led. + +static inline void blink(void) +{ + write32(0x0d8000c0, read32(0x0d8000c0) ^ 0x20); +} + +void debug_printf(const char *fmt, ...); +void hexdump(FILE *fp, void *d, int len); +void aes_set_key(u8 *key); +void aes_decrypt(u8 *iv, u8 *inbuf, u8 *outbuf, unsigned long long len); +void aes_encrypt(u8 *iv, u8 *inbuf, u8 *outbuf, unsigned long long len); + +#define TRACE(x) debug_printf("%s / %d: %d\n", __FUNCTION__, __LINE__, (x)) + +#define ISFS_ACCESS_READ 1 +#define ISFS_ACCESS_WRITE 2 + +#endif diff --git a/source/wad/sha1.c b/source/wad/sha1.c new file mode 100644 index 00000000..83a533a7 --- /dev/null +++ b/source/wad/sha1.c @@ -0,0 +1,172 @@ +/* +SHA-1 in C +By Steve Reid +100% Public Domain + +Test Vectors (from FIPS PUB 180-1) +"abc" + A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D +"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 +A million repetitions of "a" + 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F +*/ + +/* #define LITTLE_ENDIAN * This should be #define'd if true. */ +#define SHA1HANDSOFF + +#include +#include +#include "sha1.h" + +#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) + +/* blk0() and blk() perform the initial expand. */ +/* I got the idea of expanding during the round function from SSLeay */ +#ifdef LITTLE_ENDIAN +#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \ + |(rol(block->l[i],8)&0x00FF00FF)) +#else +#define blk0(i) block->l[i] +#endif +#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \ + ^block->l[(i+2)&15]^block->l[i&15],1)) + +/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ +#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30); +#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30); +#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30); +#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30); + + +/* Hash a single 512-bit block. This is the core of the algorithm. */ + +void SHA1Transform(unsigned long state[5], unsigned char buffer[64]) +{ +unsigned long a, b, c, d, e; +typedef union { + unsigned char c[64]; + unsigned long l[16]; +} CHAR64LONG16; +CHAR64LONG16* block; +#ifdef SHA1HANDSOFF +static unsigned char workspace[64]; + block = (CHAR64LONG16*)workspace; + memcpy(block, buffer, 64); +#else + block = (CHAR64LONG16*)buffer; +#endif + /* Copy context->state[] to working vars */ + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + /* 4 rounds of 20 operations each. Loop unrolled. */ + R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); + R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); + R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); + R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); + R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); + R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); + R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); + R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); + R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); + R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); + R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); + R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); + R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); + R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); + R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); + R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); + R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); + R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); + R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); + R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); + /* Add the working vars back into context.state[] */ + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + /* Wipe variables */ + a = b = c = d = e = 0; +} + + +/* SHA1Init - Initialize new context */ + +void SHA1Init(SHA1_CTX* context) +{ + /* SHA1 initialization constants */ + context->state[0] = 0x67452301; + context->state[1] = 0xEFCDAB89; + context->state[2] = 0x98BADCFE; + context->state[3] = 0x10325476; + context->state[4] = 0xC3D2E1F0; + context->count[0] = context->count[1] = 0; +} + + +/* Run your data through this. */ + +void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int len) +{ +unsigned int i, j; + + j = (context->count[0] >> 3) & 63; + if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++; + context->count[1] += (len >> 29); + if ((j + len) > 63) { + memcpy(&context->buffer[j], data, (i = 64-j)); + SHA1Transform(context->state, context->buffer); + for ( ; i + 63 < len; i += 64) { + SHA1Transform(context->state, &data[i]); + } + j = 0; + } + else i = 0; + memcpy(&context->buffer[j], &data[i], len - i); +} + + +/* Add padding and return the message digest. */ + +void SHA1Final(unsigned char digest[20], SHA1_CTX* context) +{ +unsigned long i, j; +unsigned char finalcount[8]; + + for (i = 0; i < 8; i++) { + finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)] + >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */ + } + SHA1Update(context, (unsigned char *)"\200", 1); + while ((context->count[0] & 504) != 448) { + SHA1Update(context, (unsigned char *)"\0", 1); + } + SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */ + for (i = 0; i < 20; i++) { + digest[i] = (unsigned char) + ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255); + } + /* Wipe variables */ + i = j = 0; + memset(context->buffer, 0, 64); + memset(context->state, 0, 20); + memset(context->count, 0, 8); + memset(&finalcount, 0, 8); +#ifdef SHA1HANDSOFF /* make SHA1Transform overwrite it's own static vars */ + SHA1Transform(context->state, context->buffer); +#endif +} + +void SHA1(unsigned char *ptr, unsigned int size, unsigned char *outbuf) { + SHA1_CTX ctx; + + SHA1Init(&ctx); + SHA1Update(&ctx, ptr, size); + SHA1Final(outbuf, &ctx); +} + diff --git a/source/wad/sha1.h b/source/wad/sha1.h new file mode 100644 index 00000000..757af1cd --- /dev/null +++ b/source/wad/sha1.h @@ -0,0 +1,12 @@ +typedef struct { + unsigned long state[5]; + unsigned long count[2]; + unsigned char buffer[64]; +} SHA1_CTX; + +void SHA1Transform(unsigned long state[5], unsigned char buffer[64]); +void SHA1Init(SHA1_CTX* context); +void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int len); +void SHA1Final(unsigned char digest[20], SHA1_CTX* context); + +void SHA1(unsigned char *ptr, unsigned int size, unsigned char *outbuf); diff --git a/source/wad/title.c b/source/wad/title.c index c36562a1..0fdfa9e9 100644 --- a/source/wad/title.c +++ b/source/wad/title.c @@ -8,6 +8,7 @@ #include "utils.h" #include "../settings/cfg.h" #include "fatmounter.h" +#include "id.h" #define MAX_TITLES 256 @@ -260,6 +261,113 @@ out: return ret; } +s32 Uninstall_RemoveTicket(u64 tid) +{ + static tikview viewdata[0x10] ATTRIBUTE_ALIGN(32); + + u32 cnt, views; + s32 ret; + +/* Get number of ticket views */ + ret = ES_GetNumTicketViews(tid, &views); + if (ret < 0) { + + return ret; + } + + if (!views) { + //printf(" No tickets found!\n"); + return 1; + } else if (views > 16) { + //printf(" Too many ticket views! (views = %d)\n", views); + return -1; + } + + /* Get ticket views */ + ret = ES_GetTicketViews(tid, viewdata, views); + if (ret < 0) { + //printf(" \n\tError! ES_GetTicketViews (ret = %d)\n", ret); + return ret; + } + + /* Remove tickets */ + for (cnt = 0; cnt < views; cnt++) { + ret = ES_DeleteTicket(&viewdata[cnt]); + if (ret < 0) { + //printf(" Error! (view = %d, ret = %d)\n", cnt, ret); + return ret; + } + } + //printf(" OK!\n"); + + return ret; +} + +s32 Uninstall_DeleteTitle(u32 title_u, u32 title_l) +{ + s32 ret; + char filepath[256]; + sprintf(filepath, "/title/%08x/%08x", title_u, title_l); + + /* Remove title */ + ret = ISFS_Delete(filepath); + return ret; +} + +s32 Uninstall_DeleteTicket(u32 title_u, u32 title_l) +{ + s32 ret; + + char filepath[256]; + sprintf(filepath, "/ticket/%08x/%08x.tik", title_u, title_l); + + /* Delete ticket */ + ret = ISFS_Delete(filepath); + + return ret; +} + +//carefull when using this function +//it will force remove stuff even if something fails +s32 Uninstall_FromTitle(const u64 tid) +{ + s32 contents_ret, tik_ret, title_ret, ret; + u32 id = tid & 0xFFFFFFFF, kind = tid >> 32; + contents_ret = tik_ret = title_ret = ret = 0; + + if (kind == 1) + { + // Delete title and ticket at FS level. + tik_ret = Uninstall_DeleteTicket(kind, id); + title_ret = Uninstall_DeleteTitle(kind, id); + contents_ret = title_ret; + } + else + { + // Remove title (contents and ticket) + tik_ret = Uninstall_RemoveTicket(tid); + contents_ret = ES_DeleteTitleContent(tid); + title_ret = ES_DeleteTitle(tid); + + + // Attempt forced uninstall if something fails + if (tik_ret < 0 || contents_ret < 0 || title_ret < 0){ + tik_ret = Uninstall_DeleteTicket(kind, id); + title_ret = Uninstall_DeleteTitle(kind, id); + contents_ret = title_ret; + + } + } + if (tik_ret < 0 && contents_ret < 0 && title_ret < 0) + ret = -1; + else if (tik_ret < 0 || contents_ret < 0 || title_ret < 0) + ret = 1; + else + ret = 0; + + return ret; +} + /*------------------------------------------------------------- taken from anytitledeleter @@ -268,104 +376,6 @@ out: Copyright (C) 2009 MrClick -------------------------------------------------------------*/ -// Max number of entries in the database -#define MAX_DB 1024 - -// Max name length -#define MAX_LINE 80 - -// Contains all title ids (e.g.: "HAC") -static char **__db_i; -// Contains all title names (e.g.: "Mii Channel") -static char **__db; -// Contains the number of entries in the database -static u32 __db_cnt = 0; - -s32 loadDatabase(){ - FILE *fdb; - - char dbfile[100]; - snprintf(dbfile,sizeof(dbfile),"SD:/database.txt"); - // Init SD card access, open database file and check if it worked - //fatInitDefault(); - SDCard_Init(); - fdb = fopen(dbfile, "r"); - if (fdb == NULL) - return -1; - - // Allocate memory for the database - __db_i = calloc(MAX_DB, sizeof(char*)); - __db = calloc(MAX_DB, sizeof(char*)); - - // Define the line buffer. Each line in the db file will be stored here first - char line[MAX_LINE]; - line[sizeof(line)] = 0; - - // Generic char buffer and counter variable - char byte; - u32 i = 0; - - // Read each character from the file - do { - byte = fgetc(fdb); - // In case a line was longer than MAX_LINE - if (i == -1){ - // Read bytes till a new line is hit - if (byte == 0x0A) - i = 0; - // In case were still good with the line length - } else { - // Add the new byte to the line buffer - line[i] = byte; - i++; - // When a new line is hit or MAX_LINE is reached - if (byte == 0x0A || i == sizeof(line) - 1) { - // Terminate finished line to create a string - line[i] = 0; - // When the line is not a comment or not to short - if (line[0] != '#' && i > 5){ - - // Allocate and copy title id to database - __db_i[__db_cnt] = calloc(4, sizeof(char*)); - memcpy(__db_i[__db_cnt], line, 3); - __db_i[__db_cnt][3] = 0; - // Allocate and copy title name to database - __db[__db_cnt] = calloc(i - 4, sizeof(char*)); - memcpy(__db[__db_cnt], line + 4, i - 4); - __db[__db_cnt][i - 5] = 0; - - // Check that the next line does not overflow the database - __db_cnt++; - if (__db_cnt == MAX_DB) - break; - } - // Set routine to ignore all bytes in the line when MAX_LINE is reached - if (byte == 0x0A) i = 0; else i = -1; - } - } - } while (!feof(fdb)); - - // Close database file; we are done with it - fclose(fdb); - - return 0; -} - - -void freeDatabase(){ - u32 i = 0; - for(; i < __db_cnt; i++){ - free(__db_i[i]); - free(__db[i]); - } - free(__db_i); - free(__db); -} - - -s32 getDatabaseCount(){ - return __db_cnt; -} s32 __convertWiiString(char *str, u8 *data, u32 cnt){ u32 i = 0; @@ -385,47 +395,6 @@ s32 __convertWiiString(char *str, u8 *data, u32 cnt){ return 0; } -s32 getNameDB(char* name, char* id){ - // Return fixed values for special entries - if (strncmp(id, "IOS", 3) == 0){ - sprintf(name, "Operating System %s", id); - return 0; - } - if (strncmp(id, "MIOS", 3) == 0){ - sprintf(name, "Gamecube Compatibility Layer"); - return 0; - } - if (strncmp(id, "SYSMENU", 3) == 0){ - sprintf(name, "System Menu"); - return 0; - } - if (strncmp(id, "BC", 2) == 0){ - sprintf(name, "BC"); - return 0; - } - - // Create an ? just in case the function aborts prematurely - sprintf(name, "?"); - - u32 i; - u8 db_found = 0; - // Compare each id in the database to the title id - for (i = 0; i < __db_cnt; i++) - if (strncmp(id, __db_i[i], 3) == 0){ - db_found = 1; - break; - } - - if (db_found == 0) - // Return -1 if no mathcing entry was found - return -1; - else { - // Get name from database once a matching id was found - sprintf(name, __db[i]); - return 0; - } -} - s32 getNameBN(char* name, u64 id){ // Terminate the name string just in case the function exits prematurely @@ -438,9 +407,9 @@ s32 getNameBN(char* name, u64 id){ // Bring the Wii into the title's userspace if (ES_SetUID(id) < 0){ // Should that fail repeat after setting permissions to system menu mode -// Identify_SysMenu(); -// if (ES_SetUID(id) < 0) -// return -1; + Identify_SysMenu(); + if (ES_SetUID(id) < 0) + return -1; } // Try to open file @@ -452,8 +421,8 @@ s32 getNameBN(char* name, u64 id){ // If it fails try to open again after identifying as SU if (fh == -102){ -// Identify_SU(); -// fh = ISFS_Open(file, ISFS_OPEN_READ); + Identify_SU(); + fh = ISFS_Open(file, ISFS_OPEN_READ); } // If the file won't open else if (fh < 0) @@ -494,11 +463,21 @@ s32 getNameBN(char* name, u64 id){ } -s32 getName00(char* name, u64 id){ +s32 getName00(char* name, u64 id, int lang){ +/* +languages +0jap +2eng +4german +6french +8spanish +10italian +12dutch +*/ // Create a string containing the absolute filename char file[256] __attribute__ ((aligned (32))); sprintf(file, "/title/%08x/%08x/content/00000000.app", (u32)(id >> 32), (u32)id); - + Identify_SU(); s32 fh = ISFS_Open(file, ISFS_OPEN_READ); @@ -510,8 +489,8 @@ s32 getName00(char* name, u64 id){ // In case there is some problem with the permission if (fh == -102){ // Identify as super user -// Identify_SU(); -// fh = ISFS_Open(file, ISFS_OPEN_READ); + Identify_SU(); + fh = ISFS_Open(file, ISFS_OPEN_READ); } else if (fh < 0) return fh; @@ -541,12 +520,16 @@ s32 getName00(char* name, u64 id){ free(data); // Assemble name - // Only the English name is returned - // There are 6 other language names in the str array - sprintf(name, "%s", str[2]); - if (strlen(str[3]) > 1) - sprintf(name, "%s (%s)", name, str[3]); - + if(strlen(str[lang]) > 1){ + sprintf(name, "%s", str[lang]); + if (strlen(str[lang+1]) > 1) + sprintf(name, "%s (%s)", name, str[lang+1]); + } + else{ + sprintf(name, "%s", str[2]); + if (strlen(str[3]) > 1) + sprintf(name, "%s (%s)", name, str[3]); + } // Job well done return 2; } @@ -575,35 +558,6 @@ s32 printContent(u64 tid){ } -s32 getTitle_Name(char* name, u64 id, char *tid){ - char buf[256] __attribute__ ((aligned (32))); - - s32 r = -1; - // Determine the title's name database/banner/00000000.app - r = getNameDB(buf, tid); - if (r < 0) - r = getNameBN(buf, id); - if (r < 0) - r = getName00(buf, id); - - switch (r){ - // In case a name was found in the database - case 0: sprintf(name, "%s", buf); - break; - // In case a name was found in the banner.bin - case 1: sprintf(name, "*%s*", buf); - break; - // In case a name was found in the 00000000.app - case 2: sprintf(name, "+%s+", buf); - break; - // In case no proper name was found return a ? - default: sprintf(name, "Unknown Title"); - break; - } - - return 0; -} - char *titleText(u32 kind, u32 title){ static char text[10]; @@ -684,7 +638,7 @@ s32 getTitles_TypeCount(u32 type, u32 *count) { upper = __title_list[i] >> 32; lower = __title_list[i] & 0xFFFFFFFF; if((upper == type)&& - ((lower !=0x48414741)&&//this filters out haga,haaa, hafa. dupe foctory channels that don't load + ((lower !=0x48414741)&&//this filters out haga,haaa, hafa. dupe factory channels that don't load (lower !=0x48414141)&&//since we dont care about apps that dont load for what we are doing (lower !=0x48414641))) type_count++; @@ -721,3 +675,6 @@ s32 getTitles_Type(u32 type, u32 *titles, u32 count) { } + + + diff --git a/source/wad/title.h b/source/wad/title.h index 03a68af2..3eb76a4b 100644 --- a/source/wad/title.h +++ b/source/wad/title.h @@ -39,26 +39,11 @@ s32 Title_GetSysVersion(u64, u64 *); s32 Title_GetSize(u64, u32 *); s32 Title_GetIOSVersions(u8 **, u32 *); -// Load the database from SD card -s32 loadDatabase(); - -// Free the database on exit -void freeDatabase(); - -// Get the number of entries in the database -s32 getDatabaseCount(); - -// Get the name of a title -s32 getTitle_Name(char *name, u64 id, char *tid); - -// Get the name of a title from the database located on the SD card -s32 getNameDB(char *name, char* id); - // Get the name of a title from its banner.bin in NAND s32 getNameBN(char *name, u64 id); // Get the name of a title from its 00000000.app in NAND -s32 getName00(char *name, u64 id); +s32 getName00(char *name, u64 id, int lang = 2); // Get string representation of lower title id char *titleText(u32 kind, u32 title); @@ -71,6 +56,11 @@ s32 getTitles_TypeCount(u32 type, u32 *count); // Get the list of titles of this type s32 getTitles_Type(u32 type, u32 *titles, u32 count); + +//returns a name for a title +char *__getTitleName(u64 titleid, int language); + +s32 Uninstall_FromTitle(const u64 tid); #ifdef __cplusplus } diff --git a/source/xml/xml.c b/source/xml/xml.c index 51f38710..da6cb8dc 100644 --- a/source/xml/xml.c +++ b/source/xml/xml.c @@ -331,7 +331,7 @@ void LoadTitlesFromXML(char *langtxt, bool forcejptoen) strcpy(title_text,title_text_EN); } - snprintf(id_text, 5, "%s",id_text); + snprintf(id_text, 7, "%s",id_text); title_set(id_text, title_text); } }