From ed2ac8f0858e51a56594c06701dbdf1b5dd5e445 Mon Sep 17 00:00:00 2001 From: dimok321 <15055714+dimok789@users.noreply.github.com> Date: Wed, 21 Oct 2009 19:32:46 +0000 Subject: [PATCH] *Created a Theme Downloader with preview, downloading themes from http://wii.spiffy360.com/ (Thanks for hosting them) NOTE: The images used right now for the theme loader are made out of our old images and if someone can make some new ones go ahead. The themes are downloaded to the path you can set up. The downloaded preview images are cached at "/tmp/". The widescreenfix isn't implemented there yet because images will probably be changed. *Started 3rd SettingsPage *Added JPEG Loading GuiImageData function and 4x4RGBA converter by r-win from WiiXplorer *Added ZipFile Class from WiiXplorer *Added StringToMD5 and MD5ToString to MD5 functions and made it undependable of platform --- Makefile | 4 +- source/ZipFile.cpp | 140 ++++++ source/ZipFile.h | 58 +++ source/banner/MD5.c | 53 ++- source/banner/MD5.h | 12 +- source/filelist.h | 6 + source/images/theme_box.png | Bin 0 -> 7813 bytes source/images/theme_dialogue_box.png | Bin 0 -> 6659 bytes source/libwiigui/gui.h | 5 + source/libwiigui/gui_imagedata.cpp | 137 +++++- source/menu.cpp | 86 ++-- source/menu.h | 3 +- source/network/http.c | 8 +- source/network/networkops.cpp | 6 +- source/settings/Settings.cpp | 185 +++++++- source/settings/cfg.c | 36 +- source/settings/cfg.h | 9 +- source/themes/Theme_Downloader.cpp | 663 +++++++++++++++++++++++++++ source/themes/Theme_Downloader.h | 15 + source/themes/Theme_List.cpp | 251 ++++++++++ source/themes/Theme_List.h | 58 +++ 21 files changed, 1643 insertions(+), 92 deletions(-) create mode 100644 source/ZipFile.cpp create mode 100644 source/ZipFile.h create mode 100644 source/images/theme_box.png create mode 100644 source/images/theme_dialogue_box.png create mode 100644 source/themes/Theme_Downloader.cpp create mode 100644 source/themes/Theme_Downloader.h create mode 100644 source/themes/Theme_List.cpp create mode 100644 source/themes/Theme_List.h 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 0000000000000000000000000000000000000000..174b7b52a1d0c66423aeb4ec06e646855efb3b44 GIT binary patch literal 7813 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 RwgUKLZNA6swh1-%-vF{DzI6Zq literal 0 HcmV?d00001 diff --git a/source/images/theme_dialogue_box.png b/source/images/theme_dialogue_box.png new file mode 100644 index 0000000000000000000000000000000000000000..389cfa1d634f66d8fd25e4c577c33193fe01803d GIT binary patch literal 6659 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

n8RwKbyP0=_!7n zk;cfqI_xE3z}+o<9vFYG?o$SnpQH{H?U}rPUA42`W;wX~5nQ!%k^$dCJ+^25^W8$N zE&xCPqihMDZ-5hV`$&JNN^Upp%cOv9Yn!tBjzTO0$N$(oxa>Jtw>bo#lGur_EpZ1XA0v*Q+o-+)eB8$7`TDEQ!0wXmqJDbT j_K)`}jCRv%mvx&g#3R@g`iSvz2XMu}LcjF#%?JMjcO!%s literal 0 HcmV?d00001 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