Handle 'read from write port' functionality for CV carts. Still TODO are

the ones that bankswitch in RAM, since I don't know what should happen there.

Added 'exitlauncher' commandline argument, which specifies the functionality
of the 'Exit to launcher' action; should exiting a game actually go back to
the launcher, or exit the program entirely.  Also added a UI item in UIDialog
for this.

Reworked the fullscreen/windowed handling in FrameBuffer, simplifying the
logic for determining whether the SDL surface is actually in fullscreen
or not.


git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1752 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2009-06-05 14:05:23 +00:00
parent f76af14b25
commit 2bc2ff639c
11 changed files with 87 additions and 44 deletions

View File

@ -337,6 +337,8 @@ bool FrameBufferGL::setVidMode(VideoMode& mode)
cerr << "ERROR: Unable to open SDL window: " << SDL_GetError() << endl; cerr << "ERROR: Unable to open SDL window: " << SDL_GetError() << endl;
return false; 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 // Reload OpenGL function pointers. This only seems to be needed for Windows
// Vista, but it shouldn't hurt on other systems. // Vista, but it shouldn't hurt on other systems.

View File

@ -102,6 +102,9 @@ bool FrameBufferSoft::setVidMode(VideoMode& mode)
myFormat = myScreen->format; myFormat = myScreen->format;
myBytesPerPixel = myFormat->BytesPerPixel; myBytesPerPixel = myFormat->BytesPerPixel;
// Make sure the flags represent the current screen state
mySDLFlags = myScreen->flags;
// Make sure drawTIA() knows which renderer to use // Make sure drawTIA() knows which renderer to use
switch(myBytesPerPixel) switch(myBytesPerPixel)
{ {

View File

@ -97,6 +97,7 @@ void Cartridge3E::install(System& system)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 Cartridge3E::peek(uInt16 address) uInt8 Cartridge3E::peek(uInt16 address)
{ {
// TODO - determine what really happens when you read from the write port
address &= 0x0FFF; address &= 0x0FFF;
if(address < 0x0800) if(address < 0x0800)

View File

@ -80,13 +80,13 @@ void CartridgeCV::install(System& system)
assert((0x1800 & mask) == 0); assert((0x1800 & mask) == 0);
System::PageAccess access; System::PageAccess access;
access.directPokeBase = 0;
access.device = this;
// Map ROM image into the system // Map ROM image into the system
for(uInt32 address = 0x1800; address < 0x2000; address += (1 << shift)) for(uInt32 address = 0x1800; address < 0x2000; address += (1 << shift))
{ {
access.device = this;
access.directPeekBase = &myImage[address & 0x07FF]; access.directPeekBase = &myImage[address & 0x07FF];
access.directPokeBase = 0;
mySystem->setPageAccess(address >> mySystem->pageShift(), access); mySystem->setPageAccess(address >> mySystem->pageShift(), access);
} }
@ -112,7 +112,18 @@ void CartridgeCV::install(System& system)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt8 CartridgeCV::peek(uInt16 address) 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];
}
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -109,6 +109,7 @@ uInt8 CartridgeE7::peek(uInt16 address)
// NOTE: The following does not handle reading from RAM, however, // NOTE: The following does not handle reading from RAM, however,
// this function should never be called for RAM because of the // this function should never be called for RAM because of the
// way page accessing has been setup // 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)]; 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 // Setup the page access methods for the current bank
System::PageAccess access; System::PageAccess access;
access.device = this;
// Set the page accessing method for the 256 bytes of RAM writing pages // 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)) for(uInt32 j = 0x1800; j < 0x1900; j += (1 << shift))
{ {
access.device = this;
access.directPeekBase = 0;
access.directPokeBase = &myRAM[1024 + offset + (j & 0x00FF)]; access.directPokeBase = &myRAM[1024 + offset + (j & 0x00FF)];
mySystem->setPageAccess(j >> shift, access); mySystem->setPageAccess(j >> shift, access);
} }
// Set the page accessing method for the 256 bytes of RAM reading pages // Set the page accessing method for the 256 bytes of RAM reading pages
access.directPeekBase = 0; access.directPeekBase = 0;
access.directPokeBase = 0;
for(uInt32 k = 0x1900; k < 0x1A00; k += (1 << shift)) for(uInt32 k = 0x1900; k < 0x1A00; k += (1 << shift))
{ {
access.device = this;
access.directPeekBase = &myRAM[1024 + offset + (k & 0x00FF)]; access.directPeekBase = &myRAM[1024 + offset + (k & 0x00FF)];
access.directPokeBase = 0;
mySystem->setPageAccess(k >> shift, access); mySystem->setPageAccess(k >> shift, access);
} }
} }
@ -173,40 +174,37 @@ void CartridgeE7::bank(uInt16 slice)
uInt16 offset = slice << 11; uInt16 offset = slice << 11;
uInt16 shift = mySystem->pageShift(); uInt16 shift = mySystem->pageShift();
System::PageAccess access;
// Setup the page access methods for the current bank // Setup the page access methods for the current bank
if(slice != 7) if(slice != 7)
{ {
System::PageAccess access;
access.device = this;
access.directPokeBase = 0;
// Map ROM image into first segment // Map ROM image into first segment
for(uInt32 address = 0x1000; address < 0x1800; address += (1 << shift)) for(uInt32 address = 0x1000; address < 0x1800; address += (1 << shift))
{ {
access.device = this;
access.directPeekBase = &myImage[offset + (address & 0x07FF)]; access.directPeekBase = &myImage[offset + (address & 0x07FF)];
access.directPokeBase = 0;
mySystem->setPageAccess(address >> shift, access); mySystem->setPageAccess(address >> shift, access);
} }
} }
else else
{ {
System::PageAccess access;
access.device = this;
// Set the page accessing method for the 1K slice of RAM writing pages // 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)) for(uInt32 j = 0x1000; j < 0x1400; j += (1 << shift))
{ {
access.device = this;
access.directPeekBase = 0;
access.directPokeBase = &myRAM[j & 0x03FF]; access.directPokeBase = &myRAM[j & 0x03FF];
mySystem->setPageAccess(j >> shift, access); mySystem->setPageAccess(j >> shift, access);
} }
// Set the page accessing method for the 1K slice of RAM reading pages // 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)) for(uInt32 k = 0x1400; k < 0x1800; k += (1 << shift))
{ {
access.device = this;
access.directPeekBase = &myRAM[k & 0x03FF]; access.directPeekBase = &myRAM[k & 0x03FF];
access.directPokeBase = 0;
mySystem->setPageAccess(k >> shift, access); mySystem->setPageAccess(k >> shift, access);
} }
} }

