The ROM launcher now uses a separate FBSurface for snapshots, so that

any-sized PNG can be loaded and then scaled to the available space.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@2979 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2014-08-28 14:21:44 +00:00
parent 8da55d8eac
commit f6dd1ba27b
10 changed files with 145 additions and 168 deletions

View File

@ -21,6 +21,10 @@
* Added 'MDM' (Menu Driven Megacart) bankswitch scheme as described on * Added 'MDM' (Menu Driven Megacart) bankswitch scheme as described on
AtariAge and originally developed by Edwin Blink. AtariAge and originally developed by Edwin Blink.
* Improved snapshot viewing in the ROM launcher; snapshots are now
scaled to the available space, and can better accommodate sizes
other than those generated by Stella itself.
* Removed the 'bank' command from the debugger prompt, as it only worked * Removed the 'bank' command from the debugger prompt, as it only worked
with certain bankswitch types. The bankswitch UI should now be used with certain bankswitch types. The bankswitch UI should now be used
to query/set bank state. to query/set bank state.

View File

@ -33,36 +33,7 @@ FBSurfaceSDL2::FBSurfaceSDL2(FrameBufferSDL2& buffer,
myBlendAlpha(255), myBlendAlpha(255),
myStaticData(NULL) myStaticData(NULL)
{ {
// Create a surface in the same format as the parent GL class createSurface(width, height, data);
const SDL_PixelFormat* pf = myFB.myPixelFormat;
mySurface = SDL_CreateRGBSurface(0, width, height,
pf->BitsPerPixel, pf->Rmask, pf->Gmask, pf->Bmask, pf->Amask);
// We start out with the src and dst rectangles containing the same
// dimensions, indicating no scaling or re-positioning
mySrcR.x = mySrcR.y = myDstR.x = myDstR.y = 0;
mySrcR.w = myDstR.w = width;
mySrcR.h = myDstR.h = height;
////////////////////////////////////////////////////
// These *must* be set for the parent class
myPixels = (uInt32*) mySurface->pixels;
myPitch = mySurface->pitch / pf->BytesPerPixel;
////////////////////////////////////////////////////
if(data)
{
myTexAccess = SDL_TEXTUREACCESS_STATIC;
myStaticPitch = mySurface->w * 4; // we need pitch in 'bytes'
myStaticData = new uInt32[mySurface->w * mySurface->h];
SDL_memcpy(myStaticData, data, mySurface->w * mySurface->h * 4);
}
applyAttributes(false);
// To generate texture
reload();
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -92,14 +63,6 @@ void FBSurfaceSDL2::fillRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h, uInt32 colo
SDL_FillRect(mySurface, &tmp, myPalette[color]); SDL_FillRect(mySurface, &tmp, myPalette[color]);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceSDL2::drawSurface(const FBSurface* surface)
{
const FBSurfaceSDL2* s = (const FBSurfaceSDL2*) surface;
SDL_Rect dst = s->myDstR;
SDL_BlitSurface(s->mySurface, &(s->mySrcR), mySurface, &dst);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 FBSurfaceSDL2::width() const uInt32 FBSurfaceSDL2::width() const
{ {
@ -113,16 +76,14 @@ uInt32 FBSurfaceSDL2::height() const
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const GUI::Rect& FBSurfaceSDL2::srcRect() const GUI::Rect& FBSurfaceSDL2::srcRect() const
{ {
mySrcGUIR.setBounds(mySrcR.x, mySrcR.y, mySrcR.x+mySrcR.w, mySrcR.y+mySrcR.h);
return mySrcGUIR; return mySrcGUIR;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const GUI::Rect& FBSurfaceSDL2::dstRect() const GUI::Rect& FBSurfaceSDL2::dstRect() const
{ {
myDstGUIR.setBounds(myDstR.x, myDstR.y, myDstR.x+myDstR.w, myDstR.y+myDstR.h);
return myDstGUIR; return myDstGUIR;
} }
@ -130,24 +91,28 @@ const GUI::Rect& FBSurfaceSDL2::dstRect()
void FBSurfaceSDL2::setSrcPos(uInt32 x, uInt32 y) void FBSurfaceSDL2::setSrcPos(uInt32 x, uInt32 y)
{ {
mySrcR.x = x; mySrcR.y = y; mySrcR.x = x; mySrcR.y = y;
mySrcGUIR.moveTo(x, y);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceSDL2::setSrcSize(uInt32 w, uInt32 h) void FBSurfaceSDL2::setSrcSize(uInt32 w, uInt32 h)
{ {
mySrcR.w = w; mySrcR.h = h; mySrcR.w = w; mySrcR.h = h;
mySrcGUIR.setWidth(w); mySrcGUIR.setHeight(h);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceSDL2::setDstPos(uInt32 x, uInt32 y) void FBSurfaceSDL2::setDstPos(uInt32 x, uInt32 y)
{ {
myDstR.x = x; myDstR.y = y; myDstR.x = x; myDstR.y = y;
myDstGUIR.moveTo(x, y);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceSDL2::setDstSize(uInt32 w, uInt32 h) void FBSurfaceSDL2::setDstSize(uInt32 w, uInt32 h)
{ {
myDstR.w = w; myDstR.h = h; myDstR.w = w; myDstR.h = h;
myDstGUIR.setWidth(w); myDstGUIR.setHeight(h);
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -220,6 +185,57 @@ void FBSurfaceSDL2::reload()
} }
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceSDL2::resize(uInt32 width, uInt32 height)
{
// We will only resize when necessary, and not using static textures
if((myTexAccess == SDL_TEXTUREACCESS_STATIC) ||
(width <= mySurface->w && height <= mySurface->h))
return; // don't need to resize at all
if(mySurface)
SDL_FreeSurface(mySurface);
free();
createSurface(width, height, NULL);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceSDL2::createSurface(uInt32 width, uInt32 height,
const uInt32* data)
{
// Create a surface in the same format as the parent GL class
const SDL_PixelFormat* pf = myFB.myPixelFormat;
mySurface = SDL_CreateRGBSurface(0, width, height,
pf->BitsPerPixel, pf->Rmask, pf->Gmask, pf->Bmask, pf->Amask);
// We start out with the src and dst rectangles containing the same
// dimensions, indicating no scaling or re-positioning
mySrcR.x = mySrcR.y = myDstR.x = myDstR.y = 0;
mySrcR.w = myDstR.w = width;
mySrcR.h = myDstR.h = height;
////////////////////////////////////////////////////
// These *must* be set for the parent class
myPixels = (uInt32*) mySurface->pixels;
myPitch = mySurface->pitch / pf->BytesPerPixel;
////////////////////////////////////////////////////
if(data)
{
myTexAccess = SDL_TEXTUREACCESS_STATIC;
myStaticPitch = mySurface->w * 4; // we need pitch in 'bytes'
myStaticData = new uInt32[mySurface->w * mySurface->h];
SDL_memcpy(myStaticData, data, mySurface->w * mySurface->h * 4);
}
applyAttributes(false);
// To generate texture
reload();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceSDL2::applyAttributes(bool immediate) void FBSurfaceSDL2::applyAttributes(bool immediate)
{ {

View File

@ -40,15 +40,14 @@ class FBSurfaceSDL2 : public FBSurface
// the ones implemented here use SDL-specific code for extra performance // the ones implemented here use SDL-specific code for extra performance
// //
void fillRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h, uInt32 color); void fillRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h, uInt32 color);
void drawSurface(const FBSurface* surface);
// With hardware surfaces, it's faster to just update the entire surface // With hardware surfaces, it's faster to just update the entire surface
void setDirty() { mySurfaceIsDirty = true; } void setDirty() { mySurfaceIsDirty = true; }
uInt32 width() const; uInt32 width() const;
uInt32 height() const; uInt32 height() const;
const GUI::Rect& srcRect(); const GUI::Rect& srcRect() const;
const GUI::Rect& dstRect(); const GUI::Rect& dstRect() const;
void setSrcPos(uInt32 x, uInt32 y); void setSrcPos(uInt32 x, uInt32 y);
void setSrcSize(uInt32 w, uInt32 h); void setSrcSize(uInt32 w, uInt32 h);
void setDstPos(uInt32 x, uInt32 y); void setDstPos(uInt32 x, uInt32 y);
@ -60,10 +59,14 @@ class FBSurfaceSDL2 : public FBSurface
void invalidate(); void invalidate();
void free(); void free();
void reload(); void reload();
void resize(uInt32 width, uInt32 height);
protected: protected:
void applyAttributes(bool immediate); void applyAttributes(bool immediate);
private:
void createSurface(uInt32 width, uInt32 height, const uInt32* data);
private: private:
FrameBufferSDL2& myFB; FrameBufferSDL2& myFB;

View File

@ -38,7 +38,6 @@ PNGLibrary::PNGLibrary(const FrameBuffer& fb)
PNGLibrary::~PNGLibrary() PNGLibrary::~PNGLibrary()
{ {
delete[] ReadInfo.buffer; delete[] ReadInfo.buffer;
delete[] ReadInfo.line;
delete[] ReadInfo.row_pointers; delete[] ReadInfo.row_pointers;
} }
@ -115,8 +114,8 @@ void PNGLibrary::loadImage(const string& filename, FBSurface& surface)
// We're finished reading // We're finished reading
png_read_end(png_ptr, info_ptr); png_read_end(png_ptr, info_ptr);
// Scale image to surface dimensions // Load image into the surface, setting the correct dimensions
scaleImagetoSurface(surface); loadImagetoSurface(surface);
// Cleanup // Cleanup
done: done:
@ -258,16 +257,6 @@ bool PNGLibrary::allocateStorage(png_uint_32 w, png_uint_32 h)
ReadInfo.buffer_size = req_buffer_size; ReadInfo.buffer_size = req_buffer_size;
} }
uInt32 req_line_size = w * 3;
if(req_line_size > ReadInfo.line_size)
{
delete[] ReadInfo.line;
ReadInfo.line = new uInt32[req_line_size];
if(ReadInfo.line == NULL)
return false;
ReadInfo.line_size = req_line_size;
}
uInt32 req_row_size = h; uInt32 req_row_size = h;
if(req_row_size > ReadInfo.row_size) if(req_row_size > ReadInfo.row_size)
{ {
@ -287,53 +276,30 @@ bool PNGLibrary::allocateStorage(png_uint_32 w, png_uint_32 h)
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void PNGLibrary::scaleImagetoSurface(FBSurface& surface) void PNGLibrary::loadImagetoSurface(FBSurface& surface)
{ {
// Figure out the original zoom level of the snapshot // First determine if we need to resize the surface
// All snapshots generated by Stella are at most some multiple of 320 uInt32 iw = ReadInfo.width, ih = ReadInfo.height;
// pixels wide if(iw > surface.width() || ih > surface.height())
// The only complication is when the aspect ratio is changed, the width surface.resize(iw, ih);
// 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 = uInt32(ceil(ReadInfo.width/320.0)),
szoom = surface.width()/320;
uInt32 sw = ReadInfo.width / izoom * szoom, // The source dimensions are set here; the destination dimensions are
sh = ReadInfo.height / izoom * szoom; // set by whoever owns the surface
sw = BSPF_min(sw, surface.width()); surface.setSrcPos(0, 0);
sh = BSPF_min(sh, surface.height()); surface.setSrcSize(iw, ih);
surface.setSrcSize(sw, sh);
surface.setDstSize(sw, sh);
// Decompress the image, and scale it correctly // Convert RGB triples into pixels and store in the surface
uInt32 buf_offset = ReadInfo.pitch * izoom; uInt32 *s_buf, s_pitch;
uInt32 i_offset = 3 * izoom; surface.basePtr(s_buf, s_pitch);
uInt8* i_buf = ReadInfo.buffer;
uInt32 i_pitch = ReadInfo.pitch;
// We can only scan at most the height of the image to the constraints of for(uInt32 irow = 0; irow < ih; ++irow, i_buf += i_pitch, s_buf += s_pitch)
// the surface height (some multiple of 256)
uInt32 iheight = BSPF_min((uInt32)ReadInfo.height, izoom * 256);
// Grab each non-duplicate row of data from the image
uInt8* buffer = ReadInfo.buffer;
for(uInt32 irow = 0, srow = 0; irow < iheight; irow += izoom, buffer += buf_offset)
{ {
// Scale the image data into the temporary line buffer uInt8* i_ptr = i_buf;
uInt8* i_ptr = buffer; uInt32* s_ptr = s_buf;
uInt32* l_ptr = ReadInfo.line; for(uInt32 icol = 0; icol < ReadInfo.width; ++icol, i_ptr += 3)
for(uInt32 icol = 0; icol < ReadInfo.width; icol += izoom, i_ptr += i_offset) *s_ptr++ = myFB.mapRGB(*i_ptr, *(i_ptr+1), *(i_ptr+2));
{
uInt32 pixel = myFB.mapRGB(*i_ptr, *(i_ptr+1), *(i_ptr+2));
uInt32 xstride = szoom;
while(xstride--)
*l_ptr++ = pixel;
}
// Then fill the surface with those bytes
uInt32 ystride = szoom;
while(ystride--)
surface.drawPixels(ReadInfo.line, 0, srow++, sw);
} }
} }
@ -394,5 +360,5 @@ void PNGLibrary::png_user_error(png_structp ctx, png_const_charp str)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PNGLibrary::ReadInfoType PNGLibrary::ReadInfo = { PNGLibrary::ReadInfoType PNGLibrary::ReadInfo = {
NULL, NULL, 0, 0, 0, NULL, 0, 0, 0 NULL, NULL, 0, 0, 0, 0, 0
}; };

View File

@ -95,8 +95,7 @@ class PNGLibrary
uInt8* buffer; uInt8* buffer;
png_bytep* row_pointers; png_bytep* row_pointers;
png_uint_32 width, height, pitch; png_uint_32 width, height, pitch;
uInt32* line; uInt32 buffer_size, row_size;
uInt32 buffer_size, line_size, row_size;
} ReadInfoType; } ReadInfoType;
static ReadInfoType ReadInfo; static ReadInfoType ReadInfo;
@ -128,12 +127,12 @@ class PNGLibrary
const VariantList& comments); const VariantList& comments);
/** /**
Scale the PNG data from 'ReadInfo' into the FBSurface. For now, scaling Load the PNG data from 'ReadInfo' into the FBSurface. The surface
is done on integer boundaries only (ie, 1x, 2x, etc up or down). is resized as necessary to accommodate the data.
@param surface The FBSurface into which to place the PNG data @param surface The FBSurface into which to place the PNG data
*/ */
void scaleImagetoSurface(FBSurface& surface); void loadImagetoSurface(FBSurface& surface);
/** /**
Write PNG tEXt chunks to the image. Write PNG tEXt chunks to the image.

View File

@ -283,23 +283,5 @@ void FBSurface::drawString(const GUI::Font& font, const string& s,
} }
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurface::drawSurface(const FBSurface* surface)
{
const GUI::Rect& srcR = ((FBSurface*)surface)->srcRect();
const GUI::Rect& dstR = ((FBSurface*)surface)->dstRect();
const uInt32* src = surface->myPixels + srcR.y() * surface->myPitch + srcR.x();
uInt32* dst = myPixels + dstR.y() * myPitch + dstR.x();
uInt32 h = srcR.height(), w = srcR.width() * 4;
while(h--)
{
memcpy(dst, src, w);
src += surface->myPitch;
dst += myPitch;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const uInt32* FBSurface::myPalette = 0; const uInt32* FBSurface::myPalette = 0;

View File

@ -52,7 +52,7 @@ enum FrameStyle {
class FBSurface class FBSurface
{ {
friend class TIASurface; // friend class TIASurface;
public: public:
/** /**
@ -208,16 +208,6 @@ class FBSurface
uInt32 color, TextAlignment align = kTextAlignLeft, uInt32 color, TextAlignment align = kTextAlignLeft,
int deltax = 0, bool useEllipsis = true); int deltax = 0, bool useEllipsis = true);
/**
This method should be called copy the contents of the given
surface into the FrameBuffer surface. No scaling is done; that is,
a straight-forward copy of the surface pixels is done at the specified
destination.
@param surface The data to draw
*/
virtual void drawSurface(const FBSurface* surface);
/** /**
This method should be called to indicate that the surface has been This method should be called to indicate that the surface has been
modified, and should be redrawn at the next interval. modified, and should be redrawn at the next interval.
@ -243,8 +233,8 @@ class FBSurface
These methods answer the current *rendering* dimensions of the These methods answer the current *rendering* dimensions of the
specified surface. specified surface.
*/ */
virtual const GUI::Rect& srcRect() = 0; virtual const GUI::Rect& srcRect() const = 0;
virtual const GUI::Rect& dstRect() = 0; virtual const GUI::Rect& dstRect() const = 0;
/** /**
These methods set the origin point and width/height for the These methods set the origin point and width/height for the
@ -295,9 +285,13 @@ class FBSurface
*/ */
virtual void reload() = 0; virtual void reload() = 0;
static void setPalette(const uInt32* palette) { myPalette = palette; } /**
This method should be called to resize the surface to the
given dimensions and reload data/state. The surface is not
modified if it is larger than the given dimensions.
*/
virtual void resize(uInt32 width, uInt32 height) = 0;
protected:
/** /**
The rendering attributes that can be modified for this texture. The rendering attributes that can be modified for this texture.
These probably can only be implemented in child FBSurfaces where These probably can only be implemented in child FBSurfaces where
@ -308,6 +302,12 @@ class FBSurface
bool blending; // Blending is enabled bool blending; // Blending is enabled
uInt32 blendalpha; // Alpha to use in blending mode (0-100%) uInt32 blendalpha; // Alpha to use in blending mode (0-100%)
}; };
/**
Get the currently applied attributes.
*/
Attributes& attributes() { return myAttributes; }
/** /**
The child class chooses which (if any) of the actual attributes The child class chooses which (if any) of the actual attributes
can be applied. can be applied.
@ -318,6 +318,8 @@ class FBSurface
*/ */
virtual void applyAttributes(bool immediate = true) = 0; virtual void applyAttributes(bool immediate = true) = 0;
static void setPalette(const uInt32* palette) { myPalette = palette; }
protected: protected:
static const uInt32* myPalette; static const uInt32* myPalette;
uInt32* myPixels; uInt32* myPixels;

View File

@ -137,9 +137,8 @@ const FBSurface& TIASurface::baseSurface(GUI::Rect& rect)
rect.setBounds(0, 0, width, height); rect.setBounds(0, 0, width, height);
// Fill the surface with pixels from the TIA, scaled 2x horizontally // Fill the surface with pixels from the TIA, scaled 2x horizontally
uInt32 *buffer, pitch; uInt32 *buf_ptr, pitch;
myBaseTiaSurface->basePtr(buffer, pitch); myBaseTiaSurface->basePtr(buf_ptr, pitch);
uInt32* buf_ptr = buffer;
for(uInt32 y = 0; y < height; ++y) for(uInt32 y = 0; y < height; ++y)
{ {
@ -219,22 +218,23 @@ void TIASurface::toggleScanlineInterpolation()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 TIASurface::enableScanlines(int relative, int absolute) uInt32 TIASurface::enableScanlines(int relative, int absolute)
{ {
uInt32& intensity = mySLineSurface->myAttributes.blendalpha; FBSurface::Attributes& attr = mySLineSurface->attributes();
if(relative == 0) intensity = absolute; if(relative == 0) attr.blendalpha = absolute;
else intensity += relative; else attr.blendalpha += relative;
intensity = BSPF_max(0u, intensity); attr.blendalpha = BSPF_max(0u, attr.blendalpha);
intensity = BSPF_min(100u, intensity); attr.blendalpha = BSPF_min(100u, attr.blendalpha);
mySLineSurface->applyAttributes(); mySLineSurface->applyAttributes();
mySLineSurface->setDirty(); mySLineSurface->setDirty();
return intensity; return attr.blendalpha;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIASurface::enableScanlineInterpolation(bool enable) void TIASurface::enableScanlineInterpolation(bool enable)
{ {
mySLineSurface->myAttributes.smoothing = enable; FBSurface::Attributes& attr = mySLineSurface->attributes();
attr.smoothing = enable;
mySLineSurface->applyAttributes(); mySLineSurface->applyAttributes();
mySLineSurface->setDirty(); mySLineSurface->setDirty();
} }
@ -266,16 +266,15 @@ void TIASurface::enableNTSC(bool enable)
// Normal vs NTSC mode uses different source widths // Normal vs NTSC mode uses different source widths
myTiaSurface->setSrcSize(enable ? ATARI_NTSC_OUT_WIDTH(160) : 160, myTIA->height()); myTiaSurface->setSrcSize(enable ? ATARI_NTSC_OUT_WIDTH(160) : 160, myTIA->height());
myTiaSurface->myAttributes.smoothing = FBSurface::Attributes& tia_attr = myTiaSurface->attributes();
myOSystem.settings().getBool("tia.inter"); tia_attr.smoothing = myOSystem.settings().getBool("tia.inter");
myTiaSurface->applyAttributes(); myTiaSurface->applyAttributes();
myScanlinesEnabled = enable; myScanlinesEnabled = enable;
mySLineSurface->myAttributes.smoothing = FBSurface::Attributes& sl_attr = mySLineSurface->attributes();
myOSystem.settings().getBool("tv.scaninter"); sl_attr.smoothing = myOSystem.settings().getBool("tv.scaninter");
mySLineSurface->myAttributes.blending = myScanlinesEnabled; sl_attr.blending = myScanlinesEnabled;
mySLineSurface->myAttributes.blendalpha = sl_attr.blendalpha = myOSystem.settings().getInt("tv.scanlines");
myOSystem.settings().getInt("tv.scanlines");
mySLineSurface->applyAttributes(); mySLineSurface->applyAttributes();
myTiaSurface->setDirty(); myTiaSurface->setDirty();
@ -285,6 +284,8 @@ void TIASurface::enableNTSC(bool enable)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string TIASurface::effectsInfo() const string TIASurface::effectsInfo() const
{ {
const FBSurface::Attributes& attr = mySLineSurface->attributes();
ostringstream buf; ostringstream buf;
switch(myFilterType) switch(myFilterType)
{ {
@ -295,14 +296,12 @@ string TIASurface::effectsInfo() const
buf << "Disabled, phosphor mode"; buf << "Disabled, phosphor mode";
break; break;
case kBlarggNormal: case kBlarggNormal:
buf << myNTSCFilter.getPreset() << ", scanlines=" buf << myNTSCFilter.getPreset() << ", scanlines=" << attr.blendalpha << "/"
<< mySLineSurface->myAttributes.blendalpha << "/" << (attr.smoothing ? "inter" : "nointer");
<< (mySLineSurface->myAttributes.smoothing ? "inter" : "nointer");
break; break;
case kBlarggPhosphor: case kBlarggPhosphor:
buf << myNTSCFilter.getPreset() << ", phosphor, scanlines=" buf << myNTSCFilter.getPreset() << ", phosphor, scanlines="
<< mySLineSurface->myAttributes.blendalpha << "/" << attr.blendalpha << "/" << (attr.smoothing ? "inter" : "nointer");
<< (mySLineSurface->myAttributes.smoothing ? "inter" : "nointer");
break; break;
} }
return buf.str(); return buf.str();

View File

@ -42,8 +42,6 @@ class VideoMode;
class TIASurface class TIASurface
{ {
friend class FrameBuffer;
public: public:
/** /**
Creates a new TIASurface object Creates a new TIASurface object

View File

@ -92,9 +92,11 @@ void RomInfoWidget::parseProperties()
// only draw certain parts of it // only draw certain parts of it
if(mySurface == NULL) if(mySurface == NULL)
{ {
uInt32 ID = instance().frameBuffer().allocateSurface( uInt32 ID = instance().frameBuffer().allocateSurface(320*2, 256*2);
320*myZoomLevel, 256*myZoomLevel);
mySurface = instance().frameBuffer().surface(ID); mySurface = instance().frameBuffer().surface(ID);
mySurface->attributes().smoothing = true;
mySurface->applyAttributes();
dialog().addSurface(mySurface); dialog().addSurface(mySurface);
} }
@ -111,6 +113,12 @@ void RomInfoWidget::parseProperties()
try try
{ {
instance().png().loadImage(filename, *mySurface); instance().png().loadImage(filename, *mySurface);
// Scale surface to available image area
const GUI::Rect& src = mySurface->srcRect();
uInt32 avail_w = 320 * myZoomLevel, avail_h = 256 * myZoomLevel;
float scale = BSPF_min(float(avail_w) / src.width(), float(avail_h) / src.height());
mySurface->setDstSize(src.width() * scale, src.height() * scale);
} }
catch(const char* msg) catch(const char* msg)
{ {
@ -145,9 +153,9 @@ void RomInfoWidget::drawWidget(bool hilite)
if(mySurfaceIsValid) if(mySurfaceIsValid)
{ {
const GUI::Rect& src = mySurface->srcRect(); const GUI::Rect& dst = mySurface->dstRect();
uInt32 x = _x + ((_w - src.width()) >> 1); uInt32 x = _x + ((_w - dst.width()) >> 1);
uInt32 y = _y + ((yoff - src.height()) >> 1); uInt32 y = _y + ((yoff - dst.height()) >> 1);
// Make sure when positioning the snapshot surface that we take // Make sure when positioning the snapshot surface that we take
// the dialog surface position into account // the dialog surface position into account