diff --git a/gui.pnproj b/gui.pnproj index dbfecb5d..54df8859 100644 --- a/gui.pnproj +++ b/gui.pnproj @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/source/buffer.cpp b/source/buffer.cpp new file mode 100644 index 00000000..49b9ce12 --- /dev/null +++ b/source/buffer.cpp @@ -0,0 +1,298 @@ +/**************************************************************************** + * USB Loader GX Team + * buffer.cpp + * + * Loading covers in a background thread + ***************************************************************************/ + +#include +#include + +#include "libwiigui/gui.h" +#include "usbloader/disc.h" +#include "settings/cfg.h" +#include "buffer.h" +#include "main.h" + +#define BUFFERSIZE 9 + +extern struct discHdr * gameList; +extern u32 gameCnt; + +static lwp_t bufferthread = LWP_THREAD_NULL; +static bool BufferHalt = true; +static int loading = 0; +static int offset = 0; +static int direction = 1; +static bool changed = false; +static bool firstime = true; + +static GuiImageData NoCoverData(nocover_png); +static GuiImageData * cover[BUFFERSIZE]; +static GuiImage * coverImg[BUFFERSIZE]; +static GuiImage * NoCover[BUFFERSIZE]; + +GuiImage * ImageBuffer(int imagenumber) +{ + if((BUFFERSIZE-1 > imagenumber) && direction >= 0) { + return coverImg[imagenumber]; + } + + if((0 < imagenumber) && direction < 0) { + return coverImg[imagenumber]; + } + + if(loading == BUFFERSIZE) { + return coverImg[imagenumber]; + } + + return NoCover[imagenumber]; +} + +void LoadImages() +{ + if(!changed || BufferHalt) + return; + + char ID[4]; + char IDfull[7]; + char imgPath[200]; + + for(u32 i = offset; (int) i < offset+BUFFERSIZE; i++) { + + struct discHdr *header; + if(i > gameCnt-1) + header = &gameList[i-gameCnt]; + else + header = &gameList[i]; + + snprintf (ID,sizeof(ID),"%c%c%c", header->id[0], header->id[1], header->id[2]); + 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]); + + + snprintf(imgPath, sizeof(imgPath), "%s%s.png", Settings.covers_path, IDfull); //Load full id image + + //firsttime loading images into memory + if(firstime) { + + if(coverImg[loading]) { + delete coverImg[loading]; + coverImg[loading] = NULL; + } + if(cover[loading]) { + delete cover[loading]; + cover[loading] = NULL; + } + + cover[loading] = new GuiImageData(imgPath,0); + if (!cover[loading]->GetImage()) { + delete cover[loading]; + cover[loading] = NULL; + snprintf(imgPath, sizeof(imgPath), "%s%s.png", Settings.covers_path, ID); //Load short id image + cover[loading] = new GuiImageData(imgPath, 0); + if (!cover[loading]->GetImage()) { + delete cover[loading]; + cover[loading] = NULL; + snprintf(imgPath, sizeof(imgPath), "%snoimage.png", Settings.covers_path); //Load no image + cover[loading] = new GuiImageData(imgPath, nocover_png); + } + } + coverImg[loading] = new GuiImage(cover[loading]); + + } else { + + if(direction >= 0) { + + if(loading < BUFFERSIZE-1) { + + if(coverImg[loading]) { + delete coverImg[loading]; + coverImg[loading] = NULL; + } + + if(loading == 0) { + if(cover[loading]) { + delete cover[loading]; + cover[loading] = NULL; + } + cover[loading] = new GuiImageData(NULL, 0); + cover[loading] = cover[loading+1]; + } else { + cover[loading] = cover[loading+1]; + } + + coverImg[loading] = new GuiImage(cover[loading]); + + } else { + + cover[loading] = new GuiImageData(imgPath,0); + if (!cover[loading]->GetImage()) { + delete cover[loading]; + cover[loading] = NULL; + snprintf(imgPath, sizeof(imgPath), "%s%s.png", Settings.covers_path, ID); //Load short id image + cover[loading] = new GuiImageData(imgPath, 0); + if (!cover[loading]->GetImage()) { + delete cover[loading]; + cover[loading] = NULL; + snprintf(imgPath, sizeof(imgPath), "%snoimage.png", Settings.covers_path); //Load no image + cover[loading] = new GuiImageData(imgPath, nocover_png); + } + } + if(coverImg[loading]) { + delete coverImg[loading]; + coverImg[loading] = NULL; + } + coverImg[loading] = new GuiImage(cover[loading]); + } + } else if(direction < 0) { + + if(BUFFERSIZE-loading-1 > 0) { + + if(coverImg[BUFFERSIZE-loading-1]) { + delete coverImg[BUFFERSIZE-loading-1]; + coverImg[BUFFERSIZE-loading-1] = NULL; + } + + if(BUFFERSIZE-loading-1 == BUFFERSIZE-1) { + if(cover[BUFFERSIZE-loading-1]) { + delete cover[BUFFERSIZE-loading-1]; + cover[BUFFERSIZE-loading-1] = NULL; + } + cover[BUFFERSIZE-loading-1] = new GuiImageData(NULL, 0); + cover[BUFFERSIZE-loading-1] = cover[BUFFERSIZE-loading-1-1]; + } else { + cover[BUFFERSIZE-loading-1] = cover[BUFFERSIZE-loading-1-1]; + coverImg[BUFFERSIZE-loading-1] = new GuiImage(cover[BUFFERSIZE-loading-1]); + } + + } else { + + header = &gameList[offset]; + + snprintf (ID,sizeof(ID),"%c%c%c", header->id[0], header->id[1], header->id[2]); + 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]); + + snprintf(imgPath, sizeof(imgPath), "%s%s.png", Settings.covers_path, IDfull); //Load full id image + + cover[0] = new GuiImageData(imgPath,0); + if (!cover[0]->GetImage()) { + delete cover[0]; + cover[0] = NULL; + snprintf(imgPath, sizeof(imgPath), "%s%s.png", Settings.covers_path, ID); //Load short id image + cover[0] = new GuiImageData(imgPath, 0); + if (!cover[0]->GetImage()) { + delete cover[0]; + cover[0] = NULL; + snprintf(imgPath, sizeof(imgPath), "%snoimage.png", Settings.covers_path); //Load no image + cover[0] = new GuiImageData(imgPath, nocover_png); + } + } + if(coverImg[0]) { + delete coverImg[0]; + coverImg[0] = NULL; + } + coverImg[0] = new GuiImage(cover[0]); + } + } + } + loading++; + } + + loading = BUFFERSIZE; + changed = false; + firstime = false; +} + +void NewOffset(int off, int d) +{ + if(offset == off || loading < BUFFERSIZE) + return; + + direction = d; + + offset = off; + + loading = 0; + changed = true; +} + +/**************************************************************************** + * HaltBuffer + ***************************************************************************/ +void HaltBufferThread() +{ + BufferHalt = true; + firstime = true; + changed = true; + loading = 0; + offset = 0; + direction = 0; + + // wait for thread to finish + while(!LWP_ThreadIsSuspended(bufferthread)) + usleep(100); + + for(int i = 0; i < BUFFERSIZE; i++) { + delete cover[i]; + cover[i] = NULL; + delete coverImg[i]; + coverImg[i] = NULL; + delete NoCover[i]; + NoCover[i] = NULL; + } +} + +/**************************************************************************** + * ResumeBufferThread + ***************************************************************************/ +void ResumeBufferThread(int offset) +{ + BufferHalt = false; + firstime = true; + changed = true; + loading = 0; + offset = offset; + direction = 0; + + for(u8 i = 0; i < BUFFERSIZE; i++) { + if(NoCover[i] != NULL) { + delete NoCover[i]; + NoCover[i] = NULL; + } + NoCover[i] = new GuiImage(&NoCoverData); + } + + LWP_ResumeThread(bufferthread); +} + +/********************************************************************************* + * Bufferthread + *********************************************************************************/ +static void * bufferinitcallback(void *arg) +{ + while(1) + { + if(BufferHalt) + LWP_SuspendThread(bufferthread); + + LoadImages(); + } + return NULL; +} + +/**************************************************************************** + * InitBufferThread with priority 50 + ***************************************************************************/ +void InitBufferThread() +{ + LWP_CreateThread(&bufferthread, bufferinitcallback, NULL, NULL, 0, 50); +} + +/**************************************************************************** + * ShutdownThread + ***************************************************************************/ +void ShutdownBufferThread() +{ + LWP_JoinThread (bufferthread, NULL); + bufferthread = LWP_THREAD_NULL; +} diff --git a/source/buffer.h b/source/buffer.h new file mode 100644 index 00000000..ab0af6c5 --- /dev/null +++ b/source/buffer.h @@ -0,0 +1,18 @@ +/**************************************************************************** + * USB Loader GX Team + * buffer.cpp + * + * Loading covers in a background thread + ***************************************************************************/ + +#ifndef BUFFER_H +#define BUFFER_H + +GuiImage * ImageBuffer(int imagenumber); +void NewOffset(int off, int d); +void InitBufferThread(); +void ShutdownBufferThread(); +void ResumeBufferThread(int offset); +void HaltBufferThread(); + +#endif diff --git a/source/libwiigui/cover.cpp b/source/libwiigui/cover.cpp new file mode 100644 index 00000000..5196ce24 --- /dev/null +++ b/source/libwiigui/cover.cpp @@ -0,0 +1,365 @@ +/**************************************************************************** + * Cover Class + * by dimok + ***************************************************************************/ + +#include "cover.h" +/** + * Constructor for the CoverImage class. + */ +CoverImage::CoverImage(const char * imgPath, const u8 * buffer) +{ + image = NULL; + width = 0; + height = 0; + imageangle = 0; + tile = -1; + stripe = 0; + widescreen = 0; + xx1 = 0; + yy1 = 0; + xx2 = 0; + yy2 = 0; + xx3 = 0; + yy3 = 0; + xx4 = 0; + yy4 = 0; + + if(imgPath) + { + PNGUPROP imgProp; + IMGCTX ctx = PNGU_SelectImageFromDevice(imgPath); + + if(ctx) + { + int res = PNGU_GetImageProperties(ctx, &imgProp); + + if(res == PNGU_OK) + { + int len = imgProp.imgWidth * imgProp.imgHeight * 4; + if(len%32) len += (32-len%32); + image = (u8 *)memalign (32, len); + + if(image) + { + res = PNGU_DecodeTo4x4RGBA8 (ctx, imgProp.imgWidth, imgProp.imgHeight, image, 255); + + if(res == PNGU_OK) + { + width = imgProp.imgWidth; + height = imgProp.imgHeight; + DCFlushRange(image, len); + } + else + { + free(image); + image = NULL; + } + } + } + PNGU_ReleaseImageContext (ctx); + } + } + + if (!image) //use buffer data instead + { + width = 0; + height = 0; + if(buffer) + { + PNGUPROP imgProp; + IMGCTX ctx = PNGU_SelectImageFromBuffer(buffer); + + if(!ctx) + return; + + int res = PNGU_GetImageProperties(ctx, &imgProp); + + if(res == PNGU_OK) + { + int len = imgProp.imgWidth * imgProp.imgHeight * 4; + if(len%32) len += (32-len%32); + image = (u8 *)memalign (32, len); + + if(image) + { + res = PNGU_DecodeTo4x4RGBA8 (ctx, imgProp.imgWidth, imgProp.imgHeight, image, 255); + + if(res == PNGU_OK) + { + width = imgProp.imgWidth; + height = imgProp.imgHeight; + DCFlushRange(image, len); + } + else + { + free(image); + image = NULL; + } + } + } + PNGU_ReleaseImageContext (ctx); + } + } + imgType = IMAGE_COPY; +} + +CoverImage::CoverImage(u8 * img, int w, int h) +{ + if((imgType == IMAGE_COLOR || imgType == IMAGE_COPY) && image) { + free(image); + image = NULL; + } + + width = w; + height = h; + int len = width * height * 4; + if(len%32) len += (32-len%32); + image = (u8 *)memalign (32, len); + memcpy(image, img, len); + DCFlushRange(image, len); + imageangle = 0; + tile = -1; + stripe = 0; + widescreen = 0; + xx1 = 0; + yy1 = 0; + xx2 = 0; + yy2 = 0; + xx3 = 0; + yy3 = 0; + xx4 = 0; + yy4 = 0; + imgType = IMAGE_COPY; +} + +CoverImage::CoverImage(GuiImageData * img) +{ + image = img->GetImage(); + width = img->GetWidth(); + height = img->GetHeight(); + imageangle = 0; + tile = -1; + stripe = 0; + widescreen = 0; + xx1 = 0; + yy1 = 0; + xx2 = 0; + yy2 = 0; + xx3 = 0; + yy3 = 0; + xx4 = 0; + yy4 = 0; + imgType = IMAGE_DATA; +} + +CoverImage::CoverImage(CoverImage &srcimage) +{ + if((imgType == IMAGE_COLOR || imgType == IMAGE_COPY) && image) { + free(image); + image = NULL; + } + + width = srcimage.GetWidth(); + height = srcimage.GetHeight(); + int len = width * height * 4; + if(len%32) len += (32-len%32); + image = (u8 *)memalign (32, len); + memcpy(image, srcimage.GetImage(), len); + DCFlushRange(image, len); + imageangle = srcimage.GetAngle(); + tile = -1; + stripe = 0; + widescreen = 0; + xx1 = 0; + yy1 = 0; + xx2 = 0; + yy2 = 0; + xx3 = 0; + yy3 = 0; + xx4 = 0; + yy4 = 0; + imgType = IMAGE_COPY; +} + +CoverImage::CoverImage(CoverImage *srcimage) +{ + if((imgType == IMAGE_COLOR || imgType == IMAGE_COPY) && image) { + free(image); + image = NULL; + } + + width = srcimage->GetWidth(); + height = srcimage->GetHeight(); + int len = width * height * 4; + if(len%32) len += (32-len%32); + image = (u8 *)memalign (32, len); + memcpy(image, srcimage->GetImage(), len); + DCFlushRange(image, len); + imageangle = srcimage->GetAngle(); + tile = -1; + stripe = 0; + widescreen = 0; + xx1 = 0; + yy1 = 0; + xx2 = 0; + yy2 = 0; + xx3 = 0; + yy3 = 0; + xx4 = 0; + yy4 = 0; + imgType = IMAGE_COPY; +} + +CoverImage &CoverImage::operator=(CoverImage &srcimage) +{ + if((imgType == IMAGE_COLOR || imgType == IMAGE_COPY) && image) { + free(image); + image = NULL; + } + + width = srcimage.GetWidth(); + height = srcimage.GetHeight(); + int len = width * height * 4; + if(len%32) len += (32-len%32); + image = (u8 *)memalign (32, len); + memcpy(image, srcimage.GetImage(), len); + DCFlushRange(image, len); + imageangle = srcimage.GetAngle(); + tile = -1; + stripe = 0; + widescreen = 0; + xx1 = 0; + yy1 = 0; + xx2 = 0; + yy2 = 0; + xx3 = 0; + yy3 = 0; + xx4 = 0; + yy4 = 0; + imgType = IMAGE_COPY; + return *this; +} + +/** + * Destructor for the CoverImage class. + */ +CoverImage::~CoverImage() +{ + if((imgType == IMAGE_COLOR || imgType == IMAGE_COPY) && image) { + free(image); + image = NULL; + } +} + +u8 * CoverImage::GetImage() +{ + return image; +} + +void CoverImage::SetAngle(float a) +{ + LOCK(this); + imageangle = a; +} +float CoverImage::GetAngle() +{ + return imageangle; +} + +void CoverImage::SetTile(int t) +{ + LOCK(this); + tile = t; +} + +void CoverImage::SetWidescreen(bool w) +{ + LOCK(this); + widescreen = w; +} + +GXColor CoverImage::GetPixel(int x, int y) +{ + if(!image || this->GetWidth() <= 0 || x < 0 || y < 0) + return (GXColor){0, 0, 0, 0}; + + u32 offset = (((y >> 2)<<4)*this->GetWidth()) + ((x >> 2)<<6) + (((y%4 << 2) + x%4 ) << 1); + GXColor color; + color.a = *(image+offset); + color.r = *(image+offset+1); + color.g = *(image+offset+32); + color.b = *(image+offset+33); + return color; +} + +void CoverImage::SetPixel(int x, int y, GXColor color) +{ + LOCK(this); + if(!image || this->GetWidth() <= 0 || x < 0 || y < 0) + return; + + u32 offset = (((y >> 2)<<4)*this->GetWidth()) + ((x >> 2)<<6) + (((y%4 << 2) + x%4 ) << 1); + *(image+offset) = color.a; + *(image+offset+1) = color.r; + *(image+offset+32) = color.g; + *(image+offset+33) = color.b; +} + + +void CoverImage::SetSkew(int XX1, int YY1,int XX2, int YY2,int XX3, int YY3,int XX4, int YY4) +{ + + xx1 = XX1; + yy1 = YY1; + xx2 = XX2; + yy2 = YY2; + xx3 = XX3; + yy3 = YY3; + xx4 = XX4; + yy4 = YY4; +} + +/** + * Draw the button on screen + */ + +void CoverImage::Draw() +{ + LOCK(this); + if(!image || !this->IsVisible() || tile == 0) + return; + + float currScale = this->GetScale(); + int currLeft = this->GetLeft(); + + float currAngleDyn = this->GetAngleDyn(); + + if(currAngleDyn) + imageangle = currAngleDyn; + + + + if(tile > 0) + { + for(int i=0; iGetTop(), 0, width, height, image, imageangle, widescreen ? currScale*0.80 : currScale, currScale, this->GetAlpha(), xx1,yy1,xx2,yy2,xx3,yy3,xx4,yy4); + } + else + { + // temporary (maybe), used to correct offset for scaled images + if(scale != 1) + currLeft = currLeft - width/2 + (width*scale)/2; + + Menu_DrawImg(currLeft, this->GetTop(), 0, width, height, image, imageangle, widescreen ? currScale*0.80 : currScale, currScale, this->GetAlpha(), xx1,yy1,xx2,yy2,xx3,yy3,xx4,yy4); + } + + if(stripe > 0) + for(int y=0; y < this->GetHeight(); y+=6) + Menu_DrawRectangle(currLeft,this->GetTop()+y,this->GetWidth(),3,(GXColor){0, 0, 0, stripe},1); + + + + + this->UpdateEffects(); +} diff --git a/source/libwiigui/cover.h b/source/libwiigui/cover.h new file mode 100644 index 00000000..1b29e1c5 --- /dev/null +++ b/source/libwiigui/cover.h @@ -0,0 +1,100 @@ +#ifndef COVER_H +#define COVER_H + +#include "gui.h" + +//!Display, manage, and manipulate images in the GUI +class CoverImage : public GuiElement +{ + public: + //!Constructor + CoverImage(const char * imgPath, const u8 * buffer); + //!\overload + //!Sets up a new image from the image data specified + //!\param img + //!\param w Image width + //!\param h Image height + CoverImage(u8 * img, int w, int h); + CoverImage(GuiImageData *img); + //!\overload + //!Creates an image filled with the specified color + //!\param w Image width + //!\param h Image height + //!\param c Image color + CoverImage(int w, int h, GXColor c); + //! Copy Constructor + CoverImage(CoverImage &srcimage); + CoverImage(CoverImage *srcimage); + //! = operator for copying images + CoverImage &operator=(CoverImage &srcimage); + //!Destructor + ~CoverImage(); + //!Sets the image rotation angle for drawing + //!\param a Angle (in degrees) + void SetAngle(float a); + //!Gets the image rotation angle for drawing + float GetAngle(); + //!Sets the number of times to draw the image horizontally + //!\param t Number of times to draw the image + void SetTile(int t); + // true set horizontal scale to 0.8 //added + void SetWidescreen(bool w); + //!Constantly called to draw the image + void Draw(); + //!Gets the image data + //!\return pointer to image data + u8 * GetImage(); + //!Sets up a new image using the CoverImageData object specified + //!\param img Pointer to CoverImageData object + void SetImage(GuiImageData * img); + //!\overload + //!\param img Pointer to image data + //!\param w Width + //!\param h Height + void SetImage(u8 * img, int w, int h); + //!Gets the pixel color at the specified coordinates of the image + //!\param x X coordinate + //!\param y Y coordinate + GXColor GetPixel(int x, int y); + //!Sets the pixel color at the specified coordinates of the image + //!\param x X coordinate + //!\param y Y coordinate + //!\param color Pixel color + void SetPixel(int x, int y, GXColor color); + //!Directly modifies the image data to create a color-striped effect + //!Alters the RGB values by the specified amount + //!\param s Amount to increment/decrement the RGB values in the image + void ColorStripe(int s); + //!Sets a stripe effect on the image, overlaying alpha blended rectangles + //!Does not alter the image data + //!\param s Alpha amount to draw over the image + void SetStripe(int s); + s32 z; + void SetSkew(int XX1, int YY1,int XX2, int YY2,int XX3, int YY3,int XX4, int YY4); + + int xx1; + int yy1; + int xx2; + int yy2; + int xx3; + int yy3; + int xx4; + int yy4; + int rxx1; + int ryy1; + int rxx2; + int ryy2; + int rxx3; + int ryy3; + int rxx4; + int ryy4; + protected: + int imgType; //!< Type of image data (IMAGE_TEXTURE, IMAGE_COLOR, IMAGE_DATA) + u8 * image; //!< Poiner to image data. May be shared with CoverImageData data + f32 imageangle; //!< Angle to draw the image + int tile; //!< Number of times to draw (tile) the image horizontally + int stripe; //!< Alpha value (0-255) to apply a stripe effect to the texture + short widescreen; //added +}; + +#endif diff --git a/source/libwiigui/gui.h b/source/libwiigui/gui.h index f479785f..ba68869c 100644 --- a/source/libwiigui/gui.h +++ b/source/libwiigui/gui.h @@ -84,7 +84,8 @@ enum { IMAGE_TEXTURE, IMAGE_COLOR, - IMAGE_DATA + IMAGE_DATA, + IMAGE_COPY }; enum @@ -593,6 +594,11 @@ class GuiImage : public GuiElement //!\param h Image height //!\param c Image color GuiImage(int w, int h, GXColor c); + //! Copy Constructor + GuiImage(GuiImage &srcimage); + GuiImage(GuiImage *srcimage); + //! = operator for copying images + GuiImage &operator=(GuiImage &srcimage); //!Destructor ~GuiImage(); //!Sets the image rotation angle for drawing @@ -637,7 +643,7 @@ class GuiImage : public GuiElement void SetStripe(int s); s32 z; void SetSkew(int XX1, int YY1,int XX2, int YY2,int XX3, int YY3,int XX4, int YY4); - + int xx1; int yy1; int xx2; @@ -784,12 +790,12 @@ class GuiButton : public GuiElement //!\param vert is verticle alignment of the button //!\param x is xposition of the button //!\param y is yposition of the button - //!\param trig is a GuiTrigger to assign to this button + //!\param trig is a GuiTrigger to assign to this button //!\param sndOver is a GuiSound used for soundOnOver for this button //!\param sndClick is a GuiSound used for clickSound of this button - //!\param grow sets effect grow for this button. 1 for yes ;0 for no + //!\param grow sets effect grow for this button. 1 for yes ;0 for no GuiButton(GuiImage* img, GuiImage* imgOver, int hor, int vert, int x, int y, GuiTrigger* trig, GuiSound* sndOver, GuiSound* sndClick, u8 grow); - //!\param same as all the parameters for the above button plus the following + //!\param same as all the parameters for the above button plus the following //!\param tt is a GuiTooltip assigned to this button //!\param ttx and tty are the xPOS and yPOS for this tooltip in relationship to the button //!\param h_align and v_align are horizontal and verticle alignment for the tooltip in relationship to the button @@ -854,7 +860,7 @@ class GuiButton : public GuiElement //!Sets the button's Tooltip on over //!\param tt Pointer to GuiElement object, x & y Positioning, h & v Align void SetToolTip(GuiElement* tt, int x, int y, int h=ALIGN_RIGHT, int v=ALIGN_TOP); - + void RemoveToolTip(); //!Constantly called to draw the GuiButton void Draw(); diff --git a/source/libwiigui/gui_gamecarousel.cpp b/source/libwiigui/gui_gamecarousel.cpp index 8c86d2fd..42bd8027 100644 --- a/source/libwiigui/gui_gamecarousel.cpp +++ b/source/libwiigui/gui_gamecarousel.cpp @@ -13,6 +13,7 @@ #include "gui_gamecarousel.h" #include "../settings/cfg.h" #include "../main.h" +#include "../buffer.h" #include #include @@ -22,9 +23,9 @@ #define DEG_OFFSET 7 #define RADIUS 780 #define IN_SPEED 175 -#define SHIFT_SPEED 100 -#define SPEED_STEP 4 -#define SAFETY 320 +#define SHIFT_SPEED 75 +#define SPEED_STEP 4 +#define SPEED_LIMIT 250 /** * Constructor for the GuiGameCarousel class. @@ -33,7 +34,7 @@ GuiGameCarousel::GuiGameCarousel(int w, int h, struct discHdr * l, int count, co { width = w; height = h; - gameCnt = (count < SAFETY) ? count : SAFETY; + gameCnt = count; gameList = l; pagesize = (gameCnt < PAGESIZE) ? gameCnt : PAGESIZE; listOffset = (offset == 0) ? this->FindMenuItem(-1, 1) : offset; @@ -92,51 +93,20 @@ GuiGameCarousel::GuiGameCarousel(int w, int h, struct discHdr * l, int count, co btnRight->SetTrigger(trigA); btnRight->SetTrigger(trigR); btnRight->SetTrigger(trigPlus); - btnRight->SetEffectGrow(); + btnRight->SetEffectGrow(); + + ResumeBufferThread(listOffset); gameIndex = new int[pagesize]; game = new GuiButton * [pagesize]; - bob = new int[pagesize]; - coverImg = new GuiImage * [gameCnt]; - cover = new GuiImageData * [gameCnt]; - - for(int i=0; iid[0], header->id[1], header->id[2]); - 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]); - - snprintf(imgPath, sizeof(imgPath), "%s%s.png", Settings.covers_path, IDfull); //Load full id image - cover[i] = new GuiImageData(imgPath,0); - if (!cover[i]->GetImage()) { - delete cover[i]; - snprintf(imgPath, sizeof(imgPath), "%s%s.png", Settings.covers_path, ID); //Load short id image - cover[i] = new GuiImageData(imgPath, 0); - if (!cover[i]->GetImage()) { - delete cover[i]; - snprintf(imgPath, sizeof(imgPath), "%snoimage.png", Settings.covers_path); //Load no image - cover[i] = new GuiImageData(imgPath, nocover_png); - } - } - - coverImg[i] = new GuiImage(cover[i]); - coverImg[i]->SetScale(SCALE); - coverImg[i]->SetWidescreen(CFG.widescreen); - } for(int i=0; i < pagesize; i++) { game[i] = new GuiButton(122,244); game[i]->SetParent(this); game[i]->SetAlignment(ALIGN_CENTRE,ALIGN_MIDDLE); game[i]->SetPosition(0,740); - game[i]->SetImage(coverImg[(listOffset+i) % gameCnt]); + game[i]->SetImage(ImageBuffer((listOffset+i) % gameCnt)); + game[i]->SetScale(SCALE); game[i]->SetRumble(false); game[i]->SetTrigger(trigA); game[i]->SetSoundClick(btnSoundClick); @@ -151,6 +121,7 @@ GuiGameCarousel::GuiGameCarousel(int w, int h, struct discHdr * l, int count, co */ GuiGameCarousel::~GuiGameCarousel() { + HaltBufferThread(); delete imgRight; delete imgLeft; @@ -170,16 +141,9 @@ GuiGameCarousel::~GuiGameCarousel() for(int i=0; iResetState(); if(f == 1) - game[bob[selectedItem]]->SetState(STATE_SELECTED); + game[selectedItem]->SetState(STATE_SELECTED); } @@ -220,12 +184,12 @@ int GuiGameCarousel::GetClickedOption() { int found = -1; if (clickedItem>=0 && clickedItem<=pagesize){ - if (game[bob[(clickedItem+1) % pagesize]]->GetState()==STATE_SELECTED){ + if (game[(clickedItem+1) % pagesize]->GetState()==STATE_SELECTED){ found = (clickedItem+listOffset+1) % gameCnt; - game[bob[(clickedItem+1) % pagesize]]->SetState(STATE_SELECTED); - game[bob[clickedItem]]->SetState(STATE_SELECTED); + game[(clickedItem+1) % pagesize]->SetState(STATE_SELECTED); + game[clickedItem]->SetState(STATE_SELECTED); } else { - game[bob[clickedItem]]->SetState(STATE_SELECTED); + game[clickedItem]->SetState(STATE_SELECTED); found= (clickedItem+listOffset) % gameCnt;} clickedItem=-1; } @@ -237,8 +201,8 @@ int GuiGameCarousel::GetSelectedOption() { int found = -1; for(int i=pagesize-1; i>-1; i--) { - if(game[bob[i]]->GetState() == STATE_SELECTED) { - game[bob[i]]->SetState(STATE_SELECTED); + if(game[i]->GetState() == STATE_SELECTED) { + game[i]->SetState(STATE_SELECTED); found = (listOffset+i) % gameCnt; break; } @@ -282,8 +246,9 @@ void GuiGameCarousel::Draw() int next = listOffset; for(int i=0; i= 0) { - game[bob[i]]->Draw(); + if(next >= 0) { + game[i]->SetImage(ImageBuffer(i)); + game[i]->Draw(); next = this->FindMenuItem(next, 1); } else break; } @@ -291,7 +256,7 @@ void GuiGameCarousel::Draw() if(gameCnt > pagesize) { btnRight->Draw(); btnLeft->Draw(); - } + } this->UpdateEffects(); } @@ -307,45 +272,53 @@ void GuiGameCarousel::Update(GuiTrigger * t) for(int i=0; iSetEffectGrow(); } - } + } + + if(speed > SPEED_LIMIT) + speed = SPEED_LIMIT; btnRight->Update(t); btnLeft->Update(t); + + if(btnRight->GetState() == STATE_CLICKED) + NewOffset(listOffset, -1); + else if(btnLeft->GetState() == STATE_CLICKED) + NewOffset(listOffset, 1); int next = listOffset; for(int i=0; i= 0) { - if(game[bob[i]]->GetState() == STATE_DISABLED) { - game[bob[i]]->SetVisible(true); - game[bob[i]]->SetState(STATE_DEFAULT); + if(game[i]->GetState() == STATE_DISABLED) { + game[i]->SetVisible(true); + game[i]->SetState(STATE_DEFAULT); } gameIndex[i] = next; next = this->FindMenuItem(next, 1); } else { - game[bob[i]]->SetVisible(false); - game[bob[i]]->SetState(STATE_DISABLED); + game[i]->SetVisible(false); + game[i]->SetState(STATE_DISABLED); } if(focus) { - if(i != selectedItem && game[bob[i]]->GetState() == STATE_SELECTED) - game[bob[i]]->ResetState(); - else if(i == selectedItem && game[bob[i]]->GetState() == STATE_DEFAULT); - game[bob[selectedItem]]->SetState(STATE_SELECTED, t->chan); + if(i != selectedItem && game[i]->GetState() == STATE_SELECTED) + game[i]->ResetState(); + else if(i == selectedItem && game[i]->GetState() == STATE_DEFAULT); + game[selectedItem]->SetState(STATE_SELECTED, t->chan); } - game[bob[i]]->Update(t); + game[i]->Update(t); - if(game[bob[i]]->GetState() == STATE_SELECTED) { + if(game[i]->GetState() == STATE_SELECTED) { selectedItem = i; } - if(game[bob[i]]->GetState() == STATE_CLICKED) { + if(game[i]->GetState() == STATE_CLICKED) { clickedItem = i; } } // navigation - if(!focus || gameCnt <= pagesize || (game[bob[0]]->GetEffect() && game[bob[pagesize-1]]->GetEffect())) + if(!focus || gameCnt <= pagesize || (game[0]->GetEffect() && game[pagesize-1]->GetEffect())) return; // skip navigation if (((btnLeft->GetState() == STATE_CLICKED) &&(Settings.xflip!=sysmenu)&&(Settings.xflip!=yes)) @@ -367,25 +340,17 @@ void GuiGameCarousel::Update(GuiTrigger * t) listOffset = (listOffset+1 < gameCnt) ? listOffset+1 : 0; firstPic = (firstPic+1 < pagesize) ? firstPic+1 : 0; - for (int i=0; iSetImage(coverImg[(listOffset + pagesize-1) % gameCnt]); - game[bob[pagesize-1]]->SetPosition(0, RADIUS); + game[pagesize-1]->SetPosition(0, RADIUS); for (int i=0; iSetEffect(EFFECT_GOROUND, -speed, DEG_OFFSET, RADIUS, 270-(pagesize-2*i-3)*DEG_OFFSET/2, 1, 0, RADIUS); - - + game[i]->SetEffect(EFFECT_GOROUND, -speed, DEG_OFFSET, RADIUS, 270-(pagesize-2*i-3)*DEG_OFFSET/2, 1, 0, RADIUS); } speed+=SPEED_STEP; } - else if (((btnRight->GetState() == STATE_CLICKED) &&(Settings.xflip!=sysmenu)&&(Settings.xflip!=yes)) - ||((btnLeft->GetState() == STATE_CLICKED) &&((Settings.xflip==sysmenu)||(Settings.xflip==yes)))){ + ||((btnLeft->GetState() == STATE_CLICKED) &&((Settings.xflip==sysmenu)||(Settings.xflip==yes)))){ u16 buttons = ButtonsHold(); if(!((buttons & WPAD_BUTTON_A) || (buttons & WPAD_BUTTON_MINUS) || t->Left() || @@ -402,15 +367,10 @@ void GuiGameCarousel::Update(GuiTrigger * t) listOffset = (listOffset-1 < 0) ? gameCnt-1 : listOffset-1; firstPic = (firstPic-1 < 0) ? pagesize-1 : firstPic-1; - for(int i=0; iSetImage(coverImg[listOffset]); - game[bob[0]]->SetPosition(0, RADIUS); + game[0]->SetPosition(0, RADIUS); for(int i=0; iSetEffect(EFFECT_GOROUND, speed, DEG_OFFSET, RADIUS, 270-(pagesize-2*i+1)*DEG_OFFSET/2, 1, 0, RADIUS); + game[i]->SetEffect(EFFECT_GOROUND, speed, DEG_OFFSET, RADIUS, 270-(pagesize-2*i+1)*DEG_OFFSET/2, 1, 0, RADIUS); } speed+=SPEED_STEP; } @@ -420,83 +380,3 @@ void GuiGameCarousel::Update(GuiTrigger * t) } -void GuiGameCarousel::Reload(struct discHdr * l, int count) -{ - for(int i=0; iFindMenuItem(-1, 1); - selectedItem = listOffset; - focus = 1; - firstPic = 0; - clickedItem = -1; - speed = SHIFT_SPEED; - - gameIndex = new int[pagesize]; - game = new GuiButton * [pagesize]; - bob = new int[pagesize]; - coverImg = new GuiImage * [gameCnt]; - cover = new GuiImageData * [gameCnt]; - - for(int i=0; iid[0], header->id[1], header->id[2]); - 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]); - - snprintf(imgPath, sizeof(imgPath), "%s%s.png", Settings.covers_path, IDfull); //Load full id image - cover[i] = new GuiImageData(imgPath,0); - if (!cover[i]->GetImage()) { - delete cover[i]; - snprintf(imgPath, sizeof(imgPath), "%s%s.png", Settings.covers_path, ID); //Load short id image - cover[i] = new GuiImageData(imgPath, 0); - if (!cover[i]->GetImage()) { - delete cover[i]; - snprintf(imgPath, sizeof(imgPath), "%snoimage.png", Settings.covers_path); //Load no image - cover[i] = new GuiImageData(imgPath, nocover_png); - } - } - - coverImg[i] = new GuiImage(cover[i]); - coverImg[i]->SetScale(SCALE); - coverImg[i]->SetWidescreen(CFG.widescreen); - } - - for(int i=0; i < pagesize; i++) { - game[i] = new GuiButton(122,244); - game[i]->SetParent(this); - game[i]->SetAlignment(ALIGN_CENTRE,ALIGN_MIDDLE); - game[i]->SetPosition(0,740); - game[i]->SetImage(coverImg[i]); - game[i]->SetRumble(false); - game[i]->SetTrigger(trigA); - game[i]->SetSoundClick(btnSoundClick); - game[i]->SetClickable(true); - game[i]->SetEffect(EFFECT_GOROUND, IN_SPEED, 90-(pagesize-2*i-1)*DEG_OFFSET/2, RADIUS, 180, 1, 0, RADIUS); - } -} - diff --git a/source/libwiigui/gui_gamecarousel.h b/source/libwiigui/gui_gamecarousel.h index 06c9aa49..333a57ed 100644 --- a/source/libwiigui/gui_gamecarousel.h +++ b/source/libwiigui/gui_gamecarousel.h @@ -32,13 +32,9 @@ class GuiGameCarousel : public GuiElement int gameCnt; int * gameIndex; - int * bob; GuiButton ** game; - GuiImage ** coverImg; - GuiImageData ** cover; - GuiButton * btnRight; GuiButton * btnLeft; diff --git a/source/libwiigui/gui_image.cpp b/source/libwiigui/gui_image.cpp index c64c25fe..e3854219 100644 --- a/source/libwiigui/gui_image.cpp +++ b/source/libwiigui/gui_image.cpp @@ -54,10 +54,10 @@ GuiImage::GuiImage(GuiImageData * img) GuiImage::GuiImage(u8 * img, int w, int h) { - image = img; + image = img; width = w; height = h; - imageangle = 0; + imageangle = 0; tile = -1; stripe = 0; widescreen = 0; @@ -108,13 +108,103 @@ GuiImage::GuiImage(int w, int h, GXColor c) DCFlushRange(image, len); } +GuiImage::GuiImage(GuiImage &srcimage) +{ + if((imgType == IMAGE_COLOR || imgType == IMAGE_COPY) && image) { + free(image); + image = NULL; + } + + width = srcimage.GetWidth(); + height = srcimage.GetHeight(); + int len = width * height * 4; + if(len%32) len += (32-len%32); + image = (u8 *)memalign (32, len); + memcpy(image, srcimage.GetImage(), len); + DCFlushRange(image, len); + imageangle = srcimage.GetAngle(); + tile = -1; + stripe = 0; + widescreen = 0; + xx1 = 0; + yy1 = 0; + xx2 = 0; + yy2 = 0; + xx3 = 0; + yy3 = 0; + xx4 = 0; + yy4 = 0; + imgType = IMAGE_COPY; +} + +GuiImage::GuiImage(GuiImage *srcimage) +{ + if((imgType == IMAGE_COLOR || imgType == IMAGE_COPY) && image) { + free(image); + image = NULL; + } + + width = srcimage->GetWidth(); + height = srcimage->GetHeight(); + int len = width * height * 4; + if(len%32) len += (32-len%32); + image = (u8 *)memalign (32, len); + memcpy(image, srcimage->GetImage(), len); + DCFlushRange(image, len); + imageangle = srcimage->GetAngle(); + tile = -1; + stripe = 0; + widescreen = 0; + xx1 = 0; + yy1 = 0; + xx2 = 0; + yy2 = 0; + xx3 = 0; + yy3 = 0; + xx4 = 0; + yy4 = 0; + imgType = IMAGE_COPY; +} + +GuiImage &GuiImage::operator=(GuiImage &srcimage) +{ + if((imgType == IMAGE_COLOR || imgType == IMAGE_COPY) && image) { + free(image); + image = NULL; + } + + width = srcimage.GetWidth(); + height = srcimage.GetHeight(); + int len = width * height * 4; + if(len%32) len += (32-len%32); + image = (u8 *)memalign (32, len); + memcpy(image, srcimage.GetImage(), len); + DCFlushRange(image, len); + imageangle = srcimage.GetAngle(); + tile = -1; + stripe = 0; + widescreen = 0; + xx1 = 0; + yy1 = 0; + xx2 = 0; + yy2 = 0; + xx3 = 0; + yy3 = 0; + xx4 = 0; + yy4 = 0; + imgType = IMAGE_COPY; + return *this; +} + /** * Destructor for the GuiImage class. */ GuiImage::~GuiImage() { - if(imgType == IMAGE_COLOR && image) + if((imgType == IMAGE_COLOR || imgType == IMAGE_COPY) && image) { free(image); + image = NULL; + } } u8 * GuiImage::GetImage() @@ -125,8 +215,11 @@ u8 * GuiImage::GetImage() void GuiImage::SetImage(GuiImageData * img) { LOCK(this); - if(imgType == IMAGE_COLOR && image) + if((imgType == IMAGE_COLOR || imgType == IMAGE_COPY) && image) { free(image); + image = NULL; + } + image = img->GetImage(); width = img->GetWidth(); height = img->GetHeight(); @@ -136,8 +229,10 @@ void GuiImage::SetImage(GuiImageData * img) void GuiImage::SetImage(u8 * img, int w, int h) { LOCK(this); - if(imgType == IMAGE_COLOR && image) + if((imgType == IMAGE_COLOR || imgType == IMAGE_COPY) && image) { free(image); + image = NULL; + } image = img; width = w; height = h; @@ -200,8 +295,8 @@ void GuiImage::SetStripe(int s) } void GuiImage::SetSkew(int XX1, int YY1,int XX2, int YY2,int XX3, int YY3,int XX4, int YY4) -{ - +{ + xx1 = XX1; yy1 = YY1; xx2 = XX2; @@ -286,7 +381,7 @@ void GuiImage::Draw() if(currAngleDyn) imageangle = currAngleDyn; - + if(tile > 0) @@ -308,7 +403,7 @@ void GuiImage::Draw() Menu_DrawRectangle(currLeft,this->GetTop()+y,this->GetWidth(),3,(GXColor){0, 0, 0, stripe},1); - + this->UpdateEffects(); } diff --git a/source/libwiigui/gui_imagedata.cpp b/source/libwiigui/gui_imagedata.cpp index 5034d9a9..6cc53b88 100644 --- a/source/libwiigui/gui_imagedata.cpp +++ b/source/libwiigui/gui_imagedata.cpp @@ -13,7 +13,7 @@ /** * Constructor for the GuiImageData class. */ - + extern int idiotFlag; extern char idiotChar[50]; GuiImageData::GuiImageData(const u8 * img) @@ -34,7 +34,7 @@ GuiImageData::GuiImageData(const u8 * img) //if (((4%imgProp.imgWidth)!=0)||((4%imgProp.imgHeight)!=0))idiotFlag=1; if(res == PNGU_OK) - { + { int len = imgProp.imgWidth * imgProp.imgHeight * 4; if(len%32) len += (32-len%32); data = (u8 *)memalign (32, len); @@ -55,7 +55,7 @@ GuiImageData::GuiImageData(const u8 * img) data = NULL; idiotFlag=1; snprintf(idiotChar, sizeof(idiotChar), "%s", img); - + } } } @@ -110,7 +110,7 @@ GuiImageData::GuiImageData(const char * imgPath, const u8 * buffer) PNGU_ReleaseImageContext (ctx); } } - + if (!data) //use buffer data instead { width = 0; diff --git a/source/menu.cpp b/source/menu.cpp index 2c21975b..7c08ae9d 100644 --- a/source/menu.cpp +++ b/source/menu.cpp @@ -38,6 +38,7 @@ #include "wpad.h" #include "listfiles.h" #include "fatmounter.h" +#include "buffer.h" #include "usbloader/wdvd.h" @@ -196,6 +197,7 @@ void InitGUIThreads() { LWP_CreateThread(&guithread, UpdateGUI, NULL, NULL, 0, 70); InitProgressThread(); + InitBufferThread(); } void ExitGUIThreads() @@ -223,8 +225,8 @@ int MenuDiscList() char ID[4]; char IDfull[7]; u32 covert = 0; - - + + WDVD_GetCoverStatus(&covert); u32 covertOld=covert; @@ -622,9 +624,9 @@ int MenuDiscList() WindowPrompt(0,idiotBuffer,tr("Ok")); idiotFlag=-1;} - + WDVD_GetCoverStatus(&covert);//for detecting if i disc has been inserted - + // if the idiot is showing favoorites and don't have any if (Settings.fave && !gameCnt){ WindowPrompt(tr("No Favorites"),tr("You are choosing to display favorites and you do not have any selected."),tr("Back")); @@ -741,7 +743,7 @@ int MenuDiscList() else if (Settings.gameDisplay==carousel){gameCarousel->SetFocus(1);} } } - + diff --git a/source/usbloader/alternatedol.h b/source/usbloader/alternatedol.h index 01bca693..816cb8c7 100644 --- a/source/usbloader/alternatedol.h +++ b/source/usbloader/alternatedol.h @@ -11,7 +11,6 @@ extern "C" bool Load_Dol(void **buffer, int* dollen, char * path); bool Remove_001_Protection(void *Address, int Size); u32 load_dol_image(void * dolstart); -char hiddenfix[1000][1000]; // temporary fix for alternative dol not working for some people #ifdef __cplusplus } #endif