mirror of
https://github.com/wiidev/usbloadergx.git
synced 2024-11-22 11:19:17 +01:00
8ab03c4bf9
Thanks to Oddx. I just tested his changes, fixed some issues and then refactored code.
473 lines
12 KiB
C++
473 lines
12 KiB
C++
/****************************************************************************
|
|
* Copyright (C) 2010
|
|
* by Dimok
|
|
*
|
|
* 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 "HomebrewBrowser.hpp"
|
|
#include "themes/CTheme.h"
|
|
#include "prompts/PromptWindows.h"
|
|
#include "prompts/HomebrewPrompt.hpp"
|
|
#include "language/gettext.h"
|
|
#include "network/networkops.h"
|
|
#include "utils/minizip/miniunz.h"
|
|
#include "prompts/TitleBrowser.h"
|
|
#include "homebrewboot/BootHomebrew.h"
|
|
#include "FileOperations/fileops.h"
|
|
#include "prompts/ProgressWindow.h"
|
|
#include "utils/tools.h"
|
|
#include "wstring.hpp"
|
|
#include "HomebrewXML.h"
|
|
|
|
extern u32 infilesize;
|
|
extern u32 uncfilesize;
|
|
extern char wiiloadVersion[2];
|
|
extern int connection;
|
|
|
|
HomebrewBrowser::HomebrewBrowser()
|
|
: FlyingButtonsMenu(tr( "Homebrew Launcher" ))
|
|
{
|
|
HomebrewList = new DirList(Settings.homebrewapps_path, ".dol,.elf", DirList::Files | DirList::Dirs | DirList::CheckSubfolders | DirList::MainDOL, 1);
|
|
|
|
if (IsNetworkInit())
|
|
ResumeNetworkWait();
|
|
|
|
wifiNotSet = true;
|
|
wifiImgData = Resources::GetImageData("wifi_btn.png");
|
|
wifiToolTip = new GuiTooltip(" ");
|
|
wifiImg = new GuiImage(wifiImgData);
|
|
wifiBtn = new GuiButton(wifiImgData->GetWidth(), wifiImgData->GetHeight());
|
|
wifiBtn->SetImage(wifiImg);
|
|
wifiBtn->SetPosition(300, 400);
|
|
wifiBtn->SetSoundOver(btnSoundOver);
|
|
wifiBtn->SetSoundClick(btnSoundClick);
|
|
wifiBtn->SetEffectGrow();
|
|
wifiBtn->SetAlpha(80);
|
|
wifiBtn->SetTrigger(trigA);
|
|
Append(wifiBtn);
|
|
|
|
channelImgData = Resources::GetImageData("channel_btn.png");
|
|
channelBtnImg = new GuiImage(channelImgData);
|
|
channelBtnImg->SetWidescreen(Settings.widescreen);
|
|
channelBtn = new GuiButton(channelBtnImg->GetWidth(), channelBtnImg->GetHeight());
|
|
channelBtn->SetPosition(240, 400);
|
|
channelBtn->SetImage(channelBtnImg);
|
|
channelBtn->SetSoundOver(btnSoundOver);
|
|
channelBtn->SetSoundClick(btnSoundClick2);
|
|
channelBtn->SetEffectGrow();
|
|
channelBtn->SetTrigger(trigA);
|
|
if (Settings.godmode || !(Settings.ParentalBlocks & BLOCK_TITLE_LAUNCHER_MENU))
|
|
Append(channelBtn);
|
|
|
|
MainButtonDesc.resize(HomebrewList->GetFilecount());
|
|
MainButtonDescOver.resize(HomebrewList->GetFilecount());
|
|
|
|
for(u32 i = 0; i < 4; ++i)
|
|
{
|
|
IconImgData[i] = NULL;
|
|
IconImg[i] = NULL;
|
|
}
|
|
|
|
for(int i = 0; i < HomebrewList->GetFilecount(); ++i)
|
|
{
|
|
MainButtonDesc[i] = new GuiText((char *) NULL, 18, (GXColor) {0, 0, 0, 255});
|
|
MainButtonDesc[i]->SetMaxWidth(MainButtonImgData->GetWidth() - 150, DOTTED);
|
|
MainButtonDesc[i]->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE);
|
|
MainButtonDesc[i]->SetPosition(148, 15);
|
|
|
|
MainButtonDescOver[i] = new GuiText((char *) NULL, 18, (GXColor) {0, 0, 0, 255});
|
|
MainButtonDescOver[i]->SetMaxWidth(MainButtonImgData->GetWidth() - 150, SCROLL_HORIZONTAL);
|
|
MainButtonDescOver[i]->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE);
|
|
MainButtonDescOver[i]->SetPosition(148, 15);
|
|
}
|
|
}
|
|
|
|
HomebrewBrowser::~HomebrewBrowser()
|
|
{
|
|
HaltGui();
|
|
delete HomebrewList;
|
|
|
|
Remove(wifiBtn);
|
|
delete wifiImgData;
|
|
delete wifiImg;
|
|
delete wifiToolTip;
|
|
delete wifiBtn;
|
|
|
|
Remove(channelBtn);
|
|
delete channelImgData;
|
|
delete channelBtnImg;
|
|
delete channelBtn;
|
|
|
|
for(u32 i = 0; i < MainButtonDesc.size(); ++i)
|
|
{
|
|
delete MainButtonDesc[i];
|
|
delete MainButtonDescOver[i];
|
|
MainButton[i]->SetLabel(NULL, 1);
|
|
MainButton[i]->SetLabelOver(NULL, 1);
|
|
}
|
|
|
|
if (IsNetworkInit())
|
|
HaltNetworkThread();
|
|
}
|
|
|
|
int HomebrewBrowser::Execute()
|
|
{
|
|
HomebrewBrowser * Menu = new HomebrewBrowser();
|
|
mainWindow->Append(Menu);
|
|
|
|
Menu->ShowMenu();
|
|
|
|
int returnMenu = MENU_NONE;
|
|
|
|
while((returnMenu = Menu->MainLoop()) == MENU_NONE);
|
|
|
|
delete Menu;
|
|
|
|
return returnMenu;
|
|
}
|
|
|
|
void HomebrewBrowser::AddMainButtons()
|
|
{
|
|
HaltGui();
|
|
|
|
for(u32 i = 0; i < 4; ++i)
|
|
{
|
|
if(IconImgData[i])
|
|
delete IconImgData[i];
|
|
if(IconImg[i])
|
|
delete IconImg[i];
|
|
IconImgData[i] = NULL;
|
|
IconImg[i] = NULL;
|
|
}
|
|
|
|
for(u32 i = 0; i < MainButton.size(); ++i)
|
|
MainButton[i]->SetIcon(NULL);
|
|
|
|
int FirstItem = currentPage*DISPLAY_BUTTONS;
|
|
|
|
for(int i = FirstItem, n = 0; i < (int) MainButton.size() && i < FirstItem+DISPLAY_BUTTONS; ++i, ++n)
|
|
{
|
|
std::string iconpath = HomebrewList->GetFilepath(i);
|
|
size_t pos = iconpath.rfind('/');
|
|
if(pos != std::string::npos && pos < iconpath.size()-1)
|
|
iconpath.erase(pos+1);
|
|
iconpath += "icon.png";
|
|
|
|
IconImgData[n] = new GuiImageData(iconpath.c_str());
|
|
IconImg[n] = new GuiImage(IconImgData[n]);
|
|
IconImg[n]->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE);
|
|
IconImg[n]->SetPosition(12, 0);
|
|
IconImg[n]->SetScale(0.95);
|
|
MainButton[i]->SetIcon(IconImg[n]);
|
|
}
|
|
|
|
FlyingButtonsMenu::AddMainButtons();
|
|
}
|
|
|
|
void HomebrewBrowser::SetupMainButtons()
|
|
{
|
|
HomebrewXML MetaXML;
|
|
|
|
for(int i = 0; i < HomebrewList->GetFilecount(); ++i)
|
|
{
|
|
const char * HomebrewName = NULL;
|
|
std::string metapath = HomebrewList->GetFilepath(i);
|
|
size_t pos = metapath.rfind('/');
|
|
if(pos != std::string::npos && pos < metapath.size()-1)
|
|
metapath.erase(pos+1);
|
|
metapath += "meta.xml";
|
|
|
|
if (MetaXML.LoadHomebrewXMLData(metapath.c_str()) > 0)
|
|
{
|
|
HomebrewName = MetaXML.GetName();
|
|
MainButtonDesc[i]->SetText(MetaXML.GetShortDescription());
|
|
MainButtonDescOver[i]->SetText(MetaXML.GetShortDescription());
|
|
}
|
|
else
|
|
{
|
|
const char * shortpath = HomebrewList->GetFilepath(i);
|
|
const char * ptr = shortpath;
|
|
const char * ptr2 = NULL;
|
|
while(*ptr != '\0')
|
|
{
|
|
if(*ptr == '/')
|
|
{
|
|
shortpath = ptr2;
|
|
ptr2 = ptr;
|
|
}
|
|
|
|
++ptr;
|
|
}
|
|
if(!shortpath && ptr2)
|
|
shortpath = ptr2;
|
|
else if(!shortpath)
|
|
shortpath = HomebrewList->GetFilename(i);
|
|
|
|
HomebrewName = shortpath;
|
|
MainButtonDesc[i]->SetText(" ");
|
|
MainButtonDescOver[i]->SetText(" ");
|
|
}
|
|
|
|
SetMainButton(i, HomebrewName, MainButtonImgData, MainButtonImgOverData);
|
|
|
|
MainButtonTxt[i]->SetFontSize(18);
|
|
MainButtonTxt[i]->SetMaxWidth(MainButtonImgData->GetWidth() - 150, DOTTED);
|
|
MainButtonTxt[i]->SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE);
|
|
MainButtonTxt[i]->SetPosition(148, -12);
|
|
MainButton[i]->SetLabel(MainButtonDesc[i], 1);
|
|
MainButton[i]->SetLabelOver(MainButtonDescOver[i], 1);
|
|
}
|
|
}
|
|
|
|
int HomebrewBrowser::MainLoop()
|
|
{
|
|
if (IsNetworkInit() && wifiNotSet)
|
|
{
|
|
wifiToolTip->SetText(GetNetworkIP());
|
|
wifiBtn->SetAlpha(255);
|
|
wifiBtn->SetToolTip(wifiToolTip, 0, -50, 0, 5);
|
|
wifiNotSet = false;
|
|
}
|
|
|
|
if(wifiBtn->GetState() == STATE_CLICKED)
|
|
{
|
|
if(IsNetworkInit() && WindowPrompt(tr("Do you want to re-init network?"), 0, tr("Yes"), tr("Cancel")))
|
|
{
|
|
DeinitNetwork();
|
|
wifiBtn->SetAlpha(80);
|
|
wifiBtn->SetToolTip(NULL, 0, -50, 0, 5);
|
|
wifiNotSet = true;
|
|
}
|
|
ResumeNetworkWait();
|
|
wifiBtn->ResetState();
|
|
}
|
|
else if(channelBtn->GetState() == STATE_CLICKED)
|
|
{
|
|
SetState(STATE_DISABLED);
|
|
TitleBrowser();
|
|
SetState(STATE_DEFAULT);
|
|
channelBtn->ResetState();
|
|
}
|
|
else if (infilesize > 0)
|
|
{
|
|
int menu = ReceiveFile();
|
|
if(menu != MENU_NONE)
|
|
return menu;
|
|
CloseConnection();
|
|
ResumeNetworkWait();
|
|
}
|
|
|
|
return FlyingButtonsMenu::MainLoop();
|
|
}
|
|
|
|
//! Callback for MainButton clicked
|
|
void HomebrewBrowser::MainButtonClicked(int button)
|
|
{
|
|
HomebrewXML MetaXML;
|
|
std::string metapath = HomebrewList->GetFilepath(button);
|
|
size_t pos = metapath.rfind('/');
|
|
if(pos != std::string::npos && pos < metapath.size()-1)
|
|
metapath.erase(pos+1);
|
|
metapath += "meta.xml";
|
|
MetaXML.LoadHomebrewXMLData(metapath.c_str());
|
|
|
|
u64 filesize = HomebrewList->GetFilesize(button);
|
|
|
|
wString HomebrewName(MainButtonTxt[button]->GetText());
|
|
|
|
HomebrewPrompt *HBCWindowPrompt = new HomebrewPrompt(HomebrewName.toUTF8().c_str(), MetaXML.GetCoder(), MetaXML.GetVersion(),
|
|
MetaXML.GetReleasedate(), MetaXML.GetLongDescription(), IconImgData[button % 4], filesize);
|
|
|
|
mainWindow->SetState(STATE_DISABLED);
|
|
mainWindow->Append(HBCWindowPrompt);
|
|
|
|
int choice = HBCWindowPrompt->MainLoop();
|
|
|
|
delete HBCWindowPrompt;
|
|
|
|
mainWindow->SetState(STATE_DEFAULT);
|
|
|
|
if (choice == 1)
|
|
{
|
|
u8 *buffer = NULL;
|
|
u32 filesize = 0;
|
|
LoadFileToMem(HomebrewList->GetFilepath(button), &buffer, &filesize);
|
|
if(!buffer)
|
|
{
|
|
WindowPrompt(tr("Error"), tr("Not enough memory."), tr("OK"));
|
|
return;
|
|
}
|
|
FreeHomebrewBuffer();
|
|
CopyHomebrewMemory(buffer, 0, filesize);
|
|
|
|
AddBootArgument(HomebrewList->GetFilepath(button));
|
|
|
|
for(u32 i = 0; i < MetaXML.GetArguments().size(); ++i)
|
|
{
|
|
AddBootArgument(MetaXML.GetArguments().at(i).c_str());
|
|
}
|
|
|
|
BootHomebrewFromMem();
|
|
}
|
|
}
|
|
|
|
int HomebrewBrowser::ReceiveFile()
|
|
{
|
|
char filesizetxt[50];
|
|
char temp[50];
|
|
u32 filesize = 0;
|
|
|
|
if (infilesize < MB_SIZE)
|
|
snprintf(filesizetxt, sizeof(filesizetxt), tr( "Incoming file %0.2fKB" ), infilesize / KB_SIZE);
|
|
else snprintf(filesizetxt, sizeof(filesizetxt), tr( "Incoming file %0.2fMB" ), infilesize / MB_SIZE);
|
|
|
|
snprintf(temp, sizeof(temp), tr( "Load file from: %s ?" ), GetIncommingIP());
|
|
|
|
int choice = WindowPrompt(filesizetxt, temp, tr( "OK" ), tr( "Cancel" ));
|
|
|
|
if (choice == 0)
|
|
return MENU_NONE;
|
|
|
|
u32 read = 0;
|
|
int len = NETWORKBLOCKSIZE;
|
|
filesize = infilesize;
|
|
u8 * buffer = (u8 *) malloc(infilesize);
|
|
if(!buffer)
|
|
{
|
|
WindowPrompt(tr( "Not enough memory." ), 0, tr( "OK" ));
|
|
return MENU_NONE;
|
|
}
|
|
|
|
int error = 0;
|
|
|
|
while (read < infilesize)
|
|
{
|
|
ShowProgress(tr( "Receiving file from:" ), GetIncommingIP(), NULL, read, infilesize, true);
|
|
|
|
if (infilesize - read < (u32) len)
|
|
len = infilesize - read;
|
|
else len = NETWORKBLOCKSIZE;
|
|
|
|
int result = network_read(connection, buffer+read, len);
|
|
|
|
if (result < 0)
|
|
{
|
|
WindowPrompt(tr( "Error while transfering data." ), 0, tr( "OK" ));
|
|
free(buffer);
|
|
ProgressStop();
|
|
return MENU_NONE;
|
|
}
|
|
if (!result)
|
|
{
|
|
break;
|
|
}
|
|
|
|
read += result;
|
|
}
|
|
|
|
char filename[101];
|
|
memset(filename, 0, sizeof(filename));
|
|
|
|
network_read(connection, (u8*) filename, 100);
|
|
|
|
// Do we need to unzip this thing?
|
|
if (wiiloadVersion[0] > 0 || wiiloadVersion[1] > 4)
|
|
{
|
|
// We need to unzip...
|
|
if (buffer[0] == 'P' && buffer[1] == 'K' && buffer[2] == 0x03 && buffer[3] == 0x04)
|
|
{
|
|
// It's a zip file, unzip to the apps directory
|
|
// Zip archive, ask for permission to install the zip
|
|
char zippath[255];
|
|
snprintf(zippath, sizeof(zippath), "%s%s", Settings.homebrewapps_path, filename);
|
|
|
|
FILE *fp = fopen(zippath, "wb");
|
|
if (!fp)
|
|
{
|
|
WindowPrompt(tr( "Error writing the data." ), 0, tr( "OK" ));
|
|
return MENU_NONE;
|
|
}
|
|
|
|
fwrite(buffer, 1, infilesize, fp);
|
|
fclose(fp);
|
|
|
|
free(buffer);
|
|
buffer = NULL;
|
|
|
|
// Now unzip the zip file...
|
|
unzFile uf = unzOpen(zippath);
|
|
if (uf == NULL)
|
|
{
|
|
WindowPrompt(tr( "Error while opening the zip." ), 0, tr( "OK" ));
|
|
return MENU_NONE;
|
|
}
|
|
|
|
extractZip(uf, 0, 1, 0, Settings.homebrewapps_path);
|
|
unzClose(uf);
|
|
|
|
remove(zippath);
|
|
|
|
WindowPrompt(tr( "Success:" ),
|
|
tr( "Uploaded ZIP file installed to homebrew directory." ), tr( "OK" ));
|
|
|
|
// Reload this menu here...
|
|
return MENU_HOMEBREWBROWSE;
|
|
}
|
|
else if (uncfilesize != 0) // if uncfilesize == 0, it's not compressed
|
|
{
|
|
// It's compressed, uncompress
|
|
u8 *unc = (u8 *) malloc(uncfilesize);
|
|
if(!unc)
|
|
{
|
|
ProgressStop();
|
|
free(buffer);
|
|
CloseConnection();
|
|
WindowPrompt(tr( "Not enough memory." ), 0, tr( "OK" ));
|
|
return MENU_NONE;
|
|
}
|
|
uLongf f = uncfilesize;
|
|
error = uncompress(unc, &f, buffer, infilesize) != Z_OK;
|
|
uncfilesize = f;
|
|
filesize = uncfilesize;
|
|
|
|
free(buffer);
|
|
buffer = unc;
|
|
}
|
|
}
|
|
|
|
CopyHomebrewMemory(buffer, 0, filesize);
|
|
free(buffer);
|
|
|
|
ProgressStop();
|
|
|
|
if (error || read != infilesize || (strcasestr(filename, ".dol") == 0 && strcasestr(filename, ".elf") == 0))
|
|
{
|
|
WindowPrompt(tr( "Error:" ), tr( "No data could be read." ), tr( "OK" ));
|
|
FreeHomebrewBuffer();
|
|
return MENU_NONE;
|
|
}
|
|
|
|
CloseConnection();
|
|
|
|
AddBootArgument(filename);
|
|
|
|
return BootHomebrewFromMem();
|
|
}
|