diff --git a/src/common/FrameBufferGL.cxx b/src/common/FrameBufferGL.cxx index 48654041a..9f9860945 100644 --- a/src/common/FrameBufferGL.cxx +++ b/src/common/FrameBufferGL.cxx @@ -337,6 +337,8 @@ bool FrameBufferGL::setVidMode(VideoMode& mode) cerr << "ERROR: Unable to open SDL window: " << SDL_GetError() << endl; return false; } + // Make sure the flags represent the current screen state + mySDLFlags = myScreen->flags; // Reload OpenGL function pointers. This only seems to be needed for Windows // Vista, but it shouldn't hurt on other systems. diff --git a/src/common/FrameBufferSoft.cxx b/src/common/FrameBufferSoft.cxx index f118d90aa..66225f8d2 100644 --- a/src/common/FrameBufferSoft.cxx +++ b/src/common/FrameBufferSoft.cxx @@ -102,6 +102,9 @@ bool FrameBufferSoft::setVidMode(VideoMode& mode) myFormat = myScreen->format; myBytesPerPixel = myFormat->BytesPerPixel; + // Make sure the flags represent the current screen state + mySDLFlags = myScreen->flags; + // Make sure drawTIA() knows which renderer to use switch(myBytesPerPixel) { diff --git a/src/emucore/Cart3E.cxx b/src/emucore/Cart3E.cxx index 6dd3ba07a..5f1496caf 100644 --- a/src/emucore/Cart3E.cxx +++ b/src/emucore/Cart3E.cxx @@ -97,6 +97,7 @@ void Cartridge3E::install(System& system) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt8 Cartridge3E::peek(uInt16 address) { + // TODO - determine what really happens when you read from the write port address &= 0x0FFF; if(address < 0x0800) diff --git a/src/emucore/CartCV.cxx b/src/emucore/CartCV.cxx index 5fa7aaf28..3a0f2a96a 100644 --- a/src/emucore/CartCV.cxx +++ b/src/emucore/CartCV.cxx @@ -80,13 +80,13 @@ void CartridgeCV::install(System& system) assert((0x1800 & mask) == 0); System::PageAccess access; - access.directPokeBase = 0; - access.device = this; // Map ROM image into the system for(uInt32 address = 0x1800; address < 0x2000; address += (1 << shift)) { + access.device = this; access.directPeekBase = &myImage[address & 0x07FF]; + access.directPokeBase = 0; mySystem->setPageAccess(address >> mySystem->pageShift(), access); } @@ -112,7 +112,18 @@ void CartridgeCV::install(System& system) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - uInt8 CartridgeCV::peek(uInt16 address) { - return myImage[address & 0x07FF]; + // Reading from the write port triggers an unwanted write + // The value written to RAM is somewhat undefined, so we use 0 + // Thanks to Kroko of AtariAge for this advice and code idea + if(address & 0x0FFF < 0x0800) // Write port is at 0xF400 - 0xF800 (1024 bytes) + { // Read port is handled in ::install() + if(myBankLocked) return 0; + else return myRAM[address & 0x03FF] = 0; + } + else + { + return myImage[address & 0x07FF]; + } } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/emucore/CartE7.cxx b/src/emucore/CartE7.cxx index 0222cdef9..e2f656a9b 100644 --- a/src/emucore/CartE7.cxx +++ b/src/emucore/CartE7.cxx @@ -109,6 +109,7 @@ uInt8 CartridgeE7::peek(uInt16 address) // NOTE: The following does not handle reading from RAM, however, // this function should never be called for RAM because of the // way page accessing has been setup + // TODO - determine what really happens when you read from the write port return myImage[(myCurrentSlice[address >> 11] << 11) + (address & 0x07FF)]; } @@ -142,23 +143,23 @@ void CartridgeE7::bankRAM(uInt16 bank) // Setup the page access methods for the current bank System::PageAccess access; - access.device = this; // Set the page accessing method for the 256 bytes of RAM writing pages - access.directPeekBase = 0; - access.directPokeBase = 0; for(uInt32 j = 0x1800; j < 0x1900; j += (1 << shift)) { + access.device = this; + access.directPeekBase = 0; access.directPokeBase = &myRAM[1024 + offset + (j & 0x00FF)]; mySystem->setPageAccess(j >> shift, access); } // Set the page accessing method for the 256 bytes of RAM reading pages access.directPeekBase = 0; - access.directPokeBase = 0; for(uInt32 k = 0x1900; k < 0x1A00; k += (1 << shift)) { + access.device = this; access.directPeekBase = &myRAM[1024 + offset + (k & 0x00FF)]; + access.directPokeBase = 0; mySystem->setPageAccess(k >> shift, access); } } @@ -173,40 +174,37 @@ void CartridgeE7::bank(uInt16 slice) uInt16 offset = slice << 11; uInt16 shift = mySystem->pageShift(); + System::PageAccess access; + // Setup the page access methods for the current bank if(slice != 7) { - System::PageAccess access; - access.device = this; - access.directPokeBase = 0; - // Map ROM image into first segment for(uInt32 address = 0x1000; address < 0x1800; address += (1 << shift)) { + access.device = this; access.directPeekBase = &myImage[offset + (address & 0x07FF)]; + access.directPokeBase = 0; mySystem->setPageAccess(address >> shift, access); } } else { - System::PageAccess access; - access.device = this; - // Set the page accessing method for the 1K slice of RAM writing pages - access.directPeekBase = 0; - access.directPokeBase = 0; for(uInt32 j = 0x1000; j < 0x1400; j += (1 << shift)) { + access.device = this; + access.directPeekBase = 0; access.directPokeBase = &myRAM[j & 0x03FF]; mySystem->setPageAccess(j >> shift, access); } // Set the page accessing method for the 1K slice of RAM reading pages - access.directPeekBase = 0; - access.directPokeBase = 0; for(uInt32 k = 0x1400; k < 0x1800; k += (1 << shift)) { + access.device = this; access.directPeekBase = &myRAM[k & 0x03FF]; + access.directPokeBase = 0; mySystem->setPageAccess(k >> shift, access); } } diff --git a/src/emucore/EventHandler.cxx b/src/emucore/EventHandler.cxx index fedb56d60..15c777bfe 100644 --- a/src/emucore/EventHandler.cxx +++ b/src/emucore/EventHandler.cxx @@ -972,8 +972,15 @@ void EventHandler::handleEvent(Event::Type event, int state) if((myState == S_EMULATE || myState == S_CMDMENU) && state) { myOSystem->settings().saveConfig(); - myOSystem->deleteConsole(); - myOSystem->createLauncher(); + + // Go back to the launcher, or immediately quit + if(!myOSystem->settings().getBool("exitlauncher")) + { + myOSystem->deleteConsole(); + myOSystem->createLauncher(); + } + else + myOSystem->quit(); } return; diff --git a/src/emucore/FrameBuffer.cxx b/src/emucore/FrameBuffer.cxx index dd7de1f66..1911a30e7 100644 --- a/src/emucore/FrameBuffer.cxx +++ b/src/emucore/FrameBuffer.cxx @@ -88,6 +88,13 @@ bool FrameBuffer::initialize(const string& title, uInt32 width, uInt32 height) return false; #endif + // Initialize SDL flags and set fullscreen flag + // This must be done before any modes are initialized + mySDLFlags = 0; +#ifdef WINDOWED_SUPPORT + if(myOSystem->settings().getBool("fullscreen")) mySDLFlags = SDL_FULLSCREEN; +#endif + // Set the available video modes for this framebuffer setAvailableVidModes(width, height); @@ -99,13 +106,6 @@ bool FrameBuffer::initialize(const string& title, uInt32 width, uInt32 height) setWindowTitle(title); if(myInitializedCount == 1) setWindowIcon(); - // Set fullscreen flag - #ifdef WINDOWED_SUPPORT - mySDLFlags = myOSystem->settings().getBool("fullscreen") ? SDL_FULLSCREEN : 0; - #else - mySDLFlags = 0; - #endif - if(!initSubsystem(mode)) { cerr << "ERROR: Couldn't initialize video subsystem" << endl; @@ -119,6 +119,9 @@ bool FrameBuffer::initialize(const string& title, uInt32 width, uInt32 height) myScreenRect.setWidth(mode.screen_w); myScreenRect.setHeight(mode.screen_h); + + // Did we get the requested fullscreen state? + myOSystem->settings().setBool("fullscreen", fullScreen()); } } else @@ -599,15 +602,13 @@ void FrameBuffer::stateChanged(EventHandler::State state) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void FrameBuffer::toggleFullscreen() { - setFullscreen(!myOSystem->settings().getBool("fullscreen")); + setFullscreen(!fullScreen()); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void FrameBuffer::setFullscreen(bool enable) { #ifdef WINDOWED_SUPPORT - // Update the settings - myOSystem->settings().setBool("fullscreen", enable); if(enable) mySDLFlags |= SDL_FULLSCREEN; else @@ -642,7 +643,7 @@ bool FrameBuffer::changeVidMode(int direction) else if(direction == -1) myCurrentModeList->previous(); - VideoMode vidmode = myCurrentModeList->current(myOSystem->settings()); + VideoMode vidmode = myCurrentModeList->current(myOSystem->settings(), fullScreen()); if(setVidMode(vidmode)) { myImageRect.setWidth(vidmode.image_w); @@ -652,6 +653,9 @@ bool FrameBuffer::changeVidMode(int direction) myScreenRect.setWidth(vidmode.screen_w); myScreenRect.setHeight(vidmode.screen_h); + // Did we get the requested fullscreen state? + myOSystem->settings().setBool("fullscreen", fullScreen()); + if(!inUIMode) { setCursorState(); @@ -684,9 +688,7 @@ cerr << "New mode:" << endl // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - void FrameBuffer::setCursorState() { - bool isFullscreen = myOSystem->settings().getBool("fullscreen"); - - if(isFullscreen) + if(fullScreen()) grabMouse(true); else grabMouse(myOSystem->settings().getBool("grabmouse")); @@ -718,9 +720,9 @@ void FrameBuffer::grabMouse(bool grab) bool FrameBuffer::fullScreen() const { #ifdef WINDOWED_SUPPORT - return myOSystem->settings().getBool("fullscreen"); + return mySDLFlags & SDL_FULLSCREEN; #else - return true; + return true; #endif } @@ -930,7 +932,7 @@ FrameBuffer::VideoMode FrameBuffer::getSavedVidMode() { EventHandler::State state = myOSystem->eventHandler().state(); - if(myOSystem->settings().getBool("fullscreen")) + if(fullScreen()) myCurrentModeList = &myFullscreenModeList; else myCurrentModeList = &myWindowedModeList; @@ -948,13 +950,13 @@ FrameBuffer::VideoMode FrameBuffer::getSavedVidMode() myCurrentModeList->setByGfxMode(name); } - return myCurrentModeList->current(myOSystem->settings()); + return myCurrentModeList->current(myOSystem->settings(), fullScreen()); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - FrameBuffer::VideoModeList::VideoModeList() + : myIdx(-1) { - myIdx = -1; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -996,14 +998,13 @@ void FrameBuffer::VideoModeList::previous() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - const FrameBuffer::VideoMode FrameBuffer:: - VideoModeList::current(const Settings& settings) const + VideoModeList::current(const Settings& settings, bool isFullscreen) const { // Fullscreen modes are related to the 'fullres' setting // If it's 'auto', we just use the mode as already previously defined // If it's not 'auto', attempt to fit the mode into the resolution // specified by 'fullres' (if possible) - if(settings.getBool("fullscreen") && - BSPF_tolower(settings.getString("fullres")) != "auto") + if(isFullscreen && BSPF_tolower(settings.getString("fullres")) != "auto") { // Only use 'fullres' if it's *bigger* than the requested mode int w, h; diff --git a/src/emucore/FrameBuffer.hxx b/src/emucore/FrameBuffer.hxx index 4bbdf6231..7df09f2e8 100644 --- a/src/emucore/FrameBuffer.hxx +++ b/src/emucore/FrameBuffer.hxx @@ -417,6 +417,9 @@ class FrameBuffer SDL_Surface* myScreen; // SDL initialization flags + // This is set by the base FrameBuffer class, and read by the derived classes + // If a FrameBuffer is successfully created, the derived classes must modify + // it to point to the actual flags used by the SDL_Surface uInt32 mySDLFlags; // Indicates if the entire frame need to redrawn @@ -509,7 +512,8 @@ class FrameBuffer uInt32 size() const; void previous(); - const FrameBuffer::VideoMode current(const Settings& settings) const; + const FrameBuffer::VideoMode current(const Settings& settings, + bool isFullscreen) const; void next(); void setByGfxMode(GfxID id); diff --git a/src/emucore/Settings.cxx b/src/emucore/Settings.cxx index 2c1a45d9e..0a3f7a1b6 100644 --- a/src/emucore/Settings.cxx +++ b/src/emucore/Settings.cxx @@ -100,6 +100,7 @@ Settings::Settings(OSystem* osystem) setInternal("launcherres", "640x480"); setInternal("launcherfont", "medium"); setInternal("launcherexts", "allfiles"); + setInternal("exitlauncher", "false"); setInternal("romviewer", "0"); setInternal("lastrom", ""); @@ -365,6 +366,7 @@ void Settings::usage() << " -launcherexts Don't go back to ROM launcher after playing a game\n" << " -romviewer <0|1|2> Show ROM info viewer at given zoom level in ROM launcher (0 for off)\n" << " -uipalette <1|2> Used the specified palette for UI elements\n" << " -listdelay Time to wait between keypresses in list widgets (300-1000)\n" diff --git a/src/gui/UIDialog.cxx b/src/gui/UIDialog.cxx index 606474027..ae0523aea 100644 --- a/src/gui/UIDialog.cxx +++ b/src/gui/UIDialog.cxx @@ -53,7 +53,7 @@ UIDialog::UIDialog(OSystem* osystem, DialogContainer* parent, // Set real dimensions _w = 42 * fontWidth + 10; - _h = 9 * (lineHeight + 4) + 10; + _h = 10 * (lineHeight + 4) + 10; // The tab widget xpos = ypos = vBorder; @@ -117,6 +117,12 @@ UIDialog::UIDialog(OSystem* osystem, DialogContainer* parent, new PopUpWidget(myTab, font, xpos, ypos+1, pwidth, lineHeight, items, "ROM Info viewer: ", lwidth); wid.push_back(myRomViewerPopup); + ypos += lineHeight + 4; + + // Should exiting a game go back to launcher + myExitLauncherBox = new CheckboxWidget(myTab, font, xpos+20, ypos+10, + "Enter launcher after exiting ROM"); + wid.push_back(myExitLauncherBox); // Add message concerning usage xpos = vBorder; ypos += 2*(lineHeight + 4); @@ -278,6 +284,9 @@ void UIDialog::loadConfig() const string& viewer = instance().settings().getString("romviewer"); myRomViewerPopup->setSelected(viewer, "0"); + // Exit launcher after a game + myExitLauncherBox->setState(!instance().settings().getBool("exitlauncher")); + // Debugger size instance().settings().getSize("debuggerres", w, h); w = BSPF_max(w, 1050); @@ -324,6 +333,9 @@ void UIDialog::saveConfig() instance().settings().setString("romviewer", myRomViewerPopup->getSelectedTag()); + // Exit launcher after a game + instance().settings().setBool("exitlauncher", !myExitLauncherBox->getState()); + // Debugger size instance().settings().setSize("debuggerres", myDebuggerWidthSlider->getValue(), myDebuggerHeightSlider->getValue()); @@ -358,6 +370,7 @@ void UIDialog::setDefaults() myLauncherHeightLabel->setValue(h); myLauncherFontPopup->setSelected("medium", ""); myRomViewerPopup->setSelected("0", ""); + myExitLauncherBox->setState(true); break; } diff --git a/src/gui/UIDialog.hxx b/src/gui/UIDialog.hxx index 1ad1a0d9f..c9bccc8f4 100644 --- a/src/gui/UIDialog.hxx +++ b/src/gui/UIDialog.hxx @@ -50,6 +50,7 @@ class UIDialog : public Dialog StaticTextWidget* myLauncherHeightLabel; PopUpWidget* myLauncherFontPopup; PopUpWidget* myRomViewerPopup; + CheckboxWidget* myExitLauncherBox; // Debugger options SliderWidget* myDebuggerWidthSlider;