2012-01-21 21:57:41 +01:00
|
|
|
/***************************************************************************
|
|
|
|
* Copyright (C) 2010
|
|
|
|
* by dude
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
* Channel Launcher Class
|
|
|
|
*
|
|
|
|
* for WiiXplorer 2010
|
|
|
|
***************************************************************************/
|
|
|
|
#include <cstdio>
|
|
|
|
#include <cstdlib>
|
|
|
|
#include <cstring>
|
|
|
|
|
2012-08-05 15:48:15 +02:00
|
|
|
#include "channel_launcher.h"
|
2012-01-21 21:57:41 +01:00
|
|
|
#include "channels.h"
|
|
|
|
#include "banner.h"
|
2012-12-22 17:47:02 +01:00
|
|
|
#include "nand.hpp"
|
2012-08-05 15:48:15 +02:00
|
|
|
#include "config/config.hpp"
|
2012-12-08 17:17:35 +01:00
|
|
|
#include "gecko/gecko.hpp"
|
2013-09-24 17:21:31 +02:00
|
|
|
#include "gui/fmt.h"
|
2012-08-05 15:48:15 +02:00
|
|
|
#include "gui/text.hpp"
|
|
|
|
#include "loader/fs.h"
|
2013-04-08 23:45:13 +02:00
|
|
|
#include "loader/nk.h"
|
2012-12-22 17:47:02 +01:00
|
|
|
#include "loader/sys.h"
|
2012-08-05 15:48:15 +02:00
|
|
|
#include "memory/mem2.hpp"
|
|
|
|
#include "wstringEx/wstringEx.hpp"
|
2012-01-21 21:57:41 +01:00
|
|
|
|
|
|
|
#define DOWNLOADED_CHANNELS 0x00010001
|
|
|
|
#define SYSTEM_CHANNELS 0x00010002
|
2012-10-20 00:01:30 +02:00
|
|
|
#define GAME_CHANNELS 0x00010004
|
|
|
|
|
2012-01-21 21:57:41 +01:00
|
|
|
#define RF_NEWS_CHANNEL 0x48414741
|
|
|
|
#define RF_FORECAST_CHANNEL 0x48414641
|
|
|
|
|
2012-10-04 17:16:04 +02:00
|
|
|
Channels ChannelHandle;
|
|
|
|
|
2012-10-20 00:01:30 +02:00
|
|
|
void Channels::Init(string lang)
|
2012-01-21 21:57:41 +01:00
|
|
|
{
|
2012-10-20 00:01:30 +02:00
|
|
|
this->langCode = lang;
|
|
|
|
this->clear();
|
|
|
|
Search();
|
2012-01-21 21:57:41 +01:00
|
|
|
}
|
|
|
|
|
2012-10-15 21:16:14 +02:00
|
|
|
void Channels::Cleanup()
|
2012-01-21 21:57:41 +01:00
|
|
|
{
|
2012-10-20 00:01:30 +02:00
|
|
|
this->clear();
|
2012-01-21 21:57:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
u8 Channels::GetRequestedIOS(u64 title)
|
|
|
|
{
|
|
|
|
u8 IOS = 0;
|
2012-12-22 17:47:02 +01:00
|
|
|
u32 size = 0;
|
|
|
|
u8 *titleTMD = NULL;
|
|
|
|
if(NANDemuView)
|
|
|
|
titleTMD = NandHandle.GetTMD(title, &size);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
char tmd[ISFS_MAXPATH] ATTRIBUTE_ALIGN(32);
|
2013-09-24 17:21:31 +02:00
|
|
|
strncpy(tmd, fmt("/title/%08x/%08x/content/title.tmd", TITLE_UPPER(title), TITLE_LOWER(title)), ISFS_MAXPATH);
|
2012-12-22 17:47:02 +01:00
|
|
|
titleTMD = ISFS_GetFile(tmd, &size, -1);
|
|
|
|
}
|
2012-05-13 19:25:26 +02:00
|
|
|
if(titleTMD == NULL)
|
|
|
|
return 0;
|
2012-01-21 21:57:41 +01:00
|
|
|
|
|
|
|
if(size > 0x18B)
|
|
|
|
IOS = titleTMD[0x18B];
|
2012-05-13 17:13:33 +02:00
|
|
|
|
2012-07-27 19:26:49 +02:00
|
|
|
free(titleTMD);
|
2012-07-10 13:25:27 +02:00
|
|
|
gprintf("Requested Game IOS: %i\n", IOS);
|
2012-01-21 21:57:41 +01:00
|
|
|
return IOS;
|
|
|
|
}
|
|
|
|
|
2012-10-20 00:01:30 +02:00
|
|
|
u64 *Channels::GetChannelList(u32 *count)
|
2012-01-21 21:57:41 +01:00
|
|
|
{
|
2012-10-20 00:01:30 +02:00
|
|
|
*count = 0;
|
2012-01-21 21:57:41 +01:00
|
|
|
u32 countall;
|
2012-10-20 00:01:30 +02:00
|
|
|
if(ES_GetNumTitles(&countall) < 0 || countall == 0)
|
|
|
|
return NULL;
|
2012-01-21 21:57:41 +01:00
|
|
|
|
2012-10-20 00:01:30 +02:00
|
|
|
u64 *titles = (u64*)MEM2_alloc(countall*sizeof(u64));
|
|
|
|
if(titles == NULL)
|
2012-05-13 19:25:26 +02:00
|
|
|
return NULL;
|
2012-01-21 21:57:41 +01:00
|
|
|
|
|
|
|
if(ES_GetTitles(titles, countall) < 0)
|
|
|
|
{
|
2012-10-20 00:01:30 +02:00
|
|
|
MEM2_free(titles);
|
2012-01-21 21:57:41 +01:00
|
|
|
return NULL;
|
|
|
|
}
|
2012-10-20 00:01:30 +02:00
|
|
|
*count = countall;
|
|
|
|
return titles;
|
2012-01-21 21:57:41 +01:00
|
|
|
}
|
|
|
|
|
2012-12-22 17:47:02 +01:00
|
|
|
bool Channels::GetAppNameFromTmd(u64 title, char *app, u32 *bootcontent)
|
2012-01-21 21:57:41 +01:00
|
|
|
{
|
|
|
|
bool ret = false;
|
2012-12-22 17:47:02 +01:00
|
|
|
u32 size = 0;
|
|
|
|
u8 *data = NULL;
|
|
|
|
if(NANDemuView)
|
|
|
|
data = NandHandle.GetTMD(title, &size);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
char tmd[ISFS_MAXPATH] ATTRIBUTE_ALIGN(32);
|
2013-09-24 17:21:31 +02:00
|
|
|
strncpy(tmd, fmt("/title/%08x/%08x/content/title.tmd", TITLE_UPPER(title), TITLE_LOWER(title)), ISFS_MAXPATH);
|
2012-12-22 17:47:02 +01:00
|
|
|
data = ISFS_GetFile(tmd, &size, -1);
|
|
|
|
}
|
2013-09-24 17:21:31 +02:00
|
|
|
if(data == NULL || size < 0x208)
|
|
|
|
{
|
|
|
|
if(data != NULL)
|
|
|
|
free(data);
|
2012-05-13 19:25:26 +02:00
|
|
|
return ret;
|
2013-09-24 17:21:31 +02:00
|
|
|
}
|
2012-05-13 19:25:26 +02:00
|
|
|
_tmd *tmd_file = (_tmd *)SIGNATURE_PAYLOAD((u32 *)data);
|
2012-01-21 21:57:41 +01:00
|
|
|
u16 i;
|
|
|
|
for(i = 0; i < tmd_file->num_contents; ++i)
|
2012-05-13 19:25:26 +02:00
|
|
|
{
|
2012-12-22 17:47:02 +01:00
|
|
|
if(tmd_file->contents[i].index == 0)
|
2012-01-21 21:57:41 +01:00
|
|
|
{
|
|
|
|
*bootcontent = tmd_file->contents[i].cid;
|
2013-09-24 17:21:31 +02:00
|
|
|
strncpy(app, fmt("/title/%08x/%08x/content/%08x.app",
|
|
|
|
TITLE_UPPER(title), TITLE_LOWER(title), *bootcontent), ISFS_MAXPATH);
|
2012-01-21 21:57:41 +01:00
|
|
|
ret = true;
|
|
|
|
break;
|
|
|
|
}
|
2012-05-13 19:25:26 +02:00
|
|
|
}
|
2012-01-21 21:57:41 +01:00
|
|
|
|
2012-07-27 19:26:49 +02:00
|
|
|
free(data);
|
2012-01-21 21:57:41 +01:00
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2012-10-15 21:16:14 +02:00
|
|
|
void Channels::GetBanner(u64 title, bool imetOnly)
|
2012-01-21 21:57:41 +01:00
|
|
|
{
|
2012-12-22 17:47:02 +01:00
|
|
|
u32 cid = 0;
|
2012-10-20 00:01:30 +02:00
|
|
|
CurrentBanner.ClearBanner();
|
2012-01-21 21:57:41 +01:00
|
|
|
char app[ISFS_MAXPATH] ATTRIBUTE_ALIGN(32);
|
2012-12-22 17:47:02 +01:00
|
|
|
if(!GetAppNameFromTmd(title, app, &cid))
|
2012-10-15 21:16:14 +02:00
|
|
|
return;
|
2013-10-19 20:59:17 +02:00
|
|
|
CurrentBanner.GetBanner(app, imetOnly);
|
2012-01-21 21:57:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
bool Channels::GetChannelNameFromApp(u64 title, wchar_t* name, int language)
|
|
|
|
{
|
|
|
|
bool ret = false;
|
|
|
|
|
|
|
|
if (language > CONF_LANG_KOREAN)
|
|
|
|
language = CONF_LANG_ENGLISH;
|
|
|
|
|
2012-10-15 21:16:14 +02:00
|
|
|
GetBanner(title, true);
|
|
|
|
if(CurrentBanner.IsValid())
|
2012-01-21 21:57:41 +01:00
|
|
|
{
|
2012-10-15 21:16:14 +02:00
|
|
|
ret = CurrentBanner.GetName(name, language);
|
|
|
|
CurrentBanner.ClearBanner();
|
2012-01-21 21:57:41 +01:00
|
|
|
}
|
2012-10-15 21:16:14 +02:00
|
|
|
|
2012-01-21 21:57:41 +01:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
int Channels::GetLanguage(const char *lang)
|
|
|
|
{
|
|
|
|
if (strncmp(lang, "JP", 2) == 0) return CONF_LANG_JAPANESE;
|
|
|
|
else if (strncmp(lang, "EN", 2) == 0) return CONF_LANG_ENGLISH;
|
|
|
|
else if (strncmp(lang, "DE", 2) == 0) return CONF_LANG_GERMAN;
|
|
|
|
else if (strncmp(lang, "FR", 2) == 0) return CONF_LANG_FRENCH;
|
|
|
|
else if (strncmp(lang, "ES", 2) == 0) return CONF_LANG_SPANISH;
|
|
|
|
else if (strncmp(lang, "IT", 2) == 0) return CONF_LANG_ITALIAN;
|
|
|
|
else if (strncmp(lang, "NL", 2) == 0) return CONF_LANG_DUTCH;
|
|
|
|
else if (strncmp(lang, "ZHTW", 4) == 0) return CONF_LANG_TRAD_CHINESE;
|
|
|
|
else if (strncmp(lang, "ZH", 2) == 0) return CONF_LANG_SIMP_CHINESE;
|
|
|
|
else if (strncmp(lang, "KO", 2) == 0) return CONF_LANG_KOREAN;
|
|
|
|
|
|
|
|
return CONF_LANG_ENGLISH; // Default to EN
|
|
|
|
}
|
|
|
|
|
2012-10-20 00:01:30 +02:00
|
|
|
void Channels::Search()
|
2012-01-21 21:57:41 +01:00
|
|
|
{
|
|
|
|
u32 count;
|
2012-12-22 17:47:02 +01:00
|
|
|
u64 *list = NULL;
|
2013-04-08 23:45:13 +02:00
|
|
|
if(!neek2o() && NANDemuView)
|
2012-12-22 17:47:02 +01:00
|
|
|
list = NandHandle.GetChannels(&count);
|
|
|
|
else
|
|
|
|
list = GetChannelList(&count);
|
2012-10-20 00:01:30 +02:00
|
|
|
if(list == NULL)
|
2012-05-13 19:25:26 +02:00
|
|
|
return;
|
2012-01-21 21:57:41 +01:00
|
|
|
|
2012-10-20 00:01:30 +02:00
|
|
|
int language = langCode.size() == 0 ? CONF_GetLanguage() : GetLanguage(langCode.c_str());
|
2012-01-21 21:57:41 +01:00
|
|
|
|
2012-10-20 00:01:30 +02:00
|
|
|
for(u32 i = 0; i < count; i++)
|
2012-01-21 21:57:41 +01:00
|
|
|
{
|
2012-10-20 00:01:30 +02:00
|
|
|
u32 Type = TITLE_UPPER(list[i]);
|
|
|
|
if(Type == SYSTEM_CHANNELS || Type == DOWNLOADED_CHANNELS || Type == GAME_CHANNELS)
|
2012-01-21 21:57:41 +01:00
|
|
|
{
|
2012-12-22 17:47:02 +01:00
|
|
|
u32 Title = TITLE_LOWER(list[i]);
|
|
|
|
if(Title == RF_NEWS_CHANNEL || Title == RF_FORECAST_CHANNEL)
|
|
|
|
continue; //skip region free news and forecast channel
|
2012-10-20 00:01:30 +02:00
|
|
|
Channel CurrentChan;
|
|
|
|
memset(&CurrentChan, 0, sizeof(Channel));
|
|
|
|
if(GetChannelNameFromApp(list[i], CurrentChan.name, language))
|
2012-01-21 21:57:41 +01:00
|
|
|
{
|
2012-10-20 00:01:30 +02:00
|
|
|
CurrentChan.title = list[i];
|
|
|
|
memcpy(CurrentChan.id, &Title, sizeof(CurrentChan.id));
|
|
|
|
this->push_back(CurrentChan);
|
2012-01-21 21:57:41 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-12-22 17:47:02 +01:00
|
|
|
free(list);
|
2012-01-21 21:57:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
wchar_t * Channels::GetName(int index)
|
|
|
|
{
|
2012-10-07 22:10:30 +02:00
|
|
|
if (index < 0 || index > (int)Count() - 1)
|
2012-01-21 21:57:41 +01:00
|
|
|
{
|
|
|
|
return (wchar_t *) "";
|
|
|
|
}
|
2012-10-20 00:01:30 +02:00
|
|
|
return this->at(index).name;
|
2012-01-21 21:57:41 +01:00
|
|
|
}
|
|
|
|
|
2012-10-07 21:59:50 +02:00
|
|
|
u32 Channels::Count()
|
2012-01-21 21:57:41 +01:00
|
|
|
{
|
2012-10-20 00:01:30 +02:00
|
|
|
return this->size();
|
2012-01-21 21:57:41 +01:00
|
|
|
}
|
|
|
|
|
2012-12-27 21:22:40 +01:00
|
|
|
const char *Channels::GetId(int index)
|
2012-01-21 21:57:41 +01:00
|
|
|
{
|
2012-12-27 21:22:40 +01:00
|
|
|
if(index < 0 || index > (int)Count() - 1)
|
|
|
|
return "";
|
2012-10-20 00:01:30 +02:00
|
|
|
return this->at(index).id;
|
2012-01-21 21:57:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
u64 Channels::GetTitle(int index)
|
|
|
|
{
|
2012-10-07 22:10:30 +02:00
|
|
|
if (index < 0 || index > (int)Count() - 1) return 0;
|
2012-10-20 00:01:30 +02:00
|
|
|
return this->at(index).title;
|
2012-01-21 21:57:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
Channel * Channels::GetChannel(int index)
|
|
|
|
{
|
2012-10-07 22:10:30 +02:00
|
|
|
if (index < 0 || index > (int)Count() - 1) return NULL;
|
2012-10-20 00:01:30 +02:00
|
|
|
return &this->at(index);
|
2012-01-21 21:57:41 +01:00
|
|
|
}
|