mirror of https://github.com/stella-emu/stella.git
RomInfoWidget now honours 1x and 2x mode, and correctly resizes PNG
snapshots to the selected mode. This means that you no longer have to make sure that snapshots are taken in 1x mode (as was the previous functionality). git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1585 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
parent
c5de58f13c
commit
8ba2482f50
|
@ -749,8 +749,9 @@
|
|||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><pre>-romviewer <1|0></pre></td>
|
||||
<td>Show/hide ROM info viewer in ROM launcher mode.</td>
|
||||
<td><pre>-romviewer <0|1|2></pre></td>
|
||||
<td>Hide ROM info viewer in ROM launcher mode (0), or use the
|
||||
given zoom level (1 or 2).</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
// See the file "license" for information on usage and redistribution of
|
||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//
|
||||
// $Id: LauncherDialog.cxx,v 1.90 2008-12-29 20:42:15 stephena Exp $
|
||||
// $Id: LauncherDialog.cxx,v 1.91 2008-12-30 02:34:49 stephena Exp $
|
||||
//
|
||||
// Based on code from ScummVM - Scumm Interpreter
|
||||
// Copyright (C) 2002-2004 The ScummVM project
|
||||
|
@ -82,9 +82,9 @@ LauncherDialog::LauncherDialog(OSystem* osystem, DialogContainer* parent,
|
|||
int romWidth = 0;
|
||||
int romSize = instance().settings().getInt("romviewer");
|
||||
if(romSize > 1 && w >= 1000 && h >= 800)
|
||||
romWidth = 375*2;
|
||||
romWidth = 660;
|
||||
else if(romSize > 0 && w >= 640 && h >= 480)
|
||||
romWidth = 375;
|
||||
romWidth = 365;
|
||||
|
||||
int listWidth = _w - (romWidth > 0 ? romWidth+25 : 20);
|
||||
myList = new StringListWidget(this, font, xpos, ypos,
|
||||
|
|
|
@ -13,10 +13,11 @@
|
|||
// See the file "license" for information on usage and redistribution of
|
||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//
|
||||
// $Id: RomInfoWidget.cxx,v 1.11 2008-12-29 20:42:15 stephena Exp $
|
||||
// $Id: RomInfoWidget.cxx,v 1.12 2008-12-30 02:34:49 stephena Exp $
|
||||
//============================================================================
|
||||
|
||||
#include <cstring>
|
||||
#include <cmath>
|
||||
#include <zlib.h>
|
||||
|
||||
#include "FrameBuffer.hxx"
|
||||
|
@ -33,6 +34,7 @@ RomInfoWidget::RomInfoWidget(GuiObject* boss, const GUI::Font& font,
|
|||
: Widget(boss, font, x, y, w, h),
|
||||
mySurface(NULL),
|
||||
mySurfaceID(-1),
|
||||
myZoomLevel(w > 400 ? 2 : 1),
|
||||
mySurfaceIsValid(false),
|
||||
myHaveProperties(false)
|
||||
{
|
||||
|
@ -94,7 +96,8 @@ void RomInfoWidget::parseProperties()
|
|||
mySurface = instance().frameBuffer().surface(mySurfaceID);
|
||||
if(mySurface == NULL)
|
||||
{
|
||||
mySurfaceID = instance().frameBuffer().allocateSurface(320, 260, false);
|
||||
mySurfaceID = instance().frameBuffer().allocateSurface(
|
||||
320*myZoomLevel, 260*myZoomLevel, false);
|
||||
mySurface = instance().frameBuffer().surface(mySurfaceID);
|
||||
}
|
||||
|
||||
|
@ -140,14 +143,11 @@ void RomInfoWidget::parseProperties()
|
|||
{
|
||||
if(!parseIHDR(width, height, data, size))
|
||||
throw "Invalid PNG image (IHDR)";
|
||||
|
||||
mySurface->setWidth(width);
|
||||
mySurface->setHeight(height);
|
||||
}
|
||||
else if(type == "IDAT")
|
||||
{
|
||||
if(!parseIDATChunk(mySurface, width, height, data, size))
|
||||
throw "PNG image too large";
|
||||
throw "Invalid PNG image (IDAT)";
|
||||
}
|
||||
else if(type == "tEXt")
|
||||
textChucks.push_back(parseTextChunk(data, size));
|
||||
|
@ -188,24 +188,27 @@ void RomInfoWidget::drawWidget(bool hilite)
|
|||
{
|
||||
FBSurface& s = dialog().surface();
|
||||
|
||||
const int yoff = myZoomLevel > 1 ? 260*2 + 10 : 275;
|
||||
|
||||
s.fillRect(_x+2, _y+2, _w-4, _h-4, kWidColor);
|
||||
s.box(_x, _y, _w, _h, kColor, kShadowColor);
|
||||
s.box(_x, _y+275, _w, _h-275, kColor, kShadowColor);
|
||||
s.box(_x, _y+yoff, _w, _h-yoff, kColor, kShadowColor);
|
||||
|
||||
if(!myHaveProperties) return;
|
||||
|
||||
if(mySurfaceIsValid)
|
||||
{
|
||||
uInt32 x = ((_w - mySurface->getWidth()) >> 1) + getAbsX();
|
||||
uInt32 y = ((275 - mySurface->getHeight()) >> 1) + getAbsY();
|
||||
uInt32 x = _x + ((_w - mySurface->getWidth()) >> 1);
|
||||
uInt32 y = _y + ((yoff - mySurface->getHeight()) >> 1);
|
||||
s.drawSurface(mySurface, x, y);
|
||||
}
|
||||
else if(mySurfaceErrorMsg != "")
|
||||
{
|
||||
int x = _x + ((_w - _font->getStringWidth(mySurfaceErrorMsg)) >> 1);
|
||||
s.drawString(_font, mySurfaceErrorMsg, x, 120, _w - 10, _textcolor);
|
||||
uInt32 x = _x + ((_w - _font->getStringWidth(mySurfaceErrorMsg)) >> 1);
|
||||
uInt32 y = _y + ((yoff - _font->getLineHeight()) >> 1);
|
||||
s.drawString(_font, mySurfaceErrorMsg, x, y, _w - 10, _textcolor);
|
||||
}
|
||||
int xpos = _x + 5, ypos = _y + 280 + 5;
|
||||
int xpos = _x + 5, ypos = _y + yoff + 10;
|
||||
for(unsigned int i = 0; i < myRomInfo.size(); ++i)
|
||||
{
|
||||
s.drawString(_font, myRomInfo[i], xpos, ypos, _w - 10, _textcolor);
|
||||
|
@ -257,10 +260,6 @@ bool RomInfoWidget::parseIHDR(int& width, int& height, uInt8* data, int size)
|
|||
width = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
|
||||
height = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7];
|
||||
|
||||
// Make sure image can fit in widget bounds
|
||||
width = BSPF_min(320, width);
|
||||
height = BSPF_min(260, height);
|
||||
|
||||
uInt8 trailer[5] = { 8, 2, 0, 0, 0 }; // 24-bit RGB
|
||||
return memcmp(trailer, data + 8, 5) == 0;
|
||||
}
|
||||
|
@ -269,23 +268,81 @@ bool RomInfoWidget::parseIHDR(int& width, int& height, uInt8* data, int size)
|
|||
bool RomInfoWidget::parseIDATChunk(FBSurface* surface, int width, int height,
|
||||
uInt8* data, int size)
|
||||
{
|
||||
// The entire decompressed image data
|
||||
uLongf bufsize = (width * 3 + 1) * height;
|
||||
uInt8* buffer = new uInt8[bufsize];
|
||||
// Figure out the original zoom level of the snapshot
|
||||
// All snapshots generated by Stella are at most some multiple of 320
|
||||
// pixels wide
|
||||
// The only complication is when the aspect ratio is changed, the width
|
||||
// can range from 256 (80%) to 320 (100%)
|
||||
// The following calculation will work up to approx. 16x zoom level,
|
||||
// but since Stella only generates snapshots at up to 10x, we should
|
||||
// be fine for a while ...
|
||||
uInt32 izoom = int(ceil(width/320.0));
|
||||
|
||||
// Set the surface size
|
||||
uInt32 sw = width / izoom * myZoomLevel,
|
||||
sh = height / izoom * myZoomLevel;
|
||||
mySurface->setWidth(sw);
|
||||
mySurface->setHeight(sh);
|
||||
|
||||
// Decompress the image, and scale it correctly
|
||||
uInt32 ipitch = width * 3 + 1, // bytes per line of the actual PNG image
|
||||
spitch = sw * 3; // bytes per line of the surface/line
|
||||
uLongf bufsize = ipitch * height;
|
||||
uInt8* buffer = new uInt8[bufsize];
|
||||
uInt8* line = new uInt8[spitch + myZoomLevel*3]; // few extra bytes for rounding issues
|
||||
|
||||
int pitch = width * 3; // bytes per line of the image
|
||||
if(uncompress(buffer, &bufsize, data, size) == Z_OK)
|
||||
{
|
||||
uInt8* buf_ptr = buffer;
|
||||
for(int row = 0; row < height; row++, buf_ptr += pitch)
|
||||
uInt8* buf_ptr = buffer + 1; // skip past first column (PNG filter type)
|
||||
uInt32 buf_offset = ipitch * izoom;
|
||||
uInt32 i_offset = 3 * izoom;
|
||||
uInt32 srow = 0;
|
||||
/*
|
||||
cerr << "surface:" << endl
|
||||
<< " w = " << sw << endl
|
||||
<< " h = " << sh << endl
|
||||
<< " szoom = " << myZoomLevel << endl
|
||||
<< " spitch = " << spitch << endl
|
||||
<< endl;
|
||||
|
||||
cerr << "image:" << endl
|
||||
<< " width = " << width << endl
|
||||
<< " height = " << height << endl
|
||||
<< " izoom = " << izoom << endl
|
||||
<< " ipitch = " << ipitch << endl
|
||||
<< " bufsize = " << bufsize << endl
|
||||
<< " buf_offset = " << buf_offset << endl
|
||||
<< " i_offset = " << i_offset << endl
|
||||
<< endl;
|
||||
*/
|
||||
// Grab each non-duplicate row of data from the image
|
||||
for(int irow = 0; irow < height; irow += izoom, buf_ptr += buf_offset)
|
||||
{
|
||||
buf_ptr++; // skip past first byte (PNG filter type)
|
||||
surface->drawBytes(buf_ptr, 0, row, pitch);
|
||||
// Scale the image data into the temporary line buffer
|
||||
uInt8* i_ptr = buf_ptr;
|
||||
uInt8* l_ptr = line;
|
||||
for(int icol = 0; icol < width; icol += izoom, i_ptr += i_offset)
|
||||
{
|
||||
uInt32 xstride = myZoomLevel;
|
||||
while(xstride--)
|
||||
{
|
||||
*l_ptr++ = *i_ptr;
|
||||
*l_ptr++ = *(i_ptr+1);
|
||||
*l_ptr++ = *(i_ptr+2);
|
||||
}
|
||||
}
|
||||
|
||||
// Then fill the surface with those bytes
|
||||
uInt32 ystride = myZoomLevel;
|
||||
while(ystride--)
|
||||
surface->drawBytes(line, 0, srow++, spitch);
|
||||
}
|
||||
delete[] buffer;
|
||||
delete[] line;
|
||||
return true;
|
||||
}
|
||||
delete[] buffer;
|
||||
delete[] line;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
// See the file "license" for information on usage and redistribution of
|
||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//
|
||||
// $Id: RomInfoWidget.hxx,v 1.6 2008-12-29 20:42:15 stephena Exp $
|
||||
// $Id: RomInfoWidget.hxx,v 1.7 2008-12-30 02:34:49 stephena Exp $
|
||||
//============================================================================
|
||||
|
||||
#ifndef ROM_INFO_WIDGET_HXX
|
||||
|
@ -44,18 +44,21 @@ class RomInfoWidget : public Widget
|
|||
|
||||
private:
|
||||
void parseProperties();
|
||||
static bool isValidPNGHeader(uInt8* header);
|
||||
static void readPNGChunk(ifstream& in, string& type, uInt8** data, int& size);
|
||||
static bool parseIHDR(int& width, int& height, uInt8* data, int size);
|
||||
static bool parseIDATChunk(FBSurface* surface, int width, int height,
|
||||
uInt8* data, int size);
|
||||
static string parseTextChunk(uInt8* data, int size);
|
||||
bool isValidPNGHeader(uInt8* header);
|
||||
void readPNGChunk(ifstream& in, string& type, uInt8** data, int& size);
|
||||
bool parseIHDR(int& width, int& height, uInt8* data, int size);
|
||||
bool parseIDATChunk(FBSurface* surface, int width, int height,
|
||||
uInt8* data, int size);
|
||||
string parseTextChunk(uInt8* data, int size);
|
||||
|
||||
private:
|
||||
// Surface id and pointer holding the scaled PNG image
|
||||
FBSurface* mySurface;
|
||||
int mySurfaceID;
|
||||
|
||||
// How much to zoom the PNG image
|
||||
int myZoomLevel;
|
||||
|
||||
// Whether the surface should be redrawn by drawWidget()
|
||||
bool mySurfaceIsValid;
|
||||
|
||||
|
|
Loading…
Reference in New Issue