Ticket #8926: sdl_transaction_rollback_v3.2.patch

File sdl_transaction_rollback_v3.2.patch, 57.0 KB (added by lordhoto, 15 years ago)

Patch against r35045.

  • engines/sword1/sword1.cpp

     
    7878
    7979Common::Error SwordEngine::init() {
    8080
    81         _system->beginGFXTransaction();
    82                 initCommonGFX(true);
    83                 _system->initSize(640, 480);
    84         _system->endGFXTransaction();
     81        initGraphics(640, 480, true);
    8582
    8683        if ( 0 == scumm_stricmp(ConfMan.get("gameid").c_str(), "sword1mac") ||
    8784             0 == scumm_stricmp(ConfMan.get("gameid").c_str(), "sword1macdemo") )
  • engines/m4/m4.cpp

     
    143143
    144144Common::Error M4Engine::init() {
    145145        // Initialize backend
    146         _system->beginGFXTransaction();
    147         initCommonGFX(isM4());
    148146        if (isM4())
    149                 _system->initSize(640, 480);
     147                initGraphics(640, 480, true);
    150148        else
    151                 _system->initSize(320, 200);
    152         _system->endGFXTransaction();
     149                initGraphics(320, 200, false);
    153150
    154151        _screen = new M4Surface(true); // Special form for creating screen reference
    155152
  • engines/sword2/sword2.cpp

     
    371371        _resman = NULL;
    372372        _memory = NULL;
    373373
    374         _system->beginGFXTransaction();
    375                 initCommonGFX(true);
    376                 _screen = new Screen(this, 640, 480);
    377         _system->endGFXTransaction();
     374        initGraphics(640, 480, true);
     375        _screen = new Screen(this, 640, 480);
    378376
    379377        // Create the debugger as early as possible (but not before the
    380378        // screen object!) so that errors can be displayed in it. In
  • engines/sword2/screen.cpp

     
    5252
    5353        _dirtyGrid = _buffer = NULL;
    5454
    55         _vm->_system->initSize(width, height);
    56 
    5755        _screenWide = width;
    5856        _screenDeep = height;
    5957
  • engines/scumm/scumm.cpp

     
    822822}
    823823
    824824Common::Error ScummEngine_vCUPhe::init() {
    825         _system->beginGFXTransaction();
    826                 _system->initSize(CUP_Player::kDefaultVideoWidth, CUP_Player::kDefaultVideoHeight);
    827                 initCommonGFX(true);
    828         _system->endGFXTransaction();
     825        initGraphics(CUP_Player::kDefaultVideoWidth, CUP_Player::kDefaultVideoHeight, true);
    829826
    830827        return Common::kNoError;
    831828}
     
    10691066        loadCJKFont();
    10701067
    10711068        // Initialize backend
    1072         _system->beginGFXTransaction();
    1073                 bool defaultTo1XScaler = false;
    1074                 if (_renderMode == Common::kRenderHercA || _renderMode == Common::kRenderHercG) {
    1075                         _system->initSize(Common::kHercW, Common::kHercH);
    1076                         defaultTo1XScaler = true;
    1077                 } else if (_useCJKMode) {
    1078                         _system->initSize(_screenWidth * _textSurfaceMultiplier, _screenHeight * _textSurfaceMultiplier);
     1069        if (_renderMode == Common::kRenderHercA || _renderMode == Common::kRenderHercG) {
     1070                initGraphics(Common::kHercW, Common::kHercH, true);
     1071        } else if (_useCJKMode) {
     1072                initGraphics(_screenWidth * _textSurfaceMultiplier, _screenHeight * _textSurfaceMultiplier,
     1073                                        // CJK FT and DIG use usual NUT fonts, not FM-TOWNS ROM, so
     1074                                        // there is no text surface for them. This takes that into account
     1075                                        (_screenWidth * _textSurfaceMultiplier > 320));
     1076        } else {
     1077                initGraphics(_screenWidth, _screenHeight, _screenWidth > 320);
     1078        }
    10791079
    1080                         // CJK FT and DIG use usual NUT fonts, not FM-TOWNS ROM, so
    1081                         // there is no text surface for them. This takes that into account
    1082                         defaultTo1XScaler = (_screenWidth * _textSurfaceMultiplier > 320);
    1083                 } else {
    1084                         _system->initSize(_screenWidth, _screenHeight);
    1085                         defaultTo1XScaler = (_screenWidth > 320);
    1086                 }
    1087                 initCommonGFX(defaultTo1XScaler);
    1088         _system->endGFXTransaction();
    1089 
    10901080        setupScumm();
    10911081
    10921082        readIndexFile();
  • engines/engine.cpp

     
    125125                g_system->setFeatureState(OSystem::kFeatureFullscreenMode, ConfMan.getBool("fullscreen"));
    126126}
    127127
     128void initGraphics(int width, int height, bool defaultTo1xScaler) {
     129        g_system->beginGFXTransaction();
     130
     131                initCommonGFX(defaultTo1xScaler);
     132                g_system->initSize(width, height);
     133
     134        OSystem::TransactionError gfxError = g_system->endGFXTransaction();
     135
     136        if (gfxError == OSystem::kTransactionSuccess)
     137                return;
     138
     139        // Error out on size switch failure
     140        if (gfxError & OSystem::kTransactionSizeChangeFailed) {
     141                char buffer[16];
     142                snprintf(buffer, 16, "%dx%d", width, height);
     143
     144                Common::String message = "Could not switch to resolution: '";
     145                message += buffer;
     146                message += "'.";
     147
     148                GUIErrorMessage(message);
     149                error(message.c_str());
     150        }
     151
     152        // Just show warnings then these occur:
     153        if (gfxError & OSystem::kTransactionModeSwitchFailed) {
     154                Common::String message = "Could not switch to video mode: '";
     155                message += ConfMan.get("gfx_mode");
     156                message += "'.";
     157
     158                GUI::MessageDialog dialog(message);
     159                dialog.runModal();             
     160        }
     161       
     162        if (gfxError & OSystem::kTransactionAspectRatioFailed) {
     163                GUI::MessageDialog dialog("Could not apply aspect ratio setting.");
     164                dialog.runModal();
     165        }
     166
     167        if (gfxError & OSystem::kTransactionFullscreenFailed) {
     168                GUI::MessageDialog dialog("Could not apply fullscreen setting.");
     169                dialog.runModal();
     170        }
     171}
     172
    128173void GUIErrorMessage(const Common::String msg) {
    129174        g_system->setWindowCaption("Error");
    130175        g_system->beginGFXTransaction();
    131176                initCommonGFX(false);
    132177                g_system->initSize(320, 200);
    133         g_system->endGFXTransaction();
    134 
    135         GUI::MessageDialog dialog(msg);
    136         dialog.runModal();
     178        if (g_system->endGFXTransaction() == OSystem::kTransactionSuccess) {
     179                GUI::MessageDialog dialog(msg);
     180                dialog.runModal();
     181        } else {
     182                error(msg.c_str());
     183        }
    137184}
    138185
    139186void Engine::checkCD() {
  • engines/touche/touche.cpp

     
    8282}
    8383
    8484Common::Error ToucheEngine::init() {
    85         _system->beginGFXTransaction();
    86                 initCommonGFX(true);
    87                 _system->initSize(kScreenWidth, kScreenHeight);
    88         _system->endGFXTransaction();
     85        initGraphics(kScreenWidth, kScreenHeight, true);
    8986
    9087        Graphics::setupFont(_language);
    9188
  • engines/agos/agos.cpp

     
    540540                _screenHeight = 200;
    541541        }
    542542
    543         _system->beginGFXTransaction();
    544                 initCommonGFX(getGameType() == GType_FF || getGameType() == GType_PP);
    545                 _system->initSize(_screenWidth, _screenHeight);
    546         _system->endGFXTransaction();
     543        initGraphics(_screenWidth, _screenHeight, getGameType() == GType_FF || getGameType() == GType_PP);
    547544
    548545        // Setup mixer
    549546        _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
  • engines/cruise/cruise.cpp

     
    7272
    7373Common::Error CruiseEngine::init() {
    7474        // Initialize backend
    75         _system->beginGFXTransaction();
    76         initCommonGFX(false);
    77         _system->initSize(320, 200);
    78         _system->endGFXTransaction();
     75        initGraphics(320, 200, false);
    7976
    8077        initialize();
    8178
  • engines/engine.h

     
    5151void initCommonGFX(bool defaultTo1XScaler);
    5252
    5353/**
    54  * Initialized graphics and shows error message.
     54 * Setup the backend's screen size and graphics mode.
     55 *
     56 * Shows an various warnings on certain backend graphics
     57 * transaction failures (aspect switch, fullscreen switch, etc.).
     58 *
     59 * Errors out when backend is not able to switch to the specified
     60 * mode.
    5561 */
     62void initGraphics(int width, int height, bool defaultTo1xScaler);
     63
     64/**
     65 * Initializes graphics and shows error message.
     66 */
    5667void GUIErrorMessage(const Common::String msg);
    5768
    5869
  • engines/tucker/tucker.cpp

     
    4242}
    4343
    4444Common::Error TuckerEngine::init() {
    45         _system->beginGFXTransaction();
    46                 initCommonGFX(false);
    47                 _system->initSize(320, 200);
    48         _system->endGFXTransaction();
     45        initGraphics(320, 200, false);
    4946
    5047        _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
    5148        _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, ConfMan.getInt("speech_volume"));
  • engines/drascula/drascula.cpp

     
    106106
    107107Common::Error DrasculaEngine::init() {
    108108        // Initialize backend
    109         _system->beginGFXTransaction();
    110         initCommonGFX(false);
    111         _system->initSize(320, 200);
    112         _system->endGFXTransaction();
     109        initGraphics(320, 200, false);
    113110
    114111        switch (getLanguage()) {
    115112        case Common::EN_ANY:
  • engines/tinsel/tinsel.cpp

     
    660660
    661661Common::Error TinselEngine::init() {
    662662        // Initialize backend
    663         _system->beginGFXTransaction();
    664                 initCommonGFX(false);
    665                 _system->initSize(SCREEN_WIDTH, SCREEN_HEIGHT);
    666         _system->endGFXTransaction();
     663        initGraphics(SCREEN_WIDTH, SCREEN_HEIGHT, false);
    667664
    668665        _screenSurface.create(SCREEN_WIDTH, SCREEN_HEIGHT, 1);
    669666
  • engines/agi/agi.cpp

     
    782782Common::Error AgiBase::init() {
    783783
    784784        // Initialize backend
    785         _system->beginGFXTransaction();
    786         initCommonGFX(false);
    787         _system->initSize(320, 200);
    788         _system->endGFXTransaction();
     785        initGraphics(320, 200, false);
    789786
    790787        initialize();
    791788
  • engines/igor/igor.cpp

     
    8989}
    9090
    9191Common::Error IgorEngine::init() {
    92         _system->beginGFXTransaction();
    93                 initCommonGFX(false);
    94                 _system->initSize(320, 200);
    95         _system->endGFXTransaction();
     92        initGraphics(320, 200, false);
    9693
    9794        _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume"));
    9895        return Common::kNoError;
  • engines/sky/sky.cpp

     
    238238}
    239239
    240240Common::Error SkyEngine::init() {
    241         _system->beginGFXTransaction();
    242                 initCommonGFX(false);
    243                 _system->initSize(320, 200);
    244         _system->endGFXTransaction();
     241        initGraphics(320, 200, false);
    245242
    246243        if (ConfMan.getBool("sfx_mute")) {
    247244                SkyEngine::_systemVars.systemFlags |= SF_FX_OFF;
  • engines/made/made.cpp

     
    130130
    131131Common::Error MadeEngine::init() {
    132132        // Initialize backend
    133         _system->beginGFXTransaction();
    134         initCommonGFX(false);
    135         _system->initSize(320, 200);
    136         _system->endGFXTransaction();
     133        initGraphics(320, 200, false);
    137134
    138135        return Common::kNoError;
    139136}
  • engines/kyra/screen.cpp

     
    186186        byte palette[4*256];
    187187        _system->grabPalette(palette, 0, 256);
    188188
     189        int width = 320, height = 200;
     190        bool defaultTo1xScaler = false;
     191
    189192        if (_vm->gameFlags().useHiResOverlay) {
    190                 _system->beginGFXTransaction();
    191                         if (_debugEnabled)
    192                                 _system->initSize(960, 400);
    193                         else
    194                                 _system->initSize(640, 400);
    195                         initCommonGFX(true);
    196                 _system->endGFXTransaction();
     193                defaultTo1xScaler = true;
     194                height = 400;
     195
     196                if (_debugEnabled)
     197                        width = 960;
     198                else
     199                        width = 640;
    197200        } else {
    198                 _system->beginGFXTransaction();
    199                         if (_debugEnabled)
    200                                 _system->initSize(640, 200);
    201                         else
    202                                 _system->initSize(320, 200);
    203                         initCommonGFX(false);
    204                 _system->endGFXTransaction();
     201                if (_debugEnabled)
     202                        width = 640;
     203                else
     204                        width = 320;
    205205        }
    206206
     207        initGraphics(width, height, defaultTo1xScaler);
     208
    207209        _system->setPalette(palette, 0, 256);
    208210}
    209211
  • engines/lure/lure.cpp

     
    5252        int_engine = this;
    5353        _initialised = false;
    5454
    55         _system->beginGFXTransaction();
    56         initCommonGFX(false);
    57         _system->initSize(FULL_SCREEN_WIDTH, FULL_SCREEN_HEIGHT);
    58         _system->endGFXTransaction();
     55        initGraphics(FULL_SCREEN_WIDTH, FULL_SCREEN_HEIGHT, false);
    5956
    6057        // Check the version of the lure.dat file
    6158        Common::File f;
  • engines/gob/video.cpp

     
    169169}
    170170
    171171void Video::setSize(bool defaultTo1XScaler) {
    172         _vm->_system->beginGFXTransaction();
    173                 _vm->_system->initSize(_vm->_width, _vm->_height);
    174                 initCommonGFX(defaultTo1XScaler);
    175         _vm->_system->endGFXTransaction();
     172        initGraphics(_vm->_width, _vm->_height, defaultTo1XScaler);
    176173}
    177174
    178175void Video::retrace(bool mouse) {
  • engines/parallaction/graphics.cpp

     
    749749Gfx::Gfx(Parallaction* vm) :
    750750        _vm(vm), _disk(vm->_disk) {
    751751
    752         _vm->_system->beginGFXTransaction();
    753                 _vm->_system->initSize(_vm->_screenWidth, _vm->_screenHeight);
    754                 initCommonGFX(_vm->getGameType() == GType_BRA);
    755         _vm->_system->endGFXTransaction();
     752        initGraphics(_vm->_screenWidth, _vm->_screenHeight, _vm->getGameType() == GType_BRA);
    756753
    757754        setPalette(_palette);
    758755
  • engines/saga/gfx.cpp

     
    4040#define RID_IHNM_HOURGLASS_CURSOR 11 // not in demo
    4141
    4242Gfx::Gfx(SagaEngine *vm, OSystem *system, int width, int height) : _vm(vm), _system(system) {
    43         _system->beginGFXTransaction();
    44                 initCommonGFX(width > 320);
    45                 _system->initSize(width, height);
    46         _system->endGFXTransaction();
     43        initGraphics(width, height, width > 320);
    4744
    4845        debug(5, "Init screen %dx%d", width, height);
    4946        // Convert surface data to R surface data
  • engines/queen/queen.cpp

     
    473473}
    474474
    475475Common::Error QueenEngine::init() {
    476         _system->beginGFXTransaction();
    477                 initCommonGFX(false);
    478                 _system->initSize(GAME_SCREEN_WIDTH, GAME_SCREEN_HEIGHT);
    479         _system->endGFXTransaction();
     476        initGraphics(GAME_SCREEN_WIDTH, GAME_SCREEN_HEIGHT, false);
    480477
    481478        _resource = new Resource();
    482479
  • engines/cine/cine.cpp

     
    7676
    7777Common::Error CineEngine::init() {
    7878        // Initialize backend
    79         _system->beginGFXTransaction();
    80         initCommonGFX(false);
    81         _system->initSize(320, 200);
    82         _system->endGFXTransaction();
     79        initGraphics(320, 200, false);
    8380
    8481        if (g_cine->getPlatform() == Common::kPlatformPC) {
    8582                g_sound = new PCSound(_mixer, this);
  • common/system.h

     
    393393         */
    394394        virtual void beginGFXTransaction() {}
    395395
     396        /**
     397         * This type is able to save the different errors which can happen while
     398         * changing GFX config values inside GFX transactions.
     399         *
     400         * endGFXTransaction returns a ORed combination of the '*Failed' values
     401         * if any problem occures, on success 0.
     402         *
     403         * @see endGFXTransaction
     404         */
     405        enum TransactionError {
     406                kTransactionSuccess = 0,                                        /**< Everything fine (use EQUAL check for this one!) */
     407                kTransactionAspectRatioFailed = (1 << 0),       /**< Failed switchting aspect ratio correction mode */
     408                kTransactionFullscreenFailed = (1 << 1),        /**< Failed switchting fullscreen mode */
     409                kTransactionModeSwitchFailed = (1 << 2),        /**< Failed switchting the GFX graphics mode (setGraphicsMode) */
     410                kTransactionSizeChangeFailed = (1 << 3)         /**< Failed switchting the screen dimensions (initSize) */
     411        };
    396412
    397413        /**
    398414         * End (and thereby commit) the current GFX transaction.
    399415         * @see beginGFXTransaction
     416         * @see kTransactionError
     417         * @return returns a ORed combination of TransactionError values or 0 on success
    400418         */
    401         virtual void endGFXTransaction() {}
     419        virtual TransactionError endGFXTransaction() { return kTransactionSuccess; }
    402420
    403421
    404422        /**
  • backends/platform/sdl/graphics.cpp

     
    4949};
    5050
    5151// Table of relative scalers magnitudes
    52 // [definedScale - 1][_scaleFactor - 1]
     52// [definedScale - 1][scaleFactor - 1]
    5353static ScalerProc *scalersMagn[3][3] = {
    5454#ifndef DISABLE_SCALERS
    5555        { Normal1x, AdvMame2x, AdvMame3x },
     
    8686}
    8787
    8888void OSystem_SDL::beginGFXTransaction(void) {
    89         assert (_transactionMode == kTransactionNone);
     89        assert(_transactionMode == kTransactionNone);
    9090
    9191        _transactionMode = kTransactionActive;
    9292
    93         _transactionDetails.modeChanged = false;
    9493        _transactionDetails.sizeChanged = false;
    95         _transactionDetails.arChanged = false;
    96         _transactionDetails.fsChanged = false;
    9794
    9895        _transactionDetails.needHotswap = false;
    9996        _transactionDetails.needUpdatescreen = false;
    100         _transactionDetails.needUnload = false;
    10197
    10298        _transactionDetails.normal1xScaler = false;
     99
     100        _oldVideoMode = _videoMode;
    103101}
    104102
    105 void OSystem_SDL::endGFXTransaction(void) {
    106         // for each engine we run initCommonGFX() as first thing in the transaction
    107         // and initSize() is called later. If user runs launcher at 320x200 with
    108         // 2x overlay, setting to Nomral1x sclaler in that case will be suppressed
    109         // and backend is forced to 2x
    110         //
    111         // This leads to bad results such as 1280x960 window for 640x480 engines.
    112         // To prevent that we rerun setGraphicsMode() if there was 1x scaler request
    113         if (_transactionDetails.normal1xScaler)
    114                 setGraphicsMode(GFX_NORMAL);
     103OSystem::TransactionError OSystem_SDL::endGFXTransaction(void) {
     104        int errors = kTransactionSuccess;
    115105
    116         assert (_transactionMode == kTransactionActive);
     106        assert(_transactionMode != kTransactionNone);
    117107
    118         _transactionMode = kTransactionCommit;
    119         if (_transactionDetails.modeChanged)
    120                 setGraphicsMode(_transactionDetails.mode);
     108        if (_transactionMode == kTransactionRollback) {
     109                if (_videoMode.fullscreen != _oldVideoMode.fullscreen) {
     110                        errors |= kTransactionFullscreenFailed;
    121111
    122         if (_transactionDetails.sizeChanged)
    123                 initSize(_transactionDetails.w, _transactionDetails.h);
     112                        _videoMode.fullscreen = _oldVideoMode.fullscreen;
     113                } else if (_videoMode.aspectRatio != _oldVideoMode.aspectRatio) {
     114                        errors |= kTransactionAspectRatioFailed;
    124115
    125         if (_transactionDetails.arChanged)
    126                 setAspectRatioCorrection(_transactionDetails.ar);
     116                        _videoMode.aspectRatio = _oldVideoMode.aspectRatio;
     117                } else if (_videoMode.mode != _oldVideoMode.mode) {
     118                        errors |= kTransactionModeSwitchFailed;
    127119
    128         if (_transactionDetails.needUnload) {
     120                        _videoMode.mode = _oldVideoMode.mode;
     121                        _videoMode.scaleFactor = _oldVideoMode.scaleFactor;
     122                } else if (_videoMode.screenWidth != _oldVideoMode.screenWidth || _videoMode.screenHeight != _oldVideoMode.screenHeight) {
     123                        errors |= kTransactionSizeChangeFailed;
     124
     125                        _videoMode.screenWidth = _oldVideoMode.screenWidth;
     126                        _videoMode.screenHeight = _oldVideoMode.screenHeight;
     127                        _videoMode.overlayWidth = _oldVideoMode.overlayWidth;
     128                        _videoMode.overlayHeight = _oldVideoMode.overlayHeight;
     129                }
     130
     131                if (_videoMode.fullscreen == _oldVideoMode.fullscreen &&
     132                        _videoMode.aspectRatio == _oldVideoMode.aspectRatio &&
     133                        _videoMode.mode == _oldVideoMode.mode &&
     134                        _videoMode.screenWidth == _oldVideoMode.screenWidth &&
     135                        _videoMode.screenHeight == _oldVideoMode.screenHeight) {
     136
     137                        // Our new video mode would now be exactly the same as the
     138                        // old one. Since we still can not assume SDL_SetVideoMode
     139                        // to be working fine, we need to invalidate the old video
     140                        // mode, so loadGFXMode would error out properly.
     141                        _oldVideoMode.setup = false;
     142                }
     143        }
     144
     145        if (_transactionDetails.sizeChanged) {
    129146                unloadGFXMode();
    130                 loadGFXMode();
    131                 clearOverlay();
    132         } else {
    133                 if (!_transactionDetails.fsChanged) {
    134                         if (_transactionDetails.needHotswap)
    135                                 hotswapGFXMode();
    136                         else if (_transactionDetails.needUpdatescreen)
     147                if (!loadGFXMode()) {
     148                        if (_oldVideoMode.setup) {
     149                                _transactionMode = kTransactionRollback;
     150                                errors |= endGFXTransaction();
     151                        }
     152                } else {
     153                        setGraphicsModeIntern();
     154                        clearOverlay();
     155
     156                        _videoMode.setup = true;
     157                        _modeChanged = true;
     158                }
     159        } else if (_transactionDetails.needHotswap) {
     160                setGraphicsModeIntern();
     161                if (!hotswapGFXMode()) {
     162                        if (_oldVideoMode.setup) {
     163                                _transactionMode = kTransactionRollback;
     164                                errors |= endGFXTransaction();
     165                        }
     166                } else {
     167                        _videoMode.setup = true;
     168                        _modeChanged = true;
     169
     170                        if (_transactionDetails.needUpdatescreen)
    137171                                internUpdateScreen();
    138172                }
    139173        }
    140174
    141         if (_transactionDetails.fsChanged)
    142                 setFullscreenMode(_transactionDetails.fs);
    143 
    144175        _transactionMode = kTransactionNone;
     176        return (TransactionError)errors;
    145177}
    146178
    147179bool OSystem_SDL::setGraphicsMode(int mode) {
    148180        Common::StackLock lock(_graphicsMutex);
    149181
     182        assert(_transactionMode == kTransactionActive);
     183
     184        if (_oldVideoMode.setup && _oldVideoMode.mode == mode)
     185                return true;
     186
    150187        int newScaleFactor = 1;
    151         ScalerProc *newScalerProc;
    152188
    153189        switch(mode) {
    154190        case GFX_NORMAL:
    155191                newScaleFactor = 1;
    156                 newScalerProc = Normal1x;
    157192                break;
    158193#ifndef DISABLE_SCALERS
    159194        case GFX_DOUBLESIZE:
    160195                newScaleFactor = 2;
    161                 newScalerProc = Normal2x;
    162196                break;
    163197        case GFX_TRIPLESIZE:
    164198                newScaleFactor = 3;
    165                 newScalerProc = Normal3x;
    166199                break;
    167200
    168201        case GFX_2XSAI:
    169202                newScaleFactor = 2;
    170                 newScalerProc = _2xSaI;
    171203                break;
    172204        case GFX_SUPER2XSAI:
    173205                newScaleFactor = 2;
    174                 newScalerProc = Super2xSaI;
    175206                break;
    176207        case GFX_SUPEREAGLE:
    177208                newScaleFactor = 2;
    178                 newScalerProc = SuperEagle;
    179209                break;
    180210        case GFX_ADVMAME2X:
    181211                newScaleFactor = 2;
    182                 newScalerProc = AdvMame2x;
    183212                break;
    184213        case GFX_ADVMAME3X:
    185214                newScaleFactor = 3;
    186                 newScalerProc = AdvMame3x;
    187215                break;
    188216#ifndef DISABLE_HQ_SCALERS
    189217        case GFX_HQ2X:
    190218                newScaleFactor = 2;
    191                 newScalerProc = HQ2x;
    192219                break;
    193220        case GFX_HQ3X:
    194221                newScaleFactor = 3;
    195                 newScalerProc = HQ3x;
    196222                break;
    197223#endif
    198224        case GFX_TV2X:
    199225                newScaleFactor = 2;
    200                 newScalerProc = TV2x;
    201226                break;
    202227        case GFX_DOTMATRIX:
    203228                newScaleFactor = 2;
    204                 newScalerProc = DotMatrix;
    205229                break;
    206230#endif // DISABLE_SCALERS
    207231
     
    211235        }
    212236
    213237        _transactionDetails.normal1xScaler = (mode == GFX_NORMAL);
     238        if (_oldVideoMode.setup && _oldVideoMode.scaleFactor != newScaleFactor)
     239                _transactionDetails.needHotswap = true;
    214240
    215         _mode = mode;
    216         _scalerProc = newScalerProc;
     241        _transactionDetails.needUpdatescreen = true;
    217242
    218         if (_transactionMode == kTransactionActive) {
    219                 _transactionDetails.mode = mode;
    220                 _transactionDetails.modeChanged = true;
     243        _videoMode.mode = mode;
     244        _videoMode.scaleFactor = newScaleFactor;
    221245
    222                 if (newScaleFactor != _scaleFactor) {
    223                         _transactionDetails.needHotswap = true;
    224                         _scaleFactor = newScaleFactor;
    225                 }
     246        return true;
     247}
    226248
    227                 _transactionDetails.needUpdatescreen = true;
     249void OSystem_SDL::setGraphicsModeIntern() {
     250        Common::StackLock lock(_graphicsMutex);
     251        ScalerProc *newScalerProc = 0;
    228252
    229                 return true;
    230         }
     253        switch (_videoMode.mode) {
     254        case GFX_NORMAL:
     255                newScalerProc = Normal1x;
     256                break;
     257#ifndef DISABLE_SCALERS
     258        case GFX_DOUBLESIZE:
     259                newScalerProc = Normal2x;
     260                break;
     261        case GFX_TRIPLESIZE:
     262                newScalerProc = Normal3x;
     263                break;
    231264
    232         // NOTE: This should not be executed at transaction commit
    233         //   Otherwise there is some unsolicited setGraphicsMode() call
    234         //   which should be properly removed
    235         if (newScaleFactor != _scaleFactor) {
    236                 assert(_transactionMode != kTransactionCommit);
     265        case GFX_2XSAI:
     266                newScalerProc = _2xSaI;
     267                break;
     268        case GFX_SUPER2XSAI:
     269                newScalerProc = Super2xSaI;
     270                break;
     271        case GFX_SUPEREAGLE:
     272                newScalerProc = SuperEagle;
     273                break;
     274        case GFX_ADVMAME2X:
     275                newScalerProc = AdvMame2x;
     276                break;
     277        case GFX_ADVMAME3X:
     278                newScalerProc = AdvMame3x;
     279                break;
     280#ifndef DISABLE_HQ_SCALERS
     281        case GFX_HQ2X:
     282                newScalerProc = HQ2x;
     283                break;
     284        case GFX_HQ3X:
     285                newScalerProc = HQ3x;
     286                break;
     287#endif
     288        case GFX_TV2X:
     289                newScalerProc = TV2x;
     290                break;
     291        case GFX_DOTMATRIX:
     292                newScalerProc = DotMatrix;
     293                break;
     294#endif // DISABLE_SCALERS
    237295
    238                 _scaleFactor = newScaleFactor;
    239                 hotswapGFXMode();
     296        default:
     297                error("Unknown gfx mode %d", _videoMode.mode);
    240298        }
    241299
    242         // Determine the "scaler type", i.e. essentially an index into the
    243         // s_gfxModeSwitchTable array defined in events.cpp.
    244         if (_mode != GFX_NORMAL) {
     300        _scalerProc = newScalerProc;
     301       
     302        if (_videoMode.mode != GFX_NORMAL) {
    245303                for (int i = 0; i < ARRAYSIZE(s_gfxModeSwitchTable); i++) {
    246                         if (s_gfxModeSwitchTable[i][1] == _mode || s_gfxModeSwitchTable[i][2] == _mode) {
     304                        if (s_gfxModeSwitchTable[i][1] == _videoMode.mode || s_gfxModeSwitchTable[i][2] == _videoMode.mode) {
    247305                                _scalerType = i;
    248306                                break;
    249307                        }
    250308                }
    251309        }
    252310
    253         if (!_screen)
    254                 return true;
     311        if (!_screen || !_hwscreen)
     312                return;
    255313
    256314        // Blit everything to the screen
    257315        _forceFull = true;
     
    259317        // Even if the old and new scale factors are the same, we may have a
    260318        // different scaler for the cursor now.
    261319        blitCursor();
    262 
    263         if (_transactionMode != kTransactionCommit)
    264                 internUpdateScreen();
    265 
    266         // Make sure that an Common::EVENT_SCREEN_CHANGED gets sent later
    267         _modeChanged = true;
    268 
    269         return true;
    270320}
    271321
    272322int OSystem_SDL::getGraphicsMode() const {
    273323        assert (_transactionMode == kTransactionNone);
    274         return _mode;
     324        return _videoMode.mode;
    275325}
    276326
    277327void OSystem_SDL::initSize(uint w, uint h) {
     328        assert(_transactionMode == kTransactionActive);
     329
    278330        // Avoid redundant res changes
    279         if ((int)w == _screenWidth && (int)h == _screenHeight &&
    280                 _transactionMode != kTransactionCommit)
     331        if ((int)w == _videoMode.screenWidth && (int)h == _videoMode.screenHeight)
    281332                return;
    282333
    283         _screenWidth = w;
    284         _screenHeight = h;
     334        _videoMode.screenWidth = w;
     335        _videoMode.screenHeight = h;
    285336
    286         _cksumNum = (_screenWidth * _screenHeight / (8 * 8));
     337        _cksumNum = (w * h / (8 * 8));
    287338
    288         if (_transactionMode == kTransactionActive) {
    289                 _transactionDetails.w = w;
    290                 _transactionDetails.h = h;
    291                 _transactionDetails.sizeChanged = true;
     339        _transactionDetails.sizeChanged = true;
    292340
    293                 _transactionDetails.needUnload = true;
    294 
    295                 return;
    296         }
    297 
    298341        free(_dirtyChecksums);
    299342        _dirtyChecksums = (uint32 *)calloc(_cksumNum * 2, sizeof(uint32));
    300 
    301         if (_transactionMode != kTransactionCommit) {
    302                 unloadGFXMode();
    303                 loadGFXMode();
    304 
    305                 // if initSize() gets called in the middle, overlay is not transparent
    306                 clearOverlay();
    307         }
    308343}
    309344
    310 void OSystem_SDL::loadGFXMode() {
     345bool OSystem_SDL::loadGFXMode() {
    311346        assert(_inited);
    312347        _forceFull = true;
    313348
    314349        int hwW, hwH;
    315350
    316351#ifndef __MAEMO__
    317         _overlayWidth = _screenWidth * _scaleFactor;
    318         _overlayHeight = _screenHeight * _scaleFactor;
     352        _videoMode.overlayWidth = _videoMode.screenWidth * _videoMode.scaleFactor;
     353        _videoMode.overlayHeight = _videoMode.screenHeight * _videoMode.scaleFactor;
    319354
    320         if (_screenHeight != 200 && _screenHeight != 400)
    321                 _adjustAspectRatio = false;
     355        if (_videoMode.screenHeight != 200 && _videoMode.screenHeight != 400)
     356                _videoMode.aspectRatio = false;
    322357
    323         if (_adjustAspectRatio)
    324                 _overlayHeight = real2Aspect(_overlayHeight);
     358        if (_videoMode.aspectRatio)
     359                _videoMode.overlayHeight = real2Aspect(_videoMode.overlayHeight);
    325360
    326         hwW = _screenWidth * _scaleFactor;
     361        hwW = _videoMode.screenWidth * _videoMode.scaleFactor;
    327362        hwH = effectiveScreenHeight();
    328363#else
    329         hwW = _overlayWidth;
    330         hwH = _overlayHeight;
     364        hwW = _videoMode.overlayWidth;
     365        hwH = _videoMode.overlayHeight;
    331366#endif
    332367
    333368        //
    334369        // Create the surface that contains the 8 bit game data
    335370        //
    336         _screen = SDL_CreateRGBSurface(SDL_SWSURFACE, _screenWidth, _screenHeight, 8, 0, 0, 0, 0);
     371        _screen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.screenWidth, _videoMode.screenHeight, 8, 0, 0, 0, 0);
    337372        if (_screen == NULL)
    338373                error("allocating _screen failed");
    339374
     
    342377        //
    343378
    344379        _hwscreen = SDL_SetVideoMode(hwW, hwH, 16,
    345                 _fullscreen ? (SDL_FULLSCREEN|SDL_SWSURFACE) : SDL_SWSURFACE
     380                _videoMode.fullscreen ? (SDL_FULLSCREEN|SDL_SWSURFACE) : SDL_SWSURFACE
    346381        );
    347382        if (_hwscreen == NULL) {
    348383                // DON'T use error(), as this tries to bring up the debug
    349384                // console, which WON'T WORK now that _hwscreen is hosed.
    350385
    351                 // FIXME: We should be able to continue the game without
    352                 // shutting down or bringing up the debug console, but at
    353                 // this point we've already screwed up all our member vars.
    354                 // We need to find a way to call SDL_SetVideoMode *before*
    355                 // that happens and revert to all the old settings if we
    356                 // can't pull off the switch to the new settings.
    357                 //
    358                 // Fingolfin says: the "easy" way to do that is not to modify
    359                 // the member vars before we are sure everything is fine. Think
    360                 // of "transactions, commit, rollback" style... we use local vars
    361                 // in place of the member vars, do everything etc. etc.. In case
    362                 // of a failure, rollback is trivial. Only if everything worked fine
    363                 // do we "commit" the changed values to the member vars.
    364                 warning("SDL_SetVideoMode says we can't switch to that mode (%s)", SDL_GetError());
    365                 quit();
     386                if (!_oldVideoMode.setup) {
     387                        warning("SDL_SetVideoMode says we can't switch to that mode (%s)", SDL_GetError());
     388                        quit();
     389                } else {
     390                        return false;
     391                }
    366392        }
    367393
    368394        //
     
    376402                InitScalers(565);
    377403
    378404        // Need some extra bytes around when using 2xSaI
    379         _tmpscreen = SDL_CreateRGBSurface(SDL_SWSURFACE, _screenWidth + 3, _screenHeight + 3,
     405        _tmpscreen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.screenWidth + 3, _videoMode.screenHeight + 3,
    380406                                                16,
    381407                                                _hwscreen->format->Rmask,
    382408                                                _hwscreen->format->Gmask,
     
    386412        if (_tmpscreen == NULL)
    387413                error("allocating _tmpscreen failed");
    388414
    389         _overlayscreen = SDL_CreateRGBSurface(SDL_SWSURFACE, _overlayWidth, _overlayHeight,
     415        _overlayscreen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.overlayWidth, _videoMode.overlayHeight,
    390416                                                16,
    391417                                                _hwscreen->format->Rmask,
    392418                                                _hwscreen->format->Gmask,
     
    408434        _overlayFormat.bShift = _overlayscreen->format->Bshift;
    409435        _overlayFormat.aShift = _overlayscreen->format->Ashift;
    410436
    411         _tmpscreen2 = SDL_CreateRGBSurface(SDL_SWSURFACE, _overlayWidth + 3, _overlayHeight + 3,
     437        _tmpscreen2 = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.overlayWidth + 3, _videoMode.overlayHeight + 3,
    412438                                                16,
    413439                                                _hwscreen->format->Rmask,
    414440                                                _hwscreen->format->Gmask,
     
    433459#endif
    434460
    435461        // keyboard cursor control, some other better place for it?
    436         _km.x_max = _screenWidth * _scaleFactor - 1;
     462        _km.x_max = _videoMode.screenWidth * _videoMode.scaleFactor - 1;
    437463        _km.y_max = effectiveScreenHeight() - 1;
    438464        _km.delay_time = 25;
    439465        _km.last_time = 0;
     466
     467        return true;
    440468}
    441469
    442470void OSystem_SDL::unloadGFXMode() {
     
    474502        DestroyScalers();
    475503}
    476504
    477 void OSystem_SDL::hotswapGFXMode() {
     505bool OSystem_SDL::hotswapGFXMode() {
    478506        if (!_screen)
    479                 return;
     507                return false;
    480508
    481509        // Keep around the old _screen & _overlayscreen so we can restore the screen data
    482510        // after the mode switch.
    483511        SDL_Surface *old_screen = _screen;
    484512        SDL_Surface *old_overlayscreen = _overlayscreen;
     513        _screen = NULL;
     514        _overlayscreen = NULL;
    485515
    486516        // Release the HW screen surface
    487         SDL_FreeSurface(_hwscreen);
     517        SDL_FreeSurface(_hwscreen); _hwscreen = NULL;
    488518
    489         SDL_FreeSurface(_tmpscreen);
    490         SDL_FreeSurface(_tmpscreen2);
     519        SDL_FreeSurface(_tmpscreen); _tmpscreen = NULL;
     520        SDL_FreeSurface(_tmpscreen2); _tmpscreen2 = NULL;
    491521
    492522#ifdef USE_OSD
    493523        // Release the OSD surface
    494         SDL_FreeSurface(_osdSurface);
     524        SDL_FreeSurface(_osdSurface); _osdSurface = NULL;
    495525#endif
    496526
    497527        // Setup the new GFX mode
    498         loadGFXMode();
     528        if (!loadGFXMode()) {
     529                unloadGFXMode();
    499530
     531                _screen = old_screen;
     532                _overlayscreen = old_overlayscreen;
     533
     534                return false;
     535        }
     536
    500537        // reset palette
    501538        SDL_SetColors(_screen, _currentPalette, 0, 256);
    502539
     
    514551        // Blit everything to the screen
    515552        internUpdateScreen();
    516553
    517         // Make sure that an Common::EVENT_SCREEN_CHANGED gets sent later
    518         _modeChanged = true;
     554        return true;
    519555}
    520556
    521557void OSystem_SDL::updateScreen() {
     
    539575
    540576        // If the shake position changed, fill the dirty area with blackness
    541577        if (_currentShakePos != _newShakePos) {
    542                 SDL_Rect blackrect = {0, 0, _screenWidth * _scaleFactor, _newShakePos * _scaleFactor};
     578                SDL_Rect blackrect = {0, 0, _videoMode.screenWidth * _videoMode.scaleFactor, _newShakePos * _videoMode.scaleFactor};
    543579
    544                 if (_adjustAspectRatio && !_overlayVisible)
     580                if (_videoMode.aspectRatio && !_overlayVisible)
    545581                        blackrect.h = real2Aspect(blackrect.h - 1) + 1;
    546582
    547583                SDL_FillRect(_hwscreen, &blackrect, 0);
     
    586622        if (!_overlayVisible) {
    587623                origSurf = _screen;
    588624                srcSurf = _tmpscreen;
    589                 width = _screenWidth;
    590                 height = _screenHeight;
     625                width = _videoMode.screenWidth;
     626                height = _videoMode.screenHeight;
    591627                scalerProc = _scalerProc;
    592                 scale1 = _scaleFactor;
     628                scale1 = _videoMode.scaleFactor;
    593629        } else {
    594630                origSurf = _overlayscreen;
    595631                srcSurf = _tmpscreen2;
    596                 width = _overlayWidth;
    597                 height = _overlayHeight;
     632                width = _videoMode.overlayWidth;
     633                height = _videoMode.overlayHeight;
    598634                scalerProc = Normal1x;
    599635
    600636                scale1 = 1;
     
    647683                                orig_dst_y = dst_y;
    648684                                dst_y = dst_y * scale1;
    649685
    650                                 if (_adjustAspectRatio && !_overlayVisible)
     686                                if (_videoMode.aspectRatio && !_overlayVisible)
    651687                                        dst_y = real2Aspect(dst_y);
    652688
    653689                                assert(scalerProc != NULL);
     
    661697                        r->h = dst_h * scale1;
    662698
    663699#ifndef DISABLE_SCALERS
    664                         if (_adjustAspectRatio && orig_dst_y < height && !_overlayVisible)
     700                        if (_videoMode.aspectRatio && orig_dst_y < height && !_overlayVisible)
    665701                                r->h = stretch200To240((uint8 *) _hwscreen->pixels, dstPitch, r->w, r->h, r->x, r->y, orig_dst_y * scale1);
    666702#endif
    667703                }
     
    704740void OSystem_SDL::setFullscreenMode(bool enable) {
    705741        Common::StackLock lock(_graphicsMutex);
    706742       
    707         if (_fullscreen == enable)
     743        if (_oldVideoMode.setup && _oldVideoMode.fullscreen == enable)
    708744                return;
    709745
    710         if (_transactionMode == kTransactionCommit) {
    711                 assert(_hwscreen != 0);
    712                 _fullscreen = enable;
    713 
    714                 // Switch between fullscreen and windowed mode by invoking hotswapGFXMode().
    715                 // We used to use SDL_WM_ToggleFullScreen() in the past, but this caused various
    716                 // problems. E.g. on OS X, it was implemented incorrectly for a long time; on
    717                 // the MAEMO platform, it seems to have caused problems, too.
    718                 // And on Linux, there were some troubles, too (see bug #1705410).
    719                 // So, we just do it "manually" now. There shouldn't be any drawbacks to that
    720                 // anyway.
    721                 hotswapGFXMode();
    722         } else if (_transactionMode == kTransactionActive) {
    723                 _transactionDetails.fs = enable;
    724                 _transactionDetails.fsChanged = true;
    725 
     746        if (_transactionMode == kTransactionActive) {
     747                _videoMode.fullscreen = enable;
    726748                _transactionDetails.needHotswap = true;
    727749        }
    728750}
    729751
    730752void OSystem_SDL::setAspectRatioCorrection(bool enable) {
    731         if (((_screenHeight == 200 || _screenHeight == 400) && _adjustAspectRatio != enable) ||
    732                 _transactionMode == kTransactionCommit) {
    733                 Common::StackLock lock(_graphicsMutex);
     753        Common::StackLock lock(_graphicsMutex);
    734754
    735                 //assert(_hwscreen != 0);
    736                 _adjustAspectRatio = enable;
     755        if (_oldVideoMode.setup && _oldVideoMode.aspectRatio == enable)
     756                return;
    737757
    738                 if (_transactionMode == kTransactionActive) {
    739                         _transactionDetails.ar = enable;
    740                         _transactionDetails.arChanged = true;
    741 
    742                         _transactionDetails.needHotswap = true;
    743 
    744                         return;
    745                 } else {
    746                         if (_transactionMode != kTransactionCommit)
    747                                 hotswapGFXMode();
    748                 }
    749 
    750                 // Make sure that an Common::EVENT_SCREEN_CHANGED gets sent later
    751                 _modeChanged = true;
     758        if (_transactionMode == kTransactionActive) {
     759                _videoMode.aspectRatio = enable;
     760                _transactionDetails.needHotswap = true;
    752761        }
    753762}
    754763
     
    763772
    764773        Common::StackLock lock(_graphicsMutex); // Lock the mutex until this function ends
    765774
    766         assert(x >= 0 && x < _screenWidth);
    767         assert(y >= 0 && y < _screenHeight);
    768         assert(h > 0 && y + h <= _screenHeight);
    769         assert(w > 0 && x + w <= _screenWidth);
     775        assert(x >= 0 && x < _videoMode.screenWidth);
     776        assert(y >= 0 && y < _videoMode.screenHeight);
     777        assert(h > 0 && y + h <= _videoMode.screenHeight);
     778        assert(w > 0 && x + w <= _videoMode.screenWidth);
    770779
    771         if (((long)src & 3) == 0 && pitch == _screenWidth && x == 0 && y == 0 &&
    772                         w == _screenWidth && h == _screenHeight && _modeFlags & DF_WANT_RECT_OPTIM) {
     780        if (((long)src & 3) == 0 && pitch == _videoMode.screenWidth && x == 0 && y == 0 &&
     781                        w == _videoMode.screenWidth && h == _videoMode.screenHeight && _modeFlags & DF_WANT_RECT_OPTIM) {
    773782                /* Special, optimized case for full screen updates.
    774783                 * It tries to determine what areas were actually changed,
    775784                 * and just updates those, on the actual display. */
     
    788797                        y = 0;
    789798                }
    790799
    791                 if (w > _screenWidth - x) {
    792                         w = _screenWidth - x;
     800                if (w > _videoMode.screenWidth - x) {
     801                        w = _videoMode.screenWidth - x;
    793802                }
    794803
    795                 if (h > _screenHeight - y) {
    796                         h = _screenHeight - y;
     804                if (h > _videoMode.screenHeight - y) {
     805                        h = _videoMode.screenHeight - y;
    797806                }
    798807
    799808                if (w <= 0 || h <= 0)
     
    807816        if (SDL_LockSurface(_screen) == -1)
    808817                error("SDL_LockSurface failed: %s", SDL_GetError());
    809818
    810         byte *dst = (byte *)_screen->pixels + y * _screenWidth + x;
     819        byte *dst = (byte *)_screen->pixels + y * _videoMode.screenWidth + x;
    811820
    812         if (_screenWidth == pitch && pitch == w) {
     821        if (_videoMode.screenWidth == pitch && pitch == w) {
    813822                memcpy(dst, src, h*w);
    814823        } else {
    815824                do {
    816825                        memcpy(dst, src, w);
    817826                        src += pitch;
    818                         dst += _screenWidth;
     827                        dst += _videoMode.screenWidth;
    819828                } while (--h);
    820829        }
    821830
     
    875884        int height, width;
    876885
    877886        if (!_overlayVisible && !realCoordinates) {
    878                 width = _screenWidth;
    879                 height = _screenHeight;
     887                width = _videoMode.screenWidth;
     888                height = _videoMode.screenHeight;
    880889        } else {
    881                 width = _overlayWidth;
    882                 height = _overlayHeight;
     890                width = _videoMode.overlayWidth;
     891                height = _videoMode.overlayHeight;
    883892        }
    884893
    885894        // Extend the dirty region by 1 pixel for scalers
     
    911920        }
    912921
    913922#ifndef DISABLE_SCALERS
    914         if (_adjustAspectRatio && !_overlayVisible && !realCoordinates) {
     923        if (_videoMode.aspectRatio && !_overlayVisible && !realCoordinates) {
    915924                makeRectStretchable(x, y, w, h);
    916925        }
    917926#endif
     
    936945        assert(buf);
    937946        uint32 *sums = _dirtyChecksums;
    938947        uint x,y;
    939         const uint last_x = (uint)_screenWidth / 8;
    940         const uint last_y = (uint)_screenHeight / 8;
     948        const uint last_x = (uint)_videoMode.screenWidth / 8;
     949        const uint last_y = (uint)_videoMode.screenHeight / 8;
    941950
    942951        const uint BASE = 65521; /* largest prime smaller than 65536 */
    943952
    944953        /* the 8x8 blocks in buf are enumerated starting in the top left corner and
    945954         * reading each line at a time from left to right */
    946         for (y = 0; y != last_y; y++, buf += _screenWidth * (8 - 1))
     955        for (y = 0; y != last_y; y++, buf += _videoMode.screenWidth * (8 - 1))
    947956                for (x = 0; x != last_x; x++, buf += 8) {
    948957                        // Adler32 checksum algorithm (from RFC1950, used by gzip and zlib).
    949958                        // This computes the Adler32 checksum of a 8x8 pixel block. Note
     
    959968                                        s1 += ptr[subX];
    960969                                        s2 += s1;
    961970                                }
    962                                 ptr += _screenWidth;
     971                                ptr += _videoMode.screenWidth;
    963972                        }
    964973
    965974                        s1 %= BASE;
     
    989998                int x, y, w;
    990999                uint32 *ck = _dirtyChecksums;
    9911000
    992                 for (y = 0; y != _screenHeight / 8; y++) {
    993                         for (x = 0; x != _screenWidth / 8; x++, ck++) {
     1001                for (y = 0; y != _videoMode.screenHeight / 8; y++) {
     1002                        for (x = 0; x != _videoMode.screenWidth / 8; x++, ck++) {
    9941003                                if (ck[0] != ck[_cksumNum]) {
    9951004                                        /* found a dirty 8x8 block, now go as far to the right as possible,
    9961005                                                 and at the same time, unmark the dirty status by setting old to new. */
     
    9981007                                        do {
    9991008                                                ck[w + _cksumNum] = ck[w];
    10001009                                                w++;
    1001                                         } while (x + w != _screenWidth / 8 && ck[w] != ck[w + _cksumNum]);
     1010                                        } while (x + w != _videoMode.screenWidth / 8 && ck[w] != ck[w + _cksumNum]);
    10021011
    10031012                                        addDirtyRect(x * 8, y * 8, w * 8, 8);
    10041013
     
    10151024}
    10161025
    10171026int16 OSystem_SDL::getHeight() {
    1018         return _screenHeight;
     1027        return _videoMode.screenHeight;
    10191028}
    10201029
    10211030int16 OSystem_SDL::getWidth() {
    1022         return _screenWidth;
     1031        return _videoMode.screenWidth;
    10231032}
    10241033
    10251034void OSystem_SDL::setPalette(const byte *colors, uint start, uint num) {
     
    11051114
    11061115        // Since resolution could change, put mouse to adjusted position
    11071116        // Fixes bug #1349059
    1108         x = _mouseCurState.x * _scaleFactor;
    1109         if (_adjustAspectRatio)
    1110                 y = real2Aspect(_mouseCurState.y) * _scaleFactor;
     1117        x = _mouseCurState.x * _videoMode.scaleFactor;
     1118        if (_videoMode.aspectRatio)
     1119                y = real2Aspect(_mouseCurState.y) * _videoMode.scaleFactor;
    11111120        else
    1112                 y = _mouseCurState.y * _scaleFactor;
     1121                y = _mouseCurState.y * _videoMode.scaleFactor;
    11131122
    11141123        warpMouse(x, y);
    11151124
     
    11281137
    11291138        // Since resolution could change, put mouse to adjusted position
    11301139        // Fixes bug #1349059
    1131         x = _mouseCurState.x / _scaleFactor;
    1132         y = _mouseCurState.y / _scaleFactor;
    1133         if (_adjustAspectRatio)
     1140        x = _mouseCurState.x / _videoMode.scaleFactor;
     1141        y = _mouseCurState.y / _videoMode.scaleFactor;
     1142        if (_videoMode.aspectRatio)
    11341143                y = aspect2Real(y);
    11351144
    11361145        warpMouse(x, y);
     
    11521161        SDL_Rect src, dst;
    11531162        src.x = src.y = 0;
    11541163        dst.x = dst.y = 1;
    1155         src.w = dst.w = _screenWidth;
    1156         src.h = dst.h = _screenHeight;
     1164        src.w = dst.w = _videoMode.screenWidth;
     1165        src.h = dst.h = _videoMode.screenHeight;
    11571166        if (SDL_BlitSurface(_screen, &src, _tmpscreen, &dst) != 0)
    11581167                error("SDL_BlitSurface failed: %s", SDL_GetError());
    11591168
    11601169        SDL_LockSurface(_tmpscreen);
    11611170        SDL_LockSurface(_overlayscreen);
    11621171        _scalerProc((byte *)(_tmpscreen->pixels) + _tmpscreen->pitch + 2, _tmpscreen->pitch,
    1163         (byte *)_overlayscreen->pixels, _overlayscreen->pitch, _screenWidth, _screenHeight);
     1172        (byte *)_overlayscreen->pixels, _overlayscreen->pitch, _videoMode.screenWidth, _videoMode.screenHeight);
    11641173
    11651174#ifndef DISABLE_SCALERS
    1166         if (_adjustAspectRatio)
     1175        if (_videoMode.aspectRatio)
    11671176                stretch200To240((uint8 *)_overlayscreen->pixels, _overlayscreen->pitch,
    1168                                                 _overlayWidth, _screenHeight * _scaleFactor, 0, 0, 0);
     1177                                                _videoMode.overlayWidth, _videoMode.screenHeight * _videoMode.scaleFactor, 0, 0, 0);
    11691178#endif
    11701179        SDL_UnlockSurface(_tmpscreen);
    11711180        SDL_UnlockSurface(_overlayscreen);
     
    11831192                error("SDL_LockSurface failed: %s", SDL_GetError());
    11841193
    11851194        byte *src = (byte *)_overlayscreen->pixels;
    1186         int h = _overlayHeight;
     1195        int h = _videoMode.overlayHeight;
    11871196        do {
    1188                 memcpy(buf, src, _overlayWidth * 2);
     1197                memcpy(buf, src, _videoMode.overlayWidth * 2);
    11891198                src += _overlayscreen->pitch;
    11901199                buf += pitch;
    11911200        } while (--h);
     
    12111220                y = 0;
    12121221        }
    12131222
    1214         if (w > _overlayWidth - x) {
    1215                 w = _overlayWidth - x;
     1223        if (w > _videoMode.overlayWidth - x) {
     1224                w = _videoMode.overlayWidth - x;
    12161225        }
    12171226
    1218         if (h > _overlayHeight - y) {
    1219                 h = _overlayHeight - y;
     1227        if (h > _videoMode.overlayHeight - y) {
     1228                h = _videoMode.overlayHeight - y;
    12201229        }
    12211230
    12221231        if (w <= 0 || h <= 0)
     
    12641273void OSystem_SDL::warpMouse(int x, int y) {
    12651274        int y1 = y;
    12661275
    1267         if (_adjustAspectRatio && !_overlayVisible)
     1276        if (_videoMode.aspectRatio && !_overlayVisible)
    12681277                y1 = real2Aspect(y);
    12691278
    12701279        if (_mouseCurState.x != x || _mouseCurState.y != y) {
    12711280                if (!_overlayVisible)
    1272                         SDL_WarpMouse(x * _scaleFactor, y1 * _scaleFactor);
     1281                        SDL_WarpMouse(x * _videoMode.scaleFactor, y1 * _videoMode.scaleFactor);
    12731282                else
    12741283                        SDL_WarpMouse(x, y1);
    12751284
     
    13721381
    13731382        int rW, rH;
    13741383
    1375         if (_cursorTargetScale >= _scaleFactor) {
     1384        if (_cursorTargetScale >= _videoMode.scaleFactor) {
    13761385                // The cursor target scale is greater or equal to the scale at
    13771386                // which the rest of the screen is drawn. We do not downscale
    13781387                // the cursor image, we draw it at its original size. It will
     
    13851394
    13861395                // The virtual dimensions may be larger than the original.
    13871396
    1388                 _mouseCurState.vW = w * _cursorTargetScale / _scaleFactor;
    1389                 _mouseCurState.vH = h * _cursorTargetScale / _scaleFactor;
     1397                _mouseCurState.vW = w * _cursorTargetScale / _videoMode.scaleFactor;
     1398                _mouseCurState.vH = h * _cursorTargetScale / _videoMode.scaleFactor;
    13901399                _mouseCurState.vHotX = _mouseCurState.hotX * _cursorTargetScale /
    1391                         _scaleFactor;
     1400                        _videoMode.scaleFactor;
    13921401                _mouseCurState.vHotY = _mouseCurState.hotY * _cursorTargetScale /
    1393                         _scaleFactor;
     1402                        _videoMode.scaleFactor;
    13941403        } else {
    13951404                // The cursor target scale is smaller than the scale at which
    13961405                // the rest of the screen is drawn. We scale up the cursor
    13971406                // image to make it appear correct.
    13981407
    1399                 rW = w * _scaleFactor / _cursorTargetScale;
    1400                 rH = h * _scaleFactor / _cursorTargetScale;
    1401                 _mouseCurState.rHotX = _mouseCurState.hotX * _scaleFactor /
     1408                rW = w * _videoMode.scaleFactor / _cursorTargetScale;
     1409                rH = h * _videoMode.scaleFactor / _cursorTargetScale;
     1410                _mouseCurState.rHotX = _mouseCurState.hotX * _videoMode.scaleFactor /
    14021411                        _cursorTargetScale;
    1403                 _mouseCurState.rHotY = _mouseCurState.hotY * _scaleFactor /
     1412                _mouseCurState.rHotY = _mouseCurState.hotY * _videoMode.scaleFactor /
    14041413                        _cursorTargetScale;
    14051414
    14061415                // The virtual dimensions will be the same as the original.
     
    14151424        int rH1 = rH; // store original to pass to aspect-correction function later
    14161425#endif
    14171426
    1418         if (_adjustAspectRatio && _cursorTargetScale == 1) {
     1427        if (_videoMode.aspectRatio && _cursorTargetScale == 1) {
    14191428                rH = real2Aspect(rH - 1) + 1;
    14201429                _mouseCurState.rHotY = real2Aspect(_mouseCurState.rHotY);
    14211430        }
     
    14501459        // the game. This only works well with the non-blurring scalers so we
    14511460        // actually only use the 1x, 1.5x, 2x and AdvMame scalers.
    14521461
    1453         if (_cursorTargetScale == 1 && (_mode == GFX_DOUBLESIZE || _mode == GFX_TRIPLESIZE))
     1462        if (_cursorTargetScale == 1 && (_videoMode.mode == GFX_DOUBLESIZE || _videoMode.mode == GFX_TRIPLESIZE))
    14541463                scalerProc = _scalerProc;
    14551464        else
    1456                 scalerProc = scalersMagn[_cursorTargetScale - 1][_scaleFactor - 1];
     1465                scalerProc = scalersMagn[_cursorTargetScale - 1][_videoMode.scaleFactor - 1];
    14571466
    14581467        scalerProc((byte *)_mouseOrigSurface->pixels + _mouseOrigSurface->pitch + 2,
    14591468                _mouseOrigSurface->pitch, (byte *)_mouseSurface->pixels, _mouseSurface->pitch,
    14601469                _mouseCurState.w, _mouseCurState.h);
    14611470
    14621471#ifndef DISABLE_SCALERS
    1463         if (_adjustAspectRatio && _cursorTargetScale == 1)
     1472        if (_videoMode.aspectRatio && _cursorTargetScale == 1)
    14641473                cursorStretch200To240((uint8 *)_mouseSurface->pixels, _mouseSurface->pitch, rW, rH1, 0, 0, 0);
    14651474#endif
    14661475
     
    15031512
    15041513        // When we switch bigger overlay off mouse jumps. Argh!
    15051514        // This is intended to prevent undrawing offscreen mouse
    1506         if (!_overlayVisible && (x >= _screenWidth || y >= _screenHeight)) {
     1515        if (!_overlayVisible && (x >= _videoMode.screenWidth || y >= _videoMode.screenHeight)) {
    15071516                return;
    15081517        }
    15091518
     
    15261535        dst.y = _mouseCurState.y;
    15271536
    15281537        if (!_overlayVisible) {
    1529                 scale = _scaleFactor;
    1530                 width = _screenWidth;
    1531                 height = _screenHeight;
     1538                scale = _videoMode.scaleFactor;
     1539                width = _videoMode.screenWidth;
     1540                height = _videoMode.screenHeight;
    15321541                dst.w = _mouseCurState.vW;
    15331542                dst.h = _mouseCurState.vH;
    15341543                hotX = _mouseCurState.vHotX;
    15351544                hotY = _mouseCurState.vHotY;
    15361545        } else {
    15371546                scale = 1;
    1538                 width = _overlayWidth;
    1539                 height = _overlayHeight;
     1547                width = _videoMode.overlayWidth;
     1548                height = _videoMode.overlayHeight;
    15401549                dst.w = _mouseCurState.rW;
    15411550                dst.h = _mouseCurState.rH;
    15421551                hotX = _mouseCurState.rHotX;
     
    15581567                dst.y += _currentShakePos;
    15591568        }
    15601569
    1561         if (_adjustAspectRatio && !_overlayVisible)
     1570        if (_videoMode.aspectRatio && !_overlayVisible)
    15621571                dst.y = real2Aspect(dst.y);
    15631572
    15641573        dst.x = scale * dst.x - _mouseCurState.rHotX;
     
    16741683void OSystem_SDL::handleScalerHotkeys(const SDL_KeyboardEvent &key) {
    16751684        // Ctrl-Alt-a toggles aspect ratio correction
    16761685        if (key.keysym.sym == 'a') {
    1677                 setFeatureState(kFeatureAspectRatioCorrection, !_adjustAspectRatio);
     1686                beginGFXTransaction();
     1687                        setFeatureState(kFeatureAspectRatioCorrection, !_videoMode.aspectRatio);
     1688                endGFXTransaction();
    16781689#ifdef USE_OSD
    16791690                char buffer[128];
    1680                 if (_adjustAspectRatio)
     1691                if (_videoMode.aspectRatio)
    16811692                        sprintf(buffer, "Enabled aspect ratio correction\n%d x %d -> %d x %d",
    1682                                 _screenWidth, _screenHeight,
     1693                                _videoMode.screenWidth, _videoMode.screenHeight,
    16831694                                _hwscreen->w, _hwscreen->h
    16841695                                );
    16851696                else
    16861697                        sprintf(buffer, "Disabled aspect ratio correction\n%d x %d -> %d x %d",
    1687                                 _screenWidth, _screenHeight,
     1698                                _videoMode.screenWidth, _videoMode.screenHeight,
    16881699                                _hwscreen->w, _hwscreen->h
    16891700                                );
    16901701                displayMessageOnOSD(buffer);
     
    16941705        }
    16951706
    16961707        int newMode = -1;
    1697         int factor = _scaleFactor - 1;
     1708        int factor = _videoMode.scaleFactor - 1;
    16981709
    16991710        // Increase/decrease the scale factor
    17001711        if (key.keysym.sym == SDLK_EQUALS || key.keysym.sym == SDLK_PLUS || key.keysym.sym == SDLK_MINUS ||
     
    17201731        }
    17211732
    17221733        if (newMode >= 0) {
    1723                 setGraphicsMode(newMode);
     1734                beginGFXTransaction();
     1735                        setGraphicsMode(newMode);
     1736                endGFXTransaction();
    17241737#ifdef USE_OSD
    17251738                if (_osdSurface) {
    17261739                        const char *newScalerName = 0;
    17271740                        const GraphicsMode *g = getSupportedGraphicsModes();
    17281741                        while (g->name) {
    1729                                 if (g->id == _mode) {
     1742                                if (g->id == _videoMode.mode) {
    17301743                                        newScalerName = g->description;
    17311744                                        break;
    17321745                                }
     
    17361749                                char buffer[128];
    17371750                                sprintf(buffer, "Active graphics filter: %s\n%d x %d -> %d x %d",
    17381751                                        newScalerName,
    1739                                         _screenWidth, _screenHeight,
     1752                                        _videoMode.screenWidth, _videoMode.screenHeight,
    17401753                                        _hwscreen->w, _hwscreen->h
    17411754                                        );
    17421755                                displayMessageOnOSD(buffer);
  • backends/platform/sdl/sdl.cpp

     
    116116        // Enable unicode support if possible
    117117        SDL_EnableUNICODE(1);
    118118
     119        _oldVideoMode.setup = false;
     120        _videoMode.setup = false;
     121
    119122        _cksumValid = false;
    120123#if !defined(_WIN32_WCE) && !defined(__SYMBIAN32__) && !defined(DISABLE_SCALERS)
    121         _mode = GFX_DOUBLESIZE;
    122         _scaleFactor = 2;
     124        _videoMode.mode = GFX_DOUBLESIZE;
     125        _videoMode.scaleFactor = 2;
     126        _videoMode.aspectRatio = ConfMan.getBool("aspect_ratio");
    123127        _scalerProc = Normal2x;
    124         _adjustAspectRatio = ConfMan.getBool("aspect_ratio");
    125128#else // for small screen platforms
    126         _mode = GFX_NORMAL;
    127         _scaleFactor = 1;
     129        _videoMode.mode = GFX_NORMAL;
     130        _videoMode.scaleFactor = 1;
     131        _videoMode.aspectRatio = false;
    128132        _scalerProc = Normal1x;
    129         _adjustAspectRatio = false;
    130133#endif
    131134        _scalerType = 0;
    132135        _modeFlags = 0;
    133136
    134137#if !defined(_WIN32_WCE) && !defined(__SYMBIAN32__)
    135         _fullscreen = ConfMan.getBool("fullscreen");
     138        _videoMode.fullscreen = ConfMan.getBool("fullscreen");
    136139#else
    137         _fullscreen = true;
     140        _videoMode.fullscreen = true;
    138141#endif
    139142
    140143#if !defined(MACOSX) && !defined(__SYMBIAN32__)
     
    192195#ifdef USE_OSD
    193196        _osdSurface(0), _osdAlpha(SDL_ALPHA_TRANSPARENT), _osdFadeStartTime(0),
    194197#endif
    195         _hwscreen(0), _screen(0), _screenWidth(0), _screenHeight(0),
    196         _tmpscreen(0), _overlayWidth(0), _overlayHeight(0),
     198        _hwscreen(0), _screen(0), _tmpscreen(0),
    197199        _overlayVisible(false),
    198200        _overlayscreen(0), _tmpscreen2(0),
    199201        _samplesPerSec(0),
     
    429431
    430432        switch (f) {
    431433        case kFeatureFullscreenMode:
    432                 return _fullscreen;
     434                return _videoMode.fullscreen;
    433435        case kFeatureAspectRatioCorrection:
    434                 return _adjustAspectRatio;
     436                return _videoMode.aspectRatio;
    435437        case kFeatureAutoComputeDirtyRects:
    436438                return _modeFlags & DF_WANT_RECT_OPTIM;
    437439        default:
  • backends/platform/sdl/events.cpp

     
    7777
    7878        // Adjust for the screen scaling
    7979        if (!_overlayVisible) {
    80                 event.mouse.x /= _scaleFactor;
    81                 event.mouse.y /= _scaleFactor;
    82                 if (_adjustAspectRatio)
     80                event.mouse.x /= _videoMode.scaleFactor;
     81                event.mouse.y /= _videoMode.scaleFactor;
     82                if (_videoMode.aspectRatio)
    8383                        event.mouse.y = aspect2Real(event.mouse.y);
    8484        }
    8585}
     
    196196                        if (b == Common::KBD_ALT && (ev.key.keysym.sym == SDLK_RETURN
    197197                                          || ev.key.keysym.sym == SDLK_KP_ENTER)) {
    198198                                beginGFXTransaction();
    199                                 setFullscreenMode(!_fullscreen);
     199                                        setFullscreenMode(!_videoMode.fullscreen);
    200200                                endGFXTransaction();
    201201#ifdef USE_OSD
    202                                 if (_fullscreen)
     202                                if (_videoMode.fullscreen)
    203203                                        displayMessageOnOSD("Fullscreen mode");
    204204                                else
    205205                                        displayMessageOnOSD("Windowed mode");
  • backends/platform/sdl/sdl.h

     
    8080        virtual void initBackend();
    8181
    8282        void beginGFXTransaction(void);
    83         void endGFXTransaction(void);
     83        TransactionError endGFXTransaction(void);
    8484
    8585        // Set the size of the video bitmap.
    8686        // Typically, 320x200
     
    179179        virtual void copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h);
    180180        virtual int16 getHeight();
    181181        virtual int16 getWidth();
    182         virtual int16 getOverlayHeight()  { return _overlayHeight; }
    183         virtual int16 getOverlayWidth()   { return _overlayWidth; }
     182        virtual int16 getOverlayHeight()  { return _videoMode.overlayHeight; }
     183        virtual int16 getOverlayWidth()   { return _videoMode.overlayWidth; }
    184184
    185185        virtual const GraphicsMode *getSupportedGraphicsModes() const;
    186186        virtual int getDefaultGraphicsMode() const;
     
    226226        // unseen game screen
    227227        SDL_Surface *_screen;
    228228
    229         // TODO: We could get rid of the following two vars and just use _screen instead
    230         int _screenWidth, _screenHeight;
    231 
    232229        // temporary screen (for scalers)
    233230        SDL_Surface *_tmpscreen;
    234231        SDL_Surface *_tmpscreen2;
    235232
    236233        // overlay
    237234        SDL_Surface *_overlayscreen;
    238         int _overlayWidth, _overlayHeight;
    239235        bool _overlayVisible;
    240236        Graphics::PixelFormat _overlayFormat;
    241237
     
    253249
    254250        enum {
    255251                kTransactionNone = 0,
    256                 kTransactionCommit = 1,
    257                 kTransactionActive = 2
     252                kTransactionActive = 1,
     253                kTransactionRollback = 2
    258254        };
    259255
    260256        struct TransactionDetails {
    261                 int mode;
    262                 bool modeChanged;
    263                 int w;
    264                 int h;
    265257                bool sizeChanged;
    266                 bool fs;
    267                 bool fsChanged;
    268                 bool ar;
    269                 bool arChanged;
    270258                bool needHotswap;
    271259                bool needUpdatescreen;
    272                 bool needUnload;
    273                 bool needToggle;
    274260                bool normal1xScaler;
    275261        };
    276262        TransactionDetails _transactionDetails;
    277263
     264        struct VideoState {
     265                bool setup;
     266
     267                bool fullscreen;
     268                bool aspectRatio;
     269
     270                int mode;
     271                int scaleFactor;
     272
     273                int screenWidth, screenHeight;
     274                int overlayWidth, overlayHeight;
     275        };
     276        VideoState _videoMode, _oldVideoMode;
     277
     278        void setGraphicsModeIntern();
     279
    278280        /** Force full redraw on next updateScreen */
    279281        bool _forceFull;
    280282        ScalerProc *_scalerProc;
    281283        int _scalerType;
    282         int _scaleFactor;
    283         int _mode;
    284284        int _transactionMode;
    285         bool _fullscreen;
    286285
    287286        bool _screenIsLocked;
    288287        Graphics::Surface _framebuffer;
     
    292291        bool _modeChanged;
    293292        int _screenChangeCount;
    294293
    295         /** True if aspect ratio correction is enabled. */
    296         bool _adjustAspectRatio;
    297 
    298294        enum {
    299295                NUM_DIRTY_RECT = 100,
    300296                MAX_SCALING = 3
     
    417413
    418414        virtual void internUpdateScreen(); // overloaded by CE backend
    419415
    420         virtual void loadGFXMode(); // overloaded by CE backend
     416        virtual bool loadGFXMode(); // overloaded by CE backend
    421417        virtual void unloadGFXMode(); // overloaded by CE backend
    422         virtual void hotswapGFXMode(); // overloaded by CE backend
     418        virtual bool hotswapGFXMode(); // overloaded by CE backend
    423419
    424420        void setFullscreenMode(bool enable);
    425421        void setAspectRatioCorrection(bool enable);
     
    427423        virtual bool saveScreenshot(const char *filename); // overloaded by CE backend
    428424
    429425        int effectiveScreenHeight() const {
    430                 return (_adjustAspectRatio ? real2Aspect(_screenHeight) : _screenHeight)
    431                         * _scaleFactor;
     426                return (_videoMode.aspectRatio ? real2Aspect(_videoMode.screenHeight) : _videoMode.screenHeight)
     427                        * _videoMode.scaleFactor;
    432428        }
    433429
    434430        void setupIcon();
  • base/main.cpp

     
    6767                        system.setFeatureState(OSystem::kFeatureAspectRatioCorrection, ConfMan.getBool("aspect_ratio"));
    6868                if (ConfMan.hasKey("fullscreen"))
    6969                        system.setFeatureState(OSystem::kFeatureFullscreenMode, ConfMan.getBool("fullscreen"));
    70         system.endGFXTransaction();
     70        if (system.endGFXTransaction() != OSystem::kTransactionSuccess)
     71                error("Could not switch to graphics mode: 320x200 ('%s')", ConfMan.get("gfx_mode").c_str());
    7172
    7273        // When starting up launcher for the first time, the user might have specified
    7374        // a --gui-theme option, to allow that option to be working, we need to initialize