View File

@ -972,8 +972,15 @@ void EventHandler::handleEvent(Event::Type event, int state)
if((myState == S_EMULATE || myState == S_CMDMENU) && state) if((myState == S_EMULATE || myState == S_CMDMENU) && state)
{ {
myOSystem->settings().saveConfig(); 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; return;

View File

@ -88,6 +88,13 @@ bool FrameBuffer::initialize(const string& title, uInt32 width, uInt32 height)
return false; return false;
#endif #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 // Set the available video modes for this framebuffer
setAvailableVidModes(width, height); setAvailableVidModes(width, height);
@ -99,13 +106,6 @@ bool FrameBuffer::initialize(const string& title, uInt32 width, uInt32 height)
setWindowTitle(title); setWindowTitle(title);
if(myInitializedCount == 1) setWindowIcon(); 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)) if(!initSubsystem(mode))
{ {
cerr << "ERROR: Couldn't initialize video subsystem" << endl; 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.setWidth(mode.screen_w);
myScreenRect.setHeight(mode.screen_h); myScreenRect.setHeight(mode.screen_h);
// Did we get the requested fullscreen state?
myOSystem->settings().setBool("fullscreen", fullScreen());
} }
} }
else else
@ -599,15 +602,13 @@ void FrameBuffer::stateChanged(EventHandler::State state)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::toggleFullscreen() void FrameBuffer::toggleFullscreen()
{ {
setFullscreen(!myOSystem->settings().getBool("fullscreen")); setFullscreen(!fullScreen());
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::setFullscreen(bool enable) void FrameBuffer::setFullscreen(bool enable)
{ {
#ifdef WINDOWED_SUPPORT #ifdef WINDOWED_SUPPORT
// Update the settings
myOSystem->settings().setBool("fullscreen", enable);
if(enable) if(enable)
mySDLFlags |= SDL_FULLSCREEN; mySDLFlags |= SDL_FULLSCREEN;
else else
@ -642,7 +643,7 @@ bool FrameBuffer::changeVidMode(int direction)
else if(direction == -1) else if(direction == -1)
myCurrentModeList->previous(); myCurrentModeList->previous();
VideoMode vidmode = myCurrentModeList->current(myOSystem->settings()); VideoMode vidmode = myCurrentModeList->current(myOSystem->settings(), fullScreen());
if(setVidMode(vidmode)) if(setVidMode(vidmode))
{ {
myImageRect.setWidth(vidmode.image_w); myImageRect.setWidth(vidmode.image_w);
@ -652,6 +653,9 @@ bool FrameBuffer::changeVidMode(int direction)
myScreenRect.setWidth(vidmode.screen_w); myScreenRect.setWidth(vidmode.screen_w);
myScreenRect.setHeight(vidmode.screen_h); myScreenRect.setHeight(vidmode.screen_h);
// Did we get the requested fullscreen state?
myOSystem->settings().setBool("fullscreen", fullScreen());
if(!inUIMode) if(!inUIMode)
{ {
setCursorState(); setCursorState();
@ -684,9 +688,7 @@ cerr << "New mode:" << endl
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::setCursorState() void FrameBuffer::setCursorState()
{ {
bool isFullscreen = myOSystem->settings().getBool("fullscreen"); if(fullScreen())
if(isFullscreen)
grabMouse(true); grabMouse(true);
else else
grabMouse(myOSystem->settings().getBool("grabmouse")); grabMouse(myOSystem->settings().getBool("grabmouse"));
@ -718,9 +720,9 @@ void FrameBuffer::grabMouse(bool grab)
bool FrameBuffer::fullScreen() const bool FrameBuffer::fullScreen() const
{ {
#ifdef WINDOWED_SUPPORT #ifdef WINDOWED_SUPPORT
return myOSystem->settings().getBool("fullscreen"); return mySDLFlags & SDL_FULLSCREEN;
#else #else
return true; return true;
#endif #endif
} }
@ -930,7 +932,7 @@ FrameBuffer::VideoMode FrameBuffer::getSavedVidMode()
{ {
EventHandler::State state = myOSystem->eventHandler().state(); EventHandler::State state = myOSystem->eventHandler().state();
if(myOSystem->settings().getBool("fullscreen")) if(fullScreen())
myCurrentModeList = &myFullscreenModeList; myCurrentModeList = &myFullscreenModeList;
else else
myCurrentModeList = &myWindowedModeList; myCurrentModeList = &myWindowedModeList;
@ -948,13 +950,13 @@ FrameBuffer::VideoMode FrameBuffer::getSavedVidMode()
myCurrentModeList->setByGfxMode(name); myCurrentModeList->setByGfxMode(name);
} }
return myCurrentModeList->current(myOSystem->settings()); return myCurrentModeList->current(myOSystem->settings(), fullScreen());
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FrameBuffer::VideoModeList::VideoModeList() FrameBuffer::VideoModeList::VideoModeList()
: myIdx(-1)
{ {
myIdx = -1;
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -996,14 +998,13 @@ void FrameBuffer::VideoModeList::previous()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const FrameBuffer::VideoMode FrameBuffer:: 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 // Fullscreen modes are related to the 'fullres' setting
// If it's 'auto', we just use the mode as already previously defined // 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 // If it's not 'auto', attempt to fit the mode into the resolution
// specified by 'fullres' (if possible) // specified by 'fullres' (if possible)
if(settings.getBool("fullscreen") && if(isFullscreen && BSPF_tolower(settings.getString("fullres")) != "auto")
BSPF_tolower(settings.getString("fullres")) != "auto")
{ {
// Only use 'fullres' if it's *bigger* than the requested mode // Only use 'fullres' if it's *bigger* than the requested mode
int w, h; int w, h;

View File

@ -417,6 +417,9 @@ class FrameBuffer
SDL_Surface* myScreen; SDL_Surface* myScreen;
// SDL initialization flags // 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; uInt32 mySDLFlags;
// Indicates if the entire frame need to redrawn // Indicates if the entire frame need to redrawn
@ -509,7 +512,8 @@ class FrameBuffer
uInt32 size() const; uInt32 size() const;
void previous(); void previous();
const FrameBuffer::VideoMode current(const Settings& settings) const; const FrameBuffer::VideoMode current(const Settings& settings,
bool isFullscreen) const;
void next(); void next();
void setByGfxMode(GfxID id); void setByGfxMode(GfxID id);

View File

@ -100,6 +100,7 @@ Settings::Settings(OSystem* osystem)
setInternal("launcherres", "640x480"); setInternal("launcherres", "640x480");
setInternal("launcherfont", "medium"); setInternal("launcherfont", "medium");
setInternal("launcherexts", "allfiles"); setInternal("launcherexts", "allfiles");
setInternal("exitlauncher", "false");
setInternal("romviewer", "0"); setInternal("romviewer", "0");
setInternal("lastrom", ""); setInternal("lastrom", "");
@ -365,6 +366,7 @@ void Settings::usage()
<< " -launcherexts <allfiles| Show files with the given extensions in ROM launcher\n" << " -launcherexts <allfiles| Show files with the given extensions in ROM launcher\n"
<< " allroms| (exts is a ':' separated list of extensions)\n" << " allroms| (exts is a ':' separated list of extensions)\n"
<< " exts\n" << " exts\n"
<< " -exitlauncher <1|0> 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" << " -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" << " -uipalette <1|2> Used the specified palette for UI elements\n"
<< " -listdelay <delay> Time to wait between keypresses in list widgets (300-1000)\n" << " -listdelay <delay> Time to wait between keypresses in list widgets (300-1000)\n"

View File

@ -53,7 +53,7 @@ UIDialog::UIDialog(OSystem* osystem, DialogContainer* parent,
// Set real dimensions // Set real dimensions
_w = 42 * fontWidth + 10; _w = 42 * fontWidth + 10;
_h = 9 * (lineHeight + 4) + 10; _h = 10 * (lineHeight + 4) + 10;
// The tab widget // The tab widget
xpos = ypos = vBorder; xpos = ypos = vBorder;
@ -117,6 +117,12 @@ UIDialog::UIDialog(OSystem* osystem, DialogContainer* parent,
new PopUpWidget(myTab, font, xpos, ypos+1, pwidth, lineHeight, items, new PopUpWidget(myTab, font, xpos, ypos+1, pwidth, lineHeight, items,
"ROM Info viewer: ", lwidth); "ROM Info viewer: ", lwidth);
wid.push_back(myRomViewerPopup); 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 // Add message concerning usage
xpos = vBorder; ypos += 2*(lineHeight + 4); xpos = vBorder; ypos += 2*(lineHeight + 4);
@ -278,6 +284,9 @@ void UIDialog::loadConfig()
const string& viewer = instance().settings().getString("romviewer"); const string& viewer = instance().settings().getString("romviewer");
myRomViewerPopup->setSelected(viewer, "0"); myRomViewerPopup->setSelected(viewer, "0");
// Exit launcher after a game
myExitLauncherBox->setState(!instance().settings().getBool("exitlauncher"));
// Debugger size // Debugger size
instance().settings().getSize("debuggerres", w, h); instance().settings().getSize("debuggerres", w, h);
w = BSPF_max(w, 1050); w = BSPF_max(w, 1050);
@ -324,6 +333,9 @@ void UIDialog::saveConfig()
instance().settings().setString("romviewer", instance().settings().setString("romviewer",
myRomViewerPopup->getSelectedTag()); myRomViewerPopup->getSelectedTag());
// Exit launcher after a game
instance().settings().setBool("exitlauncher", !myExitLauncherBox->getState());
// Debugger size // Debugger size
instance().settings().setSize("debuggerres", instance().settings().setSize("debuggerres",
myDebuggerWidthSlider->getValue(), myDebuggerHeightSlider->getValue()); myDebuggerWidthSlider->getValue(), myDebuggerHeightSlider->getValue());
@ -358,6 +370,7 @@ void UIDialog::setDefaults()
myLauncherHeightLabel->setValue(h); myLauncherHeightLabel->setValue(h);
myLauncherFontPopup->setSelected("medium", ""); myLauncherFontPopup->setSelected("medium", "");
myRomViewerPopup->setSelected("0", ""); myRomViewerPopup->setSelected("0", "");
myExitLauncherBox->setState(true);
break; break;
} }

View File

@ -50,6 +50,7 @@ class UIDialog : public Dialog
StaticTextWidget* myLauncherHeightLabel; StaticTextWidget* myLauncherHeightLabel;
PopUpWidget* myLauncherFontPopup; PopUpWidget* myLauncherFontPopup;
PopUpWidget* myRomViewerPopup; PopUpWidget* myRomViewerPopup;
CheckboxWidget* myExitLauncherBox;
// Debugger options // Debugger options
SliderWidget* myDebuggerWidthSlider; SliderWidget* myDebuggerWidthSlider;