2009-01-10 18:42:49 +00:00
|
|
|
//============================================================================
|
2003-09-25 16:20:34 +00:00
|
|
|
//
|
2016-12-30 00:00:30 +00:00
|
|
|
// SSSS tt lll lll
|
|
|
|
// SS SS tt ll ll
|
|
|
|
// SS tttttt eeee ll ll aaaa
|
2003-09-25 16:20:34 +00:00
|
|
|
// SSSS tt ee ee ll ll aa
|
|
|
|
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
|
|
|
|
// SS SS tt ee ll ll aa aa
|
|
|
|
// SSSS ttt eeeee llll llll aaaaa
|
|
|
|
//
|
2024-01-01 16:08:25 +00:00
|
|
|
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
2010-04-10 21:37:23 +00:00
|
|
|
// and the Stella Team
|
2003-09-25 16:20:34 +00:00
|
|
|
//
|
2010-01-10 03:23:32 +00:00
|
|
|
// See the file "License.txt" for information on usage and redistribution of
|
2003-09-25 16:20:34 +00:00
|
|
|
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
|
|
|
//============================================================================
|
|
|
|
|
|
|
|
#include "bspf.hxx"
|
2019-05-01 21:13:17 +00:00
|
|
|
#include "Logger.hxx"
|
2007-09-03 18:37:24 +00:00
|
|
|
|
2003-09-25 16:20:34 +00:00
|
|
|
#include "Console.hxx"
|
The first version of a GUI for event remapping is here!
Now for the things that aren't finished yet:
- Only the most basic functions can be remapped. If you
erase the mapping for those that can't yet be remapped,
you'll have to delete the 'keymap' line from stellarc and
start over.
- Core events can only be remapped to other keys on the keyboard.
I haven't got the joystick remapping working yet (but it should
be easy to do).
- The TIA needs to be modified to show 320 pixels horizontally.
Right now, I'm using 8 pixel-width fonts on a framebuffer of
160 pixels, so there's not a lot of horizontal real estate.
So text will probably overwrite other stuff. This is cosmetic,
and WILL be fixed.
- Modification of the TIA will break every frontends rendering
code. It had to be done sometime ...
- I haven't yet added any user feedback mechanism for the user. So when
you go into remap mode and are about to remap a key, you won't
know it :) I'll be adding arrows (like in XMAME) ...
I've added a "Game Information" menu, which shows things like Game name,
manufacturer, rarity, type, etc. Basically stuff from the stella.pro file.
It has no purpose other than for coolness :)
git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@193 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
2003-09-28 21:59:24 +00:00
|
|
|
#include "EventHandler.hxx"
|
2005-02-21 02:23:57 +00:00
|
|
|
#include "OSystem.hxx"
|
2007-09-03 18:37:24 +00:00
|
|
|
#include "Settings.hxx"
|
2016-12-10 17:08:28 +00:00
|
|
|
#include "TIA.hxx"
|
2018-08-31 23:22:56 +00:00
|
|
|
#include "Sound.hxx"
|
2020-12-06 11:08:25 +00:00
|
|
|
#include "AudioSettings.hxx"
|
2020-10-23 12:57:06 +00:00
|
|
|
#include "MediaFactory.hxx"
|
2023-08-17 16:18:15 +00:00
|
|
|
#include "PNGLibrary.hxx"
|
2007-09-03 18:37:24 +00:00
|
|
|
|
2014-04-30 16:53:21 +00:00
|
|
|
#include "FBSurface.hxx"
|
2014-05-12 23:34:25 +00:00
|
|
|
#include "TIASurface.hxx"
|
2023-08-25 13:57:21 +00:00
|
|
|
#include "Bezel.hxx"
|
2007-09-03 18:37:24 +00:00
|
|
|
#include "FrameBuffer.hxx"
|
2020-07-23 10:39:22 +00:00
|
|
|
#include "StateManager.hxx"
|
|
|
|
#include "RewindManager.hxx"
|
2005-08-24 22:54:30 +00:00
|
|
|
|
2006-12-15 16:43:12 +00:00
|
|
|
#ifdef DEBUGGER_SUPPORT
|
2005-08-24 22:54:30 +00:00
|
|
|
#include "Debugger.hxx"
|
|
|
|
#endif
|
2019-05-02 20:28:39 +00:00
|
|
|
#ifdef GUI_SUPPORT
|
|
|
|
#include "Font.hxx"
|
|
|
|
#include "StellaFont.hxx"
|
2020-04-29 12:25:54 +00:00
|
|
|
#include "ConsoleMediumFont.hxx"
|
2020-03-14 10:14:24 +00:00
|
|
|
#include "ConsoleMediumBFont.hxx"
|
2019-05-02 20:28:39 +00:00
|
|
|
#include "StellaMediumFont.hxx"
|
|
|
|
#include "StellaLargeFont.hxx"
|
2020-03-15 16:16:37 +00:00
|
|
|
#include "Stella12x24tFont.hxx"
|
|
|
|
#include "Stella14x28tFont.hxx"
|
|
|
|
#include "Stella16x32tFont.hxx"
|
2019-05-02 20:28:39 +00:00
|
|
|
#include "ConsoleFont.hxx"
|
|
|
|
#include "Launcher.hxx"
|
2021-09-10 20:16:19 +00:00
|
|
|
#include "OptionsMenu.hxx"
|
2019-05-02 20:28:39 +00:00
|
|
|
#include "CommandMenu.hxx"
|
2020-02-11 19:28:06 +00:00
|
|
|
#include "HighScoresMenu.hxx"
|
2020-01-19 14:45:32 +00:00
|
|
|
#include "MessageMenu.hxx"
|
2021-09-01 12:06:09 +00:00
|
|
|
#include "PlusRomsMenu.hxx"
|
2019-05-02 20:28:39 +00:00
|
|
|
#include "TimeMachine.hxx"
|
|
|
|
#endif
|
2005-08-24 22:54:30 +00:00
|
|
|
|
2022-12-17 10:03:48 +00:00
|
|
|
static constexpr int MESSAGE_TIME = 120; // display message for 2 seconds
|
|
|
|
|
2003-09-25 16:20:34 +00:00
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
2014-05-12 23:34:25 +00:00
|
|
|
FrameBuffer::FrameBuffer(OSystem& osystem)
|
2020-12-20 21:44:28 +00:00
|
|
|
: myOSystem{osystem}
|
2018-07-25 11:18:21 +00:00
|
|
|
{
|
|
|
|
}
|
2003-10-01 19:01:02 +00:00
|
|
|
|
2017-11-17 17:00:17 +00:00
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
2022-08-20 18:02:15 +00:00
|
|
|
FrameBuffer::~FrameBuffer() // NOLINT (we need an empty d'tor)
|
2017-11-17 17:00:17 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2003-10-17 18:02:16 +00:00
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
2020-10-23 12:57:06 +00:00
|
|
|
void FrameBuffer::initialize()
|
2014-02-05 22:09:57 +00:00
|
|
|
{
|
2020-10-23 12:57:06 +00:00
|
|
|
// First create the platform-specific backend; it is needed before anything
|
|
|
|
// else can be used
|
2020-12-20 17:09:28 +00:00
|
|
|
myBackend = MediaFactory::createVideoBackend(myOSystem);
|
2020-10-23 12:57:06 +00:00
|
|
|
|
2014-03-07 22:12:39 +00:00
|
|
|
// Get desktop resolution and supported renderers
|
2021-04-06 13:56:01 +00:00
|
|
|
myBackend->queryHardware(myFullscreenDisplays, myWindowedDisplays, myRenderers);
|
|
|
|
|
2022-03-29 00:30:26 +00:00
|
|
|
const size_t numDisplays = myWindowedDisplays.size();
|
2021-04-06 13:56:01 +00:00
|
|
|
|
2022-03-29 00:30:26 +00:00
|
|
|
for(size_t display = 0; display < numDisplays; ++display)
|
2019-05-11 17:03:07 +00:00
|
|
|
{
|
2021-04-06 13:56:01 +00:00
|
|
|
uInt32 query_w = myWindowedDisplays[display].w, query_h = myWindowedDisplays[display].h;
|
|
|
|
|
|
|
|
// Check the 'maxres' setting, which is an undocumented developer feature
|
|
|
|
// that specifies the desktop size (not normally set)
|
|
|
|
const Common::Size& s = myOSystem.settings().getSize("maxres");
|
|
|
|
if(s.valid())
|
|
|
|
{
|
|
|
|
query_w = s.w;
|
|
|
|
query_h = s.h;
|
|
|
|
}
|
|
|
|
// Various parts of the codebase assume a minimum screen size
|
|
|
|
Common::Size size(std::max(query_w, FBMinimum::Width), std::max(query_h, FBMinimum::Height));
|
|
|
|
myAbsDesktopSize.push_back(size);
|
|
|
|
|
|
|
|
// Check for HiDPI mode (is it activated, and can we use it?)
|
2021-04-06 14:53:44 +00:00
|
|
|
myHiDPIAllowed.push_back(((size.w / 2) >= FBMinimum::Width) &&
|
|
|
|
((size.h / 2) >= FBMinimum::Height));
|
2021-04-06 13:56:01 +00:00
|
|
|
myHiDPIEnabled.push_back(myHiDPIAllowed.back() && myOSystem.settings().getBool("hidpi"));
|
|
|
|
|
|
|
|
// In HiDPI mode, the desktop resolution is essentially halved
|
|
|
|
// Later, the output is scaled and rendered in 2x mode
|
|
|
|
if(myHiDPIEnabled.back())
|
|
|
|
{
|
2021-04-06 14:53:44 +00:00
|
|
|
size.w /= hidpiScaleFactor();
|
|
|
|
size.h /= hidpiScaleFactor();
|
2021-04-06 13:56:01 +00:00
|
|
|
}
|
|
|
|
myDesktopSize.push_back(size);
|
2019-05-11 17:03:07 +00:00
|
|
|
}
|
2014-02-05 22:09:57 +00:00
|
|
|
|
2019-05-02 20:28:39 +00:00
|
|
|
#ifdef GUI_SUPPORT
|
2020-04-29 12:25:54 +00:00
|
|
|
setupFonts();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
setUIPalette();
|
|
|
|
|
|
|
|
myGrabMouse = myOSystem.settings().getBool("grabmouse");
|
|
|
|
|
|
|
|
// Create a TIA surface; we need it for rendering TIA images
|
|
|
|
myTIASurface = make_unique<TIASurface>(myOSystem);
|
2023-08-25 13:57:21 +00:00
|
|
|
// Create a bezel surface for TIA overlays
|
|
|
|
myBezel = make_unique<Bezel>(myOSystem);
|
2020-04-29 12:25:54 +00:00
|
|
|
}
|
|
|
|
|
2021-04-06 13:56:01 +00:00
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
2021-04-06 15:45:49 +00:00
|
|
|
int FrameBuffer::displayId(BufferType bufferType) const
|
2021-04-06 13:56:01 +00:00
|
|
|
{
|
2022-03-29 00:30:26 +00:00
|
|
|
const int maxDisplay = static_cast<int>(myWindowedDisplays.size()) - 1;
|
|
|
|
int display = 0;
|
2021-04-06 13:56:01 +00:00
|
|
|
|
|
|
|
if(bufferType == myBufferType)
|
|
|
|
display = myBackend->getCurrentDisplayIndex();
|
|
|
|
else
|
2021-04-06 14:53:44 +00:00
|
|
|
display = myOSystem.settings().getInt(getDisplayKey(bufferType != BufferType::None
|
|
|
|
? bufferType : myBufferType));
|
2021-04-06 13:56:01 +00:00
|
|
|
|
|
|
|
return std::min(std::max(0, display), maxDisplay);
|
|
|
|
}
|
|
|
|
|
2020-04-29 12:25:54 +00:00
|
|
|
#ifdef GUI_SUPPORT
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
void FrameBuffer::setupFonts()
|
|
|
|
{
|
2014-02-05 22:09:57 +00:00
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
// Create fonts to draw text
|
|
|
|
// NOTE: the logic determining appropriate font sizes is done here,
|
|
|
|
// so that the UI classes can just use the font they expect,
|
|
|
|
// and not worry about it
|
|
|
|
// This logic should also take into account the size of the
|
|
|
|
// framebuffer, and try to be intelligent about font sizes
|
|
|
|
// We can probably add ifdefs to take care of corner cases,
|
|
|
|
// but that means we've failed to abstract it enough ...
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
// This font is used in a variety of situations when a really small
|
|
|
|
// font is needed; we let the specific widget/dialog decide when to
|
|
|
|
// use it
|
2020-03-14 10:14:24 +00:00
|
|
|
mySmallFont = make_unique<GUI::Font>(GUI::stellaDesc); // 6x10
|
2014-02-05 22:09:57 +00:00
|
|
|
|
2019-04-23 18:08:03 +00:00
|
|
|
if(myOSystem.settings().getBool("minimal_ui"))
|
2020-03-16 08:26:45 +00:00
|
|
|
{
|
2020-04-29 12:25:54 +00:00
|
|
|
// The general font used in all UI elements
|
2020-03-15 16:16:37 +00:00
|
|
|
myFont = make_unique<GUI::Font>(GUI::stella12x24tDesc); // 12x24
|
2020-03-16 08:26:45 +00:00
|
|
|
// The info font used in all UI elements
|
|
|
|
myInfoFont = make_unique<GUI::Font>(GUI::stellaLargeDesc); // 10x20
|
|
|
|
}
|
2019-04-23 18:08:03 +00:00
|
|
|
else
|
2020-03-16 08:26:45 +00:00
|
|
|
{
|
2022-03-29 00:30:26 +00:00
|
|
|
constexpr int NUM_FONTS = 7;
|
2022-09-14 01:22:59 +00:00
|
|
|
const FontDesc FONT_DESC[NUM_FONTS] = {
|
|
|
|
GUI::consoleDesc, GUI::consoleMediumDesc, GUI::stellaMediumDesc,
|
|
|
|
GUI::stellaLargeDesc, GUI::stella12x24tDesc, GUI::stella14x28tDesc,
|
|
|
|
GUI::stella16x32tDesc};
|
2022-12-16 22:45:30 +00:00
|
|
|
const string_view dialogFont = myOSystem.settings().getString("dialogfont");
|
2022-09-14 01:22:59 +00:00
|
|
|
const FontDesc fd = getFontDesc(dialogFont);
|
2020-04-29 12:25:54 +00:00
|
|
|
|
|
|
|
// The general font used in all UI elements
|
|
|
|
myFont = make_unique<GUI::Font>(fd); // default: 9x18
|
|
|
|
// The info font used in all UI elements,
|
|
|
|
// automatically determined aiming for 1 / 1.4 (~= 18 / 13) size
|
|
|
|
int fontIdx = 0;
|
|
|
|
for(int i = 0; i < NUM_FONTS; ++i)
|
|
|
|
{
|
|
|
|
if(fd.height <= FONT_DESC[i].height * 1.4)
|
|
|
|
{
|
|
|
|
fontIdx = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
myInfoFont = make_unique<GUI::Font>(FONT_DESC[fontIdx]); // default 8x13
|
|
|
|
|
|
|
|
// Determine minimal zoom level based on the default font
|
|
|
|
// So what fits with default font should fit for any font.
|
|
|
|
// However, we have to make sure all Dialogs are sized using the fontsize.
|
2022-03-29 00:30:26 +00:00
|
|
|
const int zoom_h = (fd.height * 4 * 2) / GUI::stellaMediumDesc.height;
|
|
|
|
const int zoom_w = (fd.maxwidth * 4 * 2) / GUI::stellaMediumDesc.maxwidth;
|
2020-10-13 13:17:37 +00:00
|
|
|
// round to 25% steps, >= 200%
|
2023-08-26 14:53:06 +00:00
|
|
|
myTIAMinZoom = std::max(std::max(zoom_w, zoom_h) / 4., 2.);
|
2020-03-16 08:26:45 +00:00
|
|
|
}
|
2014-02-05 22:09:57 +00:00
|
|
|
|
|
|
|
// The font used by the ROM launcher
|
2022-12-16 22:45:30 +00:00
|
|
|
const string_view lf = myOSystem.settings().getString("launcherfont");
|
2014-04-28 16:47:10 +00:00
|
|
|
|
2020-04-29 12:25:54 +00:00
|
|
|
myLauncherFont = make_unique<GUI::Font>(getFontDesc(lf)); // 8x13
|
|
|
|
}
|
2018-08-12 21:01:43 +00:00
|
|
|
|
2020-04-29 12:25:54 +00:00
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
2022-12-16 22:45:30 +00:00
|
|
|
FontDesc FrameBuffer::getFontDesc(string_view name)
|
2020-04-29 12:25:54 +00:00
|
|
|
{
|
|
|
|
if(name == "small")
|
2020-11-22 20:58:49 +00:00
|
|
|
return GUI::consoleDesc; // 8x13
|
2020-04-29 12:25:54 +00:00
|
|
|
else if(name == "low_medium")
|
|
|
|
return GUI::consoleMediumBDesc; // 9x15
|
|
|
|
else if(name == "medium")
|
|
|
|
return GUI::stellaMediumDesc; // 9x18
|
|
|
|
else if(name == "large" || name == "large10")
|
|
|
|
return GUI::stellaLargeDesc; // 10x20
|
|
|
|
else if(name == "large12")
|
|
|
|
return GUI::stella12x24tDesc; // 12x24
|
|
|
|
else if(name == "large14")
|
|
|
|
return GUI::stella14x28tDesc; // 14x28
|
|
|
|
else // "large16"
|
|
|
|
return GUI::stella16x32tDesc; // 16x32
|
2018-08-12 21:01:43 +00:00
|
|
|
}
|
2020-04-29 12:25:54 +00:00
|
|
|
#endif
|
2018-08-12 21:01:43 +00:00
|
|
|
|
2014-02-05 22:09:57 +00:00
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
2022-12-16 22:45:30 +00:00
|
|
|
FBInitStatus FrameBuffer::createDisplay(string_view title, BufferType type,
|
2020-10-13 23:56:05 +00:00
|
|
|
Common::Size size, bool honourHiDPI)
|
2003-10-17 18:02:16 +00:00
|
|
|
{
|
2018-08-28 18:49:50 +00:00
|
|
|
++myInitializedCount;
|
2020-10-23 12:57:06 +00:00
|
|
|
myBackend->setTitle(title);
|
2006-12-03 01:24:34 +00:00
|
|
|
|
2021-04-06 13:56:01 +00:00
|
|
|
// Always save, maybe only the mode of the window has changed
|
|
|
|
saveCurrentWindowPosition();
|
|
|
|
myBufferType = type;
|
|
|
|
|
2020-10-13 13:17:37 +00:00
|
|
|
// In HiDPI mode, all created displays must be scaled appropriately
|
2019-05-11 17:03:07 +00:00
|
|
|
if(honourHiDPI && hidpiEnabled())
|
|
|
|
{
|
2020-10-13 23:56:05 +00:00
|
|
|
size.w *= hidpiScaleFactor();
|
|
|
|
size.h *= hidpiScaleFactor();
|
2019-05-11 17:03:07 +00:00
|
|
|
}
|
|
|
|
|
2010-07-22 15:41:46 +00:00
|
|
|
// A 'windowed' system is defined as one where the window size can be
|
|
|
|
// larger than the screen size, as there's some sort of window manager
|
|
|
|
// that takes care of it (all current desktop systems fall in this category)
|
|
|
|
// However, some systems have no concept of windowing, and have hard limits
|
|
|
|
// on how large a window can be (ie, the size of the 'desktop' is the
|
|
|
|
// absolute upper limit on window size)
|
|
|
|
//
|
|
|
|
// If the WINDOWED_SUPPORT macro is defined, we treat the system as the
|
|
|
|
// former type; if not, as the latter type
|
2006-12-03 01:24:34 +00:00
|
|
|
|
2022-03-29 00:30:26 +00:00
|
|
|
const int display = displayId();
|
2009-06-05 14:05:23 +00:00
|
|
|
#ifdef WINDOWED_SUPPORT
|
2014-04-28 16:47:10 +00:00
|
|
|
// We assume that a desktop of at least minimum acceptable size means that
|
|
|
|
// we're running on a 'large' system, and the window size requirements
|
|
|
|
// can be relaxed
|
2010-07-22 15:41:46 +00:00
|
|
|
// Otherwise, we treat the system as if WINDOWED_SUPPORT is not defined
|
2021-04-06 13:56:01 +00:00
|
|
|
if(myDesktopSize[display].w < FBMinimum::Width &&
|
|
|
|
myDesktopSize[display].h < FBMinimum::Height &&
|
|
|
|
size > myDesktopSize[display])
|
2017-12-15 00:59:45 +00:00
|
|
|
return FBInitStatus::FailTooLarge;
|
2010-07-22 15:41:46 +00:00
|
|
|
#else
|
|
|
|
// Make sure this mode is even possible
|
|
|
|
// We only really need to worry about it in non-windowed environments,
|
|
|
|
// where requesting a window that's too large will probably cause a crash
|
2021-04-06 13:56:01 +00:00
|
|
|
if(size > myDesktopSize[display])
|
2017-12-15 00:59:45 +00:00
|
|
|
return FBInitStatus::FailTooLarge;
|
2009-06-05 14:05:23 +00:00
|
|
|
#endif
|
|
|
|
|
2021-04-06 13:56:01 +00:00
|
|
|
if(myBufferType == BufferType::Emulator)
|
|
|
|
{
|
2023-08-28 09:16:27 +00:00
|
|
|
myBezel->load(); // make sure we have the correct bezel size
|
2023-08-25 13:57:21 +00:00
|
|
|
|
2021-04-06 13:56:01 +00:00
|
|
|
// Determine possible TIA windowed zoom levels
|
2023-10-15 16:23:46 +00:00
|
|
|
const auto currentTIAZoom =
|
2023-08-26 14:53:06 +00:00
|
|
|
static_cast<double>(myOSystem.settings().getFloat("tia.zoom"));
|
2021-04-06 13:56:01 +00:00
|
|
|
myOSystem.settings().setValue("tia.zoom",
|
2023-08-27 09:13:37 +00:00
|
|
|
BSPF::clamp(currentTIAZoom, supportedTIAMinZoom(), supportedTIAMaxZoom()));
|
2021-04-06 13:56:01 +00:00
|
|
|
}
|
|
|
|
|
2021-01-16 18:57:18 +00:00
|
|
|
#ifdef GUI_SUPPORT // TODO: put message stuff in its own class
|
2005-05-12 18:45:21 +00:00
|
|
|
// Erase any messages from a previous run
|
2020-11-13 15:00:19 +00:00
|
|
|
myMsg.enabled = false;
|
2008-06-19 12:01:31 +00:00
|
|
|
|
|
|
|
// Create surfaces for TIA statistics and general messages
|
2019-05-11 17:03:07 +00:00
|
|
|
const GUI::Font& f = hidpiEnabled() ? infoFont() : font();
|
2017-12-19 15:56:01 +00:00
|
|
|
myStatsMsg.color = kColorInfo;
|
2019-05-11 17:03:07 +00:00
|
|
|
myStatsMsg.w = f.getMaxCharWidth() * 40 + 3;
|
|
|
|
myStatsMsg.h = (f.getFontHeight() + 2) * 3;
|
2008-12-25 23:05:16 +00:00
|
|
|
|
2014-11-09 15:10:47 +00:00
|
|
|
if(!myStatsMsg.surface)
|
2018-01-15 13:44:09 +00:00
|
|
|
{
|
2014-11-09 15:10:47 +00:00
|
|
|
myStatsMsg.surface = allocateSurface(myStatsMsg.w, myStatsMsg.h);
|
2018-01-15 13:44:09 +00:00
|
|
|
myStatsMsg.surface->attributes().blending = true;
|
2018-01-31 07:37:31 +00:00
|
|
|
myStatsMsg.surface->attributes().blendalpha = 92; //aligned with TimeMachineDialog
|
2018-01-15 13:44:09 +00:00
|
|
|
myStatsMsg.surface->applyAttributes();
|
|
|
|
}
|
2014-11-09 15:10:47 +00:00
|
|
|
|
|
|
|
if(!myMsg.surface)
|
2020-05-13 07:32:11 +00:00
|
|
|
{
|
|
|
|
const int fontWidth = font().getMaxCharWidth(),
|
|
|
|
HBORDER = fontWidth * 1.25 / 2.0;
|
|
|
|
myMsg.surface = allocateSurface(fontWidth * MESSAGE_WIDTH + HBORDER * 2,
|
|
|
|
font().getFontHeight() * 1.5);
|
|
|
|
}
|
2019-05-02 20:28:39 +00:00
|
|
|
#endif
|
2006-12-11 00:15:34 +00:00
|
|
|
|
2021-01-16 18:57:18 +00:00
|
|
|
// Initialize video mode handler, so it can know what video modes are
|
|
|
|
// appropriate for the requested image size
|
|
|
|
myVidModeHandler.setImageSize(size);
|
|
|
|
|
|
|
|
// Initialize video subsystem
|
2022-09-14 01:22:59 +00:00
|
|
|
const string pre_about = myBackend->about();
|
2022-03-29 00:30:26 +00:00
|
|
|
const FBInitStatus status = applyVideoMode();
|
2021-11-17 18:43:50 +00:00
|
|
|
|
|
|
|
// Only set phosphor once when ROM is started
|
|
|
|
if(myOSystem.eventHandler().inTIAMode())
|
|
|
|
{
|
|
|
|
// Phosphor mode can be enabled either globally or per-ROM
|
2024-05-01 19:55:29 +00:00
|
|
|
int p_blend = 0;
|
|
|
|
bool enable = false;
|
2024-01-25 11:24:18 +00:00
|
|
|
const int phosphorMode = PhosphorHandler::toPhosphorMode(
|
|
|
|
myOSystem.settings().getString(PhosphorHandler::SETTING_MODE));
|
2021-11-17 18:43:50 +00:00
|
|
|
|
2024-01-25 11:24:18 +00:00
|
|
|
switch(phosphorMode)
|
2021-11-17 18:43:50 +00:00
|
|
|
{
|
2024-01-25 11:24:18 +00:00
|
|
|
case PhosphorHandler::Always:
|
|
|
|
enable = true;
|
|
|
|
p_blend = myOSystem.settings().getInt(PhosphorHandler::SETTING_BLEND);
|
|
|
|
myOSystem.console().tia().enableAutoPhosphor(false);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PhosphorHandler::Auto_on:
|
|
|
|
case PhosphorHandler::Auto:
|
|
|
|
enable = false;
|
|
|
|
p_blend = myOSystem.settings().getInt(PhosphorHandler::SETTING_BLEND);
|
|
|
|
myOSystem.console().tia().enableAutoPhosphor(true, phosphorMode == PhosphorHandler::Auto_on);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default: // PhosphorHandler::ByRom
|
|
|
|
enable = myOSystem.console().properties().get(PropType::Display_Phosphor) == "YES";
|
|
|
|
p_blend = BSPF::stoi(myOSystem.console().properties().get(PropType::Display_PPBlend));
|
|
|
|
myOSystem.console().tia().enableAutoPhosphor(false);
|
|
|
|
break;
|
2021-11-17 18:43:50 +00:00
|
|
|
}
|
|
|
|
myTIASurface->enablePhosphor(enable, p_blend);
|
|
|
|
}
|
|
|
|
|
2021-01-16 18:57:18 +00:00
|
|
|
if(status != FBInitStatus::Success)
|
|
|
|
return status;
|
|
|
|
|
2014-06-30 22:46:33 +00:00
|
|
|
// Print initial usage message, but only print it later if the status has changed
|
2014-11-09 15:10:47 +00:00
|
|
|
if(myInitializedCount == 1)
|
2014-01-31 16:23:10 +00:00
|
|
|
{
|
2020-10-23 12:57:06 +00:00
|
|
|
Logger::info(myBackend->about());
|
2014-01-31 16:23:10 +00:00
|
|
|
}
|
2014-03-08 22:15:02 +00:00
|
|
|
else
|
|
|
|
{
|
2022-09-14 01:22:59 +00:00
|
|
|
const string post_about = myBackend->about();
|
2014-03-08 22:15:02 +00:00
|
|
|
if(post_about != pre_about)
|
2019-08-14 10:01:15 +00:00
|
|
|
Logger::info(post_about);
|
2014-03-08 22:15:02 +00:00
|
|
|
}
|
2008-05-30 19:07:55 +00:00
|
|
|
|
2020-10-16 16:49:15 +00:00
|
|
|
return status;
|
2003-10-26 19:40:39 +00:00
|
|
|
}
|
The first version of a GUI for event remapping is here!
Now for the things that aren't finished yet:
- Only the most basic functions can be remapped. If you
erase the mapping for those that can't yet be remapped,
you'll have to delete the 'keymap' line from stellarc and
start over.
- Core events can only be remapped to other keys on the keyboard.
I haven't got the joystick remapping working yet (but it should
be easy to do).
- The TIA needs to be modified to show 320 pixels horizontally.
Right now, I'm using 8 pixel-width fonts on a framebuffer of
160 pixels, so there's not a lot of horizontal real estate.
So text will probably overwrite other stuff. This is cosmetic,
and WILL be fixed.
- Modification of the TIA will break every frontends rendering
code. It had to be done sometime ...
- I haven't yet added any user feedback mechanism for the user. So when
you go into remap mode and are about to remap a key, you won't
know it :) I'll be adding arrows (like in XMAME) ...
I've added a "Game Information" menu, which shows things like Game name,
manufacturer, rarity, type, etc. Basically stuff from the stella.pro file.
It has no purpose other than for coolness :)
git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@193 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
2003-09-28 21:59:24 +00:00
|
|
|
|
2003-10-26 19:40:39 +00:00
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
2020-11-13 18:53:19 +00:00
|
|
|
void FrameBuffer::update(UpdateMode mode)
|
2003-10-26 19:40:39 +00:00
|
|
|
{
|
2018-07-25 11:18:21 +00:00
|
|
|
// Onscreen messages are a special case and require different handling than
|
|
|
|
// other objects; they aren't UI dialogs in the normal sense nor are they
|
|
|
|
// TIA images, and they need to be rendered on top of everything
|
|
|
|
// The logic is split in two pieces:
|
|
|
|
// - at the top of ::update(), to determine whether underlying dialogs
|
|
|
|
// need to be force-redrawn
|
|
|
|
// - at the bottom of ::update(), to actually draw them (this must come
|
|
|
|
// last, since they are always drawn on top of everything else).
|
|
|
|
|
2022-03-29 00:30:26 +00:00
|
|
|
const bool forceRedraw = mode & UpdateMode::REDRAW;
|
2020-11-13 18:53:19 +00:00
|
|
|
bool redraw = forceRedraw;
|
2018-07-25 11:18:21 +00:00
|
|
|
|
2020-11-13 10:18:25 +00:00
|
|
|
// Forced render without draw required if messages or dialogs were closed
|
|
|
|
// Note: For dialogs only relevant when two or more dialogs were stacked
|
2022-03-29 00:30:26 +00:00
|
|
|
const bool rerender = (mode & (UpdateMode::REDRAW | UpdateMode::RERENDER))
|
2020-11-13 18:53:19 +00:00
|
|
|
|| myPendingRender;
|
2020-11-13 10:18:25 +00:00
|
|
|
myPendingRender = false;
|
2015-03-15 17:36:46 +00:00
|
|
|
|
2014-05-12 23:34:25 +00:00
|
|
|
switch(myOSystem.eventHandler().state())
|
Huge changes across the map. Lets see if I can remember it all ...
There is now an SDL OpenGL port with filtering and alpha-blending.
It's a work in progress right now, but is already quite stable.
It's not as optimized as the software version yet, but this will
change as well. For now, you have to compile the SDL version in
either normal software mode or OpenGL mode. This will change
before the 1.4 release.
When entering menu mode, the emulation is now suspended. And when
pause is pressed, you can't enter menu mode. Because of these changes,
CPU use has dropped dramatically when viewing menus. This will benefit
all ports, since menus are now redrawn only when necessary, instead of
at the current framerate.
For a reference, on a Pentium-IV 2.4GHz, the software SDL version
maxes CPU usage at 9%, and the SDL OpenGL version at 13.5%. This is
at 60 fps and a zoomlevel of 4. While some small improvements can
(possibly) be made to the OpenGL version, I think we'll soon be hitting
the glass ceiling.
Work on the Porting.txt document is progressing, and I estimate it to
be 45% complete.
The Windows version still doesn't compile, and I still haven't looked
at it. Rest assured that it will be done before 1.4. There will be
a simultaneous release, even if the Linux versions are finished.
git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@200 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
2003-11-06 22:22:33 +00:00
|
|
|
{
|
2018-07-25 11:18:21 +00:00
|
|
|
case EventHandlerState::NONE:
|
2017-12-21 01:26:22 +00:00
|
|
|
case EventHandlerState::EMULATION:
|
2018-05-23 22:13:43 +00:00
|
|
|
// Do nothing; emulation mode is handled separately (see below)
|
2018-07-25 11:18:21 +00:00
|
|
|
return;
|
2003-10-26 19:40:39 +00:00
|
|
|
|
2017-12-21 01:26:22 +00:00
|
|
|
case EventHandlerState::PAUSE:
|
2007-01-30 17:13:10 +00:00
|
|
|
{
|
2017-10-14 10:22:21 +00:00
|
|
|
// Show a pause message immediately and then every 7 seconds
|
2022-09-14 01:22:59 +00:00
|
|
|
const bool shade = myOSystem.settings().getBool("pausedim");
|
2021-01-14 08:32:39 +00:00
|
|
|
|
2022-12-17 10:03:48 +00:00
|
|
|
if(myMsg.counter < MESSAGE_TIME && myPausedCount-- <= 0)
|
2007-01-30 17:13:10 +00:00
|
|
|
{
|
2022-03-29 00:30:26 +00:00
|
|
|
myPausedCount = static_cast<uInt32>(7 * myOSystem.frameRate());
|
2020-11-12 09:43:04 +00:00
|
|
|
showTextMessage("Paused", MessagePosition::MiddleCenter);
|
2023-08-27 06:00:14 +00:00
|
|
|
renderTIA(false, shade);
|
2007-01-30 17:13:10 +00:00
|
|
|
}
|
2020-11-12 10:50:26 +00:00
|
|
|
if(rerender)
|
2023-08-27 06:00:14 +00:00
|
|
|
renderTIA(false, shade);
|
2017-12-21 01:26:22 +00:00
|
|
|
break; // EventHandlerState::PAUSE
|
2007-01-30 17:13:10 +00:00
|
|
|
}
|
|
|
|
|
2019-05-02 20:28:39 +00:00
|
|
|
#ifdef GUI_SUPPORT
|
2017-12-21 01:26:22 +00:00
|
|
|
case EventHandlerState::OPTIONSMENU:
|
2005-02-27 23:41:19 +00:00
|
|
|
{
|
2021-09-10 20:16:19 +00:00
|
|
|
myOSystem.optionsMenu().tick();
|
|
|
|
redraw |= myOSystem.optionsMenu().needsRedraw();
|
2020-11-12 10:50:26 +00:00
|
|
|
if(redraw)
|
2018-07-25 11:18:21 +00:00
|
|
|
{
|
2023-08-27 06:00:14 +00:00
|
|
|
renderTIA(true, true);
|
2021-09-10 20:16:19 +00:00
|
|
|
myOSystem.optionsMenu().draw(forceRedraw);
|
2020-11-13 10:18:25 +00:00
|
|
|
}
|
|
|
|
else if(rerender)
|
|
|
|
{
|
2023-08-27 06:00:14 +00:00
|
|
|
renderTIA(true, true);
|
2021-09-10 20:16:19 +00:00
|
|
|
myOSystem.optionsMenu().render();
|
2018-07-25 11:18:21 +00:00
|
|
|
}
|
2017-12-21 01:26:22 +00:00
|
|
|
break; // EventHandlerState::OPTIONSMENU
|
2005-02-27 23:41:19 +00:00
|
|
|
}
|
Huge changes across the map. Lets see if I can remember it all ...
There is now an SDL OpenGL port with filtering and alpha-blending.
It's a work in progress right now, but is already quite stable.
It's not as optimized as the software version yet, but this will
change as well. For now, you have to compile the SDL version in
either normal software mode or OpenGL mode. This will change
before the 1.4 release.
When entering menu mode, the emulation is now suspended. And when
pause is pressed, you can't enter menu mode. Because of these changes,
CPU use has dropped dramatically when viewing menus. This will benefit
all ports, since menus are now redrawn only when necessary, instead of
at the current framerate.
For a reference, on a Pentium-IV 2.4GHz, the software SDL version
maxes CPU usage at 9%, and the SDL OpenGL version at 13.5%. This is
at 60 fps and a zoomlevel of 4. While some small improvements can
(possibly) be made to the OpenGL version, I think we'll soon be hitting
the glass ceiling.
Work on the Porting.txt document is progressing, and I estimate it to
be 45% complete.
The Windows version still doesn't compile, and I still haven't looked
at it. Rest assured that it will be done before 1.4. There will be
a simultaneous release, even if the Linux versions are finished.
git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@200 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
2003-11-06 22:22:33 +00:00
|
|
|
|
2017-12-21 01:26:22 +00:00
|
|
|
case EventHandlerState::CMDMENU:
|
2005-08-29 18:36:42 +00:00
|
|
|
{
|
2020-11-12 17:14:26 +00:00
|
|
|
myOSystem.commandMenu().tick();
|
2020-11-12 10:50:26 +00:00
|
|
|
redraw |= myOSystem.commandMenu().needsRedraw();
|
|
|
|
if(redraw)
|
2018-07-25 11:18:21 +00:00
|
|
|
{
|
2023-08-27 06:00:14 +00:00
|
|
|
renderTIA(true, true);
|
2020-11-13 10:18:25 +00:00
|
|
|
myOSystem.commandMenu().draw(forceRedraw);
|
2018-07-25 11:18:21 +00:00
|
|
|
}
|
2021-01-12 10:23:16 +00:00
|
|
|
else if(rerender)
|
|
|
|
{
|
2023-08-27 06:00:14 +00:00
|
|
|
renderTIA(true, true);
|
2021-01-12 10:23:16 +00:00
|
|
|
myOSystem.commandMenu().render();
|
|
|
|
}
|
2017-12-21 01:26:22 +00:00
|
|
|
break; // EventHandlerState::CMDMENU
|
|
|
|
}
|
|
|
|
|
2020-02-11 19:28:06 +00:00
|
|
|
case EventHandlerState::HIGHSCORESMENU:
|
|
|
|
{
|
2020-11-30 17:52:42 +00:00
|
|
|
myOSystem.highscoresMenu().tick();
|
2020-11-28 19:10:17 +00:00
|
|
|
redraw |= myOSystem.highscoresMenu().needsRedraw();
|
|
|
|
if(redraw)
|
2020-02-11 19:28:06 +00:00
|
|
|
{
|
2023-08-27 06:00:14 +00:00
|
|
|
renderTIA(true, true);
|
2020-11-28 19:10:17 +00:00
|
|
|
myOSystem.highscoresMenu().draw(forceRedraw);
|
2020-02-11 19:28:06 +00:00
|
|
|
}
|
2020-11-30 17:52:42 +00:00
|
|
|
else if(rerender)
|
|
|
|
{
|
2023-08-27 06:00:14 +00:00
|
|
|
renderTIA(true, true);
|
2020-11-30 17:52:42 +00:00
|
|
|
myOSystem.highscoresMenu().render();
|
|
|
|
}
|
2020-02-11 19:28:06 +00:00
|
|
|
break; // EventHandlerState::HIGHSCORESMENU
|
|
|
|
}
|
|
|
|
|
2020-01-19 14:45:32 +00:00
|
|
|
case EventHandlerState::MESSAGEMENU:
|
|
|
|
{
|
2020-11-12 17:14:26 +00:00
|
|
|
myOSystem.messageMenu().tick();
|
2020-11-12 10:50:26 +00:00
|
|
|
redraw |= myOSystem.messageMenu().needsRedraw();
|
|
|
|
if(redraw)
|
2020-01-19 14:45:32 +00:00
|
|
|
{
|
2023-08-27 06:00:14 +00:00
|
|
|
renderTIA(true, true);
|
2020-11-13 10:18:25 +00:00
|
|
|
myOSystem.messageMenu().draw(forceRedraw);
|
2020-01-19 14:45:32 +00:00
|
|
|
}
|
|
|
|
break; // EventHandlerState::MESSAGEMENU
|
|
|
|
}
|
|
|
|
|
2021-09-01 12:06:09 +00:00
|
|
|
case EventHandlerState::PLUSROMSMENU:
|
2021-08-31 15:04:27 +00:00
|
|
|
{
|
2021-09-01 12:06:09 +00:00
|
|
|
myOSystem.plusRomsMenu().tick();
|
|
|
|
redraw |= myOSystem.plusRomsMenu().needsRedraw();
|
2021-08-31 15:04:27 +00:00
|
|
|
if(redraw)
|
|
|
|
{
|
2023-08-27 06:00:14 +00:00
|
|
|
renderTIA(true, true);
|
2021-09-01 12:06:09 +00:00
|
|
|
myOSystem.plusRomsMenu().draw(forceRedraw);
|
2021-08-31 15:04:27 +00:00
|
|
|
}
|
2021-09-01 12:06:09 +00:00
|
|
|
break; // EventHandlerState::PLUSROMSMENU
|
2021-08-31 15:04:27 +00:00
|
|
|
}
|
|
|
|
|
2017-12-21 01:26:22 +00:00
|
|
|
case EventHandlerState::TIMEMACHINE:
|
|
|
|
{
|
2020-11-12 17:14:26 +00:00
|
|
|
myOSystem.timeMachine().tick();
|
2020-11-12 10:50:26 +00:00
|
|
|
redraw |= myOSystem.timeMachine().needsRedraw();
|
|
|
|
if(redraw)
|
2018-07-25 11:18:21 +00:00
|
|
|
{
|
2023-08-19 16:12:32 +00:00
|
|
|
renderTIA();
|
2020-11-13 10:18:25 +00:00
|
|
|
myOSystem.timeMachine().draw(forceRedraw);
|
2018-07-25 11:18:21 +00:00
|
|
|
}
|
2020-11-30 17:52:42 +00:00
|
|
|
else if(rerender)
|
|
|
|
{
|
2023-08-19 16:12:32 +00:00
|
|
|
renderTIA();
|
2020-11-30 17:52:42 +00:00
|
|
|
myOSystem.timeMachine().render();
|
|
|
|
}
|
2017-12-21 01:26:22 +00:00
|
|
|
break; // EventHandlerState::TIMEMACHINE
|
2005-08-29 18:36:42 +00:00
|
|
|
}
|
|
|
|
|
2020-07-23 10:39:22 +00:00
|
|
|
case EventHandlerState::PLAYBACK:
|
|
|
|
{
|
|
|
|
static Int32 frames = 0;
|
|
|
|
bool success = true;
|
|
|
|
|
|
|
|
if(--frames <= 0)
|
|
|
|
{
|
2020-12-06 11:08:25 +00:00
|
|
|
RewindManager& r = myOSystem.state().rewindManager();
|
2022-03-29 00:30:26 +00:00
|
|
|
const uInt64 prevCycles = r.getCurrentCycles();
|
2020-12-06 11:08:25 +00:00
|
|
|
|
2020-07-23 10:39:22 +00:00
|
|
|
success = r.unwindStates(1);
|
|
|
|
|
2020-12-07 03:13:11 +00:00
|
|
|
// Determine playback speed, the faster the more the states are apart
|
2022-08-20 18:02:15 +00:00
|
|
|
const Int64 frameCycles = static_cast<Int64>(76) * std::max<Int32>(myOSystem.console().tia().scanlinesLastFrame(), 240);
|
2022-03-29 00:30:26 +00:00
|
|
|
const Int64 intervalFrames = r.getInterval() / frameCycles;
|
|
|
|
const Int64 stateFrames = (r.getCurrentCycles() - prevCycles) / frameCycles;
|
2020-07-23 10:39:22 +00:00
|
|
|
|
2020-12-06 20:17:56 +00:00
|
|
|
//frames = intervalFrames + std::sqrt(std::max(stateFrames - intervalFrames, 0));
|
|
|
|
frames = std::round(std::sqrt(stateFrames));
|
2020-12-06 11:08:25 +00:00
|
|
|
|
2022-09-25 00:03:39 +00:00
|
|
|
// Pause sound if saved states were removed or states are too far apart
|
|
|
|
myOSystem.sound().pause(stateFrames > intervalFrames ||
|
2020-12-07 03:13:11 +00:00
|
|
|
frames > static_cast<Int32>(myOSystem.audioSettings().bufferSize() / 2 + 1));
|
2020-12-06 11:08:25 +00:00
|
|
|
}
|
2020-11-12 10:50:26 +00:00
|
|
|
redraw |= success;
|
|
|
|
if(redraw)
|
2023-08-27 06:00:14 +00:00
|
|
|
renderTIA(false);
|
2020-07-23 10:39:22 +00:00
|
|
|
|
|
|
|
// Stop playback mode at the end of the state buffer
|
|
|
|
// and switch to Time Machine or Pause mode
|
2020-11-12 09:43:04 +00:00
|
|
|
if(!success)
|
2020-07-23 10:39:22 +00:00
|
|
|
{
|
|
|
|
frames = 0;
|
2022-09-25 00:03:39 +00:00
|
|
|
myOSystem.sound().pause(true);
|
2020-07-23 10:39:22 +00:00
|
|
|
myOSystem.eventHandler().enterMenuMode(EventHandlerState::TIMEMACHINE);
|
|
|
|
}
|
|
|
|
break; // EventHandlerState::PLAYBACK
|
|
|
|
}
|
|
|
|
|
2017-12-21 01:26:22 +00:00
|
|
|
case EventHandlerState::LAUNCHER:
|
Added first pass of the ROM launcher. When you press 'Start' in the ROM
launcher, it launches Frostbite. Then pressing 'Escape' goes back to the
launcher, and you're able to then launch Frostbite again! Success !!!
Still TODO is actually get a ROM listing and use the selected game, but
the fact that it works multiple times for some game means that the
infrastructure is working correctly :)
Changed behaviour of the 'Escape' key. Specifically, it now only acts
as a key to enter ROM launcher mode. In the case where the emulation
was started without the launcher, the key will now do nothing. From now
on, the only way to quit Stella is Ctrl-Q (or equivalent for OSX),
close the window, or from the 'Quit' button.
Also, the 'Enter launcher mode' event will eventually be made remappable,
as will the 'Enter menu mode' event (currently the 'Tab' key).
git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@412 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
2005-05-06 18:39:00 +00:00
|
|
|
{
|
2020-11-12 17:14:26 +00:00
|
|
|
myOSystem.launcher().tick();
|
2020-11-12 10:50:26 +00:00
|
|
|
redraw |= myOSystem.launcher().needsRedraw();
|
|
|
|
if(redraw)
|
2020-11-13 10:18:25 +00:00
|
|
|
myOSystem.launcher().draw(forceRedraw);
|
2020-11-12 10:50:26 +00:00
|
|
|
else if(rerender)
|
|
|
|
myOSystem.launcher().render();
|
2017-12-21 01:26:22 +00:00
|
|
|
break; // EventHandlerState::LAUNCHER
|
Added first pass of the ROM launcher. When you press 'Start' in the ROM
launcher, it launches Frostbite. Then pressing 'Escape' goes back to the
launcher, and you're able to then launch Frostbite again! Success !!!
Still TODO is actually get a ROM listing and use the selected game, but
the fact that it works multiple times for some game means that the
infrastructure is working correctly :)
Changed behaviour of the 'Escape' key. Specifically, it now only acts
as a key to enter ROM launcher mode. In the case where the emulation
was started without the launcher, the key will now do nothing. From now
on, the only way to quit Stella is Ctrl-Q (or equivalent for OSX),
close the window, or from the 'Quit' button.
Also, the 'Enter launcher mode' event will eventually be made remappable,
as will the 'Enter menu mode' event (currently the 'Tab' key).
git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@412 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
2005-05-06 18:39:00 +00:00
|
|
|
}
|
2019-05-02 20:28:39 +00:00
|
|
|
#endif
|
2004-06-23 03:43:47 +00:00
|
|
|
|
2019-05-02 20:28:39 +00:00
|
|
|
#ifdef DEBUGGER_SUPPORT
|
2017-12-21 01:26:22 +00:00
|
|
|
case EventHandlerState::DEBUGGER:
|
2005-06-23 14:33:12 +00:00
|
|
|
{
|
2020-11-12 17:14:26 +00:00
|
|
|
myOSystem.debugger().tick();
|
2020-11-12 10:50:26 +00:00
|
|
|
redraw |= myOSystem.debugger().needsRedraw();
|
|
|
|
if(redraw)
|
2020-11-13 10:18:25 +00:00
|
|
|
myOSystem.debugger().draw(forceRedraw);
|
2020-11-12 10:50:26 +00:00
|
|
|
else if(rerender)
|
|
|
|
myOSystem.debugger().render();
|
2017-12-21 01:26:22 +00:00
|
|
|
break; // EventHandlerState::DEBUGGER
|
2005-06-23 14:33:12 +00:00
|
|
|
}
|
2019-05-02 20:28:39 +00:00
|
|
|
#endif
|
|
|
|
default:
|
|
|
|
break;
|
2003-10-26 19:40:39 +00:00
|
|
|
}
|
|
|
|
|
2006-12-18 12:53:33 +00:00
|
|
|
// Draw any pending messages
|
2018-07-25 11:18:21 +00:00
|
|
|
// The logic here determines whether to draw the message
|
|
|
|
// If the message is to be disabled, logic inside the draw method
|
|
|
|
// indicates that, and then the code at the top of this method sees
|
|
|
|
// the change and redraws everything
|
2009-01-10 18:42:49 +00:00
|
|
|
if(myMsg.enabled)
|
2020-11-12 09:43:04 +00:00
|
|
|
redraw |= drawMessage();
|
2006-12-18 12:53:33 +00:00
|
|
|
|
2018-07-25 11:18:21 +00:00
|
|
|
// Push buffers to screen only when necessary
|
2020-11-12 10:50:26 +00:00
|
|
|
if(redraw || rerender)
|
2020-10-23 12:57:06 +00:00
|
|
|
myBackend->renderToScreen();
|
2003-09-25 16:20:34 +00:00
|
|
|
}
|
|
|
|
|
2018-05-23 22:13:43 +00:00
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
2018-07-30 21:19:09 +00:00
|
|
|
void FrameBuffer::updateInEmulationMode(float framesPerSecond)
|
2018-05-23 22:13:43 +00:00
|
|
|
{
|
2018-07-25 11:18:21 +00:00
|
|
|
// Update method that is specifically tailored to emulation mode
|
|
|
|
//
|
|
|
|
// We don't worry about selective rendering here; the rendering
|
|
|
|
// always happens at the full framerate
|
2018-05-23 22:13:43 +00:00
|
|
|
|
2023-08-27 20:37:55 +00:00
|
|
|
renderTIA();
|
2018-05-23 22:13:43 +00:00
|
|
|
|
|
|
|
// Show frame statistics
|
|
|
|
if(myStatsMsg.enabled)
|
2018-07-30 21:19:09 +00:00
|
|
|
drawFrameStats(framesPerSecond);
|
2018-05-23 22:13:43 +00:00
|
|
|
|
2018-06-08 22:30:33 +00:00
|
|
|
myLastScanlines = myOSystem.console().tia().frameBufferScanlinesLastFrame();
|
2018-05-23 22:13:43 +00:00
|
|
|
myPausedCount = 0;
|
|
|
|
|
|
|
|
// Draw any pending messages
|
|
|
|
if(myMsg.enabled)
|
|
|
|
drawMessage();
|
|
|
|
|
2018-07-25 11:18:21 +00:00
|
|
|
// Push buffers to screen
|
2020-10-23 12:57:06 +00:00
|
|
|
myBackend->renderToScreen();
|
2018-05-23 22:13:43 +00:00
|
|
|
}
|
|
|
|
|
2019-05-02 20:28:39 +00:00
|
|
|
#ifdef GUI_SUPPORT
|
2021-01-13 19:54:09 +00:00
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
2022-12-16 22:45:30 +00:00
|
|
|
void FrameBuffer::createMessage(string_view message, MessagePosition position,
|
|
|
|
bool force)
|
2020-11-12 09:43:04 +00:00
|
|
|
{
|
Revamped the result on floating pins for TIA reads. Previously, this was
controlled by 'tiafloat', which has now been removed. Now, all
undriven pins take on the last value on the databus. This fixes a bug
in those reads where bit 6 or bits 6 & 7 are also undriven (previously,
these bits would always be zero, and only bits 0-5 were from lastdatabus.
Added new commandline argument 'tiadriven', which defaults to false.
In this default case, relevant bits take on values from the databus.
If true, relevant bits still take on databus values, but some are
randomly driven high as well. This helps to expose bugs when
developers assume the values for undriven/floating bits.
Added 'uimessages' commandline argument and associated UI item. When
disabled, messages which are normally shown in-game are disabled.
Certain messages which indicate a serious error are still shown, however.
git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1900 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
2009-11-10 20:12:50 +00:00
|
|
|
// Only show messages if they've been enabled
|
2018-05-27 18:47:12 +00:00
|
|
|
if(myMsg.surface == nullptr || !(force || myOSystem.settings().getBool("uimessages")))
|
Revamped the result on floating pins for TIA reads. Previously, this was
controlled by 'tiafloat', which has now been removed. Now, all
undriven pins take on the last value on the databus. This fixes a bug
in those reads where bit 6 or bits 6 & 7 are also undriven (previously,
these bits would always be zero, and only bits 0-5 were from lastdatabus.
Added new commandline argument 'tiadriven', which defaults to false.
In this default case, relevant bits take on values from the databus.
If true, relevant bits still take on databus values, but some are
randomly driven high as well. This helps to expose bugs when
developers assume the values for undriven/floating bits.
Added 'uimessages' commandline argument and associated UI item. When
disabled, messages which are normally shown in-game are disabled.
Certain messages which indicate a serious error are still shown, however.
git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1900 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
2009-11-10 20:12:50 +00:00
|
|
|
return;
|
|
|
|
|
2020-11-12 09:43:04 +00:00
|
|
|
const int fontHeight = font().getFontHeight();
|
2020-04-29 21:49:00 +00:00
|
|
|
const int VBORDER = fontHeight / 4;
|
|
|
|
|
2022-08-21 22:03:08 +00:00
|
|
|
// Show message for 2 seconds
|
2022-12-17 10:03:48 +00:00
|
|
|
myMsg.counter = std::min(static_cast<Int32>(myOSystem.frameRate()) * 2, MESSAGE_TIME);
|
2020-05-13 07:32:11 +00:00
|
|
|
if(myMsg.counter == 0)
|
2022-12-17 10:03:48 +00:00
|
|
|
myMsg.counter = MESSAGE_TIME;
|
2020-05-13 07:32:11 +00:00
|
|
|
|
2006-03-19 18:17:48 +00:00
|
|
|
// Precompute the message coordinates
|
2020-05-13 07:32:11 +00:00
|
|
|
myMsg.text = message;
|
|
|
|
myMsg.color = kBtnTextColor;
|
|
|
|
myMsg.h = fontHeight + VBORDER * 2;
|
|
|
|
myMsg.position = position;
|
|
|
|
myMsg.enabled = true;
|
2020-11-12 09:43:04 +00:00
|
|
|
myMsg.dirty = true;
|
2006-03-19 18:17:48 +00:00
|
|
|
|
2014-05-07 20:02:47 +00:00
|
|
|
myMsg.surface->setSrcSize(myMsg.w, myMsg.h);
|
2019-05-11 17:03:07 +00:00
|
|
|
myMsg.surface->setDstSize(myMsg.w * hidpiScaleFactor(), myMsg.h * hidpiScaleFactor());
|
2020-05-13 07:32:11 +00:00
|
|
|
}
|
2020-11-12 09:43:04 +00:00
|
|
|
#endif
|
2020-05-13 07:32:11 +00:00
|
|
|
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
2022-12-16 22:45:30 +00:00
|
|
|
void FrameBuffer::showTextMessage(string_view message,
|
|
|
|
MessagePosition position, bool force)
|
2020-05-13 07:32:11 +00:00
|
|
|
{
|
|
|
|
#ifdef GUI_SUPPORT
|
2020-11-12 09:43:04 +00:00
|
|
|
const int fontWidth = font().getMaxCharWidth();
|
2020-05-13 07:32:11 +00:00
|
|
|
const int HBORDER = fontWidth * 1.25 / 2.0;
|
|
|
|
|
2020-11-12 09:43:04 +00:00
|
|
|
myMsg.showGauge = false;
|
|
|
|
myMsg.w = std::min(fontWidth * (MESSAGE_WIDTH) - HBORDER * 2,
|
|
|
|
font().getStringWidth(message) + HBORDER * 2);
|
|
|
|
|
|
|
|
createMessage(message, position, force);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
2022-12-16 22:45:30 +00:00
|
|
|
void FrameBuffer::showGaugeMessage(string_view message, string_view valueText,
|
2020-11-12 09:43:04 +00:00
|
|
|
float value, float minValue, float maxValue)
|
|
|
|
{
|
|
|
|
#ifdef GUI_SUPPORT
|
|
|
|
const int fontWidth = font().getMaxCharWidth();
|
|
|
|
const int HBORDER = fontWidth * 1.25 / 2.0;
|
2020-05-13 07:32:11 +00:00
|
|
|
|
|
|
|
myMsg.showGauge = true;
|
|
|
|
if(maxValue - minValue != 0)
|
|
|
|
myMsg.value = (value - minValue) / (maxValue - minValue) * 100.F;
|
|
|
|
else
|
|
|
|
myMsg.value = 100.F;
|
|
|
|
myMsg.valueText = valueText;
|
|
|
|
myMsg.w = std::min(fontWidth * MESSAGE_WIDTH,
|
2020-11-12 09:43:04 +00:00
|
|
|
font().getStringWidth(message)
|
2020-05-14 19:18:55 +00:00
|
|
|
+ fontWidth * (GAUGEBAR_WIDTH + 2)
|
2020-11-12 09:43:04 +00:00
|
|
|
+ font().getStringWidth(valueText))
|
|
|
|
+ HBORDER * 2;
|
2020-04-29 21:49:00 +00:00
|
|
|
|
2020-11-12 09:43:04 +00:00
|
|
|
createMessage(message, MessagePosition::BottomCenter);
|
2019-05-02 20:28:39 +00:00
|
|
|
#endif
|
2009-01-10 18:42:49 +00:00
|
|
|
}
|
|
|
|
|
2020-05-14 19:18:55 +00:00
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
2020-06-19 22:25:27 +00:00
|
|
|
bool FrameBuffer::messageShown() const
|
2020-05-14 19:18:55 +00:00
|
|
|
{
|
|
|
|
#ifdef GUI_SUPPORT
|
|
|
|
return myMsg.enabled;
|
|
|
|
#else
|
|
|
|
return false;
|
2019-05-02 20:28:39 +00:00
|
|
|
#endif
|
2009-01-10 18:42:49 +00:00
|
|
|
}
|
|
|
|
|
2018-01-17 18:03:25 +00:00
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
2018-07-30 21:19:09 +00:00
|
|
|
void FrameBuffer::drawFrameStats(float framesPerSecond)
|
2018-01-17 18:03:25 +00:00
|
|
|
{
|
2019-05-02 20:28:39 +00:00
|
|
|
#ifdef GUI_SUPPORT
|
2018-01-17 18:03:25 +00:00
|
|
|
const ConsoleInfo& info = myOSystem.console().about();
|
2022-03-29 00:30:26 +00:00
|
|
|
constexpr int xPos = 2;
|
|
|
|
int yPos = 0;
|
2019-05-11 17:03:07 +00:00
|
|
|
const GUI::Font& f = hidpiEnabled() ? infoFont() : font();
|
|
|
|
const int dy = f.getFontHeight() + 2;
|
2018-07-30 21:19:09 +00:00
|
|
|
|
|
|
|
ostringstream ss;
|
2018-01-17 18:03:25 +00:00
|
|
|
|
|
|
|
myStatsMsg.surface->invalidate();
|
2018-02-05 12:45:34 +00:00
|
|
|
|
|
|
|
// draw scanlines
|
2022-10-20 10:48:51 +00:00
|
|
|
ColorId color = myOSystem.console().tia().frameBufferScanlinesLastFrame() !=
|
2019-12-26 20:58:55 +00:00
|
|
|
myLastScanlines ? kDbgColorRed : myStatsMsg.color;
|
2018-07-30 21:19:09 +00:00
|
|
|
|
|
|
|
ss
|
|
|
|
<< myOSystem.console().tia().frameBufferScanlinesLastFrame()
|
|
|
|
<< " / "
|
2020-10-23 12:57:06 +00:00
|
|
|
<< std::fixed << std::setprecision(1)
|
|
|
|
<< myOSystem.console().currentFrameRate()
|
2018-07-30 21:19:09 +00:00
|
|
|
<< "Hz => "
|
|
|
|
<< info.DisplayFormat;
|
|
|
|
|
2024-05-10 23:03:04 +00:00
|
|
|
myStatsMsg.surface->drawString(f, ss.view(), xPos, yPos,
|
2018-01-17 18:03:25 +00:00
|
|
|
myStatsMsg.w, color, TextAlign::Left, 0, true, kBGColor);
|
2018-01-21 10:05:00 +00:00
|
|
|
|
2018-07-30 21:19:09 +00:00
|
|
|
yPos += dy;
|
|
|
|
ss.str("");
|
2018-01-21 10:05:00 +00:00
|
|
|
|
2018-07-30 21:19:09 +00:00
|
|
|
ss
|
|
|
|
<< std::fixed << std::setprecision(1) << framesPerSecond
|
2018-07-31 15:07:51 +00:00
|
|
|
<< "fps @ "
|
2020-04-19 21:08:25 +00:00
|
|
|
<< std::fixed << std::setprecision(0) << 100 *
|
|
|
|
(myOSystem.settings().getBool("turbo")
|
2024-01-24 10:24:21 +00:00
|
|
|
? 50.0F
|
2020-04-19 21:08:25 +00:00
|
|
|
: myOSystem.settings().getFloat("speed"))
|
2018-07-30 21:19:09 +00:00
|
|
|
<< "% speed";
|
2018-02-12 22:32:03 +00:00
|
|
|
|
2024-05-10 23:03:04 +00:00
|
|
|
myStatsMsg.surface->drawString(f, ss.view(), xPos, yPos,
|
2019-12-26 20:58:55 +00:00
|
|
|
myStatsMsg.w, myStatsMsg.color, TextAlign::Left, 0, true, kBGColor);
|
2018-01-17 18:03:25 +00:00
|
|
|
|
2018-07-30 21:19:09 +00:00
|
|
|
yPos += dy;
|
|
|
|
ss.str("");
|
|
|
|
|
|
|
|
ss << info.BankSwitch;
|
2022-10-20 10:48:51 +00:00
|
|
|
int xPosEnd =
|
2024-05-10 23:03:04 +00:00
|
|
|
myStatsMsg.surface->drawString(f, ss.view(), xPos, yPos,
|
2022-10-20 10:48:51 +00:00
|
|
|
myStatsMsg.w, myStatsMsg.color, TextAlign::Left, 0, true, kBGColor);
|
2018-07-30 21:19:09 +00:00
|
|
|
|
2022-10-20 10:48:51 +00:00
|
|
|
if(myOSystem.settings().getBool("dev.settings"))
|
|
|
|
{
|
|
|
|
xPosEnd = myStatsMsg.surface->drawString(f, "| ", xPosEnd, yPos,
|
|
|
|
myStatsMsg.w, color, TextAlign::Left, 0, true, kBGColor);
|
|
|
|
ss.str("");
|
|
|
|
color = myStatsMsg.color;
|
|
|
|
if(myOSystem.console().vsyncCorrect())
|
|
|
|
ss << "Developer";
|
|
|
|
else
|
|
|
|
{
|
|
|
|
color = kDbgColorRed;
|
|
|
|
ss << "VSYNC!";
|
|
|
|
}
|
2024-05-10 23:03:04 +00:00
|
|
|
myStatsMsg.surface->drawString(f, ss.view(), xPosEnd, yPos,
|
2022-10-20 10:48:51 +00:00
|
|
|
myStatsMsg.w, color, TextAlign::Left, 0, true, kBGColor);
|
|
|
|
}
|
2018-01-17 18:03:25 +00:00
|
|
|
|
2023-08-20 05:46:33 +00:00
|
|
|
myStatsMsg.surface->setDstPos(imageRect().x() + imageRect().w() / 64,
|
|
|
|
imageRect().y() + imageRect().h() / 64);
|
2019-05-11 17:03:07 +00:00
|
|
|
myStatsMsg.surface->setDstSize(myStatsMsg.w * hidpiScaleFactor(),
|
|
|
|
myStatsMsg.h * hidpiScaleFactor());
|
2018-01-17 18:03:25 +00:00
|
|
|
myStatsMsg.surface->render();
|
2019-05-02 20:28:39 +00:00
|
|
|
#endif
|
2018-01-17 18:03:25 +00:00
|
|
|
}
|
|
|
|
|
2009-01-10 18:42:49 +00:00
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
2020-07-02 21:33:13 +00:00
|
|
|
void FrameBuffer::toggleFrameStats(bool toggle)
|
2009-01-10 18:42:49 +00:00
|
|
|
{
|
2020-07-02 21:33:13 +00:00
|
|
|
if (toggle)
|
|
|
|
showFrameStats(!myStatsEnabled);
|
2017-11-24 19:38:21 +00:00
|
|
|
myOSystem.settings().setValue(
|
|
|
|
myOSystem.settings().getBool("dev.settings") ? "dev.stats" : "plr.stats", myStatsEnabled);
|
2020-07-02 21:33:13 +00:00
|
|
|
|
2020-11-12 09:43:04 +00:00
|
|
|
myOSystem.frameBuffer().showTextMessage(string("Console info ") +
|
|
|
|
(myStatsEnabled ? "enabled" : "disabled"));
|
2009-01-10 18:42:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
void FrameBuffer::showFrameStats(bool enable)
|
|
|
|
{
|
2017-11-23 21:13:37 +00:00
|
|
|
myStatsEnabled = myStatsMsg.enabled = enable;
|
2009-01-10 18:42:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
void FrameBuffer::enableMessages(bool enable)
|
|
|
|
{
|
|
|
|
if(enable)
|
|
|
|
{
|
2010-04-14 15:41:42 +00:00
|
|
|
// Only re-enable frame stats if they were already enabled before
|
2017-11-23 21:13:37 +00:00
|
|
|
myStatsMsg.enabled = myStatsEnabled;
|
2009-01-10 18:42:49 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Temporarily disable frame stats
|
|
|
|
myStatsMsg.enabled = false;
|
2006-03-19 18:17:48 +00:00
|
|
|
|
2009-01-10 18:42:49 +00:00
|
|
|
// Erase old messages on the screen
|
2020-11-13 15:00:19 +00:00
|
|
|
hideMessage();
|
|
|
|
|
2020-11-12 10:50:26 +00:00
|
|
|
update(); // update immediately
|
2009-01-10 18:42:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-13 15:00:19 +00:00
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
void FrameBuffer::hideMessage()
|
|
|
|
{
|
|
|
|
myPendingRender = myMsg.enabled;
|
|
|
|
myMsg.enabled = false;
|
|
|
|
}
|
|
|
|
|
2009-01-10 18:42:49 +00:00
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
2018-07-25 11:18:21 +00:00
|
|
|
inline bool FrameBuffer::drawMessage()
|
2009-01-10 18:42:49 +00:00
|
|
|
{
|
2019-05-02 20:28:39 +00:00
|
|
|
#ifdef GUI_SUPPORT
|
2018-07-25 11:18:21 +00:00
|
|
|
// Either erase the entire message (when time is reached),
|
|
|
|
// or show again this frame
|
|
|
|
if(myMsg.counter == 0)
|
|
|
|
{
|
2020-11-13 15:00:19 +00:00
|
|
|
hideMessage();
|
2018-07-25 11:18:21 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-11-12 09:43:04 +00:00
|
|
|
if(myMsg.dirty)
|
2006-03-19 18:17:48 +00:00
|
|
|
{
|
2020-12-21 08:14:42 +00:00
|
|
|
#ifdef DEBUG_BUILD
|
2020-11-25 16:23:05 +00:00
|
|
|
cerr << "m";
|
2023-11-16 18:04:02 +00:00
|
|
|
//cerr << "--- draw message ---\n";
|
2020-12-21 08:14:42 +00:00
|
|
|
#endif
|
2006-03-19 18:17:48 +00:00
|
|
|
|
2020-11-12 09:43:04 +00:00
|
|
|
// Draw the bounded box and text
|
|
|
|
const Common::Rect& dst = myMsg.surface->dstRect();
|
|
|
|
const int fontWidth = font().getMaxCharWidth(),
|
2023-08-20 05:46:33 +00:00
|
|
|
fontHeight = font().getFontHeight();
|
2020-11-12 09:43:04 +00:00
|
|
|
const int VBORDER = fontHeight / 4;
|
|
|
|
const int HBORDER = fontWidth * 1.25 / 2.0;
|
|
|
|
constexpr int BORDER = 1;
|
2006-03-19 18:17:48 +00:00
|
|
|
|
2020-11-12 09:43:04 +00:00
|
|
|
switch(myMsg.position)
|
|
|
|
{
|
|
|
|
case MessagePosition::TopLeft:
|
|
|
|
myMsg.x = 5;
|
|
|
|
myMsg.y = 5;
|
|
|
|
break;
|
2006-03-19 18:17:48 +00:00
|
|
|
|
2020-11-12 09:43:04 +00:00
|
|
|
case MessagePosition::TopCenter:
|
|
|
|
myMsg.x = (imageRect().w() - dst.w()) >> 1;
|
|
|
|
myMsg.y = 5;
|
|
|
|
break;
|
2006-03-19 18:17:48 +00:00
|
|
|
|
2020-11-12 09:43:04 +00:00
|
|
|
case MessagePosition::TopRight:
|
|
|
|
myMsg.x = imageRect().w() - dst.w() - 5;
|
|
|
|
myMsg.y = 5;
|
|
|
|
break;
|
2006-03-19 18:17:48 +00:00
|
|
|
|
2020-11-12 09:43:04 +00:00
|
|
|
case MessagePosition::MiddleLeft:
|
|
|
|
myMsg.x = 5;
|
|
|
|
myMsg.y = (imageRect().h() - dst.h()) >> 1;
|
|
|
|
break;
|
2006-03-19 18:17:48 +00:00
|
|
|
|
2020-11-12 09:43:04 +00:00
|
|
|
case MessagePosition::MiddleCenter:
|
|
|
|
myMsg.x = (imageRect().w() - dst.w()) >> 1;
|
|
|
|
myMsg.y = (imageRect().h() - dst.h()) >> 1;
|
|
|
|
break;
|
2006-03-19 18:17:48 +00:00
|
|
|
|
2020-11-12 09:43:04 +00:00
|
|
|
case MessagePosition::MiddleRight:
|
|
|
|
myMsg.x = imageRect().w() - dst.w() - 5;
|
|
|
|
myMsg.y = (imageRect().h() - dst.h()) >> 1;
|
|
|
|
break;
|
2006-03-19 18:17:48 +00:00
|
|
|
|
2020-11-12 09:43:04 +00:00
|
|
|
case MessagePosition::BottomLeft:
|
|
|
|
myMsg.x = 5;
|
|
|
|
myMsg.y = imageRect().h() - dst.h() - 5;
|
|
|
|
break;
|
2005-03-13 03:38:41 +00:00
|
|
|
|
2020-11-12 09:43:04 +00:00
|
|
|
case MessagePosition::BottomCenter:
|
|
|
|
myMsg.x = (imageRect().w() - dst.w()) >> 1;
|
|
|
|
myMsg.y = imageRect().h() - dst.h() - 5;
|
|
|
|
break;
|
2020-05-13 07:32:11 +00:00
|
|
|
|
2020-11-12 09:43:04 +00:00
|
|
|
case MessagePosition::BottomRight:
|
|
|
|
myMsg.x = imageRect().w() - dst.w() - 5;
|
|
|
|
myMsg.y = imageRect().h() - dst.h() - 5;
|
|
|
|
break;
|
2024-05-08 21:43:23 +00:00
|
|
|
|
|
|
|
default:
|
|
|
|
break; // Not supposed to get here
|
2020-05-13 07:32:11 +00:00
|
|
|
}
|
2020-11-12 09:43:04 +00:00
|
|
|
|
|
|
|
myMsg.surface->setDstPos(myMsg.x + imageRect().x(), myMsg.y + imageRect().y());
|
|
|
|
myMsg.surface->fillRect(0, 0, myMsg.w, myMsg.h, kColor);
|
|
|
|
myMsg.surface->fillRect(BORDER, BORDER, myMsg.w - BORDER * 2, myMsg.h - BORDER * 2, kBtnColor);
|
|
|
|
myMsg.surface->drawString(font(), myMsg.text, HBORDER, VBORDER,
|
2020-05-13 07:32:11 +00:00
|
|
|
myMsg.w, myMsg.color);
|
2020-11-12 09:43:04 +00:00
|
|
|
|
|
|
|
if(myMsg.showGauge)
|
|
|
|
{
|
|
|
|
constexpr int NUM_TICKMARKS = 4;
|
|
|
|
// limit gauge bar width if texts are too long
|
|
|
|
const int swidth = std::min(fontWidth * GAUGEBAR_WIDTH,
|
|
|
|
fontWidth * (MESSAGE_WIDTH - 2)
|
|
|
|
- font().getStringWidth(myMsg.text)
|
|
|
|
- font().getStringWidth(myMsg.valueText));
|
|
|
|
const int bwidth = swidth * myMsg.value / 100.F;
|
|
|
|
const int bheight = fontHeight >> 1;
|
|
|
|
const int x = HBORDER + font().getStringWidth(myMsg.text) + fontWidth;
|
|
|
|
// align bar with bottom of text
|
|
|
|
const int y = VBORDER + font().desc().ascent - bheight;
|
|
|
|
|
|
|
|
// draw gauge bar
|
|
|
|
myMsg.surface->fillRect(x - BORDER, y, swidth + BORDER * 2, bheight, kSliderBGColor);
|
|
|
|
myMsg.surface->fillRect(x, y + BORDER, bwidth, bheight - BORDER * 2, kSliderColor);
|
|
|
|
// draw tickmark in the middle of the bar
|
|
|
|
for(int i = 1; i < NUM_TICKMARKS; ++i)
|
|
|
|
{
|
2022-03-29 00:30:26 +00:00
|
|
|
const int xt = x + swidth * i / NUM_TICKMARKS;
|
|
|
|
const ColorId color = (bwidth < xt - x) ? kCheckColor : kSliderBGColor;
|
2020-11-12 09:43:04 +00:00
|
|
|
myMsg.surface->vLine(xt, y + bheight / 2, y + bheight - 1, color);
|
|
|
|
}
|
|
|
|
// draw value text
|
|
|
|
myMsg.surface->drawString(font(), myMsg.valueText,
|
|
|
|
x + swidth + fontWidth, VBORDER,
|
|
|
|
myMsg.w, myMsg.color);
|
|
|
|
}
|
|
|
|
myMsg.dirty = false;
|
|
|
|
myMsg.surface->render();
|
|
|
|
return true;
|
2020-05-13 07:32:11 +00:00
|
|
|
}
|
2020-11-12 09:43:04 +00:00
|
|
|
|
2018-07-25 11:18:21 +00:00
|
|
|
myMsg.counter--;
|
2020-11-12 09:43:04 +00:00
|
|
|
myMsg.surface->render();
|
2019-05-02 20:28:39 +00:00
|
|
|
#endif
|
2006-03-18 00:00:30 +00:00
|
|
|
|
2020-11-12 09:43:04 +00:00
|
|
|
return false;
|
2006-03-18 00:00:30 +00:00
|
|
|
}
|
|
|
|
|
2017-12-13 18:15:09 +00:00
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
2017-12-15 17:10:40 +00:00
|
|
|
void FrameBuffer::setPauseDelay()
|
2017-12-13 18:15:09 +00:00
|
|
|
{
|
2022-03-29 00:30:26 +00:00
|
|
|
myPausedCount = static_cast<uInt32>(2 * myOSystem.frameRate());
|
2017-12-13 18:15:09 +00:00
|
|
|
}
|
|
|
|
|
2008-12-12 15:51:07 +00:00
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
2021-05-29 00:42:12 +00:00
|
|
|
shared_ptr<FBSurface> FrameBuffer::allocateSurface(
|
2021-01-13 19:54:09 +00:00
|
|
|
int w, int h, ScalingInterpolation inter, const uInt32* data)
|
2008-12-12 15:51:07 +00:00
|
|
|
{
|
2021-05-29 00:42:12 +00:00
|
|
|
mySurfaceList.push_back(myBackend->createSurface(w, h, inter, data));
|
|
|
|
return mySurfaceList.back();
|
2008-12-12 15:51:07 +00:00
|
|
|
}
|
|
|
|
|
2018-06-07 15:16:26 +00:00
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
2022-08-20 18:02:15 +00:00
|
|
|
void FrameBuffer::deallocateSurface(const shared_ptr<FBSurface>& surface)
|
2018-06-07 15:16:26 +00:00
|
|
|
{
|
2021-05-29 00:42:12 +00:00
|
|
|
if(surface)
|
|
|
|
mySurfaceList.remove(surface);
|
|
|
|
}
|
|
|
|
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
void FrameBuffer::resetSurfaces()
|
|
|
|
{
|
|
|
|
for(auto& surface: mySurfaceList)
|
|
|
|
surface->reload();
|
2018-07-25 11:18:21 +00:00
|
|
|
|
2020-11-13 18:53:19 +00:00
|
|
|
update(UpdateMode::REDRAW); // force full update
|
2008-12-12 15:51:07 +00:00
|
|
|
}
|
|
|
|
|
2023-08-19 16:12:32 +00:00
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
2023-08-27 06:00:14 +00:00
|
|
|
void FrameBuffer::renderTIA(bool doClear, bool shade)
|
2023-08-19 16:12:32 +00:00
|
|
|
{
|
|
|
|
if(doClear)
|
|
|
|
clear(); // TODO - test this: it may cause slowdowns on older systems
|
|
|
|
|
|
|
|
myTIASurface->render(shade);
|
2023-08-25 13:57:21 +00:00
|
|
|
if(myBezel)
|
2023-08-27 20:37:55 +00:00
|
|
|
myBezel->render();
|
2023-08-19 16:12:32 +00:00
|
|
|
}
|
|
|
|
|
2009-01-03 15:44:13 +00:00
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
2019-12-26 20:58:55 +00:00
|
|
|
void FrameBuffer::setTIAPalette(const PaletteArray& rgb_palette)
|
2009-01-03 15:44:13 +00:00
|
|
|
{
|
2019-12-26 20:58:55 +00:00
|
|
|
// Create a TIA palette from the raw RGB data
|
2022-03-29 00:30:26 +00:00
|
|
|
PaletteArray tia_palette = {0};
|
2014-05-12 23:34:25 +00:00
|
|
|
for(int i = 0; i < 256; ++i)
|
2006-01-10 02:09:34 +00:00
|
|
|
{
|
2022-03-29 00:30:26 +00:00
|
|
|
const uInt8 r = (rgb_palette[i] >> 16) & 0xff;
|
|
|
|
const uInt8 g = (rgb_palette[i] >> 8) & 0xff;
|
|
|
|
const uInt8 b = rgb_palette[i] & 0xff;
|
2003-10-26 19:40:39 +00:00
|
|
|
|
2019-12-26 20:58:55 +00:00
|
|
|
tia_palette[i] = mapRGB(r, g, b);
|
2005-03-28 00:04:54 +00:00
|
|
|
}
|
|
|
|
|
2019-12-26 20:58:55 +00:00
|
|
|
// Remember the TIA palette; place it at the beginning of the full palette
|
|
|
|
std::copy_n(tia_palette.begin(), tia_palette.size(), myFullPalette.begin());
|
|
|
|
|
2014-05-12 23:34:25 +00:00
|
|
|
// Let the TIA surface know about the new palette
|
2019-12-26 20:58:55 +00:00
|
|
|
myTIASurface->setPalette(tia_palette, rgb_palette);
|
|
|
|
|
|
|
|
// Since the UI palette shares the TIA palette, we need to update it too
|
|
|
|
setUIPalette();
|
|
|
|
}
|
|
|
|
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
void FrameBuffer::setUIPalette()
|
|
|
|
{
|
2023-03-15 16:06:52 +00:00
|
|
|
const Settings& settings = myOSystem.settings();
|
|
|
|
const string& key = settings.getBool("altuipalette") ? "uipalette2" : "uipalette";
|
2019-12-26 20:58:55 +00:00
|
|
|
// Set palette for UI (upper area of full palette)
|
|
|
|
const UIPaletteArray& ui_palette =
|
2023-03-15 16:06:52 +00:00
|
|
|
(settings.getString(key) == "classic") ? ourClassicUIPalette :
|
|
|
|
(settings.getString(key) == "light") ? ourLightUIPalette :
|
|
|
|
(settings.getString(key) == "dark") ? ourDarkUIPalette :
|
2019-12-26 20:58:55 +00:00
|
|
|
ourStandardUIPalette;
|
|
|
|
|
|
|
|
for(size_t i = 0, j = myFullPalette.size() - ui_palette.size();
|
|
|
|
i < ui_palette.size(); ++i, ++j)
|
|
|
|
{
|
|
|
|
const uInt8 r = (ui_palette[i] >> 16) & 0xff,
|
|
|
|
g = (ui_palette[i] >> 8) & 0xff,
|
|
|
|
b = ui_palette[i] & 0xff;
|
|
|
|
|
|
|
|
myFullPalette[j] = mapRGB(r, g, b);
|
|
|
|
}
|
|
|
|
FBSurface::setPalette(myFullPalette);
|
2003-10-26 19:40:39 +00:00
|
|
|
}
|
|
|
|
|
2009-01-10 18:52:55 +00:00
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
2017-12-21 01:26:22 +00:00
|
|
|
void FrameBuffer::stateChanged(EventHandlerState state)
|
2009-01-10 18:52:55 +00:00
|
|
|
{
|
2022-12-17 10:03:48 +00:00
|
|
|
// Prevent removing state change messages
|
|
|
|
if(myMsg.counter < MESSAGE_TIME - 1)
|
|
|
|
{
|
|
|
|
// Make sure any onscreen messages are removed
|
|
|
|
hideMessage();
|
|
|
|
}
|
2020-11-12 10:50:26 +00:00
|
|
|
update(); // update immediately
|
2009-01-10 18:52:55 +00:00
|
|
|
}
|
|
|
|
|
2020-05-02 14:46:37 +00:00
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
2021-04-06 13:56:01 +00:00
|
|
|
string FrameBuffer::getDisplayKey(BufferType bufferType) const
|
2020-05-02 14:46:37 +00:00
|
|
|
{
|
2021-04-06 13:56:01 +00:00
|
|
|
if(bufferType == BufferType::None)
|
|
|
|
bufferType = myBufferType;
|
|
|
|
|
2020-05-02 14:46:37 +00:00
|
|
|
// save current window's display and position
|
2021-04-06 13:56:01 +00:00
|
|
|
switch(bufferType)
|
2020-05-02 14:46:37 +00:00
|
|
|
{
|
|
|
|
case BufferType::Launcher:
|
|
|
|
return "launcherdisplay";
|
|
|
|
|
|
|
|
case BufferType::Emulator:
|
|
|
|
return "display";
|
|
|
|
|
2020-11-13 15:12:33 +00:00
|
|
|
#ifdef DEBUGGER_SUPPORT
|
2020-05-02 14:46:37 +00:00
|
|
|
case BufferType::Debugger:
|
|
|
|
return "dbg.display";
|
2020-11-13 15:12:33 +00:00
|
|
|
#endif
|
2020-05-02 14:46:37 +00:00
|
|
|
|
|
|
|
default:
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
2020-12-20 17:09:28 +00:00
|
|
|
string FrameBuffer::getPositionKey() const
|
2020-05-02 14:46:37 +00:00
|
|
|
{
|
|
|
|
// save current window's display and position
|
|
|
|
switch(myBufferType)
|
|
|
|
{
|
|
|
|
case BufferType::Launcher:
|
|
|
|
return "launcherpos";
|
|
|
|
|
|
|
|
case BufferType::Emulator:
|
|
|
|
return "windowedpos";
|
|
|
|
|
2020-11-13 15:12:33 +00:00
|
|
|
#ifdef DEBUGGER_SUPPORT
|
2020-05-02 14:46:37 +00:00
|
|
|
case BufferType::Debugger:
|
|
|
|
return "dbg.pos";
|
2020-11-13 15:12:33 +00:00
|
|
|
#endif
|
2020-05-02 14:46:37 +00:00
|
|
|
|
|
|
|
default:
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
2020-12-20 17:09:28 +00:00
|
|
|
void FrameBuffer::saveCurrentWindowPosition() const
|
2020-05-02 14:46:37 +00:00
|
|
|
{
|
2020-12-20 17:09:28 +00:00
|
|
|
if(myBackend)
|
|
|
|
{
|
2020-10-23 12:57:06 +00:00
|
|
|
myOSystem.settings().setValue(
|
2020-12-20 17:09:28 +00:00
|
|
|
getDisplayKey(), myBackend->getCurrentDisplayIndex());
|
|
|
|
if(myBackend->isCurrentWindowPositioned())
|
|
|
|
myOSystem.settings().setValue(
|
|
|
|
getPositionKey(), myBackend->getCurrentWindowPos());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
void FrameBuffer::saveConfig(Settings& settings) const
|
|
|
|
{
|
|
|
|
// Save the last windowed position and display on system shutdown
|
|
|
|
saveCurrentWindowPosition();
|
2020-05-02 14:46:37 +00:00
|
|
|
}
|
|
|
|
|
2005-05-01 20:11:07 +00:00
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
void FrameBuffer::setFullscreen(bool enable)
|
|
|
|
{
|
2019-03-31 19:12:48 +00:00
|
|
|
#ifdef WINDOWED_SUPPORT
|
2018-08-15 16:03:08 +00:00
|
|
|
// Switching between fullscreen and windowed modes will invariably mean
|
|
|
|
// that the 'window' resolution changes. Currently, dialogs are not
|
|
|
|
// able to resize themselves when they are actively being shown
|
|
|
|
// (they would have to be closed and then re-opened, etc).
|
|
|
|
// For now, we simply disallow screen switches in such modes
|
|
|
|
switch(myOSystem.eventHandler().state())
|
|
|
|
{
|
|
|
|
case EventHandlerState::EMULATION:
|
|
|
|
case EventHandlerState::PAUSE:
|
|
|
|
break; // continue with processing (aka, allow a mode switch)
|
2019-05-12 00:46:23 +00:00
|
|
|
case EventHandlerState::DEBUGGER:
|
|
|
|
case EventHandlerState::LAUNCHER:
|
|
|
|
if(myOSystem.eventHandler().overlay().baseDialogIsActive())
|
|
|
|
break; // allow a mode switch when there is only one dialog
|
|
|
|
[[fallthrough]];
|
2018-08-15 16:03:08 +00:00
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-10-13 13:17:37 +00:00
|
|
|
myOSystem.settings().setValue("fullscreen", enable);
|
2020-10-16 16:49:15 +00:00
|
|
|
saveCurrentWindowPosition();
|
|
|
|
applyVideoMode();
|
2019-03-31 19:12:48 +00:00
|
|
|
#endif
|
2005-03-28 00:04:54 +00:00
|
|
|
}
|
|
|
|
|
2014-04-28 16:47:10 +00:00
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
2020-05-16 11:00:38 +00:00
|
|
|
void FrameBuffer::toggleFullscreen(bool toggle)
|
2014-04-28 16:47:10 +00:00
|
|
|
{
|
2022-03-29 00:30:26 +00:00
|
|
|
const EventHandlerState state = myOSystem.eventHandler().state();
|
2020-11-13 15:12:33 +00:00
|
|
|
|
|
|
|
switch(state)
|
2020-07-02 07:33:16 +00:00
|
|
|
{
|
|
|
|
case EventHandlerState::LAUNCHER:
|
|
|
|
case EventHandlerState::EMULATION:
|
|
|
|
case EventHandlerState::PAUSE:
|
|
|
|
case EventHandlerState::DEBUGGER:
|
|
|
|
{
|
|
|
|
const bool isFullscreen = toggle ? !fullScreen() : fullScreen();
|
|
|
|
setFullscreen(isFullscreen);
|
2020-05-16 11:00:38 +00:00
|
|
|
|
2020-11-13 15:12:33 +00:00
|
|
|
if(state != EventHandlerState::LAUNCHER)
|
2020-07-02 07:33:16 +00:00
|
|
|
{
|
|
|
|
ostringstream msg;
|
|
|
|
msg << "Fullscreen ";
|
2020-05-18 19:13:18 +00:00
|
|
|
|
2020-11-13 15:12:33 +00:00
|
|
|
if(state != EventHandlerState::DEBUGGER)
|
|
|
|
{
|
|
|
|
if(isFullscreen)
|
|
|
|
msg << "enabled (" << myBackend->refreshRate() << " Hz, ";
|
|
|
|
else
|
|
|
|
msg << "disabled (";
|
2023-08-25 13:57:21 +00:00
|
|
|
msg << "Zoom " << round(myActiveVidMode.zoom * 100) << "%)";
|
2020-11-13 15:12:33 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if(isFullscreen)
|
|
|
|
msg << "enabled";
|
|
|
|
else
|
|
|
|
msg << "disabled";
|
|
|
|
}
|
2024-05-10 23:03:04 +00:00
|
|
|
showTextMessage(msg.view());
|
2020-07-02 07:33:16 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
break;
|
2020-05-19 06:53:11 +00:00
|
|
|
}
|
2014-04-28 16:47:10 +00:00
|
|
|
}
|
|
|
|
|
2020-05-24 08:03:53 +00:00
|
|
|
#ifdef ADAPTABLE_REFRESH_SUPPORT
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
void FrameBuffer::toggleAdaptRefresh(bool toggle)
|
|
|
|
{
|
|
|
|
bool isAdaptRefresh = myOSystem.settings().getInt("tia.fs_refresh");
|
|
|
|
|
|
|
|
if(toggle)
|
|
|
|
isAdaptRefresh = !isAdaptRefresh;
|
|
|
|
|
|
|
|
if(myBufferType == BufferType::Emulator)
|
|
|
|
{
|
|
|
|
if(toggle)
|
|
|
|
{
|
|
|
|
myOSystem.settings().setValue("tia.fs_refresh", isAdaptRefresh);
|
|
|
|
// issue a complete framebuffer re-initialization
|
|
|
|
myOSystem.createFrameBuffer();
|
|
|
|
}
|
|
|
|
|
|
|
|
ostringstream msg;
|
|
|
|
|
|
|
|
msg << "Adapt refresh rate ";
|
|
|
|
msg << (isAdaptRefresh ? "enabled" : "disabled");
|
2020-10-23 12:57:06 +00:00
|
|
|
msg << " (" << myBackend->refreshRate() << " Hz)";
|
2020-05-24 08:03:53 +00:00
|
|
|
|
2024-05-10 23:03:04 +00:00
|
|
|
showTextMessage(msg.view());
|
2020-05-24 08:03:53 +00:00
|
|
|
}
|
2014-04-28 16:47:10 +00:00
|
|
|
}
|
2020-05-24 08:03:53 +00:00
|
|
|
#endif
|
2014-04-28 16:47:10 +00:00
|
|
|
|
2019-06-02 07:21:20 +00:00
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
void FrameBuffer::changeOverscan(int direction)
|
|
|
|
{
|
|
|
|
if (fullScreen())
|
|
|
|
{
|
2022-03-29 00:30:26 +00:00
|
|
|
const int oldOverscan = myOSystem.settings().getInt("tia.fs_overscan");
|
|
|
|
const int overscan = BSPF::clamp(oldOverscan + direction, 0, 10);
|
2019-06-02 07:21:20 +00:00
|
|
|
|
|
|
|
if (overscan != oldOverscan)
|
|
|
|
{
|
|
|
|
myOSystem.settings().setValue("tia.fs_overscan", overscan);
|
|
|
|
|
|
|
|
// issue a complete framebuffer re-initialization
|
|
|
|
myOSystem.createFrameBuffer();
|
|
|
|
}
|
2020-05-13 07:32:11 +00:00
|
|
|
|
|
|
|
ostringstream val;
|
2020-05-16 07:50:16 +00:00
|
|
|
if(overscan)
|
|
|
|
val << (overscan > 0 ? "+" : "" ) << overscan << "%";
|
|
|
|
else
|
|
|
|
val << "Off";
|
2024-05-10 23:03:04 +00:00
|
|
|
myOSystem.frameBuffer().showGaugeMessage("Overscan", val.view(), overscan, 0, 10);
|
2019-06-02 07:21:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-03-28 00:04:54 +00:00
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
2020-10-13 13:17:37 +00:00
|
|
|
void FrameBuffer::switchVideoMode(int direction)
|
2005-03-28 00:04:54 +00:00
|
|
|
{
|
2019-04-08 21:14:27 +00:00
|
|
|
// Only applicable when in TIA/emulation mode
|
2020-10-16 16:49:15 +00:00
|
|
|
if(!myOSystem.eventHandler().inTIAMode())
|
2020-05-16 07:50:16 +00:00
|
|
|
return;
|
Reworked 'fullres' argument to also accept the 'auto' option. In this case,
fullscreen resolutions will be automatically chosen based on the required
size for the window. The image will be centered and keep the same aspect
ratio, however, so operation will still work correctly on widescreen
monitors. 'Auto' will be the new default. Otherwise, if a specific
resolution is requested, Stella will try to accomodate it *only* if it fits
into the resolution; otherwise the smallest resolution that fits will be
used.
Removed 'zoom_ui' and 'zoom_tia'. The UI can now only be at 1x mode.
Aded 'tia_filter' commandline argument, which specifies to the filter
to use when rendering the tia image. For now, these accept 'zoom1x',
'zoom2x'..., up to 'zoom10x', and duplicate previous behaviour. Eventually,
Scalexx and HQxx filters may be added. Still TODO is add this to the UI.
First pass at making the standard build use a minimum of zoom2x for the TIA,
so the UI can be larger and use a better looking font. There's still work
to do in this area, especially for those ports with limited hardware that
support zoom1x only.
git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1544 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
2008-07-22 14:54:39 +00:00
|
|
|
|
2020-10-13 13:17:37 +00:00
|
|
|
if(!fullScreen())
|
|
|
|
{
|
|
|
|
// Windowed TIA modes support variable zoom levels
|
2023-10-15 16:23:46 +00:00
|
|
|
auto zoom = static_cast<double>(myOSystem.settings().getFloat("tia.zoom"));
|
2020-10-13 13:17:37 +00:00
|
|
|
if(direction == +1) zoom += ZOOM_STEPS;
|
|
|
|
else if(direction == -1) zoom -= ZOOM_STEPS;
|
|
|
|
|
|
|
|
// Make sure the level is within the allowable desktop size
|
2023-08-28 09:16:27 +00:00
|
|
|
zoom = BSPF::clampw(zoom, supportedTIAMinZoom(), supportedTIAMaxZoom());
|
2020-10-13 13:17:37 +00:00
|
|
|
myOSystem.settings().setValue("tia.zoom", zoom);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// In fullscreen mode, there are only two modes, so direction
|
|
|
|
// is irrelevant
|
|
|
|
if(direction == +1 || direction == -1)
|
|
|
|
{
|
2022-09-14 01:22:59 +00:00
|
|
|
const bool stretch = myOSystem.settings().getBool("tia.fs_stretch");
|
2020-10-13 13:17:37 +00:00
|
|
|
myOSystem.settings().setValue("tia.fs_stretch", !stretch);
|
|
|
|
}
|
|
|
|
}
|
Added preliminary framework for using advanced scalers. Right now,
functionality is exactly the same as before; Alt-Equals goes to the
next valid scaler, and Alt-Minus goes to the previous one.
What were previously zoomed modes are now treated as scalers, named
'Zoom1x', 'Zoom2x', etc. Various scalexx and hqxx modes will also be made
available.
For now, and probably forever, these advanced scaling modes will only
be available for OpenGL, since if you don't have a card that can handle
GL well, the scalers will probably be too much anyway. Also, the advanced
scaling will not be available in UI mode, only OpenGL emulation mode.
The UI (Launcher, Debugger) and emulation modes are now scaled separately,
specified with the new settings 'scale_ui' and 'scale_tia'. The 'zoom'
setting has been removed.
git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1133 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
2006-10-14 20:08:29 +00:00
|
|
|
|
2020-05-07 21:09:11 +00:00
|
|
|
saveCurrentWindowPosition();
|
2021-11-01 16:55:45 +00:00
|
|
|
if(!direction || applyVideoMode() == FBInitStatus::Success)
|
2008-06-19 12:01:31 +00:00
|
|
|
{
|
2020-05-16 07:50:16 +00:00
|
|
|
if(fullScreen())
|
2020-11-12 09:43:04 +00:00
|
|
|
showTextMessage(myActiveVidMode.description);
|
2020-05-16 07:50:16 +00:00
|
|
|
else
|
2020-11-12 09:43:04 +00:00
|
|
|
showGaugeMessage("Zoom", myActiveVidMode.description, myActiveVidMode.zoom,
|
2021-04-06 13:56:01 +00:00
|
|
|
supportedTIAMinZoom(), supportedTIAMaxZoom());
|
2008-06-19 12:01:31 +00:00
|
|
|
}
|
2003-10-26 19:40:39 +00:00
|
|
|
}
|
|
|
|
|
2023-08-26 11:50:39 +00:00
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
void FrameBuffer::toggleBezel(bool toggle)
|
|
|
|
{
|
|
|
|
bool enabled = myOSystem.settings().getBool("bezel.show");
|
|
|
|
|
2023-08-27 14:57:36 +00:00
|
|
|
if(toggle && myBufferType == BufferType::Emulator)
|
2023-08-26 11:50:39 +00:00
|
|
|
{
|
2023-08-27 14:57:36 +00:00
|
|
|
if(!fullScreen() && !myOSystem.settings().getBool("bezel.windowed"))
|
|
|
|
{
|
|
|
|
myOSystem.frameBuffer().showTextMessage("Bezels in windowed mode are not enabled");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else
|
2023-08-26 11:50:39 +00:00
|
|
|
{
|
|
|
|
enabled = !enabled;
|
|
|
|
myOSystem.settings().setValue("bezel.show", enabled);
|
2023-08-27 14:57:36 +00:00
|
|
|
if(!myBezel->load() && enabled)
|
|
|
|
{
|
|
|
|
myOSystem.settings().setValue("bezel.show", !enabled);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Determine possible TIA windowed zoom levels
|
2023-10-15 16:23:46 +00:00
|
|
|
const auto currentTIAZoom =
|
2023-08-27 14:57:36 +00:00
|
|
|
static_cast<double>(myOSystem.settings().getFloat("tia.zoom"));
|
|
|
|
myOSystem.settings().setValue("tia.zoom",
|
|
|
|
BSPF::clamp(currentTIAZoom, supportedTIAMinZoom(), supportedTIAMaxZoom()));
|
|
|
|
|
|
|
|
saveCurrentWindowPosition();
|
|
|
|
applyVideoMode();
|
|
|
|
}
|
2023-08-26 11:50:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
myOSystem.frameBuffer().showTextMessage(enabled ? "Bezel enabled" : "Bezel disabled");
|
|
|
|
}
|
|
|
|
|
2020-10-13 13:17:37 +00:00
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
2020-10-16 16:49:15 +00:00
|
|
|
FBInitStatus FrameBuffer::applyVideoMode()
|
2020-10-13 13:17:37 +00:00
|
|
|
{
|
|
|
|
// Update display size, in case windowed/fullscreen mode has changed
|
|
|
|
const Settings& s = myOSystem.settings();
|
2022-03-29 00:30:26 +00:00
|
|
|
const int display = displayId();
|
2021-04-06 13:56:01 +00:00
|
|
|
|
2020-10-13 13:17:37 +00:00
|
|
|
if(s.getBool("fullscreen"))
|
2021-04-06 13:56:01 +00:00
|
|
|
myVidModeHandler.setDisplaySize(myFullscreenDisplays[display], display);
|
2020-10-13 13:17:37 +00:00
|
|
|
else
|
2021-04-06 13:56:01 +00:00
|
|
|
myVidModeHandler.setDisplaySize(myAbsDesktopSize[display]);
|
2020-10-13 13:17:37 +00:00
|
|
|
|
2020-10-16 16:49:15 +00:00
|
|
|
const bool inTIAMode = myOSystem.eventHandler().inTIAMode();
|
|
|
|
|
2023-08-27 20:37:55 +00:00
|
|
|
#ifdef IMAGE_SUPPORT
|
|
|
|
if(inTIAMode)
|
|
|
|
myBezel->load();
|
|
|
|
#endif
|
|
|
|
|
2020-10-16 16:49:15 +00:00
|
|
|
// Build the new mode based on current settings
|
2023-08-25 13:57:21 +00:00
|
|
|
const VideoModeHandler::Mode& mode
|
|
|
|
= myVidModeHandler.buildMode(s, inTIAMode, myBezel->info());
|
2020-10-16 16:49:15 +00:00
|
|
|
if(mode.imageR.size() > mode.screenS)
|
|
|
|
return FBInitStatus::FailTooLarge;
|
Added preliminary framework for using advanced scalers. Right now,
functionality is exactly the same as before; Alt-Equals goes to the
next valid scaler, and Alt-Minus goes to the previous one.
What were previously zoomed modes are now treated as scalers, named
'Zoom1x', 'Zoom2x', etc. Various scalexx and hqxx modes will also be made
available.
For now, and probably forever, these advanced scaling modes will only
be available for OpenGL, since if you don't have a card that can handle
GL well, the scalers will probably be too much anyway. Also, the advanced
scaling will not be available in UI mode, only OpenGL emulation mode.
The UI (Launcher, Debugger) and emulation modes are now scaled separately,
specified with the new settings 'scale_ui' and 'scale_tia'. The 'zoom'
setting has been removed.
git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@1133 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
2006-10-14 20:08:29 +00:00
|
|
|
|
2018-08-31 23:22:56 +00:00
|
|
|
// Changing the video mode can take some time, during which the last
|
|
|
|
// sound played may get 'stuck'
|
2022-09-25 00:03:39 +00:00
|
|
|
// So we pause the sound until the operation completes
|
|
|
|
const bool oldPauseState = myOSystem.sound().pause(true);
|
2020-10-16 16:49:15 +00:00
|
|
|
FBInitStatus status = FBInitStatus::FailNotSupported;
|
2018-08-31 23:22:56 +00:00
|
|
|
|
2020-10-23 12:57:06 +00:00
|
|
|
if(myBackend->setVideoMode(mode,
|
|
|
|
myOSystem.settings().getInt(getDisplayKey()),
|
|
|
|
myOSystem.settings().getPoint(getPositionKey()))
|
|
|
|
)
|
2008-06-19 12:01:31 +00:00
|
|
|
{
|
2020-10-16 16:49:15 +00:00
|
|
|
myActiveVidMode = mode;
|
|
|
|
status = FBInitStatus::Success;
|
2014-06-02 14:34:12 +00:00
|
|
|
|
2020-10-16 16:49:15 +00:00
|
|
|
// Did we get the requested fullscreen state?
|
|
|
|
myOSystem.settings().setValue("fullscreen", fullScreen());
|
|
|
|
|
|
|
|
// Inform TIA surface about new mode, and update TIA settings
|
|
|
|
if(inTIAMode)
|
|
|
|
{
|
2023-08-27 20:37:55 +00:00
|
|
|
myTIASurface->initialize(myOSystem.console(), myActiveVidMode);
|
2023-08-19 17:25:50 +00:00
|
|
|
if(fullScreen())
|
|
|
|
myOSystem.settings().setValue("tia.fs_stretch",
|
|
|
|
myActiveVidMode.stretch == VideoModeHandler::Mode::Stretch::Fill);
|
|
|
|
else
|
|
|
|
myOSystem.settings().setValue("tia.zoom", myActiveVidMode.zoom);
|
2023-08-27 20:37:55 +00:00
|
|
|
|
|
|
|
myBezel->apply();
|
2023-08-19 17:25:50 +00:00
|
|
|
}
|
|
|
|
|
2014-05-12 23:34:25 +00:00
|
|
|
resetSurfaces();
|
2020-10-16 16:49:15 +00:00
|
|
|
setCursorState();
|
2020-11-13 15:00:19 +00:00
|
|
|
myPendingRender = true;
|
2020-10-16 16:49:15 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
Logger::error("ERROR: Couldn't initialize video subsystem");
|
2019-04-08 21:14:27 +00:00
|
|
|
|
2020-10-16 16:49:15 +00:00
|
|
|
// Restore sound settings
|
2022-09-25 00:03:39 +00:00
|
|
|
myOSystem.sound().pause(oldPauseState);
|
2019-04-08 21:14:27 +00:00
|
|
|
|
2020-10-16 16:49:15 +00:00
|
|
|
return status;
|
2020-10-13 13:17:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
2023-08-25 13:57:21 +00:00
|
|
|
double FrameBuffer::maxWindowZoom() const
|
2020-10-13 13:17:37 +00:00
|
|
|
{
|
2022-03-29 00:30:26 +00:00
|
|
|
const int display = displayId(BufferType::Emulator);
|
2023-08-25 13:57:21 +00:00
|
|
|
double multiplier = 1;
|
2023-08-17 16:18:15 +00:00
|
|
|
|
2020-10-13 13:17:37 +00:00
|
|
|
for(;;)
|
|
|
|
{
|
2023-08-25 13:57:21 +00:00
|
|
|
// Figure out the zoomed size of the window (incl. the bezel)
|
|
|
|
const uInt32 width = static_cast<double>(TIAConstants::viewableWidth) * myBezel->ratioW() * multiplier;
|
|
|
|
const uInt32 height = static_cast<double>(TIAConstants::viewableHeight) * myBezel->ratioH() * multiplier;
|
2020-10-13 13:17:37 +00:00
|
|
|
|
2023-08-24 15:01:06 +00:00
|
|
|
if((width > myAbsDesktopSize[display].w) ||
|
|
|
|
(height > myAbsDesktopSize[display].h))
|
2020-10-13 13:17:37 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
multiplier += ZOOM_STEPS;
|
2008-06-19 12:01:31 +00:00
|
|
|
}
|
2020-10-13 13:17:37 +00:00
|
|
|
return multiplier > 1 ? multiplier - ZOOM_STEPS : 1;
|
2003-10-26 19:40:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
2005-03-28 00:04:54 +00:00
|
|
|
void FrameBuffer::setCursorState()
|
2003-10-26 19:40:39 +00:00
|
|
|
{
|
2020-12-17 15:37:51 +00:00
|
|
|
myGrabMouse = myOSystem.settings().getBool("grabmouse");
|
2017-01-28 23:15:30 +00:00
|
|
|
// Always grab mouse in emulation (if enabled) and emulating a controller
|
|
|
|
// that always uses the mouse
|
2020-12-17 15:37:51 +00:00
|
|
|
const bool emulation =
|
2017-12-21 01:26:22 +00:00
|
|
|
myOSystem.eventHandler().state() == EventHandlerState::EMULATION;
|
2020-12-17 15:37:51 +00:00
|
|
|
const bool usesLightgun = emulation && myOSystem.hasConsole() ?
|
2019-12-30 08:11:46 +00:00
|
|
|
myOSystem.console().leftController().type() == Controller::Type::Lightgun ||
|
|
|
|
myOSystem.console().rightController().type() == Controller::Type::Lightgun : false;
|
2015-06-28 18:16:33 +00:00
|
|
|
// Show/hide cursor in UI/emulation mode based on 'cursor' setting
|
2019-12-30 08:46:46 +00:00
|
|
|
int cursor = myOSystem.settings().getInt("cursor");
|
2020-12-17 15:37:51 +00:00
|
|
|
|
|
|
|
// Always enable cursor in lightgun games
|
2020-02-22 18:03:21 +00:00
|
|
|
if (usesLightgun && !myGrabMouse)
|
|
|
|
cursor |= 1; // +Emulation
|
2019-12-30 16:27:28 +00:00
|
|
|
|
2019-12-30 08:46:46 +00:00
|
|
|
switch(cursor)
|
2015-06-28 18:16:33 +00:00
|
|
|
{
|
2020-02-22 18:03:21 +00:00
|
|
|
case 0: // -UI, -Emulation
|
2019-12-30 08:46:46 +00:00
|
|
|
showCursor(false);
|
|
|
|
break;
|
|
|
|
case 1:
|
2020-12-17 15:37:51 +00:00
|
|
|
showCursor(emulation); // -UI, +Emulation
|
2019-12-30 08:46:46 +00:00
|
|
|
break;
|
2020-02-22 18:03:21 +00:00
|
|
|
case 2: // +UI, -Emulation
|
2019-12-30 08:46:46 +00:00
|
|
|
showCursor(!emulation);
|
|
|
|
break;
|
|
|
|
case 3:
|
2020-02-22 18:03:21 +00:00
|
|
|
showCursor(true); // +UI, +Emulation
|
2019-12-30 08:46:46 +00:00
|
|
|
break;
|
2020-12-16 19:54:46 +00:00
|
|
|
default:
|
|
|
|
break;
|
2015-06-28 18:16:33 +00:00
|
|
|
}
|
2019-12-30 08:46:46 +00:00
|
|
|
|
2020-12-17 15:37:51 +00:00
|
|
|
myGrabMouse &= grabMouseAllowed();
|
|
|
|
myBackend->grabMouse(myGrabMouse);
|
|
|
|
}
|
|
|
|
|
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
bool FrameBuffer::grabMouseAllowed()
|
|
|
|
{
|
|
|
|
// Allow grabbing mouse in emulation (if enabled) and emulating a controller
|
|
|
|
// that always uses the mouse
|
2022-03-29 00:30:26 +00:00
|
|
|
const bool emulation =
|
2020-12-17 15:37:51 +00:00
|
|
|
myOSystem.eventHandler().state() == EventHandlerState::EMULATION;
|
2022-03-29 00:30:26 +00:00
|
|
|
const bool analog = myOSystem.hasConsole() ?
|
2020-12-17 15:37:51 +00:00
|
|
|
(myOSystem.console().leftController().isAnalog() ||
|
|
|
|
myOSystem.console().rightController().isAnalog()) : false;
|
2022-03-29 00:30:26 +00:00
|
|
|
const bool usesLightgun = emulation && myOSystem.hasConsole() ?
|
2020-12-17 15:37:51 +00:00
|
|
|
myOSystem.console().leftController().type() == Controller::Type::Lightgun ||
|
|
|
|
myOSystem.console().rightController().type() == Controller::Type::Lightgun : false;
|
2022-03-29 00:30:26 +00:00
|
|
|
const bool alwaysUseMouse = BSPF::equalsIgnoreCase("always", myOSystem.settings().getString("usemouse"));
|
2020-12-17 15:37:51 +00:00
|
|
|
|
|
|
|
// Disable grab while cursor is shown in emulation
|
2022-09-14 01:22:59 +00:00
|
|
|
const bool cursorHidden = !(myOSystem.settings().getInt("cursor") & 1);
|
2020-12-17 15:37:51 +00:00
|
|
|
|
|
|
|
return emulation && (analog || usesLightgun || alwaysUseMouse) && cursorHidden;
|
2003-10-01 19:01:02 +00:00
|
|
|
}
|
|
|
|
|
2017-11-23 21:13:37 +00:00
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
void FrameBuffer::enableGrabMouse(bool enable)
|
|
|
|
{
|
|
|
|
myGrabMouse = enable;
|
|
|
|
setCursorState();
|
|
|
|
}
|
|
|
|
|
2011-06-07 13:40:59 +00:00
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
2020-12-17 15:37:51 +00:00
|
|
|
void FrameBuffer::toggleGrabMouse(bool toggle)
|
2011-06-07 13:40:59 +00:00
|
|
|
{
|
2020-12-17 15:37:51 +00:00
|
|
|
bool oldState = myGrabMouse = myOSystem.settings().getBool("grabmouse");
|
|
|
|
|
|
|
|
if(toggle)
|
|
|
|
{
|
|
|
|
if(grabMouseAllowed())
|
|
|
|
{
|
|
|
|
myGrabMouse = !myGrabMouse;
|
|
|
|
myOSystem.settings().setValue("grabmouse", myGrabMouse);
|
|
|
|
setCursorState();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
oldState = !myGrabMouse; // display current state
|
2020-05-14 09:12:56 +00:00
|
|
|
|
2020-11-12 09:43:04 +00:00
|
|
|
myOSystem.frameBuffer().showTextMessage(oldState != myGrabMouse ? myGrabMouse
|
|
|
|
? "Grab mouse enabled" : "Grab mouse disabled"
|
2020-12-17 15:37:51 +00:00
|
|
|
: "Grab mouse not allowed");
|
2019-04-08 21:14:27 +00:00
|
|
|
}
|
|
|
|
|
2014-01-31 16:23:10 +00:00
|
|
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
|
|
/*
|
|
|
|
Palette is defined as follows:
|
2017-12-17 09:09:59 +00:00
|
|
|
*** Base colors ***
|
2014-01-31 16:23:10 +00:00
|
|
|
kColor Normal foreground color (non-text)
|
|
|
|
kBGColor Normal background color (non-text)
|
2017-05-04 12:06:32 +00:00
|
|
|
kBGColorLo Disabled background color dark (non-text)
|
|
|
|
kBGColorHi Disabled background color light (non-text)
|
2023-08-29 11:51:10 +00:00
|
|
|
kShadowColor Item is disabled (unused)
|
2017-12-17 09:09:59 +00:00
|
|
|
*** Text colors ***
|
2014-01-31 16:23:10 +00:00
|
|
|
kTextColor Normal text color
|
|
|
|
kTextColorHi Highlighted text color
|
|
|
|
kTextColorEm Emphasized text color
|
2018-01-25 16:00:41 +00:00
|
|
|
kTextColorInv Color for selected text
|
2021-04-24 09:53:26 +00:00
|
|
|
kTextColorLink Color for links
|
2017-12-17 09:09:59 +00:00
|
|
|
*** UI elements (dialog and widgets) ***
|
2014-01-31 16:23:10 +00:00
|
|
|
kDlgColor Dialog background
|
|
|
|
kWidColor Widget background
|
2018-01-24 19:53:00 +00:00
|
|
|
kWidColorHi Widget highlight color
|
2014-01-31 16:23:10 +00:00
|
|
|
kWidFrameColor Border for currently selected widget
|
2017-12-17 09:09:59 +00:00
|
|
|
*** Button colors ***
|
2014-01-31 16:23:10 +00:00
|
|
|
kBtnColor Normal button background
|
|
|
|
kBtnColorHi Highlighted button background
|
2018-01-25 14:10:37 +00:00
|
|
|
kBtnBorderColor,
|
|
|
|
kBtnBorderColorHi,
|
2014-01-31 16:23:10 +00:00
|
|
|
kBtnTextColor Normal button font color
|
|
|
|
kBtnTextColorHi Highlighted button font color
|
2017-12-17 09:09:59 +00:00
|
|
|
*** Checkbox colors ***
|
2014-01-31 16:23:10 +00:00
|
|
|
kCheckColor Color of 'X' in checkbox
|
2017-12-17 09:09:59 +00:00
|
|
|
*** Scrollbar colors ***
|
2014-01-31 16:23:10 +00:00
|
|
|
kScrollColor Normal scrollbar color
|
|
|
|
kScrollColorHi Highlighted scrollbar color
|
2018-08-22 09:10:45 +00:00
|
|
|
*** Debugger colors ***
|
|
|
|
kDbgChangedColor Background color for changed cells
|
|
|
|
kDbgChangedTextColor Text color for changed cells
|
|
|
|
kDbgColorHi Highlighted color in debugger data cells
|
|
|
|
kDbgColorRed Red color in debugger
|
2017-12-17 09:09:59 +00:00
|
|
|
*** Slider colors ***
|
2018-02-01 17:21:57 +00:00
|
|
|
kSliderColor Enabled slider
|
|
|
|
kSliderColorHi Focussed slider
|
|
|
|
kSliderBGColor Enabled slider background
|
|
|
|
kSliderBGColorHi Focussed slider background
|
|
|
|
kSliderBGColorLo Disabled slider background
|
2018-01-24 13:37:07 +00:00
|
|
|
*** Other colors ***
|
|
|
|
kColorInfo TIA output position color
|
2018-01-26 11:55:05 +00:00
|
|
|
kColorTitleBar Title bar color
|
|
|
|
kColorTitleText Title text color
|
2014-01-31 16:23:10 +00:00
|
|
|
*/
|
2019-12-26 20:58:55 +00:00
|
|
|
UIPaletteArray FrameBuffer::ourStandardUIPalette = {
|
2018-01-25 16:00:41 +00:00
|
|
|
{ 0x686868, 0x000000, 0xa38c61, 0xdccfa5, 0x404040, // base
|
2021-04-24 09:53:26 +00:00
|
|
|
0x000000, 0xac3410, 0x9f0000, 0xf0f0cf, 0xac3410, // text
|
2018-01-25 16:00:41 +00:00
|
|
|
0xc9af7c, 0xf0f0cf, 0xd55941, 0xc80000, // UI elements
|
|
|
|
0xac3410, 0xd55941, 0x686868, 0xdccfa5, 0xf0f0cf, 0xf0f0cf, // buttons
|
|
|
|
0xac3410, // checkbox
|
2018-08-28 18:49:50 +00:00
|
|
|
0xac3410, 0xd55941, // scrollbar
|
2019-08-10 16:08:53 +00:00
|
|
|
0xc80000, 0xffff80, 0xc8c8ff, 0xc80000, // debugger
|
2018-08-22 09:10:45 +00:00
|
|
|
0xac3410, 0xd55941, 0xdccfa5, 0xf0f0cf, 0xa38c61, // slider
|
2020-11-14 09:03:29 +00:00
|
|
|
0xffffff, 0xac3410, 0xf0f0cf // other
|
2019-12-26 20:58:55 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
UIPaletteArray FrameBuffer::ourClassicUIPalette = {
|
2018-01-25 16:00:41 +00:00
|
|
|
{ 0x686868, 0x000000, 0x404040, 0x404040, 0x404040, // base
|
2021-04-24 09:53:26 +00:00
|
|
|
0x20a020, 0x00ff00, 0xc80000, 0x000000, 0x00ff00, // text
|
2018-01-25 16:00:41 +00:00
|
|
|
0x000000, 0x000000, 0x00ff00, 0xc80000, // UI elements
|
|
|
|
0x000000, 0x000000, 0x686868, 0x00ff00, 0x20a020, 0x00ff00, // buttons
|
|
|
|
0x20a020, // checkbox
|
2018-08-28 18:49:50 +00:00
|
|
|
0x20a020, 0x00ff00, // scrollbar
|
2018-01-25 16:00:41 +00:00
|
|
|
0xc80000, 0x00ff00, 0xc8c8ff, 0xc80000, // debugger
|
2018-08-22 09:10:45 +00:00
|
|
|
0x20a020, 0x00ff00, 0x404040, 0x686868, 0x404040, // slider
|
2020-11-14 09:03:29 +00:00
|
|
|
0x00ff00, 0x20a020, 0x000000 // other
|
2019-12-26 20:58:55 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
UIPaletteArray FrameBuffer::ourLightUIPalette = {
|
2018-01-26 10:33:46 +00:00
|
|
|
{ 0x808080, 0x000000, 0xc0c0c0, 0xe1e1e1, 0x333333, // base
|
2021-04-24 09:53:26 +00:00
|
|
|
0x000000, 0xBDDEF9, 0x0078d7, 0x000000, 0x005aa1, // text
|
2018-01-25 16:00:41 +00:00
|
|
|
0xf0f0f0, 0xffffff, 0x0078d7, 0x0f0f0f, // UI elements
|
|
|
|
0xe1e1e1, 0xe5f1fb, 0x808080, 0x0078d7, 0x000000, 0x000000, // buttons
|
|
|
|
0x333333, // checkbox
|
2018-08-28 18:49:50 +00:00
|
|
|
0xc0c0c0, 0x808080, // scrollbar
|
2018-01-25 16:00:41 +00:00
|
|
|
0xffc0c0, 0x000000, 0xe00000, 0xc00000, // debugger
|
2018-08-22 09:10:45 +00:00
|
|
|
0x333333, 0x0078d7, 0xc0c0c0, 0xffffff, 0xc0c0c0, // slider 0xBDDEF9| 0xe1e1e1 | 0xffffff
|
2020-11-14 09:03:29 +00:00
|
|
|
0xffffff, 0x333333, 0xf0f0f0 // other
|
2014-09-03 13:27:33 +00:00
|
|
|
}
|
2014-01-31 16:23:10 +00:00
|
|
|
};
|
2020-06-21 13:58:58 +00:00
|
|
|
|
|
|
|
UIPaletteArray FrameBuffer::ourDarkUIPalette = {
|
|
|
|
{ 0x646464, 0xc0c0c0, 0x3c3c3c, 0x282828, 0x989898, // base
|
2021-04-25 19:08:06 +00:00
|
|
|
0xc0c0c0, 0x1567a5, 0x0064b7, 0xc0c0c0, 0x1d92e0, // text
|
2020-06-21 13:58:58 +00:00
|
|
|
0x202020, 0x000000, 0x0059a3, 0xb0b0b0, // UI elements
|
|
|
|
0x282828, 0x00467f, 0x646464, 0x0059a3, 0xc0c0c0, 0xc0c0c0, // buttons
|
|
|
|
0x989898, // checkbox
|
|
|
|
0x3c3c3c, 0x646464, // scrollbar
|
|
|
|
0x7f2020, 0xc0c0c0, 0xe00000, 0xc00000, // debugger
|
|
|
|
0x989898, 0x0059a3, 0x3c3c3c, 0x000000, 0x3c3c3c, // slider
|
2023-08-29 11:51:10 +00:00
|
|
|
0x000000, 0x404040, 0xc0c0c0 // other
|
2020-06-21 13:58:58 +00:00
|
|
|
}
|
|
|
|
};
|