diff --git a/stella/src/common/FrameBufferGL.cxx b/stella/src/common/FrameBufferGL.cxx index 6a18bc211..54023d96a 100644 --- a/stella/src/common/FrameBufferGL.cxx +++ b/stella/src/common/FrameBufferGL.cxx @@ -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) diff --git a/stella/src/common/FrameBufferGL.hxx b/stella/src/common/FrameBufferGL.hxx index 3c508a3fa..b66d37b02 100644 --- a/stella/src/common/FrameBufferGL.hxx +++ b/stella/src/common/FrameBufferGL.hxx @@ -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(); diff --git a/stella/src/common/FrameBufferSoft.cxx b/stella/src/common/FrameBufferSoft.cxx index 62f69f3cc..6216d37a5 100644 --- a/stella/src/common/FrameBufferSoft.cxx +++ b/stella/src/common/FrameBufferSoft.cxx @@ -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 @@ -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; diff --git a/stella/src/common/FrameBufferSoft.hxx b/stella/src/common/FrameBufferSoft.hxx index 7eb6f7fe2..c40be716a 100644 --- a/stella/src/common/FrameBufferSoft.hxx +++ b/stella/src/common/FrameBufferSoft.hxx @@ -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(); diff --git a/stella/src/common/Snapshot.cxx b/stella/src/common/Snapshot.cxx index 6024f1d14..5819319e3 100644 --- a/stella/src/common/Snapshot.cxx +++ b/stella/src/common/Snapshot.cxx @@ -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 @@ -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()) diff --git a/stella/src/common/VideoModeList.hxx b/stella/src/common/VideoModeList.hxx index 5e302f4f8..c30cfff40 100644 --- a/stella/src/common/VideoModeList.hxx +++ b/stella/src/common/VideoModeList.hxx @@ -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::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 myModeList; int myIdx; diff --git a/stella/src/debugger/gui/RomListWidget.cxx b/stella/src/debugger/gui/RomListWidget.cxx index 8285cbd61..0208f3af9 100644 --- a/stella/src/debugger/gui/RomListWidget.cxx +++ b/stella/src/debugger/gui/RomListWidget.cxx @@ -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); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/stella/src/debugger/gui/TiaOutputWidget.cxx b/stella/src/debugger/gui/TiaOutputWidget.cxx index aaaf157c2..cd9223cff 100644 --- a/stella/src/debugger/gui/TiaOutputWidget.cxx +++ b/stella/src/debugger/gui/TiaOutputWidget.cxx @@ -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); } } diff --git a/stella/src/debugger/gui/TiaZoomWidget.cxx b/stella/src/debugger/gui/TiaZoomWidget.cxx index 5e13660e1..523898099 100644 --- a/stella/src/debugger/gui/TiaZoomWidget.cxx +++ b/stella/src/debugger/gui/TiaZoomWidget.cxx @@ -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); + } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/stella/src/emucore/EventHandler.cxx b/stella/src/emucore/EventHandler.cxx index 31f129035..91fdc3a43 100644 --- a/stella/src/emucore/EventHandler.cxx +++ b/stella/src/emucore/EventHandler.cxx @@ -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 @@ -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); diff --git a/stella/src/emucore/FrameBuffer.cxx b/stella/src/emucore/FrameBuffer.cxx index 69ee685c6..060a46e81 100644 --- a/stella/src/emucore/FrameBuffer.cxx +++ b/stella/src/emucore/FrameBuffer.cxx @@ -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 @@ -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); } diff --git a/stella/src/emucore/FrameBuffer.hxx b/stella/src/emucore/FrameBuffer.hxx index 967c8e264..8f22b2cfb 100644 --- a/stella/src/emucore/FrameBuffer.hxx +++ b/stella/src/emucore/FrameBuffer.hxx @@ -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 diff --git a/stella/src/gui/ContextMenu.cxx b/stella/src/gui/ContextMenu.cxx index 71838d281..6928ebda8 100644 --- a/stella/src/gui/ContextMenu.cxx +++ b/stella/src/gui/ContextMenu.cxx @@ -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 { diff --git a/stella/src/gui/ContextMenu.hxx b/stella/src/gui/ContextMenu.hxx index c10fae7a7..3eb04f3a7 100644 --- a/stella/src/gui/ContextMenu.hxx +++ b/stella/src/gui/ContextMenu.hxx @@ -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); diff --git a/stella/src/gui/Dialog.cxx b/stella/src/gui/Dialog.cxx index 9af15b2a7..3a252000d 100644 --- a/stella/src/gui/Dialog.cxx +++ b/stella/src/gui/Dialog.cxx @@ -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); + } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/stella/src/gui/Launcher.cxx b/stella/src/gui/Launcher.cxx index 99cfb2c48..d92314c79 100644 --- a/stella/src/gui/Launcher.cxx +++ b/stella/src/gui/Launcher.cxx @@ -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 @@ -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); diff --git a/stella/src/gui/PopUpWidget.cxx b/stella/src/gui/PopUpWidget.cxx index 72ec2cf89..8ae0c4784 100644 --- a/stella/src/gui/PopUpWidget.cxx +++ b/stella/src/gui/PopUpWidget.cxx @@ -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()); } } diff --git a/stella/src/gui/Rect.hxx b/stella/src/gui/Rect.hxx index a00246214..312a20b57 100644 --- a/stella/src/gui/Rect.hxx +++ b/stella/src/gui/Rect.hxx @@ -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; diff --git a/stella/src/gui/RomInfoWidget.cxx b/stella/src/gui/RomInfoWidget.cxx index e24321d1d..cf9c7b171 100644 --- a/stella/src/gui/RomInfoWidget.cxx +++ b/stella/src/gui/RomInfoWidget.cxx @@ -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 @@ -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) diff --git a/stella/src/gui/RomInfoWidget.hxx b/stella/src/gui/RomInfoWidget.hxx index 3b45f22da..968c18735 100644 --- a/stella/src/gui/RomInfoWidget.hxx +++ b/stella/src/gui/RomInfoWidget.hxx @@ -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 -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;