use less memory for snapshot screenshots - so now thumbs are activated for GameCube

This commit is contained in:
dborth 2010-06-03 23:15:34 +00:00
parent 2ffdd76b7c
commit 118ca267c5
10 changed files with 89 additions and 78 deletions

View File

@ -43,35 +43,19 @@ void S9xCloseSnapshotFile(STREAM s)
int
SaveSnapshot (char * filepath, bool silent)
{
int imgSize = 0; // image screenshot bytes written
int device;
if(!FindDevice(filepath, &device))
return 0;
// save screenshot - I would prefer to do this from gameScreenTex
if(gameScreenTex2 != NULL)
{
AllocSaveBuffer ();
IMGCTX pngContext = PNGU_SelectImageFromBuffer(savebuffer);
if (pngContext != NULL)
{
imgSize = PNGU_EncodeFromGXTexture(pngContext, vmode->fbWidth, vmode->efbHeight, gameScreenTex2, 0);
PNGU_ReleaseImageContext(pngContext);
}
if(imgSize > 0)
// save screenshot
if(gameScreenPngSize > 0)
{
char screenpath[1024];
strncpy(screenpath, filepath, 1024);
screenpath[strlen(screenpath)-4] = 0;
sprintf(screenpath, "%s.png", screenpath);
SaveFile(screenpath, imgSize, silent);
}
FreeSaveBuffer ();
SaveFile((char *)gameScreenPng, screenpath, gameScreenPngSize, silent);
}
STREAM fp = OPEN_STREAM(filepath, "wb");

View File

@ -538,7 +538,9 @@ class GuiImageData
//!Constructor
//!Converts the image data to RGBA8 - expects PNG format
//!\param i Image data
GuiImageData(const u8 * i);
//!\param w Max image width (0 = not set)
//!\param h Max image height (0 = not set)
GuiImageData(const u8 * i, int w=0, int h=0);
//!Destructor
~GuiImageData();
//!Gets a pointer to the image data

View File

@ -13,14 +13,14 @@
/**
* Constructor for the GuiImageData class.
*/
GuiImageData::GuiImageData(const u8 * i)
GuiImageData::GuiImageData(const u8 * i, int maxw, int maxh)
{
data = NULL;
width = 0;
height = 0;
if(i)
data = DecodePNG(i, &width, &height);
data = DecodePNG(i, &width, &height, maxw, maxh);
}
/**

View File

@ -327,8 +327,6 @@ void GuiSaveBrowser::Update(GuiTrigger * t)
saveType[1]->SetText("Snapshot");
savePreviewImg[0]->SetImage(gameSaveBlank);
savePreviewImg[1]->SetImage(gameSaveBlank);
savePreviewImg[0]->SetScale(1);
savePreviewImg[1]->SetScale(1);
saveBtn[0]->SetVisible(true);
saveBtn[1]->SetVisible(true);
@ -367,16 +365,9 @@ void GuiSaveBrowser::Update(GuiTrigger * t)
saveType[i]->SetText(savetext);
if(saves->previewImg[listOffset+i] != NULL)
{
savePreviewImg[i]->SetImage(saves->previewImg[listOffset+i]);
savePreviewImg[i]->SetScale(0.1);
}
else
{
savePreviewImg[i]->SetImage(gameSaveBlank);
savePreviewImg[i]->SetScale(1);
}
}
else
{

View File

@ -1444,6 +1444,7 @@ static int MenuGame()
{
free(gameScreenTex);
gameScreenTex = NULL;
gameScreenPngSize = 0;
}
bgImg->SetVisible(true);
#ifndef NO_SOUND
@ -1645,7 +1646,7 @@ static int MenuGameSaves(int action)
memset(savebuffer, 0, SAVEBUFFERSIZE);
if(LoadFile(scrfile, SILENT))
saves.previewImg[j] = new GuiImageData(savebuffer);
saves.previewImg[j] = new GuiImageData(savebuffer, 64, 48);
}
snprintf(filepath, 1024, "%s%s/%s", pathPrefix[GCSettings.SaveMethod], GCSettings.SaveFolder, saves.filename[j]);
if (stat(filepath, &filestat) == 0)
@ -3769,6 +3770,15 @@ MainMenu (int menu)
if(gameScreenTex)
{
IMGCTX pngContext = PNGU_SelectImageFromBuffer(gameScreenPng);
if (pngContext != NULL)
{
gameScreenPngSize = PNGU_EncodeFromGXTexture(pngContext, vmode->fbWidth, vmode->efbHeight, gameScreenTex, 0);
PNGU_ReleaseImageContext(pngContext);
DCFlushRange(gameScreenPng, 50*1024);
}
gameScreenImg = new GuiImage(gameScreenTex, vmode->fbWidth, vmode->efbHeight);
gameScreenImg->SetAlpha(192);
gameScreenImg->ColorStripe(30);
@ -3915,11 +3925,7 @@ MainMenu (int menu)
{
free(gameScreenTex);
gameScreenTex = NULL;
}
if(gameScreenTex2)
{
free(gameScreenTex2);
gameScreenTex2 = NULL;
gameScreenPngSize = 0;
}
// wait for keys to be depressed

View File

@ -456,6 +456,8 @@ main(int argc, char *argv[])
// Initialize font system
InitFreeType((u8*)font_ttf, font_ttf_size);
gameScreenPng = (u8 *)malloc(50*1024);
InitGUIThreads();
emulate(); // main loop

View File

@ -374,34 +374,56 @@ static inline PNGU_u32 coordsRGBA8(PNGU_u32 x, PNGU_u32 y, PNGU_u32 w)
return ((((y >> 2) * (w >> 2) + (x >> 2)) << 5) + ((y & 3) << 2) + (x & 3)) << 1;
}
static PNGU_u8 * PNGU_DecodeTo4x4RGBA8 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, PNGU_u8 default_alpha)
static u8 * PNGU_DecodeTo4x4RGBA8 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, int * dstWidth, int * dstHeight, int maxWidth, int maxHeight)
{
PNGU_u8 *dst;
PNGU_u32 x, y, offset;
PNGU_u8 default_alpha = 255;
u8 *dst;
int x, y, x2, y2, offset;
int xRatio = 0, yRatio = 0;
png_byte *pixel;
if (pngu_decode (ctx, width, height, 0) != PNGU_OK)
return NULL;
PNGU_u32 newWidth = width;
if(newWidth%4) newWidth += (4-newWidth%4);
PNGU_u32 newHeight = height;
if(newHeight%4) newHeight += (4-newHeight%4);
int newWidth = width;
int newHeight = height;
int len = (newWidth * newHeight) << 2;
if((maxWidth > 0 && width > maxWidth) || (maxHeight > 0 && height > maxHeight))
{
float ratio = (float)width/(float)height;
newWidth = maxWidth;
newHeight = maxWidth/ratio;
if(newHeight > maxHeight)
{
newWidth = maxHeight*ratio;
newHeight = maxHeight;
}
xRatio = (int)((width<<16)/newWidth)+1;
yRatio = (int)((height<<16)/newHeight)+1;
}
int padWidth = newWidth;
int padHeight = newHeight;
if(padWidth%4) padWidth += (4-padWidth%4);
if(padHeight%4) padHeight += (4-padHeight%4);
int len = (padWidth * padHeight) << 2;
if(len%32) len += (32-len%32);
dst = memalign (32, len);
if(!dst)
return NULL;
for (y = 0; y < newHeight; y++)
for (y = 0; y < padHeight; y++)
{
for (x = 0; x < newWidth; x++)
for (x = 0; x < padWidth; x++)
{
offset = coordsRGBA8(x, y, newWidth);
offset = coordsRGBA8(x, y, padWidth);
if(y >= height || x >= width)
if(y >= newHeight || x >= newWidth)
{
dst[offset] = 0;
dst[offset+1] = 255;
@ -410,10 +432,20 @@ static PNGU_u8 * PNGU_DecodeTo4x4RGBA8 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 hei
}
else
{
if(xRatio > 0)
{
x2 = ((x*xRatio)>>16);
y2 = ((y*yRatio)>>16);
}
if (ctx->prop.imgColorType == PNGU_COLOR_TYPE_GRAY_ALPHA ||
ctx->prop.imgColorType == PNGU_COLOR_TYPE_RGB_ALPHA)
{
if(xRatio > 0)
pixel = &(ctx->row_pointers[y2][x2*4]);
else
pixel = &(ctx->row_pointers[y][x*4]);
dst[offset] = pixel[3]; // Alpha
dst[offset+1] = pixel[0]; // Red
dst[offset+32] = pixel[1]; // Green
@ -421,7 +453,11 @@ static PNGU_u8 * PNGU_DecodeTo4x4RGBA8 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 hei
}
else
{
if(xRatio > 0)
pixel = &(ctx->row_pointers[y2][x2*3]);
else
pixel = &(ctx->row_pointers[y][x*3]);
dst[offset] = default_alpha; // Alpha
dst[offset+1] = pixel[0]; // Red
dst[offset+32] = pixel[1]; // Green
@ -435,6 +471,8 @@ static PNGU_u8 * PNGU_DecodeTo4x4RGBA8 (IMGCTX ctx, PNGU_u32 width, PNGU_u32 hei
free (ctx->img_data);
free (ctx->row_pointers);
*dstWidth = padWidth;
*dstHeight = padHeight;
DCFlushRange(dst, len);
return dst;
}
@ -519,22 +557,17 @@ int PNGU_GetImageProperties (IMGCTX ctx, PNGUPROP *imgprop)
return PNGU_OK;
}
PNGU_u8 * DecodePNG(const PNGU_u8 *src, int * width, int * height)
PNGU_u8 * DecodePNG(const PNGU_u8 *src, int * width, int * height, int maxwidth, int maxheight)
{
PNGUPROP imgProp;
IMGCTX ctx = PNGU_SelectImageFromBuffer(src);
PNGU_u8 *dst = NULL;
u8 *dst = NULL;
if(!ctx)
return NULL;
if(PNGU_GetImageProperties(ctx, &imgProp) == PNGU_OK)
{
dst = PNGU_DecodeTo4x4RGBA8 (ctx, imgProp.imgWidth, imgProp.imgHeight, 255);
*width = imgProp.imgWidth;
*height = imgProp.imgHeight;
}
dst = PNGU_DecodeTo4x4RGBA8 (ctx, imgProp.imgWidth, imgProp.imgHeight, width, height, maxwidth, maxheight);
PNGU_ReleaseImageContext (ctx);
return dst;

View File

@ -67,7 +67,7 @@ int PNGU_GetImageProperties (IMGCTX ctx, PNGUPROP *fileproperties);
* Image conversion *
****************************************************************************/
PNGU_u8 * DecodePNG(const PNGU_u8 *src, int *width, int *height);
PNGU_u8 * DecodePNG(const PNGU_u8 *src, int *width, int *height, int maxwidth, int maxheight);
int PNGU_EncodeFromRGB (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride);
int PNGU_EncodeFromGXTexture (IMGCTX ctx, PNGU_u32 width, PNGU_u32 height, void *buffer, PNGU_u32 stride);

View File

@ -61,7 +61,8 @@ static Mtx GXmodelView2D;
static int vwidth, vheight, oldvwidth, oldvheight;
u8 * gameScreenTex = NULL; // a GX texture screen capture of the game
u8 * gameScreenTex2 = NULL; // a GX texture screen capture of the game (copy)
u8 * gameScreenPng = NULL;
int gameScreenPngSize = 0;
u32 FrameTimer = 0;
@ -890,15 +891,6 @@ void TakeScreenshot()
GX_CopyTex(gameScreenTex, GX_FALSE);
GX_PixModeSync();
DCFlushRange(gameScreenTex, texSize);
#ifdef HW_RVL
if(gameScreenTex2) free(gameScreenTex2);
gameScreenTex2 = (u8 *)memalign(32, texSize);
if(gameScreenTex2 == NULL) return;
GX_CopyTex(gameScreenTex2, GX_FALSE);
GX_PixModeSync();
DCFlushRange(gameScreenTex2, texSize);
#endif
}
/****************************************************************************

View File

@ -35,7 +35,8 @@ extern int screenheight;
extern int screenwidth;
extern bool progressive;
extern u8 * gameScreenTex;
extern u8 * gameScreenTex2;
extern u8 * gameScreenPng;
extern int gameScreenPngSize;
extern u32 FrameTimer;
extern u8 vmode_60hz;
extern int timerstyle;