diff --git a/Makefile b/Makefile index 89d2c9e8..8548d9c2 100644 --- a/Makefile +++ b/Makefile @@ -20,7 +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 \ - source/themefs + source/themes DATA := data INCLUDES := source @@ -35,7 +35,7 @@ LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map,--section-start,.init=0x80B00 #--------------------------------------------------------------------------------- # any extra libraries we wish to link with the project #--------------------------------------------------------------------------------- -LIBS := -lfat -lpngu -lpng -lm -lz -lwiiuse -lbte -lasnd -logc -lfreetype -ltremor -lmxml +LIBS := -lfat -lpngu -lpng -lm -lz -lwiiuse -lbte -lasnd -logc -lfreetype -ltremor -lmxml -ljpeg #--------------------------------------------------------------------------------- # list of directories containing libraries, this must be the top level containing # include and lib diff --git a/source/ZipFile.cpp b/source/ZipFile.cpp new file mode 100644 index 00000000..7255dee6 --- /dev/null +++ b/source/ZipFile.cpp @@ -0,0 +1,140 @@ +/**************************************************************************** + * Copyright (C) 2009 + * 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. + * + * ZipFile.cpp + * + * ZipFile Class + * for Wii-FileXplorer 2009 + * + * STILL UNCOMPLETE AND UNDER CONSTRUCTION + ***************************************************************************/ +#include +#include +#include +#include +#include + +#include "prompts/ProgressWindow.h" +#include "listfiles.h" +#include "ZipFile.h" +#include "language/gettext.h" + +ZipFile::ZipFile(const char *filepath) +{ + File = unzOpen(filepath); + if(File) + this->LoadList(); +} + +ZipFile::~ZipFile() +{ + unzClose(File); +} + +bool ZipFile::LoadList() +{ + return true; +} + +bool ZipFile::ExtractAll(const char *dest) +{ + if(!File) + return false; + + bool Stop = false; + + u32 blocksize = 1024*50; + void *buffer = malloc(blocksize); + + if(!buffer) + return false; + + char writepath[MAXPATHLEN]; + char filename[MAXPATHLEN]; + memset(filename, 0, sizeof(filename)); + + int ret = unzGoToFirstFile(File); + if(ret != UNZ_OK) + Stop = true; + + while(!Stop) + { + if(unzGetCurrentFileInfo(File, &cur_file_info, filename, sizeof(filename), NULL, NULL, NULL, NULL) != UNZ_OK) + Stop = true; + + if(!Stop && filename[strlen(filename)-1] != '/') + { + u32 uncompressed_size = cur_file_info.uncompressed_size; + + u32 done = 0; + char *pointer = NULL; + + ret = unzOpenCurrentFile(File); + + snprintf(writepath, sizeof(writepath), "%s/%s", dest, filename); + + pointer = strrchr(writepath, '/'); + int position = pointer-writepath+2; + + char temppath[strlen(writepath)]; + snprintf(temppath, position, "%s", writepath); + + subfoldercreate(temppath); + + if(ret == UNZ_OK) + { + FILE *pfile = fopen(writepath, "wb"); + + do + { + ShowProgress(tr("Extracting files..."), 0, pointer+1, done, uncompressed_size); + + if(uncompressed_size - done < blocksize) + blocksize = uncompressed_size - done; + + ret = unzReadCurrentFile(File, buffer, blocksize); + + if(ret == 0) + break; + + fwrite(buffer, 1, blocksize, pfile); + + done += ret; + + } while(done < uncompressed_size); + + fclose(pfile); + unzCloseCurrentFile(File); + } + } + if(unzGoToNextFile(File) != UNZ_OK) + Stop = true; + } + + free(buffer); + buffer = NULL; + + ProgressStop(); + + return true; +} diff --git a/source/ZipFile.h b/source/ZipFile.h new file mode 100644 index 00000000..88487565 --- /dev/null +++ b/source/ZipFile.h @@ -0,0 +1,58 @@ +/*************************************************************************** + * Copyright (C) 2009 + * 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. + * + * ZipFile.cpp + * + * for Wii-FileXplorer 2009 + ***************************************************************************/ +#ifndef _ZIPFILE_H_ +#define _ZIPFILE_H_ + +#include "unzip/unzip.h" + +typedef struct +{ + u64 offset; // ZipFile offset + u64 length; // uncompressed file length in 64 bytes for sizes higher than 4GB + bool isdir; // 0 - file, 1 - directory + char filename[256]; // full filename +} FileStructure; + +class ZipFile +{ + public: + //!Constructor + ZipFile(const char *filepath); + //!Destructor + ~ZipFile(); + //!Extract all files from a zip file to a directory + //!\param dest Destination path to where to extract + bool ExtractAll(const char *dest); + protected: + bool LoadList(); + unzFile File; + unz_file_info cur_file_info; + FileStructure *FileList; +}; + +#endif diff --git a/source/banner/MD5.c b/source/banner/MD5.c index 582ae8b1..0aeb6bc9 100644 --- a/source/banner/MD5.c +++ b/source/banner/MD5.c @@ -10,7 +10,7 @@ * $Id: MD5.c,v 0.6 2005/06/08 18:35:59 crh Exp $ * * - * Modified by dimok + * Modifications and additions by dimok * * -------------------------------------------------------------------------- ** * @@ -82,7 +82,7 @@ #include #include #include -#include +#include #include "MD5.h" @@ -168,7 +168,9 @@ static const uint32_t T[4][16] = #define md5H( X, Y, Z ) ( (X) ^ (Y) ^ (Z) ) #define md5I( X, Y, Z ) ( (Y) ^ ((X) | (~(Z))) ) -#define GetLongByte( L, idx ) ((unsigned char)(( L >> (((idx) & 0x03) << 3) ) & 0xFF)) +#define GetLongByte( L, idx ) ((unsigned char)(( L >> (((idx) & 0x03) << 3) ) & 0xFF)) + +#define STR2HEX(x) ((x >= 0x30) && (x <= 0x39)) ? x - 0x30 : toupper((int)x)-0x37 /* -------------------------------------------------------------------------- ** @@ -545,8 +547,8 @@ unsigned char * MD5fromFile(unsigned char *dst, const char *src) auth_md5Ctx ctx[1]; FILE * file; - u32 blksize = 0; - u32 read = 0; + unsigned int blksize = 0; + unsigned int read = 0; file = fopen(src, "rb"); @@ -557,7 +559,7 @@ unsigned char * MD5fromFile(unsigned char *dst, const char *src) (void)auth_md5InitCtx( ctx ); /* Open a context. */ fseek (file , 0 , SEEK_END); - u64 filesize = ftell(file); + unsigned long long filesize = ftell(file); rewind (file); if(filesize < 1048576) //1MB cache for files bigger than 1 MB @@ -586,7 +588,44 @@ unsigned char * MD5fromFile(unsigned char *dst, const char *src) (void)auth_md5CloseCtx( ctx, dst ); /* Close the context. */ return( dst ); /* Makes life easy. */ - } /* auth_md5Sum */ + } /* auth_md5Sum */ + + +const char * MD5ToString(const unsigned char * hash, char * dst) +{ + char hexchar[3]; + short i = 0, n = 0; + + for (i = 0; i < 16; i++) + { + sprintf(hexchar, "%02X", hash[i]); + + dst[n++] = hexchar[0]; + dst[n++] = hexchar[1]; + } + + dst[n] = 0x00; + + return dst; +} + +unsigned char * StringToMD5(const char * hash, unsigned char * dst) +{ + char hexchar[2]; + short i = 0, n = 0; + + for (i = 0; i < 16; i++) + { + hexchar[0] = hash[n++]; + hexchar[1] = hash[n++]; + + dst[i] = STR2HEX(hexchar[0]); + dst[i] <<= 4; + dst[i] += STR2HEX(hexchar[1]); + } + + return dst; +} /* ========================================================================== */ diff --git a/source/banner/MD5.h b/source/banner/MD5.h index f1c5bd3c..fb67ab25 100644 --- a/source/banner/MD5.h +++ b/source/banner/MD5.h @@ -14,7 +14,9 @@ extern "C" * * Email: crh@ubiqx.mn.org * - * $Id: MD5.h,v 0.6 2005/06/08 18:35:59 crh Exp $ + * $Id: MD5.h,v 0.6 2005/06/08 18:35:59 crh Exp $ + * + * Modifications and additions by dimok * * -------------------------------------------------------------------------- ** * @@ -85,8 +87,8 @@ extern "C" typedef struct { - uint32_t len; - uint32_t ABCD[4]; + unsigned int len; + unsigned int ABCD[4]; int b_used; unsigned char block[64]; } auth_md5Ctx; @@ -231,8 +233,10 @@ unsigned char * MD5fromFile(unsigned char *dst, const char *src); * See Also: * * ------------------------------------------------------------------------ ** - */ + */ +const char * MD5ToString(const unsigned char *hash, char *dst); +unsigned char * StringToMD5(const char * hash, unsigned char * dst); /* ========================================================================== */ diff --git a/source/filelist.h b/source/filelist.h index 76716fb3..78970130 100644 --- a/source/filelist.h +++ b/source/filelist.h @@ -161,6 +161,9 @@ extern const u32 nocoverFlat_png_size; extern const u8 nodisc_png[]; extern const u32 nodisc_png_size; +extern const u8 theme_dialogue_box_png[]; +extern const u32 theme_dialogue_box_png_size; + extern const u8 button_install_png[]; extern const u32 button_install_png_size; @@ -221,6 +224,9 @@ extern const u32 wiimote_poweroff_png_size; extern const u8 dialogue_box_png[]; extern const u32 dialogue_box_png_size; +extern const u8 theme_box_png[]; +extern const u32 theme_box_png_size; + extern const u8 wiimote_poweroff_over_png[]; extern const u32 wiimote_poweroff_over_png_size; diff --git a/source/images/theme_box.png b/source/images/theme_box.png new file mode 100644 index 00000000..174b7b52 Binary files /dev/null and b/source/images/theme_box.png differ diff --git a/source/images/theme_dialogue_box.png b/source/images/theme_dialogue_box.png new file mode 100644 index 00000000..389cfa1d Binary files /dev/null and b/source/images/theme_dialogue_box.png differ diff --git a/source/libwiigui/gui.h b/source/libwiigui/gui.h index 9fac862c..50d9e1fe 100644 --- a/source/libwiigui/gui.h +++ b/source/libwiigui/gui.h @@ -560,6 +560,7 @@ class GuiImageData //!\param i Image data GuiImageData(const u8 * i); GuiImageData(const char * imgPath, const u8 * buffer); + GuiImageData(const u8 * img, int imgSize); GuiImageData(const char *path, const char *file, const u8 * buffer, bool force_widescreen=false, const u8 * wbuffer=NULL); //!Destructor ~GuiImageData(); @@ -572,6 +573,10 @@ class GuiImageData //!Gets the image height //!\return image height int GetHeight(); + //!LoadJpeg file + void LoadJpeg(const u8 *img, int imgSize); + //!RawTo4x4RGBA + void RawTo4x4RGBA(const unsigned char *src, void *dst, const unsigned int width, const unsigned int height); //!Sets the image to grayscale void SetGrayscale(void); protected: diff --git a/source/libwiigui/gui_imagedata.cpp b/source/libwiigui/gui_imagedata.cpp index 5869abb0..562903b2 100644 --- a/source/libwiigui/gui_imagedata.cpp +++ b/source/libwiigui/gui_imagedata.cpp @@ -5,11 +5,28 @@ * * gui_imagedata.cpp * + * LoadJpeg copyright by r-win for WiiXplorer + * check WiiXplorer source for license conditions + * * GUI class definitions ***************************************************************************/ #include "gui.h" +#ifdef __cplusplus +extern "C" +{ +#endif + +#include + +#ifdef __cplusplus +} +#endif + +#define new_width 640 +#define new_height 480 + /** * Constructor for the GuiImageData class. */ @@ -63,6 +80,19 @@ GuiImageData::GuiImageData(const u8 * img) } } +GuiImageData::GuiImageData(const u8 * img, int imgSize) +{ + data = NULL; + width = 0; + height = 0; + + if(img) + { + if (img[0] == 0xFF && img[1] == 0xD8) { // IMAGE_JPEG + LoadJpeg(img, imgSize); + } + } +} /** * Constructor for the GuiImageData class. */ @@ -175,7 +205,7 @@ GuiImageData::GuiImageData(const char *path, const char *file, const u8 *buffer, } else imgPath = path_4_3; - + for(;;) { if(imgPath) @@ -309,3 +339,108 @@ void GuiImageData::SetGrayscale(void) } } } + +// This function finds it's origin in GRRLIB, which can be found here: http://code.google.com/p/grrlib/ +void GuiImageData::LoadJpeg(const u8 *img, int imgSize) +{ + struct jpeg_decompress_struct cinfo; + struct jpeg_error_mgr jerr; + + int n = imgSize; + + while (n > 1) { + if (img[n - 1] == 0xff && img[n] == 0xd9) { + break; + } + n--; + } + + jpeg_create_decompress(&cinfo); + cinfo.err = jpeg_std_error(&jerr); + cinfo.progress = NULL; + jpeg_memory_src(&cinfo, img, n); + jpeg_read_header(&cinfo, TRUE); + jpeg_calc_output_dimensions(&cinfo); + + if (cinfo.output_width > new_width || cinfo.output_height > new_height) + { + float factor = (cinfo.output_width > cinfo.output_height) ? (1.0 * cinfo.output_width) / new_width : (1.0 * cinfo.output_height) / new_height; + cinfo.scale_num = 1; + cinfo.scale_denom = factor; + cinfo.do_fancy_upsampling = true; + cinfo.do_block_smoothing = false; + cinfo.dct_method = JDCT_IFAST; + } + + jpeg_start_decompress(&cinfo); + + int rowsize = cinfo.output_width * cinfo.num_components; + unsigned char *tempBuffer = (unsigned char *) malloc(rowsize * cinfo.output_height); + + JSAMPROW row_pointer[1]; + + row_pointer[0] = (unsigned char*) malloc(rowsize); + size_t location = 0; + while (cinfo.output_scanline < cinfo.output_height) { + jpeg_read_scanlines(&cinfo, row_pointer, 1); + memcpy(tempBuffer + location, row_pointer[0], rowsize); + location += rowsize; + } + + int len = ((cinfo.output_width+3)>>2)*((cinfo.output_height+3)>>2)*32*2; + + data = (u8 *) memalign(32, len); + + RawTo4x4RGBA(tempBuffer, data, cinfo.output_width, cinfo.output_height); + DCFlushRange(data, len); + + width = cinfo.output_width; + height = cinfo.output_height; + + jpeg_finish_decompress(&cinfo); + jpeg_destroy_decompress(&cinfo); + free(row_pointer[0]); + free(tempBuffer); +} + +/** + * Convert a raw bmp (RGB, no alpha) to 4x4RGBA. + * @author DragonMinded + * @param src + * @param dst + * @param width + * @param height +*/ +void GuiImageData::RawTo4x4RGBA(const unsigned char *src, void *dst, const unsigned int width, const unsigned int height) +{ + unsigned int block; + unsigned int i; + unsigned int c; + unsigned int ar; + unsigned int gb; + unsigned char *p = (unsigned char*)dst; + + for (block = 0; block < height; block += 4) { + for (i = 0; i < width; i += 4) { + /* Alpha and Red */ + for (c = 0; c < 4; ++c) { + for (ar = 0; ar < 4; ++ar) { + /* Alpha pixels */ + *p++ = 255; + /* Red pixels */ + *p++ = src[((i + ar) + ((block + c) * width)) * 3]; + } + } + + /* Green and Blue */ + for (c = 0; c < 4; ++c) { + for (gb = 0; gb < 4; ++gb) { + /* Green pixels */ + *p++ = src[(((i + gb) + ((block + c) * width)) * 3) + 1]; + /* Blue pixels */ + *p++ = src[(((i + gb) + ((block + c) * width)) * 3) + 2]; + } + } + } /* i */ + } /* block */ +} diff --git a/source/menu.cpp b/source/menu.cpp index 4d9c1ac5..ede42f14 100644 --- a/source/menu.cpp +++ b/source/menu.cpp @@ -52,6 +52,7 @@ #include "usbloader/wdvd.h" +#include "themes/Theme_Downloader.h" #define MAX_CHARACTERS 38 @@ -214,7 +215,7 @@ void ExitGUIThreads() { } void rockout(int f = 0) { - + HaltGui(); int num=(f==2?-1:gameSelected); @@ -271,7 +272,7 @@ GuiImageData *LoadCoverImage(struct discHdr *header, bool Prefere3D, bool noCove { char *coverPath = flag ? Settings.covers_path : Settings.covers2d_path; flag = !flag; //Load full id image - snprintf(Path, sizeof(Path), "%s%s.png", coverPath, IDfull); + snprintf(Path, sizeof(Path), "%s%s.png", coverPath, IDfull); delete Cover; Cover = new(std::nothrow) GuiImageData(Path, NULL); //Load short id image if (!Cover || !Cover->GetImage()) @@ -338,7 +339,7 @@ int MenuDiscList() { if (!dvdheader) dvdheader = new struct discHdr; u8 mountMethodOLD =0; - + WDVD_GetCoverStatus(&covert); u32 covertOld=covert; @@ -461,19 +462,19 @@ int MenuDiscList() { GuiText usedSpaceTxt(spaceinfo, 18, THEME.info); usedSpaceTxt.SetAlignment(THEME.hddinfo_align, ALIGN_TOP); usedSpaceTxt.SetPosition(THEME.hddinfo_x, THEME.hddinfo_y); - + char GamesCnt[15]; sprintf(GamesCnt,"%s: %i",(mountMethod!=3?tr("Games"):tr("Channels")), gameCnt); GuiText gamecntTxt(GamesCnt, 18, THEME.info); - + GuiButton gamecntBtn(100,18); gamecntBtn.SetAlignment(THEME.gamecount_align, ALIGN_TOP); gamecntBtn.SetPosition(THEME.gamecount_x,THEME.gamecount_y); gamecntBtn.SetLabel(&gamecntTxt); gamecntBtn.SetEffectGrow(); gamecntBtn.SetTrigger(&trigA); - - + + GuiTooltip installBtnTT(tr("Install a game")); if (Settings.wsprompt == yes) @@ -737,18 +738,18 @@ int MenuDiscList() { idBtn.SetAlignment(ALIGN_LEFT, ALIGN_TOP); idBtn.SetPosition(THEME.id_x,THEME.id_y); - + if (Settings.godmode == 1 && mountMethod!=3) {//only make the button have trigger & tooltip if in godmode DownloadBtn.SetSoundOver(&btnSoundOver); DownloadBtn.SetTrigger(&trigA); DownloadBtn.SetTrigger(&trig1); DownloadBtn.SetToolTip(&DownloadBtnTT,205,-30); - + idBtn.SetSoundOver(&btnSoundOver); idBtn.SetTrigger(&trigA); idBtn.SetToolTip(&IDBtnTT,205,-30); - + } else { DownloadBtn.SetRumble(false); @@ -800,7 +801,7 @@ int MenuDiscList() { w.Append(&settingsBtn); w.Append(&DownloadBtn); w.Append(&idBtn); - + // Begin Toolbar w.Append(&favoriteBtn); Toolbar[0] = &favoriteBtn; @@ -820,9 +821,9 @@ int MenuDiscList() { Toolbar[7] = &dvdBtn; w.SetUpdateCallback(DiscListWinUpdateCallback); // End Toolbar - - - + + + if (Settings.godmode == 1) w.Append(&homebrewBtn); @@ -848,10 +849,10 @@ int MenuDiscList() { if(searchBar) mainWindow->Append(searchBar); } - + ResumeGui(); - - + + while (menu == MENU_NONE) { if (idiotFlag==1) { @@ -1062,7 +1063,7 @@ int MenuDiscList() { } if (isInserted(bootDevice)) { HaltGui(); // to fix endless rumble when clicking on the SD icon when rumble is disabled because rumble is set to on in Global_Default() - CFG_Load(); + CFG_Load(); ResumeGui(); } sdcardBtn.ResetState(); @@ -1181,8 +1182,8 @@ int MenuDiscList() { wcscpy(newFilter, gameFilter); newFilter[len] = searchChar; newFilter[len+1] = 0; - - + + __Menu_GetEntries(0, newFilter); menu = MENU_DISCLIST; break; @@ -1212,7 +1213,7 @@ int MenuDiscList() { searchBtn.SetImageOver(&searchBtnImg_g); searchBtn.SetAlpha(180); } - + ResumeGui(); } else if(searchChar == 8) // Backspace @@ -1223,7 +1224,7 @@ int MenuDiscList() { } } - + else if (abcBtn.GetState() == STATE_CLICKED) { gprintf("\n\tabcBtn clicked"); if (Settings.sort != all) { @@ -1326,7 +1327,7 @@ int MenuDiscList() { else if (dvdBtn.GetState() == STATE_CLICKED) { gprintf("\n\tdvdBtn Clicked"); mountMethodOLD = (mountMethod==3?mountMethod:0); - + mountMethod=DiscMount(dvdheader); dvdBtn.ResetState(); @@ -1379,7 +1380,7 @@ int MenuDiscList() { delete GameRegionTxt; GameRegionTxt = NULL; } - + switch (header->id[3]) { case 'E': sprintf(gameregion,"NTSC U"); @@ -1443,7 +1444,7 @@ int MenuDiscList() { } } } - + if (idBtn.GetState() == STATE_CLICKED && mountMethod!=3) { gprintf("\n\tidBtn Clicked"); struct discHdr * header = &gameList[gameBrowser->GetSelectedOption()]; @@ -1457,13 +1458,13 @@ int MenuDiscList() { //__Menu_GetEntries(); menu = MENU_DISCLIST; } - + idBtn.ResetState(); } } if (((gameSelected >= 0) && (gameSelected < (s32)gameCnt)) - || mountMethod==1 + || mountMethod==1 || mountMethod==2) { if(searchBar) { @@ -1492,7 +1493,7 @@ int MenuDiscList() { header = (mountMethod==1||mountMethod==2?dvdheader:&gameList[gameSelected]); //reset header snprintf (IDfull,sizeof(IDfull),"%c%c%c%c%c%c", header->id[0], header->id[1], header->id[2],header->id[3], header->id[4], header->id[5]); struct Game_CFG* game_cfg = CFG_get_game_opt(header->id); - + if (game_cfg) { alternatedol = game_cfg->loadalternatedol; ocarinaChoice = game_cfg->ocarina; @@ -1538,7 +1539,7 @@ int MenuDiscList() { } } - + wiilight(0); if (isInserted(bootDevice)) { //////////save game play count//////////////// @@ -1642,7 +1643,7 @@ int MenuDiscList() { wiilight(0); //re-evaluate header now in case they changed games while on the game prompt header = &gameList[gameSelected]; - + //enter new game title char entered[60]; snprintf(entered, sizeof(entered), "%s", get_title(header)); @@ -1699,7 +1700,7 @@ int MenuDiscList() { if (game_cfg) { if (game_cfg->alternatedolstart != 0) altdoldefault = false; - } + } if (altdoldefault) { int autodol = autoSelectDol((char*)header->id, true); if (autodol>0) { @@ -1717,11 +1718,11 @@ int MenuDiscList() { } } } - + if (menu == MENU_EXIT) { SDCard_deInit(); } - + HaltGui(); mainWindow->RemoveAll(); mainWindow->Append(bgImg); @@ -1766,7 +1767,7 @@ static int MenuInstall() { GuiImageData batteryRed(imgPath, battery_red_png); snprintf(imgPath, sizeof(imgPath), "%sbattery_bar_red.png", CFG.theme_path); GuiImageData batteryBarRed(imgPath, battery_bar_red_png); - + HaltGui(); GuiWindow w(screenwidth, screenheight); @@ -2196,6 +2197,9 @@ int MainMenu(int menu) { case MENU_SETTINGS: currentMenu = MenuSettings(); break; + case MENU_THEMEDOWNLOADER: + currentMenu = Theme_Downloader(); + break; case MENU_HOMEBREWBROWSE: currentMenu = MenuHomebrewBrowse(); break; @@ -2207,7 +2211,7 @@ int MainMenu(int menu) { break; } } - + //MemInfoPrompt(); //for testing /*if (mountMethod) @@ -2231,7 +2235,7 @@ int MainMenu(int menu) { delete GameIDTxt; delete cover; delete coverImg; - delete fontClock; + delete fontClock; delete fontSystem; ShutdownAudio(); StopGX(); @@ -2278,7 +2282,7 @@ int MainMenu(int menu) { if (!altdoldefault) { alternatedol = game_cfg->loadalternatedol; alternatedoloffset = game_cfg->alternatedolstart; - } + } reloadblock = game_cfg->iosreloadblock; } else { videoChoice = Settings.video; @@ -2298,7 +2302,7 @@ int MainMenu(int menu) { } reloadblock = off; } - + int ios2; switch (iosChoice) { case i249: @@ -2325,8 +2329,8 @@ int MainMenu(int menu) { Sys_IosReload(249); } } - if (!mountMethod) - { + if (!mountMethod) + { ret = Disc_SetUSB(header->id); if (ret < 0) Sys_BackToLoader(); gprintf("\n\tUSB set to game"); @@ -2345,7 +2349,7 @@ int MainMenu(int menu) { } if(dvdheader) delete dvdheader; - + if (reloadblock == on && (IOS_GetVersion() == 222 || IOS_GetVersion() == 223)) { patch_cios_data(); mload_close(); diff --git a/source/menu.h b/source/menu.h index 144bca0e..347b1d43 100644 --- a/source/menu.h +++ b/source/menu.h @@ -28,7 +28,8 @@ enum { MENU_CHECK, MENU_GAME_SETTINGS, MENU_HOMEBREWBROWSE, - BOOTHOMEBREW + BOOTHOMEBREW, + MENU_THEMEDOWNLOADER }; class GuiImageData; GuiImageData *LoadCoverImage(struct discHdr *header, bool Prefere3D=true, bool noCover=true); diff --git a/source/network/http.c b/source/network/http.c index 116e517a..c2b24d92 100644 --- a/source/network/http.c +++ b/source/network/http.c @@ -156,7 +156,7 @@ struct block downloadfile(const char *url) { char domain[domainlength + 1]; strlcpy(domain, url + strlen("http://"), domainlength+1); - + //Parsing of the URL is done, start making an actual connection u32 ipaddress = getipbynamecached(domain); @@ -174,9 +174,9 @@ struct block downloadfile(const char *url) { } //Form a nice request header to send to the webserver - char* headerformat = "GET %s HTTP/1.0\r\nHost: %s\r\nUser-Agent: USBLoaderGX r%s\r\n\r\n";; - char header[strlen(headerformat) + strlen(domain) + strlen(path)]; - sprintf(header, headerformat, path, domain, GetRev()); + char* headerformat = "GET %s HTTP/1.1\r\nHost: %s\r\nReferer: %s\r\nUser-Agent: USBLoaderGX r%s\r\n\r\n";; + char header[strlen(headerformat) + strlen(domain) + strlen(path)+strlen(url)]; + sprintf(header, headerformat, path, domain, url, GetRev()); //Do the request and get the response send_message(connection, header); diff --git a/source/network/networkops.cpp b/source/network/networkops.cpp index ccee7c0c..86c86cd1 100644 --- a/source/network/networkops.cpp +++ b/source/network/networkops.cpp @@ -187,8 +187,8 @@ s32 download_request(const char * url) { } //Form a nice request header to send to the webserver - char header[strlen(path)+strlen(domain)+100]; - sprintf(header, "GET %s HTTP/1.1\r\nHost: %s\r\nConnection: close\r\n\r\n", path, domain); + char header[strlen(path)+strlen(domain)+strlen(url)+100]; + sprintf(header, "GET %s HTTP/1.1\r\nHost: %s\r\nReferer: %s\r\nConnection: close\r\n\r\n", path, domain, url); s32 filesize = network_request(header); @@ -254,7 +254,7 @@ int NetworkWait() { net_read(connection, &haxx, 8); wiiloadVersion[0] = haxx[4]; wiiloadVersion[1] = haxx[5]; - + net_read(connection, &infilesize, 4); if (haxx[4] > 0 || haxx[5] > 4) { diff --git a/source/settings/Settings.cpp b/source/settings/Settings.cpp index d650fb04..2f1a22b4 100644 --- a/source/settings/Settings.cpp +++ b/source/settings/Settings.cpp @@ -23,7 +23,7 @@ /*** Extern functions ***/ extern void ResumeGui(); extern void HaltGui(); -extern bool +extern bool Database(char* xmlfilepath, char* argdblang, bool argJPtoEN, bool openfile, bool loadtitles, bool keepopen); extern void titles_default(); @@ -135,7 +135,7 @@ int MenuSettings() { GuiText PageindicatorTxt1("1", 22, (GXColor) { 0, 0, 0, 255}); GuiButton PageIndicatorBtn1(PageindicatorImg1.GetWidth(), PageindicatorImg1.GetHeight()); PageIndicatorBtn1.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); - PageIndicatorBtn1.SetPosition(200, 400); + PageIndicatorBtn1.SetPosition(165, 400); PageIndicatorBtn1.SetImage(&PageindicatorImg1); PageIndicatorBtn1.SetLabel(&PageindicatorTxt1); PageIndicatorBtn1.SetSoundOver(&btnSoundOver); @@ -147,7 +147,7 @@ int MenuSettings() { GuiText PageindicatorTxt2("2", 22, (GXColor) {0, 0, 0, 255}); GuiButton PageIndicatorBtn2(PageindicatorImg2.GetWidth(), PageindicatorImg2.GetHeight()); PageIndicatorBtn2.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); - PageIndicatorBtn2.SetPosition(235, 400); + PageIndicatorBtn2.SetPosition(200, 400); PageIndicatorBtn2.SetImage(&PageindicatorImg2); PageIndicatorBtn2.SetLabel(&PageindicatorTxt2); PageIndicatorBtn2.SetSoundOver(&btnSoundOver); @@ -155,6 +155,18 @@ int MenuSettings() { PageIndicatorBtn2.SetTrigger(&trigA); PageIndicatorBtn2.SetEffectGrow(); + GuiImage PageindicatorImg3(&PageindicatorImgData); + GuiText PageindicatorTxt3("3", 22, (GXColor) {0, 0, 0, 255}); + GuiButton PageIndicatorBtn3(PageindicatorImg3.GetWidth(), PageindicatorImg3.GetHeight()); + PageIndicatorBtn3.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + PageIndicatorBtn3.SetPosition(235, 400); + PageIndicatorBtn3.SetImage(&PageindicatorImg3); + PageIndicatorBtn3.SetLabel(&PageindicatorTxt3); + PageIndicatorBtn3.SetSoundOver(&btnSoundOver); + PageIndicatorBtn3.SetSoundClick(&btnClick1); + PageIndicatorBtn3.SetTrigger(&trigA); + PageIndicatorBtn3.SetEffectGrow(); + GuiImage GoLeftImg(&arrow_left); GuiButton GoLeftBtn(GoLeftImg.GetWidth(), GoLeftImg.GetHeight()); GoLeftBtn.SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); @@ -293,6 +305,7 @@ int MenuSettings() { w.Append(&settingsbackground); w.Append(&PageIndicatorBtn1); w.Append(&PageIndicatorBtn2); + w.Append(&PageIndicatorBtn3); w.Append(&titleTxt); w.Append(&backBtn); w.Append(&homo); @@ -305,6 +318,7 @@ int MenuSettings() { PageIndicatorBtn1.SetAlpha(255); PageIndicatorBtn2.SetAlpha(50); + PageIndicatorBtn3.SetAlpha(50); /** Creditsbutton change **/ MainButton4.SetImage(&MainButton4Img); @@ -387,6 +401,7 @@ int MenuSettings() { w.Append(&settingsbackground); w.Append(&PageIndicatorBtn1); w.Append(&PageIndicatorBtn2); + w.Append(&PageIndicatorBtn3); w.Append(&titleTxt); w.Append(&backBtn); w.Append(&homo); @@ -399,6 +414,7 @@ int MenuSettings() { PageIndicatorBtn1.SetAlpha(50); PageIndicatorBtn2.SetAlpha(255); + PageIndicatorBtn3.SetAlpha(50); /** Creditsbutton change **/ MainButton4.SetImage(&creditsImg); @@ -444,6 +460,95 @@ int MenuSettings() { while (MainButton1.GetEffect() > 0) usleep(50); } + else if ( pageToDisplay == 3 ) { + /** Standard procedure made in all pages **/ + MainButton1.StopEffect(); + MainButton2.StopEffect(); + MainButton3.StopEffect(); + MainButton4.StopEffect(); + + if (slidedirection == RIGHT) { + MainButton1.SetEffect(EFFECT_SLIDE_LEFT | EFFECT_SLIDE_OUT, 35); + MainButton2.SetEffect(EFFECT_SLIDE_LEFT | EFFECT_SLIDE_OUT, 35); + MainButton3.SetEffect(EFFECT_SLIDE_LEFT | EFFECT_SLIDE_OUT, 35); + MainButton4.SetEffect(EFFECT_SLIDE_LEFT | EFFECT_SLIDE_OUT, 35); + while (MainButton1.GetEffect()>0) usleep(50); + } else if (slidedirection == LEFT) { + MainButton1.SetEffect(EFFECT_SLIDE_RIGHT | EFFECT_SLIDE_OUT, 35); + MainButton2.SetEffect(EFFECT_SLIDE_RIGHT | EFFECT_SLIDE_OUT, 35); + MainButton3.SetEffect(EFFECT_SLIDE_RIGHT | EFFECT_SLIDE_OUT, 35); + MainButton4.SetEffect(EFFECT_SLIDE_RIGHT | EFFECT_SLIDE_OUT, 35); + while (MainButton1.GetEffect()>0) usleep(50); + } + + HaltGui(); + + snprintf(MainButtonText, sizeof(MainButtonText), "%s", tr("Theme Downloader")); + MainButton1Txt.SetText(MainButtonText); + snprintf(MainButtonText, sizeof(MainButtonText), "%s", tr(" ")); + MainButton2Txt.SetText(MainButtonText); + snprintf(MainButtonText, sizeof(MainButtonText), "%s", tr(" ")); + MainButton3Txt.SetText(MainButtonText); + snprintf(MainButtonText, sizeof(MainButtonText), "%s", tr(" ")); + MainButton4Txt.SetText(MainButtonText); + + mainWindow->RemoveAll(); + mainWindow->Append(&w); + w.RemoveAll(); + w.Append(&settingsbackground); + w.Append(&PageIndicatorBtn1); + w.Append(&PageIndicatorBtn2); + w.Append(&PageIndicatorBtn3); + w.Append(&titleTxt); + w.Append(&backBtn); + w.Append(&homo); + w.Append(&GoRightBtn); + w.Append(&GoLeftBtn); + w.Append(&MainButton1); + + PageIndicatorBtn1.SetAlpha(50); + PageIndicatorBtn2.SetAlpha(50); + PageIndicatorBtn3.SetAlpha(255); + + /** Disable ability to click through MainButtons */ + optionBrowser2.SetClickable(false); + /** Default no scrollbar and reset position **/ + optionBrowser2.SetScrollbar(0); + optionBrowser2.SetOffset(0); + + MainButton1.StopEffect(); + MainButton2.StopEffect(); + MainButton3.StopEffect(); + MainButton4.StopEffect(); + + MainButton1.SetEffectGrow(); + MainButton2.SetEffectGrow(); + MainButton3.SetEffectGrow(); + MainButton4.SetEffectGrow(); + + if (slidedirection == FADE) { + MainButton1.SetEffect(EFFECT_FADE, 20); + MainButton2.SetEffect(EFFECT_FADE, 20); + MainButton3.SetEffect(EFFECT_FADE, 20); + MainButton4.SetEffect(EFFECT_FADE, 20); + } else if (slidedirection == LEFT) { + MainButton1.SetEffect(EFFECT_SLIDE_LEFT | EFFECT_SLIDE_IN, 35); + MainButton2.SetEffect(EFFECT_SLIDE_LEFT | EFFECT_SLIDE_IN, 35); + MainButton3.SetEffect(EFFECT_SLIDE_LEFT | EFFECT_SLIDE_IN, 35); + MainButton4.SetEffect(EFFECT_SLIDE_LEFT | EFFECT_SLIDE_IN, 35); + } else if (slidedirection == RIGHT) { + MainButton1.SetEffect(EFFECT_SLIDE_RIGHT | EFFECT_SLIDE_IN, 35); + MainButton2.SetEffect(EFFECT_SLIDE_RIGHT | EFFECT_SLIDE_IN, 35); + MainButton3.SetEffect(EFFECT_SLIDE_RIGHT | EFFECT_SLIDE_IN, 35); + MainButton4.SetEffect(EFFECT_SLIDE_RIGHT | EFFECT_SLIDE_IN, 35); + } + + mainWindow->Append(&w); + + ResumeGui(); + + while (MainButton1.GetEffect() > 0) usleep(50); + } while (menu == MENU_NONE) { VIDEO_WaitVSync (); @@ -458,6 +563,7 @@ int MenuSettings() { HaltGui(); w.Remove(&PageIndicatorBtn1); w.Remove(&PageIndicatorBtn2); + w.Remove(&PageIndicatorBtn3); w.Remove(&GoRightBtn); w.Remove(&GoLeftBtn); w.Remove(&MainButton1); @@ -711,6 +817,7 @@ int MenuSettings() { HaltGui(); w.Remove(&PageIndicatorBtn1); w.Remove(&PageIndicatorBtn2); + w.Remove(&PageIndicatorBtn3); w.Remove(&GoRightBtn); w.Remove(&GoLeftBtn); w.Remove(&MainButton1); @@ -879,6 +986,7 @@ int MenuSettings() { HaltGui(); w.Remove(&PageIndicatorBtn1); w.Remove(&PageIndicatorBtn2); + w.Remove(&PageIndicatorBtn3); w.Remove(&GoRightBtn); w.Remove(&GoLeftBtn); w.Remove(&MainButton1); @@ -1033,6 +1141,7 @@ int MenuSettings() { HaltGui(); w.Remove(&PageIndicatorBtn1); w.Remove(&PageIndicatorBtn2); + w.Remove(&PageIndicatorBtn3); w.Remove(&GoRightBtn); w.Remove(&GoLeftBtn); w.Remove(&MainButton1); @@ -1167,6 +1276,7 @@ int MenuSettings() { HaltGui(); w.Remove(&PageIndicatorBtn1); w.Remove(&PageIndicatorBtn2); + w.Remove(&PageIndicatorBtn3); w.Remove(&GoRightBtn); w.Remove(&GoLeftBtn); w.Remove(&MainButton1); @@ -1175,7 +1285,7 @@ int MenuSettings() { w.Remove(&MainButton4); titleTxt.SetText(tr("Custom Paths")); exit = false; - options2.SetLength(10); + options2.SetLength(11); for (int i = 0; i <= MAXOPTIONS; i++) options2.SetName(i, NULL); options2.SetName(0, "%s", tr("3D Cover Path")); options2.SetName(1, "%s", tr("2D Cover Path")); @@ -1187,6 +1297,7 @@ int MenuSettings() { options2.SetName(7, "%s", tr("TXT Cheatcodes Path")); options2.SetName(8, "%s", tr("DOL Path")); options2.SetName(9, "%s", tr("Homebrew Apps Path")); + options2.SetName(10, "%s", tr("Theme Downloadpath")); for (int i = 0; i <= MAXOPTIONS; i++) options2.SetValue(i, NULL); optionBrowser2.SetScrollbar(1); w.Append(&optionBrowser2); @@ -1212,6 +1323,7 @@ int MenuSettings() { options2.SetValue(7, "%s", Settings.TxtCheatcodespath); options2.SetValue(8, "%s", Settings.dolpath); options2.SetValue(9, "%s", Settings.homebrewapps_path); + options2.SetValue(10, "%s", Settings.theme_downloadpath); if (backBtn.GetState() == STATE_CLICKED) { backBtn.ResetState(); @@ -1526,6 +1638,31 @@ int MenuSettings() { WindowPrompt(tr("Homebrew Appspath change"),tr("Console should be unlocked to modify it."),tr("OK")); } break; + case 10: + if ( Settings.godmode == 1) { + w.Remove(&optionBrowser2); + w.Remove(&backBtn); + char entered[43] = ""; + strlcpy(entered, Settings.theme_downloadpath, sizeof(entered)); + titleTxt.SetText(tr("Theme Downloadpath")); + int result = BrowseDevice(entered, sizeof(entered), FB_DEFAULT, noFILES); + titleTxt.SetText(tr("Custom Paths")); + w.Append(&optionBrowser2); + w.Append(&backBtn); + if ( result == 1 ) { + int len = (strlen(entered)-1); + if (entered[len] !='/') + strncat (entered, "/", 1); + strlcpy(Settings.theme_downloadpath, entered, sizeof(Settings.theme_downloadpath)); + WindowPrompt(tr("Theme Downloadpath changed."),0,tr("OK")); + if (!isInserted(bootDevice)) { + WindowPrompt(tr("No SD-Card inserted!"), tr("Insert an SD-Card to save."), tr("OK")); + } + } + } else { + WindowPrompt(tr("Theme Downloadpath change"),tr("Console should be unlocked to modify it."),tr("OK")); + } + break; } } @@ -1550,6 +1687,7 @@ int MenuSettings() { while (MainButton2.GetEffect() > 0) usleep(50); w.Remove(&PageIndicatorBtn1); w.Remove(&PageIndicatorBtn2); + w.Remove(&PageIndicatorBtn3); w.Remove(&GoRightBtn); w.Remove(&GoLeftBtn); w.Remove(&MainButton1); @@ -1582,6 +1720,7 @@ int MenuSettings() { while (MainButton3.GetEffect() > 0) usleep(50); w.Remove(&PageIndicatorBtn1); w.Remove(&PageIndicatorBtn2); + w.Remove(&PageIndicatorBtn3); w.Remove(&GoRightBtn); w.Remove(&GoLeftBtn); w.Remove(&MainButton1); @@ -1624,6 +1763,7 @@ int MenuSettings() { while (MainButton4.GetEffect() > 0) usleep(50); w.Remove(&PageIndicatorBtn1); w.Remove(&PageIndicatorBtn2); + w.Remove(&PageIndicatorBtn3); w.Remove(&GoRightBtn); w.Remove(&GoLeftBtn); w.Remove(&MainButton1); @@ -1638,6 +1778,17 @@ int MenuSettings() { } } + if(pageToDisplay == 3) { + if (MainButton1.GetState() == STATE_CLICKED) { + if (isInserted(bootDevice)) { + cfg_save_global(); + } + menu = MENU_THEMEDOWNLOADER; + pageToDisplay = 0; + break; + } + } + if (shutdown == 1) Sys_Shutdown(); if (reset == 1) @@ -1657,7 +1808,7 @@ int MenuSettings() { pageToDisplay--; /** Change direction of the flying buttons **/ if (pageToDisplay < 1) - pageToDisplay = 2; + pageToDisplay = 3; slidedirection = LEFT; GoLeftBtn.ResetState(); break; @@ -1666,7 +1817,7 @@ int MenuSettings() { if (GoRightBtn.GetState() == STATE_CLICKED) { pageToDisplay++; /** Change direction of the flying buttons **/ - if (pageToDisplay > 2) + if (pageToDisplay > 3) pageToDisplay = 1; slidedirection = RIGHT; GoRightBtn.ResetState(); @@ -1674,7 +1825,7 @@ int MenuSettings() { } if (PageIndicatorBtn1.GetState() == STATE_CLICKED) { - if (pageToDisplay == 2) { + if (pageToDisplay > 1) { slidedirection = LEFT; pageToDisplay = 1; PageIndicatorBtn1.ResetState(); @@ -1682,13 +1833,27 @@ int MenuSettings() { } PageIndicatorBtn1.ResetState(); } else if (PageIndicatorBtn2.GetState() == STATE_CLICKED) { - if (pageToDisplay == 1) { + if (pageToDisplay < 2) { slidedirection = RIGHT; pageToDisplay = 2; PageIndicatorBtn2.ResetState(); break; - } else + } else if (pageToDisplay > 2) { + slidedirection = LEFT; + pageToDisplay = 2; PageIndicatorBtn2.ResetState(); + break; + } + else + PageIndicatorBtn2.ResetState(); + } else if (PageIndicatorBtn3.GetState() == STATE_CLICKED) { + if (pageToDisplay < 3) { + slidedirection = RIGHT; + pageToDisplay = 3; + PageIndicatorBtn3.ResetState(); + break; + } else + PageIndicatorBtn3.ResetState(); } if (homo.GetState() == STATE_CLICKED) { @@ -1732,7 +1897,7 @@ int MenuSettings() { if (opt_override != opt_overridenew && Settings.titlesOverride==0) { titles_default(); } - + HaltGui(); mainWindow->RemoveAll(); diff --git a/source/settings/cfg.c b/source/settings/cfg.c index 1e24736d..87e4ef79 100644 --- a/source/settings/cfg.c +++ b/source/settings/cfg.c @@ -197,6 +197,7 @@ void CFG_Default(int widescreen) { // -1 = non forced Mode snprintf(Settings.languagefiles_path, sizeof(Settings.languagefiles_path), "%s/config/language/", bootDevice); snprintf(Settings.oggload_path, sizeof(Settings.oggload_path), "%s/config/backgroundmusic/", bootDevice); snprintf(Settings.update_path, sizeof(Settings.update_path), "%s/apps/usbloader_gx/", bootDevice); + snprintf(Settings.theme_downloadpath, sizeof(Settings.theme_downloadpath), "%s/config/themes/", bootDevice); snprintf(Settings.homebrewapps_path, sizeof(Settings.homebrewapps_path), "%s/apps/", bootDevice); snprintf(Settings.Cheatcodespath, sizeof(Settings.Cheatcodespath), "%s/codes/", bootDevice); snprintf(Settings.TxtCheatcodespath, sizeof(Settings.TxtCheatcodespath), "%s/txtcodes/", bootDevice); @@ -217,10 +218,10 @@ void CFG_Default(int widescreen) { // -1 = non forced Mode THEME.gamecarousel_h = 400; THEME.gamecarousel_x = 0; THEME.gamecarousel_y = -20; - + THEME.covers_x = 26; THEME.covers_y = 58; - + THEME.show_id = 1; THEME.id_x = 68; THEME.id_y = 305; @@ -240,7 +241,7 @@ void CFG_Default(int widescreen) { // -1 = non forced Mode THEME.setting_y = 371; THEME.install_x = 16;//-280 THEME.install_y = 355; - + THEME.clock = (GXColor) {138, 138, 138, 240}; THEME.clock_align = CFG_ALIGN_CENTRE; THEME.clock_x = 0; @@ -390,7 +391,7 @@ void title_set(char *id, char *title) { } void titles_default() { - int i; + int i; for (i=0; i +#include + +#include "language/gettext.h" +#include "libwiigui/gui.h" +#include "prompts/PromptWindows.h" +#include "prompts/ProgressWindow.h" +#include "network/networkops.h" +#include "themes/Theme_List.h" +#include "menu.h" +#include "filelist.h" +#include "listfiles.h" +#include "sys.h" +#include "network/http.h" +#include "ZipFile.h" + +/*** Extern functions ***/ +extern void ResumeGui(); +extern void HaltGui(); + +/*** Extern variables ***/ +extern GuiWindow * mainWindow; +extern GuiSound * bgMusic; +extern GuiImage * bgImg; +extern u8 shutdown; +extern u8 reset; + + +bool DownloadTheme(const char *url, const char *title) +{ + if(!url) + return false; + + int filesize = download_request(url); + + if(filesize <= 0) + { + WindowPrompt(tr("Download request failed."), 0, tr("OK")); + return false; + } + + char path[300]; + char filepath[300]; + + snprintf(path, sizeof(path), "%s%s", Settings.theme_downloadpath, title); + + subfoldercreate(path); + + snprintf(filepath, sizeof(filepath), "%s/%s.zip", path, title); + + FILE *file = fopen(filepath, "wb"); + if(!file) + { + WindowPrompt(tr("Download failed."), tr("Can't create file"), tr("OK")); + return false; + } + + u32 done = 0; + + int blocksize = 1024; + + u8 *buffer = (u8*) malloc(blocksize); + + while(done < (u32) filesize) + { + if((u32) blocksize > filesize-done) + blocksize = filesize-done; + + ShowProgress(tr("Downloading file:"), 0, (char*) title, done, filesize, true); + + int ret = network_read(buffer, blocksize); + if(ret < 0) + { + free(buffer); + fclose(file); + remove(path); + ProgressStop(); + WindowPrompt(tr("Download failed."), tr("Transfer failed."), tr("OK")); + return false; + } + + fwrite(buffer, 1, blocksize, file); + + done += ret; + } + + free(buffer); + fclose(file); + + ProgressStop(); + + ZipFile zipfile(filepath); + + bool result = zipfile.ExtractAll(path); + if(result) + { + remove(filepath); + WindowPrompt(tr("Successfully extracted theme."), title, tr("OK")); + } + else + WindowPrompt(tr("Failed to extract."), tr("Unsupported format, try to extract manually."), tr("OK")); + + return result; +} + + +static void Theme_Prompt(const char *title, const char *author, GuiImageData *thumbimageData, const char *downloadlink) +{ + bool leave = false; + + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM, Settings.sfxvolume); + GuiSound btnClick(button_click2_pcm, button_click2_pcm_size, SOUND_PCM, Settings.sfxvolume); + + char imgPath[100]; + snprintf(imgPath, sizeof(imgPath), "%sbutton_dialogue_box.png", CFG.theme_path); + GuiImageData btnOutline(imgPath, button_dialogue_box_png); + snprintf(imgPath, sizeof(imgPath), "%stheme_dialogue_box.png", CFG.theme_path); + GuiImageData dialogBox(imgPath, theme_dialogue_box_png); + + GuiImage dialogBoxImg(&dialogBox); + + GuiWindow promptWindow(dialogBox.GetWidth(),dialogBox.GetHeight()); + promptWindow.SetAlignment(ALIGN_CENTRE, ALIGN_MIDDLE); + promptWindow.SetPosition(0, -10); + + GuiTrigger trigA; + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + GuiTrigger trigB; + trigB.SetButtonOnlyTrigger(-1, WPAD_BUTTON_B | WPAD_CLASSIC_BUTTON_B, PAD_BUTTON_B); + + GuiText titleTxt(tr("Themetitle:"), 18, THEME.prompttext); + titleTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + titleTxt.SetPosition(230, 30); + + GuiText titleTxt2(title, 18, THEME.prompttext); + titleTxt2.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + titleTxt2.SetPosition(230, 50); + titleTxt2.SetMaxWidth(dialogBox.GetWidth()-220, GuiText::WRAP); + + GuiText authorTxt(tr("Author:"), 18, THEME.prompttext); + authorTxt.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + authorTxt.SetPosition(230, 100); + + GuiText authorTxt2(author, 18, THEME.prompttext); + authorTxt2.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + authorTxt2.SetPosition(230, 120); + authorTxt2.SetMaxWidth(dialogBox.GetWidth()-220, GuiText::DOTTED); + + GuiText downloadBtnTxt(tr("Download") , 22, THEME.prompttext); + downloadBtnTxt.SetMaxWidth(btnOutline.GetWidth()-30); + GuiImage downloadBtnImg(&btnOutline); + if (Settings.wsprompt == yes) + { + downloadBtnTxt.SetWidescreen(CFG.widescreen); + downloadBtnImg.SetWidescreen(CFG.widescreen); + } + GuiButton downloadBtn(&downloadBtnImg,&downloadBtnImg, ALIGN_RIGHT, ALIGN_TOP, -5, 170, &trigA, &btnSoundOver, &btnClick,1); + downloadBtn.SetLabel(&downloadBtnTxt); + downloadBtn.SetScale(0.9); + + GuiText backBtnTxt(tr("Back") , 22, THEME.prompttext); + backBtnTxt.SetMaxWidth(btnOutline.GetWidth()-30); + GuiImage backBtnImg(&btnOutline); + if (Settings.wsprompt == yes) + { + backBtnTxt.SetWidescreen(CFG.widescreen); + backBtnImg.SetWidescreen(CFG.widescreen); + } + GuiButton backBtn(&backBtnImg,&backBtnImg, ALIGN_RIGHT, ALIGN_TOP, -5, 220, &trigA, &btnSoundOver, &btnClick,1); + backBtn.SetLabel(&backBtnTxt); + backBtn.SetTrigger(&trigB); + backBtn.SetScale(0.9); + + GuiImage ThemeImage(thumbimageData); + ThemeImage.SetAlignment(ALIGN_LEFT, ALIGN_TOP); + ThemeImage.SetPosition(20, 10); + ThemeImage.SetScale(0.8); + + ThemeImage.SetScale(0.8); + + promptWindow.Append(&dialogBoxImg); + promptWindow.Append(&ThemeImage); + promptWindow.Append(&titleTxt); + promptWindow.Append(&titleTxt2); + promptWindow.Append(&authorTxt); + promptWindow.Append(&authorTxt2); + promptWindow.Append(&downloadBtn); + promptWindow.Append(&backBtn); + + HaltGui(); + promptWindow.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_IN, 50); + mainWindow->SetState(STATE_DISABLED); + mainWindow->Append(&promptWindow); + mainWindow->ChangeFocus(&promptWindow); + ResumeGui(); + + while (!leave) + { + VIDEO_WaitVSync(); + + if (shutdown == 1) + Sys_Shutdown(); + else if (reset == 1) + Sys_Reboot(); + + if (downloadBtn.GetState() == STATE_CLICKED) + { + int choice = WindowPrompt(tr("Do you want to download this theme?"), title, tr("Yes"), tr("Cancel")); + if(choice) + { + DownloadTheme(downloadlink, title); + } + mainWindow->SetState(STATE_DISABLED); + promptWindow.SetState(STATE_DEFAULT); + mainWindow->ChangeFocus(&promptWindow); + downloadBtn.ResetState(); + } + + else if (backBtn.GetState() == STATE_CLICKED) + { + leave = true; + backBtn.ResetState(); + } + } + + promptWindow.SetEffect(EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 50); + while (promptWindow.GetEffect() > 0) usleep(50); + HaltGui(); + mainWindow->Remove(&promptWindow); + mainWindow->SetState(STATE_DEFAULT); + ResumeGui(); +} + + +int Theme_Downloader() +{ + int pagesize = 4; + int menu = MENU_NONE; + bool pagechanged = false; + bool listchanged = false; + + char THEME_LINK[30] = "http://wii.spiffy360.com/"; + + /*** Sound Variables ***/ + GuiSound btnSoundOver(button_over_pcm, button_over_pcm_size, SOUND_PCM, Settings.sfxvolume); + GuiSound btnClick(button_click2_pcm, button_click2_pcm_size, SOUND_PCM, Settings.sfxvolume); + GuiSound btnClick1(button_click_pcm, button_click_pcm_size, SOUND_PCM, Settings.sfxvolume); + + /*** Image Variables ***/ + char imgPath[150]; + snprintf(imgPath, sizeof(imgPath), "%sbutton_dialogue_box.png", CFG.theme_path); + GuiImageData btnOutline(imgPath, button_dialogue_box_png); + + snprintf(imgPath, sizeof(imgPath), "%stheme_box.png", CFG.theme_path); + GuiImageData theme_box_Data(imgPath, theme_box_png); + + snprintf(imgPath, sizeof(imgPath), "%ssettings_background.png", CFG.theme_path); + GuiImageData bgData(imgPath, settings_background_png); + + snprintf(imgPath, sizeof(imgPath), "%sstartgame_arrow_left.png", CFG.theme_path); + GuiImageData arrow_left(imgPath, startgame_arrow_left_png); + + snprintf(imgPath, sizeof(imgPath), "%sstartgame_arrow_right.png", CFG.theme_path); + GuiImageData arrow_right(imgPath, startgame_arrow_right_png); + + snprintf(imgPath, sizeof(imgPath), "%sWifi_btn.png", CFG.theme_path); + GuiImageData wifiImgData(imgPath, Wifi_btn_png); + + snprintf(imgPath, sizeof(imgPath), "%spageindicator.png", CFG.theme_path); + GuiImageData PageindicatorImgData(imgPath, pageindicator_png); + + GuiImage background(&bgData); + + /*** Trigger Variables ***/ + GuiTrigger trigA; + trigA.SetSimpleTrigger(-1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A); + GuiTrigger trigHome; + trigHome.SetButtonOnlyTrigger(-1, WPAD_BUTTON_HOME | WPAD_CLASSIC_BUTTON_HOME, 0); + GuiTrigger trigB; + trigB.SetButtonOnlyTrigger(-1, WPAD_BUTTON_B | WPAD_CLASSIC_BUTTON_B, PAD_BUTTON_B); + GuiTrigger trigL; + trigL.SetButtonOnlyTrigger(-1, WPAD_BUTTON_LEFT | WPAD_CLASSIC_BUTTON_LEFT, PAD_BUTTON_LEFT); + GuiTrigger trigR; + trigR.SetButtonOnlyTrigger(-1, WPAD_BUTTON_RIGHT | WPAD_CLASSIC_BUTTON_RIGHT, PAD_BUTTON_RIGHT); + GuiTrigger trigMinus; + trigMinus.SetButtonOnlyTrigger(-1, WPAD_BUTTON_MINUS | WPAD_CLASSIC_BUTTON_MINUS, 0); + GuiTrigger trigPlus; + trigPlus.SetButtonOnlyTrigger(-1, WPAD_BUTTON_PLUS | WPAD_CLASSIC_BUTTON_PLUS, 0); + + GuiText titleTxt(tr("Theme Downloader"), 28, (GXColor) {0, 0, 0, 255}); + titleTxt.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + titleTxt.SetPosition(0,40); + + GuiImageData *ImageData[pagesize]; + GuiImage *Image[pagesize]; + GuiImage *theme_box_img[pagesize]; + GuiButton *MainButton[pagesize]; + GuiText *MainButtonTxt[pagesize]; + Theme_List *Theme = NULL; + + /*** Buttons ***/ + + for (int i = 0; i < pagesize; i++) + { + ImageData[i] = NULL; + Image[i] = NULL; + MainButtonTxt[i] = NULL; + theme_box_img[i] = new GuiImage(&theme_box_Data); + + MainButton[i] = new GuiButton(theme_box_Data.GetWidth(), theme_box_Data.GetHeight()); + MainButton[i]->SetAlignment(ALIGN_LEFT, ALIGN_TOP); + MainButton[i]->SetSoundOver(&btnSoundOver); + MainButton[i]->SetSoundClick(&btnClick1); + MainButton[i]->SetImage(theme_box_img[i]); + MainButton[i]->SetEffectGrow(); + MainButton[i]->SetTrigger(&trigA); + } + + /*** Positions ***/ + MainButton[0]->SetPosition(90, 75); + MainButton[1]->SetPosition(340, 75); + MainButton[2]->SetPosition(90, 230); + MainButton[3]->SetPosition(340, 230); + + GuiText backBtnTxt(tr("Back") , 22, THEME.prompttext); + backBtnTxt.SetMaxWidth(btnOutline.GetWidth()-30); + GuiImage backBtnImg(&btnOutline); + if (Settings.wsprompt == yes) + { + backBtnTxt.SetWidescreen(CFG.widescreen); + backBtnImg.SetWidescreen(CFG.widescreen); + } + GuiButton backBtn(&backBtnImg,&backBtnImg, 2, 3, -180, 400, &trigA, &btnSoundOver, &btnClick,1); + backBtn.SetLabel(&backBtnTxt); + backBtn.SetTrigger(&trigB); + + GuiButton HomeBtn(1,1); + HomeBtn.SetTrigger(&trigHome); + + GuiImage GoLeftImg(&arrow_left); + GuiButton GoLeftBtn(GoLeftImg.GetWidth(), GoLeftImg.GetHeight()); + GoLeftBtn.SetAlignment(ALIGN_LEFT, ALIGN_MIDDLE); + GoLeftBtn.SetPosition(25, -25); + GoLeftBtn.SetImage(&GoLeftImg); + GoLeftBtn.SetSoundOver(&btnSoundOver); + GoLeftBtn.SetSoundClick(&btnClick); + GoLeftBtn.SetEffectGrow(); + GoLeftBtn.SetTrigger(&trigA); + GoLeftBtn.SetTrigger(&trigL); + GoLeftBtn.SetTrigger(&trigMinus); + + GuiImage GoRightImg(&arrow_right); + GuiButton GoRightBtn(GoRightImg.GetWidth(), GoRightImg.GetHeight()); + GoRightBtn.SetAlignment(ALIGN_RIGHT, ALIGN_MIDDLE); + GoRightBtn.SetPosition(-25, -25); + GoRightBtn.SetImage(&GoRightImg); + GoRightBtn.SetSoundOver(&btnSoundOver); + GoRightBtn.SetSoundClick(&btnClick); + GoRightBtn.SetEffectGrow(); + GoRightBtn.SetTrigger(&trigA); + GoRightBtn.SetTrigger(&trigR); + GoRightBtn.SetTrigger(&trigPlus); + + GuiImage PageindicatorImg(&PageindicatorImgData); + GuiText PageindicatorTxt(NULL, 22, (GXColor) { 0, 0, 0, 255}); + GuiButton PageIndicatorBtn(PageindicatorImg.GetWidth(), PageindicatorImg.GetHeight()); + PageIndicatorBtn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + PageIndicatorBtn.SetPosition(110, 400); + PageIndicatorBtn.SetImage(&PageindicatorImg); + PageIndicatorBtn.SetLabel(&PageindicatorTxt); + PageIndicatorBtn.SetSoundOver(&btnSoundOver); + PageIndicatorBtn.SetSoundClick(&btnClick1); + PageIndicatorBtn.SetTrigger(&trigA); + PageIndicatorBtn.SetEffectGrow(); + + GuiImage Pageindicator2Img(&PageindicatorImgData); + GuiText Pageindicator2Txt(NULL, 22, (GXColor) { 0, 0, 0, 255}); + GuiButton PageIndicator2Btn(Pageindicator2Img.GetWidth(), Pageindicator2Img.GetHeight()); + PageIndicator2Btn.SetAlignment(ALIGN_CENTRE, ALIGN_TOP); + PageIndicator2Btn.SetPosition(150, 400); + PageIndicator2Btn.SetImage(&Pageindicator2Img); + PageIndicator2Btn.SetLabel(&Pageindicator2Txt); + PageIndicator2Btn.SetSoundOver(&btnSoundOver); + PageIndicator2Btn.SetSoundClick(&btnClick1); + PageIndicator2Btn.SetTrigger(&trigA); + PageIndicator2Btn.SetEffectGrow(); + + GuiImage wifiImg(&wifiImgData); + if (Settings.wsprompt == yes) + { + wifiImg.SetWidescreen(CFG.widescreen); + } + GuiButton wifiBtn(wifiImg.GetWidth(), wifiImg.GetHeight()); + wifiBtn.SetImage(&wifiImg); + wifiBtn.SetPosition(500, 400); + wifiBtn.SetSoundOver(&btnSoundOver); + wifiBtn.SetSoundClick(&btnClick1); + wifiBtn.SetEffectGrow(); + wifiBtn.SetTrigger(&trigA); + + GuiWindow w(screenwidth, screenheight); + + HaltGui(); + w.Append(&background); + mainWindow->Append(&w); + ResumeGui(); + + if(!IsNetworkInit()) + NetworkInitPrompt(); + + char url[300]; + int currentpage = 1; + int currenttheme = 0; + int currentloaderpage = 1; + + while(menu == MENU_NONE) + { + HaltGui(); + w.RemoveAll(); + w.Append(&background); + w.Append(&titleTxt); + w.Append(&backBtn); + w.Append(&GoLeftBtn); + w.Append(&GoRightBtn); + w.Append(&PageIndicatorBtn); + w.Append(&PageIndicator2Btn); + w.Append(&wifiBtn); + w.Append(&HomeBtn); + ResumeGui(); + + ShowProgress(tr("Downloading pagelist:"), 0, (char *) "please wait...", 0, pagesize); + + snprintf(url, sizeof(url), "%sthemes.php?creator=&sort=1&page=%i", THEME_LINK, currentpage); + + if(Theme) + { + delete Theme; + Theme = NULL; + } + Theme = new Theme_List(url); + + sprintf(url, "%i", currentpage); + PageindicatorTxt.SetText(url); + + int SitePageCount = Theme->GetSitepageCount(); + int ThemesOnPage = Theme->GetThemeCount(); + + pagechanged = false; + + if(!ThemesOnPage) + { + WindowPrompt(tr("No themes found on the site."), 0, "OK"); + pagechanged = true; + menu = MENU_SETTINGS; + } + + while(!pagechanged) + { + HaltGui(); + w.RemoveAll(); + w.Append(&background); + w.Append(&titleTxt); + w.Append(&backBtn); + w.Append(&GoLeftBtn); + w.Append(&GoRightBtn); + w.Append(&PageIndicatorBtn); + w.Append(&PageIndicator2Btn); + w.Append(&wifiBtn); + w.Append(&HomeBtn); + ResumeGui(); + + sprintf(url, "%i", currentloaderpage); + Pageindicator2Txt.SetText(url); + + int n = 0; + + for(int i = currenttheme; (i < (currenttheme+pagesize)); i++) + { + ShowProgress(tr("Downloading image:"), 0, (char *) Theme->GetThemeTitle(i), n, pagesize); + + if(MainButtonTxt[n]) + delete MainButtonTxt[n]; + if(ImageData[n]) + delete ImageData[n]; + if(Image[n]) + delete Image[n]; + + MainButtonTxt[n] = NULL; + ImageData[n] = NULL; + Image[n] = NULL; + + if(i < ThemesOnPage) + { + MainButtonTxt[n] = new GuiText(Theme->GetThemeTitle(i), 18, (GXColor) { 0, 0, 0, 255}); + MainButtonTxt[n]->SetAlignment(ALIGN_CENTER, ALIGN_TOP); + MainButtonTxt[n]->SetPosition(0, 10); + MainButtonTxt[n]->SetMaxWidth(theme_box_Data.GetWidth()-10, GuiText::DOTTED); + + if(!Theme->IsDirectImageLink(i)) + sprintf(url, "%s%s", THEME_LINK, Theme->GetImageLink(i)); + else + sprintf(url, "%s", Theme->GetImageLink(i)); + + char filepath[300]; + snprintf(filepath, sizeof(filepath), "%s/tmp/%s.png", Settings.theme_downloadpath, Theme->GetThemeTitle(i)); + + FILE * storefile = fopen(filepath, "rb"); + + if(!storefile) + { + struct block file = downloadfile(url); + char storepath[300]; + snprintf(storepath, sizeof(storepath), "%s/tmp/", Settings.theme_downloadpath); + subfoldercreate(storepath); + if(file.data) + { + storefile = fopen(filepath, "wb"); + fwrite(file.data, 1, file.size, storefile); + fclose(storefile); + } + ImageData[n] = new GuiImageData(file.data, file.size); + free(file.data); + } + else + { + fseek(storefile, 0, SEEK_END); + u32 filesize = ftell(storefile); + u8 *buffer = (u8*) malloc(filesize); + rewind(storefile); + fread(buffer, 1, filesize, storefile); + fclose(storefile); + ImageData[n] = new GuiImageData(buffer, filesize); + free(buffer); + buffer = NULL; + } + Image[n] = new GuiImage(ImageData[n]); + Image[n]->SetScale(0.4); + Image[n]->SetPosition(50, -45); + MainButton[n]->SetIcon(Image[n]); + MainButton[n]->SetLabel(MainButtonTxt[n]); + } + n++; + } + + ProgressStop(); + + HaltGui(); + for(int i = 0; i < pagesize; i++) + { + if(MainButtonTxt[i]) + w.Append(MainButton[i]); + } + ResumeGui(); + + listchanged = false; + + while(!listchanged) + { + VIDEO_WaitVSync (); + + if (shutdown == 1) + Sys_Shutdown(); + else if (reset == 1) + Sys_Reboot(); + + else if (wifiBtn.GetState() == STATE_CLICKED) + { + Initialize_Network(); + wifiBtn.ResetState(); + } + else if (backBtn.GetState() == STATE_CLICKED) + { + listchanged = true; + pagechanged = true; + menu = MENU_SETTINGS; + backBtn.ResetState(); + break; + } + else if (GoRightBtn.GetState() == STATE_CLICKED) + { + listchanged = true; + currenttheme += pagesize; + currentloaderpage++; + if(currenttheme >= ThemesOnPage) + { + pagechanged = true; + currentpage++; + if(currentpage > SitePageCount) + currentpage = 1; + + currenttheme = 0; + currentloaderpage = 1; + } + GoRightBtn.ResetState(); + } + else if (GoLeftBtn.GetState() == STATE_CLICKED) + { + listchanged = true; + currenttheme -= pagesize; + currentloaderpage--; + if(currenttheme < 0) + { + pagechanged = true; + currentpage--; + if(currentpage < 1) + currentpage = SitePageCount; + + currenttheme = 0; + currentloaderpage = 1; + } + GoLeftBtn.ResetState(); + } + + for(int i = 0; i < pagesize; i++) + { + if(MainButton[i]->GetState() == STATE_CLICKED) + { + snprintf(url, sizeof(url), "%s%s", THEME_LINK, Theme->GetDownloadLink(currenttheme+i)); + Theme_Prompt(Theme->GetThemeTitle(currenttheme+i), Theme->GetThemeAuthor(currenttheme+i), ImageData[i], url); + MainButton[i]->ResetState(); + } + } + } + } + } + + w.SetEffect(EFFECT_FADE, -20); + + while(w.GetEffect() > 0) usleep(100); + + HaltGui(); + mainWindow->Remove(&w); + + for (int i = 0; i < pagesize; i++) + { + if(MainButton[i]) + delete MainButton[i]; + if(theme_box_img[i]) + delete theme_box_img[i]; + if(ImageData[i]) + delete ImageData[i]; + if(Image[i]) + delete Image[i]; + if(MainButtonTxt[i]) + delete MainButtonTxt[i]; + } + + if(Theme) + delete Theme; + Theme = NULL; + + ResumeGui(); + + return menu; +} diff --git a/source/themes/Theme_Downloader.h b/source/themes/Theme_Downloader.h new file mode 100644 index 00000000..95603755 --- /dev/null +++ b/source/themes/Theme_Downloader.h @@ -0,0 +1,15 @@ +/**************************************************************************** + * Theme_Downloader + * USB Loader GX 2009 + * + * Theme downloader for USB Loader GX + * + * Theme_Downloader.h + ***************************************************************************/ + +#ifndef _THEME_DOWNLOADER_H_ +#define _THEME_DOWNLOADER_H_ + +int Theme_Downloader(); + +#endif diff --git a/source/themes/Theme_List.cpp b/source/themes/Theme_List.cpp new file mode 100644 index 00000000..9d8d97fe --- /dev/null +++ b/source/themes/Theme_List.cpp @@ -0,0 +1,251 @@ +/*************************************************************************** + * Copyright (C) 2009 + * by USB Loader GX Team + * + * 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. + * + * Theme_List Class + * for the USB Loader GX + ***************************************************************************/ +#include +#include +#include +#include + +#include "Theme_List.h" + +#define stringcompare(text, cmp, pos) strncasecmp((const char*) &text[pos-strlen(cmp)], (const char*) cmp, strlen((const char*) cmp)) + +static void copyhtmlsting(const char *from, char *outtext, const char *stopat, u32 &cnt) +{ + u32 cnt2 = 0; + + u32 stringlength = strlen(from); + + while ((stringcompare(from, stopat, cnt+strlen(stopat)) != 0) && (cnt2 < 1024) && (cnt < stringlength)) + { + outtext[cnt2] = from[cnt]; + cnt2++; + cnt++; + } + outtext[cnt2] = '\0'; +} + +Theme_List::Theme_List(const char * url) +{ + Theme = NULL; + themescount = 0; + sitepages = 0; + + if (!IsNetworkInit()) + { + themescount = -1; + return; + } + + struct block file = downloadfile(url); + + if (!file.data || !file.size) + { + themescount = -2; + return; + } + + u32 cnt = 0; + char temp[1024]; + + Theme = (Theme_Info *) malloc(sizeof(Theme_Info)); + if (!Theme) { + free(file.data); + themescount = -3; + return; + } + + memset(&Theme[themescount], 0, sizeof(Theme_Info)); + + while (cnt < file.size) { + + if(stringcompare(file.data, "\"themetitle\">", cnt) == 0) + { + Theme = (Theme_Info *) realloc(Theme, (themescount+1)*sizeof(Theme_Info)); + + if (!Theme) + { + for (int i = 0; i < themescount; i++) + { + if(Theme[i].imagelink) + delete [] Theme[i].imagelink; + if(Theme[i].imagelink) + delete [] Theme[i].downloadlink; + Theme[i].imagelink = NULL; + Theme[i].downloadlink = NULL; + } + free(Theme); + Theme = NULL; + free(file.data); + themescount = -4; + break; + } + + memset(&(Theme[themescount]), 0, sizeof(Theme_Info)); + + copyhtmlsting((const char *) file.data, temp, "By: ", cnt) != 0) + cnt++; + + copyhtmlsting((const char *) file.data, temp, " - <", cnt); + + snprintf(Theme[themescount].author, sizeof(Theme[themescount].author), "%s", temp); + + while(cnt < file.size && stringcompare(file.data, "class=\"image\" src=\"", cnt) != 0) + cnt++; + + copyhtmlsting((const char *) file.data, temp, "\" ", cnt); + + Theme[themescount].imagelink = new char[strlen(temp)+1]; + + snprintf(Theme[themescount].imagelink, strlen(temp)+1, "%s", temp); + + if (strncmp(Theme[themescount].imagelink, "http://", strlen("http://")) != 0) + Theme[themescount].direct[0] = false; + else + Theme[themescount].direct[0] = true; + + while(cnt < file.size && stringcompare(file.data, "href=\"getfile.php", cnt+strlen("getfile.php")) != 0) + cnt++; + + copyhtmlsting((const char *) file.data, temp, "\">", cnt); + + Theme[themescount].downloadlink = new char[strlen(temp)+1]; + + snprintf(Theme[themescount].downloadlink, strlen(temp)+1, "%s", temp); + + if (strncmp(Theme[themescount].downloadlink, "http://", strlen("http://")) != 0) + Theme[themescount].direct[1] = false; + else + Theme[themescount].direct[1] = true; + + themescount++; + } + + if(stringcompare(file.data, "/themes.php?creator=&sort=1&page=", cnt) == 0) + { + copyhtmlsting((const char *) file.data, temp, "class", cnt); + int currentvalue = atoi(temp); + + if(currentvalue > sitepages); + sitepages = currentvalue; + } + + cnt++; + } + + free(file.data); +} + +Theme_List::~Theme_List() +{ + for (int i = 0; i < themescount; i++) + { + if(Theme[i].imagelink) + delete [] Theme[i].imagelink; + if(Theme[i].imagelink) + delete [] Theme[i].downloadlink; + Theme[i].imagelink = NULL; + Theme[i].downloadlink = NULL; + } + + if(Theme) + free(Theme); + Theme = NULL; +} + +const char * Theme_List::GetThemeTitle(int ind) +{ + if (ind > themescount || ind < 0 || !Theme || themescount <= 0) + return NULL; + else + return Theme[ind].themetitle; +} + +const char * Theme_List::GetThemeAuthor(int ind) +{ + if (ind > themescount || ind < 0 || !Theme || themescount <= 0) + return NULL; + else + return Theme[ind].author; +} + +const char * Theme_List::GetImageLink(int ind) +{ + if (ind > themescount || ind < 0 || !Theme || themescount <= 0) + return NULL; + else + return Theme[ind].imagelink; +} + +const char * Theme_List::GetDownloadLink(int ind) +{ + if (ind > themescount || ind < 0 || !Theme || themescount <= 0) + return NULL; + else + return Theme[ind].downloadlink; +} + +int Theme_List::GetThemeCount() +{ + return themescount; +} + +int Theme_List::GetSitepageCount() +{ + return sitepages; +} + +bool Theme_List::IsDirectImageLink(int ind) +{ + if (ind > themescount || ind < 0 || !Theme || themescount <= 0) + return false; + else + return Theme[ind].direct[0]; +} + +bool Theme_List::IsDirectDownloadLink(int ind) +{ + if (ind > themescount || ind < 0 || !Theme || themescount <= 0) + return false; + else + return Theme[ind].direct[1]; +} + +static int ListCompare(const void *a, const void *b) +{ + Theme_Info *ab = (Theme_Info*) a; + Theme_Info *bb = (Theme_Info*) b; + + return stricmp((char *) ab->themetitle, (char *) bb->themetitle); +} +void Theme_List::SortList() +{ + qsort(Theme, themescount, sizeof(Theme_Info), ListCompare); +} diff --git a/source/themes/Theme_List.h b/source/themes/Theme_List.h new file mode 100644 index 00000000..5a9163f6 --- /dev/null +++ b/source/themes/Theme_List.h @@ -0,0 +1,58 @@ +/**************************************************************************** + * Theme_List Class + * for USB Loader GX + * by dimok + ***************************************************************************/ +#ifndef ___THEMELIST_H_ +#define ___THEMELIST_H_ + +#include "network/networkops.h" +#include "network/http.h" + +typedef struct _theme_info +{ + char themetitle[100]; + char author[50]; + char *imagelink; + char *downloadlink; + bool direct[2]; +} Theme_Info; + + +class Theme_List +{ + public: + //!Constructor + //!\param url from where to get the list of links + Theme_List(const char *url); + //!Destructor + ~Theme_List(); + //! Get the a theme title + //!\param list index + const char * GetThemeTitle(int index); + //! Get the author of the theme + //!\param list index + const char * GetThemeAuthor(int index); + //! Get the author of the theme + //!\param list index + const char * GetImageLink(int index); + //! Get the download link of the theme + //!\param list index + const char * GetDownloadLink(int index); + //! Is it a direct URL or just a file or path under the main url + bool IsDirectImageLink(int index); + //! Is it a direct URL or just a file or path under the main url + bool IsDirectDownloadLink(int index); + //! Get the number of links counted + int GetThemeCount(); + //! Get the number of pages counted on which there are Themes + int GetSitepageCount(); + //! Sort list + void SortList(); + protected: + int themescount; + int sitepages; + Theme_Info *Theme; +}; + +#endif