Compare commits
3 Commits
Author | SHA1 | Date |
---|---|---|
![]() |
2128ceb81a | |
![]() |
01702f1230 | |
![]() |
3dbdcd0682 |
|
@ -11,46 +11,35 @@ jobs:
|
|||
linux:
|
||||
name: Linux
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
SDL3_VERSION: 3.2.14
|
||||
steps:
|
||||
- name: Check out the repository
|
||||
uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8
|
||||
- name: Install SDL3
|
||||
- name: Install SDL2
|
||||
run: |
|
||||
wget https://github.com/libsdl-org/SDL/releases/download/release-${SDL3_VERSION}/SDL3-${SDL3_VERSION}.tar.gz
|
||||
tar -xzf SDL3-${SDL3_VERSION}.tar.gz
|
||||
mv SDL3-${SDL3_VERSION} SDL3
|
||||
cd SDL3
|
||||
cmake -DCMAKE_INSTALL_PREFIX="`pwd`/prefix" -DSDL_UNIX_CONSOLE_BUILD=ON .
|
||||
make -j2 install
|
||||
sudo apt-get update
|
||||
sudo apt-get install libsdl2-dev
|
||||
- name: Build Stella
|
||||
run: |
|
||||
CXXFLAGS="-I `pwd`/SDL3/prefix/include -O2 -g" PKG_CONFIG_PATH="`pwd`/SDL3/prefix/lib/pkgconfig/" ./configure
|
||||
make -j2 all
|
||||
./configure && make -j2 all
|
||||
|
||||
macos:
|
||||
name: macOS
|
||||
runs-on: macos-latest
|
||||
env:
|
||||
SDL3_VERSION: 3.2.14
|
||||
steps:
|
||||
- uses: maxim-lobanov/setup-xcode@v1
|
||||
with:
|
||||
xcode-version: '16.2'
|
||||
xcode-version: '15.4'
|
||||
- name: Check out the repository
|
||||
uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8
|
||||
- name: Install SDL3
|
||||
- name: Install SDL2
|
||||
run: |
|
||||
wget https://github.com/libsdl-org/SDL/releases/download/release-${SDL3_VERSION}/SDL3-${SDL3_VERSION}.dmg
|
||||
hdiutil attach SDL3-${SDL3_VERSION}.dmg
|
||||
mkdir -p src/os/macos/Frameworks
|
||||
cp -Rv /Volumes/SDL3/SDL3.xcframework src/os/macos/Frameworks
|
||||
hdiutil detach /Volumes/SDL3
|
||||
curl https://www.libsdl.org/release/SDL2-2.26.0.tar.gz | tar xzf -
|
||||
mkdir SDL2-2.26.0/build
|
||||
cd SDL2-2.26.0/build
|
||||
../configure && make -j3 && sudo make install
|
||||
- name: Build Stella
|
||||
run: |
|
||||
cd src/os/macos
|
||||
xcodebuild
|
||||
./configure && make -j3 all
|
||||
|
||||
windows:
|
||||
name: Windows
|
||||
|
@ -60,19 +49,19 @@ jobs:
|
|||
platform: [x64]
|
||||
env:
|
||||
Platform: ${{ matrix.platform }}
|
||||
SDL3_version: 3.2.14
|
||||
SDL2_version: 2.26.0
|
||||
steps:
|
||||
- name: Check out the repository
|
||||
uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8
|
||||
- name: Set up MSBUILD
|
||||
uses: microsoft/setup-msbuild@34cfbaee7f672c76950673338facd8a73f637506
|
||||
- name: Install SDL3
|
||||
- name: Install SDL2
|
||||
shell: cmd
|
||||
run: |
|
||||
curl -o "C:\SDL3-devel.zip" "https://www.libsdl.org/release/SDL3-devel-%SDL3_version%-VC.zip"
|
||||
7z x "C:\SDL3-devel.zip" -o"C:\"
|
||||
xcopy /S "C:\SDL3-%SDL3_version%\include" src\common
|
||||
if %Platform%==x64 xcopy /S "C:\SDL3-%SDL3_version%\lib\x64" src\os\windows
|
||||
curl -o "C:\SDL2-devel.zip" "https://www.libsdl.org/release/SDL2-devel-%SDL2_version%-VC.zip"
|
||||
7z x "C:\SDL2-devel.zip" -o"C:\"
|
||||
xcopy /S "C:\SDL2-%SDL2_version%\include" src\common
|
||||
if %Platform%==x64 xcopy /S "C:\SDL2-%SDL2_version%\lib\x64" src\os\windows
|
||||
|
||||
- name: Build Stella
|
||||
run: |
|
||||
|
|
|
@ -5,7 +5,6 @@ src/**/*.so
|
|||
src/**/*.dylib
|
||||
src/**/*.dll
|
||||
src/**/*.o
|
||||
src/**/*.d
|
||||
src/**/*.obj
|
||||
src/**/*.tlog
|
||||
out
|
||||
|
@ -26,7 +25,6 @@ src/os/macos/M6502.ins
|
|||
.vscode/c_cpp_properties.json
|
||||
.vscode/settings.json
|
||||
src/os/windows/sdl/*
|
||||
src/os/windows/sdl3/*
|
||||
src/os/windows/x64/*
|
||||
src/os/windows/Win32/*
|
||||
src/os/windows/Stella.vcxproj.user
|
||||
|
@ -45,4 +43,3 @@ a.out
|
|||
*.json
|
||||
*.sqlite3
|
||||
*.bak
|
||||
debian/files
|
||||
|
|
|
@ -28,7 +28,7 @@ distributions currently available are:
|
|||
Stella-7.0-x64.exe (64-bit EXE installer)
|
||||
Stella-7.0-windows.zip (64 bit ZIP version)
|
||||
|
||||
* Binary distribution for macOS 10.13 and above :
|
||||
* Binary distribution for macOS 10.12 and above :
|
||||
Stella-7.0-macos.dmg (ARM M1 and 64-bit Intel)
|
||||
|
||||
* Binary distribution for 64-bit Ubuntu :
|
||||
|
|
14
Changes.txt
|
@ -12,20 +12,6 @@
|
|||
Release History
|
||||
===========================================================================
|
||||
|
||||
7.x to 8.0 (xxx x, 202x)
|
||||
|
||||
* Ported Stella to SDL3
|
||||
|
||||
* Added option for switching Stella's theme in sync with OS
|
||||
|
||||
7.0 to 7.1 (xxx x, 202x)
|
||||
|
||||
* Enhanced PAL-60 detection, searches for signature (e.g. PAL60) in ROM
|
||||
|
||||
* Enhanced VSYNC emulation, considers VBLANK now too
|
||||
|
||||
* Added developer option for disabling PlusROM support
|
||||
|
||||
6.7.1 to 7.0 (October 5, 2024)
|
||||
|
||||
* Enhanced ROM launcher to allow multiple images per ROM.
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
License Information and Copyright Notice
|
||||
===========================================================================
|
||||
|
||||
Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony and the
|
||||
Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony and the
|
||||
Stella Team
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
|
|
2
Makefile
|
@ -8,7 +8,7 @@
|
|||
## SS SS tt ee ll ll aa aa
|
||||
## SSSS ttt eeeee llll llll aaaaa
|
||||
##
|
||||
## Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
## Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
## and the Stella Team
|
||||
##
|
||||
## See the file "License.txt" for information on usage and redistribution of
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
# * command line options to...
|
||||
# - override the host settings (for cross compiles
|
||||
# - whether to do a debug build (with -g) or an optimized build (-O3 etc.)
|
||||
# * detect whether the chosen backend is available
|
||||
# * detect whether the chosen backend is available (e.g. call sdl2-config)
|
||||
# * ....
|
||||
|
||||
|
||||
|
@ -45,7 +45,6 @@ _ranlib=ranlib
|
|||
_install=install
|
||||
_ar="ar cru"
|
||||
_strip=strip
|
||||
_pkg_config=pkg-config
|
||||
_mkdir="mkdir -p"
|
||||
_echo=printf
|
||||
_cat=cat
|
||||
|
@ -54,6 +53,7 @@ _rm_rec="$_rm -r"
|
|||
_zip="zip -q"
|
||||
_cp=cp
|
||||
_windowspath=""
|
||||
_sdlconfig=sdl2-config
|
||||
_sdlpath="$PATH"
|
||||
_prefix=/usr/local
|
||||
|
||||
|
@ -335,22 +335,20 @@ case $_host in
|
|||
# _host_os=amigaos
|
||||
# _host_cpu=ppc
|
||||
# ;;
|
||||
retron77)
|
||||
_host_os=retron77
|
||||
;;
|
||||
mingw32-cross)
|
||||
_host_os=mingw32msvc
|
||||
_host_cpu=i386
|
||||
_host_prefix=i386-mingw32msvc
|
||||
;;
|
||||
"")
|
||||
*)
|
||||
guessed_host=`$_srcdir/config.guess`
|
||||
_host_cpu=`echo $guessed_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
|
||||
_host_os=`echo $guessed_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
|
||||
_host_vendor=`echo $guessed_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
|
||||
;;
|
||||
*)
|
||||
_host_cpu=`echo "$_host" | sed 's/^\([^-]*\)-.*/\1/'`
|
||||
_host_os=`echo "$_host" | sed 's/-\([^-]*\)-[^-]*$/\1/'`
|
||||
_host_prefix="$_host"
|
||||
;;
|
||||
esac
|
||||
|
||||
#
|
||||
|
@ -555,6 +553,14 @@ fi
|
|||
if test -n "$_host"; then
|
||||
# Cross-compiling mode - add your target here if needed
|
||||
case "$_host" in
|
||||
retron77)
|
||||
echo "Compiling for $_host, disabling windowed mode, debugger and cheats."
|
||||
_build_gui=yes
|
||||
_build_windowed=no
|
||||
_build_debugger=no
|
||||
_build_cheats=no
|
||||
_build_httplib=no
|
||||
;;
|
||||
mingw32-cross)
|
||||
echo "Cross-compiling for Windows using MinGW."
|
||||
DEFINES="$DEFINES -DWIN32"
|
||||
|
@ -620,9 +626,6 @@ fi
|
|||
# Cross-compilers use their own commands for the following functions
|
||||
if test -n "$_host_prefix"; then
|
||||
_strip="$_host_prefix-$_strip"
|
||||
if command -v "$_host_prefix-$_pkg_config" >/dev/null 2>&1; then
|
||||
_pkg_config="$_host_prefix-$_pkg_config"
|
||||
fi
|
||||
fi
|
||||
|
||||
#
|
||||
|
@ -636,7 +639,7 @@ if test "$_build_zip" = yes ; then
|
|||
#include <zlib.h>
|
||||
int main(void) { return strcmp(ZLIB_VERSION, zlibVersion()); }
|
||||
EOF
|
||||
cc_check $LDFLAGS $CXXFLAGS $ZLIB_CFLAGS $ZLIB_LIBS `$_pkg_config --libs zlib` && _zlib=yes
|
||||
cc_check $LDFLAGS $CXXFLAGS $ZLIB_CFLAGS $ZLIB_LIBS `pkg-config --libs zlib` && _zlib=yes
|
||||
|
||||
if test "$_zlib" = yes ; then
|
||||
echo "$_zlib"
|
||||
|
@ -662,7 +665,7 @@ if test "$_build_png" = yes ; then
|
|||
#include <png.h>
|
||||
int main(void) { return printf("%s\n", PNG_HEADER_VERSION_STRING); }
|
||||
EOF
|
||||
cc_check $LDFLAGS $CXXFLAGS $LIBPNG_CFLAGS $LIBPNG_LIBS `$_pkg_config --libs libpng` && _libpng=yes
|
||||
cc_check $LDFLAGS $CXXFLAGS $LIBPNG_CFLAGS $LIBPNG_LIBS `pkg-config --libs libpng` && _libpng=yes
|
||||
|
||||
if test "$_libpng" = yes ; then
|
||||
echo "$_libpng"
|
||||
|
@ -686,7 +689,7 @@ if test "$_build_sqlite3" = yes ; then
|
|||
#include <sqlite3.h>
|
||||
int main(void) { return printf("%s\n", SQLITE_VERSION); }
|
||||
EOF
|
||||
cc_check $LDFLAGS $CXXFLAGS `$_pkg_config --libs sqlite3` && _libsqlite3=yes
|
||||
cc_check $LDFLAGS $CXXFLAGS `pkg-config --libs sqlite3` && _libsqlite3=yes
|
||||
|
||||
if test "$_libsqlite3" = yes ; then
|
||||
echo "$_libsqlite3"
|
||||
|
@ -805,8 +808,8 @@ fi
|
|||
#
|
||||
# Now, add the appropriate defines/libraries/headers
|
||||
#
|
||||
#echo
|
||||
#find_sdlconfig
|
||||
echo
|
||||
find_sdlconfig
|
||||
|
||||
SRC="src"
|
||||
SRC_OS="$SRC/os"
|
||||
|
@ -833,18 +836,15 @@ HTTP_LIB="$SRC_LIB/httplib"
|
|||
|
||||
INCLUDES="-I$CORE -I$COMMON -I$TV -I$TIA -I$TIA_FRAME_MANAGER -I$ELF -I$JSON -I$SQLITE_REPO"
|
||||
|
||||
#INCLUDES="$INCLUDES `$_sdlconfig --cflags`"
|
||||
#if test "$_build_static" = yes ; then
|
||||
# _sdl_conf_libs="--static-libs"
|
||||
# LDFLAGS="-static $LDFLAGS"
|
||||
#else
|
||||
# _sdl_conf_libs="--libs"
|
||||
#fi
|
||||
|
||||
#if test "$_libpng" = yes ; then #FIXME:
|
||||
LIBS="$LIBS `$_pkg_config --libs sdl3`"
|
||||
#fi
|
||||
INCLUDES="$INCLUDES `$_sdlconfig --cflags`"
|
||||
if test "$_build_static" = yes ; then
|
||||
_sdl_conf_libs="--static-libs"
|
||||
LDFLAGS="-static $LDFLAGS"
|
||||
else
|
||||
_sdl_conf_libs="--libs"
|
||||
fi
|
||||
|
||||
LIBS="$LIBS `$_sdlconfig $_sdl_conf_libs`"
|
||||
LD=$CXX
|
||||
|
||||
case $_host_os in
|
||||
|
@ -865,6 +865,11 @@ case $_host_os in
|
|||
fi
|
||||
_libsqlite3=no
|
||||
;;
|
||||
retron77)
|
||||
DEFINES="$DEFINES -DBSPF_UNIX -DRETRON77"
|
||||
MODULES="$MODULES $SRC_OS/unix $SRC_OS/unix/r77"
|
||||
INCLUDES="$INCLUDES -I$SRC_OS/unix -I$SRC_OS/unix/r77"
|
||||
;;
|
||||
win32)
|
||||
DEFINES="$DEFINES -DBSPF_WINDOWS"
|
||||
MODULES="$MODULES $SRC_OS/windows"
|
||||
|
@ -917,7 +922,7 @@ if test "$_build_png" = yes ; then
|
|||
INCLUDES="$INCLUDES -I$LIBJPG -I$LIBJPGEXIF"
|
||||
MODULES="$MODULES $LIBJPGEXIF"
|
||||
if test "$_libpng" = yes ; then
|
||||
LIBS="$LIBS `$_pkg_config --libs libpng`"
|
||||
LIBS="$LIBS `pkg-config --libs libpng`"
|
||||
else
|
||||
MODULES="$MODULES $LIBPNG"
|
||||
INCLUDES="$INCLUDES -I$LIBPNG"
|
||||
|
@ -925,7 +930,7 @@ if test "$_build_png" = yes ; then
|
|||
fi
|
||||
|
||||
if test "$_libsqlite3" = yes ; then
|
||||
LIBS="$LIBS `$_pkg_config --libs sqlite3`"
|
||||
LIBS="$LIBS `pkg-config --libs sqlite3`"
|
||||
else
|
||||
MODULES="$MODULES $SQLITE_LIB"
|
||||
INCLUDES="$INCLUDES -I$SQLITE_LIB"
|
||||
|
@ -934,7 +939,7 @@ fi
|
|||
if test "$_build_zip" = yes ; then
|
||||
DEFINES="$DEFINES -DZIP_SUPPORT"
|
||||
if test "$_zlib" = yes ; then
|
||||
LIBS="$LIBS `$_pkg_config --libs zlib`"
|
||||
LIBS="$LIBS `pkg-config --libs zlib`"
|
||||
else
|
||||
MODULES="$MODULES $ZLIB"
|
||||
INCLUDES="$INCLUDES -I$ZLIB"
|
||||
|
|
|
@ -3,9 +3,8 @@ Maintainer: Stephen Anthony <sa666666@gmail.com>
|
|||
Section: otherosfs
|
||||
Priority: optional
|
||||
Build-Depends: debhelper (>= 10~),
|
||||
libgtest-dev,
|
||||
libpng-dev,
|
||||
libsdl3-dev,
|
||||
libsdl2-dev,
|
||||
zlib1g-dev
|
||||
Standards-Version: 4.5.0
|
||||
Vcs-Browser: https://github.com/stella-emu/stella/
|
||||
|
@ -19,7 +18,7 @@ Depends: ${misc:Depends},
|
|||
${shlibs:Depends}
|
||||
Recommends: joystick (>= 1:1.5.1)
|
||||
Pre-Depends: ${misc:Pre-Depends}
|
||||
Description: Atari 2600 Emulator for SDL
|
||||
Description: Atari 2600 Emulator for SDL2
|
||||
Stella is a portable emulator of the old Atari 2600 video-game
|
||||
console. You can play most Atari 2600 games with it.
|
||||
.
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0
|
||||
Upstream-Name: stella
|
||||
Source: https://stella-emu.github.io
|
||||
Copyright: 1995-2025 Bradford W. Mott, Stephen Anthony and the Stella Team
|
||||
Copyright: 1995-2024 Bradford W. Mott, Stephen Anthony and the Stella Team
|
||||
License: GPL-2+
|
||||
|
||||
Files: *
|
||||
Copyright: 1995-2025 Bradford W. Mott, Stephen Anthony and the Stella
|
||||
Copyright: 1995-2024 Bradford W. Mott, Stephen Anthony and the Stella
|
||||
Team
|
||||
License: GPL-2+
|
||||
|
||||
Files: debian/*
|
||||
Copyright: 1998-2004 Tom Lear <tom@trap.mtview.ca.us>
|
||||
2006 Mario Iseli <admin@marioiseli.com>
|
||||
2010-2025 Stephen Kitt <skitt@debian.org>
|
||||
2010-2024 Stephen Kitt <skitt@debian.org>
|
||||
License: GPL-2+
|
||||
|
||||
Files:
|
||||
|
|
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 5.2 KiB |
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 6.2 KiB |
Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 6.1 KiB |
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 4.7 KiB |
|
@ -21,7 +21,7 @@
|
|||
<img src="graphics/stella_icon.png">
|
||||
<h2><b>A multi-platform Atari 2600 VCS emulator</b></h2>
|
||||
|
||||
<h4><b>Release 8.0</b></h4>
|
||||
<h4><b>Release 7.0</b></h4>
|
||||
<br>
|
||||
|
||||
<h2><b>User's Guide</b></h2>
|
||||
|
@ -342,7 +342,7 @@
|
|||
<p>
|
||||
<h3><b><u>General</u> (required for all versions of Stella)</b></h3>
|
||||
<ul>
|
||||
<li>SDL version 3.2.14 or greater, latest version highly recommended</li>
|
||||
<li>SDL version 2.0.14 or greater, latest version highly recommended</li>
|
||||
<li>32 bit color graphics card</li>
|
||||
<li>Enough RAM for the OS + 256MB RAM for the emulation; 512MB+ highly recommended</li>
|
||||
<li>Joysticks or gamepads are highly recommended</li>
|
||||
|
@ -368,9 +368,9 @@
|
|||
<p>The Mac version of Stella is designed to work on an Apple Macintosh with
|
||||
the following:</p>
|
||||
<ul>
|
||||
<li>macOS 10.13 or above</li>
|
||||
<li>macOS 10.11 or above</li>
|
||||
<li>64-bit ARM or Intel processor</li>
|
||||
<li>Xcode 16.0 is required to compile the Stella source code</li>
|
||||
<li>Xcode 13.0 is required to compile the Stella source code</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
|
@ -387,7 +387,7 @@
|
|||
<h3><b><u>Other</u></b></h3>
|
||||
|
||||
<p>Stella is extremely portable, and in its lifetime has been ported to almost every
|
||||
platform where the SDL library exists. It is 64-bit and endian clean in Linux/Unix, macOS
|
||||
platform where the SDL library exists. It is 32/64-bit and endian clean in Linux/Unix, macOS
|
||||
and Windows. The Stella Team is interested in hearing about any problems you may
|
||||
encounter with diverse operating systems and CPU types.</p>
|
||||
</blockquote></br>
|
||||
|
@ -2526,7 +2526,7 @@
|
|||
|
||||
<br>
|
||||
<p><h2>
|
||||
<a name="HighScores">High Scores Saving</a></h2>
|
||||
<a name="Highscores">High Scores Saving</a></h2>
|
||||
<blockquote>
|
||||
|
||||
<p>Stella allows the user to save high scores when the required definitions
|
||||
|
@ -3249,17 +3249,12 @@
|
|||
|
||||
<tr>
|
||||
<td><pre>-uipalette2 <standard|classic|light|dark></pre></td>
|
||||
<td>Define alternative/light palette/theme for UI elements.</td>
|
||||
<td>Define alternative palette/theme for UI elements.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><pre>-altpalette <1|0></pre></td>
|
||||
<td>Use alternative/dark palette/theme for UI elements.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td><pre>-autouipalette <1|0></pre></td>
|
||||
<td>Automatic switching between light and dark theme in sync with OS.</td>
|
||||
<td>Use alternative palette/theme for UI elements.</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
|
@ -3640,9 +3635,6 @@
|
|||
</tr><tr>
|
||||
<td><pre>-<plr.|dev.>console <2600|7800></pre></td>
|
||||
<td>Select console for B/W and Pause key handling and RAM initialization.</td>
|
||||
</tr><tr>
|
||||
<td><pre>-dev.plusroms.on <1|0></pre></td>
|
||||
<td>Enable/disable PlusROM support, e.g. for testing.</td>
|
||||
</tr><tr>
|
||||
<td><pre>-<plr.|dev.>bankrandom <1|0></pre></td>
|
||||
<td>On reset, randomize the startup bank (only for selected bankswitch types).</td>
|
||||
|
@ -4015,9 +4007,8 @@
|
|||
<td valign="top">
|
||||
<table border="1" cellpadding="4">
|
||||
<tr><th>Item</th><th>Brief description</th><th>For more information,<br>see <a href="#CommandLine">Command Line</a></th></tr>
|
||||
<tr><td>Light theme</td><td>Default theme to use for UI elements (see examples)</td><td>-uipalette</td></tr>
|
||||
<tr><td>Dark theme</td><td>Alternative theme to use for UI elements (see examples)</td><td>-uipalette2</td></tr>
|
||||
<tr><td>Auto theme</td><td>Enable for automatic switching between light and dark themes in sync with OS.</td><td>-autouipalette</td></tr>
|
||||
<tr><td>Theme #1</td><td>Default theme to use for UI elements (see examples)</td><td>-uipalette</td></tr>
|
||||
<tr><td>Theme #2</td><td>Alternative theme to use for UI elements (see examples)</td><td>-uipalette2</td></tr>
|
||||
<tr><td>Dialogs font</td><td>The font used in the dialogs</td><td>-dialogfont</td></tr>
|
||||
<tr><td>HiDPI mode</td><td>Scale the UI by a factor of two when enabled</td><td>-hidpi</td></tr>
|
||||
<tr><td>Dialogs position</td><td>Position of dialogs with Stella window</td><td>-dialogpos</td></tr>
|
||||
|
@ -4585,11 +4576,6 @@
|
|||
emulation and zero-page RAM initialization</td>
|
||||
<td>-plr.console <br/>-dev.console</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>PlusROM support</td>
|
||||
<td>Enable/disable PlusROM support, e.g. for testing.</td>
|
||||
<td>-dev.plusroms.on</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Random startup bank</td>
|
||||
<td>Randomize the startup bank (only for selected bankswitch types)</td>
|
||||
|
@ -5155,9 +5141,7 @@ Ms Pac-Man (Stella extended codes):
|
|||
<tr><td>NTSC50 ¹</td><td>NTSC50, NTSC 50, NTSC-50, PAL-N</td></tr>
|
||||
<tr><td>PAL60 ¹</td><td>PAL60, PAL 60, PAL-60</td></tr>
|
||||
<tr><td>SECAM60 ¹</td><td>SECAM60, SECAM 60, SECAM-60</td></tr>
|
||||
</table>
|
||||
Additionally, to detect PAL-60 format games, the ROM is scanned for the following
|
||||
signature strings: "PAL60", "PAL 60" and "PAL-60"</td>
|
||||
</table></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
|
|
|
@ -264,7 +264,7 @@
|
|||
<td width="41%">This dialog is similar to the PC version's
|
||||
<a href="index.html#CommandMenu"><b>Command Menu</b></a>, but with some
|
||||
commands especially selected for the RetroN 77.</td>
|
||||
<td><p><img src="graphics/commandsmenu_r77.png"></p></td>
|
||||
<td><p><img src="commandsmenu_r77.png"></p></td>
|
||||
</tr>
|
||||
</table>
|
||||
</p>
|
||||
|
@ -309,7 +309,7 @@
|
|||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
<td><p><img src="graphics/basic_settings.png"></p></td>
|
||||
<td><p><img src="basic_settings.png"></p></td>
|
||||
</tr>
|
||||
</table>
|
||||
</p>
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
@ -33,7 +33,7 @@ BankRomCheat::BankRomCheat(OSystem& os, string_view name, string_view code)
|
|||
count = static_cast<uInt8>(BSPF::stoi<16>(myCode.substr(7, 1)) + 1);
|
||||
|
||||
// Back up original data; we need this if the cheat is ever disabled
|
||||
for(int i = 0; std::cmp_less(i, count); ++i)
|
||||
for(int i = 0; i < count; ++i)
|
||||
savedRom[i] = myOSystem.console().cartridge().peek(address + i);
|
||||
}
|
||||
|
||||
|
@ -50,7 +50,7 @@ bool BankRomCheat::disable()
|
|||
const int oldBank = myOSystem.console().cartridge().getBank(address);
|
||||
myOSystem.console().cartridge().bank(bank);
|
||||
|
||||
for(int i = 0; std::cmp_less(i, count); ++i)
|
||||
for(int i = 0; i < count; ++i)
|
||||
myOSystem.console().cartridge().patch(address + i, savedRom[i]);
|
||||
|
||||
myOSystem.console().cartridge().bank(oldBank);
|
||||
|
@ -66,7 +66,7 @@ void BankRomCheat::evaluate()
|
|||
const int oldBank = myOSystem.console().cartridge().getBank(address);
|
||||
myOSystem.console().cartridge().bank(bank);
|
||||
|
||||
for(int i = 0; std::cmp_less(i, count); ++i)
|
||||
for(int i = 0; i < count; ++i)
|
||||
myOSystem.console().cartridge().patch(address + i, value);
|
||||
|
||||
myOSystem.console().cartridge().bank(oldBank);
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
@ -28,7 +28,7 @@ CheetahCheat::CheetahCheat(OSystem& os, string_view name, string_view code)
|
|||
count{static_cast<uInt8>(BSPF::stoi<16>(code.substr(5, 1)) + 1)}
|
||||
{
|
||||
// Back up original data; we need this if the cheat is ever disabled
|
||||
for(uInt8 i = 0; i < count; ++i)
|
||||
for(int i = 0; i < count; ++i)
|
||||
savedRom[i] = myOSystem.console().cartridge().peek(address + i);
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,7 @@ bool CheetahCheat::enable()
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CheetahCheat::disable()
|
||||
{
|
||||
for(uInt8 i = 0; i < count; ++i)
|
||||
for(int i = 0; i < count; ++i)
|
||||
myOSystem.console().cartridge().patch(address + i, savedRom[i]);
|
||||
|
||||
return myEnabled = false;
|
||||
|
@ -53,7 +53,7 @@ void CheetahCheat::evaluate()
|
|||
{
|
||||
if(!myEnabled)
|
||||
{
|
||||
for(uInt8 i = 0; i < count; ++i)
|
||||
for(int i = 0; i < count; ++i)
|
||||
myOSystem.console().cartridge().patch(address + i, value);
|
||||
|
||||
myEnabled = true;
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
@ -67,6 +67,20 @@ void AudioSettings::normalize(Settings& settings)
|
|||
break;
|
||||
}
|
||||
|
||||
switch (settings.getInt(SETTING_FRAGMENT_SIZE)) {
|
||||
case 128:
|
||||
case 256:
|
||||
case 512:
|
||||
case 1024:
|
||||
case 2048:
|
||||
case 4096:
|
||||
break;
|
||||
|
||||
default:
|
||||
settings.setValue(SETTING_FRAGMENT_SIZE, DEFAULT_FRAGMENT_SIZE);
|
||||
break;
|
||||
}
|
||||
|
||||
const int settingBufferSize = settings.getInt(SETTING_BUFFER_SIZE);
|
||||
if (settingBufferSize < 0 || settingBufferSize > MAX_BUFFER_SIZE) settings.setValue(SETTING_BUFFER_SIZE, DEFAULT_BUFFER_SIZE);
|
||||
|
||||
|
@ -101,7 +115,7 @@ uInt32 AudioSettings::sampleRate()
|
|||
uInt32 AudioSettings::fragmentSize()
|
||||
{
|
||||
updatePresetFromSettings();
|
||||
return myPresetFragmentSize; // No longer configurable in sound backend
|
||||
return customSettings() ? lboundInt(mySettings.getInt(SETTING_FRAGMENT_SIZE), DEFAULT_FRAGMENT_SIZE) : myPresetFragmentSize;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -141,6 +155,12 @@ uInt32 AudioSettings::volume() const
|
|||
return lboundInt(mySettings.getInt(SETTING_VOLUME), 0);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt32 AudioSettings::device() const
|
||||
{
|
||||
return mySettings.getInt(SETTING_DEVICE);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool AudioSettings::enabled() const
|
||||
{
|
||||
|
@ -165,6 +185,7 @@ void AudioSettings::setPreset(AudioSettings::Preset preset)
|
|||
|
||||
case Preset::lowQualityMediumLag:
|
||||
myPresetSampleRate = 44100;
|
||||
myPresetFragmentSize = 1024;
|
||||
myPresetBufferSize = 6;
|
||||
myPresetHeadroom = 5;
|
||||
myPresetResamplingQuality = ResamplingQuality::nearestNeighbour;
|
||||
|
@ -172,6 +193,7 @@ void AudioSettings::setPreset(AudioSettings::Preset preset)
|
|||
|
||||
case Preset::highQualityMediumLag:
|
||||
myPresetSampleRate = 44100;
|
||||
myPresetFragmentSize = 1024;
|
||||
myPresetBufferSize = 6;
|
||||
myPresetHeadroom = 5;
|
||||
myPresetResamplingQuality = ResamplingQuality::lanczos_2;
|
||||
|
@ -179,6 +201,7 @@ void AudioSettings::setPreset(AudioSettings::Preset preset)
|
|||
|
||||
case Preset::highQualityLowLag:
|
||||
myPresetSampleRate = 48000;
|
||||
myPresetFragmentSize = 512;
|
||||
myPresetBufferSize = 3;
|
||||
myPresetHeadroom = 2;
|
||||
myPresetResamplingQuality = ResamplingQuality::lanczos_2;
|
||||
|
@ -186,6 +209,7 @@ void AudioSettings::setPreset(AudioSettings::Preset preset)
|
|||
|
||||
case Preset::ultraQualityMinimalLag:
|
||||
myPresetSampleRate = 96000;
|
||||
myPresetFragmentSize = 128;
|
||||
myPresetBufferSize = 0;
|
||||
myPresetHeadroom = 0;
|
||||
myPresetResamplingQuality = ResamplingQuality::lanczos_3;
|
||||
|
@ -207,6 +231,15 @@ void AudioSettings::setSampleRate(uInt32 sampleRate)
|
|||
normalize(mySettings);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void AudioSettings::setFragmentSize(uInt32 fragmentSize)
|
||||
{
|
||||
if (!myIsPersistent) return;
|
||||
|
||||
mySettings.setValue(SETTING_FRAGMENT_SIZE, fragmentSize);
|
||||
normalize(mySettings);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void AudioSettings::setBufferSize(uInt32 bufferSize)
|
||||
{
|
||||
|
@ -259,6 +292,14 @@ void AudioSettings::setVolume(uInt32 volume)
|
|||
normalize(mySettings);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void AudioSettings::setDevice(uInt32 device)
|
||||
{
|
||||
if(!myIsPersistent) return;
|
||||
|
||||
mySettings.setValue(SETTING_DEVICE, device);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void AudioSettings::setEnabled(bool isEnabled)
|
||||
{
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
@ -42,11 +42,13 @@ class AudioSettings
|
|||
|
||||
static constexpr string_view SETTING_PRESET = "audio.preset";
|
||||
static constexpr string_view SETTING_SAMPLE_RATE = "audio.sample_rate";
|
||||
static constexpr string_view SETTING_FRAGMENT_SIZE = "audio.fragment_size";
|
||||
static constexpr string_view SETTING_BUFFER_SIZE = "audio.buffer_size";
|
||||
static constexpr string_view SETTING_HEADROOM = "audio.headroom";
|
||||
static constexpr string_view SETTING_RESAMPLING_QUALITY = "audio.resampling_quality";
|
||||
static constexpr string_view SETTING_STEREO = "audio.stereo";
|
||||
static constexpr string_view SETTING_VOLUME = "audio.volume";
|
||||
static constexpr string_view SETTING_DEVICE = "audio.device";
|
||||
static constexpr string_view SETTING_ENABLED = "audio.enabled";
|
||||
static constexpr string_view SETTING_DPC_PITCH = "audio.dpc_pitch";
|
||||
|
||||
|
@ -130,8 +132,7 @@ class AudioSettings
|
|||
Preset myPreset{Preset::custom};
|
||||
|
||||
uInt32 myPresetSampleRate{0};
|
||||
uInt32 myPresetFragmentSize{1024}; // no longer configurable in sound backend
|
||||
|
||||
uInt32 myPresetFragmentSize{0};
|
||||
uInt32 myPresetBufferSize{0};
|
||||
uInt32 myPresetHeadroom{0};
|
||||
ResamplingQuality myPresetResamplingQuality{ResamplingQuality::nearestNeighbour};
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
@ -234,8 +234,9 @@ void Bezel::apply()
|
|||
// Note: Variable bezel window positions are handled in VideoModeHandler::Mode
|
||||
|
||||
// Enable blending to allow overlaying the bezel over the TIA output
|
||||
mySurface->enableBlend(true);
|
||||
mySurface->setBlendLevel(100);
|
||||
mySurface->attributes().blending = true;
|
||||
mySurface->attributes().blendalpha = 100;
|
||||
mySurface->applyAttributes();
|
||||
mySurface->setVisible(true);
|
||||
}
|
||||
else
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
@ -46,7 +46,6 @@ void DevSettingsHandler::loadSettings(SettingsSet set)
|
|||
// AtariVox/SaveKey/PlusROM access
|
||||
myExternAccess[set] = settings.getBool(prefix + "extaccess");
|
||||
myConsole[set] = settings.getString(prefix + "console") == "7800" ? 1 : 0;
|
||||
myPlusROM[set] = devSettings ? settings.getBool("dev.plusroms.on") : true;
|
||||
// Randomization
|
||||
myRandomBank[set] = settings.getBool(prefix + "bankrandom");
|
||||
myRandomizeTIA[set] = settings.getBool(prefix + "tiarandom");
|
||||
|
@ -119,7 +118,6 @@ void DevSettingsHandler::saveSettings(SettingsSet set)
|
|||
|
||||
if(devSettings)
|
||||
{
|
||||
settings.setValue("dev.plusroms.on", myPlusROM[set]);
|
||||
settings.setValue("dev.hsrandom", myRandomHotspots[set]);
|
||||
// Undriven TIA pins
|
||||
settings.setValue("dev.tiadriven", myUndrivenPins[set]);
|
||||
|
@ -185,7 +183,6 @@ void DevSettingsHandler::applySettings(SettingsSet set)
|
|||
{
|
||||
myOSystem.console().cartridge().enableRandomHotspots(myRandomHotspots[set]);
|
||||
myOSystem.console().tia().driveUnusedPinsRandom(myUndrivenPins[set]);
|
||||
myOSystem.console().cartridge().enablePlusROM(myPlusROM[set]);
|
||||
// Notes:
|
||||
// - thumb exceptions not updated, because set in cart constructor
|
||||
// - other missing settings are used on-the-fly
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
@ -51,7 +51,6 @@ class DevSettingsHandler
|
|||
std::array<bool, numSets> myDetectedInfo{};
|
||||
std::array<bool, numSets> myExternAccess{};
|
||||
std::array<int, numSets> myConsole{};
|
||||
std::array<int, numSets> myPlusROM{};
|
||||
std::array<bool, numSets> myRandomBank{};
|
||||
std::array<bool, numSets> myRandomizeTIA{};
|
||||
std::array<bool, numSets> myRandomizeRAM{};
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
@ -17,12 +17,12 @@
|
|||
|
||||
#include "Logger.hxx"
|
||||
#include "OSystem.hxx"
|
||||
#include "EventHandlerSDL.hxx"
|
||||
#include "EventHandlerSDL2.hxx"
|
||||
|
||||
#include "ThreadDebugging.hxx"
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
EventHandlerSDL::EventHandlerSDL(OSystem& osystem)
|
||||
EventHandlerSDL2::EventHandlerSDL2(OSystem& osystem)
|
||||
: EventHandler{osystem}
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
@ -31,30 +31,28 @@ EventHandlerSDL::EventHandlerSDL(OSystem& osystem)
|
|||
{
|
||||
ostringstream buf;
|
||||
myQwertz = int{'y'} == static_cast<int>
|
||||
(SDL_GetKeyFromScancode(static_cast<SDL_Scancode>(KBDK_Z), static_cast<SDL_Keymod>(StellaMod::KBDM_NONE), false));
|
||||
(SDL_GetKeyFromScancode(static_cast<SDL_Scancode>(KBDK_Z)));
|
||||
buf << "Keyboard: " << (myQwertz ? "QWERTZ" : "QWERTY");
|
||||
Logger::debug(buf.view());
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef JOYSTICK_SUPPORT
|
||||
if(!SDL_InitSubSystem(SDL_INIT_JOYSTICK))
|
||||
if(SDL_InitSubSystem(SDL_INIT_JOYSTICK) < 0)
|
||||
{
|
||||
ostringstream buf;
|
||||
buf << "ERROR: Couldn't initialize SDL joystick support: "
|
||||
<< SDL_GetError() << '\n';
|
||||
Logger::error(buf.view());
|
||||
}
|
||||
Logger::debug("EventHandlerSDL::EventHandlerSDL SDL_INIT_JOYSTICK");
|
||||
Logger::debug("EventHandlerSDL2::EventHandlerSDL2 SDL_INIT_JOYSTICK");
|
||||
#endif
|
||||
|
||||
SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1");
|
||||
//SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_SYSTEM_SCALE, "1");
|
||||
//SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_MODE_CENTER, "0");
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
EventHandlerSDL::~EventHandlerSDL()
|
||||
EventHandlerSDL2::~EventHandlerSDL2()
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
|
@ -63,13 +61,24 @@ EventHandlerSDL::~EventHandlerSDL()
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void EventHandlerSDL::copyText(const string& text) const
|
||||
void EventHandlerSDL2::enableTextEvents(bool enable)
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
if(enable)
|
||||
SDL_StartTextInput();
|
||||
else
|
||||
SDL_StopTextInput();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void EventHandlerSDL2::copyText(const string& text) const
|
||||
{
|
||||
SDL_SetClipboardText(text.c_str());
|
||||
};
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
string EventHandlerSDL::pasteText(string& text) const
|
||||
string EventHandlerSDL2::pasteText(string& text) const
|
||||
{
|
||||
if(SDL_HasClipboardText())
|
||||
text = SDL_GetClipboardText();
|
||||
|
@ -80,7 +89,7 @@ string EventHandlerSDL::pasteText(string& text) const
|
|||
};
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void EventHandlerSDL::pollEvent()
|
||||
void EventHandlerSDL2::pollEvent()
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
|
@ -89,31 +98,31 @@ void EventHandlerSDL::pollEvent()
|
|||
switch(myEvent.type)
|
||||
{
|
||||
// keyboard events
|
||||
case SDL_EVENT_KEY_UP:
|
||||
case SDL_EVENT_KEY_DOWN:
|
||||
case SDL_KEYUP:
|
||||
case SDL_KEYDOWN:
|
||||
{
|
||||
handleKeyEvent(static_cast<StellaKey>(myEvent.key.scancode),
|
||||
static_cast<StellaMod>(myEvent.key.mod),
|
||||
myEvent.type == SDL_EVENT_KEY_DOWN,
|
||||
handleKeyEvent(static_cast<StellaKey>(myEvent.key.keysym.scancode),
|
||||
static_cast<StellaMod>(myEvent.key.keysym.mod),
|
||||
myEvent.key.type == SDL_KEYDOWN,
|
||||
myEvent.key.repeat);
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_EVENT_TEXT_INPUT:
|
||||
case SDL_TEXTINPUT:
|
||||
{
|
||||
handleTextEvent(*(myEvent.text.text));
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_EVENT_MOUSE_MOTION:
|
||||
case SDL_MOUSEMOTION:
|
||||
{
|
||||
handleMouseMotionEvent(myEvent.motion.x, myEvent.motion.y,
|
||||
myEvent.motion.xrel, myEvent.motion.yrel);
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_EVENT_MOUSE_BUTTON_DOWN:
|
||||
case SDL_EVENT_MOUSE_BUTTON_UP:
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
case SDL_MOUSEBUTTONUP:
|
||||
{
|
||||
// ToDo: check support of more buttons and double-click
|
||||
MouseButton b{MouseButton::NONE};
|
||||
|
@ -131,43 +140,39 @@ void EventHandlerSDL::pollEvent()
|
|||
default:
|
||||
break;
|
||||
}
|
||||
handleMouseButtonEvent(b, myEvent.button.type == SDL_EVENT_MOUSE_BUTTON_DOWN,
|
||||
handleMouseButtonEvent(b, myEvent.button.type == SDL_MOUSEBUTTONDOWN,
|
||||
myEvent.button.x, myEvent.button.y);
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_EVENT_MOUSE_WHEEL:
|
||||
case SDL_MOUSEWHEEL:
|
||||
{
|
||||
// TODO: SDL now uses float for mouse coords, but the core still
|
||||
// uses int throughout; maybe this is sufficient?
|
||||
float x{0.F}, y{0.F};
|
||||
int x{0}, y{0};
|
||||
SDL_GetMouseState(&x, &y); // we need mouse position too
|
||||
if(myEvent.wheel.y < 0)
|
||||
handleMouseButtonEvent(MouseButton::WHEELDOWN, true,
|
||||
static_cast<int>(x), static_cast<int>(y));
|
||||
handleMouseButtonEvent(MouseButton::WHEELDOWN, true, x, y);
|
||||
else if(myEvent.wheel.y > 0)
|
||||
handleMouseButtonEvent(MouseButton::WHEELUP, true,
|
||||
static_cast<int>(x), static_cast<int>(y));
|
||||
handleMouseButtonEvent(MouseButton::WHEELUP, true, x, y);
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef JOYSTICK_SUPPORT
|
||||
case SDL_EVENT_JOYSTICK_BUTTON_UP:
|
||||
case SDL_EVENT_JOYSTICK_BUTTON_DOWN:
|
||||
case SDL_JOYBUTTONUP:
|
||||
case SDL_JOYBUTTONDOWN:
|
||||
{
|
||||
handleJoyBtnEvent(myEvent.jbutton.which, myEvent.jbutton.button,
|
||||
myEvent.jbutton.down);
|
||||
myEvent.jbutton.state == SDL_PRESSED);
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_EVENT_JOYSTICK_AXIS_MOTION:
|
||||
case SDL_JOYAXISMOTION:
|
||||
{
|
||||
handleJoyAxisEvent(myEvent.jaxis.which, myEvent.jaxis.axis,
|
||||
myEvent.jaxis.value);
|
||||
break;
|
||||
}
|
||||
|
||||
case SDL_EVENT_JOYSTICK_HAT_MOTION:
|
||||
case SDL_JOYHATMOTION:
|
||||
{
|
||||
int value = 0;
|
||||
const int v = myEvent.jhat.value;
|
||||
|
@ -182,82 +187,86 @@ void EventHandlerSDL::pollEvent()
|
|||
}
|
||||
|
||||
handleJoyHatEvent(myEvent.jhat.which, myEvent.jhat.hat, value);
|
||||
break;
|
||||
break; // SDL_JOYHATMOTION
|
||||
}
|
||||
|
||||
case SDL_EVENT_JOYSTICK_ADDED:
|
||||
case SDL_JOYDEVICEADDED:
|
||||
{
|
||||
addPhysicalJoystick(make_shared<JoystickSDL>(myEvent.jdevice.which));
|
||||
break;
|
||||
addPhysicalJoystick(make_shared<JoystickSDL2>(myEvent.jdevice.which));
|
||||
break; // SDL_JOYDEVICEADDED
|
||||
}
|
||||
case SDL_EVENT_JOYSTICK_REMOVED:
|
||||
case SDL_JOYDEVICEREMOVED:
|
||||
{
|
||||
removePhysicalJoystick(myEvent.jdevice.which);
|
||||
break;
|
||||
break; // SDL_JOYDEVICEREMOVED
|
||||
}
|
||||
#endif
|
||||
|
||||
case SDL_EVENT_QUIT:
|
||||
case SDL_QUIT:
|
||||
{
|
||||
handleEvent(Event::Quit);
|
||||
break;
|
||||
break; // SDL_QUIT
|
||||
}
|
||||
|
||||
case SDL_EVENT_WINDOW_SHOWN:
|
||||
case SDL_WINDOWEVENT:
|
||||
switch(myEvent.window.event)
|
||||
{
|
||||
case SDL_WINDOWEVENT_SHOWN:
|
||||
handleSystemEvent(SystemEvent::WINDOW_SHOWN);
|
||||
break;
|
||||
case SDL_EVENT_WINDOW_HIDDEN:
|
||||
case SDL_WINDOWEVENT_HIDDEN:
|
||||
handleSystemEvent(SystemEvent::WINDOW_HIDDEN);
|
||||
break;
|
||||
case SDL_EVENT_WINDOW_EXPOSED:
|
||||
case SDL_WINDOWEVENT_EXPOSED:
|
||||
handleSystemEvent(SystemEvent::WINDOW_EXPOSED);
|
||||
break;
|
||||
case SDL_EVENT_WINDOW_MOVED:
|
||||
case SDL_WINDOWEVENT_MOVED:
|
||||
handleSystemEvent(SystemEvent::WINDOW_MOVED,
|
||||
myEvent.window.data1, myEvent.window.data1);
|
||||
break;
|
||||
case SDL_EVENT_WINDOW_RESIZED:
|
||||
case SDL_WINDOWEVENT_RESIZED:
|
||||
handleSystemEvent(SystemEvent::WINDOW_RESIZED,
|
||||
myEvent.window.data1, myEvent.window.data1);
|
||||
break;
|
||||
case SDL_EVENT_WINDOW_MINIMIZED:
|
||||
case SDL_WINDOWEVENT_MINIMIZED:
|
||||
handleSystemEvent(SystemEvent::WINDOW_MINIMIZED);
|
||||
break;
|
||||
case SDL_EVENT_WINDOW_MAXIMIZED:
|
||||
case SDL_WINDOWEVENT_MAXIMIZED:
|
||||
handleSystemEvent(SystemEvent::WINDOW_MAXIMIZED);
|
||||
break;
|
||||
case SDL_EVENT_WINDOW_RESTORED:
|
||||
case SDL_WINDOWEVENT_RESTORED:
|
||||
handleSystemEvent(SystemEvent::WINDOW_RESTORED);
|
||||
break;
|
||||
case SDL_EVENT_WINDOW_MOUSE_ENTER:
|
||||
case SDL_WINDOWEVENT_ENTER:
|
||||
handleSystemEvent(SystemEvent::WINDOW_ENTER);
|
||||
break;
|
||||
case SDL_EVENT_WINDOW_MOUSE_LEAVE:
|
||||
case SDL_WINDOWEVENT_LEAVE:
|
||||
handleSystemEvent(SystemEvent::WINDOW_LEAVE);
|
||||
break;
|
||||
case SDL_EVENT_WINDOW_FOCUS_GAINED:
|
||||
case SDL_WINDOWEVENT_FOCUS_GAINED:
|
||||
handleSystemEvent(SystemEvent::WINDOW_FOCUS_GAINED);
|
||||
break;
|
||||
case SDL_EVENT_WINDOW_FOCUS_LOST:
|
||||
case SDL_WINDOWEVENT_FOCUS_LOST:
|
||||
handleSystemEvent(SystemEvent::WINDOW_FOCUS_LOST);
|
||||
break;
|
||||
case SDL_EVENT_SYSTEM_THEME_CHANGED:
|
||||
handleSystemEvent(SystemEvent::THEME_CHANGED);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break; // SDL_WINDOWEVENT
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef JOYSTICK_SUPPORT
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
EventHandlerSDL::JoystickSDL::JoystickSDL(int idx)
|
||||
EventHandlerSDL2::JoystickSDL2::JoystickSDL2(int idx)
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
// NOLINTNEXTLINE: we want to initialize here, not in the member list
|
||||
myStick = SDL_OpenJoystick(idx);
|
||||
myStick = SDL_JoystickOpen(idx);
|
||||
if(myStick)
|
||||
{
|
||||
// In Windows, all XBox controllers using the XInput API seem to name
|
||||
|
@ -265,24 +274,21 @@ EventHandlerSDL::JoystickSDL::JoystickSDL(int idx)
|
|||
// it also appends " #x", where x seems to vary. Obviously this wreaks
|
||||
// havoc with the idea that a joystick will always have the same name.
|
||||
// So we truncate the number.
|
||||
const char* const sdlname = SDL_GetJoystickName(myStick);
|
||||
const char* const sdlname = SDL_JoystickName(myStick);
|
||||
const string& desc = BSPF::startsWithIgnoreCase(sdlname, "XInput Controller")
|
||||
? "XInput Controller" : sdlname;
|
||||
|
||||
initialize(SDL_GetJoystickID(myStick), desc,
|
||||
SDL_GetNumJoystickAxes(myStick),
|
||||
SDL_GetNumJoystickButtons(myStick),
|
||||
SDL_GetNumJoystickHats(myStick),
|
||||
SDL_GetNumJoystickBalls(myStick));
|
||||
initialize(SDL_JoystickInstanceID(myStick), desc,
|
||||
SDL_JoystickNumAxes(myStick), SDL_JoystickNumButtons(myStick),
|
||||
SDL_JoystickNumHats(myStick), SDL_JoystickNumBalls(myStick));
|
||||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
EventHandlerSDL::JoystickSDL::~JoystickSDL()
|
||||
EventHandlerSDL2::JoystickSDL2::~JoystickSDL2()
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
if(SDL_WasInit(SDL_INIT_JOYSTICK) && myStick)
|
||||
SDL_CloseJoystick(myStick);
|
||||
SDL_JoystickClose(myStick);
|
||||
}
|
||||
#endif
|
|
@ -8,15 +8,15 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//============================================================================
|
||||
|
||||
#ifndef EVENTHANDLER_SDL_HXX
|
||||
#define EVENTHANDLER_SDL_HXX
|
||||
#ifndef EVENTHANDLER_SDL2_HXX
|
||||
#define EVENTHANDLER_SDL2_HXX
|
||||
|
||||
#include "SDL_lib.hxx"
|
||||
#include "EventHandler.hxx"
|
||||
|
@ -24,21 +24,26 @@
|
|||
|
||||
/**
|
||||
This class handles event collection from the point of view of the specific
|
||||
backend toolkit (SDL). It converts from SDL-specific events into events
|
||||
backend toolkit (SDL2). It converts from SDL2-specific events into events
|
||||
that the Stella core can understand.
|
||||
|
||||
@author Stephen Anthony
|
||||
*/
|
||||
class EventHandlerSDL : public EventHandler
|
||||
class EventHandlerSDL2 : public EventHandler
|
||||
{
|
||||
public:
|
||||
/**
|
||||
Create a new SDL event handler object
|
||||
Create a new SDL2 event handler object
|
||||
*/
|
||||
explicit EventHandlerSDL(OSystem& osystem);
|
||||
~EventHandlerSDL() override;
|
||||
explicit EventHandlerSDL2(OSystem& osystem);
|
||||
~EventHandlerSDL2() override;
|
||||
|
||||
private:
|
||||
/**
|
||||
Enable/disable text events (distinct from single-key events).
|
||||
*/
|
||||
void enableTextEvents(bool enable) override;
|
||||
|
||||
/**
|
||||
Clipboard methods.
|
||||
*/
|
||||
|
@ -46,42 +51,40 @@ class EventHandlerSDL : public EventHandler
|
|||
string pasteText(string& text) const override;
|
||||
|
||||
/**
|
||||
Collects and dispatches any pending SDL events.
|
||||
Collects and dispatches any pending SDL2 events.
|
||||
*/
|
||||
void pollEvent() override;
|
||||
|
||||
private:
|
||||
SDL_Event myEvent{0};
|
||||
|
||||
#ifdef JOYSTICK_SUPPORT
|
||||
// A thin wrapper around a basic PhysicalJoystick, holding the pointer to
|
||||
// the underlying SDL joystick device.
|
||||
class JoystickSDL : public PhysicalJoystick
|
||||
class JoystickSDL2 : public PhysicalJoystick
|
||||
{
|
||||
public:
|
||||
explicit JoystickSDL(int idx);
|
||||
virtual ~JoystickSDL();
|
||||
explicit JoystickSDL2(int idx);
|
||||
virtual ~JoystickSDL2();
|
||||
|
||||
private:
|
||||
SDL_Joystick* myStick{nullptr};
|
||||
|
||||
private:
|
||||
// Following constructors and assignment operators not supported
|
||||
JoystickSDL() = delete;
|
||||
JoystickSDL(const JoystickSDL&) = delete;
|
||||
JoystickSDL(JoystickSDL&&) = delete;
|
||||
JoystickSDL& operator=(const JoystickSDL&) = delete;
|
||||
JoystickSDL& operator=(JoystickSDL&&) = delete;
|
||||
JoystickSDL2() = delete;
|
||||
JoystickSDL2(const JoystickSDL2&) = delete;
|
||||
JoystickSDL2(JoystickSDL2&&) = delete;
|
||||
JoystickSDL2& operator=(const JoystickSDL2&) = delete;
|
||||
JoystickSDL2& operator=(JoystickSDL2&&) = delete;
|
||||
};
|
||||
#endif
|
||||
|
||||
private:
|
||||
// Following constructors and assignment operators not supported
|
||||
EventHandlerSDL() = delete;
|
||||
EventHandlerSDL(const EventHandlerSDL&) = delete;
|
||||
EventHandlerSDL(EventHandlerSDL&&) = delete;
|
||||
EventHandlerSDL& operator=(const EventHandlerSDL&) = delete;
|
||||
EventHandlerSDL& operator=(EventHandlerSDL&&) = delete;
|
||||
EventHandlerSDL2() = delete;
|
||||
EventHandlerSDL2(const EventHandlerSDL2&) = delete;
|
||||
EventHandlerSDL2(EventHandlerSDL2&&) = delete;
|
||||
EventHandlerSDL2& operator=(const EventHandlerSDL2&) = delete;
|
||||
EventHandlerSDL2& operator=(EventHandlerSDL2&&) = delete;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
@ -25,36 +25,38 @@
|
|||
#include "Settings.hxx"
|
||||
|
||||
#include "ThreadDebugging.hxx"
|
||||
#include "FBSurfaceSDL.hxx"
|
||||
#include "FBBackendSDL.hxx"
|
||||
#include "FBSurfaceSDL2.hxx"
|
||||
#include "FBBackendSDL2.hxx"
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
FBBackendSDL::FBBackendSDL(OSystem& osystem)
|
||||
FBBackendSDL2::FBBackendSDL2(OSystem& osystem)
|
||||
: myOSystem{osystem}
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
// Initialize SDL context
|
||||
if(!SDL_InitSubSystem(SDL_INIT_VIDEO))
|
||||
// Initialize SDL2 context
|
||||
if(SDL_InitSubSystem(SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0)
|
||||
{
|
||||
ostringstream buf;
|
||||
buf << "ERROR: Couldn't initialize SDL: " << SDL_GetError();
|
||||
throw runtime_error(buf.str());
|
||||
}
|
||||
Logger::debug("FBBackendSDL::FBBackendSDL SDL_Init()");
|
||||
Logger::debug("FBBackendSDL2::FBBackendSDL2 SDL_Init()");
|
||||
|
||||
// We need a pixel format for palette value calculations
|
||||
// It's done this way (vs directly accessing a FBSurfaceSDL object)
|
||||
// It's done this way (vs directly accessing a FBSurfaceSDL2 object)
|
||||
// since the structure may be needed before any FBSurface's have
|
||||
// been created
|
||||
myPixelFormat = SDL_GetPixelFormatDetails(SDL_PIXELFORMAT_ARGB8888);
|
||||
myPixelFormat = SDL_AllocFormat(SDL_PIXELFORMAT_ARGB8888);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
FBBackendSDL::~FBBackendSDL()
|
||||
FBBackendSDL2::~FBBackendSDL2()
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
SDL_FreeFormat(myPixelFormat);
|
||||
|
||||
if(myRenderer)
|
||||
{
|
||||
SDL_DestroyRenderer(myRenderer);
|
||||
|
@ -62,55 +64,46 @@ FBBackendSDL::~FBBackendSDL()
|
|||
}
|
||||
if(myWindow)
|
||||
{
|
||||
SDL_SetWindowFullscreen(myWindow, false); // on some systems, a crash occurs
|
||||
SDL_SetWindowFullscreen(myWindow, 0); // on some systems, a crash occurs
|
||||
// when destroying fullscreen window
|
||||
SDL_DestroyWindow(myWindow);
|
||||
myWindow = nullptr;
|
||||
}
|
||||
SDL_QuitSubSystem(SDL_INIT_VIDEO);
|
||||
SDL_QuitSubSystem(SDL_INIT_VIDEO | SDL_INIT_TIMER);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FBBackendSDL::queryHardware(vector<Common::Size>& fullscreenRes,
|
||||
void FBBackendSDL2::queryHardware(vector<Common::Size>& fullscreenRes,
|
||||
vector<Common::Size>& windowedRes,
|
||||
VariantList& renderers)
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
// Get number of displays (for most systems, this will be '1')
|
||||
int count = 0;
|
||||
SDL_DisplayID* displays = SDL_GetDisplays(&count);
|
||||
if(displays && count > 0)
|
||||
myNumDisplays = static_cast<uInt32>(count);
|
||||
else
|
||||
return;
|
||||
myNumDisplays = SDL_GetNumVideoDisplays();
|
||||
|
||||
// Get the maximum fullscreen and windowed desktop resolutions
|
||||
for(uInt32 i = 0; i < myNumDisplays; ++i)
|
||||
// First get the maximum fullscreen desktop resolution
|
||||
SDL_DisplayMode display;
|
||||
for(int i = 0; i < myNumDisplays; ++i)
|
||||
{
|
||||
// Fullscreen mode
|
||||
const SDL_DisplayMode* display = SDL_GetDesktopDisplayMode(displays[i]);
|
||||
fullscreenRes.emplace_back(display->w, display->h);
|
||||
SDL_GetDesktopDisplayMode(i, &display);
|
||||
fullscreenRes.emplace_back(display.w, display.h);
|
||||
|
||||
// Windowed mode
|
||||
SDL_Rect r{};
|
||||
if(SDL_GetDisplayUsableBounds(displays[i], &r))
|
||||
windowedRes.emplace_back(r.w, r.h);
|
||||
|
||||
int numModes = 0;
|
||||
// evaluate fullscreen display modes (debug only for now)
|
||||
const int numModes = SDL_GetNumDisplayModes(i);
|
||||
ostringstream s;
|
||||
string lastRes;
|
||||
SDL_DisplayMode** modes = SDL_GetFullscreenDisplayModes(displays[i], &numModes);
|
||||
|
||||
s << "Supported video modes (" << numModes << ") for display " << i
|
||||
<< " (" << SDL_GetDisplayName(displays[i]) << "):";
|
||||
<< " (" << SDL_GetDisplayName(i) << "):";
|
||||
|
||||
for(int m = 0; modes != nullptr && modes[m] != nullptr; m++)
|
||||
string lastRes;
|
||||
for(int m = 0; m < numModes; ++m)
|
||||
{
|
||||
const SDL_DisplayMode* mode = modes[m];
|
||||
ostringstream res, ref;
|
||||
SDL_DisplayMode mode;
|
||||
ostringstream res;
|
||||
|
||||
res << std::setw(4) << mode->w << "x" << std::setw(4) << mode->h;
|
||||
SDL_GetDisplayMode(i, m, &mode);
|
||||
res << std::setw(4) << mode.w << "x" << std::setw(4) << mode.h;
|
||||
|
||||
if(lastRes != res.view())
|
||||
{
|
||||
|
@ -119,23 +112,47 @@ void FBBackendSDL::queryHardware(vector<Common::Size>& fullscreenRes,
|
|||
lastRes = res.view();
|
||||
s << " " << lastRes << ": ";
|
||||
}
|
||||
|
||||
ref << mode->refresh_rate << "Hz";
|
||||
s << std::setw(7) << std::left << ref.str();
|
||||
if(mode->w == display->w && mode->h == display->h &&
|
||||
mode->refresh_rate == display->refresh_rate)
|
||||
s << mode.refresh_rate << "Hz";
|
||||
if(mode.w == display.w && mode.h == display.h && mode.refresh_rate == display.refresh_rate)
|
||||
s << "* ";
|
||||
else
|
||||
s << " ";
|
||||
}
|
||||
Logger::debug(s.view());
|
||||
}
|
||||
SDL_free(displays);
|
||||
|
||||
// Now get the maximum windowed desktop resolution
|
||||
// Try to take into account taskbars, etc, if available
|
||||
#if SDL_VERSION_ATLEAST(2,0,5)
|
||||
// Take window title-bar into account; SDL_GetDisplayUsableBounds doesn't do that
|
||||
int wTop = 0, wLeft = 0, wBottom = 0, wRight = 0;
|
||||
SDL_Window* tmpWindow = SDL_CreateWindow("", 0, 0, 0, 0, SDL_WINDOW_HIDDEN);
|
||||
if(tmpWindow != nullptr)
|
||||
{
|
||||
SDL_GetWindowBordersSize(tmpWindow, &wTop, &wLeft, &wBottom, &wRight);
|
||||
SDL_DestroyWindow(tmpWindow);
|
||||
}
|
||||
|
||||
SDL_Rect r;
|
||||
for(int i = 0; i < myNumDisplays; ++i)
|
||||
{
|
||||
// Display bounds minus dock
|
||||
SDL_GetDisplayUsableBounds(i, &r); // Requires SDL-2.0.5 or higher
|
||||
r.h -= (wTop + wBottom);
|
||||
windowedRes.emplace_back(r.w, r.h);
|
||||
}
|
||||
#else
|
||||
for(int i = 0; i < myNumDisplays; ++i)
|
||||
{
|
||||
SDL_GetDesktopDisplayMode(i, &display);
|
||||
windowedRes.emplace_back(display.w, display.h);
|
||||
}
|
||||
#endif
|
||||
|
||||
struct RenderName
|
||||
{
|
||||
string_view sdlName;
|
||||
string_view stellaName;
|
||||
string sdlName;
|
||||
string stellaName;
|
||||
};
|
||||
// Create name map for all currently known SDL renderers
|
||||
static const std::array<RenderName, 8> RENDERER_NAMES = {{
|
||||
|
@ -152,66 +169,68 @@ void FBBackendSDL::queryHardware(vector<Common::Size>& fullscreenRes,
|
|||
const int numDrivers = SDL_GetNumRenderDrivers();
|
||||
for(int i = 0; i < numDrivers; ++i)
|
||||
{
|
||||
const char* const rendername = SDL_GetRenderDriver(i);
|
||||
if(rendername)
|
||||
SDL_RendererInfo info;
|
||||
if(SDL_GetRenderDriverInfo(i, &info) == 0)
|
||||
{
|
||||
// Map SDL names into nicer Stella names (if available)
|
||||
bool found = false;
|
||||
for(const auto& render: RENDERER_NAMES)
|
||||
{
|
||||
if(render.sdlName == rendername)
|
||||
if(render.sdlName == info.name)
|
||||
{
|
||||
VarList::push_back(renderers, render.stellaName, rendername);
|
||||
VarList::push_back(renderers, render.stellaName, info.name);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found)
|
||||
VarList::push_back(renderers, rendername, rendername);
|
||||
VarList::push_back(renderers, info.name, info.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool FBBackendSDL::isCurrentWindowPositioned() const
|
||||
bool FBBackendSDL2::isCurrentWindowPositioned() const
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
return myWindow && !fullScreen() && !myCenter;
|
||||
return !myCenter
|
||||
&& myWindow && !(SDL_GetWindowFlags(myWindow) & SDL_WINDOW_FULLSCREEN_DESKTOP);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Common::Point FBBackendSDL::getCurrentWindowPos() const
|
||||
Common::Point FBBackendSDL2::getCurrentWindowPos() const
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
Common::Point pos;
|
||||
|
||||
SDL_GetWindowPosition(myWindow, &pos.x, &pos.y);
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt32 FBBackendSDL::getCurrentDisplayID() const
|
||||
Int32 FBBackendSDL2::getCurrentDisplayIndex() const
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
return SDL_GetDisplayForWindow(myWindow);
|
||||
return SDL_GetWindowDisplayIndex(myWindow);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool FBBackendSDL::setVideoMode(const VideoModeHandler::Mode& mode,
|
||||
bool FBBackendSDL2::setVideoMode(const VideoModeHandler::Mode& mode,
|
||||
int winIdx, const Common::Point& winPos)
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
// cerr << mode << '\n';
|
||||
|
||||
// If not initialized by this point, then immediately fail
|
||||
if(SDL_WasInit(SDL_INIT_VIDEO) == 0)
|
||||
return false;
|
||||
|
||||
const uInt32 displayIndex = std::min<uInt32>(myNumDisplays, winIdx);
|
||||
const bool fullScreen = mode.fsIndex != -1;
|
||||
const Int32 displayIndex = std::min(myNumDisplays - 1, winIdx);
|
||||
|
||||
int posX = 0, posY = 0;
|
||||
|
||||
myCenter = myOSystem.settings().getBool("center");
|
||||
|
@ -242,10 +261,10 @@ bool FBBackendSDL::setVideoMode(const VideoModeHandler::Mode& mode,
|
|||
}
|
||||
|
||||
#ifdef ADAPTABLE_REFRESH_SUPPORT
|
||||
SDL_DisplayMode adaptedSdlMode{};
|
||||
SDL_DisplayMode adaptedSdlMode;
|
||||
const int gameRefreshRate =
|
||||
myOSystem.hasConsole() ? myOSystem.console().gameRefreshRate() : 0;
|
||||
const bool shouldAdapt = mode.fullscreen
|
||||
const bool shouldAdapt = fullScreen
|
||||
&& myOSystem.settings().getBool("tia.fs_refresh")
|
||||
&& gameRefreshRate
|
||||
// take care of 59.94 Hz
|
||||
|
@ -256,18 +275,20 @@ bool FBBackendSDL::setVideoMode(const VideoModeHandler::Mode& mode,
|
|||
#else
|
||||
const bool adaptRefresh = false;
|
||||
#endif
|
||||
const uInt32 flags = SDL_WINDOW_ALLOW_HIGHDPI
|
||||
| (fullScreen ? adaptRefresh ? SDL_WINDOW_FULLSCREEN :
|
||||
SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
|
||||
|
||||
// Don't re-create the window if its display and size hasn't changed,
|
||||
// as it's not necessary, and causes flashing in fullscreen mode
|
||||
if(myWindow)
|
||||
{
|
||||
const uInt32 d = getCurrentDisplayID();
|
||||
const int d = SDL_GetWindowDisplayIndex(myWindow);
|
||||
int w{0}, h{0};
|
||||
|
||||
SDL_GetWindowSize(myWindow, &w, &h);
|
||||
if(d != displayIndex ||
|
||||
std::cmp_not_equal(w, mode.screenS.w) ||
|
||||
std::cmp_not_equal(h, mode.screenS.h) || adaptRefresh)
|
||||
if(d != displayIndex || static_cast<uInt32>(w) != mode.screenS.w ||
|
||||
static_cast<uInt32>(h) != mode.screenS.h || adaptRefresh)
|
||||
{
|
||||
// Renderer has to be destroyed *before* the window gets destroyed to avoid memory leaks
|
||||
SDL_DestroyRenderer(myRenderer);
|
||||
|
@ -285,25 +306,8 @@ bool FBBackendSDL::setVideoMode(const VideoModeHandler::Mode& mode,
|
|||
}
|
||||
else
|
||||
{
|
||||
// Re-create with new properties
|
||||
const SDL_PropertiesID props = SDL_CreateProperties();
|
||||
SDL_SetStringProperty(props, SDL_PROP_WINDOW_CREATE_TITLE_STRING,
|
||||
myScreenTitle.c_str());
|
||||
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_X_NUMBER, posX);
|
||||
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_Y_NUMBER, posY);
|
||||
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_WIDTH_NUMBER,
|
||||
mode.screenS.w);
|
||||
SDL_SetNumberProperty(props, SDL_PROP_WINDOW_CREATE_HEIGHT_NUMBER,
|
||||
mode.screenS.h);
|
||||
SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_HIDDEN_BOOLEAN,
|
||||
true);
|
||||
SDL_SetBooleanProperty(props, SDL_PROP_WINDOW_CREATE_FULLSCREEN_BOOLEAN,
|
||||
mode.fullscreen);
|
||||
SDL_SetBooleanProperty(props,
|
||||
SDL_PROP_WINDOW_CREATE_HIGH_PIXEL_DENSITY_BOOLEAN,
|
||||
true);
|
||||
myWindow = SDL_CreateWindowWithProperties(props);
|
||||
SDL_DestroyProperties(props);
|
||||
myWindow = SDL_CreateWindow(myScreenTitle.c_str(), posX, posY,
|
||||
mode.screenS.w, mode.screenS.h, flags);
|
||||
if(myWindow == nullptr)
|
||||
{
|
||||
const string msg = "ERROR: Unable to open SDL window: " + string(SDL_GetError());
|
||||
|
@ -311,7 +315,6 @@ bool FBBackendSDL::setVideoMode(const VideoModeHandler::Mode& mode,
|
|||
return false;
|
||||
}
|
||||
|
||||
enableTextEvents(myTextEventsEnabled);
|
||||
setWindowIcon();
|
||||
}
|
||||
|
||||
|
@ -319,7 +322,7 @@ bool FBBackendSDL::setVideoMode(const VideoModeHandler::Mode& mode,
|
|||
if(adaptRefresh)
|
||||
{
|
||||
// Switch to mode for adapted refresh rate
|
||||
if(!SDL_SetWindowFullscreenMode(myWindow, &adaptedSdlMode))
|
||||
if(SDL_SetWindowDisplayMode(myWindow, &adaptedSdlMode) != 0)
|
||||
{
|
||||
Logger::error("ERROR: Display refresh rate change failed");
|
||||
}
|
||||
|
@ -331,39 +334,31 @@ bool FBBackendSDL::setVideoMode(const VideoModeHandler::Mode& mode,
|
|||
<< adaptedSdlMode.refresh_rate << " Hz " << "(" << adaptedSdlMode.w << "x" << adaptedSdlMode.h << ")";
|
||||
Logger::info(msg.view());
|
||||
|
||||
const SDL_DisplayMode* setSdlMode = SDL_GetWindowFullscreenMode(myWindow);
|
||||
cerr << setSdlMode->refresh_rate << "Hz\n";
|
||||
SDL_DisplayMode setSdlMode;
|
||||
SDL_GetWindowDisplayMode(myWindow, &setSdlMode);
|
||||
cerr << setSdlMode.refresh_rate << "Hz\n";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
const bool result = createRenderer();
|
||||
if(result)
|
||||
{
|
||||
// TODO: Checking for fullscreen status later returns invalid results,
|
||||
// so we check and cache it here
|
||||
myIsFullscreen = SDL_GetWindowFlags(myWindow) & SDL_WINDOW_FULLSCREEN;
|
||||
SDL_ShowWindow(myWindow);
|
||||
}
|
||||
|
||||
return result;
|
||||
return createRenderer();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool FBBackendSDL::adaptRefreshRate(Int32 displayIndex,
|
||||
bool FBBackendSDL2::adaptRefreshRate(Int32 displayIndex,
|
||||
SDL_DisplayMode& adaptedSdlMode)
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
const SDL_DisplayMode* sdlMode = SDL_GetCurrentDisplayMode(displayIndex);
|
||||
SDL_DisplayMode sdlMode;
|
||||
|
||||
if(sdlMode == nullptr)
|
||||
if(SDL_GetCurrentDisplayMode(displayIndex, &sdlMode) != 0)
|
||||
{
|
||||
Logger::error("ERROR: Display mode could not be retrieved");
|
||||
return false;
|
||||
}
|
||||
|
||||
const int currentRefreshRate = sdlMode->refresh_rate;
|
||||
const int currentRefreshRate = sdlMode.refresh_rate;
|
||||
const int wantedRefreshRate =
|
||||
myOSystem.hasConsole() ? myOSystem.console().gameRefreshRate() : 0;
|
||||
// Take care of rounded refresh rates (e.g. 59.94 Hz)
|
||||
|
@ -379,19 +374,18 @@ bool FBBackendSDL::adaptRefreshRate(Int32 displayIndex,
|
|||
// Check for integer factors 1 (60/50 Hz) and 2 (120/100 Hz)
|
||||
for(int m = 1; m <= 2; ++m)
|
||||
{
|
||||
SDL_DisplayMode closestSdlMode{};
|
||||
const float refresh_rate = wantedRefreshRate * m;
|
||||
SDL_DisplayMode closestSdlMode;
|
||||
|
||||
if(!SDL_GetClosestFullscreenDisplayMode(displayIndex, sdlMode->w, sdlMode->h, refresh_rate, true, &closestSdlMode))
|
||||
sdlMode.refresh_rate = wantedRefreshRate * m;
|
||||
if(SDL_GetClosestDisplayMode(displayIndex, &sdlMode, &closestSdlMode) == nullptr)
|
||||
{
|
||||
Logger::error("ERROR: Closest display mode could not be retrieved");
|
||||
return adapt;
|
||||
}
|
||||
factor = std::min(
|
||||
static_cast<float>(refresh_rate) / refresh_rate,
|
||||
static_cast<float>(refresh_rate) / (refresh_rate - 1));
|
||||
static_cast<float>(sdlMode.refresh_rate) / sdlMode.refresh_rate,
|
||||
static_cast<float>(sdlMode.refresh_rate) / (sdlMode.refresh_rate - 1));
|
||||
const float diff = std::abs(factor - std::round(factor)) / factor;
|
||||
|
||||
if(diff < bestDiff)
|
||||
{
|
||||
bestDiff = diff;
|
||||
|
@ -411,46 +405,38 @@ bool FBBackendSDL::adaptRefreshRate(Int32 displayIndex,
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool FBBackendSDL::createRenderer()
|
||||
bool FBBackendSDL2::createRenderer()
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
// A new renderer is only created when necessary:
|
||||
// - no renderer existing
|
||||
// - different renderer flags
|
||||
// - different renderer name
|
||||
// - different renderer vsync
|
||||
const bool enableVSync = myOSystem.settings().getBool("vsync") &&
|
||||
!myOSystem.settings().getBool("turbo");
|
||||
const string& video = myOSystem.settings().getString("video");
|
||||
|
||||
bool recreate = myRenderer == nullptr;
|
||||
if(myRenderer)
|
||||
{
|
||||
recreate = recreate || video != SDL_GetRendererName(myRenderer);
|
||||
uInt32 renderFlags = SDL_RENDERER_ACCELERATED;
|
||||
const string& video = myOSystem.settings().getString("video"); // Render hint
|
||||
SDL_RendererInfo renderInfo;
|
||||
|
||||
const SDL_PropertiesID props = SDL_GetRendererProperties(myRenderer);
|
||||
const bool currentVSync = SDL_GetNumberProperty(props,
|
||||
SDL_PROP_RENDERER_VSYNC_NUMBER, 0) != 0;
|
||||
recreate = recreate || currentVSync != enableVSync;
|
||||
}
|
||||
if(myOSystem.settings().getBool("vsync")
|
||||
&& !myOSystem.settings().getBool("turbo")) // V'synced blits option
|
||||
renderFlags |= SDL_RENDERER_PRESENTVSYNC;
|
||||
|
||||
// check renderer flags and name
|
||||
recreate |= (SDL_GetRendererInfo(myRenderer, &renderInfo) != 0)
|
||||
|| ((renderInfo.flags & (SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC)) != renderFlags
|
||||
|| (video != renderInfo.name));
|
||||
|
||||
if(recreate)
|
||||
{
|
||||
//cerr << "Create new renderer for buffer type #" << int(myBufferType) << '\n';
|
||||
if(myRenderer)
|
||||
SDL_DestroyRenderer(myRenderer);
|
||||
|
||||
// Re-create with new properties
|
||||
const SDL_PropertiesID props = SDL_CreateProperties();
|
||||
if(!video.empty())
|
||||
SDL_SetStringProperty(props, SDL_PROP_RENDERER_CREATE_NAME_STRING,
|
||||
video.c_str());
|
||||
SDL_SetNumberProperty(props, SDL_PROP_RENDERER_CREATE_PRESENT_VSYNC_NUMBER,
|
||||
enableVSync ? 1 : 0);
|
||||
SDL_SetPointerProperty(props, SDL_PROP_RENDERER_CREATE_WINDOW_POINTER,
|
||||
myWindow);
|
||||
SDL_SetHint(SDL_HINT_RENDER_DRIVER, video.c_str());
|
||||
|
||||
myRenderer = SDL_CreateRendererWithProperties(props);
|
||||
SDL_DestroyProperties(props);
|
||||
myRenderer = SDL_CreateRenderer(myWindow, -1, renderFlags);
|
||||
|
||||
detectFeatures();
|
||||
determineDimensions();
|
||||
|
@ -464,106 +450,85 @@ bool FBBackendSDL::createRenderer()
|
|||
}
|
||||
clear();
|
||||
|
||||
const char* const detectedvideo = SDL_GetRendererName(myRenderer);
|
||||
if(detectedvideo)
|
||||
myOSystem.settings().setValue("video", detectedvideo);
|
||||
SDL_RendererInfo renderinfo;
|
||||
|
||||
if(SDL_GetRendererInfo(myRenderer, &renderinfo) >= 0)
|
||||
myOSystem.settings().setValue("video", renderinfo.name);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FBBackendSDL::setTitle(string_view title)
|
||||
void FBBackendSDL2::setTitle(string_view title)
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
myScreenTitle = title;
|
||||
|
||||
if(myWindow)
|
||||
SDL_SetWindowTitle(myWindow, myScreenTitle.c_str());
|
||||
SDL_SetWindowTitle(myWindow, string{title}.c_str());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
string FBBackendSDL::about() const
|
||||
string FBBackendSDL2::about() const
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
ostringstream out;
|
||||
out << "Video system: " << SDL_GetCurrentVideoDriver() << '\n';
|
||||
|
||||
const SDL_PropertiesID props = SDL_GetRendererProperties(myRenderer);
|
||||
if(props != 0)
|
||||
SDL_RendererInfo info;
|
||||
if(SDL_GetRendererInfo(myRenderer, &info) >= 0)
|
||||
{
|
||||
out << " Renderer: "
|
||||
<< SDL_GetStringProperty(props, SDL_PROP_RENDERER_NAME_STRING, "")
|
||||
<< '\n';
|
||||
const uInt64 maxTexSize =
|
||||
SDL_GetNumberProperty(props, SDL_PROP_RENDERER_MAX_TEXTURE_SIZE_NUMBER, 0);
|
||||
if(maxTexSize > 0)
|
||||
out << " Max texture: " << maxTexSize << "x" << maxTexSize << '\n';
|
||||
const bool usingVSync = SDL_GetNumberProperty(props,
|
||||
SDL_PROP_RENDERER_VSYNC_NUMBER, 0) != 0;
|
||||
out << " Renderer: " << info.name << '\n';
|
||||
if(info.max_texture_width > 0 && info.max_texture_height > 0)
|
||||
out << " Max texture: " << info.max_texture_width << "x"
|
||||
<< info.max_texture_height << '\n';
|
||||
out << " Flags: "
|
||||
<< (usingVSync ? "+" : "-") << "vsync"
|
||||
<< ((info.flags & SDL_RENDERER_PRESENTVSYNC) ? "+" : "-") << "vsync, "
|
||||
<< ((info.flags & SDL_RENDERER_ACCELERATED) ? "+" : "-") << "accel"
|
||||
<< '\n';
|
||||
}
|
||||
return out.str();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FBBackendSDL::showCursor(bool show)
|
||||
void FBBackendSDL2::showCursor(bool show)
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
if(show) SDL_ShowCursor();
|
||||
else SDL_HideCursor();
|
||||
SDL_ShowCursor(show ? SDL_ENABLE : SDL_DISABLE);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FBBackendSDL::grabMouse(bool grab)
|
||||
void FBBackendSDL2::grabMouse(bool grab)
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
SDL_SetWindowMouseGrab(myWindow, grab);
|
||||
SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_SYSTEM_SCALE, grab ? "1" : "0");
|
||||
SDL_SetWindowRelativeMouseMode(myWindow, grab);
|
||||
SDL_SetRelativeMouseMode(grab ? SDL_TRUE : SDL_FALSE);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FBBackendSDL::enableTextEvents(bool enable)
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
if(enable)
|
||||
SDL_StartTextInput(myWindow);
|
||||
else
|
||||
SDL_StopTextInput(myWindow);
|
||||
// myWindows can still be null, so we remember the state and set again when
|
||||
// the window is created
|
||||
myTextEventsEnabled = enable;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool FBBackendSDL::fullScreen() const
|
||||
bool FBBackendSDL2::fullScreen() const
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
#ifdef WINDOWED_SUPPORT
|
||||
return myIsFullscreen; // TODO: should query SDL directly
|
||||
return SDL_GetWindowFlags(myWindow) & SDL_WINDOW_FULLSCREEN_DESKTOP;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
int FBBackendSDL::refreshRate() const
|
||||
int FBBackendSDL2::refreshRate() const
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
const SDL_DisplayID displayID = getCurrentDisplayID();
|
||||
const SDL_DisplayMode* mode = SDL_GetCurrentDisplayMode(displayID);
|
||||
const uInt32 displayIndex = SDL_GetWindowDisplayIndex(myWindow);
|
||||
SDL_DisplayMode sdlMode;
|
||||
|
||||
if(mode)
|
||||
return mode->refresh_rate;
|
||||
if(SDL_GetCurrentDisplayMode(displayIndex, &sdlMode) == 0)
|
||||
return sdlMode.refresh_rate;
|
||||
|
||||
if(myWindow != nullptr)
|
||||
Logger::error("Could not retrieve current display mode");
|
||||
|
@ -572,7 +537,7 @@ int FBBackendSDL::refreshRate() const
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FBBackendSDL::renderToScreen()
|
||||
void FBBackendSDL2::renderToScreen()
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
|
@ -581,42 +546,35 @@ void FBBackendSDL::renderToScreen()
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FBBackendSDL::setWindowIcon()
|
||||
void FBBackendSDL2::setWindowIcon()
|
||||
{
|
||||
#if !defined(BSPF_MACOS)
|
||||
#if !defined(BSPF_MACOS) && !defined(RETRON77)
|
||||
#include "stella_icon.hxx"
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
SDL_Surface* surface =
|
||||
SDL_CreateSurfaceFrom(32, 32, pixelFormat().format, stella_icon, 32 * 4);
|
||||
SDL_Surface* surface = SDL_CreateRGBSurfaceFrom(stella_icon, 32, 32, 32,
|
||||
32 * 4, 0xFF0000, 0x00FF00, 0x0000FF, 0xFF000000);
|
||||
SDL_SetWindowIcon(myWindow, surface);
|
||||
SDL_DestroySurface(surface);
|
||||
SDL_FreeSurface(surface);
|
||||
#endif
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
unique_ptr<FBSurface> FBBackendSDL::createSurface(
|
||||
unique_ptr<FBSurface> FBBackendSDL2::createSurface(
|
||||
uInt32 w,
|
||||
uInt32 h,
|
||||
ScalingInterpolation inter,
|
||||
const uInt32* data
|
||||
) const
|
||||
{
|
||||
unique_ptr<FBSurface> s = make_unique<FBSurfaceSDL>
|
||||
(const_cast<FBBackendSDL&>(*this), w, h, inter, data);
|
||||
s->setBlendLevel(100); // by default, disable shading (use full alpha)
|
||||
|
||||
return s;
|
||||
return make_unique<FBSurfaceSDL2>
|
||||
(const_cast<FBBackendSDL2&>(*this), w, h, inter, data);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FBBackendSDL::readPixels(uInt8* buffer, size_t pitch,
|
||||
void FBBackendSDL2::readPixels(uInt8* buffer, size_t pitch,
|
||||
const Common::Rect& rect) const
|
||||
{
|
||||
// FIXME: this method needs to be refactored to return an FBSurface,
|
||||
// since SDL_RenderReadPixels now returns an SDL_Surface
|
||||
// PNGLibrary is the only user of this; that will need to be refactored too
|
||||
#if 0
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
SDL_Rect r;
|
||||
|
@ -624,11 +582,10 @@ void FBBackendSDL::readPixels(uInt8* buffer, size_t pitch,
|
|||
r.w = rect.w(); r.h = rect.h();
|
||||
|
||||
SDL_RenderReadPixels(myRenderer, &r, 0, buffer, static_cast<int>(pitch));
|
||||
#endif
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FBBackendSDL::clear()
|
||||
void FBBackendSDL2::clear()
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
|
@ -636,7 +593,7 @@ void FBBackendSDL::clear()
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FBBackendSDL::detectFeatures()
|
||||
void FBBackendSDL2::detectFeatures()
|
||||
{
|
||||
myRenderTargetSupport = detectRenderTargetSupport();
|
||||
|
||||
|
@ -645,20 +602,36 @@ void FBBackendSDL::detectFeatures()
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool FBBackendSDL::detectRenderTargetSupport()
|
||||
bool FBBackendSDL2::detectRenderTargetSupport()
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
if(myRenderer == nullptr)
|
||||
return false;
|
||||
|
||||
// All texture modes except software support render targets
|
||||
const char* const detectedvideo = SDL_GetRendererName(myRenderer);
|
||||
return detectedvideo && !BSPF::equalsIgnoreCase(detectedvideo, "software");
|
||||
SDL_RendererInfo info;
|
||||
SDL_GetRendererInfo(myRenderer, &info);
|
||||
|
||||
if(!(info.flags & SDL_RENDERER_TARGETTEXTURE))
|
||||
return false;
|
||||
|
||||
SDL_Texture* tex =
|
||||
SDL_CreateTexture(myRenderer, myPixelFormat->format,
|
||||
SDL_TEXTUREACCESS_TARGET, 16, 16);
|
||||
|
||||
if(!tex)
|
||||
return false;
|
||||
|
||||
const int sdlError = SDL_SetRenderTarget(myRenderer, tex);
|
||||
SDL_SetRenderTarget(myRenderer, nullptr);
|
||||
|
||||
SDL_DestroyTexture(tex);
|
||||
|
||||
return sdlError == 0;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FBBackendSDL::determineDimensions()
|
||||
void FBBackendSDL2::determineDimensions()
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
|
@ -670,5 +643,5 @@ void FBBackendSDL::determineDimensions()
|
|||
myRenderH = myWindowH;
|
||||
}
|
||||
else
|
||||
SDL_GetCurrentRenderOutputSize(myRenderer, &myRenderW, &myRenderH);
|
||||
SDL_GetRendererOutputSize(myRenderer, &myRenderW, &myRenderH);
|
||||
}
|
|
@ -8,38 +8,38 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//============================================================================
|
||||
|
||||
#ifndef FB_BACKEND_SDL_HXX
|
||||
#define FB_BACKEND_SDL_HXX
|
||||
#ifndef FB_BACKEND_SDL2_HXX
|
||||
#define FB_BACKEND_SDL2_HXX
|
||||
|
||||
#include "SDL_lib.hxx"
|
||||
|
||||
class OSystem;
|
||||
class FBSurfaceSDL;
|
||||
class FBSurfaceSDL2;
|
||||
|
||||
#include "bspf.hxx"
|
||||
#include "FBBackend.hxx"
|
||||
|
||||
/**
|
||||
This class implements a standard SDL 2D, hardware accelerated framebuffer
|
||||
This class implements a standard SDL2 2D, hardware accelerated framebuffer
|
||||
backend. Behind the scenes, it may be using Direct3D, OpenGL(ES), etc.
|
||||
|
||||
@author Stephen Anthony
|
||||
*/
|
||||
class FBBackendSDL : public FBBackend
|
||||
class FBBackendSDL2 : public FBBackend
|
||||
{
|
||||
public:
|
||||
/**
|
||||
Creates a new SDL framebuffer
|
||||
Creates a new SDL2 framebuffer
|
||||
*/
|
||||
explicit FBBackendSDL(OSystem& osystem);
|
||||
~FBBackendSDL() override;
|
||||
explicit FBBackendSDL2(OSystem& osystem);
|
||||
~FBBackendSDL2() override;
|
||||
|
||||
public:
|
||||
/**
|
||||
|
@ -55,7 +55,7 @@ class FBBackendSDL : public FBBackend
|
|||
/**
|
||||
Get the SDL pixel format.
|
||||
*/
|
||||
const SDL_PixelFormatDetails& pixelFormat() const { return *myPixelFormat; }
|
||||
const SDL_PixelFormat& pixelFormat() const { return *myPixelFormat; }
|
||||
|
||||
/**
|
||||
Does the renderer support render targets?
|
||||
|
@ -99,7 +99,7 @@ class FBBackendSDL : public FBBackend
|
|||
@param b The blue component of the color
|
||||
*/
|
||||
FORCE_INLINE void getRGB(uInt32 pixel, uInt8* r, uInt8* g, uInt8* b) const override
|
||||
{ SDL_GetRGB(pixel, myPixelFormat, nullptr, r, g, b); }
|
||||
{ SDL_GetRGB(pixel, myPixelFormat, r, g, b); }
|
||||
|
||||
/**
|
||||
This method is called to retrieve the R/G/B/A data from the given pixel.
|
||||
|
@ -111,7 +111,7 @@ class FBBackendSDL : public FBBackend
|
|||
@param a The alpha component of the color.
|
||||
*/
|
||||
FORCE_INLINE void getRGBA(uInt32 pixel, uInt8* r, uInt8* g, uInt8* b, uInt8* a) const override
|
||||
{ SDL_GetRGBA(pixel, myPixelFormat, nullptr, r, g, b, a); }
|
||||
{ SDL_GetRGBA(pixel, myPixelFormat, r, g, b, a); }
|
||||
|
||||
/**
|
||||
This method is called to map a given R/G/B triple to the screen palette.
|
||||
|
@ -121,7 +121,7 @@ class FBBackendSDL : public FBBackend
|
|||
@param b The blue component of the color.
|
||||
*/
|
||||
uInt32 mapRGB(uInt8 r, uInt8 g, uInt8 b) const override
|
||||
{ return SDL_MapRGB(myPixelFormat, nullptr, r, g, b); }
|
||||
{ return SDL_MapRGB(myPixelFormat, r, g, b); }
|
||||
|
||||
/**
|
||||
This method is called to map a given R/G/B/A triple to the screen palette.
|
||||
|
@ -132,7 +132,7 @@ class FBBackendSDL : public FBBackend
|
|||
@param a The alpha component of the color.
|
||||
*/
|
||||
uInt32 mapRGBA(uInt8 r, uInt8 g, uInt8 b, uInt8 a) const override
|
||||
{ return SDL_MapRGBA(myPixelFormat, nullptr, r, g, b, a); }
|
||||
{ return SDL_MapRGBA(myPixelFormat, r, g, b, a); }
|
||||
|
||||
/**
|
||||
This method is called to get a copy of the specified ARGB data from the
|
||||
|
@ -167,9 +167,10 @@ class FBBackendSDL : public FBBackend
|
|||
This method is called to query the video hardware for the index
|
||||
of the display the current window is displayed on
|
||||
|
||||
@return the current display index or a 0 if no window is displayed
|
||||
@return the current display index or a negative value if no
|
||||
window is displayed
|
||||
*/
|
||||
uInt32 getCurrentDisplayID() const override;
|
||||
Int32 getCurrentDisplayIndex() const override;
|
||||
|
||||
/**
|
||||
Clear the frame buffer.
|
||||
|
@ -222,11 +223,6 @@ class FBBackendSDL : public FBBackend
|
|||
*/
|
||||
void grabMouse(bool grab) override;
|
||||
|
||||
/**
|
||||
Enable/disable text events (distinct from single-key events).
|
||||
*/
|
||||
void enableTextEvents(bool enable) override;
|
||||
|
||||
/**
|
||||
This method is called to provide information about the backend.
|
||||
*/
|
||||
|
@ -250,20 +246,6 @@ class FBBackendSDL : public FBBackend
|
|||
*/
|
||||
int refreshRate() const override;
|
||||
|
||||
/**
|
||||
Checks if the OS theme is set to light.
|
||||
*/
|
||||
bool isLightTheme() const override {
|
||||
return SDL_GetSystemTheme() == SDL_SYSTEM_THEME_LIGHT;
|
||||
}
|
||||
|
||||
/**
|
||||
Checks if the OS theme is set to dark.
|
||||
*/
|
||||
bool isDarkTheme() const override {
|
||||
return SDL_GetSystemTheme() == SDL_SYSTEM_THEME_DARK;
|
||||
}
|
||||
|
||||
/**
|
||||
Checks if the display refresh rate should be adapted to game refresh
|
||||
rate in (real) fullscreen mode.
|
||||
|
@ -304,18 +286,7 @@ class FBBackendSDL : public FBBackend
|
|||
SDL_Renderer* myRenderer{nullptr};
|
||||
|
||||
// Used by mapRGB (when palettes are created)
|
||||
const SDL_PixelFormatDetails* myPixelFormat{nullptr};
|
||||
|
||||
// Are we in fullscreen mode?
|
||||
// There seem to be issues with creating the window and renderer separately,
|
||||
// and doing so means we can't query the window for fullscreen status
|
||||
// So we do it at window creation and cache the result
|
||||
// TODO: Is this a bug in SDL?
|
||||
bool myIsFullscreen{false};
|
||||
|
||||
// Text events are sometimes enabled before a window exists
|
||||
// So we cache the request here, and honour it after the window has been created
|
||||
bool myTextEventsEnabled{false};
|
||||
SDL_PixelFormat* myPixelFormat{nullptr};
|
||||
|
||||
// Center setting of current window
|
||||
bool myCenter{false};
|
||||
|
@ -327,18 +298,18 @@ class FBBackendSDL : public FBBackend
|
|||
string myScreenTitle;
|
||||
|
||||
// Number of displays
|
||||
uInt32 myNumDisplays{0};
|
||||
int myNumDisplays{1};
|
||||
|
||||
// Window and renderer dimensions
|
||||
int myWindowW{0}, myWindowH{0}, myRenderW{0}, myRenderH{0};
|
||||
|
||||
private:
|
||||
// Following constructors and assignment operators not supported
|
||||
FBBackendSDL() = delete;
|
||||
FBBackendSDL(const FBBackendSDL&) = delete;
|
||||
FBBackendSDL(FBBackendSDL&&) = delete;
|
||||
FBBackendSDL& operator=(const FBBackendSDL&) = delete;
|
||||
FBBackendSDL& operator=(FBBackendSDL&&) = delete;
|
||||
FBBackendSDL2() = delete;
|
||||
FBBackendSDL2(const FBBackendSDL2&) = delete;
|
||||
FBBackendSDL2(FBBackendSDL2&&) = delete;
|
||||
FBBackendSDL2& operator=(const FBBackendSDL2&) = delete;
|
||||
FBBackendSDL2& operator=(FBBackendSDL2&&) = delete;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -8,14 +8,14 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//============================================================================
|
||||
|
||||
#include "FBSurfaceSDL.hxx"
|
||||
#include "FBSurfaceSDL2.hxx"
|
||||
|
||||
#include "Logger.hxx"
|
||||
#include "ThreadDebugging.hxx"
|
||||
|
@ -41,7 +41,7 @@ namespace {
|
|||
} // namespace
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
FBSurfaceSDL::FBSurfaceSDL(FBBackendSDL& backend,
|
||||
FBSurfaceSDL2::FBSurfaceSDL2(FBBackendSDL2& backend,
|
||||
uInt32 width, uInt32 height,
|
||||
ScalingInterpolation inter,
|
||||
const uInt32* staticData)
|
||||
|
@ -53,19 +53,19 @@ FBSurfaceSDL::FBSurfaceSDL(FBBackendSDL& backend,
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
FBSurfaceSDL::~FBSurfaceSDL()
|
||||
FBSurfaceSDL2::~FBSurfaceSDL2()
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
if(mySurface)
|
||||
{
|
||||
SDL_DestroySurface(mySurface);
|
||||
SDL_FreeSurface(mySurface);
|
||||
mySurface = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FBSurfaceSDL::fillRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h, ColorId color)
|
||||
void FBSurfaceSDL2::fillRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h, ColorId color)
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
|
@ -75,49 +75,49 @@ void FBSurfaceSDL::fillRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h, ColorId colo
|
|||
tmp.y = y;
|
||||
tmp.w = w;
|
||||
tmp.h = h;
|
||||
SDL_FillSurfaceRect(mySurface, &tmp, myPalette[color]);
|
||||
SDL_FillRect(mySurface, &tmp, myPalette[color]);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt32 FBSurfaceSDL::width() const
|
||||
uInt32 FBSurfaceSDL2::width() const
|
||||
{
|
||||
return mySurface->w;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt32 FBSurfaceSDL::height() const
|
||||
uInt32 FBSurfaceSDL2::height() const
|
||||
{
|
||||
return mySurface->h;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
const Common::Rect& FBSurfaceSDL::srcRect() const
|
||||
const Common::Rect& FBSurfaceSDL2::srcRect() const
|
||||
{
|
||||
return mySrcGUIR;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
const Common::Rect& FBSurfaceSDL::dstRect() const
|
||||
const Common::Rect& FBSurfaceSDL2::dstRect() const
|
||||
{
|
||||
return myDstGUIR;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FBSurfaceSDL::setSrcPos(uInt32 x, uInt32 y)
|
||||
void FBSurfaceSDL2::setSrcPos(uInt32 x, uInt32 y)
|
||||
{
|
||||
if(setSrcPosInternal(x, y))
|
||||
reinitializeBlitter();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FBSurfaceSDL::setSrcSize(uInt32 w, uInt32 h)
|
||||
void FBSurfaceSDL2::setSrcSize(uInt32 w, uInt32 h)
|
||||
{
|
||||
if(setSrcSizeInternal(w, h))
|
||||
reinitializeBlitter();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FBSurfaceSDL::setSrcRect(const Common::Rect& r)
|
||||
void FBSurfaceSDL2::setSrcRect(const Common::Rect& r)
|
||||
{
|
||||
const bool posChanged = setSrcPosInternal(r.x(), r.y()),
|
||||
sizeChanged = setSrcSizeInternal(r.w(), r.h());
|
||||
|
@ -127,21 +127,21 @@ void FBSurfaceSDL::setSrcRect(const Common::Rect& r)
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FBSurfaceSDL::setDstPos(uInt32 x, uInt32 y)
|
||||
void FBSurfaceSDL2::setDstPos(uInt32 x, uInt32 y)
|
||||
{
|
||||
if(setDstPosInternal(x, y))
|
||||
reinitializeBlitter();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FBSurfaceSDL::setDstSize(uInt32 w, uInt32 h)
|
||||
void FBSurfaceSDL2::setDstSize(uInt32 w, uInt32 h)
|
||||
{
|
||||
if(setDstSizeInternal(w, h))
|
||||
reinitializeBlitter();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FBSurfaceSDL::setDstRect(const Common::Rect& r)
|
||||
void FBSurfaceSDL2::setDstRect(const Common::Rect& r)
|
||||
{
|
||||
const bool posChanged = setDstPosInternal(r.x(), r.y()),
|
||||
sizeChanged = setDstSizeInternal(r.w(), r.h());
|
||||
|
@ -151,23 +151,22 @@ void FBSurfaceSDL::setDstRect(const Common::Rect& r)
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FBSurfaceSDL::setVisible(bool visible)
|
||||
void FBSurfaceSDL2::setVisible(bool visible)
|
||||
{
|
||||
myIsVisible = visible;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FBSurfaceSDL::translateCoords(Int32& x, Int32& y) const
|
||||
void FBSurfaceSDL2::translateCoords(Int32& x, Int32& y) const
|
||||
{
|
||||
x -= myDstR.x; x /= myDstR.w / mySrcR.w;
|
||||
y -= myDstR.y; y /= myDstR.h / mySrcR.h;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool FBSurfaceSDL::render()
|
||||
bool FBSurfaceSDL2::render()
|
||||
{
|
||||
if(!myBlitter)
|
||||
reinitializeBlitter();
|
||||
if (!myBlitter) reinitializeBlitter();
|
||||
|
||||
if(myIsVisible && myBlitter)
|
||||
{
|
||||
|
@ -179,15 +178,15 @@ bool FBSurfaceSDL::render()
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FBSurfaceSDL::invalidate()
|
||||
void FBSurfaceSDL2::invalidate()
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
SDL_FillSurfaceRect(mySurface, nullptr, 0);
|
||||
SDL_FillRect(mySurface, nullptr, 0);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FBSurfaceSDL::invalidateRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h)
|
||||
void FBSurfaceSDL2::invalidateRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h)
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
|
@ -199,22 +198,22 @@ void FBSurfaceSDL::invalidateRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h)
|
|||
tmp.h = h;
|
||||
// Note: Transparency has to be 0 to clear the rectangle foreground
|
||||
// without affecting the background display.
|
||||
SDL_FillSurfaceRect(mySurface, &tmp, 0);
|
||||
SDL_FillRect(mySurface, &tmp, 0);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FBSurfaceSDL::reload()
|
||||
void FBSurfaceSDL2::reload()
|
||||
{
|
||||
reinitializeBlitter(true);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FBSurfaceSDL::resize(uInt32 width, uInt32 height)
|
||||
void FBSurfaceSDL2::resize(uInt32 width, uInt32 height)
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
if(mySurface)
|
||||
SDL_DestroySurface(mySurface);
|
||||
SDL_FreeSurface(mySurface);
|
||||
|
||||
// NOTE: Currently, a resize changes a 'static' surface to 'streaming'
|
||||
// No code currently does this, but we should at least check for it
|
||||
|
@ -225,13 +224,17 @@ void FBSurfaceSDL::resize(uInt32 width, uInt32 height)
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FBSurfaceSDL::createSurface(uInt32 width, uInt32 height, const uInt32* data)
|
||||
void FBSurfaceSDL2::createSurface(uInt32 width, uInt32 height,
|
||||
const uInt32* data)
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
// Create a surface in the same format as the parent GL class
|
||||
const SDL_PixelFormatDetails& pf = myBackend.pixelFormat();
|
||||
mySurface = SDL_CreateSurface(width, height, pf.format);
|
||||
const SDL_PixelFormat& pf = myBackend.pixelFormat();
|
||||
|
||||
mySurface = SDL_CreateRGBSurface(0, width, height,
|
||||
pf.BitsPerPixel, pf.Rmask, pf.Gmask, pf.Bmask, pf.Amask);
|
||||
//SDL_SetSurfaceBlendMode(mySurface, SDL_BLENDMODE_ADD); // default: SDL_BLENDMODE_BLEND
|
||||
|
||||
// We start out with the src and dst rectangles containing the same
|
||||
// dimensions, indicating no scaling or re-positioning
|
||||
|
@ -243,7 +246,7 @@ void FBSurfaceSDL::createSurface(uInt32 width, uInt32 height, const uInt32* data
|
|||
////////////////////////////////////////////////////
|
||||
// These *must* be set for the parent class
|
||||
myPixels = static_cast<uInt32*>(mySurface->pixels);
|
||||
myPitch = mySurface->pitch / pf.bytes_per_pixel;
|
||||
myPitch = mySurface->pitch / pf.BytesPerPixel;
|
||||
////////////////////////////////////////////////////
|
||||
|
||||
myIsStatic = data != nullptr;
|
||||
|
@ -255,40 +258,30 @@ void FBSurfaceSDL::createSurface(uInt32 width, uInt32 height, const uInt32* data
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FBSurfaceSDL::reinitializeBlitter(bool force)
|
||||
void FBSurfaceSDL2::reinitializeBlitter(bool force)
|
||||
{
|
||||
if(force)
|
||||
if (force)
|
||||
myBlitter.reset();
|
||||
|
||||
if(!myBlitter && myBackend.isInitialized())
|
||||
if (!myBlitter && myBackend.isInitialized())
|
||||
myBlitter = BlitterFactory::createBlitter(
|
||||
myBackend, scalingAlgorithm(myInterpolationMode));
|
||||
|
||||
if(myBlitter)
|
||||
myBlitter->reinitialize(mySrcR, myDstR, myEnableBlend, myBlendLevel,
|
||||
if (myBlitter)
|
||||
myBlitter->reinitialize(mySrcR, myDstR, myAttributes,
|
||||
myIsStatic ? mySurface : nullptr);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FBSurfaceSDL::setBlendLevel(uInt32 percent)
|
||||
void FBSurfaceSDL2::applyAttributes()
|
||||
{
|
||||
myBlendLevel = BSPF::clamp(percent, 0U, 100U);
|
||||
|
||||
reinitializeBlitter();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FBSurfaceSDL::enableBlend(bool enableBlend)
|
||||
void FBSurfaceSDL2::setScalingInterpolation(ScalingInterpolation interpolation)
|
||||
{
|
||||
myEnableBlend = enableBlend;
|
||||
|
||||
reinitializeBlitter();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FBSurfaceSDL::setScalingInterpolation(ScalingInterpolation interpolation)
|
||||
{
|
||||
if(interpolation == ScalingInterpolation::sharp &&
|
||||
if (interpolation == ScalingInterpolation::sharp &&
|
||||
(
|
||||
static_cast<int>(mySrcGUIR.h()) >= myBackend.scaleY(myDstGUIR.h()) ||
|
||||
static_cast<int>(mySrcGUIR.w()) >= myBackend.scaleX(myDstGUIR.w())
|
||||
|
@ -296,8 +289,7 @@ void FBSurfaceSDL::setScalingInterpolation(ScalingInterpolation interpolation)
|
|||
)
|
||||
interpolation = ScalingInterpolation::blur;
|
||||
|
||||
if(interpolation == myInterpolationMode)
|
||||
return;
|
||||
if (interpolation == myInterpolationMode) return;
|
||||
|
||||
myInterpolationMode = interpolation;
|
||||
reload();
|
|
@ -8,33 +8,33 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//============================================================================
|
||||
|
||||
#ifndef FBSURFACE_SDL_HXX
|
||||
#define FBSURFACE_SDL_HXX
|
||||
#ifndef FBSURFACE_SDL2_HXX
|
||||
#define FBSURFACE_SDL2_HXX
|
||||
|
||||
#include "bspf.hxx"
|
||||
#include "FBSurface.hxx"
|
||||
#include "FBBackendSDL.hxx"
|
||||
#include "FBBackendSDL2.hxx"
|
||||
#include "sdl_blitter/Blitter.hxx"
|
||||
|
||||
/**
|
||||
An FBSurface suitable for the SDL Render2D API, making use of hardware
|
||||
An FBSurface suitable for the SDL2 Render2D API, making use of hardware
|
||||
acceleration behind the scenes.
|
||||
|
||||
@author Stephen Anthony
|
||||
*/
|
||||
class FBSurfaceSDL : public FBSurface
|
||||
class FBSurfaceSDL2 : public FBSurface
|
||||
{
|
||||
public:
|
||||
FBSurfaceSDL(FBBackendSDL& backend, uInt32 width, uInt32 height,
|
||||
FBSurfaceSDL2(FBBackendSDL2& backend, uInt32 width, uInt32 height,
|
||||
ScalingInterpolation inter, const uInt32* staticData);
|
||||
~FBSurfaceSDL() override;
|
||||
~FBSurfaceSDL2() override;
|
||||
|
||||
// Most of the surface drawing primitives are implemented in FBSurface;
|
||||
// the ones implemented here use SDL-specific code for extra performance
|
||||
|
@ -63,13 +63,14 @@ class FBSurfaceSDL : public FBSurface
|
|||
void reload() override;
|
||||
void resize(uInt32 width, uInt32 height) override;
|
||||
|
||||
void enableBlend(bool enable) override;
|
||||
void setBlendLevel(uInt32 percent) override;
|
||||
void setScalingInterpolation(ScalingInterpolation) override;
|
||||
|
||||
protected:
|
||||
void applyAttributes() override;
|
||||
|
||||
private:
|
||||
bool setSrcPosInternal(uInt32 x, uInt32 y) {
|
||||
if(std::cmp_not_equal(x, mySrcR.x) || std::cmp_not_equal(y, mySrcR.y))
|
||||
if(x != static_cast<uInt32>(mySrcR.x) || y != static_cast<uInt32>(mySrcR.y))
|
||||
{
|
||||
mySrcR.x = x; mySrcR.y = y;
|
||||
mySrcGUIR.moveTo(x, y);
|
||||
|
@ -78,7 +79,7 @@ class FBSurfaceSDL : public FBSurface
|
|||
return false;
|
||||
}
|
||||
bool setSrcSizeInternal(uInt32 w, uInt32 h) {
|
||||
if(std::cmp_not_equal(w, mySrcR.w) || std::cmp_not_equal(h, mySrcR.h))
|
||||
if(w != static_cast<uInt32>(mySrcR.w) || h != static_cast<uInt32>(mySrcR.h))
|
||||
{
|
||||
mySrcR.w = w; mySrcR.h = h;
|
||||
mySrcGUIR.setWidth(w); mySrcGUIR.setHeight(h);
|
||||
|
@ -87,7 +88,7 @@ class FBSurfaceSDL : public FBSurface
|
|||
return false;
|
||||
}
|
||||
bool setDstPosInternal(uInt32 x, uInt32 y) {
|
||||
if(std::cmp_not_equal(x, myDstR.x) || std::cmp_not_equal(y, myDstR.y))
|
||||
if(x != static_cast<uInt32>(myDstR.x) || y != static_cast<uInt32>(myDstR.y))
|
||||
{
|
||||
myDstR.x = x; myDstR.y = y;
|
||||
myDstGUIR.moveTo(x, y);
|
||||
|
@ -96,7 +97,7 @@ class FBSurfaceSDL : public FBSurface
|
|||
return false;
|
||||
}
|
||||
bool setDstSizeInternal(uInt32 w, uInt32 h) {
|
||||
if(std::cmp_not_equal(w, myDstR.w) || std::cmp_not_equal(h, myDstR.h))
|
||||
if(w != static_cast<uInt32>(myDstR.w) || h != static_cast<uInt32>(myDstR.h))
|
||||
{
|
||||
myDstR.w = w; myDstR.h = h;
|
||||
myDstGUIR.setWidth(w); myDstGUIR.setHeight(h);
|
||||
|
@ -110,17 +111,18 @@ class FBSurfaceSDL : public FBSurface
|
|||
void reinitializeBlitter(bool force = false);
|
||||
|
||||
// Following constructors and assignment operators not supported
|
||||
FBSurfaceSDL() = delete;
|
||||
FBSurfaceSDL(const FBSurfaceSDL&) = delete;
|
||||
FBSurfaceSDL(FBSurfaceSDL&&) = delete;
|
||||
FBSurfaceSDL& operator=(const FBSurfaceSDL&) = delete;
|
||||
FBSurfaceSDL& operator=(FBSurfaceSDL&&) = delete;
|
||||
FBSurfaceSDL2() = delete;
|
||||
FBSurfaceSDL2(const FBSurfaceSDL2&) = delete;
|
||||
FBSurfaceSDL2(FBSurfaceSDL2&&) = delete;
|
||||
FBSurfaceSDL2& operator=(const FBSurfaceSDL2&) = delete;
|
||||
FBSurfaceSDL2& operator=(FBSurfaceSDL2&&) = delete;
|
||||
|
||||
private:
|
||||
FBBackendSDL& myBackend;
|
||||
FBBackendSDL2& myBackend;
|
||||
|
||||
unique_ptr<Blitter> myBlitter;
|
||||
ScalingInterpolation myInterpolationMode{ScalingInterpolation::none};
|
||||
ScalingInterpolation myInterpolationMode
|
||||
{ScalingInterpolation::none};
|
||||
|
||||
SDL_Surface* mySurface{nullptr};
|
||||
SDL_Rect mySrcR{-1, -1, -1, -1}, myDstR{-1, -1, -1, -1};
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
@ -381,7 +381,8 @@ string HighScoresManager::formattedScore(Int32 score, Int32 width) const
|
|||
|
||||
if(scoreBCD(jprops))
|
||||
{
|
||||
digits = std::max(width, digits);
|
||||
if(width > digits)
|
||||
digits = width;
|
||||
buf << std::setw(digits) << std::setfill(' ') << score;
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
@ -132,7 +132,7 @@ class HighScoresManager
|
|||
|
||||
@return The number of score address bytes
|
||||
*/
|
||||
static constexpr uInt32 numAddrBytes(Int32 digits, Int32 trailing) {
|
||||
static uInt32 numAddrBytes(Int32 digits, Int32 trailing) {
|
||||
return (digits - trailing + 1) / 2;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
@ -188,7 +188,8 @@ json JoyMap::saveMapping(EventMode mode) const
|
|||
using MapType = std::pair<JoyMapping, Event::Type>;
|
||||
std::vector<MapType> sortedMap(myMap.begin(), myMap.end());
|
||||
|
||||
std::ranges::sort(sortedMap, [](const MapType& a, const MapType& b)
|
||||
std::sort(sortedMap.begin(), sortedMap.end(),
|
||||
[](const MapType& a, const MapType& b)
|
||||
{
|
||||
// Event::Type first
|
||||
if(a.first.button != b.first.button)
|
||||
|
@ -284,17 +285,17 @@ int JoyMap::loadMapping(const json& eventMappings, EventMode mode)
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
json JoyMap::convertLegacyMapping(string lst)
|
||||
json JoyMap::convertLegacyMapping(string list)
|
||||
{
|
||||
json eventMappings = json::array();
|
||||
|
||||
// Since istringstream swallows whitespace, we have to make the
|
||||
// delimiters be spaces
|
||||
std::ranges::replace(lst, '|', ' ');
|
||||
std::ranges::replace(lst, ':', ' ');
|
||||
std::ranges::replace(lst, ',', ' ');
|
||||
std::replace(list.begin(), list.end(), '|', ' ');
|
||||
std::replace(list.begin(), list.end(), ':', ' ');
|
||||
std::replace(list.begin(), list.end(), ',', ' ');
|
||||
|
||||
istringstream buf(lst);
|
||||
istringstream buf(list);
|
||||
int event = 0, button = 0, axis = 0, adir = 0, hat = 0, hdir = 0;
|
||||
|
||||
while(buf >> event && buf >> button
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
@ -112,7 +112,7 @@ class JoyMap
|
|||
nlohmann::json saveMapping(EventMode mode) const;
|
||||
int loadMapping(const nlohmann::json& eventMappings, EventMode mode);
|
||||
|
||||
static nlohmann::json convertLegacyMapping(string lst);
|
||||
static nlohmann::json convertLegacyMapping(string list);
|
||||
|
||||
/** Erase all mappings for given mode */
|
||||
void eraseMode(EventMode mode);
|
||||
|
@ -129,10 +129,10 @@ class JoyMap
|
|||
size_t operator()(const JoyMapping& m)const {
|
||||
return std::hash<uInt64>()((static_cast<uInt64>(m.mode)) // 3 bits
|
||||
+ ((static_cast<uInt64>(m.button)) * 7) // 3 bits
|
||||
+ (((static_cast<uInt64>(m.axis)) << 0) // 3 bits
|
||||
| ((static_cast<uInt64>(m.adir)) << 3) // 2 bits
|
||||
| ((static_cast<uInt64>(m.hat )) << 5) // 1 bit
|
||||
| ((static_cast<uInt64>(m.hdir)) << 6) // 2 bits
|
||||
+ (((static_cast<uInt64>(m.axis)) << 0) // 2 bits
|
||||
| ((static_cast<uInt64>(m.adir)) << 2) // 2 bits
|
||||
| ((static_cast<uInt64>(m.hat )) << 4) // 1 bit
|
||||
| ((static_cast<uInt64>(m.hdir)) << 5) // 2 bits
|
||||
) * 61
|
||||
);
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
@ -43,7 +43,8 @@ namespace {
|
|||
StellaMod::KBDM_RGUI,
|
||||
StellaMod::KBDM_NUM,
|
||||
StellaMod::KBDM_CAPS,
|
||||
StellaMod::KBDM_MODE
|
||||
StellaMod::KBDM_MODE,
|
||||
StellaMod::KBDM_RESERVED
|
||||
}) {
|
||||
if((mask & mod) != mod) continue;
|
||||
|
||||
|
@ -221,7 +222,8 @@ json KeyMap::saveMapping(EventMode mode) const
|
|||
using MapType = std::pair<Mapping, Event::Type>;
|
||||
std::vector<MapType> sortedMap(myMap.begin(), myMap.end());
|
||||
|
||||
std::ranges::sort(sortedMap, [](const MapType& a, const MapType& b)
|
||||
std::sort(sortedMap.begin(), sortedMap.end(),
|
||||
[](const MapType& a, const MapType& b)
|
||||
{
|
||||
// Event::Type first
|
||||
if(a.first.key != b.first.key)
|
||||
|
@ -288,11 +290,11 @@ json KeyMap::convertLegacyMapping(string_view lm)
|
|||
|
||||
// Since istringstream swallows whitespace, we have to make the
|
||||
// delimiters be spaces
|
||||
string lst{lm};
|
||||
std::ranges::replace(lst, '|', ' ');
|
||||
std::ranges::replace(lst, ':', ' ');
|
||||
std::ranges::replace(lst, ',', ' ');
|
||||
istringstream buf(lst);
|
||||
string list{lm};
|
||||
std::replace(list.begin(), list.end(), '|', ' ');
|
||||
std::replace(list.begin(), list.end(), ':', ' ');
|
||||
std::replace(list.begin(), list.end(), ',', ' ');
|
||||
istringstream buf(list);
|
||||
int event = 0, key = 0, mod = 0;
|
||||
|
||||
while(buf >> event && buf >> key && buf >> mod)
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
@ -17,10 +17,6 @@
|
|||
|
||||
#include "Logger.hxx"
|
||||
|
||||
#ifdef __LIB_RETRO__
|
||||
extern void libretro_logger(int log_level, const char *string);
|
||||
#endif
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Logger& Logger::instance()
|
||||
{
|
||||
|
@ -57,10 +53,6 @@ void Logger::logMessage(string_view message, Level level)
|
|||
{
|
||||
const std::lock_guard<std::mutex> lock(mutex);
|
||||
|
||||
#ifdef __LIB_RETRO__
|
||||
libretro_logger(static_cast<int>(level), string{message}.c_str());
|
||||
#endif
|
||||
|
||||
if(level == Logger::Level::ERR)
|
||||
{
|
||||
cout << message << '\n' << std::flush;
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
@ -28,13 +28,21 @@
|
|||
#include "SerialPort.hxx"
|
||||
#if defined(BSPF_UNIX)
|
||||
#include "SerialPortUNIX.hxx"
|
||||
#if defined(RETRON77)
|
||||
#include "SettingsR77.hxx"
|
||||
#include "OSystemR77.hxx"
|
||||
#else
|
||||
#include "OSystemUNIX.hxx"
|
||||
#endif
|
||||
#elif defined(BSPF_WINDOWS)
|
||||
#include "SerialPortWINDOWS.hxx"
|
||||
#include "OSystemWINDOWS.hxx"
|
||||
#elif defined(BSPF_MACOS)
|
||||
#include "SerialPortMACOS.hxx"
|
||||
#include "OSystemMACOS.hxx"
|
||||
extern "C" {
|
||||
int stellaMain(int argc, char* argv[]);
|
||||
}
|
||||
#elif defined(__LIB_RETRO__)
|
||||
#include "OSystemLIBRETRO.hxx"
|
||||
#else
|
||||
|
@ -45,8 +53,8 @@
|
|||
#include "EventHandlerLIBRETRO.hxx"
|
||||
#include "FBBackendLIBRETRO.hxx"
|
||||
#elif defined(SDL_SUPPORT)
|
||||
#include "EventHandlerSDL.hxx"
|
||||
#include "FBBackendSDL.hxx"
|
||||
#include "EventHandlerSDL2.hxx"
|
||||
#include "FBBackendSDL2.hxx"
|
||||
#else
|
||||
#error Unsupported backend!
|
||||
#endif
|
||||
|
@ -55,7 +63,7 @@
|
|||
#if defined(__LIB_RETRO__)
|
||||
#include "SoundLIBRETRO.hxx"
|
||||
#elif defined(SDL_SUPPORT)
|
||||
#include "SoundSDL.hxx"
|
||||
#include "SoundSDL2.hxx"
|
||||
#else
|
||||
#include "SoundNull.hxx"
|
||||
#endif
|
||||
|
@ -70,6 +78,10 @@ class AudioSettings;
|
|||
implementations for the various ports of Stella, and always returns a
|
||||
valid object based on the specific port and restrictions on that port.
|
||||
|
||||
As of SDL2, this code is greatly simplified. However, it remains here
|
||||
in case we ever have multiple backend implementations again (should
|
||||
not be necessary since SDL2 covers this nicely).
|
||||
|
||||
@author Stephen Anthony
|
||||
*/
|
||||
class MediaFactory
|
||||
|
@ -78,7 +90,11 @@ class MediaFactory
|
|||
static unique_ptr<OSystem> createOSystem()
|
||||
{
|
||||
#if defined(BSPF_UNIX)
|
||||
#if defined(RETRON77)
|
||||
return make_unique<OSystemR77>();
|
||||
#else
|
||||
return make_unique<OSystemUNIX>();
|
||||
#endif
|
||||
#elif defined(BSPF_WINDOWS)
|
||||
return make_unique<OSystemWINDOWS>();
|
||||
#elif defined(BSPF_MACOS)
|
||||
|
@ -92,7 +108,11 @@ class MediaFactory
|
|||
|
||||
static unique_ptr<Settings> createSettings()
|
||||
{
|
||||
#ifdef RETRON77
|
||||
return make_unique<SettingsR77>();
|
||||
#else
|
||||
return make_unique<Settings>();
|
||||
#endif
|
||||
}
|
||||
|
||||
static unique_ptr<SerialPort> createSerialPort()
|
||||
|
@ -113,7 +133,7 @@ class MediaFactory
|
|||
#if defined(__LIB_RETRO__)
|
||||
return make_unique<FBBackendLIBRETRO>(osystem);
|
||||
#elif defined(SDL_SUPPORT)
|
||||
return make_unique<FBBackendSDL>(osystem);
|
||||
return make_unique<FBBackendSDL2>(osystem);
|
||||
#else
|
||||
#error Unsupported platform for FrameBuffer!
|
||||
#endif
|
||||
|
@ -125,7 +145,7 @@ class MediaFactory
|
|||
#if defined(__LIB_RETRO__)
|
||||
return make_unique<SoundLIBRETRO>(osystem, audioSettings);
|
||||
#elif defined(SOUND_SUPPORT) && defined(SDL_SUPPORT)
|
||||
return make_unique<SoundSDL>(osystem, audioSettings);
|
||||
return make_unique<SoundSDL2>(osystem, audioSettings);
|
||||
#else
|
||||
return make_unique<SoundNull>(osystem);
|
||||
#endif
|
||||
|
@ -139,7 +159,7 @@ class MediaFactory
|
|||
#if defined(__LIB_RETRO__)
|
||||
return make_unique<EventHandlerLIBRETRO>(osystem);
|
||||
#elif defined(SDL_SUPPORT)
|
||||
return make_unique<EventHandlerSDL>(osystem);
|
||||
return make_unique<EventHandlerSDL2>(osystem);
|
||||
#else
|
||||
#error Unsupported platform for EventHandler!
|
||||
#endif
|
||||
|
@ -161,6 +181,15 @@ class MediaFactory
|
|||
#endif
|
||||
}
|
||||
|
||||
static bool supportsURL()
|
||||
{
|
||||
#if defined(SDL_SUPPORT)
|
||||
return SDLSupportsURL();
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool openURL(const string& url)
|
||||
{
|
||||
#if defined(SDL_SUPPORT)
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
@ -405,11 +405,18 @@ void PhysicalJoystickHandler::setStickDefaultMapping(
|
|||
setDefaultAction(stick, item, event, EventMode::kDrivingMode, updateDefaults);
|
||||
}
|
||||
|
||||
#if defined(RETRON77)
|
||||
constexpr bool retron77 = true;
|
||||
#else
|
||||
constexpr bool retron77 = false;
|
||||
#endif
|
||||
|
||||
// Regular joysticks can only be used by one player at a time,
|
||||
// so we need to separate the paddles onto different
|
||||
// devices. The Stelladaptor and 2600-daptor controllers support
|
||||
// two players each when used as paddles, so are different.
|
||||
const int paddlesPerJoystick = (j->type == PhysicalJoystick::Type::REGULAR) ? 1 : 2;
|
||||
// devices. The R77 controllers support two players each when
|
||||
// used as paddles, so are different. Similarly, stelladaptors
|
||||
// and 2600-daptors support two players natively.
|
||||
const int paddlesPerJoystick = (j->type == PhysicalJoystick::Type::REGULAR && !retron77) ? 1 : 2;
|
||||
|
||||
if(paddlesPerJoystick == 2)
|
||||
{
|
||||
|
@ -1348,11 +1355,17 @@ PhysicalJoystickHandler::EventMappingArray PhysicalJoystickHandler::DefaultRight
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
PhysicalJoystickHandler::EventMappingArray PhysicalJoystickHandler::DefaultLeftPaddlesMapping = {
|
||||
{Event::LeftPaddleAAnalog, JOY_CTRL_NONE, JoyAxis::X, JoyDir::ANALOG},
|
||||
#if defined(RETRON77)
|
||||
{Event::LeftPaddleAAnalog, JOY_CTRL_NONE, JoyAxis::Z, JoyDir::ANALOG},
|
||||
#endif
|
||||
// Current code does NOT allow digital and anlog events on the same axis at the same time
|
||||
//{Event::LeftPaddleADecrease, JOY_CTRL_NONE, JoyAxis::X, JoyDir::POS},
|
||||
//{Event::LeftPaddleAIncrease, JOY_CTRL_NONE, JoyAxis::X, JoyDir::NEG},
|
||||
{Event::LeftPaddleAFire, 0},
|
||||
{Event::LeftPaddleBAnalog, JOY_CTRL_NONE, JoyAxis::Y, JoyDir::ANALOG},
|
||||
#if defined(RETRON77)
|
||||
{Event::LeftPaddleBAnalog, JOY_CTRL_NONE, JoyAxis::A3, JoyDir::ANALOG},
|
||||
#endif
|
||||
// Current code does NOT allow digital and anlog events on the same axis at the same
|
||||
//{Event::LeftPaddleBDecrease, JOY_CTRL_NONE, JoyAxis::Y, JoyDir::POS},
|
||||
//{Event::LeftPaddleBIncrease, JOY_CTRL_NONE, JoyAxis::Y, JoyDir::NEG},
|
||||
|
@ -1362,11 +1375,17 @@ PhysicalJoystickHandler::EventMappingArray PhysicalJoystickHandler::DefaultLeftP
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
PhysicalJoystickHandler::EventMappingArray PhysicalJoystickHandler::DefaultRightPaddlesMapping = {
|
||||
{Event::RightPaddleAAnalog, JOY_CTRL_NONE, JoyAxis::X, JoyDir::ANALOG},
|
||||
#if defined(RETRON77)
|
||||
{Event::RightPaddleAAnalog, JOY_CTRL_NONE, JoyAxis::Z, JoyDir::ANALOG},
|
||||
#endif
|
||||
// Current code does NOT allow digital and anlog events on the same axis at the same
|
||||
//{Event::RightPaddleADecrease, JOY_CTRL_NONE, JoyAxis::X, JoyDir::POS},
|
||||
//{Event::RightPaddleAIncrease, JOY_CTRL_NONE, JoyAxis::X, JoyDir::NEG},
|
||||
{Event::RightPaddleAFire, 0},
|
||||
{Event::RightPaddleBAnalog, JOY_CTRL_NONE, JoyAxis::Y, JoyDir::ANALOG},
|
||||
#if defined(RETRON77)
|
||||
{Event::RightPaddleBAnalog, JOY_CTRL_NONE, JoyAxis::A3, JoyDir::ANALOG},
|
||||
#endif
|
||||
// Current code does NOT allow digital and anlog events on the same axis at the same
|
||||
//{Event::RightPaddleBDecrease,JOY_CTRL_NONE, JoyAxis::Y, JoyDir::POS},
|
||||
//{Event::RightPaddleBIncrease,JOY_CTRL_NONE, JoyAxis::Y, JoyDir::NEG},
|
||||
|
@ -1466,6 +1485,14 @@ PhysicalJoystickHandler::EventMappingArray
|
|||
PhysicalJoystickHandler::DefaultCommonMapping = {
|
||||
// valid for all joysticks
|
||||
// Note: buttons 0..2 are used by controllers!
|
||||
#if defined(RETRON77)
|
||||
{Event::CmdMenuMode, 3}, // Button "Y" / "4"
|
||||
{Event::ExitMode, 4}, // Left Shoulder Button
|
||||
{Event::OptionsMenuMode, 5}, // Right Shoulder Button
|
||||
{Event::RewindPause, 7}, // Right Trigger Button
|
||||
{Event::ConsoleSelect, 8}, // Button "Select"
|
||||
{Event::ConsoleReset, 9}, // Button "Start"
|
||||
#else
|
||||
{Event::ConsoleSelect, 8}, // Button "Select"
|
||||
{Event::ConsoleReset, 9}, // Button "Start"
|
||||
{Event::ConsoleColorToggle, 3}, // Button "Y" / "4"
|
||||
|
@ -1473,6 +1500,7 @@ PhysicalJoystickHandler::DefaultCommonMapping = {
|
|||
{Event::ConsoleRightDiffToggle, 5}, // Right Shoulder Button
|
||||
{Event::CmdMenuMode, 6}, // Left Trigger Button
|
||||
{Event::OptionsMenuMode, 7}, // Right Trigger Button
|
||||
#endif
|
||||
};
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
@ -806,10 +806,18 @@ PhysicalKeyboardHandler::DefaultCommonMapping = {
|
|||
{ Event::HighScoresMenuMode, KBDK_INSERT },
|
||||
{ Event::TogglePlayBackMode, KBDK_SPACE, KBDM_SHIFT },
|
||||
|
||||
#if defined(RETRON77)
|
||||
{ Event::ConsoleColorToggle, KBDK_F4 }, // back ("COLOR","B/W")
|
||||
{ Event::ConsoleLeftDiffToggle, KBDK_F6 }, // front ("SKILL P1")
|
||||
{ Event::ConsoleRightDiffToggle, KBDK_F8 }, // front ("SKILL P2")
|
||||
{ Event::CmdMenuMode, KBDK_F13 }, // back ("4:3","16:9")
|
||||
{ Event::ExitMode, KBDK_BACKSPACE }, // back ("FRY")
|
||||
#else // defining duplicate keys must be avoided!
|
||||
{ Event::ConsoleBlackWhite, KBDK_F4 },
|
||||
{ Event::ConsoleLeftDiffB, KBDK_F6 },
|
||||
{ Event::ConsoleRightDiffB, KBDK_F8 },
|
||||
{ Event::Fry, KBDK_BACKSPACE, KBDM_SHIFT }
|
||||
{ Event::Fry, KBDK_BACKSPACE, KBDM_SHIFT },
|
||||
#endif
|
||||
};
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -854,12 +862,24 @@ PhysicalKeyboardHandler::DefaultMenuMapping = {
|
|||
{Event::Quit, KBDK_Q, KBDM_CTRL},
|
||||
#endif
|
||||
|
||||
#if defined(RETRON77)
|
||||
{Event::UIUp, KBDK_F9}, // front ("SAVE")
|
||||
{Event::UIDown, KBDK_F2}, // front ("RESET")
|
||||
{Event::UINavPrev, KBDK_F11}, // front ("LOAD")
|
||||
{Event::UINavNext, KBDK_F1}, // front ("MODE")
|
||||
{Event::UISelect, KBDK_F6}, // front ("SKILL P1")
|
||||
{Event::UICancel, KBDK_F8}, // front ("SKILL P2")
|
||||
//{Event::NoType, KBDK_F4}, // back ("COLOR","B/W")
|
||||
{Event::UITabPrev, KBDK_F13}, // back ("4:3","16:9")
|
||||
{Event::UITabNext, KBDK_BACKSPACE}, // back (FRY)
|
||||
#else // defining duplicate keys must be avoided!
|
||||
{Event::UIPrevDir, KBDK_BACKSPACE},
|
||||
#ifdef BSPF_MACOS
|
||||
{Event::UIHelp, KBDK_SLASH, KBDM_SHIFT | CMD},
|
||||
#else
|
||||
{Event::UIHelp, KBDK_F1},
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef GUI_SUPPORT
|
||||
|
@ -1017,8 +1037,6 @@ PhysicalKeyboardHandler::DefaultPaddleMapping = {
|
|||
{Event::LeftPaddleAFire, KBDK_SPACE},
|
||||
{Event::LeftPaddleAFire, KBDK_LCTRL},
|
||||
{Event::LeftPaddleAFire, KBDK_KP_5},
|
||||
{Event::LeftPaddleAButton1, KBDK_UP, KBDM_SHIFT},
|
||||
{Event::LeftPaddleAButton2, KBDK_DOWN, KBDM_SHIFT},
|
||||
|
||||
{Event::LeftPaddleBDecrease, KBDK_DOWN},
|
||||
{Event::LeftPaddleBIncrease, KBDK_UP},
|
||||
|
@ -1028,8 +1046,6 @@ PhysicalKeyboardHandler::DefaultPaddleMapping = {
|
|||
{Event::RightPaddleADecrease, KBDK_J},
|
||||
{Event::RightPaddleAIncrease, KBDK_G},
|
||||
{Event::RightPaddleAFire, KBDK_F},
|
||||
{Event::RightPaddleAButton1, KBDK_Y, KBDM_SHIFT},
|
||||
{Event::RightPaddleAButton2, KBDK_H, KBDM_SHIFT},
|
||||
|
||||
{Event::RightPaddleBDecrease, KBDK_H},
|
||||
{Event::RightPaddleBIncrease, KBDK_Y},
|
||||
|
@ -1081,16 +1097,10 @@ PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultDrivi
|
|||
{Event::LeftDrivingFire, KBDK_SPACE},
|
||||
{Event::LeftDrivingFire, KBDK_LCTRL},
|
||||
{Event::LeftDrivingFire, KBDK_KP_5},
|
||||
{Event::LeftDrivingButton1, KBDK_UP},
|
||||
{Event::LeftDrivingButton2, KBDK_DOWN},
|
||||
{Event::LeftDrivingButton1, KBDK_KP_8},
|
||||
{Event::LeftDrivingButton2, KBDK_KP_2},
|
||||
|
||||
{Event::RightDrivingCCW, KBDK_G},
|
||||
{Event::RightDrivingCW, KBDK_J},
|
||||
{Event::RightDrivingFire, KBDK_F},
|
||||
{Event::RightDrivingButton1, KBDK_Y},
|
||||
{Event::RightDrivingButton2, KBDK_H},
|
||||
};
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -1147,7 +1157,9 @@ PhysicalKeyboardHandler::CompuMateMapping = {
|
|||
{Event::CompuMateRightBracket, KBDK_RIGHTBRACKET},
|
||||
{Event::CompuMateMinus, KBDK_MINUS},
|
||||
{Event::CompuMateQuote, KBDK_APOSTROPHE, KBDM_SHIFT},
|
||||
#ifndef RETRON77
|
||||
{Event::CompuMateBackspace, KBDK_BACKSPACE},
|
||||
#endif
|
||||
{Event::CompuMateEquals, KBDK_EQUALS},
|
||||
{Event::CompuMatePlus, KBDK_EQUALS, KBDM_SHIFT},
|
||||
{Event::CompuMateSlash, KBDK_SLASH}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
@ -449,15 +449,13 @@ void PaletteHandler::generateCustomPalette(ConsoleTiming timing) const
|
|||
{
|
||||
constexpr int NUM_CHROMA = 16;
|
||||
constexpr int NUM_LUMA = 8;
|
||||
constexpr float SATURATION = 0.25F; // default saturation
|
||||
|
||||
if(timing == ConsoleTiming::ntsc)
|
||||
{
|
||||
constexpr float SATURATION = 0.30F; // default NTSC saturation
|
||||
vector2d IQ[NUM_CHROMA];
|
||||
// YIQ is YUV shifted by 33°
|
||||
// -90° + 33° = -57° would create a greenish yellow
|
||||
// -90° + 53° = -37° creates gold (which is correct according to the documentation)
|
||||
constexpr float offset = (33 + 20) * BSPF::PI_f / 180;
|
||||
// YIQ is YUV shifted by 33 degrees
|
||||
constexpr float offset = 33 * BSPF::PI_f / 180;
|
||||
const float shift = myPhaseNTSC * BSPF::PI_f / 180;
|
||||
|
||||
// color 0 is grayscale
|
||||
|
@ -480,9 +478,9 @@ void PaletteHandler::generateCustomPalette(ConsoleTiming timing) const
|
|||
float G = Y + dotProduct(IQ[chroma], IQG);
|
||||
float B = Y + dotProduct(IQ[chroma], IQB);
|
||||
|
||||
R = std::max(R, 0.F);
|
||||
G = std::max(G, 0.F);
|
||||
B = std::max(B, 0.F);
|
||||
if(R < 0) R = 0;
|
||||
if(G < 0) G = 0;
|
||||
if(B < 0) B = 0;
|
||||
|
||||
R = powf(R, 0.9F);
|
||||
G = powf(G, 0.9F);
|
||||
|
@ -498,7 +496,6 @@ void PaletteHandler::generateCustomPalette(ConsoleTiming timing) const
|
|||
}
|
||||
else if(timing == ConsoleTiming::pal)
|
||||
{
|
||||
constexpr float SATURATION = 0.25F; // default PAL saturation
|
||||
constexpr float offset = BSPF::PI_f;
|
||||
const float shift = myPhasePAL * BSPF::PI_f / 180;
|
||||
constexpr float fixedShift = 22.5F * BSPF::PI_f / 180;
|
||||
|
@ -672,9 +669,9 @@ const PaletteArray PaletteHandler::ourPALPalette = {
|
|||
0x6c6c6c, 0, 0x909090, 0, 0xb4b4b4, 0, 0xd8d8d8, 0,
|
||||
#else
|
||||
0x0b0b0b, 0, 0x333333, 0, 0x595959, 0, 0x7b7b7b, 0, // 0
|
||||
0x999999, 0, 0xb6b6b6, 0, 0xcfcfcf, 0, 0xe6e6e6, 0,
|
||||
0x0b0b0b, 0, 0x333333, 0, 0x595959, 0, 0x7b7b7b, 0, // 1
|
||||
0x999999, 0, 0xb6b6b6, 0, 0xcfcfcf, 0, 0xe6e6e6, 0,
|
||||
0x8b8b8b, 0, 0xaaaaaa, 0, 0xc7c7c7, 0, 0xe3e3e3, 0,
|
||||
0x000000, 0, 0x272727, 0, 0x404040, 0, 0x696969, 0, // 1
|
||||
0x8b8b8b, 0, 0xaaaaaa, 0, 0xc7c7c7, 0, 0xe3e3e3, 0,
|
||||
0x3b2400, 0, 0x664700, 0, 0x8b7000, 0, 0xac9200, 0, // 2
|
||||
0xc5ae36, 0, 0xdec85e, 0, 0xf7e27f, 0, 0xfff19e, 0,
|
||||
0x004500, 0, 0x006f00, 0, 0x3b9200, 0, 0x65b009, 0, // 3
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
@ -33,7 +33,7 @@ class PaletteHandler
|
|||
static constexpr string_view SETTING_CUSTOM = "custom";
|
||||
|
||||
// Phase shift default and limits
|
||||
static constexpr float DEF_NTSC_SHIFT = 26.7F; // makes color $fx fall between $1x and $2x
|
||||
static constexpr float DEF_NTSC_SHIFT = 26.2F;
|
||||
static constexpr float DEF_PAL_SHIFT = 31.3F; // ~= 360 / 11.5
|
||||
static constexpr float MAX_PHASE_SHIFT = 4.5F;
|
||||
static constexpr float DEF_RGB_SHIFT = 0.0F;
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
@ -64,15 +64,15 @@ class PhosphorHandler
|
|||
static constexpr uInt32 getPixel(const uInt32 c, const uInt32 p)
|
||||
{
|
||||
// Mix current calculated frame with previous displayed frame
|
||||
const auto rc = static_cast<uInt8>(c),
|
||||
const auto rc = static_cast<uInt8>(c >> 16),
|
||||
gc = static_cast<uInt8>(c >> 8),
|
||||
bc = static_cast<uInt8>(c >> 16),
|
||||
rp = static_cast<uInt8>(p),
|
||||
bc = static_cast<uInt8>(c),
|
||||
rp = static_cast<uInt8>(p >> 16),
|
||||
gp = static_cast<uInt8>(p >> 8),
|
||||
bp = static_cast<uInt8>(p >> 16);
|
||||
bp = static_cast<uInt8>(p);
|
||||
|
||||
return ourPhosphorLUT[rc][rp] | (ourPhosphorLUT[gc][gp] << 8) |
|
||||
(ourPhosphorLUT[bc][bp] << 16);
|
||||
return (ourPhosphorLUT[rc][rp] << 16) | (ourPhosphorLUT[gc][gp] << 8) |
|
||||
ourPhosphorLUT[bc][bp];
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
@ -112,26 +112,26 @@ json PhysicalJoystick::convertLegacyMapping(string_view mapping, string_view nam
|
|||
{
|
||||
istringstream buf(string{mapping}); // TODO: fixed in C++23
|
||||
json convertedMapping = json::object();
|
||||
string lmap;
|
||||
string map;
|
||||
|
||||
// Skip joystick name
|
||||
getline(buf, lmap, MODE_DELIM);
|
||||
getline(buf, map, MODE_DELIM);
|
||||
|
||||
while (getline(buf, lmap, MODE_DELIM))
|
||||
while (getline(buf, map, MODE_DELIM))
|
||||
{
|
||||
int mode{0};
|
||||
|
||||
// Get event mode
|
||||
std::ranges::replace(lmap, '|', ' ');
|
||||
istringstream modeBuf(lmap);
|
||||
std::replace(map.begin(), map.end(), '|', ' ');
|
||||
istringstream modeBuf(map);
|
||||
modeBuf >> mode;
|
||||
|
||||
// Remove leading "<mode>|" string
|
||||
lmap.erase(0, 2);
|
||||
map.erase(0, 2);
|
||||
|
||||
const json lmappingForMode = JoyMap::convertLegacyMapping(lmap);
|
||||
const json mappingForMode = JoyMap::convertLegacyMapping(map);
|
||||
|
||||
convertedMapping[jsonName(static_cast<EventMode>(mode))] = lmappingForMode;
|
||||
convertedMapping[jsonName(static_cast<EventMode>(mode))] = mappingForMode;
|
||||
}
|
||||
|
||||
convertedMapping["name"] = name;
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
@ -114,10 +114,10 @@ private:
|
|||
|
||||
public:
|
||||
constexpr Rect() = default;
|
||||
constexpr explicit Rect(const Size& s) : bottom{s.h}, right{s.w} { assert(valid()); }
|
||||
constexpr Rect(uInt32 w, uInt32 h) : bottom{h}, right{w} { assert(valid()); }
|
||||
constexpr explicit Rect(const Size& s) : bottom{ s.h }, right{ s.w } { assert(valid()); }
|
||||
constexpr Rect(uInt32 w, uInt32 h) : bottom{ h }, right{ w } { assert(valid()); }
|
||||
constexpr Rect(const Point& p, uInt32 w, uInt32 h)
|
||||
: top(p.y), left(p.x), bottom(p.y + h), right(p.x + w) { assert(valid()); }
|
||||
: top(p.y), left(p.x), bottom(p.y + h), right( p.x + w) { assert(valid()); }
|
||||
constexpr Rect(uInt32 x1, uInt32 y1, uInt32 x2, uInt32 y2) : top{y1}, left{x1}, bottom{y2}, right{x2} { assert(valid()); }
|
||||
|
||||
constexpr uInt32 x() const { return left; }
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
@ -114,7 +114,7 @@ bool RewindManager::addState(string_view message, bool timeMachine)
|
|||
interval = interval * scanlines / 262;
|
||||
}
|
||||
|
||||
if(myOSystem.console().system().cycles() - lastState.cycles < interval)
|
||||
if(myOSystem.console().tia().cycles() - lastState.cycles < interval)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -135,7 +135,7 @@ bool RewindManager::addState(string_view message, bool timeMachine)
|
|||
if(myStateManager.saveState(s) && myOSystem.console().tia().saveDisplay(s))
|
||||
{
|
||||
state.message = message;
|
||||
state.cycles = myOSystem.console().system().cycles();
|
||||
state.cycles = myOSystem.console().tia().cycles();
|
||||
myLastTimeMachineAdd = timeMachine;
|
||||
return true;
|
||||
}
|
||||
|
@ -145,7 +145,7 @@ bool RewindManager::addState(string_view message, bool timeMachine)
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt32 RewindManager::rewindStates(uInt32 numStates)
|
||||
{
|
||||
const uInt64 startCycles = myOSystem.console().system().cycles();
|
||||
const uInt64 startCycles = myOSystem.console().tia().cycles();
|
||||
uInt32 i{0};
|
||||
string message;
|
||||
|
||||
|
@ -185,7 +185,7 @@ uInt32 RewindManager::rewindStates(uInt32 numStates)
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt32 RewindManager::unwindStates(uInt32 numStates)
|
||||
{
|
||||
const uInt64 startCycles = myOSystem.console().system().cycles();
|
||||
const uInt64 startCycles = myOSystem.console().tia().cycles();
|
||||
uInt32 i{0};
|
||||
string message;
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
@ -33,30 +33,48 @@
|
|||
#pragma clang diagnostic ignored "-Wold-style-cast"
|
||||
#pragma clang diagnostic ignored "-Wreserved-identifier"
|
||||
#pragma clang diagnostic ignored "-Wswitch-default"
|
||||
#include <SDL3/SDL.h>
|
||||
#include <SDL.h>
|
||||
#pragma clang diagnostic pop
|
||||
#elif defined(BSPF_WINDOWS)
|
||||
#pragma warning(push, 0)
|
||||
#include <SDL3/SDL.h>
|
||||
#include <SDL.h>
|
||||
#pragma warning(pop)
|
||||
#else
|
||||
#include <SDL3/SDL.h>
|
||||
#include <SDL.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Seems to be needed for ppc64le, doesn't hurt other archs
|
||||
* Note that this is a problem in SDL2, which includes <altivec.h>
|
||||
* https://bugzilla.redhat.com/show_bug.cgi?id=1419452
|
||||
*/
|
||||
#undef vector
|
||||
#undef pixel
|
||||
#undef bool
|
||||
|
||||
static inline string SDLVersion()
|
||||
{
|
||||
ostringstream buf;
|
||||
const int ver = SDL_GetVersion();
|
||||
buf << "SDL "
|
||||
<< SDL_VERSIONNUM_MAJOR(ver) << "."
|
||||
<< SDL_VERSIONNUM_MINOR(ver) << "."
|
||||
<< SDL_VERSIONNUM_MICRO(ver);
|
||||
SDL_version ver;
|
||||
SDL_GetVersion(&ver);
|
||||
buf << "SDL " << static_cast<int>(ver.major) << "." << static_cast<int>(ver.minor)
|
||||
<< "." << static_cast<int>(ver.patch);
|
||||
return buf.str();
|
||||
}
|
||||
|
||||
static inline bool SDLSupportsURL()
|
||||
{
|
||||
return SDL_VERSION_ATLEAST(2,0,14);
|
||||
}
|
||||
|
||||
static inline bool SDLOpenURL(const string& url)
|
||||
{
|
||||
return SDL_OpenURL(url.c_str());
|
||||
#if SDL_VERSION_ATLEAST(2,0,14)
|
||||
return SDL_OpenURL(url.c_str()) == 0;
|
||||
#else
|
||||
cerr << "OpenURL requires at least SDL 2.0.14\n";
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // SDL_LIB_HXX
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
@ -91,9 +91,8 @@ class SoundNull : public Sound
|
|||
outside this range indicate that the volume shouldn't be changed at all.
|
||||
|
||||
@param volume The new volume level for the sound device
|
||||
@param persist Whether to save the volume change to settings
|
||||
*/
|
||||
void setVolume(uInt32 volume, bool persist = true) override { }
|
||||
void setVolume(uInt32 volume) override { }
|
||||
|
||||
/**
|
||||
Adjusts the volume of the sound device based on the given direction.
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
@ -31,18 +31,18 @@
|
|||
#include "audio/LanczosResampler.hxx"
|
||||
#include "ThreadDebugging.hxx"
|
||||
|
||||
#include "SoundSDL.hxx"
|
||||
#include "SoundSDL2.hxx"
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
SoundSDL::SoundSDL(OSystem& osystem, AudioSettings& audioSettings)
|
||||
SoundSDL2::SoundSDL2(OSystem& osystem, AudioSettings& audioSettings)
|
||||
: Sound{osystem},
|
||||
myAudioSettings{audioSettings}
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
Logger::debug("SoundSDL::SoundSDL started ...");
|
||||
Logger::debug("SoundSDL2::SoundSDL2 started ...");
|
||||
|
||||
if(!SDL_InitSubSystem(SDL_INIT_AUDIO))
|
||||
if(SDL_InitSubSystem(SDL_INIT_AUDIO) < 0)
|
||||
{
|
||||
ostringstream buf;
|
||||
|
||||
|
@ -52,35 +52,77 @@ SoundSDL::SoundSDL(OSystem& osystem, AudioSettings& audioSettings)
|
|||
return;
|
||||
}
|
||||
|
||||
SDL_zero(mySpec);
|
||||
if(!myAudioSettings.enabled())
|
||||
Logger::info("Sound disabled\n");
|
||||
queryHardware(myDevices); // NOLINT
|
||||
|
||||
Logger::debug("SoundSDL::SoundSDL initialized");
|
||||
SDL_zero(myHardwareSpec);
|
||||
if(!openDevice())
|
||||
return;
|
||||
|
||||
// Reserve 8K for the audio buffer; seems to be enough on most systems
|
||||
myBuffer.reserve(8_KB);
|
||||
Logger::debug("SoundSDL2::SoundSDL2 initialized");
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
SoundSDL::~SoundSDL()
|
||||
SoundSDL2::~SoundSDL2()
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
if(!myIsInitializedFlag)
|
||||
return;
|
||||
|
||||
SDL_DestroyAudioStream(myStream);
|
||||
SDL_CloseAudioDevice(myDevice);
|
||||
SDL_QuitSubSystem(SDL_INIT_AUDIO);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool SoundSDL::openDevice()
|
||||
void SoundSDL2::queryHardware(VariantList& devices)
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
auto SOUND_ERROR = [this]() -> bool
|
||||
const int numDevices = SDL_GetNumAudioDevices(0);
|
||||
|
||||
// log the available audio devices
|
||||
ostringstream s;
|
||||
s << "Supported audio devices (" << numDevices << "):";
|
||||
Logger::debug(s.view());
|
||||
|
||||
VarList::push_back(devices, "Default", 0);
|
||||
for(int i = 0; i < numDevices; ++i)
|
||||
{
|
||||
ostringstream ss;
|
||||
|
||||
ss << " " << i + 1 << ": " << SDL_GetAudioDeviceName(i, 0);
|
||||
Logger::debug(ss.view());
|
||||
|
||||
VarList::push_back(devices, SDL_GetAudioDeviceName(i, 0), i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool SoundSDL2::openDevice()
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
SDL_AudioSpec desired;
|
||||
desired.freq = myAudioSettings.sampleRate();
|
||||
desired.format = AUDIO_F32SYS;
|
||||
desired.channels = 2;
|
||||
desired.samples = static_cast<Uint16>(myAudioSettings.fragmentSize());
|
||||
desired.callback = callback;
|
||||
desired.userdata = this;
|
||||
|
||||
if(myIsInitializedFlag)
|
||||
SDL_CloseAudioDevice(myDevice);
|
||||
|
||||
myDeviceId = BSPF::clamp(myAudioSettings.device(), 0U,
|
||||
static_cast<uInt32>(myDevices.size() - 1));
|
||||
const char* const device = myDeviceId
|
||||
? myDevices.at(myDeviceId).first.c_str()
|
||||
: nullptr;
|
||||
|
||||
myDevice = SDL_OpenAudioDevice(device, 0, &desired, &myHardwareSpec,
|
||||
SDL_AUDIO_ALLOW_FREQUENCY_CHANGE);
|
||||
|
||||
if(myDevice == 0)
|
||||
{
|
||||
ostringstream buf;
|
||||
|
||||
|
@ -89,72 +131,49 @@ bool SoundSDL::openDevice()
|
|||
Logger::error(buf.view());
|
||||
|
||||
return myIsInitializedFlag = false;
|
||||
};
|
||||
|
||||
if(myIsInitializedFlag)
|
||||
{
|
||||
SDL_DestroyAudioStream(myStream);
|
||||
myStream = nullptr;
|
||||
}
|
||||
|
||||
mySpec = { SDL_AUDIO_F32, 2, static_cast<int>(myAudioSettings.sampleRate()) };
|
||||
|
||||
myDevice = SDL_OpenAudioDevice(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &mySpec);
|
||||
if(myDevice == 0)
|
||||
return SOUND_ERROR();
|
||||
myStream = SDL_CreateAudioStream(&mySpec, nullptr);
|
||||
if(!myStream)
|
||||
return SOUND_ERROR();
|
||||
if(!SDL_BindAudioStream(myDevice, myStream))
|
||||
return SOUND_ERROR();
|
||||
if(!SDL_SetAudioStreamGetCallback(myStream, audioCallback, this))
|
||||
return SOUND_ERROR();
|
||||
|
||||
return myIsInitializedFlag = true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void SoundSDL::setEnabled(bool enable)
|
||||
void SoundSDL2::setEnabled(bool enable)
|
||||
{
|
||||
if(myIsInitializedFlag)
|
||||
{
|
||||
mute(!enable);
|
||||
pause(!enable);
|
||||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void SoundSDL::open(shared_ptr<AudioQueue> audioQueue,
|
||||
void SoundSDL2::open(shared_ptr<AudioQueue> audioQueue,
|
||||
shared_ptr<const EmulationTiming> emulationTiming)
|
||||
{
|
||||
const string pre_about = myAboutString;
|
||||
|
||||
// Do we need to re-open the sound device?
|
||||
// Only do this when absolutely necessary
|
||||
if(myAudioSettings.sampleRate() != static_cast<uInt32>(myHardwareSpec.freq) ||
|
||||
myAudioSettings.fragmentSize() != static_cast<uInt32>(myHardwareSpec.samples) ||
|
||||
myAudioSettings.device() != myDeviceId)
|
||||
openDevice();
|
||||
|
||||
myEmulationTiming = emulationTiming;
|
||||
myWavHandler.setSpeed(262 * 60 * 2. / myEmulationTiming->audioSampleRate());
|
||||
|
||||
Logger::debug("SoundSDL2::open started ...");
|
||||
|
||||
audioQueue->ignoreOverflows(!myAudioSettings.enabled());
|
||||
if(!myAudioSettings.enabled())
|
||||
{
|
||||
Logger::info("Sound disabled\n");
|
||||
return;
|
||||
}
|
||||
pause(true);
|
||||
|
||||
const string pre_about = myAboutString;
|
||||
|
||||
myAudioQueue = audioQueue;
|
||||
myEmulationTiming = emulationTiming;
|
||||
myUnderrun = true;
|
||||
myCurrentFragment = nullptr;
|
||||
|
||||
myAudioQueue->ignoreOverflows(!myAudioSettings.enabled());
|
||||
myWavHandler.setSpeed(262 * 60 * 2. / myEmulationTiming->audioSampleRate());
|
||||
|
||||
// Do we need to re-open the sound device?
|
||||
// Only do this when absolutely necessary
|
||||
if(myAudioSettings.sampleRate() != static_cast<uInt32>(mySpec.freq))
|
||||
openDevice();
|
||||
|
||||
Logger::debug("SoundSDL::open started ...");
|
||||
|
||||
// Adjust volume to that defined in settings
|
||||
setVolume(myAudioSettings.volume());
|
||||
|
||||
// Initialize resampler; must be done after the sound device has opened
|
||||
initResampler();
|
||||
|
||||
// Show some info
|
||||
|
@ -165,20 +184,20 @@ void SoundSDL::open(shared_ptr<AudioQueue> audioQueue,
|
|||
// And start the SDL sound subsystem ...
|
||||
pause(false);
|
||||
|
||||
Logger::debug("SoundSDL::open finished");
|
||||
Logger::debug("SoundSDL2::open finished");
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void SoundSDL::mute(bool enable)
|
||||
void SoundSDL2::mute(bool enable)
|
||||
{
|
||||
if(enable)
|
||||
setVolume(0, false);
|
||||
myVolumeFactor = 0;
|
||||
else
|
||||
setVolume(myAudioSettings.volume());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void SoundSDL::toggleMute()
|
||||
void SoundSDL2::toggleMute()
|
||||
{
|
||||
const bool wasMuted = myVolumeFactor == 0;
|
||||
mute(!wasMuted);
|
||||
|
@ -192,40 +211,31 @@ void SoundSDL::toggleMute()
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool SoundSDL::pause(bool enable)
|
||||
bool SoundSDL2::pause(bool enable)
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
const bool wasPaused = SDL_AudioStreamDevicePaused(myStream);
|
||||
const bool wasPaused = SDL_GetAudioDeviceStatus(myDevice) == SDL_AUDIO_PAUSED;
|
||||
if(myIsInitializedFlag)
|
||||
{
|
||||
if(enable) SDL_PauseAudioStreamDevice(myStream);
|
||||
else SDL_ResumeAudioStreamDevice(myStream);
|
||||
|
||||
SDL_PauseAudioDevice(myDevice, enable ? 1 : 0);
|
||||
myWavHandler.pause(enable);
|
||||
}
|
||||
return wasPaused;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void SoundSDL::setVolume(uInt32 volume, bool persist)
|
||||
void SoundSDL2::setVolume(uInt32 volume)
|
||||
{
|
||||
if(myIsInitializedFlag && (volume <= 100))
|
||||
{
|
||||
myVolumeFactor = myAudioSettings.enabled()
|
||||
? static_cast<float>(volume) / 100.F
|
||||
: 0.F;
|
||||
|
||||
SDL_SetAudioStreamGain(myStream, myVolumeFactor);
|
||||
myWavHandler.setVolumeFactor(myVolumeFactor);
|
||||
|
||||
if(persist)
|
||||
myAudioSettings.setVolume(volume);
|
||||
myVolumeFactor = myAudioSettings.enabled() ? static_cast<float>(volume) / 100.F : 0;
|
||||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void SoundSDL::adjustVolume(int direction)
|
||||
void SoundSDL2::adjustVolume(int direction)
|
||||
{
|
||||
Int32 percent = myAudioSettings.volume();
|
||||
percent = BSPF::clamp(percent + direction * 2, 0, 100);
|
||||
|
@ -247,12 +257,13 @@ void SoundSDL::adjustVolume(int direction)
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
string SoundSDL::about() const
|
||||
string SoundSDL2::about() const
|
||||
{
|
||||
ostringstream buf;
|
||||
buf << "Sound enabled:\n"
|
||||
<< " Volume: " << myAudioSettings.volume() << "%\n"
|
||||
<< " Channels: " << static_cast<uInt32>(mySpec.channels)
|
||||
<< " Device: " << myDevices.at(myDeviceId).first << '\n'
|
||||
<< " Channels: " << static_cast<uInt32>(myHardwareSpec.channels)
|
||||
<< (myAudioQueue->isStereo() ? " (Stereo)" : " (Mono)") << '\n'
|
||||
<< " Preset: ";
|
||||
switch(myAudioSettings.preset())
|
||||
|
@ -276,7 +287,10 @@ string SoundSDL::about() const
|
|||
default:
|
||||
break; // Not supposed to get here
|
||||
}
|
||||
buf << " Sample rate: " << static_cast<uInt32>(mySpec.freq) << " Hz\n";
|
||||
buf << " Fragment size: " << static_cast<uInt32>(myHardwareSpec.samples)
|
||||
<< " bytes\n"
|
||||
<< " Sample rate: " << static_cast<uInt32>(myHardwareSpec.freq)
|
||||
<< " Hz\n";
|
||||
buf << " Resampling: ";
|
||||
switch(myAudioSettings.resamplingQuality())
|
||||
{
|
||||
|
@ -301,7 +315,7 @@ string SoundSDL::about() const
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void SoundSDL::initResampler()
|
||||
void SoundSDL2::initResampler()
|
||||
{
|
||||
const Resampler::NextFragmentCallback nextFragmentCallback = [this] () -> Int16* {
|
||||
Int16* nextFragment = nullptr;
|
||||
|
@ -319,11 +333,13 @@ void SoundSDL::initResampler()
|
|||
|
||||
return nextFragment;
|
||||
};
|
||||
|
||||
const Resampler::Format formatFrom =
|
||||
Resampler::Format(myEmulationTiming->audioSampleRate(),
|
||||
myAudioQueue->fragmentSize(), myAudioQueue->isStereo());
|
||||
const Resampler::Format formatTo =
|
||||
Resampler::Format(mySpec.freq, 1024, mySpec.channels > 1);
|
||||
Resampler::Format(myHardwareSpec.freq, myHardwareSpec.samples,
|
||||
myHardwareSpec.channels > 1);
|
||||
|
||||
switch(myAudioSettings.resamplingQuality())
|
||||
{
|
||||
|
@ -349,147 +365,183 @@ void SoundSDL::initResampler()
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void SoundSDL::audioCallback(void* object, SDL_AudioStream* stream,
|
||||
int additional_amt, int)
|
||||
void SoundSDL2::callback(void* object, uInt8* stream, int len)
|
||||
{
|
||||
auto* self = static_cast<SoundSDL*>(object);
|
||||
std::vector<uInt8>& buf = self->myBuffer;
|
||||
|
||||
// Make sure we always have enough room in the buffer
|
||||
if(std::cmp_greater_equal(additional_amt, buf.capacity()))
|
||||
buf.resize(additional_amt);
|
||||
auto* self = static_cast<SoundSDL2*>(object);
|
||||
|
||||
if(self->myAudioQueue && self->myResampler)
|
||||
{
|
||||
// The stream is 32-bit float (even though this callback is 8-bits), since
|
||||
// the resampler and TIA audio subsystem always generate float samples
|
||||
auto* s = reinterpret_cast<float*>(buf.data());
|
||||
self->myResampler->fillFragment(s, additional_amt >> 2);
|
||||
auto* s = reinterpret_cast<float*>(stream);
|
||||
const uInt32 length = len >> 2;
|
||||
self->myResampler->fillFragment(s, length);
|
||||
|
||||
SDL_PutAudioStreamData(stream, buf.data(), additional_amt);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool SoundSDL::playWav(const string& fileName, uInt32 position, uInt32 length)
|
||||
{
|
||||
if(myStream)
|
||||
return myWavHandler.play(SDL_GetAudioStreamDevice(myStream),
|
||||
fileName, position, length);
|
||||
for(uInt32 i = 0; i < length; ++i)
|
||||
s[i] *= SoundSDL2::myVolumeFactor;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
SDL_memset(stream, 0, len);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void SoundSDL::stopWav()
|
||||
bool SoundSDL2::playWav(const string& fileName, uInt32 position, uInt32 length)
|
||||
{
|
||||
const char* const device = myDeviceId
|
||||
? myDevices.at(myDeviceId).first.c_str()
|
||||
: nullptr;
|
||||
|
||||
return myWavHandler.play(fileName, device, position, length);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void SoundSDL2::stopWav()
|
||||
{
|
||||
myWavHandler.stop();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
uInt32 SoundSDL::wavSize() const
|
||||
uInt32 SoundSDL2::wavSize() const
|
||||
{
|
||||
return myWavHandler.size();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool SoundSDL::WavHandler::play(SDL_AudioDeviceID device,
|
||||
const string& fileName, uInt32 position, uInt32 length)
|
||||
bool SoundSDL2::WavHandlerSDL2::play(
|
||||
const string& fileName, const char* device, uInt32 position, uInt32 length)
|
||||
{
|
||||
// Load WAV file
|
||||
if(fileName != myFilename || myBuffer == nullptr)
|
||||
{
|
||||
if(myBuffer)
|
||||
{
|
||||
SDL_free(myBuffer);
|
||||
SDL_FreeWAV(myBuffer);
|
||||
myBuffer = nullptr;
|
||||
}
|
||||
SDL_zero(mySpec);
|
||||
if(!SDL_LoadWAV(fileName.c_str(), &mySpec, &myBuffer, &myLength))
|
||||
if(SDL_LoadWAV(fileName.c_str(), &mySpec, &myBuffer, &myLength) == nullptr)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set the callback function
|
||||
mySpec.callback = callback;
|
||||
mySpec.userdata = this;
|
||||
}
|
||||
if(position > myLength)
|
||||
return false;
|
||||
|
||||
if(myStream)
|
||||
SDL_UnbindAudioStream(myStream);
|
||||
|
||||
myStream = SDL_CreateAudioStream(&mySpec, nullptr);
|
||||
if(myStream == nullptr)
|
||||
return false;
|
||||
if(!SDL_BindAudioStream(device, myStream))
|
||||
return false;
|
||||
if(!SDL_SetAudioStreamGetCallback(myStream, WavHandler::wavCallback, this))
|
||||
return false;
|
||||
SDL_SetAudioStreamGain(myStream, myVolumeFactor);
|
||||
|
||||
myFilename = fileName;
|
||||
|
||||
myRemaining = length
|
||||
? std::min(length, myLength - position)
|
||||
: myLength;
|
||||
myPos = myBuffer + position;
|
||||
|
||||
// Open audio device
|
||||
if(!myDevice)
|
||||
{
|
||||
myDevice = SDL_OpenAudioDevice(device, 0, &mySpec, nullptr, 0);
|
||||
if(!myDevice)
|
||||
return false;
|
||||
|
||||
// Play audio
|
||||
pause(false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void SoundSDL::WavHandler::stop()
|
||||
void SoundSDL2::WavHandlerSDL2::stop()
|
||||
{
|
||||
if(myBuffer)
|
||||
{
|
||||
// Clean up
|
||||
myRemaining = 0;
|
||||
SDL_UnbindAudioStream(myStream); myStream = nullptr;
|
||||
SDL_free(myBuffer); myBuffer = nullptr;
|
||||
SDL_CloseAudioDevice(myDevice); myDevice = 0;
|
||||
SDL_FreeWAV(myBuffer); myBuffer = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void SoundSDL::WavHandler::setVolumeFactor(float volumeFactor)
|
||||
{
|
||||
myVolumeFactor = volumeFactor;
|
||||
if(myStream)
|
||||
SDL_SetAudioStreamGain(myStream, myVolumeFactor);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void SoundSDL::WavHandler::pause(bool state) const
|
||||
{
|
||||
if(myStream)
|
||||
if(myCvtBuffer)
|
||||
{
|
||||
if(state) SDL_PauseAudioStreamDevice(myStream);
|
||||
else SDL_ResumeAudioStreamDevice(myStream);
|
||||
myCvtBuffer.reset();
|
||||
myCvtBufferSize = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void SoundSDL::WavHandler::wavCallback(void* object, SDL_AudioStream* stream,
|
||||
int additional_amt, int)
|
||||
void SoundSDL2::WavHandlerSDL2::processWav(uInt8* stream, uInt32 len)
|
||||
{
|
||||
auto* self = static_cast<WavHandler*>(object);
|
||||
auto len = static_cast<uInt32>(additional_amt);
|
||||
auto& remaining = self->myRemaining;
|
||||
|
||||
if(remaining)
|
||||
SDL_memset(stream, mySpec.silence, len);
|
||||
if(myRemaining)
|
||||
{
|
||||
if(self->mySpeed != 1.0)
|
||||
len = std::round(len / self->mySpeed);
|
||||
if(mySpeed != 1.0)
|
||||
{
|
||||
const int origLen = len;
|
||||
len = std::round(len / mySpeed);
|
||||
const int newFreq =
|
||||
std::round(static_cast<double>(mySpec.freq) * origLen / len);
|
||||
|
||||
if(len > remaining) // NOLINT(readability-use-std-min-max)
|
||||
len = remaining;
|
||||
if(len > myRemaining)
|
||||
len = myRemaining;
|
||||
|
||||
SDL_PutAudioStreamData(stream, self->myPos, len);
|
||||
SDL_AudioCVT cvt;
|
||||
SDL_BuildAudioCVT(&cvt, mySpec.format, mySpec.channels, mySpec.freq,
|
||||
mySpec.format, mySpec.channels, newFreq);
|
||||
SDL_assert(cvt.needed); // Obviously, this one is always needed.
|
||||
cvt.len = len * mySpec.channels; // Mono 8 bit sample frames
|
||||
|
||||
self->myPos += len;
|
||||
remaining -= len;
|
||||
if(!myCvtBuffer ||
|
||||
myCvtBufferSize < static_cast<uInt32>(cvt.len * cvt.len_mult))
|
||||
{
|
||||
myCvtBufferSize = cvt.len * cvt.len_mult;
|
||||
myCvtBuffer = make_unique<uInt8[]>(myCvtBufferSize);
|
||||
}
|
||||
cvt.buf = myCvtBuffer.get();
|
||||
|
||||
// Read original data into conversion buffer
|
||||
SDL_memcpy(cvt.buf, myPos, cvt.len);
|
||||
SDL_ConvertAudio(&cvt);
|
||||
// Mix volume adjusted WAV data into silent buffer
|
||||
SDL_MixAudioFormat(stream, cvt.buf, mySpec.format, cvt.len_cvt,
|
||||
SDL_MIX_MAXVOLUME * SoundSDL2::myVolumeFactor);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(len > myRemaining)
|
||||
len = myRemaining;
|
||||
|
||||
// Mix volume adjusted WAV data into silent buffer
|
||||
SDL_MixAudioFormat(stream, myPos, mySpec.format, len,
|
||||
SDL_MIX_MAXVOLUME * myVolumeFactor);
|
||||
}
|
||||
myPos += len;
|
||||
myRemaining -= len;
|
||||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
SoundSDL::WavHandler::~WavHandler()
|
||||
void SoundSDL2::WavHandlerSDL2::callback(void* object, uInt8* stream, int len)
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
if(myBuffer)
|
||||
SDL_free(myBuffer);
|
||||
static_cast<WavHandlerSDL2*>(object)->processWav(
|
||||
stream, static_cast<uInt32>(len));
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
SoundSDL2::WavHandlerSDL2::~WavHandlerSDL2()
|
||||
{
|
||||
if(myDevice)
|
||||
{
|
||||
SDL_CloseAudioDevice(myDevice);
|
||||
SDL_FreeWAV(myBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void SoundSDL2::WavHandlerSDL2::pause(bool state) const
|
||||
{
|
||||
if(myDevice)
|
||||
SDL_PauseAudioDevice(myDevice, state ? 1 : 0);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
float SoundSDL2::myVolumeFactor = 0.F;
|
||||
|
||||
#endif // SOUND_SUPPORT
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
@ -17,8 +17,8 @@
|
|||
|
||||
#ifdef SOUND_SUPPORT
|
||||
|
||||
#ifndef SOUND_SDL_HXX
|
||||
#define SOUND_SDL_HXX
|
||||
#ifndef SOUND_SDL2_HXX
|
||||
#define SOUND_SDL2_HXX
|
||||
|
||||
class OSystem;
|
||||
class AudioQueue;
|
||||
|
@ -36,15 +36,15 @@ class Resampler;
|
|||
|
||||
@author Stephen Anthony and Christian Speckner (DirtyHairy)
|
||||
*/
|
||||
class SoundSDL : public Sound
|
||||
class SoundSDL2 : public Sound
|
||||
{
|
||||
public:
|
||||
/**
|
||||
Create a new sound object. The init method must be invoked before
|
||||
using the object.
|
||||
*/
|
||||
SoundSDL(OSystem& osystem, AudioSettings& audioSettings);
|
||||
~SoundSDL() override;
|
||||
SoundSDL2(OSystem& osystem, AudioSettings& audioSettings);
|
||||
~SoundSDL2() override;
|
||||
|
||||
public:
|
||||
/**
|
||||
|
@ -93,9 +93,8 @@ class SoundSDL : public Sound
|
|||
outside this range indicate that the volume shouldn't be changed at all.
|
||||
|
||||
@param volume The new volume level for the sound device
|
||||
@param persist Whether to save the volume change to settings
|
||||
*/
|
||||
void setVolume(uInt32 volume, bool persist = true) override;
|
||||
void setVolume(uInt32 volume) override;
|
||||
|
||||
/**
|
||||
Adjusts the volume of the sound device based on the given direction.
|
||||
|
@ -134,6 +133,13 @@ class SoundSDL : public Sound
|
|||
uInt32 wavSize() const override;
|
||||
|
||||
private:
|
||||
/**
|
||||
This method is called to query the audio devices.
|
||||
|
||||
@param devices List of device names
|
||||
*/
|
||||
void queryHardware(VariantList& devices) override;
|
||||
|
||||
/**
|
||||
The actual sound device is opened only when absolutely necessary.
|
||||
Typically this will only happen once per program run, but it can also
|
||||
|
@ -150,14 +156,10 @@ class SoundSDL : public Sound
|
|||
bool myIsInitializedFlag{false};
|
||||
|
||||
// Audio specification structure
|
||||
SDL_AudioSpec mySpec{};
|
||||
SDL_AudioSpec myHardwareSpec{};
|
||||
|
||||
// Audio device and stream, which handles all interaction with SDL sound backend
|
||||
SDL_AudioDeviceID myDevice{};
|
||||
SDL_AudioStream* myStream{nullptr};
|
||||
|
||||
// Audio buffer, passed to the audio callback and filled from the resampler
|
||||
std::vector<uInt8> myBuffer;
|
||||
SDL_AudioDeviceID myDevice{0};
|
||||
uInt32 myDeviceId{0};
|
||||
|
||||
shared_ptr<AudioQueue> myAudioQueue;
|
||||
unique_ptr<Resampler> myResampler;
|
||||
|
@ -167,66 +169,65 @@ class SoundSDL : public Sound
|
|||
Int16* myCurrentFragment{nullptr};
|
||||
bool myUnderrun{false};
|
||||
|
||||
float myVolumeFactor{1.F}; // Current volume level (0.F - 1.F)
|
||||
|
||||
string myAboutString;
|
||||
|
||||
/**
|
||||
This class implements WAV file playback using the SDL sound API.
|
||||
This class implements WAV file playback using the SDL2 sound API.
|
||||
*/
|
||||
class WavHandler
|
||||
class WavHandlerSDL2
|
||||
{
|
||||
public:
|
||||
explicit WavHandler() = default;
|
||||
~WavHandler();
|
||||
explicit WavHandlerSDL2() = default;
|
||||
~WavHandlerSDL2();
|
||||
|
||||
bool play(SDL_AudioDeviceID device, const string& fileName,
|
||||
bool play(const string& fileName, const char* device,
|
||||
uInt32 position, uInt32 length);
|
||||
void stop();
|
||||
uInt32 size() const { return myBuffer ? myRemaining : 0; }
|
||||
void setSpeed(double speed) { mySpeed = speed; }
|
||||
void setVolumeFactor(float volumeFactor);
|
||||
|
||||
void setSpeed(const double speed) { mySpeed = speed; }
|
||||
void pause(bool state) const;
|
||||
|
||||
private:
|
||||
string myFilename;
|
||||
SDL_AudioStream* myStream{nullptr};
|
||||
SDL_AudioSpec mySpec{};
|
||||
uInt8* myBuffer{nullptr};
|
||||
uInt32 myLength{0};
|
||||
SDL_AudioDeviceID myDevice{0};
|
||||
uInt8* myBuffer{nullptr};
|
||||
double mySpeed{1.0};
|
||||
float myVolumeFactor{1.F}; // Current volume level (0.F - 1.F)
|
||||
|
||||
unique_ptr<uInt8[]> myCvtBuffer;
|
||||
uInt32 myCvtBufferSize{0};
|
||||
SDL_AudioSpec mySpec{}; // audio output format
|
||||
uInt8* myPos{nullptr}; // pointer to the audio buffer to be played
|
||||
uInt32 myRemaining{0}; // remaining length of the sample we have to play
|
||||
|
||||
private:
|
||||
// Callback function invoked by the SDL Audio library when it needs data
|
||||
static void wavCallback(void* object, SDL_AudioStream* stream,
|
||||
int additional_amt, int);
|
||||
void processWav(uInt8* stream, uInt32 len);
|
||||
static void callback(void* object, uInt8* stream, int len);
|
||||
|
||||
// Following constructors and assignment operators not supported
|
||||
WavHandler(const WavHandler&) = delete;
|
||||
WavHandler(WavHandler&&) = delete;
|
||||
WavHandler& operator=(const WavHandler&) = delete;
|
||||
WavHandler& operator=(WavHandler&&) = delete;
|
||||
WavHandlerSDL2(const WavHandlerSDL2&) = delete;
|
||||
WavHandlerSDL2(WavHandlerSDL2&&) = delete;
|
||||
WavHandlerSDL2& operator=(const WavHandlerSDL2&) = delete;
|
||||
WavHandlerSDL2& operator=(WavHandlerSDL2&&) = delete;
|
||||
};
|
||||
|
||||
WavHandler myWavHandler;
|
||||
WavHandlerSDL2 myWavHandler;
|
||||
|
||||
static float myVolumeFactor; // Current volume level (0 - 100)
|
||||
|
||||
private:
|
||||
// Callback functions invoked by the SDL Audio library when it needs data
|
||||
static void audioCallback(void* object, SDL_AudioStream* stream,
|
||||
int additional_amt, int);
|
||||
static void callback(void* object, uInt8* stream, int len);
|
||||
|
||||
// Following constructors and assignment operators not supported
|
||||
SoundSDL() = delete;
|
||||
SoundSDL(const SoundSDL&) = delete;
|
||||
SoundSDL(SoundSDL&&) = delete;
|
||||
SoundSDL& operator=(const SoundSDL&) = delete;
|
||||
SoundSDL& operator=(SoundSDL&&) = delete;
|
||||
SoundSDL2() = delete;
|
||||
SoundSDL2(const SoundSDL2&) = delete;
|
||||
SoundSDL2(SoundSDL2&&) = delete;
|
||||
SoundSDL2& operator=(const SoundSDL2&) = delete;
|
||||
SoundSDL2& operator=(SoundSDL2&&) = delete;
|
||||
};
|
||||
|
||||
#endif // SOUND_SDL_HXX
|
||||
#endif
|
||||
|
||||
#endif // SOUND_SUPPORT
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
@ -116,9 +116,7 @@ void StaggeredLogger::startInterval()
|
|||
Int64 msecSinceLastIntervalEnd =
|
||||
duration_cast<duration<Int64, std::milli>>(now - myLastIntervalEndTimestamp).count();
|
||||
|
||||
while (std::cmp_greater(msecSinceLastIntervalEnd, myCooldownTime) &&
|
||||
myCurrentIntervalFactor > 1)
|
||||
{
|
||||
while (msecSinceLastIntervalEnd > myCooldownTime && myCurrentIntervalFactor > 1) {
|
||||
msecSinceLastIntervalEnd -= myCooldownTime;
|
||||
decreaseInterval();
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
@ -18,7 +18,7 @@
|
|||
#ifndef STATE_MANAGER_HXX
|
||||
#define STATE_MANAGER_HXX
|
||||
|
||||
#define STATE_HEADER "07000001state"
|
||||
#define STATE_HEADER "07000000state"
|
||||
|
||||
class OSystem;
|
||||
class RewindManager;
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
@ -221,16 +221,16 @@ enum StellaKey // NOLINT: use 32-bit, even though 16-bit is sufficient
|
|||
KBDK_F23 = 114,
|
||||
KBDK_F24 = 115,
|
||||
KBDK_EXECUTE = 116,
|
||||
KBDK_HELP = 117, /**< AL Integrated Help Center */
|
||||
KBDK_MENU = 118, /**< Menu (show menu) */
|
||||
KBDK_HELP = 117,
|
||||
KBDK_MENU = 118,
|
||||
KBDK_SELECT = 119,
|
||||
KBDK_STOP = 120, /**< AC Stop */
|
||||
KBDK_AGAIN = 121, /**< AC Redo/Repeat */
|
||||
KBDK_UNDO = 122, /**< AC Undo */
|
||||
KBDK_CUT = 123, /**< AC Cut */
|
||||
KBDK_COPY = 124, /**< AC Copy */
|
||||
KBDK_PASTE = 125, /**< AC Paste */
|
||||
KBDK_FIND = 126, /**< AC Find */
|
||||
KBDK_STOP = 120,
|
||||
KBDK_AGAIN = 121, /**< redo */
|
||||
KBDK_UNDO = 122,
|
||||
KBDK_CUT = 123,
|
||||
KBDK_COPY = 124,
|
||||
KBDK_PASTE = 125,
|
||||
KBDK_FIND = 126,
|
||||
KBDK_MUTE = 127,
|
||||
KBDK_VOLUMEUP = 128,
|
||||
KBDK_VOLUMEDOWN = 129,
|
||||
|
@ -263,7 +263,7 @@ enum StellaKey // NOLINT: use 32-bit, even though 16-bit is sufficient
|
|||
|
||||
KBDK_ALTERASE = 153, /**< Erase-Eaze */
|
||||
KBDK_SYSREQ = 154,
|
||||
KBDK_CANCEL = 155, /**< AC Cancel */
|
||||
KBDK_CANCEL = 155,
|
||||
KBDK_CLEAR = 156,
|
||||
KBDK_PRIOR = 157,
|
||||
KBDK_RETURN2 = 158,
|
||||
|
@ -330,9 +330,9 @@ enum StellaKey // NOLINT: use 32-bit, even though 16-bit is sufficient
|
|||
KBDK_RALT = 230, /**< alt gr, option */
|
||||
KBDK_RGUI = 231, /**< windows, command (apple), meta */
|
||||
|
||||
KBDK_MODE = 257, /**< I'm not sure if this is really not covered
|
||||
* by any of the above, but since there's a
|
||||
* special SDL_KMOD_MODE for it I'm adding it here
|
||||
KBDK_MODE = 257, /**< ALT-GR(aph) key on non-American keyboards
|
||||
* This is like pressing KBDK_RALT + KBDK_RCTRL
|
||||
* on some keyboards
|
||||
*/
|
||||
|
||||
/* @} *//* Usage page 0x07 */
|
||||
|
@ -341,98 +341,77 @@ enum StellaKey // NOLINT: use 32-bit, even though 16-bit is sufficient
|
|||
* \name Usage page 0x0C
|
||||
*
|
||||
* These values are mapped from usage page 0x0C (USB consumer page).
|
||||
*
|
||||
* There are way more keys in the spec than we can represent in the
|
||||
* current scancode range, so pick the ones that commonly come up in
|
||||
* real world usage.
|
||||
*/
|
||||
/* @{ */
|
||||
|
||||
KBDK_SLEEP = 258, /**< Sleep */
|
||||
KBDK_WAKE = 259, /**< Wake */
|
||||
|
||||
KBDK_CHANNEL_INCREMENT = 260, /**< Channel Increment */
|
||||
KBDK_CHANNEL_DECREMENT = 261, /**< Channel Decrement */
|
||||
|
||||
KBDK_MEDIA_PLAY = 262, /**< Play */
|
||||
KBDK_MEDIA_PAUSE = 263, /**< Pause */
|
||||
KBDK_MEDIA_RECORD = 264, /**< Record */
|
||||
KBDK_MEDIA_FAST_FORWARD = 265, /**< Fast Forward */
|
||||
KBDK_MEDIA_REWIND = 266, /**< Rewind */
|
||||
KBDK_MEDIA_NEXT_TRACK = 267, /**< Next Track */
|
||||
KBDK_MEDIA_PREVIOUS_TRACK = 268, /**< Previous Track */
|
||||
KBDK_MEDIA_STOP = 269, /**< Stop */
|
||||
KBDK_MEDIA_EJECT = 270, /**< Eject */
|
||||
KBDK_MEDIA_PLAY_PAUSE = 271, /**< Play / Pause */
|
||||
KBDK_MEDIA_SELECT = 272, /* Media Select */
|
||||
|
||||
KBDK_AC_NEW = 273, /**< AC New */
|
||||
KBDK_AC_OPEN = 274, /**< AC Open */
|
||||
KBDK_AC_CLOSE = 275, /**< AC Close */
|
||||
KBDK_AC_EXIT = 276, /**< AC Exit */
|
||||
KBDK_AC_SAVE = 277, /**< AC Save */
|
||||
KBDK_AC_PRINT = 278, /**< AC Print */
|
||||
KBDK_AC_PROPERTIES = 279, /**< AC Properties */
|
||||
|
||||
KBDK_AC_SEARCH = 280, /**< AC Search */
|
||||
KBDK_AC_HOME = 281, /**< AC Home */
|
||||
KBDK_AC_BACK = 282, /**< AC Back */
|
||||
KBDK_AC_FORWARD = 283, /**< AC Forward */
|
||||
KBDK_AC_STOP = 284, /**< AC Stop */
|
||||
KBDK_AC_REFRESH = 285, /**< AC Refresh */
|
||||
KBDK_AC_BOOKMARKS = 286, /**< AC Bookmarks */
|
||||
KBDK_AUDIONEXT = 258,
|
||||
KBDK_AUDIOPREV = 259,
|
||||
KBDK_AUDIOSTOP = 260,
|
||||
KBDK_AUDIOPLAY = 261,
|
||||
KBDK_AUDIOMUTE = 262,
|
||||
KBDK_MEDIASELECT = 263,
|
||||
KBDK_WWW = 264,
|
||||
KBDK_MAIL = 265,
|
||||
KBDK_CALCULATOR = 266,
|
||||
KBDK_COMPUTER = 267,
|
||||
KBDK_AC_SEARCH = 268,
|
||||
KBDK_AC_HOME = 269,
|
||||
KBDK_AC_BACK = 270,
|
||||
KBDK_AC_FORWARD = 271,
|
||||
KBDK_AC_STOP = 272,
|
||||
KBDK_AC_REFRESH = 273,
|
||||
KBDK_AC_BOOKMARKS = 274,
|
||||
|
||||
/* @} *//* Usage page 0x0C */
|
||||
|
||||
|
||||
/**
|
||||
* \name Mobile keys
|
||||
* \name Walther keys
|
||||
*
|
||||
* These are values that are often used on mobile phones.
|
||||
* These are values that Christian Walther added (for mac keyboard?).
|
||||
*/
|
||||
/* @{ */
|
||||
|
||||
KBDK_SOFTLEFT = 287, /**< Usually situated below the display on phones and
|
||||
used as a multi-function feature key for selecting
|
||||
a software defined function shown on the bottom left
|
||||
of the display. */
|
||||
KBDK_SOFTRIGHT = 288, /**< Usually situated below the display on phones and
|
||||
used as a multi-function feature key for selecting
|
||||
a software defined function shown on the bottom right
|
||||
of the display. */
|
||||
KBDK_CALL = 289, /**< Used for accepting phone calls. */
|
||||
KBDK_ENDCALL = 290, /**< Used for rejecting phone calls. */
|
||||
KBDK_BRIGHTNESSDOWN = 275,
|
||||
KBDK_BRIGHTNESSUP = 276,
|
||||
KBDK_DISPLAYSWITCH = 277, /**< display mirroring/dual display
|
||||
switch, video mode switch */
|
||||
KBDK_KBDILLUMTOGGLE = 278,
|
||||
KBDK_KBDILLUMDOWN = 279,
|
||||
KBDK_KBDILLUMUP = 280,
|
||||
KBDK_EJECT = 281,
|
||||
KBDK_SLEEP = 282,
|
||||
|
||||
/* @} *//* Mobile keys */
|
||||
KBDK_APP1 = 283,
|
||||
KBDK_APP2 = 284,
|
||||
|
||||
/* @} *//* Walther keys */
|
||||
|
||||
/* Add any other keys here. */
|
||||
|
||||
KBDK_RESERVED = 400, /**< 400-500 reserved for dynamic keycodes */
|
||||
|
||||
KBDK_COUNT = 512 /**< not a key, just marks the number of scancodes for array bounds */
|
||||
KBDK_LAST = 512 /**< not a key, just marks the number of scancodes
|
||||
for array bounds */
|
||||
};
|
||||
|
||||
// This comes directly from SDL_keycode.h
|
||||
enum StellaMod: uInt16
|
||||
{
|
||||
KBDM_NONE = 0x0000U, /**< no modifier is applicable. */
|
||||
KBDM_LSHIFT = 0x0001U, /**< the left Shift key is down. */
|
||||
KBDM_RSHIFT = 0x0002U, /**< the right Shift key is down. */
|
||||
KBDM_LEVEL5 = 0x0004U, /**< the Level 5 Shift key is down. */
|
||||
KBDM_LCTRL = 0x0040U, /**< the left Ctrl (Control) key is down. */
|
||||
KBDM_RCTRL = 0x0080U, /**< the right Ctrl (Control) key is down. */
|
||||
KBDM_LALT = 0x0100U, /**< the left Alt key is down. */
|
||||
KBDM_RALT = 0x0200U, /**< the right Alt key is down. */
|
||||
KBDM_LGUI = 0x0400U, /**< the left GUI key (often the Windows key) is down. */
|
||||
KBDM_RGUI = 0x0800U, /**< the right GUI key (often the Windows key) is down. */
|
||||
KBDM_NUM = 0x1000U, /**< the Num Lock key (may be located on an extended keypad) is down. */
|
||||
KBDM_CAPS = 0x2000U, /**< the Caps Lock key is down. */
|
||||
KBDM_MODE = 0x4000U, /**< the !AltGr key is down. */
|
||||
KBDM_SCROLL = 0x8000U, /**< the Scroll Lock key is down. */
|
||||
KBDM_CTRL = (KBDM_LCTRL | KBDM_RCTRL), /**< Any Ctrl key is down. */
|
||||
KBDM_SHIFT = (KBDM_LSHIFT | KBDM_RSHIFT), /**< Any Shift key is down. */
|
||||
KBDM_ALT = (KBDM_LALT | KBDM_RALT), /**< Any Alt key is down. */
|
||||
KBDM_GUI = (KBDM_LGUI | KBDM_RGUI) /**< Any GUI key is down. */
|
||||
KBDM_NONE = 0x0000,
|
||||
KBDM_LSHIFT = 0x0001,
|
||||
KBDM_RSHIFT = 0x0002,
|
||||
KBDM_LCTRL = 0x0040,
|
||||
KBDM_RCTRL = 0x0080,
|
||||
KBDM_LALT = 0x0100,
|
||||
KBDM_RALT = 0x0200,
|
||||
KBDM_LGUI = 0x0400,
|
||||
KBDM_RGUI = 0x0800,
|
||||
KBDM_NUM = 0x1000,
|
||||
KBDM_CAPS = 0x2000,
|
||||
KBDM_MODE = 0x4000,
|
||||
KBDM_RESERVED = 0x8000,
|
||||
KBDM_CTRL = (KBDM_LCTRL|KBDM_RCTRL),
|
||||
KBDM_SHIFT = (KBDM_LSHIFT|KBDM_RSHIFT),
|
||||
KBDM_ALT = (KBDM_LALT|KBDM_RALT),
|
||||
KBDM_GUI = (KBDM_LGUI|KBDM_RGUI)
|
||||
};
|
||||
|
||||
// Test if specified modifier is pressed
|
||||
|
@ -463,7 +442,7 @@ namespace StellaKeyName
|
|||
inline string_view forKey(StellaKey key)
|
||||
{
|
||||
#ifdef SDL_SUPPORT
|
||||
return SDL_GetScancodeName(static_cast<SDL_Scancode>(key));
|
||||
return SDL_GetScancodeName(SDL_Scancode(key));
|
||||
#else
|
||||
return string_view{};
|
||||
#endif
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
@ -18,7 +18,7 @@
|
|||
#ifndef VERSION_HXX
|
||||
#define VERSION_HXX
|
||||
|
||||
#define STELLA_VERSION "8.0_pre"
|
||||
#define STELLA_VERSION "7.0"
|
||||
#define STELLA_BUILD "8005"
|
||||
|
||||
#endif
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
@ -29,17 +29,17 @@ void VideoModeHandler::setImageSize(const Common::Size& image)
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void VideoModeHandler::setDisplaySize(const Common::Size& display, bool fullscreen)
|
||||
void VideoModeHandler::setDisplaySize(const Common::Size& display, Int32 fsIndex)
|
||||
{
|
||||
myDisplay = display;
|
||||
myFullscreen = fullscreen;
|
||||
myFSIndex = fsIndex;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
const VideoModeHandler::Mode&
|
||||
VideoModeHandler::buildMode(const Settings& settings, bool inTIAMode, Bezel::Info bezelInfo)
|
||||
{
|
||||
const bool windowedRequested = !myFullscreen;
|
||||
const bool windowedRequested = myFSIndex == -1;
|
||||
|
||||
// TIA mode allows zooming at non-integral factors in most cases
|
||||
if(inTIAMode)
|
||||
|
@ -53,7 +53,7 @@ const VideoModeHandler::Mode&
|
|||
// Image and screen (aka window) dimensions are the same
|
||||
// Overscan is not applicable in this mode
|
||||
myMode = Mode(myImage.w, myImage.h,
|
||||
Mode::Stretch::Fill, myFullscreen,
|
||||
Mode::Stretch::Fill, myFSIndex,
|
||||
desc.view(), zoom, bezelInfo);
|
||||
}
|
||||
else
|
||||
|
@ -74,7 +74,7 @@ const VideoModeHandler::Mode&
|
|||
{
|
||||
myMode = Mode(myImage.w, myImage.h,
|
||||
myDisplay.w, myDisplay.h,
|
||||
Mode::Stretch::Preserve, myFullscreen,
|
||||
Mode::Stretch::Preserve, myFSIndex,
|
||||
"Fullscreen: Preserve aspect, no stretch",
|
||||
zoom, overscan, bezelInfo);
|
||||
}
|
||||
|
@ -82,7 +82,7 @@ const VideoModeHandler::Mode&
|
|||
{
|
||||
myMode = Mode(myImage.w, myImage.h,
|
||||
myDisplay.w, myDisplay.h,
|
||||
Mode::Stretch::Fill, myFullscreen,
|
||||
Mode::Stretch::Fill, myFSIndex,
|
||||
"Fullscreen: Ignore aspect, full stretch",
|
||||
zoom, overscan, bezelInfo);
|
||||
}
|
||||
|
@ -94,31 +94,31 @@ const VideoModeHandler::Mode&
|
|||
myMode = Mode(myImage.w, myImage.h, Mode::Stretch::None);
|
||||
else
|
||||
myMode = Mode(myImage.w, myImage.h, myDisplay.w, myDisplay.h,
|
||||
Mode::Stretch::None, myFullscreen);
|
||||
Mode::Stretch::None, myFSIndex);
|
||||
}
|
||||
return myMode;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
VideoModeHandler::Mode::Mode(uInt32 iw, uInt32 ih, Stretch smode,
|
||||
bool fullscreen, string_view desc,
|
||||
Int32 fsindex, string_view desc,
|
||||
double zoomLevel, Bezel::Info bezelInfo)
|
||||
: Mode(iw, ih, iw, ih, smode, fullscreen, desc, zoomLevel, 1., bezelInfo)
|
||||
: Mode(iw, ih, iw, ih, smode, fsindex, desc, zoomLevel, 1., bezelInfo)
|
||||
{
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
VideoModeHandler::Mode::Mode(uInt32 iw, uInt32 ih, uInt32 sw, uInt32 sh,
|
||||
Stretch smode, bool fullscreen, string_view desc,
|
||||
Stretch smode, Int32 fsindex, string_view desc,
|
||||
double zoomLevel, double overscan, Bezel::Info bezelInfo)
|
||||
: screenS{sw, sh},
|
||||
stretch{smode},
|
||||
description{desc},
|
||||
zoom{zoomLevel}, //hZoom{zoomLevel}, vZoom{zoomLevel},
|
||||
fullscreen{fullscreen}
|
||||
fsIndex{fsindex}
|
||||
{
|
||||
// Now resize based on windowed/fullscreen mode and stretch factor
|
||||
if(fullscreen)
|
||||
if(fsIndex != -1) // fullscreen mode
|
||||
{
|
||||
switch(stretch)
|
||||
{
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
@ -46,14 +46,14 @@ class VideoModeHandler
|
|||
Stretch stretch{Mode::Stretch::None};
|
||||
string description;
|
||||
double zoom{1.};
|
||||
bool fullscreen{false}; // false indicates windowed mode
|
||||
Int32 fsIndex{-1}; // -1 indicates windowed mode
|
||||
|
||||
Mode() = default;
|
||||
Mode(uInt32 iw, uInt32 ih, uInt32 sw, uInt32 sh, Stretch smode,
|
||||
bool fullscreen = false, string_view desc = "",
|
||||
Int32 fsindex = -1, string_view desc = "",
|
||||
double zoomLevel = 1., double overscan = 1.,
|
||||
Bezel::Info bezelInfo = Bezel::Info());
|
||||
Mode(uInt32 iw, uInt32 ih, Stretch smode, bool fullscreen = false,
|
||||
Mode(uInt32 iw, uInt32 ih, Stretch smode, Int32 fsindex = -1,
|
||||
string_view desc = "", double zoomLevel = 1.,
|
||||
Bezel::Info bezelInfo = Bezel::Info());
|
||||
|
||||
|
@ -63,7 +63,7 @@ class VideoModeHandler
|
|||
<< " stretch=" << (vm.stretch == Stretch::Preserve ? "preserve" :
|
||||
vm.stretch == Stretch::Fill ? "fill" : "none")
|
||||
<< " desc=" << vm.description << " zoom=" << vm.zoom
|
||||
<< " fullscreen= " << vm.fullscreen;
|
||||
<< " fsIndex= " << vm.fsIndex;
|
||||
return os;
|
||||
}
|
||||
};
|
||||
|
@ -85,9 +85,9 @@ class VideoModeHandler
|
|||
or the size of the monitor currently active.
|
||||
|
||||
@param display The dimensions of the enclosing display
|
||||
@param fullscreen Whether to use fullscreen or windowed mode
|
||||
@param fsIndex Fullscreen mode in use (-1 indicates windowed mode)
|
||||
*/
|
||||
void setDisplaySize(const Common::Size& display, bool fullscreen);
|
||||
void setDisplaySize(const Common::Size& display, Int32 fsIndex = -1);
|
||||
|
||||
/**
|
||||
Build a video mode based on the given parameters, assuming that
|
||||
|
@ -103,7 +103,7 @@ class VideoModeHandler
|
|||
|
||||
private:
|
||||
Common::Size myImage, myDisplay;
|
||||
bool myFullscreen{false};
|
||||
Int32 myFSIndex{-1};
|
||||
|
||||
Mode myMode;
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
@ -266,7 +266,8 @@ void ZipHandler::ZipFile::readEcd()
|
|||
uInt64 read_length = 0;
|
||||
|
||||
// Max out the buf length at the size of the file
|
||||
buflen = std::min(buflen, myLength);
|
||||
if(buflen > myLength)
|
||||
buflen = myLength;
|
||||
|
||||
// Allocate buffer
|
||||
const ByteBuffer buffer = make_unique<uInt8[]>(buflen + 1);
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
|
||||
// Copyright (c) 1995-2024 by Bradford W. Mott, Stephen Anthony
|
||||
// and the Stella Team
|
||||
//
|
||||
// See the file "License.txt" for information on usage and redistribution of
|
||||
|
|