mirror of
https://github.com/dborth/snes9xgx.git
synced 2024-11-27 21:14:21 +01:00
use less memory for snapshot screenshots - so now thumbs are activated for GameCube
This commit is contained in:
parent
2ffdd76b7c
commit
118ca267c5
@ -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");
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user