/*************************************************************************** * 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 #include #include #include "channel_launcher.h" #include "channels.h" #include "banner.h" #include "config/config.hpp" #include "gecko/gecko.h" #include "gui/text.hpp" #include "loader/fs.h" #include "memory/mem2.hpp" #include "wstringEx/wstringEx.hpp" #define DOWNLOADED_CHANNELS 0x00010001 #define SYSTEM_CHANNELS 0x00010002 #define GAME_CHANNELS 0x00010004 #define RF_NEWS_CHANNEL 0x48414741 #define RF_FORECAST_CHANNEL 0x48414641 Channels ChannelHandle; void Channels::Init(string lang) { this->langCode = lang; this->clear(); Search(); } void Channels::Cleanup() { this->clear(); } u8 Channels::GetRequestedIOS(u64 title) { u8 IOS = 0; char tmd[ISFS_MAXPATH] ATTRIBUTE_ALIGN(32); sprintf(tmd, "/title/%08x/%08x/content/title.tmd", TITLE_UPPER(title), TITLE_LOWER(title)); u32 size; u8 *titleTMD = (u8 *)ISFS_GetFile((u8 *) &tmd, &size, -1); if(titleTMD == NULL) return 0; if(size > 0x18B) IOS = titleTMD[0x18B]; free(titleTMD); gprintf("Requested Game IOS: %i\n", IOS); return IOS; } u64 *Channels::GetChannelList(u32 *count) { *count = 0; u32 countall; if(ES_GetNumTitles(&countall) < 0 || countall == 0) return NULL; u64 *titles = (u64*)MEM2_alloc(countall*sizeof(u64)); if(titles == NULL) return NULL; if(ES_GetTitles(titles, countall) < 0) { MEM2_free(titles); return NULL; } *count = countall; return titles; } bool Channels::GetAppNameFromTmd(u64 title, char *app, bool dol, u32 *bootcontent) { bool ret = false; char tmd[ISFS_MAXPATH] ATTRIBUTE_ALIGN(32); sprintf(tmd, "/title/%08x/%08x/content/title.tmd", TITLE_UPPER(title), TITLE_LOWER(title)); u32 size; u8 *data = ISFS_GetFile((u8 *) &tmd, &size, -1); if (data == NULL || size < 0x208) return ret; _tmd *tmd_file = (_tmd *)SIGNATURE_PAYLOAD((u32 *)data); u16 i; for(i = 0; i < tmd_file->num_contents; ++i) { if(tmd_file->contents[i].index == (dol ? tmd_file->boot_index : 0)) { *bootcontent = tmd_file->contents[i].cid; sprintf(app, "/title/%08x/%08x/content/%08x.app", TITLE_UPPER(title), TITLE_LOWER(title), *bootcontent); ret = true; break; } } free(data); return ret; } void Channels::GetBanner(u64 title, bool imetOnly) { CurrentBanner.ClearBanner(); char app[ISFS_MAXPATH] ATTRIBUTE_ALIGN(32); u32 cid; if(!GetAppNameFromTmd(title, app, false, &cid)) { gprintf("No title found\n"); return; } CurrentBanner.GetBanner(title, app, true, imetOnly); } bool Channels::GetChannelNameFromApp(u64 title, wchar_t* name, int language) { bool ret = false; if (language > CONF_LANG_KOREAN) language = CONF_LANG_ENGLISH; GetBanner(title, true); if(CurrentBanner.IsValid()) { ret = CurrentBanner.GetName(name, language); CurrentBanner.ClearBanner(); } 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 } void Channels::Search() { u32 count; u64 *list = GetChannelList(&count); if(list == NULL) return; int language = langCode.size() == 0 ? CONF_GetLanguage() : GetLanguage(langCode.c_str()); for(u32 i = 0; i < count; i++) { u32 Type = TITLE_UPPER(list[i]); if(Type == SYSTEM_CHANNELS || Type == DOWNLOADED_CHANNELS || Type == GAME_CHANNELS) { Channel CurrentChan; memset(&CurrentChan, 0, sizeof(Channel)); if(GetChannelNameFromApp(list[i], CurrentChan.name, language)) { u32 Title = TITLE_LOWER(list[i]); if(Title == RF_NEWS_CHANNEL || Title == RF_FORECAST_CHANNEL) continue; //skip region free news and forecast channel CurrentChan.title = list[i]; memcpy(CurrentChan.id, &Title, sizeof(CurrentChan.id)); this->push_back(CurrentChan); } } } MEM2_free(list); } wchar_t * Channels::GetName(int index) { if (index < 0 || index > (int)Count() - 1) { return (wchar_t *) ""; } return this->at(index).name; } u32 Channels::Count() { return this->size(); } char * Channels::GetId(int index) { if (index < 0 || index > (int)Count() - 1) return (char *) ""; return this->at(index).id; } u64 Channels::GetTitle(int index) { if (index < 0 || index > (int)Count() - 1) return 0; return this->at(index).title; } Channel * Channels::GetChannel(int index) { if (index < 0 || index > (int)Count() - 1) return NULL; return &this->at(index); }