From 45d0740819e8126043af968c83927847fcae16b2 Mon Sep 17 00:00:00 2001 From: stephena Date: Wed, 5 Feb 2014 22:09:57 +0000 Subject: [PATCH] Some reorganization of the FrameBuffer classes, to move all SDL-related stuff into FrameBufferSDL2 only. This will make conversion to actual SDL2 code much easier, since it won't be touching any of the core emulation code in src/emucore. Next TODO is something similar for EventHandler (which uses SDL heavily and is too tied to a core class). git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@2846 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba --- src/common/FrameBufferSDL2.cxx | 97 ++++++++++++++++++--- src/common/FrameBufferSDL2.hxx | 8 ++ src/debugger/Debugger.cxx | 2 +- src/emucore/Console.cxx | 2 +- src/emucore/FrameBuffer.cxx | 102 ++++++++++++++++++---- src/emucore/FrameBuffer.hxx | 71 +++++++++++++-- src/emucore/OSystem.cxx | 153 ++------------------------------- src/emucore/OSystem.hxx | 79 ++--------------- src/gui/AudioDialog.cxx | 2 +- src/gui/CommandDialog.cxx | 2 +- src/gui/GameInfoDialog.cxx | 2 +- src/gui/GlobalPropsDialog.cxx | 2 +- src/gui/Launcher.cxx | 2 +- src/gui/LauncherDialog.cxx | 21 ++--- src/gui/LoggerDialog.cxx | 7 +- src/gui/OptionsDialog.cxx | 2 +- src/gui/RomAuditDialog.cxx | 4 +- src/gui/RomInfoWidget.cxx | 2 +- src/gui/UIDialog.cxx | 2 +- src/gui/VideoDialog.cxx | 7 +- 20 files changed, 285 insertions(+), 284 deletions(-) diff --git a/src/common/FrameBufferSDL2.cxx b/src/common/FrameBufferSDL2.cxx index b507854d9..60b112887 100644 --- a/src/common/FrameBufferSDL2.cxx +++ b/src/common/FrameBufferSDL2.cxx @@ -44,10 +44,15 @@ FrameBufferSDL2::FrameBufferSDL2(OSystem* osystem) myTiaSurface(NULL), myDirtyFlag(true) { - // Added from MediaFactory ///////////////////////// - const string& gl_lib = osystem->settings().getString("gl_lib"); - loadLibrary(gl_lib); - //////////////////////////////////////////////////// + // Initialize SDL2 context + if(SDL_WasInit(SDL_INIT_VIDEO) == 0) + if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0) + return; + + // Load OpenGL function pointers + loadLibrary(osystem->settings().getString("gl_lib")); + if(loadFuncs(kGL_BASIC)) + myVBOAvailable = myOSystem->settings().getBool("gl_vbo") && loadFuncs(kGL_VBO); // We need a pixel format for palette value calculations // It's done this way (vs directly accessing a FBSurfaceUI object) @@ -143,6 +148,81 @@ bool FrameBufferSDL2::loadFuncs(GLFunctionality functionality) return true; } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +bool FrameBufferSDL2::queryHardware(uInt32& w, uInt32& h, ResolutionList& res) +{ + // First get the maximum windowed desktop resolution + // Check the 'maxres' setting, which is an undocumented developer feature + // that specifies the desktop size + // Normally, this wouldn't be set, and we ask SDL directly + const GUI::Size& s = myOSystem->settings().getSize("maxres"); + if(s.w <= 0 || s.h <= 0) + { + const SDL_VideoInfo* info = SDL_GetVideoInfo(); + w = info->current_w; + h = info->current_h; + } + +#if 0 + // Various parts of the codebase assume a minimum screen size of 320x240 + if(!(myDesktopWidth >= 320 && myDesktopHeight >= 240)) + { + logMessage("ERROR: queryVideoHardware failed, " + "window 320x240 or larger required", 0); + return false; + } + + // Then get the valid fullscreen modes + // If there are any errors, just use the desktop resolution + ostringstream buf; + SDL_Rect** modes = SDL_ListModes(NULL, SDL_FULLSCREEN); + if((modes == (SDL_Rect**)0) || (modes == (SDL_Rect**)-1)) + { + Resolution r; + r.width = myDesktopWidth; + r.height = myDesktopHeight; + buf << r.width << "x" << r.height; + r.name = buf.str(); + myResolutions.push_back(r); + } + else + { + // All modes must fit between the lower and upper limits of the desktop + // For 'small' desktop, this means larger than 320x240 + // For 'large'/normal desktop, exclude all those less than 640x480 + bool largeDesktop = myDesktopWidth >= 640 && myDesktopHeight >= 480; + uInt32 lowerWidth = largeDesktop ? 640 : 320, + lowerHeight = largeDesktop ? 480 : 240; + for(uInt32 i = 0; modes[i]; ++i) + { + if(modes[i]->w >= lowerWidth && modes[i]->w <= myDesktopWidth && + modes[i]->h >= lowerHeight && modes[i]->h <= myDesktopHeight) + { + Resolution r; + r.width = modes[i]->w; + r.height = modes[i]->h; + buf.str(""); + buf << r.width << "x" << r.height; + r.name = buf.str(); + myResolutions.insert_at(0, r); // insert in opposite (of descending) order + } + } + // If no modes were valid, use the desktop dimensions + if(myResolutions.size() == 0) + { + Resolution r; + r.width = myDesktopWidth; + r.height = myDesktopHeight; + buf << r.width << "x" << r.height; + r.name = buf.str(); + myResolutions.push_back(r); + } + } +#endif + + return true; +} + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bool FrameBufferSDL2::initSubsystem(VideoMode& mode, bool full) { @@ -288,18 +368,13 @@ bool FrameBufferSDL2::setVidMode(VideoMode& mode) myScreen = SDL_SetVideoMode(mode.screen_w, mode.screen_h, 0, mySDLFlags); if(myScreen == NULL) { - cerr << "ERROR: Unable to open SDL window: " << SDL_GetError() << endl; + string msg = "ERROR: Unable to open SDL window: " + string(SDL_GetError()); + myOSystem->logMessage(msg, 0); return false; } // Make sure the flags represent the current screen state mySDLFlags = myScreen->flags; - // Load OpenGL function pointers - if(loadFuncs(kGL_BASIC)) - myVBOAvailable = myOSystem->settings().getBool("gl_vbo") && loadFuncs(kGL_VBO); - else - return false; - // Optimization hints p_gl.ShadeModel(GL_FLAT); p_gl.Disable(GL_CULL_FACE); diff --git a/src/common/FrameBufferSDL2.hxx b/src/common/FrameBufferSDL2.hxx index 00d21cc83..9f2a55f25 100644 --- a/src/common/FrameBufferSDL2.hxx +++ b/src/common/FrameBufferSDL2.hxx @@ -149,6 +149,14 @@ class FrameBufferSDL2 : public FrameBuffer ////////////////////////////////////////////////////////////////////// // The following are derived from protected methods in FrameBuffer.hxx ////////////////////////////////////////////////////////////////////// + /** + This method is called to query and initialize the video hardware + for desktop and fullscreen resolution information. + + @return False on any errors, else true + */ + bool queryHardware(uInt32& w, uInt32& h, ResolutionList& res); + /** This method is called to initialize the video subsystem with the given video mode. Normally, it will also call setVidMode(). diff --git a/src/debugger/Debugger.cxx b/src/debugger/Debugger.cxx index a9a40d0b1..d9a052443 100644 --- a/src/debugger/Debugger.cxx +++ b/src/debugger/Debugger.cxx @@ -185,7 +185,7 @@ void Debugger::initialize() FBInitStatus Debugger::initializeVideo() { string title = string("Stella ") + STELLA_VERSION + ": Debugger mode"; - return myOSystem->frameBuffer().initialize(title, myWidth, myHeight); + return myOSystem->frameBuffer().createDisplay(title, myWidth, myHeight); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/emucore/Console.cxx b/src/emucore/Console.cxx index 90a3a8ba5..955e23f1e 100644 --- a/src/emucore/Console.cxx +++ b/src/emucore/Console.cxx @@ -409,7 +409,7 @@ FBInitStatus Console::initializeVideo(bool full) { const string& title = string("Stella ") + STELLA_VERSION + ": \"" + myProperties.get(Cartridge_Name) + "\""; - fbstatus = myOSystem->frameBuffer().initialize(title, + fbstatus = myOSystem->frameBuffer().createDisplay(title, myTIA->width() << 1, myTIA->height()); if(fbstatus != kSuccess) return fbstatus; diff --git a/src/emucore/FrameBuffer.cxx b/src/emucore/FrameBuffer.cxx index 6bfe9722e..ce221c2f0 100644 --- a/src/emucore/FrameBuffer.cxx +++ b/src/emucore/FrameBuffer.cxx @@ -27,6 +27,10 @@ #include "EventHandler.hxx" #include "Event.hxx" #include "Font.hxx" +#include "StellaFont.hxx" +#include "StellaMediumFont.hxx" +#include "StellaLargeFont.hxx" +#include "ConsoleFont.hxx" #include "Launcher.hxx" #include "Menu.hxx" #include "OSystem.hxx" @@ -58,6 +62,11 @@ FrameBuffer::FrameBuffer(OSystem* osystem) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - FrameBuffer::~FrameBuffer(void) { + delete myFont; + delete myInfoFont; + delete mySmallFont; + delete myLauncherFont; + // Free all allocated surfaces while(!mySurfaceList.empty()) { @@ -67,8 +76,69 @@ FrameBuffer::~FrameBuffer(void) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -FBInitStatus FrameBuffer::initialize(const string& title, - uInt32 width, uInt32 height) +bool FrameBuffer::initialize() +{ + // Get desktop resolution information + if(!queryHardware(myDesktopWidth, myDesktopHeight, myResolutions)) + return false; + + // Various parts of the codebase assume a minimum screen size of 320x240 + myDesktopWidth = BSPF_max(myDesktopWidth, 320u); + myDesktopHeight = BSPF_max(myDesktopHeight, 240u); + if(!(myDesktopWidth >= 320 && myDesktopHeight >= 240)) + { + myOSystem->logMessage("ERROR: queryVideoHardware failed, " + "window 320x240 or larger required", 0); + return false; + } + + //////////////////////////////////////////////////////////////////// + // Create fonts to draw text + // NOTE: the logic determining appropriate font sizes is done here, + // so that the UI classes can just use the font they expect, + // and not worry about it + // This logic should also take into account the size of the + // framebuffer, and try to be intelligent about font sizes + // We can probably add ifdefs to take care of corner cases, + // but that means we've failed to abstract it enough ... + //////////////////////////////////////////////////////////////////// + bool smallScreen = myDesktopWidth < 640 || myDesktopHeight < 480; + + // This font is used in a variety of situations when a really small + // font is needed; we let the specific widget/dialog decide when to + // use it + mySmallFont = new GUI::Font(GUI::stellaDesc); + + // The general font used in all UI elements + // This is determined by the size of the framebuffer + myFont = new GUI::Font(smallScreen ? GUI::stellaDesc : GUI::stellaMediumDesc); + + // The info font used in all UI elements + // This is determined by the size of the framebuffer + myInfoFont = new GUI::Font(smallScreen ? GUI::stellaDesc : GUI::consoleDesc); + + // The font used by the ROM launcher + // Normally, this is configurable by the user, except in the case of + // very small screens + if(!smallScreen) + { + const string& lf = myOSystem->settings().getString("launcherfont"); + if(lf == "small") + myLauncherFont = new GUI::Font(GUI::consoleDesc); + else if(lf == "medium") + myLauncherFont = new GUI::Font(GUI::stellaMediumDesc); + else + myLauncherFont = new GUI::Font(GUI::stellaLargeDesc); + } + else + myLauncherFont = new GUI::Font(GUI::stellaDesc); + + return true; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +FBInitStatus FrameBuffer::createDisplay(const string& title, + uInt32 width, uInt32 height) { myInitializedCount++; @@ -148,8 +218,8 @@ FBInitStatus FrameBuffer::initialize(const string& title, // Create surfaces for TIA statistics and general messages myStatsMsg.color = kBtnTextColor; - myStatsMsg.w = myOSystem->infoFont().getMaxCharWidth() * 24 + 2; - myStatsMsg.h = (myOSystem->infoFont().getFontHeight() + 2) * 2; + myStatsMsg.w = infoFont().getMaxCharWidth() * 24 + 2; + myStatsMsg.h = (infoFont().getFontHeight() + 2) * 2; if(myStatsMsg.surface == NULL) { @@ -158,7 +228,7 @@ FBInitStatus FrameBuffer::initialize(const string& title, } if(myMsg.surface == NULL) { - uInt32 surfaceID = allocateSurface(640, myOSystem->font().getFontHeight()+10); + uInt32 surfaceID = allocateSurface(640, font().getFontHeight()+10); myMsg.surface = surface(surfaceID); } @@ -205,9 +275,9 @@ void FrameBuffer::update() myOSystem->console().tia().scanlines(), myOSystem->console().getFramerate(), info.DisplayFormat.c_str()); myStatsMsg.surface->fillRect(0, 0, myStatsMsg.w, myStatsMsg.h, kBGColor); - myStatsMsg.surface->drawString(myOSystem->infoFont(), + myStatsMsg.surface->drawString(infoFont(), msg, 1, 1, myStatsMsg.w, myStatsMsg.color, kTextAlignLeft); - myStatsMsg.surface->drawString(myOSystem->infoFont(), + myStatsMsg.surface->drawString(infoFont(), info.BankSwitch, 1, 15, myStatsMsg.w, myStatsMsg.color, kTextAlignLeft); myStatsMsg.surface->addDirtyRect(0, 0, 0, 0); // force a full draw myStatsMsg.surface->setPos(myImageRect.x() + 1, myImageRect.y() + 1); @@ -300,8 +370,8 @@ void FrameBuffer::showMessage(const string& message, MessagePosition position, myMsg.counter = uInt32(myOSystem->frameRate()) << 1; // Show message for 2 seconds myMsg.color = kBtnTextColor; - myMsg.w = myOSystem->font().getStringWidth(myMsg.text) + 10; - myMsg.h = myOSystem->font().getFontHeight() + 8; + myMsg.w = font().getStringWidth(myMsg.text) + 10; + myMsg.h = font().getFontHeight() + 8; myMsg.surface->setWidth(myMsg.w); myMsg.surface->setHeight(myMsg.h); myMsg.position = position; @@ -398,8 +468,8 @@ inline void FrameBuffer::drawMessage() myMsg.surface->setPos(myMsg.x + myImageRect.x(), myMsg.y + myImageRect.y()); myMsg.surface->fillRect(1, 1, myMsg.w-2, myMsg.h-2, kBtnColor); myMsg.surface->box(0, 0, myMsg.w, myMsg.h, kColor, kShadowColor); - myMsg.surface->drawString(myOSystem->font(), myMsg.text, 4, 4, - myMsg.w, myMsg.color, kTextAlignLeft); + myMsg.surface->drawString(font(), myMsg.text, 4, 4, + myMsg.w, myMsg.color, kTextAlignLeft); myMsg.counter--; // Either erase the entire message (when time is reached), @@ -912,15 +982,15 @@ void FrameBuffer::addVidMode(VideoMode& mode) // normally different depending on the OSystem in use // As well, we usually can't get fullscreen modes in the exact size // we want, so we need to calculate image offsets - const ResolutionList& res = myOSystem->supportedResolutions(); - for(uInt32 i = 0; i < res.size(); ++i) + for(uInt32 i = 0; i < myResolutions.size(); ++i) { - if(mode.screen_w <= res[i].width && mode.screen_h <= res[i].height) + if(mode.screen_w <= myResolutions[i].width && + mode.screen_h <= myResolutions[i].height) { // Auto-calculate 'smart' centering; platform-specific framebuffers are // free to ignore or augment it - mode.screen_w = BSPF_max(res[i].width, 320u); - mode.screen_h = BSPF_max(res[i].height, 240u); + mode.screen_w = BSPF_max(myResolutions[i].width, 320u); + mode.screen_h = BSPF_max(myResolutions[i].height, 240u); mode.image_x = (mode.screen_w - mode.image_w) >> 1; mode.image_y = (mode.screen_h - mode.image_h) >> 1; break; diff --git a/src/emucore/FrameBuffer.hxx b/src/emucore/FrameBuffer.hxx index 867139efc..7a78a5220 100644 --- a/src/emucore/FrameBuffer.hxx +++ b/src/emucore/FrameBuffer.hxx @@ -98,6 +98,14 @@ enum { kNumColors }; +// Fullscreen resolutions supported by the underlying hardware +struct Resolution { + uInt32 width; + uInt32 height; + string name; +}; +typedef Common::Array ResolutionList; + /** This class encapsulates all video buffers and is the basis for the video @@ -124,16 +132,21 @@ class FrameBuffer virtual ~FrameBuffer(); /** - (Re)initializes the framebuffer display. This must be called before any + Initialize the framebuffer object (set up the underlying hardware) + */ + bool initialize(); + + /** + (Re)creates the framebuffer display. This must be called before any calls are made to derived methods. - @param title The title of the window + @param title The title of the application / window @param width The width of the framebuffer @param height The height of the framebuffer @return Status of initialization (see FBInitStatus 'enum') */ - FBInitStatus initialize(const string& title, uInt32 width, uInt32 height); + FBInitStatus createDisplay(const string& title, uInt32 width, uInt32 height); /** Updates the display, which depending on the current mode could mean @@ -203,6 +216,27 @@ class FrameBuffer */ const GUI::Rect& screenRect() const { return myScreenRect; } + /** + Get the maximum dimensions of a window for the framebuffer hardware. + */ + uInt32 desktopWidth() const { return myDesktopWidth; } + uInt32 desktopHeight() const { return myDesktopHeight; } + + /** + Get the supported fullscreen resolutions for the video hardware. + + @return An array of supported resolutions + */ + const ResolutionList& supportedResolutions() const { return myResolutions; } + + /** + Get the font object(s) of the framebuffer + */ + const GUI::Font& font() const { return *myFont; } + const GUI::Font& infoFont() const { return *myInfoFont; } + const GUI::Font& smallFont() const { return *mySmallFont; } + const GUI::Font& launcherFont() const { return *myLauncherFont; } + /** Refresh display according to the current state, taking single vs. double-buffered modes into account, and redrawing accordingly. @@ -320,13 +354,10 @@ class FrameBuffer virtual void setWindowTitle(const string& title) = 0; /** - Enable/disable NTSC filtering effects. + Enable/disable/query NTSC filtering effects. */ virtual void enableNTSC(bool enable) { } virtual bool ntscEnabled() const { return false; } - /** - This method is called to query the TV effects in use by the FrameBuffer. - */ virtual string effectsInfo() const { return "None / not available"; } /** @@ -414,6 +445,14 @@ class FrameBuffer } }; + /** + This method is called to query and initialize the video hardware + for desktop and fullscreen resolution information. + + @return False on any errors, else true + */ + virtual bool queryHardware(uInt32& w, uInt32& h, ResolutionList& res) = 0; + /** This method is called to initialize the video subsystem with the given video mode. Normally, it will also call setVidMode(). @@ -619,6 +658,24 @@ class FrameBuffer // Dimensions of the main window (not always the same as the image) GUI::Rect myScreenRect; + // Maximum dimensions of the desktop area + uInt32 myDesktopWidth, myDesktopHeight; + + // Supported fullscreen resolutions + ResolutionList myResolutions; + + // The font object to use for the normal in-game GUI + GUI::Font* myFont; + + // The info font object to use for the normal in-game GUI + GUI::Font* myInfoFont; + + // The font object to use when space is very limited + GUI::Font* mySmallFont; + + // The font object to use for the ROM launcher + GUI::Font* myLauncherFont; + // Used for onscreen messages and frame statistics // (scanline count and framerate) struct Message { diff --git a/src/emucore/OSystem.cxx b/src/emucore/OSystem.cxx index ce0dddfea..71dce4a42 100644 --- a/src/emucore/OSystem.cxx +++ b/src/emucore/OSystem.cxx @@ -57,11 +57,6 @@ #include "Menu.hxx" #include "CommandMenu.hxx" #include "Launcher.hxx" -#include "Font.hxx" -#include "StellaFont.hxx" -#include "StellaMediumFont.hxx" -#include "StellaLargeFont.hxx" -#include "ConsoleFont.hxx" #include "Widget.hxx" #include "Console.hxx" #include "Random.hxx" @@ -91,8 +86,7 @@ OSystem::OSystem() myRomFile(""), myRomMD5(""), myFeatures(""), - myBuildInfo(""), - myFont(NULL) + myBuildInfo("") { // Calculate startup time myMillisAtStart = (uInt32)(time(NULL) * 1000); @@ -127,10 +121,6 @@ OSystem::~OSystem() delete myMenu; delete myCommandMenu; delete myLauncher; - delete myFont; - delete myInfoFont; - delete mySmallFont; - delete myLauncherFont; // Remove any game console that is currently attached deleteConsole(); @@ -176,52 +166,14 @@ bool OSystem::create() << FilesystemNode(myPropertiesFile).getShortPath() << "'" << endl; logMessage(buf.str(), 1); + // NOTE: The framebuffer MUST be created before any other object!!! // Get relevant information about the video hardware // This must be done before any graphics context is created, since // it may be needed to initialize the size of graphical objects - if(!queryVideoHardware()) + myFrameBuffer = MediaFactory::createVideo(this); + if(!myFrameBuffer->initialize()) return false; - //////////////////////////////////////////////////////////////////// - // Create fonts to draw text - // NOTE: the logic determining appropriate font sizes is done here, - // so that the UI classes can just use the font they expect, - // and not worry about it - // This logic should also take into account the size of the - // framebuffer, and try to be intelligent about font sizes - // We can probably add ifdefs to take care of corner cases, - // but that means we've failed to abstract it enough ... - //////////////////////////////////////////////////////////////////// - bool smallScreen = myDesktopWidth < 640 || myDesktopHeight < 480; - - // This font is used in a variety of situations when a really small - // font is needed; we let the specific widget/dialog decide when to - // use it - mySmallFont = new GUI::Font(GUI::stellaDesc); - - // The general font used in all UI elements - // This is determined by the size of the framebuffer - myFont = new GUI::Font(smallScreen ? GUI::stellaDesc : GUI::stellaMediumDesc); - - // The info font used in all UI elements - // This is determined by the size of the framebuffer - myInfoFont = new GUI::Font(smallScreen ? GUI::stellaDesc : GUI::consoleDesc); - - // The font used by the ROM launcher - // Normally, this is configurable by the user, except in the case of - // very small screens - if(!smallScreen) - { - if(mySettings->getString("launcherfont") == "small") - myLauncherFont = new GUI::Font(GUI::consoleDesc); - else if(mySettings->getString("launcherfont") == "medium") - myLauncherFont = new GUI::Font(GUI::stellaMediumDesc); - else - myLauncherFont = new GUI::Font(GUI::stellaLargeDesc); - } - else - myLauncherFont = new GUI::Font(GUI::stellaDesc); - // Create the event handler for the system myEventHandler = new EventHandler(this); myEventHandler->initialize(); @@ -361,18 +313,6 @@ void OSystem::setFramerate(float framerate) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - FBInitStatus OSystem::createFrameBuffer() { - // There is only ever one FrameBuffer created per run of Stella - // Due to the multi-surface nature of the FrameBuffer, repeatedly - // creating and destroying framebuffer objects causes crashes which - // are far too invasive to fix right now - // Besides, how often does one really switch between software and - // OpenGL rendering modes, and even when they do, does it really - // need to be dynamic? - - bool firstTime = (myFrameBuffer == NULL); - if(firstTime) - myFrameBuffer = MediaFactory::createVideo(this); - // Re-initialize the framebuffer to current settings FBInitStatus fbstatus = kFailComplete; switch(myEventHandler->state()) @@ -402,12 +342,14 @@ FBInitStatus OSystem::createFrameBuffer() break; } +#if 0 // FIXME // The following only need to be done once if(firstTime) { // Setup the SDL joysticks (must be done after FrameBuffer is created) myEventHandler->setupJoysticks(); } +#endif return fbstatus; } @@ -907,89 +849,6 @@ void OSystem::mainLoop() } } -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool OSystem::queryVideoHardware() -{ - // Go ahead and open the video hardware; we're going to need it eventually - if(SDL_WasInit(SDL_INIT_VIDEO) == 0) - if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0) - return false; - - // First get the maximum windowed desktop resolution - // Check the 'maxres' setting, which is an undocumented developer feature - // that specifies the desktop size - // Normally, this wouldn't be set, and we ask SDL directly - const GUI::Size& s = mySettings->getSize("maxres"); - if(s.w <= 0 || s.h <= 0) - { - const SDL_VideoInfo* info = SDL_GetVideoInfo(); - myDesktopWidth = info->current_w; - myDesktopHeight = info->current_h; - } - else - { - myDesktopWidth = BSPF_max(s.w, 320); - myDesktopHeight = BSPF_max(s.h, 240); - } - - // Various parts of the codebase assume a minimum screen size of 320x240 - if(!(myDesktopWidth >= 320 && myDesktopHeight >= 240)) - { - logMessage("ERROR: queryVideoHardware failed, " - "window 320x240 or larger required", 0); - return false; - } - - // Then get the valid fullscreen modes - // If there are any errors, just use the desktop resolution - ostringstream buf; - SDL_Rect** modes = SDL_ListModes(NULL, SDL_FULLSCREEN); - if((modes == (SDL_Rect**)0) || (modes == (SDL_Rect**)-1)) - { - Resolution r; - r.width = myDesktopWidth; - r.height = myDesktopHeight; - buf << r.width << "x" << r.height; - r.name = buf.str(); - myResolutions.push_back(r); - } - else - { - // All modes must fit between the lower and upper limits of the desktop - // For 'small' desktop, this means larger than 320x240 - // For 'large'/normal desktop, exclude all those less than 640x480 - bool largeDesktop = myDesktopWidth >= 640 && myDesktopHeight >= 480; - uInt32 lowerWidth = largeDesktop ? 640 : 320, - lowerHeight = largeDesktop ? 480 : 240; - for(uInt32 i = 0; modes[i]; ++i) - { - if(modes[i]->w >= lowerWidth && modes[i]->w <= myDesktopWidth && - modes[i]->h >= lowerHeight && modes[i]->h <= myDesktopHeight) - { - Resolution r; - r.width = modes[i]->w; - r.height = modes[i]->h; - buf.str(""); - buf << r.width << "x" << r.height; - r.name = buf.str(); - myResolutions.insert_at(0, r); // insert in opposite (of descending) order - } - } - // If no modes were valid, use the desktop dimensions - if(myResolutions.size() == 0) - { - Resolution r; - r.width = myDesktopWidth; - r.height = myDesktopHeight; - buf << r.width << "x" << r.height; - r.name = buf.str(); - myResolutions.push_back(r); - } - } - - return true; -} - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - OSystem::OSystem(const OSystem& osystem) { diff --git a/src/emucore/OSystem.hxx b/src/emucore/OSystem.hxx index eeab5de59..1a3672f58 100644 --- a/src/emucore/OSystem.hxx +++ b/src/emucore/OSystem.hxx @@ -35,10 +35,6 @@ class Sound; class StateManager; class VideoDialog; -namespace GUI { - class Font; -} - #include "Array.hxx" #include "FSNode.hxx" #include "FrameBuffer.hxx" @@ -46,13 +42,6 @@ namespace GUI { #include "ZipHandler.hxx" #include "bspf.hxx" -struct Resolution { - uInt32 width; - uInt32 height; - string name; -}; -typedef Common::Array ResolutionList; - struct TimingInfo { uInt64 start; uInt64 current; @@ -230,34 +219,6 @@ class OSystem CheatManager& cheat() const { return *myCheatManager; } #endif - /** - Get the font object of the system - - @return The font reference - */ - const GUI::Font& font() const { return *myFont; } - - /** - Get the info font object of the system - - @return The font reference - */ - const GUI::Font& infoFont() const { return *myInfoFont; } - - /** - Get the small font object of the system - - @return The font reference - */ - const GUI::Font& smallFont() const { return *mySmallFont; } - - /** - Get the launcher font object of the system - - @return The font reference - */ - const GUI::Font& launcherFont() const { return *myLauncherFont; } - /** Set the framerate for the video system. It's placed in this class since the mainLoop() method is defined here. @@ -278,19 +239,13 @@ class OSystem */ float frameRate() const { return myDisplayFrameRate; } +//FIXME - remove this code /** Get the maximum dimensions of a window for the video hardware. */ - uInt32 desktopWidth() const { return myDesktopWidth; } - uInt32 desktopHeight() const { return myDesktopHeight; } - - /** - Get the supported fullscreen resolutions for the video hardware. - - @return An array of supported resolutions - */ - const ResolutionList& supportedResolutions() const { return myResolutions; } - + uInt32 desktopWidth() const { return myFrameBuffer->desktopWidth(); } + uInt32 desktopHeight() const { return myFrameBuffer->desktopHeight(); } +///////////////////////////////////////////////// /** Return the default full/complete directory name for storing data. */ @@ -419,7 +374,7 @@ class OSystem const string& features() const { return myFeatures; } /** - The build information for Stella (SDL version, architecture, etc). + The build information for Stella (toolkit version, architecture, etc). @return The build info */ @@ -508,11 +463,6 @@ class OSystem virtual string defaultSnapLoadDir() { return "~" BSPF_PATH_SEPARATOR; } protected: - /** - Query the OSystem video hardware for resolution information. - */ - virtual bool queryVideoHardware(); - /** Set the base directory for all Stella files (these files may be located in other places through settings). @@ -571,12 +521,6 @@ class OSystem // The list of log messages string myLogMessages; - // Maximum dimensions of the desktop area - uInt32 myDesktopWidth, myDesktopHeight; - - // Supported fullscreen resolutions - ResolutionList myResolutions; - // Number of times per second to iterate through the main loop float myDisplayFrameRate; @@ -611,18 +555,6 @@ class OSystem string myFeatures; string myBuildInfo; - // The font object to use for the normal in-game GUI - GUI::Font* myFont; - - // The info font object to use for the normal in-game GUI - GUI::Font* myInfoFont; - - // The font object to use when space is very limited - GUI::Font* mySmallFont; - - // The font object to use for the ROM launcher - GUI::Font* myLauncherFont; - // Indicates whether the main processing loop should proceed TimingInfo myTimingInfo; @@ -641,7 +573,6 @@ class OSystem /** Creates the various sound devices available in this system - (for now, that means either 'SDL' or 'Null'). */ void createSound(); diff --git a/src/gui/AudioDialog.cxx b/src/gui/AudioDialog.cxx index e8813ad95..7a5ced8d5 100644 --- a/src/gui/AudioDialog.cxx +++ b/src/gui/AudioDialog.cxx @@ -105,7 +105,7 @@ AudioDialog::AudioDialog(OSystem* osystem, DialogContainer* parent, // Add message concerning usage ypos += lineHeight + 12; - const GUI::Font& infofont = instance().infoFont(); + const GUI::Font& infofont = instance().frameBuffer().infoFont(); new StaticTextWidget(this, infofont, 10, ypos, font.getStringWidth("(*) Requires application restart"), fontHeight, "(*) Requires application restart", kTextAlignLeft); diff --git a/src/gui/CommandDialog.cxx b/src/gui/CommandDialog.cxx index 7248d7a3c..7eaaf5044 100644 --- a/src/gui/CommandDialog.cxx +++ b/src/gui/CommandDialog.cxx @@ -34,7 +34,7 @@ CommandDialog::CommandDialog(OSystem* osystem, DialogContainer* parent) : Dialog(osystem, parent, 0, 0, 16, 16) { - const GUI::Font& font = instance().font(); + const GUI::Font& font = instance().frameBuffer().font(); const int buttonWidth = font.getStringWidth("Right Diff B") + 20, buttonHeight = font.getLineHeight() + 6, rowHeight = font.getLineHeight() + 10; diff --git a/src/gui/GameInfoDialog.cxx b/src/gui/GameInfoDialog.cxx index 8d1aad108..74b78371c 100644 --- a/src/gui/GameInfoDialog.cxx +++ b/src/gui/GameInfoDialog.cxx @@ -41,7 +41,7 @@ GameInfoDialog::GameInfoDialog( myPropertiesLoaded(false), myDefaultsSelected(false) { - const GUI::Font& ifont = instance().infoFont(); + const GUI::Font& ifont = instance().frameBuffer().infoFont(); const int lineHeight = font.getLineHeight(), fontWidth = font.getMaxCharWidth(), fontHeight = font.getFontHeight(), diff --git a/src/gui/GlobalPropsDialog.cxx b/src/gui/GlobalPropsDialog.cxx index 9b8a57c2e..26b17e7af 100644 --- a/src/gui/GlobalPropsDialog.cxx +++ b/src/gui/GlobalPropsDialog.cxx @@ -45,7 +45,7 @@ GlobalPropsDialog::GlobalPropsDialog(GuiObject* boss, const GUI::Font& font) pwidth = font.getStringWidth("CM (SpectraVideo CompuMate)"); WidgetArray wid; VariantList items; - const GUI::Font& infofont = instance().infoFont(); + const GUI::Font& infofont = instance().frameBuffer().infoFont(); // Set real dimensions _w = lwidth + pwidth + fontWidth*3 + 15; diff --git a/src/gui/Launcher.cxx b/src/gui/Launcher.cxx index 18517a187..7b81f8988 100644 --- a/src/gui/Launcher.cxx +++ b/src/gui/Launcher.cxx @@ -56,7 +56,7 @@ Launcher::~Launcher() FBInitStatus Launcher::initializeVideo() { string title = string("Stella ") + STELLA_VERSION; - return myOSystem->frameBuffer().initialize(title, myWidth, myHeight); + return myOSystem->frameBuffer().createDisplay(title, myWidth, myHeight); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/gui/LauncherDialog.cxx b/src/gui/LauncherDialog.cxx index 83dfc2b6e..131ae71b6 100644 --- a/src/gui/LauncherDialog.cxx +++ b/src/gui/LauncherDialog.cxx @@ -63,7 +63,7 @@ LauncherDialog::LauncherDialog(OSystem* osystem, DialogContainer* parent, myRomDir(NULL), mySelectedItem(0) { - const GUI::Font& font = instance().launcherFont(); + const GUI::Font& font = instance().frameBuffer().launcherFont(); const int fontWidth = font.getMaxCharWidth(), fontHeight = font.getFontHeight(), @@ -115,9 +115,10 @@ LauncherDialog::LauncherDialog(OSystem* osystem, DialogContainer* parent, if(romWidth > 0) { xpos += myList->getWidth() + 5; - myRomInfoWidget = - new RomInfoWidget(this, romWidth < 660 ? instance().smallFont() : instance().infoFont(), - xpos, ypos, romWidth, myList->getHeight()); + myRomInfoWidget = new RomInfoWidget(this, + romWidth < 660 ? instance().frameBuffer().smallFont() : + instance().frameBuffer().infoFont(), + xpos, ypos, romWidth, myList->getHeight()); } // Add note textwidget to show any notes for the currently selected ROM @@ -184,14 +185,14 @@ LauncherDialog::LauncherDialog(OSystem* osystem, DialogContainer* parent, l.push_back("Power-on options", "override"); l.push_back("Filter listing", "filter"); l.push_back("Reload listing", "reload"); - myMenu = new ContextMenu(this, osystem->font(), l); + myMenu = new ContextMenu(this, osystem->frameBuffer().font(), l); // Create global props dialog, which is used to temporarily overrride // ROM properties - myGlobalProps = new GlobalPropsDialog(this, osystem->font()); + myGlobalProps = new GlobalPropsDialog(this, osystem->frameBuffer().font()); // Create dialog whereby the files shown in the ROM listing can be customized - myFilters = new LauncherFilterDialog(this, osystem->font()); + myFilters = new LauncherFilterDialog(this, osystem->frameBuffer().font()); // Figure out which filters are needed for the ROM listing setListFilters(); @@ -247,8 +248,8 @@ void LauncherDialog::loadConfig() msg.push_back(""); msg.push_back("Click 'OK' to select a default ROM directory,"); msg.push_back("or 'Cancel' to browse the filesystem manually."); - myFirstRunMsg = new GUI::MessageBox(this, instance().font(), msg, - _w, _h, kFirstRunMsgChosenCmd); + myFirstRunMsg = new GUI::MessageBox(this, instance().frameBuffer().font(), + msg, _w, _h, kFirstRunMsgChosenCmd); } myFirstRunMsg->show(); } @@ -542,7 +543,7 @@ void LauncherDialog::handleCommand(CommandSender* sender, int cmd, case kFirstRunMsgChosenCmd: // Show a file browser, starting from the users' home directory if(!myRomDir) - myRomDir = new BrowserDialog(this, instance().font(), _w, _h); + myRomDir = new BrowserDialog(this, instance().frameBuffer().font(), _w, _h); myRomDir->show("Select ROM directory:", "~", BrowserDialog::Directories, kStartupRomDirChosenCmd); diff --git a/src/gui/LoggerDialog.cxx b/src/gui/LoggerDialog.cxx index 728540fb9..4a0a9338e 100644 --- a/src/gui/LoggerDialog.cxx +++ b/src/gui/LoggerDialog.cxx @@ -53,9 +53,10 @@ LoggerDialog::LoggerDialog(OSystem* osystem, DialogContainer* parent, // Test listing of the log output xpos = 10; ypos = 10; - myLogInfo = new StringListWidget(this, instance().infoFont(), xpos, ypos, - _w - 2 * xpos, _h - buttonHeight - ypos - 20 - - 2 * lineHeight, false); + myLogInfo = new StringListWidget(this, instance().frameBuffer().infoFont(), + xpos, ypos, _w - 2 * xpos, + _h - buttonHeight - ypos - 20 - 2 * lineHeight, + false); myLogInfo->setEditable(false); wid.push_back(myLogInfo); ypos += myLogInfo->getHeight() + 8; diff --git a/src/gui/OptionsDialog.cxx b/src/gui/OptionsDialog.cxx index f860b05fd..09019cdfd 100644 --- a/src/gui/OptionsDialog.cxx +++ b/src/gui/OptionsDialog.cxx @@ -62,7 +62,7 @@ OptionsDialog::OptionsDialog(OSystem* osystem, DialogContainer* parent, myAboutDialog(NULL), myIsGlobal(global) { - const GUI::Font& font = instance().font(); + const GUI::Font& font = instance().frameBuffer().font(); const int buttonWidth = font.getStringWidth("Snapshot Settings") + 20, buttonHeight = font.getLineHeight() + 6, rowHeight = font.getLineHeight() + 10; diff --git a/src/gui/RomAuditDialog.cxx b/src/gui/RomAuditDialog.cxx index d9c153377..24107a696 100644 --- a/src/gui/RomAuditDialog.cxx +++ b/src/gui/RomAuditDialog.cxx @@ -129,7 +129,7 @@ void RomAuditDialog::auditRoms() // Create a progress dialog box to show the progress of processing // the ROMs, since this is usually a time-consuming operation - ProgressDialog progress(this, instance().font(), + ProgressDialog progress(this, instance().frameBuffer().font(), "Auditing ROM files ..."); progress.setRange(0, files.size() - 1, 5); @@ -187,7 +187,7 @@ void RomAuditDialog::handleCommand(CommandSender* sender, int cmd, msg.push_back("If you're sure you want to proceed with the"); msg.push_back("audit, click 'OK', otherwise click 'Cancel'."); myConfirmMsg = - new GUI::MessageBox(this, instance().font(), msg, + new GUI::MessageBox(this, instance().frameBuffer().font(), msg, myMaxWidth, myMaxHeight, kConfirmAuditCmd); } diff --git a/src/gui/RomInfoWidget.cxx b/src/gui/RomInfoWidget.cxx index f9c4acc58..8add42f3b 100644 --- a/src/gui/RomInfoWidget.cxx +++ b/src/gui/RomInfoWidget.cxx @@ -154,7 +154,7 @@ void RomInfoWidget::drawWidget(bool hilite) } else if(mySurfaceErrorMsg != "") { - const GUI::Font& font = instance().font(); + const GUI::Font& font = instance().frameBuffer().font(); uInt32 x = _x + ((_w - font.getStringWidth(mySurfaceErrorMsg)) >> 1); uInt32 y = _y + ((yoff - font.getLineHeight()) >> 1); s.drawString(font, mySurfaceErrorMsg, x, y, _w - 10, _textcolor); diff --git a/src/gui/UIDialog.cxx b/src/gui/UIDialog.cxx index 243b8a3a3..ebb186f94 100644 --- a/src/gui/UIDialog.cxx +++ b/src/gui/UIDialog.cxx @@ -41,7 +41,7 @@ UIDialog::UIDialog(OSystem* osystem, DialogContainer* parent, const GUI::Font& font) : Dialog(osystem, parent, 0, 0, 0, 0) { - const GUI::Font& ifont = instance().infoFont(); + const GUI::Font& ifont = instance().frameBuffer().infoFont(); const int lineHeight = font.getLineHeight(), fontWidth = font.getMaxCharWidth(), fontHeight = font.getFontHeight(), diff --git a/src/gui/VideoDialog.cxx b/src/gui/VideoDialog.cxx index 7983e9946..a634d008e 100644 --- a/src/gui/VideoDialog.cxx +++ b/src/gui/VideoDialog.cxx @@ -105,9 +105,8 @@ VideoDialog::VideoDialog(OSystem* osystem, DialogContainer* parent, // Fullscreen resolution items.clear(); items.push_back("Auto", "auto"); - for(uInt32 i = 0; i < instance().supportedResolutions().size(); ++i) - items.push_back(instance().supportedResolutions()[i].name, - instance().supportedResolutions()[i].name); + for(uInt32 i = 0; i < instance().frameBuffer().supportedResolutions().size(); ++i) + items.push_back(instance().frameBuffer().supportedResolutions()[i].name); myFSResPopup = new PopUpWidget(myTab, font, xpos, ypos, pwidth, lineHeight, items, "Fullscrn Res: ", lwidth); wid.push_back(myFSResPopup); @@ -168,7 +167,7 @@ VideoDialog::VideoDialog(OSystem* osystem, DialogContainer* parent, myFrameRateLabel->setFlags(WIDGET_CLEARBG); // Add message concerning usage - const GUI::Font& infofont = instance().infoFont(); + const GUI::Font& infofont = instance().frameBuffer().infoFont(); ypos = myTab->getHeight() - 5 - fontHeight - infofont.getFontHeight() - 10; new StaticTextWidget(myTab, infofont, 10, ypos, font.getStringWidth("(*) Requires application restart"), fontHeight,