Add mappings for increasing and decreasing current vidmode.

Map the R77 F13 key to the former.
Some refactoring of the mapping code in PKeyboardHandler and EventHandler.
Some refactoring of the VidMode handling in FrameBuffer.
Option 'tia.fsfill' is now used to select 4:3 vs. 16:9 mode in fullscreen.
This commit is contained in:
Stephen Anthony 2019-04-08 18:44:27 -02:30
parent 368159a598
commit c80e2340ea
9 changed files with 186 additions and 140 deletions

View File

@ -166,7 +166,7 @@ void PhysicalKeyboardHandler::setDefaultMapping(Event::Type event, EventMode mod
setDefaultKey( KBDK_F4, Event::ConsoleColorToggle );
setDefaultKey( KBDK_F6, Event::ConsoleLeftDiffToggle );
setDefaultKey( KBDK_F8, Event::ConsoleRightDiffToggle );
setDefaultKey( KBDK_F13, Event::FullscreenFillToggle );
setDefaultKey( KBDK_F13, Event::VidmodeIncrease );
setDefaultKey( KBDK_BACKSPACE, Event::LauncherMode );
#endif
break;
@ -390,20 +390,20 @@ bool PhysicalKeyboardHandler::handleAltEvent(StellaKey key, StellaMod mod, bool
break;
// These can work in pause mode too
case KBDK_EQUALS:
myOSystem.frameBuffer().changeWindowedVidMode(+1);
case KBDK_MINUS:
myHandler.handleEvent(Event::VidmodeDecrease, pressed);
break;
case KBDK_MINUS:
myOSystem.frameBuffer().changeWindowedVidMode(-1);
case KBDK_EQUALS:
myHandler.handleEvent(Event::VidmodeIncrease, pressed);
break;
case KBDK_LEFTBRACKET:
myOSystem.sound().adjustVolume(-1);
myHandler.handleEvent(Event::VolumeDecrease, pressed);
break;
case KBDK_RIGHTBRACKET:
myOSystem.sound().adjustVolume(+1);
myHandler.handleEvent(Event::VolumeIncrease, pressed);
break;
case KBDK_PAGEUP: // Alt-PageUp increases YStart

View File

@ -74,7 +74,7 @@ class Event
ChangeState, LoadState, SaveState, TakeSnapshot, Quit,
PauseMode, OptionsMenuMode, CmdMenuMode, TimeMachineMode, DebuggerMode, LauncherMode,
Fry, VolumeDecrease, VolumeIncrease, SoundToggle, FullscreenFillToggle,
Fry, VolumeDecrease, VolumeIncrease, SoundToggle, VidmodeDecrease, VidmodeIncrease,
UIUp, UIDown, UILeft, UIRight, UIHome, UIEnd, UIPgUp, UIPgDown,
UISelect, UINavPrev, UINavNext, UIOK, UICancel, UIPrevDir,

View File

@ -377,6 +377,14 @@ void EventHandler::handleEvent(Event::Type event, bool pressed)
if(pressed) myOSystem.sound().toggleMute();
return;
case Event::VidmodeDecrease:
if(pressed) myOSystem.frameBuffer().changeVidMode(-1);
return;
case Event::VidmodeIncrease:
if(pressed) myOSystem.frameBuffer().changeVidMode(+1);
return;
case Event::SaveState:
if(pressed) myOSystem.state().saveState();
return;
@ -1281,7 +1289,8 @@ EventHandler::ActionList EventHandler::ourEmulActionList[kEmulActionListSize] =
{ Event::VolumeDecrease, "Decrease volume", "", false },
{ Event::VolumeIncrease, "Increase volume", "", false },
{ Event::SoundToggle, "Toggle sound", "", false },
{ Event::FullscreenFillToggle, "Toggle fullscreen fill", "", false },
{ Event::VidmodeDecrease, "Previous video mode", "", false },
{ Event::VidmodeIncrease, "Next video mode", "", false },
{ Event::PauseMode, "Pause", "", false },
{ Event::OptionsMenuMode, "Enter options menu UI", "", false },
{ Event::CmdMenuMode, "Toggle command menu UI", "", false },

View File

@ -363,7 +363,7 @@ class EventHandler
enum {
kComboSize = 16,
kEventsPerCombo = 8,
kEmulActionListSize = 82 + kComboSize,
kEmulActionListSize = 83 + kComboSize,
kMenuActionListSize = 14
};

View File

@ -198,7 +198,7 @@ FBInitStatus FrameBuffer::createDisplay(const string& title,
// Initialize video subsystem (make sure we get a valid mode)
string pre_about = about();
const VideoMode& mode = getSavedVidMode(useFullscreen);
const FrameBuffer::VideoMode& mode = getSavedVidMode(useFullscreen);
if(width <= mode.screen.w && height <= mode.screen.h)
{
// Changing the video mode can take some time, during which the last
@ -702,15 +702,14 @@ void FrameBuffer::toggleFullscreen()
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool FrameBuffer::changeWindowedVidMode(int direction)
bool FrameBuffer::changeVidMode(int direction)
{
#ifdef WINDOWED_SUPPORT
EventHandlerState state = myOSystem.eventHandler().state();
bool tiaMode = (state != EventHandlerState::DEBUGGER &&
state != EventHandlerState::LAUNCHER);
// Ignore any attempts to change video size while in invalid modes
if(!tiaMode || fullScreen())
// Only applicable when in TIA/emulation mode
if(!tiaMode)
return false;
if(direction == +1)
@ -736,12 +735,18 @@ bool FrameBuffer::changeWindowedVidMode(int direction)
resetSurfaces();
showMessage(mode.description);
myOSystem.settings().setValue("tia.zoom", mode.zoom);
myOSystem.sound().mute(oldMuteState);
if(fullScreen())
myOSystem.settings().setValue("tia.fsfill",
mode.stretch == VideoMode::Stretch::Fill);
else
myOSystem.settings().setValue("tia.zoom", mode.zoom);
return true;
}
myOSystem.sound().mute(oldMuteState);
#endif
return false;
}
@ -827,9 +832,12 @@ void FrameBuffer::setAvailableVidModes(uInt32 baseWidth, uInt32 baseHeight)
uInt32 maxZoom = maxWindowSizeForScreen(baseWidth, baseHeight,
myDesktopSize.w, myDesktopSize.h);
#if 0 // FIXME - does this apply any longer??
// Aspect ratio
uInt32 aspect = myOSystem.settings().getInt(myOSystem.console().tia().frameLayout() == FrameLayout::ntsc ?
"tia.aspectn" : "tia.aspectp");
uInt32 aspect = myOSystem.settings().getInt(
myOSystem.console().tia().frameLayout() == FrameLayout::ntsc ?
"tia.aspectn" : "tia.aspectp");
#endif
// Determine all zoom levels
for(uInt32 zoom = 2; zoom <= maxZoom; ++zoom)
@ -837,9 +845,8 @@ void FrameBuffer::setAvailableVidModes(uInt32 baseWidth, uInt32 baseHeight)
ostringstream desc;
desc << "Zoom " << zoom << "x";
VideoMode mode(baseWidth*zoom, baseHeight*zoom,
baseWidth*zoom, baseHeight*zoom, -1, zoom, desc.str());
mode.applyAspectCorrection(aspect);
VideoMode mode(baseWidth*zoom, baseHeight*zoom, baseWidth*zoom, baseHeight*zoom,
VideoMode::Stretch::Fill, desc.str(), zoom);
myWindowedModeList.add(mode);
}
@ -848,29 +855,40 @@ void FrameBuffer::setAvailableVidModes(uInt32 baseWidth, uInt32 baseHeight)
{
maxZoom = maxWindowSizeForScreen(baseWidth, baseHeight,
myDisplays[i].w, myDisplays[i].h);
VideoMode mode(baseWidth*maxZoom, baseHeight*maxZoom,
myDisplays[i].w, myDisplays[i].h, i);
mode.applyAspectCorrection(aspect, myOSystem.settings().getBool("tia.fsfill"));
myFullscreenModeLists[i].add(mode);
// Add both normal aspect and filled modes
// It's easier to define them both now, and simply switch between
// them when necessary
VideoMode mode1(baseWidth*maxZoom, baseHeight*maxZoom,
myDisplays[i].w, myDisplays[i].h,
VideoMode::Stretch::Preserve,
"Preserve aspect, no stretch", maxZoom, i);
myFullscreenModeLists[i].add(mode1);
VideoMode mode2(baseWidth*maxZoom, baseHeight*maxZoom,
myDisplays[i].w, myDisplays[i].h,
VideoMode::Stretch::Fill,
"Ignore aspect, full stretch", maxZoom, i);
myFullscreenModeLists[i].add(mode2);
}
}
else // UI mode
{
// Windowed and fullscreen mode differ only in screen size
myWindowedModeList.add(
VideoMode(baseWidth, baseHeight, baseWidth, baseHeight, -1)
VideoMode(baseWidth, baseHeight, baseWidth, baseHeight, VideoMode::Stretch::Fill)
);
for(uInt32 i = 0; i < myDisplays.size(); ++i)
{
myFullscreenModeLists[i].add(
VideoMode(baseWidth, baseHeight, myDisplays[i].w, myDisplays[i].h, i)
VideoMode(baseWidth, baseHeight, myDisplays[i].w, myDisplays[i].h,
VideoMode::Stretch::Fill, "", 1, i)
);
}
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const VideoMode& FrameBuffer::getSavedVidMode(bool fullscreen)
const FrameBuffer::VideoMode& FrameBuffer::getSavedVidMode(bool fullscreen)
{
EventHandlerState state = myOSystem.eventHandler().state();
@ -891,9 +909,15 @@ const VideoMode& FrameBuffer::getSavedVidMode(bool fullscreen)
// UI modes (launcher and debugger) have only one supported resolution
// so the 'current' one is the only valid one
if(state == EventHandlerState::DEBUGGER || state == EventHandlerState::LAUNCHER)
myCurrentModeList->setZoom(1);
else
myCurrentModeList->setZoom(myOSystem.settings().getInt("tia.zoom"));
myCurrentModeList->setByZoom(1);
else // TIA mode
{
if(fullscreen)
myCurrentModeList->setByStretch(myOSystem.settings().getBool("tia.fsfill")
? VideoMode::Stretch::Fill : VideoMode::Stretch::Preserve);
else
myCurrentModeList->setByZoom(myOSystem.settings().getInt("tia.zoom"));
}
return myCurrentModeList->current();
}
@ -903,20 +927,24 @@ const VideoMode& FrameBuffer::getSavedVidMode(bool fullscreen)
// VideoMode implementation
//
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
VideoMode::VideoMode()
: fsIndex(-1),
FrameBuffer::VideoMode::VideoMode()
: stretch(VideoMode::Stretch::Fill),
description(""),
zoom(1),
description("")
fsIndex(-1)
{
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
VideoMode::VideoMode(uInt32 iw, uInt32 ih, uInt32 sw, uInt32 sh,
Int32 full, uInt32 z, const string& desc)
: fsIndex(full),
zoom(z),
description(desc)
FrameBuffer::VideoMode::VideoMode(uInt32 iw, uInt32 ih, uInt32 sw, uInt32 sh,
Stretch smode, const string& desc,
uInt32 zoomLevel, Int32 fsindex)
: stretch(smode),
description(desc),
zoom(zoomLevel),
fsIndex(fsindex)
{
// First set default size and positioning
sw = std::max(sw, TIAConstants::viewableWidth);
sh = std::max(sh, TIAConstants::viewableHeight);
iw = std::min(iw, sw);
@ -925,59 +953,51 @@ VideoMode::VideoMode(uInt32 iw, uInt32 ih, uInt32 sw, uInt32 sh,
int iy = (sh - ih) >> 1;
image = GUI::Rect(ix, iy, ix+iw, iy+ih);
screen = GUI::Size(sw, sh);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void VideoMode::applyAspectCorrection(uInt32 aspect, bool stretch)
{
#if 0 // FIXME - more work is required here for issue #368
// Height is modified by aspect ratio; other factors may be applied below
uInt32 iw = image.width();
uInt32 ih = image.height() / aspect * 100.0;
#else
// Width is modified by aspect ratio; other factors may be applied below
uInt32 iw = uInt32(float(image.width() * aspect) / 100.0);
uInt32 ih = image.height();
#endif
// Now resize based on windowed/fullscreen mode and stretch factor
iw = image.width();
ih = image.height();
if(fsIndex != -1)
{
// Fullscreen mode stretching
float stretchFactor = 1.0;
float scaleX = float(iw) / screen.w;
float scaleY = float(ih) / screen.h;
switch(stretch)
{
case Stretch::Preserve:
{
float stretchFactor = 1.0;
float scaleX = float(iw) / screen.w;
float scaleY = float(ih) / screen.h;
// Scale to actual or integral factors
if(stretch)
{
// Scale to full (non-integral) available space
if(scaleX > scaleY)
stretchFactor = float(screen.w) / iw;
else
stretchFactor = float(screen.h) / ih;
}
else
{
// Only scale to an integral amount
if(scaleX > scaleY)
{
int bw = iw / zoom;
stretchFactor = float(int(screen.w / bw) * bw) / iw;
}
else
{
int bh = ih / zoom;
stretchFactor = float(int(screen.h / bh) * bh) / ih;
// Scale to all available space, keep aspect correct
if(scaleX > scaleY)
stretchFactor = float(screen.w) / iw;
else
stretchFactor = float(screen.h) / ih;
iw = uInt32(stretchFactor * iw);
ih = uInt32(stretchFactor * ih);
break;
}
case Stretch::Fill:
// Scale to all available space
iw = screen.w;
ih = screen.h;
break;
}
iw = uInt32(stretchFactor * iw);
ih = uInt32(stretchFactor * ih);
}
else
{
// In windowed mode, the screen size changes to match the image width
// Height is never modified in this mode
screen.w = iw;
// In windowed mode, currently the size is scaled to the screen
// TODO - this may be updated if/when we allow variable-sized windows
switch(stretch)
{
case Stretch::Preserve:
case Stretch::Fill:
screen.w = iw;
screen.h = ih;
break;
}
}
// Now re-calculate the dimensions
@ -989,6 +1009,7 @@ void VideoMode::applyAspectCorrection(uInt32 aspect, bool stretch)
image.setHeight(ih);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//
// VideoModeList implementation
@ -1031,7 +1052,7 @@ void FrameBuffer::VideoModeList::previous()
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const VideoMode& FrameBuffer::VideoModeList::current() const
const FrameBuffer::VideoMode& FrameBuffer::VideoModeList::current() const
{
return myModeList[myIdx];
}
@ -1043,7 +1064,7 @@ void FrameBuffer::VideoModeList::next()
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::VideoModeList::setZoom(uInt32 zoom)
void FrameBuffer::VideoModeList::setByZoom(uInt32 zoom)
{
for(uInt32 i = 0; i < myModeList.size(); ++i)
{
@ -1056,6 +1077,20 @@ void FrameBuffer::VideoModeList::setZoom(uInt32 zoom)
myIdx = 0;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FrameBuffer::VideoModeList::setByStretch(FrameBuffer::VideoMode::Stretch stretch)
{
for(uInt32 i = 0; i < myModeList.size(); ++i)
{
if(myModeList[i].stretch == stretch)
{
myIdx = i;
return;
}
}
myIdx = 0;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
/*
Palette is defined as follows:

View File

@ -37,39 +37,6 @@ namespace GUI {
#include "EventHandlerConstants.hxx"
#include "bspf.hxx"
// Contains all relevant info for the dimensions of a video screen
// Also takes care of the case when the image should be 'centered'
// within the given screen:
// 'image' is the image dimensions into the screen
// 'screen' are the dimensions of the screen itself
class VideoMode
{
friend class FrameBuffer;
public:
GUI::Rect image;
GUI::Size screen;
Int32 fsIndex;
uInt32 zoom;
string description;
public:
VideoMode();
VideoMode(uInt32 iw, uInt32 ih, uInt32 sw, uInt32 sh, Int32 full,
uInt32 z = 1, const string& desc = "");
friend ostream& operator<<(ostream& os, const VideoMode& vm)
{
os << "image=" << vm.image << " screen=" << vm.screen
<< " full= " << vm.fsIndex << " zoom=" << vm.zoom
<< " desc=" << vm.description;
return os;
}
private:
void applyAspectCorrection(uInt32 aspect, bool stretch = false);
};
/**
This class encapsulates all video buffers and is the basis for the video
display in Stella. All graphics ports should derive from this class for
@ -82,6 +49,37 @@ class VideoMode
*/
class FrameBuffer
{
public:
// Contains all relevant info for the dimensions of a video screen
// Also takes care of the case when the image should be 'centered'
// within the given screen:
// 'image' is the image dimensions into the screen
// 'screen' are the dimensions of the screen itself
struct VideoMode
{
enum class Stretch { Preserve, Fill };
GUI::Rect image;
GUI::Size screen;
Stretch stretch;
string description;
uInt32 zoom;
Int32 fsIndex;
VideoMode();
VideoMode(uInt32 iw, uInt32 ih, uInt32 sw, uInt32 sh, Stretch smode,
const string& desc = "", uInt32 zoomLevel = 1, Int32 fsindex = -1);
friend ostream& operator<<(ostream& os, const VideoMode& vm)
{
os << "image=" << vm.image << " screen=" << vm.screen
<< " stretch= " << (vm.stretch == Stretch::Preserve ? "preserve" : "fill")
<< " desc=" << vm.description << " zoom=" << vm.zoom
<< " fsIndex= " << vm.fsIndex;
return os;
}
};
public:
/**
Creates a new Frame Buffer
@ -221,14 +219,16 @@ class FrameBuffer
void toggleFullscreen();
/**
This method is called when the user wants to switch to the next available
windowed video mode.
direction = -1 means go to the next lower windowed video mode
direction = +1 means go to the next higher windowed video mode
This method is called when the user wants to switch to the next
available video mode. In windowed mode, this typically means going to
the next/previous zoom level. In fullscreen mode, this typically means
switching between normal aspect and fully filling the screen.
direction = -1 means go to the next lower video mode
direction = +1 means go to the next higher video mode
@param direction Described above
*/
bool changeWindowedVidMode(int direction);
bool changeVidMode(int direction);
/**
Sets the state of the cursor (hidden or grabbed) based on the
@ -241,16 +241,16 @@ class FrameBuffer
*/
void enableGrabMouse(bool enable);
/**
Sets the use of grabmouse.
*/
bool grabMouseEnabled() const { return myGrabMouse; }
/**
Toggles the use of grabmouse (only has effect in emulation mode).
*/
void toggleGrabMouse();
/**
Sets the use of grabmouse.
*/
bool grabMouseEnabled() { return myGrabMouse; }
/**
Set up the TIA/emulation palette for a screen of any depth > 8.
@ -338,7 +338,8 @@ class FrameBuffer
@return False on any errors, else true
*/
virtual bool setVideoMode(const string& title, const VideoMode& mode) = 0;
virtual bool setVideoMode(const string& title,
const FrameBuffer::VideoMode& mode) = 0;
/**
This method is called to invalidate the contents of the entire
@ -428,7 +429,7 @@ class FrameBuffer
@param fullscreen Whether to use a windowed or fullscreen mode
@return A valid VideoMode for this framebuffer
*/
const VideoMode& getSavedVidMode(bool fullscreen);
const FrameBuffer::VideoMode& getSavedVidMode(bool fullscreen);
private:
/**
@ -441,17 +442,18 @@ class FrameBuffer
VideoModeList(const VideoModeList&) = default;
VideoModeList& operator=(const VideoModeList&) = default;
void add(const VideoMode& mode);
void add(const FrameBuffer::VideoMode& mode);
void clear();
bool empty() const;
uInt32 size() const;
void previous();
const VideoMode& current() const;
const FrameBuffer::VideoMode& current() const;
void next();
void setZoom(uInt32 zoom);
void setByZoom(uInt32 zoom);
void setByStretch(FrameBuffer::VideoMode::Stretch stretch);
friend ostream& operator<<(ostream& os, const VideoModeList& l)
{
@ -461,7 +463,7 @@ class FrameBuffer
}
private:
vector<VideoMode> myModeList;
vector<FrameBuffer::VideoMode> myModeList;
int myIdx;
};

View File

@ -17,7 +17,6 @@
#include <cmath>
#include "FrameBuffer.hxx"
#include "FBSurface.hxx"
#include "Settings.hxx"
#include "OSystem.hxx"
@ -66,7 +65,8 @@ TIASurface::TIASurface(OSystem& system)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TIASurface::initialize(const Console& console, const VideoMode& mode)
void TIASurface::initialize(const Console& console,
const FrameBuffer::VideoMode& mode)
{
myTIA = &(console.tia());
@ -100,7 +100,7 @@ void TIASurface::initialize(const Console& console, const VideoMode& mode)
mySLineSurface->setSrcSize(1, 2 * int(float(mode.image.height()) /
floor((float(mode.image.height()) / myTIA->height()) + 0.5)));
#if 1
#if 0
cerr << "INITIALIZE:\n"
<< "TIA:\n"
<< "src: " << myTiaSurface->srcRect() << endl

View File

@ -21,13 +21,12 @@
class TIA;
class Console;
class OSystem;
class FrameBuffer;
class FBSurface;
class VideoMode;
#include <thread>
#include "Rect.hxx"
#include "FrameBuffer.hxx"
#include "NTSCFilter.hxx"
#include "bspf.hxx"
#include "TIAConstants.hxx"
@ -52,7 +51,7 @@ class TIASurface
/**
Set the TIA object, which is needed for actually rendering the TIA image.
*/
void initialize(const Console& console, const VideoMode& mode);
void initialize(const Console& console, const FrameBuffer::VideoMode& mode);
/**
Set the palette for TIA rendering. This currently consists of two

View File

@ -79,6 +79,7 @@ bool SettingsR77::saveConfigFile(const string& cfgfile) const
out << "fullscreen = " << getString("fullscreen") << endl;
out << "lastrom = " << getString("lastrom") << endl;
out << "tia.fsfill = " << getString("tia.fsfill") << endl;
// out << "keymap = " << getString("keymap") << endl;
// out << "joymap = " << getString("joymap") << endl;