Several fixes across the board for better functionality in 'small'

window mode.  Using modes smaller that 640x480 should now work in
all cases when using the 'maxres' commandline argument.  Also, the
lower limit of 320x240 is now strictly enforced in all cases.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@2075 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2010-07-22 15:41:46 +00:00
parent 2977801ffa
commit 6faa9b4b69
15 changed files with 108 additions and 81 deletions

View File

@ -437,18 +437,13 @@ cerr << "dimensions: " << (fullScreen() ? "(full)" : "") << endl
myTiaSurface->setFilter(myOSystem->settings().getString("gl_filter"));
}
// Make sure any old parts of the screen are erased
p_glClear(GL_COLOR_BUFFER_BIT);
SDL_GL_SwapBuffers();
p_glClear(GL_COLOR_BUFFER_BIT);
return true;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBufferGL::invalidate()
{
// TODO - add code for this
p_glClear(GL_COLOR_BUFFER_BIT);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -187,7 +187,7 @@ void Debugger::initialize()
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool Debugger::initializeVideo()
FBInitStatus Debugger::initializeVideo()
{
const GUI::Rect& r = getDialogBounds();

View File

@ -99,7 +99,7 @@ class Debugger : public DialogContainer
/**
Initialize the video subsystem wrt this class.
*/
bool initializeVideo();
FBInitStatus initializeVideo();
/**
Inform this object of a console change.

View File

@ -415,19 +415,20 @@ void Console::setProperties(const Properties& props)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool Console::initializeVideo(bool full)
FBInitStatus Console::initializeVideo(bool full)
{
FBInitStatus fbstatus = kSuccess;
if(full)
{
string title = string("Stella ") + STELLA_VERSION +
": \"" + myProperties.get(Cartridge_Name) + "\"";
if(!myOSystem->frameBuffer().initialize(title,
myTIA->width() << 1, myTIA->height()))
return false;
myOSystem->frameBuffer().showFrameStats(
myOSystem->settings().getBool("stats"));
fbstatus = myOSystem->frameBuffer().initialize(title,
myTIA->width() << 1, myTIA->height());
if(fbstatus != kSuccess)
return fbstatus;
myOSystem->frameBuffer().showFrameStats(myOSystem->settings().getBool("stats"));
setColorLossPalette();
}
@ -447,7 +448,7 @@ bool Console::initializeVideo(bool full)
// Make sure auto-frame calculation is only enabled when necessary
myTIA->enableAutoFrame(framerate <= 0);
return true;
return fbstatus;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -31,6 +31,7 @@ class TIA;
#include "Props.hxx"
#include "TIA.hxx"
#include "Cart.hxx"
#include "FrameBuffer.hxx"
#include "M6532.hxx"
#include "AtariVox.hxx"
#include "Serializable.hxx"
@ -212,9 +213,9 @@ class Console : public Serializable
@param full Whether we want a full initialization,
or only reset certain attributes.
@return False on any errors, else true
@return The results from FrameBuffer::initialize()
*/
bool initializeVideo(bool full = true);
FBInitStatus initializeVideo(bool full = true);
/**
Initialize the audio subsystem wrt this class.

View File

@ -2024,11 +2024,14 @@ bool EventHandler::enterDebugMode()
// probably be modified below
myOSystem->debugger().setStartState();
setEventState(S_DEBUGGER);
if(!myOSystem->createFrameBuffer())
FBInitStatus fbstatus = myOSystem->createFrameBuffer();
if(fbstatus != kSuccess)
{
myOSystem->debugger().setQuitState();
setEventState(S_EMULATE);
myOSystem->frameBuffer().showMessage("Debugger window too large",
if(fbstatus == kFailTooLarge)
myOSystem->frameBuffer().showMessage("Debugger window too large for screen",
kBottomCenter, true);
return false;
}
@ -2036,7 +2039,7 @@ bool EventHandler::enterDebugMode()
myOSystem->frameBuffer().setCursorState();
myOSystem->sound().mute(true);
#else
myOSystem->frameBuffer().showMessage("Debugger unsupported",
myOSystem->frameBuffer().showMessage("Debugger support not included",
kBottomCenter, true);
#endif

View File

@ -66,7 +66,7 @@ FrameBuffer::~FrameBuffer(void)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool FrameBuffer::initialize(const string& title, uInt32 width, uInt32 height)
FBInitStatus FrameBuffer::initialize(const string& title, uInt32 width, uInt32 height)
{
ostringstream buf;
@ -78,24 +78,42 @@ bool FrameBuffer::initialize(const string& title, uInt32 width, uInt32 height)
{
buf << "ERROR: Couldn't initialize SDL: " << SDL_GetError() << endl;
myOSystem->logMessage(buf.str(), 0);
return false;
return kFailComplete;
}
}
myInitializedCount++;
// Make sure this mode is even possible
// We only really need to worry about it in non-windowed environments,
// where requesting a window that's too large will probably cause a crash
#ifndef WINDOWED_SUPPORT
if(myOSystem->desktopWidth() < width || myOSystem->desktopHeight() < height)
return false;
#endif
// A 'windowed' system is defined as one where the window size can be
// larger than the screen size, as there's some sort of window manager
// that takes care of it (all current desktop systems fall in this category)
// However, some systems have no concept of windowing, and have hard limits
// on how large a window can be (ie, the size of the 'desktop' is the
// absolute upper limit on window size)
//
// If the WINDOWED_SUPPORT macro is defined, we treat the system as the
// former type; if not, as the latter type
// Initialize SDL flags and set fullscreen flag
// This must be done before any modes are initialized
mySDLFlags = 0;
#ifdef WINDOWED_SUPPORT
if(myOSystem->settings().getString("fullscreen") == "1") mySDLFlags = SDL_FULLSCREEN;
if(myOSystem->settings().getString("fullscreen") == "1")
mySDLFlags = SDL_FULLSCREEN;
// We assume that a desktop size of at least 640x480 means that we're
// running on a 'large' system, and the window size requirements can
// be relaxed
// Otherwise, we treat the system as if WINDOWED_SUPPORT is not defined
if(myOSystem->desktopWidth() < 640 && myOSystem->desktopHeight() < 480 &&
(myOSystem->desktopWidth() < width || myOSystem->desktopHeight() < height))
return kFailTooLarge;
#else
// Make sure this mode is even possible
// We only really need to worry about it in non-windowed environments,
// where requesting a window that's too large will probably cause a crash
if(myOSystem->desktopWidth() < width || myOSystem->desktopHeight() < height)
return kFailTooLarge;
#endif
// Set the available video modes for this framebuffer
@ -112,7 +130,7 @@ bool FrameBuffer::initialize(const string& title, uInt32 width, uInt32 height)
if(!initSubsystem(mode))
{
myOSystem->logMessage("ERROR: Couldn't initialize video subsystem\n", 0);
return false;
return kFailNotSupported;
}
else
{
@ -131,7 +149,7 @@ bool FrameBuffer::initialize(const string& title, uInt32 width, uInt32 height)
}
}
else
return false;
return kFailTooLarge;
// Enable unicode so we can see translated key events
// (lowercase vs. uppercase characters)
@ -161,7 +179,7 @@ bool FrameBuffer::initialize(const string& title, uInt32 width, uInt32 height)
if(myInitializedCount == 1)
myOSystem->logMessage(about() + "\n", 1);
return true;
return kSuccess;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -420,54 +438,65 @@ void FrameBuffer::refresh()
// This method is in essence a FULL refresh, putting all rendering
// buffers in a known, fully redrawn state
invalidate();
bool doubleBuffered = (type() == kGLBuffer);
switch(myOSystem->eventHandler().state())
{
case EventHandler::S_EMULATE:
case EventHandler::S_PAUSE:
invalidate();
drawTIA(true);
if(doubleBuffered)
{
invalidate();
drawTIA(true);
}
break;
case EventHandler::S_MENU:
invalidate();
drawTIA(true);
myOSystem->menu().draw(true);
if(doubleBuffered)
{
postFrameUpdate();
invalidate();
drawTIA(true);
myOSystem->menu().draw(true);
}
break;
case EventHandler::S_CMDMENU:
invalidate();
drawTIA(true);
myOSystem->commandMenu().draw(true);
if(doubleBuffered)
{
postFrameUpdate();
invalidate();
drawTIA(true);
myOSystem->commandMenu().draw(true);
}
break;
case EventHandler::S_LAUNCHER:
invalidate();
myOSystem->launcher().draw(true);
if(doubleBuffered)
{
postFrameUpdate();
invalidate();
myOSystem->launcher().draw(true);
}
break;
#ifdef DEBUGGER_SUPPORT
case EventHandler::S_DEBUGGER:
invalidate();
myOSystem->debugger().draw(true);
if(doubleBuffered)
{
postFrameUpdate();
invalidate();
myOSystem->debugger().draw(true);
}
break;

View File

@ -43,6 +43,14 @@ enum BufferType {
kGLBuffer
};
// Return values for initialization of framebuffer window
enum FBInitStatus {
kSuccess,
kFailComplete,
kFailTooLarge,
kFailNotSupported,
};
// Positions for onscreen/overlaid messages
enum MessagePosition {
kTopLeft,
@ -114,8 +122,10 @@ class FrameBuffer
@param title The title of the window
@param width The width of the framebuffer
@param height The height of the framebuffer
@return Status of initialization (see FBInitStatus 'enum')
*/
bool initialize(const string& title, uInt32 width, uInt32 height);
FBInitStatus initialize(const string& title, uInt32 width, uInt32 height);
/**
Updates the display, which depending on the current mode could mean

View File

@ -385,7 +385,7 @@ void OSystem::setFramerate(float framerate)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool OSystem::createFrameBuffer()
FBInitStatus OSystem::createFrameBuffer()
{
// There is only ever one FrameBuffer created per run of Stella
// Due to the multi-surface nature of the FrameBuffer, repeatedly
@ -400,24 +400,28 @@ bool OSystem::createFrameBuffer()
myFrameBuffer = MediaFactory::createVideo(this);
// Re-initialize the framebuffer to current settings
FBInitStatus fbstatus = kFailComplete;
switch(myEventHandler->state())
{
case EventHandler::S_EMULATE:
case EventHandler::S_PAUSE:
case EventHandler::S_MENU:
case EventHandler::S_CMDMENU:
if(!myConsole->initializeVideo())
fbstatus = myConsole->initializeVideo();
if(fbstatus != kSuccess)
goto fallback;
break; // S_EMULATE, S_PAUSE, S_MENU, S_CMDMENU
case EventHandler::S_LAUNCHER:
if(!myLauncher->initializeVideo())
fbstatus = myLauncher->initializeVideo();
if(fbstatus != kSuccess)
goto fallback;
break; // S_LAUNCHER
#ifdef DEBUGGER_SUPPORT
case EventHandler::S_DEBUGGER:
if(!myDebugger->initializeVideo())
fbstatus = myDebugger->initializeVideo();
if(fbstatus != kSuccess)
goto fallback;
break; // S_DEBUGGER
#endif
@ -437,28 +441,30 @@ bool OSystem::createFrameBuffer()
setUIPalette();
}
return true;
return fbstatus;
// GOTO are normally considered evil, unless well documented :)
// If initialization of video system fails while in OpenGL mode,
// attempt to fallback to software mode
// If initialization of video system fails while in OpenGL mode
// because OpenGL is unavailable, attempt to fallback to software mode
// Otherwise, pass the error to the parent
fallback:
if(myFrameBuffer && myFrameBuffer->type() == kGLBuffer)
if(fbstatus == kFailNotSupported && myFrameBuffer &&
myFrameBuffer->type() == kGLBuffer)
{
logMessage("ERROR: OpenGL mode failed, fallback to software\n", 0);
delete myFrameBuffer; myFrameBuffer = NULL;
mySettings->setString("video", "soft");
bool ret = createFrameBuffer();
if(ret)
FBInitStatus newstatus = createFrameBuffer();
if(newstatus == kSuccess)
{
setFramerate(60);
myFrameBuffer->showMessage("OpenGL mode failed, fallback to software",
kMiddleCenter, true);
}
return ret;
return newstatus;
}
else
return false;
return fbstatus;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -522,7 +528,7 @@ bool OSystem::createConsole(const string& romfile, const string& md5sum)
//////////////////////////////////////////////////////////////////////////
if(audiofirst) myConsole->initializeAudio();
myEventHandler->reset(EventHandler::S_EMULATE);
if(!createFrameBuffer()) // Takes care of initializeVideo()
if(createFrameBuffer() != kSuccess) // Takes care of initializeVideo()
{
logMessage("ERROR: Couldn't create framebuffer for console\n", 0);
myEventHandler->reset(EventHandler::S_LAUNCHER);
@ -594,7 +600,7 @@ void OSystem::deleteConsole()
bool OSystem::createLauncher()
{
myEventHandler->reset(EventHandler::S_LAUNCHER);
if(!createFrameBuffer())
if(createFrameBuffer() != kSuccess)
{
logMessage("ERROR: Couldn't create launcher\n", 0);
return false;
@ -1020,7 +1026,7 @@ bool OSystem::queryVideoHardware()
// Normally, this wouldn't be set, and we ask SDL directly
int w, h;
mySettings->getSize("maxres", w, h);
if(w == 0 || h == 0)
if(w <= 0 || h <= 0)
{
const SDL_VideoInfo* info = SDL_GetVideoInfo();
myDesktopWidth = info->current_w;

View File

@ -560,8 +560,11 @@ class OSystem
it will only create one type per run of Stella.
@return Success or failure of the framebuffer creation
Note that if OpenGL mode fails because OpenGL is not
available, rendering will attempt to fall back to
software mode
*/
bool createFrameBuffer();
FBInitStatus createFrameBuffer();
/**
Creates the various sound devices available in this system

View File

@ -126,7 +126,7 @@ Settings::Settings(OSystem* osystem)
setInternal("audiofirst", "true");
setInternal("fastscbios", "false");
setExternal("romloadcount", "0");
setExternal("maxres", "0x0");
setExternal("maxres", "");
// Debugger options
setInternal("resolvedata", "auto");

View File

@ -116,8 +116,8 @@ void DialogContainer::draw(bool full)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void DialogContainer::addDialog(Dialog* d)
{
const GUI::Rect& image = myOSystem->frameBuffer().imageRect();
assert(d->getWidth() <= image.width() && d->getHeight() <= image.height());
const GUI::Rect& screen = myOSystem->frameBuffer().screenRect();
assert(d->getWidth() <= screen.width() && d->getHeight() <= screen.height());
myDialogStack.push(d);
d->open();

View File

@ -50,7 +50,7 @@ Launcher::~Launcher()
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool Launcher::initializeVideo()
FBInitStatus Launcher::initializeVideo()
{
string title = string("Stella ") + STELLA_VERSION;
return myOSystem->frameBuffer().initialize(title, myWidth, myHeight);

View File

@ -24,6 +24,7 @@ class Properties;
class OSystem;
#include "DialogContainer.hxx"
#include "FrameBuffer.hxx"
/**
The base dialog for the ROM launcher in Stella.
@ -47,7 +48,7 @@ class Launcher : public DialogContainer
/**
Initialize the video subsystem wrt this class.
*/
bool initializeVideo();
FBInitStatus initializeVideo();
/**
Wrapper for LauncherDialog::selectedRomMD5() method.

View File

@ -119,18 +119,6 @@ OptionsDialog::OptionsDialog(OSystem* osystem, DialogContainer* parent,
// Now create all the dialogs attached to each menu button
myVideoDialog = new VideoDialog(osystem, parent, font, max_w, max_h);
myAudioDialog = new AudioDialog(osystem, parent, font);
/* FIXME - may not be needed with small-font functionality
#ifdef _WIN32_WCE
// FIXME - adjust size for WINCE using a smaller font
// we scale the input dialog down a bit in low res devices.
// looks only a little ugly, but the functionality is very welcome
if(instance().desktopWidth() < 320) { w = 220; h = 176; }
else { w = 230; h = 185; }
#else
w = 380; h = 310;
#endif
*/
myInputDialog = new InputDialog(osystem, parent, font);
myUIDialog = new UIDialog(osystem, parent, font);
myFileSnapDialog = new FileSnapDialog(osystem, parent, font, boss, max_w, max_h);
@ -156,16 +144,6 @@ OptionsDialog::OptionsDialog(OSystem* osystem, DialogContainer* parent,
#ifdef _WIN32_WCE
myAudioSettingsButton->clearFlags(WIDGET_ENABLED); // not honored in wince port
#endif
//FIXME - this may no longer be true (with the new small font functionality)
if(instance().desktopWidth() < 320)
{
// These cannot be displayed in low res devices
myVideoSettingsButton->clearFlags(WIDGET_ENABLED);
myFileSnapButton->clearFlags(WIDGET_ENABLED);
myGameInfoButton->clearFlags(WIDGET_ENABLED);
myHelpButton->clearFlags(WIDGET_ENABLED);
myAboutButton->clearFlags(WIDGET_ENABLED);
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -