Several updates to the new UI rendering infrastructure. Overlaid frame

stats and general messages are now shown correctly.  ContextMenu and
PopUpWidget are now drawn correctly, and take image 'centering' into
account.  Fixed many 'offset' bugs in rendering surfaces.  Fixed
long-standing issue where pressing Alt-Enter to toggle fullscreen mode
actually passed the Enter to the underlying dialog (it's now properly
swallowed).  Probably many more items I'm forgetting ...

Still TODO is work on other dialogs that aren't centered by default
(InputTextDialog, etc).  My plan is to stabilize these changes and then
fix OpenGL mode, and only after I've achieved parity with 2.6.1 to
actually make use of the new infrastructure (larger fonts, etc).


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1539 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2008-06-19 12:01:31 +00:00
parent 2bbdcc34d7
commit 2e2867cb6e
20 changed files with 533 additions and 434 deletions

View File

@ -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: FrameBufferGL.cxx,v 1.103 2008-06-13 13:14:50 stephena Exp $
// $Id: FrameBufferGL.cxx,v 1.104 2008-06-19 12:01:30 stephena Exp $
//============================================================================
#ifdef DISPLAY_OPENGL
@ -180,7 +180,7 @@ bool FrameBufferGL::loadFuncs()
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool FrameBufferGL::initSubsystem(VideoMode mode)
bool FrameBufferGL::initSubsystem(VideoMode& mode)
{
mySDLFlags |= SDL_OPENGL;
@ -234,8 +234,10 @@ string FrameBufferGL::about() const
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool FrameBufferGL::setVidMode(VideoMode mode)
bool FrameBufferGL::setVidMode(VideoMode& mode)
{
return false;
#if 0
bool inUIMode =
myOSystem->eventHandler().state() == EventHandler::S_LAUNCHER ||
myOSystem->eventHandler().state() == EventHandler::S_DEBUGGER;
@ -354,6 +356,7 @@ bool FrameBufferGL::setVidMode(VideoMode mode)
p_glClear(GL_COLOR_BUFFER_BIT);
return true;
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -430,7 +433,8 @@ void FrameBufferGL::postFrameUpdate()
{
// Texturemap complete texture to surface so we have free scaling
// and antialiasing
uInt32 w = myImageDim.w, h = myImageDim.h;
// FIXME uInt32 w = myImageDim.w, h = myImageDim.h;
uInt32 w = 0, h = 0;
p_glTexSubImage2D(myBuffer.target, 0, 0, 0,
myBuffer.texture_width, myBuffer.texture_height,
@ -515,10 +519,11 @@ void FrameBufferGL::scanline(uInt32 row, uInt8* data) const
{
// Invert the row, since OpenGL rows start at the bottom
// of the framebuffer
row = myImageDim.h + myImageDim.y - row - 1;
const GUI::Rect& image = imageRect();
row = image.height() + image.y() - row - 1;
p_glPixelStorei(GL_PACK_ALIGNMENT, 1);
p_glReadPixels(myImageDim.x, row, myImageDim.w, 1, GL_RGB, GL_UNSIGNED_BYTE, data);
p_glReadPixels(image.x(), row, image.width(), 1, GL_RGB, GL_UNSIGNED_BYTE, data);
}
@ -636,36 +641,11 @@ void FBSurfaceGL::addDirtyRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceGL::centerPos()
void FBSurfaceGL::getPos(uInt32& x, uInt32& y) const
{
#if 0
// Make sure pitch is valid
recalc();
// X/Y Orig are the coordinates to use when blitting an entire (non-base)
// surface to the screen. As such, they're concerned with the 'usable'
// area of a surface, not its entire size (ie, we use the originally
// requested width & height, which are not necessarily the same as
// the surface width & height).
// These coordinates are not used at all for drawing base surfaces
myXOrig = (myFB.myScreenDim.w - myWidth) >> 1;
myYOrig = (myFB.myScreenDim.h - myHeight) >> 1;
// X/Y/Base Offset determine 'how far' to go into a surface, since base
// surfaces are defined larger than necessary in some cases, and have a
// 'non-usable' area.
if(myIsBaseSurface)
{
myXOffset = myFB.myImageDim.x;
myYOffset = myFB.myImageDim.y;
myBaseOffset = myYOffset * myPitch + myXOffset;
}
else
{
myXOffset = myYOffset = myBaseOffset = 0;
}
//cerr << "center: xorig = " << myXOrig << ", yorig = " << myYOrig << endl
// << " xoffset = " << myXOffset << ", yoffset = " << myYOffset << endl;
x = myXOrig;
y = myYOrig;
#endif
}
@ -687,12 +667,13 @@ void FBSurfaceGL::setPos(uInt32 x, uInt32 y)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceGL::getPos(uInt32& x, uInt32& y) const
void FBSurfaceGL::setWidth(uInt32 w)
{
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceGL::setHeight(uInt32 h)
{
#if 0
x = myXOrig;
y = myYOrig;
#endif
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -726,8 +707,8 @@ bool FrameBufferGL::createTextures()
// Fill buffer struct with valid data
// This changes depending on the texturing used
myBuffer.width = myBaseDim.w;
myBuffer.height = myBaseDim.h;
myBuffer.width = 0;//FIXME myBaseDim.w;
myBuffer.height = 0;//FIXME myBaseDim.h;
myBuffer.tex_coord[0] = 0.0f;
myBuffer.tex_coord[1] = 0.0f;
if(myHaveTexRectEXT)

View File

@ -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: FrameBufferGL.hxx,v 1.53 2008-06-13 13:14:50 stephena Exp $
// $Id: FrameBufferGL.hxx,v 1.54 2008-06-19 12:01:30 stephena Exp $
//============================================================================
#ifndef FRAMEBUFFER_GL_HXX
@ -35,7 +35,7 @@ class GUI::Font;
This class implements an SDL OpenGL framebuffer.
@author Stephen Anthony
@version $Id: FrameBufferGL.hxx,v 1.53 2008-06-13 13:14:50 stephena Exp $
@version $Id: FrameBufferGL.hxx,v 1.54 2008-06-19 12:01:30 stephena Exp $
*/
class FrameBufferGL : public FrameBuffer
{
@ -107,17 +107,24 @@ class FrameBufferGL : public FrameBuffer
// The following are derived from protected methods in FrameBuffer.hxx
//////////////////////////////////////////////////////////////////////
/**
This method is called to initialize OpenGL video mode.
Return false if any operation fails, otherwise return true.
This method is called to initialize the video subsystem
with the given video mode. Normally, it will also call setVidMode().
@param mode The video mode to use
@return False on any errors, else true
*/
bool initSubsystem(VideoMode mode);
bool initSubsystem(VideoMode& mode);
/**
This method is called to change to the given video mode.
This method is called to change to the given video mode. If the mode
is successfully changed, 'mode' holds the actual dimensions used.
@param mode The mode to use for rendering the mediasource
@param mode The video mode to use
@return False on any errors (in which case 'mode' is invalid), else true
*/
bool setVidMode(VideoMode mode);
bool setVidMode(VideoMode& mode);
/**
Switches between the two filtering options in OpenGL.
@ -203,7 +210,7 @@ class FrameBufferGL : public FrameBuffer
A surface suitable for software rendering mode.
@author Stephen Anthony
@version $Id: FrameBufferGL.hxx,v 1.53 2008-06-13 13:14:50 stephena Exp $
@version $Id: FrameBufferGL.hxx,v 1.54 2008-06-19 12:01:30 stephena Exp $
*/
class FBSurfaceGL : public FBSurface
{
@ -218,9 +225,10 @@ class FBSurfaceGL : public FBSurface
void drawChar(const GUI::Font* font, uInt8 c, uInt32 x, uInt32 y, int color);
void drawBitmap(uInt32* bitmap, Int32 x, Int32 y, int color, Int32 h = 8);
void addDirtyRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h);
void centerPos();
void setPos(uInt32 x, uInt32 y);
void getPos(uInt32& x, uInt32& y) const;
void setPos(uInt32 x, uInt32 y);
void setWidth(uInt32 w);
void setHeight(uInt32 h);
void translateCoords(Int32& x, Int32& y) const;
void update();

View File

@ -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: FrameBufferSoft.cxx,v 1.79 2008-06-13 13:14:50 stephena Exp $
// $Id: FrameBufferSoft.cxx,v 1.80 2008-06-19 12:01:30 stephena Exp $
//============================================================================
#include <sstream>
@ -46,7 +46,7 @@ FrameBufferSoft::~FrameBufferSoft()
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool FrameBufferSoft::initSubsystem(VideoMode mode)
bool FrameBufferSoft::initSubsystem(VideoMode& mode)
{
// Set up the rectangle list to be used in the dirty update
delete myRectList;
@ -83,26 +83,15 @@ string FrameBufferSoft::about() const
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool FrameBufferSoft::setVidMode(VideoMode mode)
bool FrameBufferSoft::setVidMode(VideoMode& mode)
{
myScreenDim.x = myScreenDim.y = 0;
myScreenDim.w = mode.screen_w;
myScreenDim.h = mode.screen_h;
myImageDim.x = mode.image_x;
myImageDim.y = mode.image_y;
myImageDim.w = mode.image_w;
myImageDim.h = mode.image_h;
myZoomLevel = mode.zoom;
// Make sure to clear the screen
if(myScreen)
{
SDL_FillRect(myScreen, NULL, 0);
SDL_UpdateRect(myScreen, 0, 0, 0, 0);
}
myScreen = SDL_SetVideoMode(myScreenDim.w, myScreenDim.h, 0, mySDLFlags);
myScreen = SDL_SetVideoMode(mode.screen_w, mode.screen_h, 0, mySDLFlags);
if(myScreen == NULL)
{
cerr << "ERROR: Unable to open SDL window: " << SDL_GetError() << endl;
@ -111,9 +100,16 @@ bool FrameBufferSoft::setVidMode(VideoMode mode)
myFormat = myScreen->format;
myBytesPerPixel = myFormat->BytesPerPixel;
// If software mode can open the given screen, it will always be in the
// requested format, or not at all; we only update mode when the screen
// is successfully created
mode.screen_w = myScreen->w;
mode.screen_h = myScreen->h;
myZoomLevel = mode.zoom;
// Make sure drawMediaSource() knows which renderer to use
stateChanged(myOSystem->eventHandler().state());
myBaseOffset = myImageDim.y * myPitch + myImageDim.x;
myBaseOffset = mode.image_y * myPitch + mode.image_x;
// Erase old rects, since they've probably been scaled for
// a different sized screen
@ -436,12 +432,13 @@ void FrameBufferSoft::scanline(uInt32 row, uInt8* data) const
uInt8 *p, r, g, b;
// Row will be offset by the amount the actual image is shifted down
row += myImageDim.y;
const GUI::Rect& image = imageRect();
row += image.y();
for(Int32 x = 0; x < myScreen->w; ++x)
{
p = (Uint8*) ((uInt8*)myScreen->pixels + // Start at top of RAM
(row * myScreen->pitch) + // Go down 'row' lines
((x + myImageDim.x) * myBytesPerPixel)); // Go in 'x' pixels
((x + image.x()) * myBytesPerPixel)); // Go in 'x' pixels
switch(myBytesPerPixel)
{
@ -691,57 +688,53 @@ void FBSurfaceSoft::addDirtyRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceSoft::centerPos()
void FBSurfaceSoft::getPos(uInt32& x, uInt32& y) const
{
// Return the origin of the 'usable' area of a surface
if(myIsBaseSurface)
{
x = myXOffset;
y = myYOffset;
}
else
{
x = myXOrig;
y = myYOrig;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceSoft::setPos(uInt32 x, uInt32 y)
{
// Make sure pitch is valid
recalc();
// X/Y Orig are the coordinates to use when blitting an entire (non-base)
// surface to the screen. As such, they're concerned with the 'usable'
// area of a surface, not its entire size (ie, we use the originally
// requested width & height, which are not necessarily the same as
// the surface width & height).
// These coordinates are not used at all for drawing base surfaces
myXOrig = (myFB.myScreenDim.w - myWidth) >> 1;
myYOrig = (myFB.myScreenDim.h - myHeight) >> 1;
myXOrig = x;
myYOrig = y;
// X/Y/Base Offset determine 'how far' to go into a surface, since base
// surfaces are defined larger than necessary in some cases, and have a
// 'non-usable' area.
if(myIsBaseSurface)
{
myXOffset = myFB.myImageDim.x;
myYOffset = myFB.myImageDim.y;
const GUI::Rect& image = myFB.imageRect();
myXOffset = image.x();
myYOffset = image.y();
myBaseOffset = myYOffset * myPitch + myXOffset;
}
else
{
myXOffset = myYOffset = myBaseOffset = 0;
}
//cerr << "center: xorig = " << myXOrig << ", yorig = " << myYOrig << endl
// << " xoffset = " << myXOffset << ", yoffset = " << myYOffset << endl;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceSoft::setPos(uInt32 x, uInt32 y)
void FBSurfaceSoft::setWidth(uInt32 w)
{
// Only non-base surfaces can be arbitrarily 'moved'
if(!myIsBaseSurface)
{
// Make sure pitch is valid
recalc();
myXOrig = x;
myYOrig = y;
myXOffset = myYOffset = myBaseOffset = 0;
}
myWidth = w;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceSoft::getPos(uInt32& x, uInt32& y) const
void FBSurfaceSoft::setHeight(uInt32 h)
{
x = myXOrig;
y = myYOrig;
myHeight = h;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -766,6 +759,12 @@ void FBSurfaceSoft::update()
}
else if(mySurfaceIsDirty /* && !myIsBaseSurface */)
{
SDL_Rect srcrect;
srcrect.x = 0;
srcrect.y = 0;
srcrect.w = myWidth;
srcrect.h = myHeight;
SDL_Rect dstrect;
dstrect.x = myXOrig;
dstrect.y = myYOrig;
@ -779,7 +778,7 @@ void FBSurfaceSoft::update()
<< " dst h = " << dstrect.h << endl
<< endl;
*/
SDL_BlitSurface(mySurface, NULL, myFB.myScreen, &dstrect);
SDL_BlitSurface(mySurface, &srcrect, myFB.myScreen, &dstrect);
SDL_UpdateRect(myFB.myScreen, myXOrig, myYOrig, myWidth, myHeight);
mySurfaceIsDirty = false;

View File

@ -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: FrameBufferSoft.hxx,v 1.51 2008-06-13 13:14:50 stephena Exp $
// $Id: FrameBufferSoft.hxx,v 1.52 2008-06-19 12:01:30 stephena Exp $
//============================================================================
#ifndef FRAMEBUFFER_SOFT_HXX
@ -33,7 +33,7 @@ class RectList;
This class implements an SDL software framebuffer.
@author Stephen Anthony
@version $Id: FrameBufferSoft.hxx,v 1.51 2008-06-13 13:14:50 stephena Exp $
@version $Id: FrameBufferSoft.hxx,v 1.52 2008-06-19 12:01:30 stephena Exp $
*/
class FrameBufferSoft : public FrameBuffer
{
@ -96,17 +96,24 @@ class FrameBufferSoft : public FrameBuffer
// The following are derived from protected methods in FrameBuffer.hxx
//////////////////////////////////////////////////////////////////////
/**
This method is called to initialize software video mode.
Return false if any operation fails, otherwise return true.
This method is called to initialize the video subsystem
with the given video mode. Normally, it will also call setVidMode().
@param mode The video mode to use
@return False on any errors, else true
*/
bool initSubsystem(VideoMode mode);
bool initSubsystem(VideoMode& mode);
/**
This method is called to change to the given videomode type.
This method is called to change to the given video mode. If the mode
is successfully changed, 'mode' holds the actual dimensions used.
@param mode The video mode to use for rendering the mediasource
@param mode The video mode to use
@return False on any errors (in which case 'mode' is invalid), else true
*/
bool setVidMode(VideoMode mode);
bool setVidMode(VideoMode& mode);
/**
Switches between the filtering options in software mode.
@ -155,7 +162,7 @@ class FrameBufferSoft : public FrameBuffer
A surface suitable for software rendering mode.
@author Stephen Anthony
@version $Id: FrameBufferSoft.hxx,v 1.51 2008-06-13 13:14:50 stephena Exp $
@version $Id: FrameBufferSoft.hxx,v 1.52 2008-06-19 12:01:30 stephena Exp $
*/
class FBSurfaceSoft : public FBSurface
{
@ -170,9 +177,10 @@ class FBSurfaceSoft : public FBSurface
void drawChar(const GUI::Font* font, uInt8 c, uInt32 x, uInt32 y, int color);
void drawBitmap(uInt32* bitmap, Int32 x, Int32 y, int color, Int32 h = 8);
void addDirtyRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h);
void centerPos();
void setPos(uInt32 x, uInt32 y);
void getPos(uInt32& x, uInt32& y) const;
void setPos(uInt32 x, uInt32 y);
void setWidth(uInt32 w);
void setHeight(uInt32 h);
void translateCoords(Int32& x, Int32& y) const;
void update();

View File

@ -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: Snapshot.cxx,v 1.22 2008-05-30 19:07:55 stephena Exp $
// $Id: Snapshot.cxx,v 1.23 2008-06-19 12:01:30 stephena Exp $
//============================================================================
#include <zlib.h>
@ -42,8 +42,8 @@ void Snapshot::savePNG(FrameBuffer& framebuffer, const Properties& props,
// Get actual image dimensions. which are not always the same
// as the framebuffer dimensions
int width = framebuffer.imageWidth();
int height = framebuffer.imageHeight();
const GUI::Rect& image = framebuffer.imageRect();
int width = image.width(), height = image.height();
out.open(filename.c_str(), ios_base::binary);
if(!out.is_open())

View File

@ -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: VideoModeList.hxx,v 1.4 2008-02-06 13:45:19 stephena Exp $
// $Id: VideoModeList.hxx,v 1.5 2008-06-19 12:01:30 stephena Exp $
//============================================================================
#ifndef VIDMODE_LIST_HXX
@ -33,7 +33,7 @@ struct VideoMode {
This class implements an iterator around an array of VideoMode objects.
@author Stephen Anthony
@version $Id: VideoModeList.hxx,v 1.4 2008-02-06 13:45:19 stephena Exp $
@version $Id: VideoModeList.hxx,v 1.5 2008-06-19 12:01:30 stephena Exp $
*/
class VideoModeList
{
@ -94,6 +94,23 @@ class VideoModeList
}
}
void print()
{
for(Common::Array<VideoMode>::const_iterator i = myModeList.begin(); i != myModeList.end(); ++i)
{
cerr << " Mode " << i << endl
<< " screen w = " << i->screen_w << endl
<< " screen h = " << i->screen_h << endl
<< " image x = " << i->image_x << endl
<< " image y = " << i->image_y << endl
<< " image w = " << i->image_w << endl
<< " image h = " << i->image_h << endl
<< " zoom = " << i->zoom << endl
<< " name = " << i->name << endl
<< endl;
}
}
private:
Common::Array<VideoMode> myModeList;
int myIdx;

View File

@ -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: RomListWidget.cxx,v 1.13 2008-06-13 13:14:50 stephena Exp $
// $Id: RomListWidget.cxx,v 1.14 2008-06-19 12:01:30 stephena Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
@ -67,9 +67,16 @@ void RomListWidget::handleMouseDown(int x, int y, int button, int clickCount)
{
// Grab right mouse button for context menu, send left to base class
if(button == 2)
myMenu->show(x + getAbsX(), y + getAbsY());
ListWidget::handleMouseDown(x, y, button, clickCount);
{
// Add menu at current x,y mouse location
uInt32 tx, ty;
dialog().surface().getPos(tx, ty);
x += getAbsX() + tx;
y += getAbsY() + ty;
myMenu->show(x, y);
}
else
ListWidget::handleMouseDown(x, y, button, clickCount);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -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: TiaOutputWidget.cxx,v 1.16 2008-06-13 13:14:50 stephena Exp $
// $Id: TiaOutputWidget.cxx,v 1.17 2008-06-19 12:01:30 stephena Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
@ -92,7 +92,12 @@ void TiaOutputWidget::handleMouseDown(int x, int y, int button, int clickCount)
myClickX = x;
myClickY = y;
myMenu->show(x + getAbsX(), y + getAbsY());
// Add menu at current x,y mouse location
uInt32 tx, ty;
dialog().surface().getPos(tx, ty);
x += getAbsX() + tx;
y += getAbsY() + ty;
myMenu->show(x, y);
}
}

View File

@ -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: TiaZoomWidget.cxx,v 1.16 2008-06-13 13:14:50 stephena Exp $
// $Id: TiaZoomWidget.cxx,v 1.17 2008-06-19 12:01:30 stephena Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
@ -137,7 +137,14 @@ void TiaZoomWidget::handleMouseDown(int x, int y, int button, int clickCount)
{
// Grab right mouse button for zoom context menu
if(button == 2)
myMenu->show(x + getAbsX(), y + getAbsY());
{
// Add menu at current x,y mouse location
uInt32 tx, ty;
dialog().surface().getPos(tx, ty);
x += getAbsX() + tx;
y += getAbsY() + ty;
myMenu->show(x, y);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -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: EventHandler.cxx,v 1.226 2008-06-13 13:14:50 stephena Exp $
// $Id: EventHandler.cxx,v 1.227 2008-06-19 12:01:30 stephena Exp $
//============================================================================
#include <sstream>
@ -344,38 +344,35 @@ void EventHandler::poll(uInt32 time)
SDLKey key = event.key.keysym.sym;
SDLMod mod = event.key.keysym.mod;
uInt8 state = event.key.type == SDL_KEYDOWN ? 1 : 0;
bool handled = true;
// An attempt to speed up event processing
// All SDL-specific event actions are accessed by either
// Control/Cmd or Alt/Shift-Cmd keys. So we quickly check for those.
if(kbdAlt(mod) && state)
{
#ifndef MAC_OSX
// These keys work in all states
switch(int(key))
if(key == SDLK_RETURN)
{
#ifndef MAC_OSX
case SDLK_EQUALS:
myOSystem->frameBuffer().changeVidMode(+1);
break;
case SDLK_MINUS:
myOSystem->frameBuffer().changeVidMode(-1);
break;
case SDLK_RETURN:
myOSystem->frameBuffer().toggleFullscreen();
break;
#endif
case SDLK_g:
myOSystem->toggleFrameBuffer();
break;
myOSystem->frameBuffer().toggleFullscreen();
}
else
#endif
// These only work when in emulation mode
if(myState == S_EMULATE)
{
switch(int(key))
{
#ifndef MAC_OSX
case SDLK_EQUALS:
myOSystem->frameBuffer().changeVidMode(+1);
break;
case SDLK_MINUS:
myOSystem->frameBuffer().changeVidMode(-1);
break;
#endif
case SDLK_LEFTBRACKET:
myOSystem->sound().adjustVolume(-1);
break;
@ -457,8 +454,13 @@ void EventHandler::poll(uInt32 time)
*/
////////////////////////////////////////////////////////////////////////
#endif
default:
handled = false;
break;
}
}
else
handled = false;
}
else if(kbdControl(mod) && state)
{
@ -469,25 +471,6 @@ void EventHandler::poll(uInt32 time)
handleEvent(Event::Quit, 1);
break;
#ifdef MAC_OSX
case SDLK_h:
case SDLK_m:
case SDLK_SLASH:
handleMacOSXKeypress(int(key));
break;
case SDLK_EQUALS:
myOSystem->frameBuffer().changeVidMode(+1);
break;
case SDLK_MINUS:
myOSystem->frameBuffer().changeVidMode(-1);
break;
case SDLK_RETURN:
myOSystem->frameBuffer().toggleFullscreen();
break;
#endif
case SDLK_g:
// don't change grabmouse in fullscreen mode
if(!myOSystem->frameBuffer().fullScreen())
@ -497,6 +480,11 @@ void EventHandler::poll(uInt32 time)
myOSystem->frameBuffer().grabMouse(myGrabMouseFlag);
}
break;
#ifdef MAC_OSX
case SDLK_RETURN:
myOSystem->frameBuffer().toggleFullscreen();
break;
#endif
}
// These only work when in emulation mode
@ -504,6 +492,21 @@ void EventHandler::poll(uInt32 time)
{
switch(int(key))
{
#ifdef MAC_OSX
case SDLK_h:
case SDLK_m:
case SDLK_SLASH:
handleMacOSXKeypress(int(key));
break;
case SDLK_EQUALS:
myOSystem->frameBuffer().changeVidMode(+1);
break;
case SDLK_MINUS:
myOSystem->frameBuffer().changeVidMode(-1);
break;
#endif
case SDLK_0: // Ctrl-0 sets the mouse to paddle 0
setPaddleMode(0, true);
break;
@ -560,9 +563,20 @@ void EventHandler::poll(uInt32 time)
myOSystem->frameBuffer().showMessage("Error saving properties");
break;
}
default:
handled = false;
break;
}
}
else
handled = false;
}
else
handled = false;
// Don't pass the key on if we've already taken care of it
if(handled) break;
// Handle keys which switch eventhandler state
// Arrange the logic to take advantage of short-circuit evaluation
@ -1874,9 +1888,14 @@ bool EventHandler::enterDebugMode()
// mode, since it takes care of locking the debugger state, which will
// probably be modified below
myOSystem->debugger().setStartState();
setEventState(S_DEBUGGER);
myOSystem->createFrameBuffer();
if(!myOSystem->createFrameBuffer())
{
myOSystem->debugger().setQuitState();
setEventState(S_EMULATE);
myOSystem->frameBuffer().showMessage("Error creating debugger window, check dimensions");
return false;
}
myOverlay->reStack();
myOSystem->frameBuffer().setCursorState();
myOSystem->sound().mute(true);

View File

@ -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: FrameBuffer.cxx,v 1.133 2008-06-13 13:14:50 stephena Exp $
// $Id: FrameBuffer.cxx,v 1.134 2008-06-19 12:01:30 stephena Exp $
//============================================================================
#include <sstream>
@ -45,14 +45,17 @@ FrameBuffer::FrameBuffer(OSystem* osystem)
myUsePhosphor(false),
myPhosphorBlend(77),
myInitializedCount(0),
myPausedCount(0),
myFrameStatsEnabled(false)
myPausedCount(0)
{
myMsg.surface = myStatsMsg.surface = 0;
myMsg.enabled = myStatsMsg.enabled = false;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FrameBuffer::~FrameBuffer(void)
{
delete myMsg.surface;
delete myStatsMsg.surface;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -70,10 +73,6 @@ bool FrameBuffer::initialize(const string& title, uInt32 width, uInt32 height)
}
myInitializedCount++;
myBaseDim.x = myBaseDim.y = 0;
myBaseDim.w = (uInt16) width;
myBaseDim.h = (uInt16) height;
// Set fullscreen flag
#ifdef WINDOWED_SUPPORT
mySDLFlags = myOSystem->settings().getBool("fullscreen") ? SDL_FULLSCREEN : 0;
@ -81,20 +80,36 @@ bool FrameBuffer::initialize(const string& title, uInt32 width, uInt32 height)
mySDLFlags = 0;
#endif
cerr << " <== FrameBuffer::initialize: w = " << width << ", h = " << height << endl;
// Set the available video modes for this framebuffer
setAvailableVidModes();
setAvailableVidModes(width, height);
// Set window title and icon
setWindowTitle(title);
if(myInitializedCount == 1) setWindowIcon();
// Initialize video subsystem
// Initialize video subsystem (make sure we get a valid mode)
VideoMode mode = getSavedVidMode();
if(!initSubsystem(mode))
if(width <= mode.screen_w && height <= mode.screen_h)
{
cerr << "ERROR: Couldn't initialize video subsystem" << endl;
return false;
// Set window title and icon
setWindowTitle(title);
if(myInitializedCount == 1) setWindowIcon();
if(!initSubsystem(mode))
{
cerr << "ERROR: Couldn't initialize video subsystem" << endl;
return false;
}
else
{
myImageRect.setWidth(mode.image_w);
myImageRect.setHeight(mode.image_h);
myImageRect.moveTo(mode.image_x, mode.image_y);
myScreenRect.setWidth(mode.screen_w);
myScreenRect.setHeight(mode.screen_h);
}
}
else
return false;
// And refresh the display
myOSystem->eventHandler().refreshDisplay();
@ -104,7 +119,16 @@ bool FrameBuffer::initialize(const string& title, uInt32 width, uInt32 height)
SDL_EnableUNICODE(1);
// Erase any messages from a previous run
myMessage.counter = 0;
myMsg.counter = 0;
// Create surfaces for TIA statistics and general messages
myStatsMsg.color = kBtnTextColor;
myStatsMsg.w = myOSystem->consoleFont().getStringWidth("000 LINES %00.00 FPS");
myStatsMsg.h = myOSystem->consoleFont().getFontHeight();
if(!myStatsMsg.surface)
myStatsMsg.surface = createSurface(myStatsMsg.w, myStatsMsg.h);
if(!myMsg.surface)
myMsg.surface = createSurface(320, 15); // TODO - size depends on font used
// Finally, show some information about the framebuffer,
// but only on the first initialization
@ -132,19 +156,21 @@ void FrameBuffer::update()
// And update the screen
drawMediaSource();
#if 0
// Show frame statistics
if(myFrameStatsEnabled)
if(myStatsMsg.enabled)
{
// FIXME - sizes hardcoded for now; fix during UI refactoring
char msg[30];
sprintf(msg, "%u LINES %2.2f FPS",
myOSystem->console().mediaSource().scanlines(),
myOSystem->console().getFramerate());
fillRect(3, 3, 95, 9, kBGColor);
drawString(&myOSystem->font(), msg, 3, 3, 95, kBtnTextColor, kTextAlignCenter);
myStatsMsg.surface->fillRect(0, 0, myStatsMsg.w, myStatsMsg.h, kBGColor);
myStatsMsg.surface->drawString(&myOSystem->consoleFont(), msg, 0, 0,
myStatsMsg.w, myStatsMsg.color, kTextAlignLeft);
myStatsMsg.surface->addDirtyRect(0, 0, 0, 0);
myStatsMsg.surface->setPos(myImageRect.x() + 3, myImageRect.y() + 3);
myStatsMsg.surface->update();
}
#endif
break; // S_EMULATE
}
@ -203,7 +229,7 @@ void FrameBuffer::update()
}
// Draw any pending messages
if(myMessage.counter > 0)
if(myMsg.counter > 0)
drawMessage();
// The frame doesn't need to be completely redrawn anymore
@ -215,65 +241,67 @@ void FrameBuffer::showMessage(const string& message, MessagePosition position,
int color)
{
// Erase old messages on the screen
if(myMessage.counter > 0)
if(myMsg.counter > 0)
{
theRedrawTIAIndicator = true;
myOSystem->eventHandler().refreshDisplay();
}
// Precompute the message coordinates
myMessage.text = message;
myMessage.counter = uInt32(myOSystem->frameRate()) << 1; // Show message for 2 seconds
myMessage.color = color;
myMsg.text = message;
myMsg.counter = uInt32(myOSystem->frameRate()) << 1; // Show message for 2 seconds
myMsg.color = color;
myMessage.w = myOSystem->font().getStringWidth(myMessage.text) + 10;
myMessage.h = myOSystem->font().getFontHeight() + 8;
myMsg.w = myOSystem->font().getStringWidth(myMsg.text) + 10;
myMsg.h = myOSystem->font().getFontHeight() + 8;
myMsg.surface->setWidth(myMsg.w);
myMsg.surface->setHeight(myMsg.h);
switch(position)
{
case kTopLeft:
myMessage.x = 5;
myMessage.y = 5;
myMsg.x = 5;
myMsg.y = 5;
break;
case kTopCenter:
myMessage.x = (myBaseDim.w >> 1) - (myMessage.w >> 1);
myMessage.y = 5;
myMsg.x = (myImageRect.width() - myMsg.w) >> 1;
myMsg.y = 5;
break;
case kTopRight:
myMessage.x = myBaseDim.w - myMessage.w - 5;
myMessage.y = 5;
myMsg.x = myImageRect.width() - myMsg.w - 5;
myMsg.y = 5;
break;
case kMiddleLeft:
myMessage.x = 5;
myMessage.y = (myBaseDim.h >> 1) - (myMessage.h >> 1);
myMsg.x = 5;
myMsg.y = (myImageRect.height() - myMsg.h) >> 1;
break;
case kMiddleCenter:
myMessage.x = (myBaseDim.w >> 1) - (myMessage.w >> 1);
myMessage.y = (myBaseDim.h >> 1) - (myMessage.h >> 1);
myMsg.x = (myImageRect.width() - myMsg.w) >> 1;
myMsg.y = (myImageRect.height() - myMsg.h) >> 1;
break;
case kMiddleRight:
myMessage.x = myBaseDim.w - myMessage.w - 5;
myMessage.y = (myBaseDim.h >> 1) - (myMessage.h >> 1);
myMsg.x = myImageRect.width() - myMsg.w - 5;
myMsg.y = (myImageRect.height() - myMsg.h) >> 1;
break;
case kBottomLeft:
myMessage.x = 5;//(myMessage.w >> 1);
myMessage.y = myBaseDim.h - myMessage.h - 5;
myMsg.x = 5;
myMsg.y = myImageRect.height() - myMsg.h - 5;
break;
case kBottomCenter:
myMessage.x = (myBaseDim.w >> 1) - (myMessage.w >> 1);
myMessage.y = myBaseDim.h - myMessage.h - 5;
myMsg.x = (myImageRect.width() - myMsg.w) >> 1;
myMsg.y = myImageRect.height() - myMsg.h - 5;
break;
case kBottomRight:
myMessage.x = myBaseDim.w - myMessage.w - 5;
myMessage.y = myBaseDim.h - myMessage.h - 5;
myMsg.x = myImageRect.width() - myMsg.w - 5;
myMsg.y = myImageRect.height() - myMsg.h - 5;
break;
}
}
@ -288,7 +316,7 @@ void FrameBuffer::toggleFrameStats()
void FrameBuffer::showFrameStats(bool enable)
{
myOSystem->settings().setBool("stats", enable);
myFrameStatsEnabled = enable;
myStatsMsg.enabled = enable;
myOSystem->eventHandler().refreshDisplay();
}
@ -298,15 +326,15 @@ void FrameBuffer::enableMessages(bool enable)
if(enable)
{
// Only re-anable frame stats if they were already enabled before
myFrameStatsEnabled = myOSystem->settings().getBool("stats");
myStatsMsg.enabled = myOSystem->settings().getBool("stats");
}
else
{
// Temporarily disable frame stats
myFrameStatsEnabled = false;
myStatsMsg.enabled = false;
// Erase old messages on the screen
myMessage.counter = 0;
myMsg.counter = 0;
myOSystem->eventHandler().refreshDisplay(true); // Do this twice for
myOSystem->eventHandler().refreshDisplay(true); // double-buffered modes
@ -316,21 +344,23 @@ void FrameBuffer::enableMessages(bool enable)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
inline void FrameBuffer::drawMessage()
{
#if 0
// Draw the bounded box and text
fillRect(myMessage.x+1, myMessage.y+2, myMessage.w-2, myMessage.h-4, kBGColor);
box(myMessage.x, myMessage.y+1, myMessage.w, myMessage.h-2, kColor, kShadowColor);
drawString(&myOSystem->font(), myMessage.text, myMessage.x+1, myMessage.y+4,
myMessage.w, myMessage.color, kTextAlignCenter);
myMessage.counter--;
myMsg.surface->setPos(myMsg.x + myImageRect.x(), myMsg.y + myImageRect.y());
myMsg.surface->fillRect(0, 0, myMsg.w-2, myMsg.h-4, kBGColor);
myMsg.surface->box(0, 0, myMsg.w, myMsg.h-2, kColor, kShadowColor);
myMsg.surface->drawString(&myOSystem->font(), myMsg.text, 4, 4,
myMsg.w, myMsg.color, kTextAlignLeft);
myMsg.counter--;
// Either erase the entire message (when time is reached),
// or show again this frame
if(myMessage.counter == 0) // Force an immediate update
if(myMsg.counter == 0) // Force an immediate update
myOSystem->eventHandler().refreshDisplay(true);
else
addDirtyRect(myMessage.x, myMessage.y, myMessage.w, myMessage.h);
#endif
{
myMsg.surface->addDirtyRect(0, 0, 0, 0);
myMsg.surface->update();
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -420,18 +450,33 @@ void FrameBuffer::setFullscreen(bool enable)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool FrameBuffer::changeVidMode(int direction)
{
bool saveModeChange = true;
EventHandler::State state = myOSystem->eventHandler().state();
bool inUIMode = (state == EventHandler::S_DEBUGGER ||
state == EventHandler::S_LAUNCHER);
// Only save mode changes in TIA mode with a valid selector
bool saveModeChange = !inUIMode && (direction == -1 || direction == +1);
VideoMode oldmode = myCurrentModeList->current();
if(direction == +1)
myCurrentModeList->next();
else if(direction == -1)
myCurrentModeList->previous();
else
saveModeChange = false; // no resolution or zoom level actually changed
if(!inUIMode)
{
if(direction == +1)
myCurrentModeList->next();
else if(direction == -1)
myCurrentModeList->previous();
}
VideoMode newmode = myCurrentModeList->current();
if(!setVidMode(newmode))
if(setVidMode(newmode))
{
myImageRect.setWidth(newmode.image_w);
myImageRect.setHeight(newmode.image_h);
myImageRect.moveTo(newmode.image_x, newmode.image_y);
myScreenRect.setWidth(newmode.screen_w);
myScreenRect.setHeight(newmode.screen_h);
}
else
return false;
myOSystem->eventHandler().handleResizeEvent();
@ -439,26 +484,10 @@ bool FrameBuffer::changeVidMode(int direction)
setCursorState();
showMessage(newmode.name);
if(saveModeChange)
if(!inUIMode && saveModeChange)
{
// Determine which mode we're in, and save to the appropriate setting
if(fullScreen())
{
myOSystem->settings().setSize("fullres", newmode.screen_w, newmode.screen_h);
}
else
{
EventHandler::State state = myOSystem->eventHandler().state();
bool inTIAMode = (state == EventHandler::S_EMULATE ||
state == EventHandler::S_PAUSE ||
state == EventHandler::S_MENU ||
state == EventHandler::S_CMDMENU);
if(inTIAMode)
myOSystem->settings().setInt("zoom_tia", newmode.zoom);
//FIXME else
// myOSystem->settings().setInt("zoom_ui", newmode.zoom);
}
// FIXME - adapt to scaler infrastructure
myOSystem->settings().setInt("zoom_tia", newmode.zoom);
}
return true;
/*
@ -595,14 +624,15 @@ uInt8 FrameBuffer::getPhosphor(uInt8 c1, uInt8 c2)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 FrameBuffer::maxWindowSizeForScreen(uInt32 screenWidth, uInt32 screenHeight)
uInt32 FrameBuffer::maxWindowSizeForScreen(uInt32 baseWidth, uInt32 baseHeight,
uInt32 screenWidth, uInt32 screenHeight)
{
uInt32 multiplier = 1;
for(;;)
{
// Figure out the zoomed size of the window
uInt32 width = myBaseDim.w * multiplier;
uInt32 height = myBaseDim.h * multiplier;
uInt32 width = baseWidth * multiplier;
uInt32 height = baseHeight * multiplier;
if((width > screenWidth) || (height > screenHeight))
break;
@ -613,27 +643,49 @@ uInt32 FrameBuffer::maxWindowSizeForScreen(uInt32 screenWidth, uInt32 screenHeig
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::setAvailableVidModes()
void FrameBuffer::setAvailableVidModes(uInt32 baseWidth, uInt32 baseHeight)
{
// Modelists are different depending on what state we're in
EventHandler::State state = myOSystem->eventHandler().state();
bool inUIMode = (state == EventHandler::S_DEBUGGER ||
state == EventHandler::S_LAUNCHER);
// First we look at windowed modes
// These can be sized exactly as required, since there's normally no
// restriction on window size (up the maximum size)
myWindowedModeList.clear();
int max_zoom = maxWindowSizeForScreen(myOSystem->desktopWidth(),
myOSystem->desktopHeight());
for(int i = 1; i <= max_zoom; ++i)
// In UI/windowed mode, there's only one valid video mode we can use
if(inUIMode)
{
VideoMode m;
m.image_x = m.image_y = 0;
m.image_w = m.screen_w = myBaseDim.w * i;
m.image_h = m.screen_h = myBaseDim.h * i;
m.zoom = i;
ostringstream buf;
buf << "Zoom " << i << "x";
m.name = buf.str();
m.image_w = m.screen_w = baseWidth;
m.image_h = m.screen_h = baseHeight;
m.zoom = 1;
myWindowedModeList.add(m);
}
else
{
// FIXME - scan list of scalers, see which ones are appropriate
// for the given dimensions
int max_zoom = maxWindowSizeForScreen(baseWidth, baseHeight,
myOSystem->desktopWidth(), myOSystem->desktopHeight());
for(int i = 1; i <= max_zoom; ++i)
{
VideoMode m;
m.image_x = m.image_y = 0;
m.image_w = m.screen_w = baseWidth * i;
m.image_h = m.screen_h = baseHeight * i;
m.zoom = i;
ostringstream buf;
buf << "Zoom " << i << "x";
m.name = buf.str();
myWindowedModeList.add(m);
}
}
// Now consider the fullscreen modes
// There are often stricter requirements on these, and they're normally
@ -641,35 +693,63 @@ void FrameBuffer::setAvailableVidModes()
// As well, we usually can't get fullscreen modes in the exact size
// we want, so we need to calculate image offsets
myFullscreenModeList.clear();
const ResolutionList& res = myOSystem->supportedResolutions();
for(unsigned int i = 0; i < res.size(); ++i)
if(inUIMode)
{
VideoMode m;
m.screen_w = res[i].width;
m.screen_h = res[i].height;
m.zoom = maxWindowSizeForScreen(m.screen_w, m.screen_h);
m.name = res[i].name;
// FIXME - document this
if(0)// use exact dimensions)
{
VideoMode m;
m.image_w = m.screen_w = baseWidth;
m.image_h = m.screen_h = baseHeight;
m.zoom = 1;
// Auto-calculate 'smart' centering; platform-specific framebuffers are
// free to ignore or augment it
m.image_w = myBaseDim.w * m.zoom;
m.image_h = myBaseDim.h * m.zoom;
m.image_x = (m.screen_w - m.image_w) / 2;
m.image_y = (m.screen_h - m.image_h) / 2;
myFullscreenModeList.add(m);
}
else // use dimensions as defined in 'fullres'
{
int w = -1, h = -1;
myOSystem->settings().getSize("fullres", w, h);
if(w < 0 || h < 0)
{
w = myOSystem->desktopWidth();
h = myOSystem->desktopHeight();
}
/*
cerr << "Fullscreen modes:" << endl
<< " Mode " << i << endl
<< " screen w = " << m.screen_w << endl
<< " screen h = " << m.screen_h << endl
<< " image x = " << m.image_x << endl
<< " image y = " << m.image_y << endl
<< " image w = " << m.image_w << endl
<< " image h = " << m.image_h << endl
<< " zoom = " << m.zoom << endl
<< endl;
*/
myFullscreenModeList.add(m);
VideoMode m;
m.screen_w = w;
m.screen_h = h;
m.zoom = 1;
// Auto-calculate 'smart' centering; platform-specific framebuffers are
// free to ignore or augment it
m.image_w = baseWidth;
m.image_h = baseHeight;
m.image_x = (m.screen_w - m.image_w) / 2;
m.image_y = (m.screen_h - m.image_h) / 2;
myFullscreenModeList.add(m);
}
}
else
{
const ResolutionList& res = myOSystem->supportedResolutions();
for(unsigned int i = 0; i < res.size(); ++i)
{
VideoMode m;
m.screen_w = res[i].width;
m.screen_h = res[i].height;
m.zoom = maxWindowSizeForScreen(baseWidth, baseHeight, m.screen_w, m.screen_h);
m.name = res[i].name;
// Auto-calculate 'smart' centering; platform-specific framebuffers are
// free to ignore or augment it
m.image_w = baseWidth * m.zoom;
m.image_h = baseHeight * m.zoom;
m.image_x = (m.screen_w - m.image_w) / 2;
m.image_y = (m.screen_h - m.image_h) / 2;
myFullscreenModeList.add(m);
}
}
}
@ -679,52 +759,21 @@ VideoMode FrameBuffer::getSavedVidMode()
EventHandler::State state = myOSystem->eventHandler().state();
if(myOSystem->settings().getBool("fullscreen"))
{
// Point the modelist to fullscreen modes, and set the iterator to
// the mode closest to the given resolution
int w = -1, h = -1;
myOSystem->settings().getSize("fullres", w, h);
if(w < 0 || h < 0)
{
w = myOSystem->desktopWidth();
h = myOSystem->desktopHeight();
}
// The launcher and debugger modes are different, in that their size is
// set at program launch and can't be changed
// In these cases, the resolution must accommodate their size
if(state == EventHandler::S_LAUNCHER)
{
int lw, lh;
myOSystem->settings().getSize("launcherres", lw, lh);
w = BSPF_max(w, lw);
h = BSPF_max(h, lh);
}
#ifdef DEBUGGER_SUPPORT
else if(state == EventHandler::S_DEBUGGER)
{
int lw, lh;
myOSystem->settings().getSize("debuggerres", lw, lh);
w = BSPF_max(w, lw);
h = BSPF_max(h, lh);
}
#endif
myCurrentModeList = &myFullscreenModeList;
myCurrentModeList->setByResolution(w, h);
else
myCurrentModeList = &myWindowedModeList;
// Now select the best resolution depending on the state
// UI modes (launcher and debugger) have only one supported resolution
// so the 'current' one is the only valid one
if(state == EventHandler::S_DEBUGGER || state == EventHandler::S_LAUNCHER)
{
myCurrentModeList->setByZoom(1);
}
else
{
// Point the modelist to windowed modes, and set the iterator to
// the mode closest to the given zoom level
bool inTIAMode = (state == EventHandler::S_EMULATE ||
state == EventHandler::S_PAUSE ||
state == EventHandler::S_MENU ||
state == EventHandler::S_CMDMENU);
int zoom = (inTIAMode ? myOSystem->settings().getInt("zoom_tia") : 1);
//FIXME myOSystem->settings().getInt("zoom_ui") );
myCurrentModeList = &myWindowedModeList;
// FIXME - get dimensions from scaler
int zoom = myOSystem->settings().getInt("zoom_tia");
myCurrentModeList->setByZoom(zoom);
}

View File

@ -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: FrameBuffer.hxx,v 1.97 2008-06-13 13:14:51 stephena Exp $
// $Id: FrameBuffer.hxx,v 1.98 2008-06-19 12:01:30 stephena Exp $
//============================================================================
#ifndef FRAMEBUFFER_HXX
@ -27,11 +27,12 @@ class Console;
namespace GUI {
class Font;
class Surface;
class Rect;
}
#include "EventHandler.hxx"
#include "VideoModeList.hxx"
#include "Rect.hxx"
#include "bspf.hxx"
// Different types of framebuffer derived objects
@ -89,7 +90,7 @@ enum {
turn drawn here as well.
@author Stephen Anthony
@version $Id: FrameBuffer.hxx,v 1.97 2008-06-13 13:14:51 stephena Exp $
@version $Id: FrameBuffer.hxx,v 1.98 2008-06-19 12:01:30 stephena Exp $
*/
class FrameBuffer
{
@ -150,34 +151,18 @@ class FrameBuffer
void enableMessages(bool enable);
/**
Returns the current width of the framebuffer *before* any scaling.
@return The current unscaled width
Returns the current dimensions of the framebuffer image.
Note that this will take into account the current scaling (if any)
as well as image 'centering'.
*/
inline const uInt32 baseWidth() { return myBaseDim.w; }
inline const GUI::Rect& imageRect() const { return myImageRect; }
/**
Returns the current height of the framebuffer *before* any scaling.
@return The current unscaled height
Returns the current dimensions of the framebuffer window.
This is the entire area containing the framebuffer image as well as any
'unusable' area.
*/
inline const uInt32 baseHeight() { return myBaseDim.h; }
/**
Returns the current width of the framebuffer image.
Note that this will take into account the current scaling (if any).
@return The current width
*/
inline const uInt32 imageWidth() { return myImageDim.w; }
/**
Returns the current height of the framebuffer image.
Note that this will take into account the current scaling (if any).
@return The current height
*/
inline const uInt32 imageHeight() { return myImageDim.h; }
inline const GUI::Rect& screenRect() const { return myScreenRect; }
/**
Indicates that the TIA area is dirty, and certain areas need
@ -300,15 +285,22 @@ class FrameBuffer
/**
This method is called to initialize the video subsystem
with the given video mode. Normally, it will also call setVidMode().
@param mode The video mode to use
@return False on any errors, else true
*/
virtual bool initSubsystem(VideoMode mode) = 0;
virtual bool initSubsystem(VideoMode& mode) = 0;
/**
This method is called to change to the given video mode.
This method is called to change to the given video mode. If the mode
is successfully changed, 'mode' holds the actual dimensions used.
@param mode The video mode to use for rendering the mediasource
@param mode The video mode to use
@return False on any errors (in which case 'mode' is invalid), else true
*/
virtual bool setVidMode(VideoMode mode) = 0;
virtual bool setVidMode(VideoMode& mode) = 0;
/**
Switches between the filtering options in the video subsystem.
@ -345,18 +337,6 @@ class FrameBuffer
// Amount to blend when using phosphor effect
int myPhosphorBlend;
// Dimensions of the base image, before scaling.
// All external GUI items should refer to these dimensions,
// since this is the *real* size of the image.
// The other sizes are simply scaled versions of these dimensions.
SDL_Rect myBaseDim;
// Dimensions of the actual image, after zooming
SDL_Rect myImageDim;
// Dimensions of the SDL window (not always the same as the image)
SDL_Rect myScreenDim;
// TIA palettes for normal and phosphor modes
Uint32 myDefPalette[256+kNumColors];
Uint32 myAvgPalette[256][256];
@ -386,13 +366,14 @@ class FrameBuffer
Calculate the maximum level by which the base window can be zoomed and
still fit in the given screen dimensions.
*/
uInt32 maxWindowSizeForScreen(uInt32 screenWidth, uInt32 screenHeight);
uInt32 maxWindowSizeForScreen(uInt32 baseWidth, uInt32 baseHeight,
uInt32 screenWidth, uInt32 screenHeight);
/**
Set all possible video modes (both windowed and fullscreen) available for
this framebuffer based on current emulation state and maximum window size.
this framebuffer based on given image dimensions and maximum window size.
*/
void setAvailableVidModes();
void setAvailableVidModes(uInt32 basewidth, uInt32 baseheight);
/**
Returns an appropriate video mode based on the current eventhandler
@ -409,18 +390,25 @@ class FrameBuffer
// Used to set intervals between messages while in pause mode
uInt32 myPausedCount;
// Used for onscreen messages
// Dimensions of the actual image, after zooming, and taking into account
// any image 'centering'
GUI::Rect myImageRect;
// Dimensions of the SDL window (not always the same as the image)
GUI::Rect myScreenRect;
// Used for onscreen messages and frame statistics
// (scanline count and framerate)
struct Message {
string text;
int counter;
int x, y, w, h;
uInt32 color;
FBSurface* surface;
bool enabled;
};
Message myMessage;
// Used to show frame statistics (scanline count and framerate)
Message myFrameStats;
bool myFrameStatsEnabled;
Message myMsg;
Message myStatsMsg;
// The list of all available video modes for this framebuffer
VideoModeList myWindowedModeList;
@ -438,7 +426,7 @@ class FrameBuffer
FrameBuffer type.
@author Stephen Anthony
@version $Id: FrameBuffer.hxx,v 1.97 2008-06-13 13:14:51 stephena Exp $
@version $Id: FrameBuffer.hxx,v 1.98 2008-06-19 12:01:30 stephena Exp $
*/
// Text alignment modes for drawString()
enum TextAlignment {
@ -533,9 +521,9 @@ class FBSurface
virtual void addDirtyRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h) = 0;
/**
This method should be called to center the position of the surface.
This method answers the current position of the surface.
*/
virtual void centerPos() = 0;
virtual void getPos(uInt32& x, uInt32& y) const = 0;
/**
This method should be called to set the position of the surface.
@ -543,9 +531,14 @@ class FBSurface
virtual void setPos(uInt32 x, uInt32 y) = 0;
/**
This method answers the current coordinates of the surface.
This method sets the width of the drawable area of the surface.
*/
virtual void getPos(uInt32& x, uInt32& y) const = 0;
virtual void setWidth(uInt32 w) = 0;
/**
This method sets the width of the drawable area of the surface.
*/
virtual void setHeight(uInt32 h) = 0;
/**
This method should be called to translate the given coordinates

View File

@ -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: ContextMenu.cxx,v 1.2 2008-06-15 15:44:30 stephena Exp $
// $Id: ContextMenu.cxx,v 1.3 2008-06-19 12:01:31 stephena Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
@ -79,6 +79,14 @@ void ContextMenu::show(uInt32 x, uInt32 y, int item)
// Make sure position is set *after* the dialog is added, since the surface
// may not exist before then
parent().addDialog(this);
// Are we in the current screen bounds?
const GUI::Rect& image = instance().frameBuffer().imageRect();
uInt32 dx = image.x() + image.width();
uInt32 dy = image.y() + image.height();
if(x + _w > dx) x -= (x + _w - dx);
if(y + _h > dy) y -= (y + _h - dy);
surface().setPos(x, y);
setSelected(item);
}
@ -280,14 +288,6 @@ void ContextMenu::moveDown()
drawCurrentSelection(++item);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void ContextMenu::center()
{
// Adjust dialog, making sure it doesn't fall outside screen area
// FIXME - add code to do this ...
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void ContextMenu::drawDialog()
{
@ -320,7 +320,7 @@ void ContextMenu::drawDialog()
if(_entries.size() & 1) n++;
if(i >= n)
{
x = _x + 2 + _w / 2;
x = _x + 1 + _w / 2;
y = _y + 2 + _rowHeight * (i - n);
}
else
@ -328,7 +328,7 @@ void ContextMenu::drawDialog()
x = _x + 2;
y = _y + 2 + _rowHeight * i;
}
w = _w / 2 - 2;
w = _w / 2 - 3;
}
else
{

View File

@ -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: ContextMenu.hxx,v 1.2 2008-06-15 15:44:30 stephena Exp $
// $Id: ContextMenu.hxx,v 1.3 2008-06-19 12:01:31 stephena Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
@ -66,7 +66,7 @@ class ContextMenu : public Dialog, public CommandSender
const string& getSelectedString() const;
/** This dialog uses its own positioning, so we override Dialog::center() */
void center();
void center() { }
protected:
void handleMouseDown(int x, int y, int button, int clickCount);

View File

@ -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: Dialog.cxx,v 1.61 2008-06-13 13:14:51 stephena Exp $
// $Id: Dialog.cxx,v 1.62 2008-06-19 12:01:31 stephena Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
@ -106,8 +106,13 @@ void Dialog::close()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Dialog::center()
{
if(_center && _surface)
_surface->centerPos();
if(_surface)
{
const GUI::Rect& screen = instance().frameBuffer().screenRect();
uInt32 x = (screen.width() - getWidth()) >> 1;
uInt32 y = (screen.height() - getHeight()) >> 1;
_surface->setPos(x, y);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -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: Launcher.cxx,v 1.23 2008-05-30 19:07:55 stephena Exp $
// $Id: Launcher.cxx,v 1.24 2008-06-19 12:01:31 stephena Exp $
//============================================================================
#include <sstream>
@ -31,8 +31,8 @@ class Properties;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Launcher::Launcher(OSystem* osystem)
: DialogContainer(osystem),
myWidth(400),
myHeight(300)
myWidth(640),
myHeight(480)
{
int w, h;
myOSystem->settings().getSize("launcherres", w, h);
@ -40,9 +40,9 @@ Launcher::Launcher(OSystem* osystem)
myHeight = BSPF_max(h, 0);
// Error check the resolution
myWidth = BSPF_max(myWidth, 320u);
myWidth = BSPF_max(myWidth, 640u);
myWidth = BSPF_min(myWidth, osystem->desktopWidth());
myHeight = BSPF_max(myHeight, 240u);
myHeight = BSPF_max(myHeight, 480u);
myHeight = BSPF_min(myHeight, osystem->desktopHeight());
myOSystem->settings().setSize("launcherres", myWidth, myHeight);

View File

@ -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: PopUpWidget.cxx,v 1.40 2008-06-13 13:14:51 stephena Exp $
// $Id: PopUpWidget.cxx,v 1.41 2008-06-19 12:01:31 stephena Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
@ -81,12 +81,11 @@ void PopUpWidget::handleMouseDown(int x, int y, int button, int clickCount)
if(isEnabled())
{
// Add menu just underneath parent widget
uInt32 x, y;
dialog().surface().getPos(x, y);
x += getAbsX() + _labelWidth;
y += getAbsY() + getHeight();
myMenu->show(x, y, myMenu->getSelected());
uInt32 tx, ty;
dialog().surface().getPos(tx, ty);
tx += getAbsX() + _labelWidth;
ty += getAbsY() + getHeight();
myMenu->show(tx, ty, myMenu->getSelected());
}
}

View File

@ -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: Rect.hxx,v 1.6 2008-02-06 13:45:24 stephena Exp $
// $Id: Rect.hxx,v 1.7 2008-06-19 12:01:31 stephena Exp $
//
// Based on code from ScummVM - Scumm Interpreter
// Copyright (C) 2002-2004 The ScummVM project
@ -72,8 +72,10 @@ struct Rect
{
assert(isValidRect());
}
int width() const { return right - left; }
int height() const { return bottom - top; }
inline int x() const { return left; }
inline int y() const { return top; }
inline int width() const { return right - left; }
inline int height() const { return bottom - top; }
void setWidth(int aWidth) {
right = left + aWidth;

View File

@ -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.cxx,v 1.8 2008-06-13 13:14:51 stephena Exp $
// $Id: RomInfoWidget.cxx,v 1.9 2008-06-19 12:01:31 stephena Exp $
//============================================================================
#include <cstring>
@ -31,7 +31,7 @@
RomInfoWidget::RomInfoWidget(GuiObject* boss, const GUI::Font& font,
int x, int y, int w, int h)
: Widget(boss, font, x, y, w, h),
mySurface(NULL),
// mySurface(NULL),
myDrawSurface(false),
myHaveProperties(false)
{
@ -42,11 +42,13 @@ RomInfoWidget::RomInfoWidget(GuiObject* boss, const GUI::Font& font,
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
RomInfoWidget::~RomInfoWidget()
{
/*
if(mySurface)
{
delete mySurface;
mySurface = NULL;
}
*/
myRomInfo.clear();
}
@ -93,8 +95,8 @@ void RomInfoWidget::clearProperties()
void RomInfoWidget::initialize()
{
// Delete surface; a new one will be created by parseProperties
delete mySurface;
mySurface = NULL;
// delete mySurface;
// mySurface = NULL;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -280,12 +282,12 @@ bool RomInfoWidget::parseIHDR(int& width, int& height, uInt8* data, int size)
return memcmp(trailer, data + 8, 5) == 0;
}
// FIXME
#if 0
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool RomInfoWidget::parseIDATChunk(const FrameBuffer& fb, GUI::Surface* surface,
int width, int height, uInt8* data, int size)
{
// FIXME
#if 0
// The entire decompressed image data
uLongf bufsize = (width * 3 + 1) * height;
uInt8* buffer = new uInt8[bufsize];
@ -304,8 +306,8 @@ bool RomInfoWidget::parseIDATChunk(const FrameBuffer& fb, GUI::Surface* surface,
}
delete[] buffer;
return false;
#endif
}
#endif
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string RomInfoWidget::parseTextChunk(uInt8* data, int size)

View File

@ -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.4 2008-03-13 22:58:07 stephena Exp $
// $Id: RomInfoWidget.hxx,v 1.5 2008-06-19 12:01:31 stephena Exp $
//============================================================================
#ifndef ROM_INFO_WIDGET_HXX
@ -21,8 +21,6 @@
#include <fstream>
class GUI::Surface;
#include "Props.hxx"
#include "Widget.hxx"
#include "Command.hxx"
@ -50,13 +48,13 @@ class RomInfoWidget : public Widget
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(const FrameBuffer& fb, GUI::Surface* surface,
int width, int height, uInt8* data, int size);
// static bool parseIDATChunk(const FrameBuffer& fb, GUI::Surface* surface,
// int width, int height, uInt8* data, int size);
static string parseTextChunk(uInt8* data, int size);
private:
// Surface holding the scaled PNG image
GUI::Surface* mySurface;
// GUI::Surface* mySurface;
// Whether the surface should be redrawn by drawWidget()
bool myDrawSurface;