Merge branch 'master' into feature-highscores
|
@ -20,6 +20,7 @@ build/
|
|||
src/macosx/M6502.ins
|
||||
*.dSYM
|
||||
.vscode/c_cpp_properties.json
|
||||
.vscode/settings.json
|
||||
src/windows/sdl/*
|
||||
src/windows/x64/*
|
||||
src/windows/Win32/*
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
.core-defs:
|
||||
variables:
|
||||
JNI_PATH: src/libretro
|
||||
CORENAME: stella
|
||||
|
||||
include:
|
||||
- template: Jobs/Code-Quality.gitlab-ci.yml
|
||||
- project: 'libretro-infrastructure/ci-templates'
|
||||
file: '/libnx-static.yml'
|
||||
- project: 'libretro-infrastructure/ci-templates'
|
||||
file: '/linux-x64.yml'
|
||||
- project: 'libretro-infrastructure/ci-templates'
|
||||
file: '/windows-x64-mingw.yml'
|
||||
- project: 'libretro-infrastructure/ci-templates'
|
||||
file: '/android-jni.yml'
|
||||
|
||||
stages:
|
||||
- build-prepare
|
||||
- build-shared
|
||||
- build-static
|
||||
- test
|
||||
|
||||
#Desktop
|
||||
libretro-build-linux-x64:
|
||||
extends:
|
||||
- .core-defs
|
||||
- .libretro-linux-x64-make-default
|
||||
variables:
|
||||
MAKEFILE_PATH: src/libretro
|
||||
MAKEFILE: Makefile
|
||||
|
||||
libretro-build-windows-x64:
|
||||
extends:
|
||||
- .core-defs
|
||||
- .libretro-windows-x64-mingw-make-default
|
||||
variables:
|
||||
MAKEFILE_PATH: src/libretro
|
||||
MAKEFILE: Makefile
|
||||
|
||||
# Android
|
||||
android-armeabi-v7a:
|
||||
extends:
|
||||
- .core-defs
|
||||
- .libretro-android-jni-armeabi-v7a
|
||||
|
||||
android-arm64-v8a:
|
||||
extends:
|
||||
- .core-defs
|
||||
- .libretro-android-jni-arm64-v8a
|
||||
|
||||
android-x86_64:
|
||||
extends:
|
||||
- .core-defs
|
||||
- .libretro-android-jni-x86_64
|
||||
|
||||
android-x86:
|
||||
extends:
|
||||
- .core-defs
|
||||
- .libretro-android-jni-x86
|
||||
|
||||
# Static
|
||||
libretro-build-libnx-aarch64:
|
||||
extends:
|
||||
- .core-defs
|
||||
- .libretro-libnx-static-retroarch-master
|
||||
variables:
|
||||
MAKEFILE_PATH: src/libretro
|
||||
MAKEFILE: Makefile
|
26
Announce.txt
|
@ -9,7 +9,7 @@
|
|||
SSSS ttt eeeee llll llll aaaaa
|
||||
|
||||
===========================================================================
|
||||
Release 6.2.1 for Linux, macOS and Windows
|
||||
Release 6.4 for Linux, macOS and Windows
|
||||
===========================================================================
|
||||
|
||||
The Atari 2600 Video Computer System (VCS), introduced in 1977, was the
|
||||
|
@ -21,27 +21,25 @@ all of your favourite Atari 2600 games again! Stella was originally
|
|||
developed for Linux by Bradford W. Mott, however, it has been ported to a
|
||||
number of other platforms and is currently maintained by Stephen Anthony.
|
||||
|
||||
This is the 6.2.1 release of Stella for Linux, macOS and Windows. The
|
||||
This is the 6.4 release of Stella for Linux, macOS and Windows. The
|
||||
distributions currently available are:
|
||||
|
||||
* Binaries for Windows Vista/7/8/10 :
|
||||
Stella-6.2.1-win32.exe (32-bit EXE installer)
|
||||
Stella-6.2.1-x64.exe (64-bit EXE installer)
|
||||
Stella-6.2.1-windows.zip (32/64 bit versions)
|
||||
* Binaries for Windows 7/8/10 :
|
||||
Stella-6.4-win32.exe (32-bit EXE installer)
|
||||
Stella-6.4-x64.exe (64-bit EXE installer)
|
||||
Stella-6.4-windows.zip (32/64 bit versions)
|
||||
|
||||
* Binary distribution for macOS 10.7 and above :
|
||||
Stella-6.2.1-macos.dmg (64-bit Intel)
|
||||
Stella-6.4-macos.dmg (64-bit Intel)
|
||||
|
||||
* Binary distribution in 32-bit & 64-bit Ubuntu DEB format :
|
||||
stella_6.2.1-1_i386.deb
|
||||
stella_6.2.1-1_amd64.deb
|
||||
* Binary distribution for 64-bit Ubuntu :
|
||||
stella_6.4-1_amd64.deb
|
||||
|
||||
* Binary distribution in 32-bit & 64-bit RPM format :
|
||||
stella-6.2.1-2.i386.rpm
|
||||
stella-6.2.1-2.x86_64.rpm
|
||||
* Binary distribution for 64-bit Redhat :
|
||||
stella-6.4-2.x86_64.rpm
|
||||
|
||||
* Source code distribution for all platforms :
|
||||
stella-6.2.1-src.tar.xz
|
||||
stella-6.4-src.tar.xz
|
||||
|
||||
|
||||
Distribution Site
|
||||
|
|
86
Changes.txt
|
@ -12,11 +12,65 @@
|
|||
Release History
|
||||
===========================================================================
|
||||
|
||||
6.2.1 to 6.3 (XXXX XX, 2020)
|
||||
6.4 to 6.5 (December XX, 2020)
|
||||
|
||||
* Enhanced cut/copy/paste for text editing. (TODO: PromptWidget)
|
||||
|
||||
* Added undo and redo to text editing. (TODO: PromptWidget)
|
||||
|
||||
* Added wildcard support to launcher dialog filter.
|
||||
|
||||
* Added option to search subdirectories in launcher.
|
||||
|
||||
* Added static tooltips to some UI items.
|
||||
|
||||
* Added dynamic tooltips to most debugger items.
|
||||
|
||||
* Increased sample size for CDFJ+.
|
||||
|
||||
* Fixed autofire bug for trackball controllers.
|
||||
|
||||
* Codebase now uses C++17 features.
|
||||
|
||||
-Have fun!
|
||||
|
||||
|
||||
6.3 to 6.4 (November 2, 2020)
|
||||
|
||||
* Added basic (entire and single line only) text cut/copy and paste.
|
||||
|
||||
* Added color parameters to 'Custom' palette.
|
||||
|
||||
* Some improvements to AtariVox-USB adaptor functionality:
|
||||
- Made serial port used for an AtariVox-USB adaptor editable.
|
||||
- Autodetection of serial ports no longer messes up devices plugged
|
||||
into other serial ports.
|
||||
|
||||
* Added CPU load stats to debugger. Related to this, added debugger
|
||||
pseudo-registers '_ftimreadcycles' and '_fwsynccycles' to show the
|
||||
number of cycles since the start of frame under certain circumstances
|
||||
(see manual for more details).
|
||||
|
||||
* Fixed bug with aspect correction and fullscreen mode; snapshots from
|
||||
such a mode are now pixel-exact.
|
||||
|
||||
* Fixed a bug that caused CDF ROMs to crash on the Retron77 and reduced
|
||||
ARM emulation performance for CDF ROMs on other platforms.
|
||||
|
||||
* Fixed crash with missing or incorrectly sized SaveKey data file, and
|
||||
with certain functions not working (erase pages, erase entire EEPROM).
|
||||
|
||||
* Fixed Atari mouse autodetection.
|
||||
|
||||
* Fixed bug in ROM launcher, with last ROM selected not being remembered
|
||||
when exiting and re-entering a directory.
|
||||
|
||||
|
||||
6.2.1 to 6.3 (October 7, 2020)
|
||||
|
||||
* Added adjustable autofire.
|
||||
|
||||
* Added 'Dark' UI theme. (TODO: DOC)
|
||||
* Added 'Dark' UI theme.
|
||||
|
||||
* Extended global hotkeys for debug options.
|
||||
|
||||
|
@ -33,16 +87,42 @@
|
|||
Basically, you are now able to put many files that Stella uses inside
|
||||
one ZIP file, and distribute just that file.
|
||||
|
||||
* Extended AtariVox support to handle flow control, so that long phrases
|
||||
are no longer corrupted/cut off. This includes properly supporting the
|
||||
2600-daptor II, which is flashable to an AVox-USB converter.
|
||||
|
||||
* Added auto-detection of the serial port used for an AtariVox-USB adaptor.
|
||||
|
||||
* Added QuadTari controller support.
|
||||
|
||||
* Added option to select the audio device.
|
||||
|
||||
* Added support for CDFJ+ bankswitching type.
|
||||
|
||||
* Further enhanced UA bankswitching to support more Brazilian carts.
|
||||
|
||||
* Added option to display detected settings info when a ROM is loaded.
|
||||
|
||||
* Added another oddball TIA glitch option for delayed background color.
|
||||
|
||||
* Added option to disable aspect ratio correct scaling.
|
||||
|
||||
* Added debugger pseudo-registers '_timwrapread' and '_timwrapwrite',
|
||||
which are set when the RIOT timer is read/written on timer wraparound,
|
||||
respectively.
|
||||
|
||||
* Bankswitching schemes BUS, DPC+ and CDFx now work when startup bank
|
||||
randomization is enabled (these schemes now ignore that setting).
|
||||
|
||||
* Replaced "Re-disassemble" with "Disassemble @ current line" in debugger.
|
||||
|
||||
* Fixed bug when taking fullscreen snapshots; the dimensions were
|
||||
sometimes cut off.
|
||||
|
||||
-Have fun!
|
||||
|
||||
6.2.1 to 6.2.2 (August 25, 2020)
|
||||
|
||||
* Fixed a bug in initial controller mapping.
|
||||
|
||||
|
||||
6.2 to 6.2.1: (June 20, 2020)
|
||||
|
|
9
Makefile
|
@ -48,11 +48,11 @@ endif
|
|||
CXXFLAGS+= -Wall -Wextra -Wno-unused-parameter
|
||||
|
||||
ifdef HAVE_GCC
|
||||
CXXFLAGS+= -Wno-multichar -Wunused -fno-rtti -Woverloaded-virtual -Wnon-virtual-dtor -std=c++14
|
||||
CXXFLAGS+= -Wno-multichar -Wunused -Woverloaded-virtual -Wnon-virtual-dtor -std=c++17
|
||||
endif
|
||||
|
||||
ifdef HAVE_CLANG
|
||||
CXXFLAGS+= -Wno-multichar -Wunused -fno-rtti -Woverloaded-virtual -Wnon-virtual-dtor -std=c++14
|
||||
CXXFLAGS+= -Wno-multichar -Wunused -Woverloaded-virtual -Wnon-virtual-dtor -std=c++17
|
||||
endif
|
||||
|
||||
ifdef CLANG_WARNINGS
|
||||
|
@ -80,6 +80,11 @@ else
|
|||
endif
|
||||
endif
|
||||
|
||||
ifdef RELEASE
|
||||
CXXFLAGS += -flto -fno-rtti
|
||||
LDFLAGS += -flto -fno-rtti
|
||||
endif
|
||||
|
||||
#######################################################################
|
||||
# Misc stuff - you should never have to edit this #
|
||||
#######################################################################
|
||||
|
|
|
@ -26,6 +26,7 @@ _build_sqlite=no
|
|||
_build_static=no
|
||||
_build_profile=no
|
||||
_build_debug=no
|
||||
_build_release=no
|
||||
|
||||
# more defaults
|
||||
_ranlib=ranlib
|
||||
|
@ -261,8 +262,10 @@ for ac_option in $@; do
|
|||
--disable-static) _build_static=no ;;
|
||||
--enable-profile) _build_profile=yes ;;
|
||||
--disable-profile) _build_profile=no ;;
|
||||
--enable-debug) _build_debug=yes ;;
|
||||
--disable-debug) _build_debug=false ;;
|
||||
--enable-debug) _build_debug=yes ;;
|
||||
--disable-debug) _build_debug=no ;;
|
||||
--enable-release) _build_release=yes ;;
|
||||
--disable-release) _build_release=no ;;
|
||||
--with-sdl-prefix=*)
|
||||
arg=`echo $ac_option | cut -d '=' -f 2`
|
||||
_sdlpath="$arg:$arg/bin"
|
||||
|
@ -277,7 +280,7 @@ for ac_option in $@; do
|
|||
ZLIB_CFLAGS="-I$_prefix/include"
|
||||
ZLIB_LIBS="-L$_prefix/lib"
|
||||
;;
|
||||
--with-sqlite-prefix=*)
|
||||
--with-sqlite-prefix=*)
|
||||
_prefix=`echo $ac_option | cut -d '=' -f 2`
|
||||
SQLITE_CFLAGS="-I$_prefix/include"
|
||||
SQLITE_LIBS="-L$_prefix/lib"
|
||||
|
@ -382,7 +385,7 @@ else
|
|||
fi
|
||||
|
||||
for compiler in $compilers; do
|
||||
if test_compiler "$compiler -std=c++14"; then
|
||||
if test_compiler "$compiler -std=c++17"; then
|
||||
CXX=$compiler
|
||||
echo $CXX
|
||||
break
|
||||
|
@ -925,6 +928,10 @@ if test "$_build_debug" = no ; then
|
|||
_build_debug=
|
||||
fi
|
||||
|
||||
if test "$_build_release" = no ; then
|
||||
_build_release=
|
||||
fi
|
||||
|
||||
echo "Creating config.mak"
|
||||
cat > config.mak << EOF
|
||||
# -------- Generated by configure -----------
|
||||
|
@ -958,6 +965,7 @@ DOCDIR := $_docdir
|
|||
DATADIR := $_datadir
|
||||
PROFILE := $_build_profile
|
||||
DEBUG := $_build_debug
|
||||
RELEASE := $_build_release
|
||||
|
||||
$_make_def_HAVE_GCC
|
||||
$_make_def_HAVE_CLANG
|
||||
|
|
|
@ -1,3 +1,17 @@
|
|||
stella (6.4) stable; urgency=high
|
||||
|
||||
* Version 6.4 release
|
||||
|
||||
-- Stephen Anthony <sa666666@gmail.com> Mon, 2 Nov 2020 17:09:59 -0230
|
||||
|
||||
|
||||
stella (6.3-1) stable; urgency=high
|
||||
|
||||
* Version 6.3 release
|
||||
|
||||
-- Stephen Anthony <sa666666@gmail.com> Wed, 7 Oct 2020 17:09:59 -0230
|
||||
|
||||
|
||||
stella (6.2.1-1) stable; urgency=high
|
||||
|
||||
* Version 6.2.1 release
|
||||
|
|
|
@ -1 +1 @@
|
|||
9
|
||||
10
|
||||
|
|
|
@ -1,17 +1,39 @@
|
|||
Source: stella
|
||||
Section: games
|
||||
Priority: optional
|
||||
Maintainer: Stephen Anthony <sa666666@gmail.com>
|
||||
Standards-Version: 3.7.2
|
||||
Build-Depends: debhelper (>= 5.0.0), libsdl2-dev, libpng-dev
|
||||
Section: otherosfs
|
||||
Priority: optional
|
||||
Build-Depends: debhelper (>= 10~),
|
||||
libpng-dev,
|
||||
libsdl2-dev,
|
||||
zlib1g-dev
|
||||
Standards-Version: 4.5.0
|
||||
Vcs-Browser: https://github.com/stella-emu/stella/
|
||||
Vcs-Git: https://github.com/stella-emu/stella.git
|
||||
Homepage: https://stella-emu.github.io
|
||||
Rules-Requires-Root: no
|
||||
|
||||
Package: stella
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}
|
||||
Depends: ${misc:Depends},
|
||||
${shlibs:Depends}
|
||||
Recommends: joystick (>= 1:1.5.1)
|
||||
Pre-Depends: ${misc:Pre-Depends}
|
||||
Description: Atari 2600 Emulator for SDL2
|
||||
The Atari 2600 Video Computer System (VCS), introduced in 1977, was
|
||||
the most popular home video game system of the early 1980's. This
|
||||
emulator will run most Atari ROM images, so that you can play your
|
||||
favorite old Atari 2600 games on your PC.
|
||||
Stella is a portable emulator of the old Atari 2600 video-game
|
||||
console. You can play most Atari 2600 games with it.
|
||||
.
|
||||
Homepage: https://stella-emu.github.io
|
||||
Stella's features include:
|
||||
* emulation of Atari 2600 joysticks, keyboards, paddles and driving
|
||||
controllers using the host system's input peripherals;
|
||||
* emulation of trackballs, joysticks, booster grips, driving
|
||||
controllers and the Amiga Mouse using the host system's mouse;
|
||||
* support for real Atari 2600 controllers using the Stelladaptor,
|
||||
2600-daptor or 2600-daptor II;
|
||||
* support for real Atari 7800 controllers using the 2600-daptor II;
|
||||
* support for the speech portion of a real AtariVox device;
|
||||
* support for Supercharger single-load and multi-load games;
|
||||
* emulation of CRT TV features, including texturing, colour bleed,
|
||||
RF noise and phosphor burn-off (requires OpenGL).
|
||||
.
|
||||
An extensive debugger is included, with the Distella disassembler.
|
||||
|
||||
|
|
|
@ -1,29 +1,205 @@
|
|||
This package was debianized first by Tom Lear <tom@ticking.accesscom.com> on
|
||||
Thu, 7 Oct 1999 08:57:16 -0700.
|
||||
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0
|
||||
Upstream-Name: stella
|
||||
Source: https://stella-emu.github.io
|
||||
Copyright: 1995-2020 Bradford W. Mott, Stephen Anthony and the Stella Team
|
||||
License: GPL-2+
|
||||
|
||||
It was downloaded from <https://stella-emu.github.io>
|
||||
Files: *
|
||||
Copyright: 1995-2020 Bradford W. Mott, Stephen Anthony and the Stella
|
||||
Team
|
||||
License: GPL-2+
|
||||
|
||||
Copyright Holder(s): Bradford W. Mott <bwmott@acm.org> and the Stella Team
|
||||
Files: debian/*
|
||||
Copyright: 1998-2004 Tom Lear <tom@trap.mtview.ca.us>
|
||||
2006 Mario Iseli <admin@marioiseli.com>
|
||||
2010-2020 Stephen Kitt <skitt@debian.org>
|
||||
License: GPL-2+
|
||||
|
||||
License:
|
||||
Files:
|
||||
src/common/Stack.hxx
|
||||
src/emucore/FrameBuffer.hxx
|
||||
src/emucore/FSNode.*
|
||||
src/gui/*
|
||||
Copyright: 2002-2004 The ScummVM project
|
||||
License: GPL-2+
|
||||
|
||||
Copyright (C) 1995-2010 Bradford W. Mott <bwmott@acm.org>
|
||||
and the Stella Team
|
||||
Files: src/common/ZipHandler.hxx
|
||||
Copyright: Aaron Giles
|
||||
License: BSD-3
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
.
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
* Neither the name 'MAME' nor the names of its contributors may
|
||||
be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
.
|
||||
THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
|
||||
IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
||||
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
This package is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
Files: src/emucore/MD5.cxx
|
||||
Copyright: 1991-1992, RSA Data Security, Inc.
|
||||
License: RSA
|
||||
License to copy and use this software is granted provided that it is
|
||||
identified as the "RSA Data Security, Inc. MD5 Message-Digest
|
||||
Algorithm" in all material mentioning or referencing this software or
|
||||
this function.
|
||||
.
|
||||
License is also granted to make and use derivative works provided
|
||||
that such works are identified as "derived from the RSA Data
|
||||
Security, Inc. MD5 Message-Digest Algorithm" in all material
|
||||
mentioning or referencing the derived work.
|
||||
.
|
||||
RSA Data Security, Inc. makes no representations concerning either
|
||||
the merchantability of this software or the suitability of this
|
||||
software for any particular purpose. It is provided "as is" without
|
||||
express or implied warranty of any kind.
|
||||
.
|
||||
These notices must be retained in any copies of any part of this
|
||||
documentation and/or software.
|
||||
|
||||
This package is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
Files: src/libpng/*
|
||||
Copyright: 1995-1996 Guy Eric Schalnat, Group 42, Inc.
|
||||
1996-1997 Andreas Dilger
|
||||
1998-2013 Glenn Randers-Pehrson
|
||||
License: libpng
|
||||
The PNG Reference Library is supplied "AS IS". The Contributing
|
||||
Authors and Group 42, Inc. disclaim all warranties, expressed or
|
||||
implied, including, without limitation, the warranties of
|
||||
merchantability and of fitness for any purpose. The Contributing
|
||||
Authors and Group 42, Inc. assume no liability for direct, indirect,
|
||||
incidental, special, exemplary, or consequential damages, which may
|
||||
result from the use of the PNG Reference Library, even if advised of
|
||||
the possibility of such damage.
|
||||
.
|
||||
Permission is hereby granted to use, copy, modify, and distribute
|
||||
this source code, or portions hereof, for any purpose, without fee,
|
||||
subject to the following restrictions:
|
||||
.
|
||||
1. The origin of this source code must not be misrepresented.
|
||||
.
|
||||
2. Altered versions must be plainly marked as such and must not be
|
||||
misrepresented as being the original source.
|
||||
.
|
||||
3. This Copyright notice may not be removed or altered from any
|
||||
source or altered source distribution.
|
||||
.
|
||||
The Contributing Authors and Group 42, Inc. specifically permit,
|
||||
without fee, and encourage the use of this source code as a component
|
||||
to supporting the PNG file format in commercial products. If you use
|
||||
this source code in a product, acknowledgment is not required but
|
||||
would be appreciated.
|
||||
.
|
||||
There is no warranty against interference with your enjoyment of the
|
||||
library or against infringement. There is no warranty that our
|
||||
efforts or the library will fulfill any of your particular purposes
|
||||
or needs. This library is provided with all faults, and the entire
|
||||
risk of satisfactory quality, performance, accuracy, and effort is
|
||||
with the user.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this package; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Files: src/libretro/libretro.h
|
||||
Copyright: 2010-2017 The RetroArch team
|
||||
License: MIT
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
.
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
On Debian systems, the complete text of the GNU General
|
||||
Public License can be found in `/usr/share/common-licenses/GPL'.
|
||||
Files: src/macos/*
|
||||
Copyright: 2005-2006 Mark Grebe
|
||||
License: GPL-2+
|
||||
|
||||
Files: src/tools/convbdf.c
|
||||
Copyright: 2002 Greg Haerr
|
||||
License: GPL-2+
|
||||
|
||||
Files: src/tools/evdev-joystick/*
|
||||
Copyright: 2016 Stephen Anthony
|
||||
License: GPL-2
|
||||
This package is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License, version 2, as
|
||||
published by the Free Software Foundation.
|
||||
.
|
||||
This package is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this package; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
USA.
|
||||
.
|
||||
On Debian systems, the complete text of the GNU General Public
|
||||
License version 2 can be found in
|
||||
`/usr/share/common-licenses/GPL-2'.
|
||||
|
||||
Files: src/zlib/*
|
||||
Copyright: 1995-2012, 2016 Jean-loup Gailly and Mark Adler
|
||||
License: zlib
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any
|
||||
damages arising from the use of this software.
|
||||
.
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute
|
||||
it freely, subject to the following restrictions:
|
||||
.
|
||||
1. The origin of this software must not be misrepresented; you must
|
||||
not claim that you wrote the original software. If you use this
|
||||
software in a product, an acknowledgment in the product
|
||||
documentation would be appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must
|
||||
not be misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
||||
|
||||
License: GPL-2+
|
||||
This package is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or (at
|
||||
your option) any later version.
|
||||
.
|
||||
This package is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
.
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this package; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
|
||||
USA.
|
||||
.
|
||||
On Debian systems, the complete text of the GNU General Public
|
||||
License version 2 can be found in
|
||||
`/usr/share/common-licenses/GPL-2'.
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
usr/bin
|
|
@ -0,0 +1,9 @@
|
|||
Document: stella
|
||||
Title: Stella Manual
|
||||
Author: The Stella Team
|
||||
Abstract: Documentation for the Stella Atari 2600 VCS emulator.
|
||||
Section: Emulators
|
||||
|
||||
Format: HTML
|
||||
Index: /usr/share/doc/stella/index.html
|
||||
Files: /usr/share/doc/stella/*.html
|
|
@ -4,67 +4,26 @@
|
|||
# Uncomment this to turn on verbose mode.
|
||||
#export DH_VERBOSE=1
|
||||
|
||||
# These are used for cross-compiling and for saving the configure script
|
||||
# from having to guess our platform (since we know it already)
|
||||
DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
|
||||
DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
|
||||
DEB_HOST_ARCH ?= $(shell dpkg-architecture -qDEB_HOST_ARCH)
|
||||
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
|
||||
|
||||
CFLAGS = -Wall
|
||||
include /usr/share/dpkg/architecture.mk
|
||||
DPKG_EXPORT_BUILDTOOLS=1
|
||||
-include /usr/share/dpkg/buildtools.mk
|
||||
|
||||
ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
|
||||
CXXFLAGS += -O0
|
||||
else
|
||||
CXXFLAGS += -O2
|
||||
endif
|
||||
%:
|
||||
dh $@ --with autotools_dev
|
||||
|
||||
config.status: configure
|
||||
dh_testdir
|
||||
CXXFLAGS="$(CXXFLAGS)" ./configure --prefix=/usr
|
||||
override_dh_auto_clean:
|
||||
# Generate the minimal config.mak required for "make distclean"
|
||||
test -f config.mak || echo "RM_REC := rm -f -r" > config.mak
|
||||
dh_auto_clean
|
||||
|
||||
build: build-stamp
|
||||
override_dh_auto_configure:
|
||||
./configure --prefix=/usr $(if $(filter $(DEB_BUILD_ARCH),$(DEB_HOST_ARCH)),,--host=$(DEB_HOST_GNU_TYPE)) --enable-release
|
||||
|
||||
build-stamp: config.status
|
||||
dh_testdir
|
||||
$(MAKE)
|
||||
touch build-stamp
|
||||
|
||||
clean:
|
||||
dh_testdir
|
||||
dh_testroot
|
||||
rm -f build-stamp
|
||||
-$(MAKE) distclean
|
||||
|
||||
dh_clean
|
||||
|
||||
install: build
|
||||
dh_testdir
|
||||
dh_testroot
|
||||
dh_clean -k
|
||||
dh_installdirs
|
||||
|
||||
$(MAKE) install DESTDIR=$(CURDIR)/debian/stella
|
||||
|
||||
# Build architecture-independent files here.
|
||||
binary-indep: build install
|
||||
# We have nothing to do by default.
|
||||
|
||||
binary-arch: build install
|
||||
dh_testdir
|
||||
dh_testroot
|
||||
dh_installchangelogs Changes.txt
|
||||
dh_installdocs
|
||||
dh_installmenu
|
||||
# dh_installman $(CURDIR)/debian/stella.6
|
||||
dh_link
|
||||
dh_strip
|
||||
dh_compress
|
||||
dh_fixperms
|
||||
dh_installdeb
|
||||
dh_shlibdeps
|
||||
dh_gencontrol
|
||||
dh_md5sums
|
||||
dh_builddeb
|
||||
|
||||
binary: binary-indep binary-arch
|
||||
.PHONY: build clean binary-indep binary-arch binary install
|
||||
override_dh_auto_install:
|
||||
dh_auto_install
|
||||
# This is also installed as the upstream changelog
|
||||
rm $(CURDIR)/debian/stella/usr/share/doc/stella/Changes.txt
|
||||
# This is overridden by the copyright file
|
||||
rm $(CURDIR)/debian/stella/usr/share/doc/stella/License.txt
|
||||
|
|
|
@ -1,2 +1,4 @@
|
|||
version=3
|
||||
http://sf.net/stella/stella-(.*)-src\.tar\.gz
|
||||
version=4
|
||||
opts="filenamemangle=s%(?:.*?)?v?(\d[\d.]*)\.tar\.gz%stella-$1.tar.gz%" \
|
||||
https://github.com/stella-emu/stella/tags \
|
||||
(?:.*?/)?v?(\d[\d.]*)\.tar\.gz debian uupdate
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<body>
|
||||
|
||||
<center><b><font size="7">Stella</font></b></center>
|
||||
<center><h4><b>Release 6.2.1</b></h4></center>
|
||||
<center><h4><b>Release 6.4</b></h4></center>
|
||||
<center><h1><b>Integrated Debugger</b></h1></center>
|
||||
<center><h4><b>(a work in progress)</b></h4></center>
|
||||
<br>
|
||||
|
@ -227,6 +227,14 @@ tabs from left-to-right, Shift + Control/Cmd + Tab cycles right-to-left.
|
|||
Pressing Tab (or Shift + Tab) cycles between widgets in the current tab (except
|
||||
for in the Prompt Tab, where 'tab' is used for something else).</p>
|
||||
|
||||
<p>Note for the GUI display:
|
||||
<ul>
|
||||
<li>Hexadecimal values are either not prefixed or with '$'.</li>
|
||||
<li>Decimal values are prefixed with '#'.</li>
|
||||
<li>Binary values are prefixed with '%'.</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<p>You can also enter the debugger at emulator startup by use the 'debug'
|
||||
command on the command line, or alternatively within the ROM launcher in
|
||||
'Power-on options':
|
||||
|
@ -753,10 +761,14 @@ that holds 'number of scanlines' on an actual console).</p>
|
|||
<tr><td> _cycleslo</td><td> Lower 32 bits of number of cycles since emulation started</td></tr>
|
||||
<tr><td> _fcount</td><td> Number of frames since emulation started</td></tr>
|
||||
<tr><td> _fcycles</td><td> Number of cycles since frame started</td></tr>
|
||||
<tr><td> _ftimreadcycles</td><td>Number of cycles used by timer reads since frame started</td></tr>
|
||||
<tr><td> _fwsynccycles</td><td>Number of cycles skipped by WSYNC since frame started</td></tr>
|
||||
<tr><td> _icycles</td><td> Number of cycles of last instruction</td></tr>
|
||||
<tr><td> _scan</td><td> Current scanline count</td></tr>
|
||||
<tr><td> _scanend</td><td> Scanline count at end of last frame</td></tr>
|
||||
<tr><td> _scycles</td><td> Number of cycles in current scanline</td></tr>
|
||||
<tr><td> _timwrapread</td><td> Timer read wrapped on this cycle</td></tr>
|
||||
<tr><td> _timwrapwrite</td><td> Timer write wrapped on this cycle</td></tr>
|
||||
<tr><td> _vblank</td><td> Whether vertical blank is enabled (1 or 0)</td></tr>
|
||||
<tr><td> _vsync</td><td> Whether vertical sync is enabled (1 or 0)</td></tr>
|
||||
</table>
|
||||
|
@ -1131,16 +1143,20 @@ as illustrated:</p>
|
|||
<!-- ///////////////////////////////////////////////////////////////////////// -->
|
||||
<br>
|
||||
<h2><a name="TIAInfo"><u>(F)</u> TIA Information</a></h2>
|
||||
<p>To the right of the <a href="#TIADisplay"><b>TIA Display</b></a> area, TIA information is displayed:</p>
|
||||
<p>To the right of the <a href="#TIADisplay"><b>TIA Display</b></a> area, TIA information is displayed (all values are decimal):</p>
|
||||
<p><img src="graphics/debugger_tiainfo.png"></p>
|
||||
<p>The indicators are as follows (note that all these are read-only):</p>
|
||||
<ul>
|
||||
<li><b>Frame Count</b>: The number of frames since this ROM was loaded or reset.</li>
|
||||
<li><b>Frame Cycle</b>: The number of CPU cycles that have been executed this frame since
|
||||
<li><b>Frame Cycls</b>: The number of CPU cycles that have been executed this frame since
|
||||
VSYNC was cleared at scanline 0.</li>
|
||||
<li><b>WSync Cycls</b>: The number of CPU cycles that have been skipped by WSYNC this frame since
|
||||
VSYNC was cleared at scanline 0.</li>
|
||||
<li><b>Timer Cycls</b>: The number of CPU cycles (approximately) that have been used by timer read loops since
|
||||
VSYNC was cleared at scanline 0.</li>
|
||||
<li><b>Total</b>: The total number of CPU cycles since this ROM was loaded or reset.</li>
|
||||
<li><b>Delta</b>: The number of CPU cycles that have been executed since the last debugger
|
||||
interrupt.</li>
|
||||
<li><b>Frame Cnt.</b>: The number of frames since this ROM was loaded or reset.</li>
|
||||
<li><b>Scanline</b>: The scanline that's currently being drawn, and the count from the
|
||||
previous frame. Scanline 0 is the one on which VSYNC is cleared (after being set for
|
||||
3 scanlines, as per the Stella Programmer's Guide).</li>
|
||||
|
@ -1273,10 +1289,9 @@ are lost (they will NOT end up in the Carry flag).</p>
|
|||
<p>This is a spreadsheet-like GUI for inspecting and changing the contents
|
||||
of the 2600's zero-page RAM.</p>
|
||||
<p>You can navigate with either the mouse or the keyboard arrow keys.
|
||||
To change a RAM location, either double-click on it or press Enter while
|
||||
it's highlighted. Enter the new value (hex only for now, sorry), then
|
||||
press Enter to make the change. If you change your mind, press Escape
|
||||
and the original value will be restored. The currently selected RAM cell
|
||||
To change a RAM location, either double-click on it or press 'Enter' while
|
||||
it's highlighted. Enter the new value (hex, other formats using the bottom textboxes), then
|
||||
press 'Enter' to make the change. The currently selected RAM cell
|
||||
can also be changed by using the
|
||||
<a href="#DataOpButtons"><b>Data Operations Buttons</b></a> or the associated
|
||||
shortcut keys.</p>
|
||||
|
@ -1287,7 +1302,8 @@ more comprehensive. It will undo <b>all</b> operations on <b>all</b> cells
|
|||
since you first made a change.</p>
|
||||
<p>The UI objects at the bottom refer to the currently selected RAM cell.
|
||||
The 'Label' textbox shows the label attached to this RAM location (if any),
|
||||
and the other two textboxes show the decimal and binary equivalent value.</p>
|
||||
and the other three textboxes show the hex, decimal and binary equivalent value.
|
||||
The values can be edited here too.</p>
|
||||
|
||||
<p>The remaining buttons to the right are further explained in the next section.</p>
|
||||
|
||||
|
@ -1569,7 +1585,7 @@ Go ahead and try to change something!</p>
|
|||
<p>If applicable, this area shows a detailed breakdown of any extra RAM supported by
|
||||
the bankswitching scheme. Since the bankswitch schemes can greatly vary in operation,
|
||||
this tab will be different for each scheme, but its specific functionality should be
|
||||
self-explanatory. An example of both F8SC (8K Atari + ram) and DPC (Pitfall II) is
|
||||
self-explanatory. An example of both F6SC (16K Atari + ram) and DPC (Pitfall II) is
|
||||
as follows:</p>
|
||||
|
||||
<p><img src="graphics/debugger_ram-f8sc.png"></p>
|
||||
|
|
Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 5.9 KiB |
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 5.0 KiB |
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 77 KiB |
Before Width: | Height: | Size: 9.5 KiB After Width: | Height: | Size: 8.1 KiB |
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.4 KiB |
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.5 KiB |
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 7.8 KiB After Width: | Height: | Size: 8.9 KiB |
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 3.9 KiB |
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 5.1 KiB |
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 5.0 KiB |
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.4 KiB |
Before Width: | Height: | Size: 6.9 KiB After Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 KiB |
After Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 7.8 KiB After Width: | Height: | Size: 9.6 KiB |
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.7 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 44 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 74 KiB |
787
docs/index.html
|
@ -58,7 +58,7 @@
|
|||
|
||||
<center><h1>Stella for RetroN 77</h1></center>
|
||||
<center><h2>Atari 2600 VCS emulator</h2></center>
|
||||
<center>Release 6.2.1</center>
|
||||
<center>Release 6.4</center>
|
||||
<center><h2>Quick Navigation Guide</h2></center>
|
||||
<br/>
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ class BankRomCheat : public Cheat
|
|||
{
|
||||
public:
|
||||
BankRomCheat(OSystem& os, const string& name, const string& code);
|
||||
virtual ~BankRomCheat() = default;
|
||||
~BankRomCheat() override = default;
|
||||
|
||||
bool enable() override;
|
||||
bool disable() override;
|
||||
|
|
|
@ -100,6 +100,7 @@ CheatCodeDialog::CheatCodeDialog(OSystem& osystem, DialogContainer& parent,
|
|||
return (c >= 'a' && c <= 'f') || (c >= '0' && c <= '9');
|
||||
};
|
||||
myCheatInput->setTextFilter(f1, 1);
|
||||
myCheatInput->setToolTip("See Stella documentation for details.", 1);
|
||||
|
||||
addToFocusList(wid);
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ class CheatCodeDialog : public Dialog
|
|||
public:
|
||||
CheatCodeDialog(OSystem& osystem, DialogContainer& parent,
|
||||
const GUI::Font& font);
|
||||
virtual ~CheatCodeDialog();
|
||||
~CheatCodeDialog() override;
|
||||
|
||||
protected:
|
||||
void handleCommand(CommandSender* sender, int cmd, int data, int id) override;
|
||||
|
|
|
@ -24,7 +24,7 @@ class CheetahCheat : public Cheat
|
|||
{
|
||||
public:
|
||||
CheetahCheat(OSystem& os, const string& name, const string& code);
|
||||
virtual ~CheetahCheat() = default;
|
||||
~CheetahCheat() override = default;
|
||||
|
||||
bool enable() override;
|
||||
bool disable() override;
|
||||
|
|
|
@ -24,7 +24,7 @@ class RamCheat : public Cheat
|
|||
{
|
||||
public:
|
||||
RamCheat(OSystem& os, const string& name, const string& code);
|
||||
virtual ~RamCheat() = default;
|
||||
~RamCheat() override = default;
|
||||
|
||||
bool enable() override;
|
||||
bool disable() override;
|
||||
|
|
|
@ -27,6 +27,15 @@ EventHandlerSDL2::EventHandlerSDL2(OSystem& osystem)
|
|||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
#ifdef GUI_SUPPORT
|
||||
{
|
||||
ostringstream buf;
|
||||
myQwertz = int('y') == int(SDL_GetKeyFromScancode(SDL_Scancode(KBDK_Z)));
|
||||
buf << "Keyboard: " << (myQwertz ? "QWERTZ" : "QWERTY");
|
||||
Logger::debug(buf.str());
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef JOYSTICK_SUPPORT
|
||||
if(SDL_InitSubSystem(SDL_INIT_JOYSTICK) < 0)
|
||||
{
|
||||
|
@ -36,6 +45,8 @@ EventHandlerSDL2::EventHandlerSDL2(OSystem& osystem)
|
|||
}
|
||||
Logger::debug("EventHandlerSDL2::EventHandlerSDL2 SDL_INIT_JOYSTICK");
|
||||
#endif
|
||||
|
||||
SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1");
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -58,6 +69,23 @@ void EventHandlerSDL2::enableTextEvents(bool enable)
|
|||
SDL_StopTextInput();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void EventHandlerSDL2::copyText(const string& text) const
|
||||
{
|
||||
SDL_SetClipboardText(text.c_str());
|
||||
};
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
string EventHandlerSDL2::pasteText(string& text) const
|
||||
{
|
||||
if(SDL_HasClipboardText())
|
||||
text = SDL_GetClipboardText();
|
||||
else
|
||||
text = "";
|
||||
|
||||
return text;
|
||||
};
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void EventHandlerSDL2::pollEvent()
|
||||
{
|
||||
|
@ -220,7 +248,6 @@ void EventHandlerSDL2::pollEvent()
|
|||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
EventHandlerSDL2::JoystickSDL2::JoystickSDL2(int idx)
|
||||
: myStick(nullptr)
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ class EventHandlerSDL2 : public EventHandler
|
|||
Create a new SDL2 event handler object
|
||||
*/
|
||||
explicit EventHandlerSDL2(OSystem& osystem);
|
||||
virtual ~EventHandlerSDL2();
|
||||
~EventHandlerSDL2() override;
|
||||
|
||||
private:
|
||||
/**
|
||||
|
@ -44,6 +44,12 @@ class EventHandlerSDL2 : public EventHandler
|
|||
*/
|
||||
void enableTextEvents(bool enable) override;
|
||||
|
||||
/**
|
||||
Clipboard methods.
|
||||
*/
|
||||
void copyText(const string& text) const override;
|
||||
string pasteText(string& text) const override;
|
||||
|
||||
/**
|
||||
Collects and dispatches any pending SDL2 events.
|
||||
*/
|
||||
|
@ -61,7 +67,7 @@ class EventHandlerSDL2 : public EventHandler
|
|||
virtual ~JoystickSDL2();
|
||||
|
||||
private:
|
||||
SDL_Joystick* myStick;
|
||||
SDL_Joystick* myStick{nullptr};
|
||||
};
|
||||
|
||||
private:
|
||||
|
|
|
@ -27,11 +27,11 @@
|
|||
|
||||
#include "ThreadDebugging.hxx"
|
||||
#include "FBSurfaceSDL2.hxx"
|
||||
#include "FrameBufferSDL2.hxx"
|
||||
#include "FBBackendSDL2.hxx"
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
FrameBufferSDL2::FrameBufferSDL2(OSystem& osystem)
|
||||
: FrameBuffer(osystem)
|
||||
FBBackendSDL2::FBBackendSDL2(OSystem& osystem)
|
||||
: myOSystem(osystem)
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
|
@ -43,7 +43,7 @@ FrameBufferSDL2::FrameBufferSDL2(OSystem& osystem)
|
|||
Logger::error(buf.str());
|
||||
throw runtime_error("FATAL ERROR");
|
||||
}
|
||||
Logger::debug("FrameBufferSDL2::FrameBufferSDL2 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 FBSurfaceSDL2 object)
|
||||
|
@ -53,7 +53,7 @@ FrameBufferSDL2::FrameBufferSDL2(OSystem& osystem)
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
FrameBufferSDL2::~FrameBufferSDL2()
|
||||
FBBackendSDL2::~FBBackendSDL2()
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
|
@ -61,12 +61,6 @@ FrameBufferSDL2::~FrameBufferSDL2()
|
|||
|
||||
if(myRenderer)
|
||||
{
|
||||
// Make sure to free surfaces/textures before destroying the renderer itself
|
||||
// Most platforms are fine with doing this in either order, but it seems
|
||||
// that OpenBSD in particular crashes when attempting to destroy textures
|
||||
// *after* the renderer is already destroyed
|
||||
freeSurfaces();
|
||||
|
||||
SDL_DestroyRenderer(myRenderer);
|
||||
myRenderer = nullptr;
|
||||
}
|
||||
|
@ -81,9 +75,9 @@ FrameBufferSDL2::~FrameBufferSDL2()
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FrameBufferSDL2::queryHardware(vector<Common::Size>& fullscreenRes,
|
||||
vector<Common::Size>& windowedRes,
|
||||
VariantList& renderers)
|
||||
void FBBackendSDL2::queryHardware(vector<Common::Size>& fullscreenRes,
|
||||
vector<Common::Size>& windowedRes,
|
||||
VariantList& renderers)
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
|
@ -105,7 +99,7 @@ void FrameBufferSDL2::queryHardware(vector<Common::Size>& fullscreenRes,
|
|||
|
||||
string lastRes = "";
|
||||
|
||||
for (int m = 0; m < numModes; m++)
|
||||
for(int m = 0; m < numModes; ++m)
|
||||
{
|
||||
SDL_DisplayMode mode;
|
||||
ostringstream res;
|
||||
|
@ -196,7 +190,7 @@ void FrameBufferSDL2::queryHardware(vector<Common::Size>& fullscreenRes,
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool FrameBufferSDL2::isCurrentWindowPositioned() const
|
||||
bool FBBackendSDL2::isCurrentWindowPositioned() const
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
|
@ -205,7 +199,7 @@ bool FrameBufferSDL2::isCurrentWindowPositioned() const
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Common::Point FrameBufferSDL2::getCurrentWindowPos() const
|
||||
Common::Point FBBackendSDL2::getCurrentWindowPos() const
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
|
@ -217,7 +211,7 @@ Common::Point FrameBufferSDL2::getCurrentWindowPos() const
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
Int32 FrameBufferSDL2::getCurrentDisplayIndex() const
|
||||
Int32 FBBackendSDL2::getCurrentDisplayIndex() const
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
|
@ -225,7 +219,8 @@ Int32 FrameBufferSDL2::getCurrentDisplayIndex() const
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool FrameBufferSDL2::setVideoMode(const string& title, const VideoMode& mode)
|
||||
bool FBBackendSDL2::setVideoMode(const VideoModeHandler::Mode& mode,
|
||||
int winIdx, const Common::Point& winPos)
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
|
@ -235,26 +230,22 @@ bool FrameBufferSDL2::setVideoMode(const string& title, const VideoMode& mode)
|
|||
|
||||
const bool fullScreen = mode.fsIndex != -1;
|
||||
bool forceCreateRenderer = false;
|
||||
|
||||
// Get windowed window's last display
|
||||
Int32 displayIndex = std::min(myNumDisplays, myOSystem.settings().getInt(getDisplayKey()));
|
||||
// Get windowed window's last position
|
||||
myWindowedPos = myOSystem.settings().getPoint(getPositionKey());
|
||||
Int32 displayIndex = std::min(myNumDisplays, winIdx);
|
||||
|
||||
int posX, posY;
|
||||
|
||||
myCenter = myOSystem.settings().getBool("center");
|
||||
if (myCenter)
|
||||
if(myCenter)
|
||||
posX = posY = SDL_WINDOWPOS_CENTERED_DISPLAY(displayIndex);
|
||||
else
|
||||
{
|
||||
posX = myWindowedPos.x;
|
||||
posY = myWindowedPos.y;
|
||||
posX = winPos.x;
|
||||
posY = winPos.y;
|
||||
|
||||
// Make sure the window is at least partially visibile
|
||||
int x0 = 0, y0 = 0, x1 = 0, y1 = 0;
|
||||
|
||||
for (int display = SDL_GetNumVideoDisplays() - 1; display >= 0; display--)
|
||||
for(int display = SDL_GetNumVideoDisplays() - 1; display >= 0; --display)
|
||||
{
|
||||
SDL_Rect rect;
|
||||
|
||||
|
@ -266,22 +257,28 @@ bool FrameBufferSDL2::setVideoMode(const string& title, const VideoMode& mode)
|
|||
y1 = std::max(y1, rect.y + rect.h);
|
||||
}
|
||||
}
|
||||
posX = BSPF::clamp(posX, x0 - Int32(mode.screen.w) + 50, x1 - 50);
|
||||
posX = BSPF::clamp(posX, x0 - Int32(mode.screenS.w) + 50, x1 - 50);
|
||||
posY = BSPF::clamp(posY, y0 + 50, y1 - 50);
|
||||
}
|
||||
|
||||
#ifdef ADAPTABLE_REFRESH_SUPPORT
|
||||
SDL_DisplayMode adaptedSdlMode;
|
||||
const bool shouldAdapt = fullScreen && myOSystem.settings().getBool("tia.fs_refresh")
|
||||
&& gameRefreshRate()
|
||||
const int gameRefreshRate =
|
||||
myOSystem.hasConsole() ? myOSystem.console().gameRefreshRate() : 0;
|
||||
const bool shouldAdapt = fullScreen
|
||||
&& myOSystem.settings().getBool("tia.fs_refresh")
|
||||
&& gameRefreshRate
|
||||
// take care of 59.94 Hz
|
||||
&& refreshRate() % gameRefreshRate() != 0 && refreshRate() % (gameRefreshRate() - 1) != 0;
|
||||
const bool adaptRefresh = shouldAdapt && adaptRefreshRate(displayIndex, adaptedSdlMode);
|
||||
&& refreshRate() % gameRefreshRate != 0
|
||||
&& refreshRate() % (gameRefreshRate - 1) != 0;
|
||||
const bool adaptRefresh = shouldAdapt &&
|
||||
adaptRefreshRate(displayIndex, adaptedSdlMode);
|
||||
#else
|
||||
const bool adaptRefresh = false;
|
||||
#endif
|
||||
const uInt32 flags = SDL_WINDOW_ALLOW_HIGHDPI
|
||||
| (fullScreen ? adaptRefresh ? SDL_WINDOW_FULLSCREEN : SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
|
||||
| (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
|
||||
|
@ -291,8 +288,8 @@ bool FrameBufferSDL2::setVideoMode(const string& title, const VideoMode& mode)
|
|||
int w, h;
|
||||
|
||||
SDL_GetWindowSize(myWindow, &w, &h);
|
||||
if(d != displayIndex || uInt32(w) != mode.screen.w || uInt32(h) != mode.screen.h
|
||||
|| adaptRefresh)
|
||||
if(d != displayIndex || uInt32(w) != mode.screenS.w ||
|
||||
uInt32(h) != mode.screenS.h || adaptRefresh)
|
||||
{
|
||||
SDL_DestroyWindow(myWindow);
|
||||
myWindow = nullptr;
|
||||
|
@ -302,14 +299,14 @@ bool FrameBufferSDL2::setVideoMode(const string& title, const VideoMode& mode)
|
|||
if(myWindow)
|
||||
{
|
||||
// Even though window size stayed the same, the title may have changed
|
||||
SDL_SetWindowTitle(myWindow, title.c_str());
|
||||
SDL_SetWindowTitle(myWindow, myScreenTitle.c_str());
|
||||
SDL_SetWindowPosition(myWindow, posX, posY);
|
||||
}
|
||||
else
|
||||
{
|
||||
forceCreateRenderer = true;
|
||||
myWindow = SDL_CreateWindow(title.c_str(), posX, posY,
|
||||
mode.screen.w, mode.screen.h, flags);
|
||||
myWindow = SDL_CreateWindow(myScreenTitle.c_str(), posX, posY,
|
||||
mode.screenS.w, mode.screenS.h, flags);
|
||||
if(myWindow == nullptr)
|
||||
{
|
||||
string msg = "ERROR: Unable to open SDL window: " + string(SDL_GetError());
|
||||
|
@ -332,7 +329,8 @@ bool FrameBufferSDL2::setVideoMode(const string& title, const VideoMode& mode)
|
|||
{
|
||||
ostringstream msg;
|
||||
|
||||
msg << "Display refresh rate changed to " << adaptedSdlMode.refresh_rate << " Hz";
|
||||
msg << "Display refresh rate changed to "
|
||||
<< adaptedSdlMode.refresh_rate << " Hz";
|
||||
Logger::info(msg.str());
|
||||
}
|
||||
}
|
||||
|
@ -342,8 +340,11 @@ bool FrameBufferSDL2::setVideoMode(const string& title, const VideoMode& mode)
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool FrameBufferSDL2::adaptRefreshRate(Int32 displayIndex, SDL_DisplayMode& adaptedSdlMode)
|
||||
bool FBBackendSDL2::adaptRefreshRate(Int32 displayIndex,
|
||||
SDL_DisplayMode& adaptedSdlMode)
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
SDL_DisplayMode sdlMode;
|
||||
|
||||
if(SDL_GetCurrentDisplayMode(displayIndex, &sdlMode) != 0)
|
||||
|
@ -353,7 +354,8 @@ bool FrameBufferSDL2::adaptRefreshRate(Int32 displayIndex, SDL_DisplayMode& adap
|
|||
}
|
||||
|
||||
const int currentRefreshRate = sdlMode.refresh_rate;
|
||||
const int wantedRefreshRate = gameRefreshRate();
|
||||
const int wantedRefreshRate =
|
||||
myOSystem.hasConsole() ? myOSystem.console().gameRefreshRate() : 0;
|
||||
// Take care of rounded refresh rates (e.g. 59.94 Hz)
|
||||
float factor = std::min(float(currentRefreshRate) / wantedRefreshRate,
|
||||
float(currentRefreshRate) / (wantedRefreshRate - 1));
|
||||
|
@ -397,8 +399,10 @@ bool FrameBufferSDL2::adaptRefreshRate(Int32 displayIndex, SDL_DisplayMode& adap
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool FrameBufferSDL2::createRenderer(bool force)
|
||||
bool FBBackendSDL2::createRenderer(bool force)
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
// A new renderer is only created when necessary:
|
||||
// - new myWindow (force = true)
|
||||
// - no renderer existing
|
||||
|
@ -450,7 +454,7 @@ bool FrameBufferSDL2::createRenderer(bool force)
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FrameBufferSDL2::setTitle(const string& title)
|
||||
void FBBackendSDL2::setTitle(const string& title)
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
|
@ -461,7 +465,7 @@ void FrameBufferSDL2::setTitle(const string& title)
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
string FrameBufferSDL2::about() const
|
||||
string FBBackendSDL2::about() const
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
|
@ -483,7 +487,7 @@ string FrameBufferSDL2::about() const
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FrameBufferSDL2::showCursor(bool show)
|
||||
void FBBackendSDL2::showCursor(bool show)
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
|
@ -491,7 +495,7 @@ void FrameBufferSDL2::showCursor(bool show)
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FrameBufferSDL2::grabMouse(bool grab)
|
||||
void FBBackendSDL2::grabMouse(bool grab)
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
|
@ -499,7 +503,7 @@ void FrameBufferSDL2::grabMouse(bool grab)
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool FrameBufferSDL2::fullScreen() const
|
||||
bool FBBackendSDL2::fullScreen() const
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
|
@ -511,7 +515,7 @@ bool FrameBufferSDL2::fullScreen() const
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
int FrameBufferSDL2::refreshRate() const
|
||||
int FBBackendSDL2::refreshRate() const
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
|
@ -528,20 +532,7 @@ int FrameBufferSDL2::refreshRate() const
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
int FrameBufferSDL2::gameRefreshRate() const
|
||||
{
|
||||
if(myOSystem.hasConsole())
|
||||
{
|
||||
const string format = myOSystem.console().getFormatString();
|
||||
const bool isNtsc = format == "NTSC" || format == "PAL60" || format == "SECAM60";
|
||||
|
||||
return isNtsc ? 60 : 50; // The code will take care of 59/49 Hz
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FrameBufferSDL2::renderToScreen()
|
||||
void FBBackendSDL2::renderToScreen()
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
|
@ -550,7 +541,7 @@ void FrameBufferSDL2::renderToScreen()
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FrameBufferSDL2::setWindowIcon()
|
||||
void FBBackendSDL2::setWindowIcon()
|
||||
{
|
||||
#if !defined(BSPF_MACOS) && !defined(RETRON77)
|
||||
#include "stella_icon.hxx"
|
||||
|
@ -564,19 +555,20 @@ void FrameBufferSDL2::setWindowIcon()
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
unique_ptr<FBSurface> FrameBufferSDL2::createSurface(
|
||||
unique_ptr<FBSurface> FBBackendSDL2::createSurface(
|
||||
uInt32 w,
|
||||
uInt32 h,
|
||||
FrameBuffer::ScalingInterpolation interpolation,
|
||||
ScalingInterpolation inter,
|
||||
const uInt32* data
|
||||
) const
|
||||
{
|
||||
return make_unique<FBSurfaceSDL2>(const_cast<FrameBufferSDL2&>(*this), w, h, interpolation, data);
|
||||
return make_unique<FBSurfaceSDL2>
|
||||
(const_cast<FBBackendSDL2&>(*this), w, h, inter, data);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FrameBufferSDL2::readPixels(uInt8* pixels, uInt32 pitch,
|
||||
const Common::Rect& rect) const
|
||||
void FBBackendSDL2::readPixels(uInt8* pixels, uInt32 pitch,
|
||||
const Common::Rect& rect) const
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
|
@ -588,7 +580,7 @@ void FrameBufferSDL2::readPixels(uInt8* pixels, uInt32 pitch,
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FrameBufferSDL2::clear()
|
||||
void FBBackendSDL2::clear()
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
|
@ -596,49 +588,34 @@ void FrameBufferSDL2::clear()
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
SDL_Renderer* FrameBufferSDL2::renderer()
|
||||
{
|
||||
return myRenderer;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool FrameBufferSDL2::isInitialized() const
|
||||
{
|
||||
return myRenderer != nullptr;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
const SDL_PixelFormat& FrameBufferSDL2::pixelFormat() const
|
||||
{
|
||||
return *myPixelFormat;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FrameBufferSDL2::detectFeatures()
|
||||
void FBBackendSDL2::detectFeatures()
|
||||
{
|
||||
myRenderTargetSupport = detectRenderTargetSupport();
|
||||
|
||||
if (myRenderer) {
|
||||
if (!myRenderTargetSupport) {
|
||||
Logger::info("Render targets are not supported --- QIS not available");
|
||||
}
|
||||
}
|
||||
if(myRenderer && !myRenderTargetSupport)
|
||||
Logger::info("Render targets are not supported --- QIS not available");
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool FrameBufferSDL2::detectRenderTargetSupport()
|
||||
bool FBBackendSDL2::detectRenderTargetSupport()
|
||||
{
|
||||
if (myRenderer == nullptr) return false;
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
if(myRenderer == nullptr)
|
||||
return false;
|
||||
|
||||
SDL_RendererInfo info;
|
||||
|
||||
SDL_GetRendererInfo(myRenderer, &info);
|
||||
|
||||
if (!(info.flags & SDL_RENDERER_TARGETTEXTURE)) return false;
|
||||
if(!(info.flags & SDL_RENDERER_TARGETTEXTURE))
|
||||
return false;
|
||||
|
||||
SDL_Texture* tex = SDL_CreateTexture(myRenderer, myPixelFormat->format, SDL_TEXTUREACCESS_TARGET, 16, 16);
|
||||
SDL_Texture* tex =
|
||||
SDL_CreateTexture(myRenderer, myPixelFormat->format,
|
||||
SDL_TEXTUREACCESS_TARGET, 16, 16);
|
||||
|
||||
if (!tex) return false;
|
||||
if(!tex)
|
||||
return false;
|
||||
|
||||
int sdlError = SDL_SetRenderTarget(myRenderer, tex);
|
||||
SDL_SetRenderTarget(myRenderer, nullptr);
|
||||
|
@ -649,20 +626,17 @@ bool FrameBufferSDL2::detectRenderTargetSupport()
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool FrameBufferSDL2::hasRenderTargetSupport() const
|
||||
void FBBackendSDL2::determineDimensions()
|
||||
{
|
||||
return myRenderTargetSupport;
|
||||
}
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FrameBufferSDL2::determineDimensions()
|
||||
{
|
||||
SDL_GetWindowSize(myWindow, &myWindowW, &myWindowH);
|
||||
|
||||
if (myRenderer == nullptr) {
|
||||
if(myRenderer == nullptr)
|
||||
{
|
||||
myRenderW = myWindowW;
|
||||
myRenderH = myWindowH;
|
||||
} else {
|
||||
SDL_GetRendererOutputSize(myRenderer, &myRenderW, &myRenderH);
|
||||
}
|
||||
else
|
||||
SDL_GetRendererOutputSize(myRenderer, &myRenderW, &myRenderH);
|
||||
}
|
|
@ -15,8 +15,8 @@
|
|||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//============================================================================
|
||||
|
||||
#ifndef FRAMEBUFFER_SDL2_HXX
|
||||
#define FRAMEBUFFER_SDL2_HXX
|
||||
#ifndef FB_BACKEND_SDL2_HXX
|
||||
#define FB_BACKEND_SDL2_HXX
|
||||
|
||||
#include "SDL_lib.hxx"
|
||||
|
||||
|
@ -24,27 +24,55 @@ class OSystem;
|
|||
class FBSurfaceSDL2;
|
||||
|
||||
#include "bspf.hxx"
|
||||
#include "FrameBuffer.hxx"
|
||||
#include "FBBackend.hxx"
|
||||
|
||||
/**
|
||||
This class implements a standard SDL2 2D, hardware accelerated framebuffer.
|
||||
Behind the scenes, it may be using Direct3D, OpenGL(ES), etc.
|
||||
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 FrameBufferSDL2 : public FrameBuffer
|
||||
class FBBackendSDL2 : public FBBackend
|
||||
{
|
||||
public:
|
||||
/**
|
||||
Creates a new SDL2 framebuffer
|
||||
*/
|
||||
explicit FrameBufferSDL2(OSystem& osystem);
|
||||
virtual ~FrameBufferSDL2();
|
||||
explicit FBBackendSDL2(OSystem& osystem);
|
||||
~FBBackendSDL2() override;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// The following are derived from public methods in FrameBuffer.hxx
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
public:
|
||||
/**
|
||||
Get a pointer to the SDL renderer.
|
||||
*/
|
||||
SDL_Renderer* renderer() { return myRenderer; }
|
||||
|
||||
/**
|
||||
Is the renderer initialized?
|
||||
*/
|
||||
bool isInitialized() const { return myRenderer != nullptr; }
|
||||
|
||||
/**
|
||||
Get the SDL pixel format.
|
||||
*/
|
||||
const SDL_PixelFormat& pixelFormat() const { return *myPixelFormat; }
|
||||
|
||||
/**
|
||||
Does the renderer support render targets?
|
||||
*/
|
||||
bool hasRenderTargetSupport() const { return myRenderTargetSupport; }
|
||||
|
||||
/**
|
||||
Transform from window to renderer coordinates, x direction
|
||||
*/
|
||||
int scaleX(int x) const override { return (x * myRenderW) / myWindowW; }
|
||||
|
||||
/**
|
||||
Transform from window to renderer coordinates, y direction
|
||||
*/
|
||||
int scaleY(int y) const override { return (y * myRenderH) / myWindowH; }
|
||||
|
||||
protected:
|
||||
/**
|
||||
Updates window title.
|
||||
|
||||
|
@ -93,7 +121,8 @@ class FrameBufferSDL2 : public FrameBuffer
|
|||
@param pitch The pitch (in bytes) for the pixel data
|
||||
@param rect The bounding rectangle for the buffer
|
||||
*/
|
||||
void readPixels(uInt8* buffer, uInt32 pitch, const Common::Rect& rect) const override;
|
||||
void readPixels(uInt8* buffer, uInt32 pitch,
|
||||
const Common::Rect& rect) const override;
|
||||
|
||||
/**
|
||||
This method is called to query if the current window is not centered
|
||||
|
@ -110,6 +139,7 @@ class FrameBufferSDL2 : public FrameBuffer
|
|||
@return The position of the currently displayed window
|
||||
*/
|
||||
Common::Point getCurrentWindowPos() const override;
|
||||
|
||||
/**
|
||||
This method is called to query the video hardware for the index
|
||||
of the display the current window is displayed on
|
||||
|
@ -124,40 +154,6 @@ class FrameBufferSDL2 : public FrameBuffer
|
|||
*/
|
||||
void clear() override;
|
||||
|
||||
/**
|
||||
Get a pointer to the SDL renderer.
|
||||
*/
|
||||
SDL_Renderer* renderer();
|
||||
|
||||
/**
|
||||
Get the SDL pixel format.
|
||||
*/
|
||||
const SDL_PixelFormat& pixelFormat() const;
|
||||
|
||||
/**
|
||||
Is the renderer initialized?
|
||||
*/
|
||||
bool isInitialized() const;
|
||||
|
||||
/**
|
||||
Does the renderer support render targets?
|
||||
*/
|
||||
bool hasRenderTargetSupport() const;
|
||||
|
||||
/**
|
||||
Transform from window to renderer coordinates, x direction
|
||||
*/
|
||||
int scaleX(int x) const override { return (x * myRenderW) / myWindowW; }
|
||||
|
||||
/**
|
||||
Transform from window to renderer coordinates, y direction
|
||||
*/
|
||||
int scaleY(int y) const override { return (y * myRenderH) / myWindowH; }
|
||||
|
||||
protected:
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// The following are derived from protected methods in FrameBuffer.hxx
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
This method is called to query and initialize the video hardware
|
||||
for desktop and fullscreen resolution information. Since several
|
||||
|
@ -174,45 +170,28 @@ class FrameBufferSDL2 : public FrameBuffer
|
|||
/**
|
||||
This method is called to change to the given video mode.
|
||||
|
||||
@param title The title for the created window
|
||||
@param mode The video mode to use
|
||||
@param mode The video mode to use
|
||||
@param winIdx The display/monitor that the window last opened on
|
||||
@param winPos The position that the window last opened at
|
||||
|
||||
@return False on any errors, else true
|
||||
*/
|
||||
bool setVideoMode(const string& title, const VideoMode& mode) override;
|
||||
|
||||
/**
|
||||
Checks if the display refresh rate should be adapted to game refresh rate in (real) fullscreen mode
|
||||
|
||||
@param displayIndex The display which should be checked
|
||||
@param adaptedSdlMode The best matching mode if the refresh rate should be changed
|
||||
|
||||
@return True if the refresh rate should be changed
|
||||
*/
|
||||
bool adaptRefreshRate(Int32 displayIndex, SDL_DisplayMode& adaptedSdlMode);
|
||||
|
||||
/**
|
||||
Create a new renderer if required
|
||||
|
||||
@param force If true, force new renderer creation
|
||||
|
||||
@return False on any errors, else true
|
||||
*/
|
||||
bool createRenderer(bool force);
|
||||
bool setVideoMode(const VideoModeHandler::Mode& mode,
|
||||
int winIdx, const Common::Point& winPos) override;
|
||||
|
||||
/**
|
||||
This method is called to create a surface with the given attributes.
|
||||
|
||||
@param w The requested width of the new surface.
|
||||
@param h The requested height of the new surface.
|
||||
@param interpolation Interpolation mode
|
||||
@param data If non-null, use the given data values as a static surface
|
||||
@param w The requested width of the new surface.
|
||||
@param h The requested height of the new surface.
|
||||
@param inter Interpolation mode
|
||||
@param data If non-null, use the given data values as a static surface
|
||||
*/
|
||||
unique_ptr<FBSurface>
|
||||
createSurface(
|
||||
uInt32 w,
|
||||
uInt32 h,
|
||||
FrameBuffer::ScalingInterpolation interpolation,
|
||||
ScalingInterpolation inter,
|
||||
const uInt32* data
|
||||
) const override;
|
||||
|
||||
|
@ -222,28 +201,49 @@ class FrameBufferSDL2 : public FrameBuffer
|
|||
void grabMouse(bool grab) override;
|
||||
|
||||
/**
|
||||
Set the icon for the main SDL window.
|
||||
*/
|
||||
void setWindowIcon() override;
|
||||
|
||||
/**
|
||||
This method is called to provide information about the FrameBuffer.
|
||||
This method is called to provide information about the backend.
|
||||
*/
|
||||
string about() const override;
|
||||
|
||||
/**
|
||||
Create a new renderer if required.
|
||||
|
||||
@param force If true, force new renderer creation
|
||||
|
||||
@return False on any errors, else true
|
||||
*/
|
||||
bool createRenderer(bool force);
|
||||
|
||||
/**
|
||||
This method must be called after all drawing is done, and indicates
|
||||
that the buffers should be pushed to the physical screen.
|
||||
*/
|
||||
void renderToScreen() override;
|
||||
|
||||
/**
|
||||
Retrieve the current display's refresh rate, or 0 if no window.
|
||||
*/
|
||||
int refreshRate() const override;
|
||||
|
||||
/**
|
||||
Checks if the display refresh rate should be adapted to game refresh
|
||||
rate in (real) fullscreen mode.
|
||||
|
||||
@param displayIndex The display which should be checked
|
||||
@param adaptedSdlMode The best matching mode if the refresh rate
|
||||
should be changed
|
||||
|
||||
@return True if the refresh rate should be changed
|
||||
*/
|
||||
bool adaptRefreshRate(Int32 displayIndex, SDL_DisplayMode& adaptedSdlMode);
|
||||
|
||||
/**
|
||||
After the renderer has been created, detect the features it supports.
|
||||
*/
|
||||
void detectFeatures();
|
||||
|
||||
/**
|
||||
Detect render target support;
|
||||
Detect render target support.
|
||||
*/
|
||||
bool detectRenderTargetSupport();
|
||||
|
||||
|
@ -253,16 +253,13 @@ class FrameBufferSDL2 : public FrameBuffer
|
|||
void determineDimensions();
|
||||
|
||||
/**
|
||||
Retrieve the current display's refresh rate, or 0 if no window
|
||||
Set the icon for the main SDL window.
|
||||
*/
|
||||
int refreshRate() const override;
|
||||
|
||||
/**
|
||||
Retrieve the current game's refresh rate, or 60 if no game
|
||||
*/
|
||||
int gameRefreshRate() const;
|
||||
void setWindowIcon();
|
||||
|
||||
private:
|
||||
OSystem& myOSystem;
|
||||
|
||||
// The SDL video buffer
|
||||
SDL_Window* myWindow{nullptr};
|
||||
SDL_Renderer* myRenderer{nullptr};
|
||||
|
@ -273,22 +270,25 @@ class FrameBufferSDL2 : public FrameBuffer
|
|||
// Center setting of current window
|
||||
bool myCenter{false};
|
||||
|
||||
// last position of windowed window
|
||||
Common::Point myWindowedPos;
|
||||
|
||||
// Does the renderer support render targets?
|
||||
bool myRenderTargetSupport{false};
|
||||
|
||||
// Title of the main window/screen
|
||||
string myScreenTitle;
|
||||
|
||||
// Number of displays
|
||||
int myNumDisplays{1};
|
||||
|
||||
// Window and renderer dimensions
|
||||
int myWindowW{0}, myWindowH{0}, myRenderW{0}, myRenderH{0};
|
||||
|
||||
private:
|
||||
// Following constructors and assignment operators not supported
|
||||
FrameBufferSDL2() = delete;
|
||||
FrameBufferSDL2(const FrameBufferSDL2&) = delete;
|
||||
FrameBufferSDL2(FrameBufferSDL2&&) = delete;
|
||||
FrameBufferSDL2& operator=(const FrameBufferSDL2&) = delete;
|
||||
FrameBufferSDL2& operator=(FrameBufferSDL2&&) = delete;
|
||||
FBBackendSDL2() = delete;
|
||||
FBBackendSDL2(const FBBackendSDL2&) = delete;
|
||||
FBBackendSDL2(FBBackendSDL2&&) = delete;
|
||||
FBBackendSDL2& operator=(const FBBackendSDL2&) = delete;
|
||||
FBBackendSDL2& operator=(FBBackendSDL2&&) = delete;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -22,16 +22,16 @@
|
|||
#include "sdl_blitter/BlitterFactory.hxx"
|
||||
|
||||
namespace {
|
||||
BlitterFactory::ScalingAlgorithm scalingAlgorithm(FrameBuffer::ScalingInterpolation interpolation)
|
||||
BlitterFactory::ScalingAlgorithm scalingAlgorithm(ScalingInterpolation inter)
|
||||
{
|
||||
switch (interpolation) {
|
||||
case FrameBuffer::ScalingInterpolation::none:
|
||||
switch (inter) {
|
||||
case ScalingInterpolation::none:
|
||||
return BlitterFactory::ScalingAlgorithm::nearestNeighbour;
|
||||
|
||||
case FrameBuffer::ScalingInterpolation::blur:
|
||||
case ScalingInterpolation::blur:
|
||||
return BlitterFactory::ScalingAlgorithm::bilinear;
|
||||
|
||||
case FrameBuffer::ScalingInterpolation::sharp:
|
||||
case ScalingInterpolation::sharp:
|
||||
return BlitterFactory::ScalingAlgorithm::quasiInteger;
|
||||
|
||||
default:
|
||||
|
@ -41,12 +41,12 @@ namespace {
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
FBSurfaceSDL2::FBSurfaceSDL2(FrameBufferSDL2& buffer,
|
||||
FBSurfaceSDL2::FBSurfaceSDL2(FBBackendSDL2& backend,
|
||||
uInt32 width, uInt32 height,
|
||||
FrameBuffer::ScalingInterpolation interpolation,
|
||||
ScalingInterpolation inter,
|
||||
const uInt32* staticData)
|
||||
: myFB(buffer),
|
||||
myInterpolationMode(interpolation)
|
||||
: myBackend(backend),
|
||||
myInterpolationMode(inter)
|
||||
{
|
||||
createSurface(width, height, staticData);
|
||||
}
|
||||
|
@ -104,41 +104,49 @@ const Common::Rect& FBSurfaceSDL2::dstRect() const
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FBSurfaceSDL2::setSrcPos(uInt32 x, uInt32 y)
|
||||
{
|
||||
if(x != static_cast<uInt32>(mySrcR.x) || y != static_cast<uInt32>(mySrcR.y))
|
||||
{
|
||||
setSrcPosInternal(x, y);
|
||||
if(setSrcPosInternal(x, y))
|
||||
reinitializeBlitter();
|
||||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FBSurfaceSDL2::setSrcSize(uInt32 w, uInt32 h)
|
||||
{
|
||||
if(w != static_cast<uInt32>(mySrcR.w) || h != static_cast<uInt32>(mySrcR.h))
|
||||
{
|
||||
setSrcSizeInternal(w, h);
|
||||
if(setSrcSizeInternal(w, h))
|
||||
reinitializeBlitter();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FBSurfaceSDL2::setSrcRect(const Common::Rect& r)
|
||||
{
|
||||
const bool posChanged = setSrcPosInternal(r.x(), r.y()),
|
||||
sizeChanged = setSrcSizeInternal(r.w(), r.h());
|
||||
|
||||
if(posChanged || sizeChanged)
|
||||
reinitializeBlitter();
|
||||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FBSurfaceSDL2::setDstPos(uInt32 x, uInt32 y)
|
||||
{
|
||||
if(x != static_cast<uInt32>(myDstR.x) || y != static_cast<uInt32>(myDstR.y))
|
||||
{
|
||||
setDstPosInternal(x, y);
|
||||
if(setDstPosInternal(x, y))
|
||||
reinitializeBlitter();
|
||||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FBSurfaceSDL2::setDstSize(uInt32 w, uInt32 h)
|
||||
{
|
||||
if(w != static_cast<uInt32>(myDstR.w) || h != static_cast<uInt32>(myDstR.h))
|
||||
{
|
||||
setDstSizeInternal(w, h);
|
||||
if(setDstSizeInternal(w, h))
|
||||
reinitializeBlitter();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FBSurfaceSDL2::setDstRect(const Common::Rect& r)
|
||||
{
|
||||
const bool posChanged = setDstPosInternal(r.x(), r.y()),
|
||||
sizeChanged = setDstSizeInternal(r.w(), r.h());
|
||||
|
||||
if(posChanged || sizeChanged)
|
||||
reinitializeBlitter();
|
||||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -176,6 +184,22 @@ void FBSurfaceSDL2::invalidate()
|
|||
SDL_FillRect(mySurface, nullptr, 0);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FBSurfaceSDL2::invalidateRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h)
|
||||
{
|
||||
ASSERT_MAIN_THREAD;
|
||||
|
||||
// Clear the rectangle
|
||||
SDL_Rect tmp;
|
||||
tmp.x = x;
|
||||
tmp.y = y;
|
||||
tmp.w = w;
|
||||
tmp.h = h;
|
||||
// Note: Transparency has to be 0 to clear the rectangle foreground
|
||||
// without affecting the background display.
|
||||
SDL_FillRect(mySurface, &tmp, 0);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FBSurfaceSDL2::free()
|
||||
{
|
||||
|
@ -214,7 +238,7 @@ void FBSurfaceSDL2::createSurface(uInt32 width, uInt32 height,
|
|||
ASSERT_MAIN_THREAD;
|
||||
|
||||
// Create a surface in the same format as the parent GL class
|
||||
const SDL_PixelFormat& pf = myFB.pixelFormat();
|
||||
const SDL_PixelFormat& pf = myBackend.pixelFormat();
|
||||
|
||||
mySurface = SDL_CreateRGBSurface(0, width, height,
|
||||
pf.BitsPerPixel, pf.Rmask, pf.Gmask, pf.Bmask, pf.Amask);
|
||||
|
@ -242,11 +266,13 @@ void FBSurfaceSDL2::createSurface(uInt32 width, uInt32 height,
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FBSurfaceSDL2::reinitializeBlitter()
|
||||
{
|
||||
if (!myBlitter && myFB.isInitialized())
|
||||
myBlitter = BlitterFactory::createBlitter(myFB, scalingAlgorithm(myInterpolationMode));
|
||||
if (!myBlitter && myBackend.isInitialized())
|
||||
myBlitter = BlitterFactory::createBlitter(
|
||||
myBackend, scalingAlgorithm(myInterpolationMode));
|
||||
|
||||
if (myBlitter)
|
||||
myBlitter->reinitialize(mySrcR, myDstR, myAttributes, myIsStatic ? mySurface : nullptr);
|
||||
myBlitter->reinitialize(mySrcR, myDstR, myAttributes,
|
||||
myIsStatic ? mySurface : nullptr);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -256,7 +282,7 @@ void FBSurfaceSDL2::applyAttributes()
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void FBSurfaceSDL2::setScalingInterpolation(FrameBuffer::ScalingInterpolation interpolation)
|
||||
void FBSurfaceSDL2::setScalingInterpolation(ScalingInterpolation interpolation)
|
||||
{
|
||||
if (interpolation == myInterpolationMode) return;
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
#include "bspf.hxx"
|
||||
#include "FBSurface.hxx"
|
||||
#include "FrameBufferSDL2.hxx"
|
||||
#include "FBBackendSDL2.hxx"
|
||||
#include "sdl_blitter/Blitter.hxx"
|
||||
|
||||
/**
|
||||
|
@ -32,10 +32,9 @@
|
|||
class FBSurfaceSDL2 : public FBSurface
|
||||
{
|
||||
public:
|
||||
FBSurfaceSDL2(FrameBufferSDL2& buffer, uInt32 width, uInt32 height,
|
||||
FrameBuffer::ScalingInterpolation interpolation,
|
||||
const uInt32* staticData);
|
||||
virtual ~FBSurfaceSDL2();
|
||||
FBSurfaceSDL2(FBBackendSDL2& backend, uInt32 width, uInt32 height,
|
||||
ScalingInterpolation inter, const uInt32* staticData);
|
||||
~FBSurfaceSDL2() override;
|
||||
|
||||
// Most of the surface drawing primitives are implemented in FBSurface;
|
||||
// the ones implemented here use SDL-specific code for extra performance
|
||||
|
@ -49,38 +48,63 @@ class FBSurfaceSDL2 : public FBSurface
|
|||
const Common::Rect& dstRect() const override;
|
||||
void setSrcPos(uInt32 x, uInt32 y) override;
|
||||
void setSrcSize(uInt32 w, uInt32 h) override;
|
||||
void setSrcRect(const Common::Rect& r) override;
|
||||
void setDstPos(uInt32 x, uInt32 y) override;
|
||||
void setDstSize(uInt32 w, uInt32 h) override;
|
||||
void setDstRect(const Common::Rect& r) override;
|
||||
|
||||
void setVisible(bool visible) override;
|
||||
|
||||
void translateCoords(Int32& x, Int32& y) const override;
|
||||
bool render() override;
|
||||
void invalidate() override;
|
||||
void invalidateRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h) override;
|
||||
|
||||
void free() override;
|
||||
void reload() override;
|
||||
void resize(uInt32 width, uInt32 height) override;
|
||||
|
||||
void setScalingInterpolation(FrameBuffer::ScalingInterpolation) override;
|
||||
void setScalingInterpolation(ScalingInterpolation) override;
|
||||
|
||||
protected:
|
||||
void applyAttributes() override;
|
||||
|
||||
private:
|
||||
inline void setSrcPosInternal(uInt32 x, uInt32 y) {
|
||||
mySrcR.x = x; mySrcR.y = y;
|
||||
mySrcGUIR.moveTo(x, y);
|
||||
inline bool setSrcPosInternal(uInt32 x, uInt32 y) {
|
||||
if(x != static_cast<uInt32>(mySrcR.x) || y != static_cast<uInt32>(mySrcR.y))
|
||||
{
|
||||
mySrcR.x = x; mySrcR.y = y;
|
||||
mySrcGUIR.moveTo(x, y);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
inline void setSrcSizeInternal(uInt32 w, uInt32 h) {
|
||||
mySrcR.w = w; mySrcR.h = h;
|
||||
mySrcGUIR.setWidth(w); mySrcGUIR.setHeight(h);
|
||||
inline bool setSrcSizeInternal(uInt32 w, uInt32 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);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
inline void setDstPosInternal(uInt32 x, uInt32 y) {
|
||||
myDstR.x = x; myDstR.y = y;
|
||||
myDstGUIR.moveTo(x, y);
|
||||
inline bool setDstPosInternal(uInt32 x, uInt32 y) {
|
||||
if(x != static_cast<uInt32>(myDstR.x) || y != static_cast<uInt32>(myDstR.y))
|
||||
{
|
||||
myDstR.x = x; myDstR.y = y;
|
||||
myDstGUIR.moveTo(x, y);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
inline void setDstSizeInternal(uInt32 w, uInt32 h) {
|
||||
myDstR.w = w; myDstR.h = h;
|
||||
myDstGUIR.setWidth(w); myDstGUIR.setHeight(h);
|
||||
inline bool setDstSizeInternal(uInt32 w, uInt32 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);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void createSurface(uInt32 width, uInt32 height, const uInt32* data);
|
||||
|
@ -95,14 +119,14 @@ class FBSurfaceSDL2 : public FBSurface
|
|||
FBSurfaceSDL2& operator=(FBSurfaceSDL2&&) = delete;
|
||||
|
||||
private:
|
||||
FrameBufferSDL2& myFB;
|
||||
FBBackendSDL2& myBackend;
|
||||
|
||||
unique_ptr<Blitter> myBlitter;
|
||||
FrameBuffer::ScalingInterpolation myInterpolationMode
|
||||
{FrameBuffer::ScalingInterpolation::none};
|
||||
ScalingInterpolation myInterpolationMode
|
||||
{ScalingInterpolation::none};
|
||||
|
||||
SDL_Surface* mySurface{nullptr};
|
||||
SDL_Rect mySrcR{0, 0, 0, 0}, myDstR{0, 0, 0, 0};
|
||||
SDL_Rect mySrcR{-1, -1, -1, -1}, myDstR{-1, -1, -1, -1};
|
||||
|
||||
bool myIsVisible{true};
|
||||
bool myIsStatic{false};
|
||||
|
|
|
@ -51,10 +51,10 @@
|
|||
|
||||
#if defined(__LIB_RETRO__)
|
||||
#include "EventHandlerLIBRETRO.hxx"
|
||||
#include "FrameBufferLIBRETRO.hxx"
|
||||
#include "FBBackendLIBRETRO.hxx"
|
||||
#elif defined(SDL_SUPPORT)
|
||||
#include "EventHandlerSDL2.hxx"
|
||||
#include "FrameBufferSDL2.hxx"
|
||||
#include "FBBackendSDL2.hxx"
|
||||
#else
|
||||
#error Unsupported backend!
|
||||
#endif
|
||||
|
@ -128,12 +128,12 @@ class MediaFactory
|
|||
#endif
|
||||
}
|
||||
|
||||
static unique_ptr<FrameBuffer> createVideo(OSystem& osystem)
|
||||
static unique_ptr<FBBackend> createVideoBackend(OSystem& osystem)
|
||||
{
|
||||
#if defined(__LIB_RETRO__)
|
||||
return make_unique<FrameBufferLIBRETRO>(osystem);
|
||||
return make_unique<FBBackendLIBRETRO>(osystem);
|
||||
#elif defined(SDL_SUPPORT)
|
||||
return make_unique<FrameBufferSDL2>(osystem);
|
||||
return make_unique<FBBackendSDL2>(osystem);
|
||||
#else
|
||||
#error Unsupported platform for FrameBuffer!
|
||||
#endif
|
||||
|
|
|
@ -123,8 +123,8 @@ int PhysicalJoystickHandler::add(const PhysicalJoystickPtr& stick)
|
|||
{
|
||||
StickInfo info("", stick);
|
||||
myDatabase.emplace(stick->name, info);
|
||||
setStickDefaultMapping(stick->ID, Event::NoType, EventMode::kEmulationMode, true);
|
||||
setStickDefaultMapping(stick->ID, Event::NoType, EventMode::kMenuMode, true);
|
||||
setStickDefaultMapping(stick->ID, Event::NoType, EventMode::kEmulationMode);
|
||||
setStickDefaultMapping(stick->ID, Event::NoType, EventMode::kMenuMode);
|
||||
}
|
||||
|
||||
return stick->ID;
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
|
||||
#if defined(BSPF_MACOS) || defined(MACOS_KEYS)
|
||||
static constexpr int MOD3 = KBDM_GUI;
|
||||
static constexpr int CMD = KBDM_GUI;
|
||||
static constexpr int OPTION = KBDM_ALT;
|
||||
#else
|
||||
static constexpr int MOD3 = KBDM_ALT;
|
||||
#endif
|
||||
|
@ -60,6 +62,9 @@ PhysicalKeyboardHandler::PhysicalKeyboardHandler(OSystem& system, EventHandler&
|
|||
|
||||
setDefaultMapping(Event::NoType, EventMode::kEmulationMode, updateDefaults);
|
||||
setDefaultMapping(Event::NoType, EventMode::kMenuMode, updateDefaults);
|
||||
#ifdef GUI_SUPPORT
|
||||
setDefaultMapping(Event::NoType, EventMode::kEditMode, updateDefaults);
|
||||
#endif // DEBUG
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -99,6 +104,17 @@ void PhysicalKeyboardHandler::setDefaultKey(EventMapping map, Event::Type event,
|
|||
// Otherwise, only reset the given event
|
||||
bool eraseAll = !updateDefaults && (event == Event::NoType);
|
||||
|
||||
#ifdef GUI_SUPPORT
|
||||
// Swap Y and Z for QWERTZ keyboards
|
||||
if(mode == EventMode::kEditMode && myHandler.isQwertz())
|
||||
{
|
||||
if(map.key == KBDK_Z)
|
||||
map.key = KBDK_Y;
|
||||
else if(map.key == KBDK_Y)
|
||||
map.key = KBDK_Z;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (updateDefaults)
|
||||
{
|
||||
// if there is no existing mapping for the event and
|
||||
|
@ -151,13 +167,22 @@ void PhysicalKeyboardHandler::setDefaultMapping(Event::Type event, EventMode mod
|
|||
setDefaultKey(item, event, EventMode::kMenuMode, updateDefaults);
|
||||
break;
|
||||
|
||||
#ifdef GUI_SUPPORT
|
||||
case EventMode::kEditMode:
|
||||
// Edit mode events are always set because they are not saved
|
||||
for(const auto& item: FixedEditMapping)
|
||||
setDefaultKey(item, event, EventMode::kEditMode);
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void PhysicalKeyboardHandler::defineControllerMappings(const Controller::Type type, Controller::Jack port)
|
||||
void PhysicalKeyboardHandler::defineControllerMappings(
|
||||
const Controller::Type type, Controller::Jack port)
|
||||
{
|
||||
// determine controller events to use
|
||||
switch(type)
|
||||
|
@ -199,7 +224,8 @@ void PhysicalKeyboardHandler::enableEmulationMappings()
|
|||
myKeyMap.eraseMode(EventMode::kEmulationMode);
|
||||
enableCommonMappings();
|
||||
|
||||
// enable right mode first, so that in case of mapping clashes the left controller has preference
|
||||
// enable right mode first, so that in case of mapping clashes the left
|
||||
// controller has preference
|
||||
switch (myRightMode)
|
||||
{
|
||||
case EventMode::kPaddlesMode:
|
||||
|
@ -253,14 +279,16 @@ void PhysicalKeyboardHandler::enableCommonMappings()
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void PhysicalKeyboardHandler::enableMappings(const Event::EventSet& events, EventMode mode)
|
||||
void PhysicalKeyboardHandler::enableMappings(const Event::EventSet& events,
|
||||
EventMode mode)
|
||||
{
|
||||
for (const auto& event : events)
|
||||
enableMapping(event, mode);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void PhysicalKeyboardHandler::enableMapping(const Event::Type event, EventMode mode)
|
||||
void PhysicalKeyboardHandler::enableMapping(const Event::Type event,
|
||||
EventMode mode)
|
||||
{
|
||||
// copy from controller mode into emulation mode
|
||||
KeyMap::MappingArray mappings = myKeyMap.getEventMapping(event, mode);
|
||||
|
@ -270,7 +298,8 @@ void PhysicalKeyboardHandler::enableMapping(const Event::Type event, EventMode m
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
EventMode PhysicalKeyboardHandler::getEventMode(const Event::Type event, const EventMode mode) const
|
||||
EventMode PhysicalKeyboardHandler::getEventMode(const Event::Type event,
|
||||
const EventMode mode) const
|
||||
{
|
||||
if (mode == EventMode::kEmulationMode)
|
||||
{
|
||||
|
@ -356,7 +385,7 @@ bool PhysicalKeyboardHandler::addMapping(Event::Type event, EventMode mode,
|
|||
myKeyMap.erase(EventMode::kKeypadMode, key, mod);
|
||||
myKeyMap.erase(EventMode::kCompuMateMode, key, mod);
|
||||
}
|
||||
else if(evMode != EventMode::kMenuMode)
|
||||
else if(evMode != EventMode::kMenuMode && evMode != EventMode::kEditMode)
|
||||
{
|
||||
// erase identical mapping for kCommonMode
|
||||
myKeyMap.erase(EventMode::kCommonMode, key, mod);
|
||||
|
@ -371,11 +400,12 @@ bool PhysicalKeyboardHandler::addMapping(Event::Type event, EventMode mode,
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void PhysicalKeyboardHandler::handleEvent(StellaKey key, StellaMod mod, bool pressed, bool repeated)
|
||||
void PhysicalKeyboardHandler::handleEvent(StellaKey key, StellaMod mod,
|
||||
bool pressed, bool repeated)
|
||||
{
|
||||
#ifdef BSPF_UNIX
|
||||
// Swallow KBDK_TAB under certain conditions
|
||||
// See commments on 'myAltKeyCounter' for more information
|
||||
// See comments on 'myAltKeyCounter' for more information
|
||||
if(myAltKeyCounter > 1 && key == KBDK_TAB)
|
||||
{
|
||||
myAltKeyCounter = 0;
|
||||
|
@ -431,7 +461,8 @@ void PhysicalKeyboardHandler::handleEvent(StellaKey key, StellaMod mod, bool pre
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultCommonMapping = {
|
||||
PhysicalKeyboardHandler::EventMappingArray
|
||||
PhysicalKeyboardHandler::DefaultCommonMapping = {
|
||||
{Event::ConsoleSelect, KBDK_F1},
|
||||
{Event::ConsoleReset, KBDK_F2},
|
||||
{Event::ConsoleColor, KBDK_F3},
|
||||
|
@ -470,6 +501,7 @@ PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultCommo
|
|||
{Event::VCenterIncrease, KBDK_PAGEDOWN, MOD3},
|
||||
{Event::VSizeAdjustDecrease, KBDK_PAGEDOWN, KBDM_SHIFT | MOD3},
|
||||
{Event::VSizeAdjustIncrease, KBDK_PAGEUP, KBDM_SHIFT | MOD3},
|
||||
{Event::ToggleCorrectAspectRatio, KBDK_C, KBDM_CTRL},
|
||||
{Event::VolumeDecrease, KBDK_LEFTBRACKET, MOD3},
|
||||
{Event::VolumeIncrease, KBDK_RIGHTBRACKET, MOD3},
|
||||
{Event::SoundToggle, KBDK_RIGHTBRACKET, KBDM_CTRL},
|
||||
|
@ -533,8 +565,8 @@ PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultCommo
|
|||
{Event::ToggleTimeMachine, KBDK_T, MOD3},
|
||||
|
||||
#ifdef PNG_SUPPORT
|
||||
{Event::ToggleContSnapshots, KBDK_S, MOD3},
|
||||
{Event::ToggleContSnapshotsFrame, KBDK_S, KBDM_SHIFT | MOD3},
|
||||
{Event::ToggleContSnapshots, KBDK_S, MOD3 | KBDM_CTRL},
|
||||
{Event::ToggleContSnapshotsFrame, KBDK_S, KBDM_SHIFT | MOD3 | KBDM_CTRL},
|
||||
#endif
|
||||
|
||||
{Event::DecreaseAutoFire, KBDK_A, KBDM_SHIFT | KBDM_CTRL},
|
||||
|
@ -587,12 +619,14 @@ PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultCommo
|
|||
};
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultMenuMapping = {
|
||||
PhysicalKeyboardHandler::EventMappingArray
|
||||
PhysicalKeyboardHandler::DefaultMenuMapping = {
|
||||
{Event::UIUp, KBDK_UP},
|
||||
{Event::UIDown, KBDK_DOWN},
|
||||
{Event::UILeft, KBDK_LEFT},
|
||||
{Event::UIRight, KBDK_RIGHT},
|
||||
{Event::UISelect, KBDK_RETURN},
|
||||
{Event::UISelect, KBDK_SPACE},
|
||||
|
||||
{Event::UIHome, KBDK_HOME},
|
||||
{Event::UIEnd, KBDK_END},
|
||||
|
@ -640,6 +674,88 @@ PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultMenuM
|
|||
#endif
|
||||
};
|
||||
|
||||
#ifdef GUI_SUPPORT
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
PhysicalKeyboardHandler::EventMappingArray
|
||||
PhysicalKeyboardHandler::FixedEditMapping = {
|
||||
{Event::MoveLeftChar, KBDK_LEFT},
|
||||
{Event::MoveRightChar, KBDK_RIGHT},
|
||||
{Event::SelectLeftChar, KBDK_LEFT, KBDM_SHIFT},
|
||||
{Event::SelectRightChar, KBDK_RIGHT, KBDM_SHIFT},
|
||||
#if defined(BSPF_MACOS) || defined(MACOS_KEYS)
|
||||
{Event::MoveLeftWord, KBDK_LEFT, OPTION},
|
||||
{Event::MoveRightWord, KBDK_RIGHT, OPTION},
|
||||
{Event::MoveHome, KBDK_HOME},
|
||||
{Event::MoveHome, KBDK_A, KBDM_CTRL},
|
||||
{Event::MoveHome, KBDK_LEFT, CMD},
|
||||
{Event::MoveEnd, KBDK_END},
|
||||
{Event::MoveEnd, KBDK_E, KBDM_CTRL},
|
||||
{Event::MoveEnd, KBDK_RIGHT, CMD},
|
||||
{Event::SelectLeftWord, KBDK_LEFT, KBDM_SHIFT | OPTION},
|
||||
{Event::SelectRightWord, KBDK_RIGHT, KBDM_SHIFT | OPTION},
|
||||
{Event::SelectHome, KBDK_HOME, KBDM_SHIFT},
|
||||
{Event::SelectHome, KBDK_LEFT, KBDM_SHIFT | CMD},
|
||||
{Event::SelectHome, KBDK_A, KBDM_CTRL | KBDM_SHIFT},
|
||||
{Event::SelectEnd, KBDK_E, KBDM_SHIFT | KBDM_CTRL},
|
||||
{Event::SelectEnd, KBDK_RIGHT, KBDM_SHIFT | CMD},
|
||||
{Event::SelectEnd, KBDK_END, KBDM_SHIFT},
|
||||
{Event::SelectAll, KBDK_A, CMD},
|
||||
{Event::Delete, KBDK_DELETE},
|
||||
{Event::Delete, KBDK_D, KBDM_CTRL},
|
||||
{Event::DeleteLeftWord, KBDK_W, KBDM_CTRL},
|
||||
{Event::DeleteLeftWord, KBDK_BACKSPACE, OPTION},
|
||||
{Event::DeleteRightWord, KBDK_DELETE, OPTION},
|
||||
{Event::DeleteHome, KBDK_U, KBDM_CTRL},
|
||||
{Event::DeleteHome, KBDK_BACKSPACE, CMD},
|
||||
{Event::DeleteEnd, KBDK_K, KBDM_CTRL},
|
||||
{Event::Backspace, KBDK_BACKSPACE},
|
||||
{Event::Undo, KBDK_Z, CMD},
|
||||
{Event::Redo, KBDK_Y, CMD},
|
||||
{Event::Redo, KBDK_Z, KBDM_SHIFT | CMD},
|
||||
{Event::Cut, KBDK_X, CMD},
|
||||
{Event::Copy, KBDK_C, CMD},
|
||||
{Event::Paste, KBDK_V, CMD},
|
||||
#else
|
||||
{Event::MoveLeftWord, KBDK_LEFT, KBDM_CTRL},
|
||||
{Event::MoveRightWord, KBDK_RIGHT, KBDM_CTRL},
|
||||
{Event::MoveHome, KBDK_HOME},
|
||||
{Event::MoveEnd, KBDK_END},
|
||||
{Event::SelectLeftWord, KBDK_LEFT, KBDM_SHIFT | KBDM_CTRL},
|
||||
{Event::SelectRightWord, KBDK_RIGHT, KBDM_SHIFT | KBDM_CTRL},
|
||||
{Event::SelectHome, KBDK_HOME, KBDM_SHIFT},
|
||||
{Event::SelectEnd, KBDK_END, KBDM_SHIFT},
|
||||
{Event::SelectAll, KBDK_A, KBDM_CTRL},
|
||||
{Event::Delete, KBDK_DELETE},
|
||||
{Event::Delete, KBDK_KP_PERIOD},
|
||||
{Event::Delete, KBDK_D, KBDM_CTRL},
|
||||
{Event::DeleteLeftWord, KBDK_BACKSPACE, KBDM_CTRL},
|
||||
{Event::DeleteLeftWord, KBDK_W, KBDM_CTRL},
|
||||
{Event::DeleteRightWord, KBDK_DELETE, KBDM_CTRL},
|
||||
{Event::DeleteRightWord, KBDK_D, KBDM_ALT},
|
||||
{Event::DeleteHome, KBDK_HOME, KBDM_CTRL},
|
||||
{Event::DeleteHome, KBDK_U, KBDM_CTRL},
|
||||
{Event::DeleteEnd, KBDK_END, KBDM_CTRL},
|
||||
{Event::DeleteEnd, KBDK_K, KBDM_CTRL},
|
||||
{Event::Backspace, KBDK_BACKSPACE},
|
||||
{Event::Undo, KBDK_Z, KBDM_CTRL},
|
||||
{Event::Undo, KBDK_BACKSPACE, KBDM_ALT},
|
||||
{Event::Redo, KBDK_Y, KBDM_CTRL},
|
||||
{Event::Redo, KBDK_Z, KBDM_SHIFT | KBDM_CTRL},
|
||||
{Event::Redo, KBDK_BACKSPACE, KBDM_SHIFT | KBDM_ALT},
|
||||
{Event::Cut, KBDK_X, KBDM_CTRL},
|
||||
{Event::Cut, KBDK_DELETE, KBDM_SHIFT},
|
||||
{Event::Cut, KBDK_KP_PERIOD, KBDM_SHIFT},
|
||||
{Event::Copy, KBDK_C, KBDM_CTRL},
|
||||
{Event::Copy, KBDK_INSERT, KBDM_CTRL},
|
||||
{Event::Paste, KBDK_V, KBDM_CTRL},
|
||||
{Event::Paste, KBDK_INSERT, KBDM_SHIFT},
|
||||
#endif
|
||||
{Event::EndEdit, KBDK_RETURN},
|
||||
{Event::EndEdit, KBDK_KP_ENTER},
|
||||
{Event::AbortEdit, KBDK_ESCAPE},
|
||||
};
|
||||
#endif
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultJoystickMapping = {
|
||||
{Event::JoystickZeroUp, KBDK_UP},
|
||||
|
@ -659,6 +775,7 @@ PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultJoyst
|
|||
{Event::JoystickZeroFire9, KBDK_5},
|
||||
{Event::JoystickZeroFire9, KBDK_RCTRL},
|
||||
{Event::JoystickZeroFire9, KBDK_KP_3},
|
||||
|
||||
{Event::JoystickOneUp, KBDK_Y},
|
||||
{Event::JoystickOneDown, KBDK_H},
|
||||
{Event::JoystickOneLeft, KBDK_G},
|
||||
|
@ -666,10 +783,27 @@ PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultJoyst
|
|||
{Event::JoystickOneFire, KBDK_F},
|
||||
{Event::JoystickOneFire5, KBDK_6},
|
||||
{Event::JoystickOneFire9, KBDK_7},
|
||||
|
||||
{Event::JoystickTwoUp, KBDK_UP, KBDM_SHIFT},
|
||||
{Event::JoystickTwoDown, KBDK_DOWN, KBDM_SHIFT},
|
||||
{Event::JoystickTwoLeft, KBDK_LEFT, KBDM_SHIFT},
|
||||
{Event::JoystickTwoRight, KBDK_RIGHT, KBDM_SHIFT},
|
||||
{Event::JoystickTwoUp, KBDK_KP_8, KBDM_SHIFT},
|
||||
{Event::JoystickTwoDown, KBDK_KP_2, KBDM_SHIFT},
|
||||
{Event::JoystickTwoLeft, KBDK_KP_4, KBDM_SHIFT},
|
||||
{Event::JoystickTwoRight, KBDK_KP_6, KBDM_SHIFT},
|
||||
{Event::JoystickTwoFire, KBDK_SPACE, KBDM_SHIFT},
|
||||
|
||||
{Event::JoystickThreeUp, KBDK_Y, KBDM_SHIFT},
|
||||
{Event::JoystickThreeDown, KBDK_H, KBDM_SHIFT},
|
||||
{Event::JoystickThreeLeft, KBDK_G, KBDM_SHIFT},
|
||||
{Event::JoystickThreeRight, KBDK_J, KBDM_SHIFT},
|
||||
{Event::JoystickThreeFire, KBDK_F, KBDM_SHIFT},
|
||||
};
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultPaddleMapping = {
|
||||
PhysicalKeyboardHandler::EventMappingArray
|
||||
PhysicalKeyboardHandler::DefaultPaddleMapping = {
|
||||
{Event::PaddleZeroDecrease, KBDK_RIGHT},
|
||||
{Event::PaddleZeroIncrease, KBDK_LEFT},
|
||||
{Event::PaddleZeroFire, KBDK_SPACE},
|
||||
|
@ -691,7 +825,8 @@ PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultPaddl
|
|||
};
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultKeypadMapping = {
|
||||
PhysicalKeyboardHandler::EventMappingArray
|
||||
PhysicalKeyboardHandler::DefaultKeypadMapping = {
|
||||
{Event::KeyboardZero1, KBDK_1},
|
||||
{Event::KeyboardZero2, KBDK_2},
|
||||
{Event::KeyboardZero3, KBDK_3},
|
||||
|
@ -720,7 +855,8 @@ PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultKeypa
|
|||
};
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::CompuMateMapping = {
|
||||
PhysicalKeyboardHandler::EventMappingArray
|
||||
PhysicalKeyboardHandler::CompuMateMapping = {
|
||||
{Event::CompuMateShift, KBDK_LSHIFT},
|
||||
{Event::CompuMateShift, KBDK_RSHIFT},
|
||||
{Event::CompuMateFunc, KBDK_LCTRL},
|
||||
|
|
|
@ -106,6 +106,7 @@ class PhysicalKeyboardHandler
|
|||
void enableMappings(const Event::EventSet& events, EventMode mode);
|
||||
void enableMapping(const Event::Type event, EventMode mode);
|
||||
|
||||
private:
|
||||
OSystem& myOSystem;
|
||||
EventHandler& myHandler;
|
||||
|
||||
|
@ -132,6 +133,9 @@ class PhysicalKeyboardHandler
|
|||
|
||||
// Controller menu and common emulation mappings
|
||||
static EventMappingArray DefaultMenuMapping;
|
||||
#ifdef GUI_SUPPORT
|
||||
static EventMappingArray FixedEditMapping;
|
||||
#endif
|
||||
static EventMappingArray DefaultCommonMapping;
|
||||
// Controller specific mappings
|
||||
static EventMappingArray DefaultJoystickMapping;
|
||||
|
|
|
@ -267,7 +267,7 @@ void PNGLibrary::toggleContinuousSnapshots(bool perFrame)
|
|||
buf << "Enabling snapshots in " << interval << " second intervals";
|
||||
interval *= uInt32(myOSystem.frameRate());
|
||||
}
|
||||
myOSystem.frameBuffer().showMessage(buf.str());
|
||||
myOSystem.frameBuffer().showTextMessage(buf.str());
|
||||
setContinuousSnapInterval(interval);
|
||||
}
|
||||
else
|
||||
|
@ -276,7 +276,7 @@ void PNGLibrary::toggleContinuousSnapshots(bool perFrame)
|
|||
buf << "Disabling snapshots, generated "
|
||||
<< (mySnapCounter / mySnapInterval)
|
||||
<< " files";
|
||||
myOSystem.frameBuffer().showMessage(buf.str());
|
||||
myOSystem.frameBuffer().showTextMessage(buf.str());
|
||||
setContinuousSnapInterval(0);
|
||||
}
|
||||
}
|
||||
|
@ -296,7 +296,6 @@ void PNGLibrary::takeSnapshot(uInt32 number)
|
|||
|
||||
// Figure out the correct snapshot name
|
||||
string filename;
|
||||
bool showmessage = number == 0;
|
||||
string sspath = myOSystem.snapshotSaveDir().getPath() +
|
||||
(myOSystem.settings().getString("snapname") != "int" ?
|
||||
myOSystem.romFile().getNameWithExt("")
|
||||
|
@ -347,9 +346,9 @@ void PNGLibrary::takeSnapshot(uInt32 number)
|
|||
VarList::push_back(comments, "TV Effects", myOSystem.frameBuffer().tiaSurface().effectsInfo());
|
||||
|
||||
// Now create a PNG snapshot
|
||||
string message = "Snapshot saved";
|
||||
if(myOSystem.settings().getBool("ss1x"))
|
||||
{
|
||||
string message = "Snapshot saved";
|
||||
try
|
||||
{
|
||||
Common::Rect rect;
|
||||
|
@ -360,8 +359,6 @@ void PNGLibrary::takeSnapshot(uInt32 number)
|
|||
{
|
||||
message = e.what();
|
||||
}
|
||||
if(showmessage)
|
||||
myOSystem.frameBuffer().showMessage(message);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -369,7 +366,6 @@ void PNGLibrary::takeSnapshot(uInt32 number)
|
|||
myOSystem.frameBuffer().enableMessages(false);
|
||||
myOSystem.frameBuffer().tiaSurface().renderForSnapshot();
|
||||
|
||||
string message = "Snapshot saved";
|
||||
try
|
||||
{
|
||||
myOSystem.png().saveImage(filename, comments);
|
||||
|
@ -381,9 +377,8 @@ void PNGLibrary::takeSnapshot(uInt32 number)
|
|||
|
||||
// Re-enable old messages
|
||||
myOSystem.frameBuffer().enableMessages(true);
|
||||
if(showmessage)
|
||||
myOSystem.frameBuffer().showMessage(message);
|
||||
}
|
||||
myOSystem.frameBuffer().showTextMessage(message);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
|
|
@ -69,35 +69,69 @@ void PaletteHandler::cyclePalette(int direction)
|
|||
const string palette = toPaletteName(PaletteType(type));
|
||||
const string message = MESSAGES[type] + " palette";
|
||||
|
||||
myOSystem.frameBuffer().showMessage(message);
|
||||
myOSystem.frameBuffer().showTextMessage(message);
|
||||
|
||||
setPalette(palette);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool PaletteHandler::isCustomAdjustable() const
|
||||
{
|
||||
return myCurrentAdjustable >= CUSTOM_START
|
||||
&& myCurrentAdjustable <= CUSTOM_END;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool PaletteHandler::isPhaseShift() const
|
||||
{
|
||||
return myCurrentAdjustable == PHASE_SHIFT;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool PaletteHandler::isRGBScale() const
|
||||
{
|
||||
return myCurrentAdjustable >= RED_SCALE && myCurrentAdjustable <= BLUE_SCALE;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool PaletteHandler::isRGBShift() const
|
||||
{
|
||||
return myCurrentAdjustable >= RED_SHIFT && myCurrentAdjustable <= BLUE_SHIFT;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void PaletteHandler::showAdjustableMessage()
|
||||
{
|
||||
const bool isPhaseShift = myAdjustables[myCurrentAdjustable].value == nullptr;
|
||||
ostringstream msg, buf;
|
||||
|
||||
msg << "Palette " << myAdjustables[myCurrentAdjustable].name;
|
||||
if(isPhaseShift)
|
||||
if(isPhaseShift())
|
||||
{
|
||||
const ConsoleTiming timing = myOSystem.console().timing();
|
||||
const bool isNTSC = timing == ConsoleTiming::ntsc;
|
||||
const float value =
|
||||
myOSystem.console().timing() == ConsoleTiming::pal ? myPhasePAL : myPhaseNTSC;
|
||||
buf << std::fixed << std::setprecision(1) << value << DEGREE;
|
||||
myOSystem.frameBuffer().showMessage(
|
||||
myOSystem.frameBuffer().showGaugeMessage(
|
||||
"Palette phase shift", buf.str(), value,
|
||||
(isNTSC ? DEF_NTSC_SHIFT : DEF_PAL_SHIFT) - MAX_SHIFT,
|
||||
(isNTSC ? DEF_NTSC_SHIFT : DEF_PAL_SHIFT) + MAX_SHIFT);
|
||||
(isNTSC ? DEF_NTSC_SHIFT : DEF_PAL_SHIFT) - MAX_PHASE_SHIFT,
|
||||
(isNTSC ? DEF_NTSC_SHIFT : DEF_PAL_SHIFT) + MAX_PHASE_SHIFT);
|
||||
}
|
||||
else if(isRGBShift())
|
||||
{
|
||||
const float value = *myAdjustables[myCurrentAdjustable].value;
|
||||
|
||||
buf << std::fixed << std::setprecision(1) << value << DEGREE;
|
||||
myOSystem.frameBuffer().showGaugeMessage(
|
||||
msg.str(), buf.str(), value, -MAX_RGB_SHIFT, +MAX_RGB_SHIFT);
|
||||
}
|
||||
else
|
||||
{
|
||||
const int value = scaleTo100(*myAdjustables[myCurrentAdjustable].value);
|
||||
const int value = isRGBScale()
|
||||
? scaleRGBTo100(*myAdjustables[myCurrentAdjustable].value)
|
||||
: scaleTo100(*myAdjustables[myCurrentAdjustable].value);
|
||||
buf << value << "%";
|
||||
myOSystem.frameBuffer().showMessage(
|
||||
myOSystem.frameBuffer().showGaugeMessage(
|
||||
msg.str(), buf.str(), value);
|
||||
}
|
||||
}
|
||||
|
@ -106,15 +140,15 @@ void PaletteHandler::showAdjustableMessage()
|
|||
void PaletteHandler::cycleAdjustable(int direction)
|
||||
{
|
||||
const bool isCustomPalette = SETTING_CUSTOM == myOSystem.settings().getString("palette");
|
||||
bool isPhaseShift;
|
||||
bool isCustomAdj;
|
||||
|
||||
do {
|
||||
myCurrentAdjustable = BSPF::clampw(int(myCurrentAdjustable + direction), 0, NUM_ADJUSTABLES - 1);
|
||||
isPhaseShift = myAdjustables[myCurrentAdjustable].value == nullptr;
|
||||
isCustomAdj = isCustomAdjustable();
|
||||
// skip phase shift when 'Custom' palette is not selected
|
||||
if(!direction && isPhaseShift && !isCustomPalette)
|
||||
if(!direction && isCustomAdj && !isCustomPalette)
|
||||
myCurrentAdjustable++;
|
||||
} while(isPhaseShift && !isCustomPalette);
|
||||
} while(isCustomAdj && !isCustomPalette);
|
||||
|
||||
showAdjustableMessage();
|
||||
}
|
||||
|
@ -122,29 +156,38 @@ void PaletteHandler::cycleAdjustable(int direction)
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void PaletteHandler::changeAdjustable(int adjustable, int direction)
|
||||
{
|
||||
const bool isCustomPalette = SETTING_CUSTOM == myOSystem.settings().getString("palette");
|
||||
const bool isPhaseShift = myAdjustables[adjustable].value == nullptr;
|
||||
|
||||
myCurrentAdjustable = adjustable;
|
||||
if(isPhaseShift && !isCustomPalette)
|
||||
myCurrentAdjustable++;
|
||||
|
||||
changeCurrentAdjustable(direction);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void PaletteHandler::changeCurrentAdjustable(int direction)
|
||||
{
|
||||
if(myAdjustables[myCurrentAdjustable].value == nullptr)
|
||||
if(isPhaseShift())
|
||||
changeColorPhaseShift(direction);
|
||||
else
|
||||
{
|
||||
int newVal = scaleTo100(*myAdjustables[myCurrentAdjustable].value);
|
||||
if(isRGBScale())
|
||||
{
|
||||
int newVal = scaleRGBTo100(*myAdjustables[myCurrentAdjustable].value);
|
||||
|
||||
newVal = BSPF::clamp(newVal + direction * 1, 0, 100);
|
||||
newVal = BSPF::clamp(newVal + direction * 1, 0, 100);
|
||||
*myAdjustables[myCurrentAdjustable].value = scaleRGBFrom100(newVal);
|
||||
}
|
||||
else if(isRGBShift())
|
||||
{
|
||||
float newShift = *myAdjustables[myCurrentAdjustable].value;
|
||||
|
||||
*myAdjustables[myCurrentAdjustable].value = scaleFrom100(newVal);
|
||||
newShift = BSPF::clamp(newShift + direction * 0.5F, -MAX_RGB_SHIFT, MAX_RGB_SHIFT);
|
||||
*myAdjustables[myCurrentAdjustable].value = newShift;
|
||||
}
|
||||
else
|
||||
{
|
||||
int newVal = scaleTo100(*myAdjustables[myCurrentAdjustable].value);
|
||||
|
||||
newVal = BSPF::clamp(newVal + direction * 1, 0, 100);
|
||||
*myAdjustables[myCurrentAdjustable].value = scaleFrom100(newVal);
|
||||
}
|
||||
showAdjustableMessage();
|
||||
setPalette();
|
||||
}
|
||||
|
@ -162,7 +205,7 @@ void PaletteHandler::changeColorPhaseShift(int direction)
|
|||
const float shift = isNTSC ? DEF_NTSC_SHIFT : DEF_PAL_SHIFT;
|
||||
float newPhase = isNTSC ? myPhaseNTSC : myPhasePAL;
|
||||
|
||||
newPhase = BSPF::clamp(newPhase + direction * 0.3F, shift - MAX_SHIFT, shift + MAX_SHIFT);
|
||||
newPhase = BSPF::clamp(newPhase + direction * 0.3F, shift - MAX_PHASE_SHIFT, shift + MAX_PHASE_SHIFT);
|
||||
|
||||
if(isNTSC)
|
||||
myPhaseNTSC = newPhase;
|
||||
|
@ -181,15 +224,21 @@ void PaletteHandler::loadConfig(const Settings& settings)
|
|||
{
|
||||
// Load adjustables
|
||||
myPhaseNTSC = BSPF::clamp(settings.getFloat("pal.phase_ntsc"),
|
||||
DEF_NTSC_SHIFT - MAX_SHIFT, DEF_NTSC_SHIFT + MAX_SHIFT);
|
||||
DEF_NTSC_SHIFT - MAX_PHASE_SHIFT, DEF_NTSC_SHIFT + MAX_PHASE_SHIFT);
|
||||
myPhasePAL = BSPF::clamp(settings.getFloat("pal.phase_pal"),
|
||||
DEF_PAL_SHIFT - MAX_SHIFT, DEF_PAL_SHIFT + MAX_SHIFT);
|
||||
DEF_PAL_SHIFT - MAX_PHASE_SHIFT, DEF_PAL_SHIFT + MAX_PHASE_SHIFT);
|
||||
myRedScale = BSPF::clamp(settings.getFloat("pal.red_scale"), -1.0F, 1.0F) + 1.F;
|
||||
myGreenScale = BSPF::clamp(settings.getFloat("pal.green_scale"), -1.0F, 1.0F) + 1.F;
|
||||
myBlueScale = BSPF::clamp(settings.getFloat("pal.blue_scale"), -1.0F, 1.0F) + 1.F;
|
||||
myRedShift = BSPF::clamp(settings.getFloat("pal.red_shift"), -MAX_RGB_SHIFT, MAX_RGB_SHIFT);
|
||||
myGreenShift = BSPF::clamp(settings.getFloat("pal.green_shift"), -MAX_RGB_SHIFT, MAX_RGB_SHIFT);
|
||||
myBlueShift = BSPF::clamp(settings.getFloat("pal.blue_shift"), -MAX_RGB_SHIFT, MAX_RGB_SHIFT);
|
||||
|
||||
myHue = BSPF::clamp(settings.getFloat("pal.hue"), -1.0F, 1.0F);
|
||||
mySaturation = BSPF::clamp(settings.getFloat("pal.saturation"), -1.0F, 1.0F);
|
||||
myContrast = BSPF::clamp(settings.getFloat("pal.contrast"), -1.0F, 1.0F);
|
||||
myBrightness = BSPF::clamp(settings.getFloat("pal.brightness"), -1.0F, 1.0F);
|
||||
myGamma = BSPF::clamp(settings.getFloat("pal.gamma"), -1.0F, 1.0F);
|
||||
myHue = BSPF::clamp(settings.getFloat("pal.hue"), -1.0F, 1.0F);
|
||||
mySaturation = BSPF::clamp(settings.getFloat("pal.saturation"), -1.0F, 1.0F);
|
||||
myContrast = BSPF::clamp(settings.getFloat("pal.contrast"), -1.0F, 1.0F);
|
||||
myBrightness = BSPF::clamp(settings.getFloat("pal.brightness"), -1.0F, 1.0F);
|
||||
myGamma = BSPF::clamp(settings.getFloat("pal.gamma"), -1.0F, 1.0F);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -198,6 +247,12 @@ void PaletteHandler::saveConfig(Settings& settings) const
|
|||
// Save adjustables
|
||||
settings.setValue("pal.phase_ntsc", myPhaseNTSC);
|
||||
settings.setValue("pal.phase_pal", myPhasePAL);
|
||||
settings.setValue("pal.red_scale", myRedScale - 1.F);
|
||||
settings.setValue("pal.green_scale", myGreenScale - 1.F);
|
||||
settings.setValue("pal.blue_scale", myBlueScale - 1.F);
|
||||
settings.setValue("pal.red_shift", myRedShift);
|
||||
settings.setValue("pal.green_shift", myGreenShift);
|
||||
settings.setValue("pal.blue_shift", myBlueShift);
|
||||
|
||||
settings.setValue("pal.hue", myHue);
|
||||
settings.setValue("pal.saturation", mySaturation);
|
||||
|
@ -209,8 +264,14 @@ void PaletteHandler::saveConfig(Settings& settings) const
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void PaletteHandler::setAdjustables(const Adjustable& adjustable)
|
||||
{
|
||||
myPhaseNTSC = adjustable.phaseNtsc / 10.F;
|
||||
myPhasePAL = adjustable.phasePal / 10.F;
|
||||
myPhaseNTSC = scaleFromAngles(adjustable.phaseNtsc);
|
||||
myPhasePAL = scaleFromAngles(adjustable.phasePal);
|
||||
myRedScale = scaleRGBFrom100(adjustable.redScale);
|
||||
myGreenScale = scaleRGBFrom100(adjustable.greenScale);
|
||||
myBlueScale = scaleRGBFrom100(adjustable.blueScale);
|
||||
myRedShift = scaleFromAngles(adjustable.redShift);
|
||||
myGreenShift = scaleFromAngles(adjustable.greenShift);
|
||||
myBlueShift = scaleFromAngles(adjustable.blueShift);
|
||||
|
||||
myHue = scaleFrom100(adjustable.hue);
|
||||
mySaturation = scaleFrom100(adjustable.saturation);
|
||||
|
@ -222,8 +283,14 @@ void PaletteHandler::setAdjustables(const Adjustable& adjustable)
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void PaletteHandler::getAdjustables(Adjustable& adjustable) const
|
||||
{
|
||||
adjustable.phaseNtsc = myPhaseNTSC * 10.F;
|
||||
adjustable.phasePal = myPhasePAL * 10.F;
|
||||
adjustable.phaseNtsc = scaleToAngles(myPhaseNTSC);
|
||||
adjustable.phasePal = scaleToAngles(myPhasePAL);
|
||||
adjustable.redScale = scaleRGBTo100(myRedScale);
|
||||
adjustable.greenScale = scaleRGBTo100(myGreenScale);
|
||||
adjustable.blueScale = scaleRGBTo100(myBlueScale);
|
||||
adjustable.redShift = scaleToAngles(myRedShift);
|
||||
adjustable.greenShift = scaleToAngles(myGreenShift);
|
||||
adjustable.blueShift = scaleToAngles(myBlueShift);
|
||||
|
||||
adjustable.hue = scaleTo100(myHue);
|
||||
adjustable.saturation = scaleTo100(mySaturation);
|
||||
|
@ -371,10 +438,9 @@ void PaletteHandler::generateCustomPalette(ConsoleTiming timing)
|
|||
constexpr int NUM_LUMA = 8;
|
||||
constexpr float SATURATION = 0.25F; // default saturation
|
||||
|
||||
float color[NUM_CHROMA][2] = {{0.0F}};
|
||||
|
||||
if(timing == ConsoleTiming::ntsc)
|
||||
{
|
||||
vector2d IQ[NUM_CHROMA];
|
||||
// YIQ is YUV shifted by 33°
|
||||
constexpr float offset = 33 * BSPF::PI_f / 180;
|
||||
const float shift = myPhaseNTSC * BSPF::PI_f / 180;
|
||||
|
@ -382,22 +448,23 @@ void PaletteHandler::generateCustomPalette(ConsoleTiming timing)
|
|||
// color 0 is grayscale
|
||||
for(int chroma = 1; chroma < NUM_CHROMA; chroma++)
|
||||
{
|
||||
color[chroma][0] = SATURATION * sinf(offset + shift * (chroma - 1));
|
||||
color[chroma][1] = SATURATION * cosf(offset + shift * (chroma - 1) - BSPF::PI_f);
|
||||
IQ[chroma] = vector2d(SATURATION * sinf(offset + shift * (chroma - 1)),
|
||||
SATURATION * cosf(offset + shift * (chroma - 1) - BSPF::PI_f));
|
||||
}
|
||||
const vector2d IQR = scale(rotate(vector2d(+0.956F, +0.621F), myRedShift), myRedScale);
|
||||
const vector2d IQG = scale(rotate(vector2d(-0.272F, -0.647F), myGreenShift), myGreenScale);
|
||||
const vector2d IQB = scale(rotate(vector2d(-1.106F, +1.703F), myBlueShift), myBlueScale);
|
||||
|
||||
for(int chroma = 0; chroma < NUM_CHROMA; chroma++)
|
||||
{
|
||||
const float I = color[chroma][0];
|
||||
const float Q = color[chroma][1];
|
||||
|
||||
for(int luma = 0; luma < NUM_LUMA; luma++)
|
||||
{
|
||||
const float Y = 0.05F + luma / 8.24F; // 0.05..~0.90
|
||||
|
||||
float R = Y + 0.956F * I + 0.621F * Q;
|
||||
float G = Y - 0.272F * I - 0.647F * Q;
|
||||
float B = Y - 1.106F * I + 1.703F * Q;
|
||||
float R = Y + dotProduct(IQ[chroma], IQR);
|
||||
float G = Y + dotProduct(IQ[chroma], IQG);
|
||||
float B = Y + dotProduct(IQ[chroma], IQB);
|
||||
|
||||
|
||||
if(R < 0) R = 0;
|
||||
if(G < 0) G = 0;
|
||||
|
@ -420,35 +487,37 @@ void PaletteHandler::generateCustomPalette(ConsoleTiming timing)
|
|||
constexpr float offset = BSPF::PI_f;
|
||||
const float shift = myPhasePAL * BSPF::PI_f / 180;
|
||||
constexpr float fixedShift = 22.5F * BSPF::PI_f / 180;
|
||||
vector2d UV[NUM_CHROMA];
|
||||
|
||||
// colors 0, 1, 14 and 15 are grayscale
|
||||
for(int chroma = 2; chroma < NUM_CHROMA - 2; chroma++)
|
||||
{
|
||||
int idx = NUM_CHROMA - 1 - chroma;
|
||||
color[idx][0] = SATURATION * sinf(offset - fixedShift * chroma);
|
||||
|
||||
UV[idx].x = SATURATION * sinf(offset - fixedShift * chroma);
|
||||
if ((idx & 1) == 0)
|
||||
color[idx][1] = SATURATION * sinf(offset - shift * (chroma - 3.5F) / 2.F);
|
||||
UV[idx].y = SATURATION * sinf(offset - shift * (chroma - 3.5F) / 2.F);
|
||||
else
|
||||
color[idx][1] = SATURATION * -sinf(offset - shift * chroma / 2.F);
|
||||
UV[idx].y = SATURATION * -sinf(offset - shift * chroma / 2.F);
|
||||
}
|
||||
// Most sources
|
||||
const vector2d UVR = scale(rotate(vector2d( 0.000F, +1.403F), myRedShift), myRedScale);
|
||||
const vector2d UVG = scale(rotate(vector2d(-0.344F, -0.714F), myGreenShift), myGreenScale);
|
||||
const vector2d UVB = scale(rotate(vector2d(+0.714F, 0.000F), myBlueShift), myBlueScale);
|
||||
// German Wikipedia, huh???
|
||||
//float R = Y + 1 / 0.877 * V;
|
||||
//float B = Y + 1 / 0.493 * U;
|
||||
//float G = 1.704 * Y - 0.590 * R - 0.194 * B;
|
||||
|
||||
for(int chroma = 0; chroma < NUM_CHROMA; chroma++)
|
||||
{
|
||||
const float U = color[chroma][0];
|
||||
const float V = color[chroma][1];
|
||||
|
||||
for(int luma = 0; luma < NUM_LUMA; luma++)
|
||||
{
|
||||
const float Y = 0.05F + luma / 8.24F; // 0.05..~0.90
|
||||
|
||||
// Most sources
|
||||
float R = Y + 1.403F * V;
|
||||
float G = Y - 0.344F * U - 0.714F * V;
|
||||
float B = Y + 1.770F * U;
|
||||
// German Wikipedia, huh???
|
||||
//float B = Y + 1 / 0.493 * U;
|
||||
//float R = Y + 1 / 0.877 * V;
|
||||
//float G = 1.704 * Y - 0.590 * R - 0.194 * B;
|
||||
float R = Y + dotProduct(UV[chroma], UVR);
|
||||
float G = Y + dotProduct(UV[chroma], UVG);
|
||||
float B = Y + dotProduct(UV[chroma], UVB);
|
||||
|
||||
if(R < 0) R = 0.0;
|
||||
if(G < 0) G = 0.0;
|
||||
|
@ -491,6 +560,28 @@ void PaletteHandler::adjustHueSaturation(int& R, int& G, int& B, float H, float
|
|||
B = BSPF::clamp(b, 0.F, 255.F);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
PaletteHandler::vector2d PaletteHandler::rotate(const PaletteHandler::vector2d& vec, float angle) const
|
||||
{
|
||||
const float r = angle * BSPF::PI_f / 180;
|
||||
|
||||
return PaletteHandler::vector2d(vec.x * cosf(r) - vec.y * sinf(r),
|
||||
vec.x * sinf(r) + vec.y * cosf(r));
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
PaletteHandler::vector2d PaletteHandler::scale(const PaletteHandler::vector2d& vec, float factor) const
|
||||
{
|
||||
return PaletteHandler::vector2d(vec.x * factor, vec.y * factor);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
float PaletteHandler::dotProduct(const PaletteHandler::vector2d& vec1,
|
||||
const PaletteHandler::vector2d& vec2) const
|
||||
{
|
||||
return vec1.x * vec2.x + vec1.y * vec2.y;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
const PaletteArray PaletteHandler::ourNTSCPalette = {
|
||||
0x000000, 0, 0x4a4a4a, 0, 0x6f6f6f, 0, 0x8e8e8e, 0,
|
||||
|
|
|
@ -35,26 +35,37 @@ class PaletteHandler
|
|||
// Phase shift default and limits
|
||||
static constexpr float DEF_NTSC_SHIFT = 26.2F;
|
||||
static constexpr float DEF_PAL_SHIFT = 31.3F; // ~= 360 / 11.5
|
||||
static constexpr float MAX_SHIFT = 4.5F;
|
||||
static constexpr float MAX_PHASE_SHIFT = 4.5F;
|
||||
static constexpr float DEF_RGB_SHIFT = 0.0F;
|
||||
static constexpr float MAX_RGB_SHIFT = 22.5F;
|
||||
|
||||
enum Adjustables {
|
||||
PHASE_SHIFT,
|
||||
RED_SCALE,
|
||||
GREEN_SCALE,
|
||||
BLUE_SCALE,
|
||||
RED_SHIFT,
|
||||
GREEN_SHIFT,
|
||||
BLUE_SHIFT,
|
||||
HUE,
|
||||
SATURATION,
|
||||
CONTRAST,
|
||||
BRIGHTNESS,
|
||||
GAMMA
|
||||
GAMMA,
|
||||
CUSTOM_START = PHASE_SHIFT,
|
||||
CUSTOM_END = BLUE_SHIFT,
|
||||
};
|
||||
|
||||
// Externally used adjustment parameters
|
||||
struct Adjustable {
|
||||
float phaseNtsc{0.F}, phasePal{0.F};
|
||||
float phaseNtsc{0.F}, phasePal{0.F},
|
||||
redScale{0.F}, greenScale{0.F}, blueScale{0.F},
|
||||
redShift{0.F}, greenShift{0.F}, blueShift{0.F};
|
||||
uInt32 hue{0}, saturation{0}, contrast{0}, brightness{0}, gamma{0};
|
||||
};
|
||||
|
||||
public:
|
||||
PaletteHandler(OSystem& system);
|
||||
virtual ~PaletteHandler() = default;
|
||||
|
||||
/**
|
||||
Cycle through available palettes.
|
||||
|
@ -109,6 +120,7 @@ class PaletteHandler
|
|||
*/
|
||||
void setPalette();
|
||||
|
||||
|
||||
private:
|
||||
static constexpr char DEGREE = 0x1c;
|
||||
|
||||
|
@ -122,12 +134,43 @@ class PaletteHandler
|
|||
MaxType = Custom
|
||||
};
|
||||
|
||||
struct vector2d {
|
||||
float x{0.F};
|
||||
float y{0.F};
|
||||
|
||||
explicit vector2d(float _x = 0.F, float _y = 0.F)
|
||||
: x(_x), y(_y) { }
|
||||
};
|
||||
|
||||
/**
|
||||
Convert RGB adjustables from/to 100% scale
|
||||
*/
|
||||
static constexpr float scaleRGBFrom100(float x) { return x / 50.F; }
|
||||
static constexpr uInt32 scaleRGBTo100(float x) { return uInt32(50.0001F * (x - 0.F)); }
|
||||
|
||||
/**
|
||||
Convert angles
|
||||
*/
|
||||
static constexpr float scaleFromAngles(float x) { return x / 10.F; }
|
||||
static constexpr Int32 scaleToAngles(float x) { return uInt32(10.F * x); }
|
||||
|
||||
/**
|
||||
Convert adjustables from/to 100% scale
|
||||
*/
|
||||
static constexpr float scaleFrom100(float x) { return (x / 50.F) - 1.F; }
|
||||
static constexpr uInt32 scaleTo100(float x) { return uInt32(50.0001F * (x + 1.F)); }
|
||||
|
||||
/**
|
||||
Check for 'Custom' palette only adjustables
|
||||
*/
|
||||
bool isCustomAdjustable() const;
|
||||
|
||||
bool isPhaseShift() const;
|
||||
|
||||
bool isRGBScale() const;
|
||||
|
||||
bool isRGBShift() const;
|
||||
|
||||
/**
|
||||
Convert palette settings name to enumeration.
|
||||
|
||||
|
@ -187,6 +230,21 @@ class PaletteHandler
|
|||
*/
|
||||
void adjustHueSaturation(int& R, int& G, int& B, float H, float S);
|
||||
|
||||
/**
|
||||
Rotate a 2D vector.
|
||||
*/
|
||||
vector2d rotate(const vector2d& vec, float angle) const;
|
||||
|
||||
/**
|
||||
Scale a 2D vector.
|
||||
*/
|
||||
vector2d scale(const vector2d& vec, float factor) const;
|
||||
|
||||
/**
|
||||
Get the dot product of two 2D vectors.
|
||||
*/
|
||||
float dotProduct(const vector2d& vec1, const vector2d& vec2) const;
|
||||
|
||||
/**
|
||||
Loads a user-defined palette file (from OSystem::paletteFile), filling the
|
||||
appropriate user-defined palette arrays.
|
||||
|
@ -194,7 +252,7 @@ class PaletteHandler
|
|||
void loadUserPalette();
|
||||
|
||||
private:
|
||||
static constexpr int NUM_ADJUSTABLES = 6;
|
||||
static constexpr int NUM_ADJUSTABLES = 12;
|
||||
|
||||
OSystem& myOSystem;
|
||||
|
||||
|
@ -208,6 +266,12 @@ class PaletteHandler
|
|||
const std::array<AdjustableTag, NUM_ADJUSTABLES> myAdjustables =
|
||||
{ {
|
||||
{ "phase shift", nullptr },
|
||||
{ "red scale", &myRedScale },
|
||||
{ "green scale", &myGreenScale },
|
||||
{ "blue scale", &myBlueScale },
|
||||
{ "red shift", &myRedShift },
|
||||
{ "green shift", &myGreenShift },
|
||||
{ "blue shift", &myBlueShift },
|
||||
{ "hue", &myHue },
|
||||
{ "saturation", &mySaturation },
|
||||
{ "contrast", &myContrast },
|
||||
|
@ -218,6 +282,14 @@ class PaletteHandler
|
|||
// NTSC and PAL color phase shifts
|
||||
float myPhaseNTSC{DEF_NTSC_SHIFT};
|
||||
float myPhasePAL{DEF_PAL_SHIFT};
|
||||
// Color intensities
|
||||
float myRedScale{1.0F};
|
||||
float myGreenScale{1.0F};
|
||||
float myBlueScale{1.0F};
|
||||
// Color shifts
|
||||
float myRedShift{0.0F};
|
||||
float myGreenShift{0.0F};
|
||||
float myBlueShift{0.0F};
|
||||
// range -1.0 to +1.0 (as in AtariNTSC)
|
||||
// Basic parameters
|
||||
float myHue{0.0F}; // -1 = -180 degrees +1 = +180 degrees
|
||||
|
|
|
@ -44,8 +44,8 @@ struct Point
|
|||
if(c != 'x')
|
||||
x = y = 0;
|
||||
}
|
||||
bool operator==(const Point & p) const { return x == p.x && y == p.y; }
|
||||
bool operator!=(const Point & p) const { return x != p.x || y != p.y; }
|
||||
bool operator==(const Point& p) const { return x == p.x && y == p.y; }
|
||||
bool operator!=(const Point& p) const { return !(*this == p); }
|
||||
|
||||
friend ostream& operator<<(ostream& os, const Point& p) {
|
||||
os << p.x << "x" << p.y;
|
||||
|
@ -69,12 +69,17 @@ struct Size
|
|||
}
|
||||
bool valid() const { return w > 0 && h > 0; }
|
||||
|
||||
void clamp(uInt32 lower_w, uInt32 upper_w, uInt32 lower_h, uInt32 upper_h) {
|
||||
w = BSPF::clamp(w, lower_w, upper_w);
|
||||
h = BSPF::clamp(h, lower_h, upper_h);
|
||||
}
|
||||
|
||||
bool operator==(const Size& s) const { return w == s.w && h == s.h; }
|
||||
bool operator!=(const Size& s) const { return w != s.w || h != s.h; }
|
||||
bool operator<(const Size& s) const { return w < s.w && h < s.h; }
|
||||
bool operator<=(const Size& s) const { return w <= s.w && h <= s.h; }
|
||||
bool operator>(const Size& s) const { return w > s.w && h > s.h; }
|
||||
bool operator>=(const Size& s) const { return w >= s.w && h >= s.h; }
|
||||
bool operator< (const Size& s) const { return w < s.w && h < s.h; }
|
||||
bool operator> (const Size& s) const { return w > s.w || h > s.h; }
|
||||
bool operator!=(const Size& s) const { return !(*this == s); }
|
||||
bool operator<=(const Size& s) const { return !(*this > s); }
|
||||
bool operator>=(const Size& s) const { return !(*this < s); }
|
||||
|
||||
friend ostream& operator<<(ostream& os, const Size& s) {
|
||||
os << s.w << "x" << s.h;
|
||||
|
@ -170,6 +175,11 @@ struct Rect
|
|||
return r.left != x || r.top != y;
|
||||
}
|
||||
|
||||
bool operator==(const Rect& r) const {
|
||||
return top == r.top && left == r.left && bottom == r.bottom && right == r.right;
|
||||
}
|
||||
bool operator!=(const Rect& r) const { return !(*this == r); }
|
||||
|
||||
friend ostream& operator<<(ostream& os, const Rect& r) {
|
||||
os << r.point() << "," << r.size();
|
||||
return os;
|
||||
|
|
|
@ -37,7 +37,6 @@ RewindManager::RewindManager(OSystem& system, StateManager& statemgr)
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void RewindManager::setup()
|
||||
{
|
||||
myStateSize = 0;
|
||||
myLastTimeMachineAdd = false;
|
||||
|
||||
const string& prefix = myOSystem.settings().getBool("dev.settings") ? "dev." : "plr.";
|
||||
|
@ -138,7 +137,6 @@ bool RewindManager::addState(const string& message, bool timeMachine)
|
|||
s.rewind(); // rewind Serializer internal buffers
|
||||
if(myStateManager.saveState(s) && myOSystem.console().tia().saveDisplay(s))
|
||||
{
|
||||
myStateSize = std::max(myStateSize, uInt32(s.size()));
|
||||
state.message = message;
|
||||
state.cycles = myOSystem.console().tia().cycles();
|
||||
myLastTimeMachineAdd = timeMachine;
|
||||
|
@ -183,7 +181,7 @@ uInt32 RewindManager::rewindStates(uInt32 numStates)
|
|||
|
||||
if(myOSystem.eventHandler().state() != EventHandlerState::TIMEMACHINE
|
||||
&& myOSystem.eventHandler().state() != EventHandlerState::PLAYBACK)
|
||||
myOSystem.frameBuffer().showMessage(message);
|
||||
myOSystem.frameBuffer().showTextMessage(message);
|
||||
return i;
|
||||
}
|
||||
|
||||
|
@ -218,7 +216,7 @@ uInt32 RewindManager::unwindStates(uInt32 numStates)
|
|||
|
||||
if(myOSystem.eventHandler().state() != EventHandlerState::TIMEMACHINE
|
||||
&& myOSystem.eventHandler().state() != EventHandlerState::PLAYBACK)
|
||||
myOSystem.frameBuffer().showMessage(message);
|
||||
myOSystem.frameBuffer().showTextMessage(message);
|
||||
return i;
|
||||
}
|
||||
|
||||
|
@ -256,18 +254,22 @@ string RewindManager::saveAllStates()
|
|||
buf.str("");
|
||||
out.putString(STATE_HEADER);
|
||||
out.putShort(numStates);
|
||||
out.putInt(myStateSize);
|
||||
|
||||
unique_ptr<uInt8[]> buffer = make_unique<uInt8[]>(myStateSize);
|
||||
for (uInt32 i = 0; i < numStates; ++i)
|
||||
{
|
||||
RewindState& state = myStateList.current();
|
||||
Serializer& s = state.data;
|
||||
uInt32 stateSize = uInt32(s.size());
|
||||
unique_ptr<uInt8[]> buffer = make_unique<uInt8[]>(stateSize);
|
||||
|
||||
out.putInt(stateSize);
|
||||
|
||||
// Rewind Serializer internal buffers
|
||||
s.rewind();
|
||||
|
||||
// Save state
|
||||
s.getByteArray(buffer.get(), myStateSize);
|
||||
out.putByteArray(buffer.get(), myStateSize);
|
||||
s.getByteArray(buffer.get(), stateSize);
|
||||
out.putByteArray(buffer.get(), stateSize);
|
||||
out.putString(state.message);
|
||||
out.putLong(state.cycles);
|
||||
|
||||
|
@ -310,25 +312,27 @@ string RewindManager::loadAllStates()
|
|||
if (in.getString() != STATE_HEADER)
|
||||
return "Incompatible all states file";
|
||||
numStates = in.getShort();
|
||||
myStateSize = in.getInt();
|
||||
|
||||
unique_ptr<uInt8[]> buffer = make_unique<uInt8[]>(myStateSize);
|
||||
for (uInt32 i = 0; i < numStates; ++i)
|
||||
{
|
||||
if (myStateList.full())
|
||||
compressStates();
|
||||
|
||||
uInt32 stateSize = in.getInt();
|
||||
unique_ptr<uInt8[]> buffer = make_unique<uInt8[]>(stateSize);
|
||||
|
||||
// Add new state at the end of the list (queue adds at end)
|
||||
// This updates the 'current' iterator inside the list
|
||||
myStateList.addLast();
|
||||
RewindState& state = myStateList.current();
|
||||
Serializer& s = state.data;
|
||||
|
||||
// Rewind Serializer internal buffers
|
||||
s.rewind();
|
||||
|
||||
// Fill new state with saved values
|
||||
in.getByteArray(buffer.get(), myStateSize);
|
||||
s.putByteArray(buffer.get(), myStateSize);
|
||||
in.getByteArray(buffer.get(), stateSize);
|
||||
s.putByteArray(buffer.get(), stateSize);
|
||||
state.message = in.getString();
|
||||
state.cycles = in.getLong();
|
||||
}
|
||||
|
|
|
@ -144,7 +144,6 @@ class RewindManager
|
|||
bool atLast() const { return myStateList.atLast(); }
|
||||
void resize(uInt32 size) { myStateList.resize(size); }
|
||||
void clear() {
|
||||
myStateSize = 0;
|
||||
myStateList.clear();
|
||||
}
|
||||
|
||||
|
@ -176,7 +175,6 @@ class RewindManager
|
|||
uInt64 myHorizon{0};
|
||||
double myFactor{0.0};
|
||||
bool myLastTimeMachineAdd{false};
|
||||
uInt32 myStateSize{0};
|
||||
|
||||
struct RewindState {
|
||||
Serializer data; // actual save state
|
||||
|
|
|
@ -43,11 +43,7 @@ class SoundNull : public Sound
|
|||
{
|
||||
Logger::info("Sound disabled.\n");
|
||||
}
|
||||
|
||||
/**
|
||||
Destructor
|
||||
*/
|
||||
virtual ~SoundNull() = default;
|
||||
~SoundNull() override = default;
|
||||
|
||||
public:
|
||||
/**
|
||||
|
|
|
@ -117,7 +117,7 @@ bool SoundSDL2::openDevice()
|
|||
if(myIsInitializedFlag)
|
||||
SDL_CloseAudioDevice(myDevice);
|
||||
|
||||
myDeviceId = BSPF::clamp(myAudioSettings.device(), 0u, uInt32(myDevices.size() - 1));
|
||||
myDeviceId = BSPF::clamp(myAudioSettings.device(), 0U, uInt32(myDevices.size() - 1));
|
||||
const char* device = myDeviceId ? myDevices.at(myDeviceId).first.c_str() : nullptr;
|
||||
|
||||
myDevice = SDL_OpenAudioDevice(device, 0, &desired, &myHardwareSpec,
|
||||
|
@ -224,7 +224,7 @@ bool SoundSDL2::toggleMute()
|
|||
string message = "Sound ";
|
||||
message += enabled ? "unmuted" : "muted";
|
||||
|
||||
myOSystem.frameBuffer().showMessage(message);
|
||||
myOSystem.frameBuffer().showTextMessage(message);
|
||||
|
||||
//ostringstream strval;
|
||||
//uInt32 volume;
|
||||
|
@ -282,7 +282,7 @@ void SoundSDL2::adjustVolume(int direction)
|
|||
strval << percent << "%";
|
||||
else
|
||||
strval << "Off";
|
||||
myOSystem.frameBuffer().showMessage("Volume", strval.str(), percent);
|
||||
myOSystem.frameBuffer().showGaugeMessage("Volume", strval.str(), percent);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
|
|
@ -48,7 +48,7 @@ class SoundSDL2 : public Sound
|
|||
/**
|
||||
Destructor
|
||||
*/
|
||||
virtual ~SoundSDL2();
|
||||
~SoundSDL2() override;
|
||||
|
||||
public:
|
||||
/**
|
||||
|
|
|
@ -132,9 +132,9 @@ void StateManager::toggleTimeMachine()
|
|||
|
||||
myActiveMode = myActiveMode == Mode::TimeMachine ? Mode::Off : Mode::TimeMachine;
|
||||
if(myActiveMode == Mode::TimeMachine)
|
||||
myOSystem.frameBuffer().showMessage("Time Machine enabled");
|
||||
myOSystem.frameBuffer().showTextMessage("Time Machine enabled");
|
||||
else
|
||||
myOSystem.frameBuffer().showMessage("Time Machine disabled");
|
||||
myOSystem.frameBuffer().showTextMessage("Time Machine disabled");
|
||||
myOSystem.settings().setValue(devSettings ? "dev.timemachine" : "plr.timemachine", myActiveMode == Mode::TimeMachine);
|
||||
}
|
||||
|
||||
|
@ -215,7 +215,7 @@ void StateManager::loadState(int slot)
|
|||
{
|
||||
buf.str("");
|
||||
buf << "Can't open/load from state file " << slot;
|
||||
myOSystem.frameBuffer().showMessage(buf.str());
|
||||
myOSystem.frameBuffer().showTextMessage(buf.str());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -239,7 +239,7 @@ void StateManager::loadState(int slot)
|
|||
buf << "Invalid data in state " << slot << " file";
|
||||
}
|
||||
|
||||
myOSystem.frameBuffer().showMessage(buf.str());
|
||||
myOSystem.frameBuffer().showTextMessage(buf.str());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -261,7 +261,7 @@ void StateManager::saveState(int slot)
|
|||
{
|
||||
buf.str("");
|
||||
buf << "Can't open/save to state file " << slot;
|
||||
myOSystem.frameBuffer().showMessage(buf.str());
|
||||
myOSystem.frameBuffer().showTextMessage(buf.str());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -274,7 +274,7 @@ void StateManager::saveState(int slot)
|
|||
catch(...)
|
||||
{
|
||||
buf << "Error saving state " << slot;
|
||||
myOSystem.frameBuffer().showMessage(buf.str());
|
||||
myOSystem.frameBuffer().showTextMessage(buf.str());
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -292,7 +292,7 @@ void StateManager::saveState(int slot)
|
|||
else
|
||||
buf << "Error saving state " << slot;
|
||||
|
||||
myOSystem.frameBuffer().showMessage(buf.str());
|
||||
myOSystem.frameBuffer().showTextMessage(buf.str());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -307,7 +307,7 @@ void StateManager::changeState(int direction)
|
|||
buf << "Changed to state slot " << myCurrentSlot;
|
||||
else
|
||||
buf << "State slot " << myCurrentSlot;
|
||||
myOSystem.frameBuffer().showMessage(buf.str());
|
||||
myOSystem.frameBuffer().showTextMessage(buf.str());
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -318,7 +318,7 @@ void StateManager::toggleAutoSlot()
|
|||
// Print appropriate message
|
||||
ostringstream buf;
|
||||
buf << "Automatic slot change " << (autoSlot ? "enabled" : "disabled");
|
||||
myOSystem.frameBuffer().showMessage(buf.str());
|
||||
myOSystem.frameBuffer().showTextMessage(buf.str());
|
||||
|
||||
myOSystem.settings().setValue("autoslot", autoSlot);
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
#ifndef VERSION_HXX
|
||||
#define VERSION_HXX
|
||||
|
||||
#define STELLA_VERSION "6.3_pre"
|
||||
#define STELLA_BUILD "6091"
|
||||
#define STELLA_VERSION "6.5_pre"
|
||||
#define STELLA_BUILD "6238"
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,165 @@
|
|||
//============================================================================
|
||||
//
|
||||
// SSSS tt lll lll
|
||||
// SS SS tt ll ll
|
||||
// SS tttttt eeee ll ll aaaa
|
||||
// SSSS tt ee ee ll ll aa
|
||||
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
|
||||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2020 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 "Settings.hxx"
|
||||
#include "VideoModeHandler.hxx"
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void VideoModeHandler::setImageSize(const Common::Size& image)
|
||||
{
|
||||
myImage = image;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void VideoModeHandler::setDisplaySize(const Common::Size& display, Int32 fsIndex)
|
||||
{
|
||||
myDisplay = display;
|
||||
myFSIndex = fsIndex;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
const VideoModeHandler::Mode&
|
||||
VideoModeHandler::buildMode(const Settings& settings, bool inTIAMode)
|
||||
{
|
||||
const bool windowedRequested = myFSIndex == -1;
|
||||
|
||||
// TIA mode allows zooming at non-integral factors in most cases
|
||||
if(inTIAMode)
|
||||
{
|
||||
if(windowedRequested)
|
||||
{
|
||||
const float zoom = settings.getFloat("tia.zoom");
|
||||
ostringstream desc;
|
||||
desc << (zoom * 100) << "%";
|
||||
|
||||
// Image and screen (aka window) dimensions are the same
|
||||
// Overscan is not applicable in this mode
|
||||
myMode = Mode(myImage.w * zoom, myImage.h * zoom, Mode::Stretch::Fill,
|
||||
myFSIndex, desc.str(), zoom);
|
||||
}
|
||||
else
|
||||
{
|
||||
const float overscan = 1 - settings.getInt("tia.fs_overscan") / 100.0;
|
||||
|
||||
// First calculate maximum zoom that keeps aspect ratio
|
||||
const float scaleX = float(myImage.w) / myDisplay.w,
|
||||
scaleY = float(myImage.h) / myDisplay.h;
|
||||
float zoom = 1.F / std::max(scaleX, scaleY);
|
||||
|
||||
// When aspect ratio correction is off, we want pixel-exact images,
|
||||
// so we default to integer zooming
|
||||
if(!settings.getBool("tia.correct_aspect"))
|
||||
zoom = static_cast<uInt32>(zoom);
|
||||
|
||||
if(!settings.getBool("tia.fs_stretch")) // preserve aspect, use all space
|
||||
{
|
||||
myMode = Mode(myImage.w * zoom, myImage.h * zoom,
|
||||
myDisplay.w, myDisplay.h,
|
||||
Mode::Stretch::Preserve, myFSIndex,
|
||||
"Fullscreen: Preserve aspect, no stretch", zoom, overscan);
|
||||
}
|
||||
else // ignore aspect, use all space
|
||||
{
|
||||
myMode = Mode(myImage.w * zoom, myImage.h * zoom,
|
||||
myDisplay.w, myDisplay.h,
|
||||
Mode::Stretch::Fill, myFSIndex,
|
||||
"Fullscreen: Ignore aspect, full stretch", zoom, overscan);
|
||||
}
|
||||
}
|
||||
}
|
||||
else // UI mode (no zooming)
|
||||
{
|
||||
if(windowedRequested)
|
||||
myMode = Mode(myImage.w, myImage.h, Mode::Stretch::None);
|
||||
else
|
||||
myMode = Mode(myImage.w, myImage.h, myDisplay.w, myDisplay.h,
|
||||
Mode::Stretch::None, myFSIndex);
|
||||
}
|
||||
|
||||
return myMode;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
VideoModeHandler::Mode::Mode(uInt32 iw, uInt32 ih, Stretch smode,
|
||||
Int32 fsindex, const string& desc,
|
||||
float zoomLevel)
|
||||
: Mode(iw, ih, iw, ih, smode, fsindex, desc, zoomLevel)
|
||||
{
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
VideoModeHandler::Mode::Mode(uInt32 iw, uInt32 ih, uInt32 sw, uInt32 sh,
|
||||
Stretch smode, Int32 fsindex, const string& desc,
|
||||
float zoomLevel, float overscan)
|
||||
: stretch(smode),
|
||||
description(desc),
|
||||
zoom(zoomLevel),
|
||||
fsIndex(fsindex)
|
||||
{
|
||||
// First set default size and positioning
|
||||
screenS = Common::Size(sw, sh);
|
||||
|
||||
// Now resize based on windowed/fullscreen mode and stretch factor
|
||||
if(fsIndex != -1) // fullscreen mode
|
||||
{
|
||||
switch(stretch)
|
||||
{
|
||||
case Stretch::Preserve:
|
||||
iw *= overscan;
|
||||
ih *= overscan;
|
||||
break;
|
||||
|
||||
case Stretch::Fill:
|
||||
// Scale to all available space
|
||||
iw = screenS.w * overscan;
|
||||
ih = screenS.h * overscan;
|
||||
break;
|
||||
|
||||
case Stretch::None:
|
||||
// Don't do any scaling at all
|
||||
iw = std::min(iw, screenS.w) * overscan;
|
||||
ih = std::min(ih, screenS.h) * overscan;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// In windowed mode, currently the size is scaled to the screen
|
||||
// TODO - this may be updated if/when we allow variable-sized windows
|
||||
switch(stretch)
|
||||
{
|
||||
case Stretch::Preserve:
|
||||
case Stretch::Fill:
|
||||
screenS.w = iw;
|
||||
screenS.h = ih;
|
||||
break;
|
||||
|
||||
case Stretch::None:
|
||||
break; // Do not change image or screen rects whatsoever
|
||||
}
|
||||
}
|
||||
|
||||
// Now re-calculate the dimensions
|
||||
iw = std::min(iw, screenS.w);
|
||||
ih = std::min(ih, screenS.h);
|
||||
|
||||
imageR.moveTo((screenS.w - iw) >> 1, (screenS.h - ih) >> 1);
|
||||
imageR.setWidth(iw);
|
||||
imageR.setHeight(ih);
|
||||
|
||||
screenR = Common::Rect(screenS);
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
//============================================================================
|
||||
//
|
||||
// SSSS tt lll lll
|
||||
// SS SS tt ll ll
|
||||
// SS tttttt eeee ll ll aaaa
|
||||
// SSSS tt ee ee ll ll aa
|
||||
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
|
||||
// SS SS tt ee ll ll aa aa
|
||||
// SSSS ttt eeeee llll llll aaaaa
|
||||
//
|
||||
// Copyright (c) 1995-2020 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 VIDEO_MODE_HANDLER_HXX
|
||||
#define VIDEO_MODE_HANDLER_HXX
|
||||
|
||||
class Settings;
|
||||
|
||||
#include "Rect.hxx"
|
||||
#include "bspf.hxx"
|
||||
|
||||
class VideoModeHandler
|
||||
{
|
||||
public:
|
||||
// Contains all relevant info for the dimensions of a video screen
|
||||
// Also takes care of the case when the image should be 'centered'
|
||||
// within the given screen:
|
||||
// 'image' is the image dimensions into the screen
|
||||
// 'screen' are the dimensions of the screen itself
|
||||
struct Mode
|
||||
{
|
||||
enum class Stretch {
|
||||
Preserve, // Stretch to fill all available space; preserve aspect ratio
|
||||
Fill, // Stretch to fill all available space
|
||||
None // No stretching (1x zoom)
|
||||
};
|
||||
|
||||
Common::Rect imageR;
|
||||
Common::Rect screenR;
|
||||
Common::Size screenS;
|
||||
Stretch stretch{Mode::Stretch::None};
|
||||
string description;
|
||||
float zoom{1.F};
|
||||
Int32 fsIndex{-1}; // -1 indicates windowed mode
|
||||
|
||||
Mode() = default;
|
||||
Mode(uInt32 iw, uInt32 ih, uInt32 sw, uInt32 sh, Stretch smode,
|
||||
Int32 fsindex = -1, const string& desc = "",
|
||||
float zoomLevel = 1.F, float overscan = 1.F);
|
||||
Mode(uInt32 iw, uInt32 ih, Stretch smode, Int32 fsindex = -1,
|
||||
const string& desc = "", float zoomLevel = 1.F);
|
||||
|
||||
friend ostream& operator<<(ostream& os, const Mode& vm)
|
||||
{
|
||||
os << "image=" << vm.imageR << " screen=" << vm.screenS
|
||||
<< " stretch=" << (vm.stretch == Stretch::Preserve ? "preserve" :
|
||||
vm.stretch == Stretch::Fill ? "fill" : "none")
|
||||
<< " desc=" << vm.description << " zoom=" << vm.zoom
|
||||
<< " fsIndex= " << vm.fsIndex;
|
||||
return os;
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
VideoModeHandler() = default;
|
||||
|
||||
/**
|
||||
Set the base size of the image. Scaling can be applied to this,
|
||||
which will change the effective size.
|
||||
|
||||
@param image The base dimensions of the image
|
||||
*/
|
||||
void setImageSize(const Common::Size& image);
|
||||
|
||||
/**
|
||||
Set the size of the display. This could be either the desktop size,
|
||||
or the size of the monitor currently active.
|
||||
|
||||
@param display The dimensions of the enclosing display
|
||||
@param fsIndex Fullscreen mode in use (-1 indicates windowed mode)
|
||||
*/
|
||||
void setDisplaySize(const Common::Size& display, Int32 fsIndex = -1);
|
||||
|
||||
/**
|
||||
Build a video mode based on the given parameters, assuming that
|
||||
setImageSize and setDisplaySize have been previously called.
|
||||
|
||||
@param settings Used to query various options that affect video mode
|
||||
@param inTIAMode Whether the video mode is being used for TIA emulation
|
||||
|
||||
@return A video mode based on the given criteria
|
||||
*/
|
||||
const VideoModeHandler::Mode& buildMode(const Settings& settings,
|
||||
bool inTIAMode);
|
||||
|
||||
private:
|
||||
Common::Size myImage, myDisplay;
|
||||
Int32 myFSIndex{-1};
|
||||
|
||||
Mode myMode;
|
||||
|
||||
private:
|
||||
VideoModeHandler(const VideoModeHandler&) = delete;
|
||||
VideoModeHandler(VideoModeHandler&&) = delete;
|
||||
VideoModeHandler& operator=(const VideoModeHandler&) = delete;
|
||||
VideoModeHandler& operator=(const VideoModeHandler&&) = delete;
|
||||
};
|
||||
|
||||
#endif // VIDEO_MODE_HANDLER_HXX
|
|
@ -93,6 +93,14 @@ constexpr size_t operator "" _KB(unsigned long long size)
|
|||
return static_cast<size_t>(size * 1024);
|
||||
}
|
||||
|
||||
// Output contents of a vector
|
||||
template<typename T>
|
||||
std::ostream& operator<< (std::ostream& out, const std::vector<T>& v) {
|
||||
for(const auto& elem: v)
|
||||
out << elem << " ";
|
||||
return out;
|
||||
}
|
||||
|
||||
static const string EmptyString("");
|
||||
|
||||
// This is defined by some systems, but Stella has other uses for it
|
||||
|
@ -160,6 +168,12 @@ namespace BSPF
|
|||
return (val < lower) ? upper : (val > upper) ? lower : val;
|
||||
}
|
||||
|
||||
// Test whether the vector contains the given value
|
||||
template<typename T>
|
||||
bool contains(const std::vector<T>& v, const T& elem) {
|
||||
return !(v.empty() || std::find(v.begin(), v.end(), elem) == v.end());
|
||||
}
|
||||
|
||||
// Convert string to given case
|
||||
inline const string& toUpperCase(string& s)
|
||||
{
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
MODULE := src/common
|
||||
|
||||
MODULE_OBJS := \
|
||||
src/common/AudioQueue.o \
|
||||
src/common/AudioSettings.o \
|
||||
src/common/Base.o \
|
||||
src/common/EventHandlerSDL2.o \
|
||||
src/common/FBBackendSDL2.o \
|
||||
src/common/FBSurfaceSDL2.o \
|
||||
src/common/FrameBufferSDL2.o \
|
||||
src/common/FpsMeter.o \
|
||||
src/common/FSNodeZIP.o \
|
||||
src/common/HighScoresManager.o \
|
||||
src/common/JoyMap.o \
|
||||
|
@ -20,14 +23,12 @@ MODULE_OBJS := \
|
|||
src/common/PNGLibrary.o \
|
||||
src/common/RewindManager.o \
|
||||
src/common/SoundSDL2.o \
|
||||
src/common/StateManager.o \
|
||||
src/common/TimerManager.o \
|
||||
src/common/ZipHandler.o \
|
||||
src/common/AudioQueue.o \
|
||||
src/common/AudioSettings.o \
|
||||
src/common/FpsMeter.o \
|
||||
src/common/ThreadDebugging.o \
|
||||
src/common/StaggeredLogger.o \
|
||||
src/common/StateManager.o \
|
||||
src/common/ThreadDebugging.o \
|
||||
src/common/TimerManager.o \
|
||||
src/common/VideoModeHandler.o \
|
||||
src/common/ZipHandler.o \
|
||||
src/common/repository/KeyValueRepositoryConfigfile.o \
|
||||
src/common/sdl_blitter/BilinearBlitter.o \
|
||||
src/common/sdl_blitter/QisBlitter.o \
|
||||
|
|
|
@ -15,12 +15,12 @@
|
|||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//============================================================================
|
||||
|
||||
#include "FrameBufferSDL2.hxx"
|
||||
#include "FBBackendSDL2.hxx"
|
||||
#include "ThreadDebugging.hxx"
|
||||
#include "BilinearBlitter.hxx"
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
BilinearBlitter::BilinearBlitter(FrameBufferSDL2& fb, bool interpolate)
|
||||
BilinearBlitter::BilinearBlitter(FBBackendSDL2& fb, bool interpolate)
|
||||
: myFB(fb),
|
||||
myInterpolate(interpolate)
|
||||
{
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
#ifndef BILINEAR_BLITTER_HXX
|
||||
#define BILINEAR_BLITTER_HXX
|
||||
|
||||
class FrameBufferSDL2;
|
||||
class FBBackendSDL2;
|
||||
|
||||
#include "Blitter.hxx"
|
||||
#include "SDL_lib.hxx"
|
||||
|
@ -27,9 +27,9 @@ class BilinearBlitter : public Blitter {
|
|||
|
||||
public:
|
||||
|
||||
BilinearBlitter(FrameBufferSDL2& fb, bool interpolate);
|
||||
BilinearBlitter(FBBackendSDL2& fb, bool interpolate);
|
||||
|
||||
virtual ~BilinearBlitter();
|
||||
~BilinearBlitter() override;
|
||||
|
||||
virtual void reinitialize(
|
||||
SDL_Rect srcRect,
|
||||
|
@ -41,7 +41,7 @@ class BilinearBlitter : public Blitter {
|
|||
virtual void blit(SDL_Surface& surface) override;
|
||||
|
||||
private:
|
||||
FrameBufferSDL2& myFB;
|
||||
FBBackendSDL2& myFB;
|
||||
|
||||
SDL_Texture* myTexture{nullptr};
|
||||
SDL_Texture* mySecondaryTexture{nullptr};
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#include "BilinearBlitter.hxx"
|
||||
#include "QisBlitter.hxx"
|
||||
|
||||
unique_ptr<Blitter> BlitterFactory::createBlitter(FrameBufferSDL2& fb, ScalingAlgorithm scaling)
|
||||
unique_ptr<Blitter> BlitterFactory::createBlitter(FBBackendSDL2& fb, ScalingAlgorithm scaling)
|
||||
{
|
||||
if (!fb.isInitialized()) {
|
||||
throw runtime_error("BlitterFactory requires an initialized framebuffer!");
|
||||
|
|
|
@ -21,8 +21,8 @@
|
|||
#include <string>
|
||||
|
||||
#include "Blitter.hxx"
|
||||
#include "FBBackendSDL2.hxx"
|
||||
#include "bspf.hxx"
|
||||
#include "FrameBufferSDL2.hxx"
|
||||
|
||||
class BlitterFactory {
|
||||
public:
|
||||
|
@ -35,7 +35,7 @@ class BlitterFactory {
|
|||
|
||||
public:
|
||||
|
||||
static unique_ptr<Blitter> createBlitter(FrameBufferSDL2& fb, ScalingAlgorithm scaling);
|
||||
static unique_ptr<Blitter> createBlitter(FBBackendSDL2& fb, ScalingAlgorithm scaling);
|
||||
};
|
||||
|
||||
#endif // BLITTER_FACTORY_HXX
|
||||
|
|
|
@ -15,12 +15,12 @@
|
|||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||
//============================================================================
|
||||
|
||||
#include "FrameBufferSDL2.hxx"
|
||||
#include "FBBackendSDL2.hxx"
|
||||
#include "ThreadDebugging.hxx"
|
||||
#include "QisBlitter.hxx"
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
QisBlitter::QisBlitter(FrameBufferSDL2& fb)
|
||||
QisBlitter::QisBlitter(FBBackendSDL2& fb)
|
||||
: myFB(fb)
|
||||
{
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ QisBlitter::~QisBlitter()
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool QisBlitter::isSupported(FrameBufferSDL2 &fb)
|
||||
bool QisBlitter::isSupported(FBBackendSDL2& fb)
|
||||
{
|
||||
if (!fb.isInitialized()) throw runtime_error("framebuffer not initialized");
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
#ifndef QIS_BLITTER_HXX
|
||||
#define QIS_BLITTER_HXX
|
||||
|
||||
class FrameBufferSDL2;
|
||||
class FBBackendSDL2;
|
||||
|
||||
#include "Blitter.hxx"
|
||||
#include "SDL_lib.hxx"
|
||||
|
@ -27,11 +27,11 @@ class QisBlitter : public Blitter {
|
|||
|
||||
public:
|
||||
|
||||
explicit QisBlitter(FrameBufferSDL2& fb);
|
||||
explicit QisBlitter(FBBackendSDL2& fb);
|
||||
|
||||
static bool isSupported(FrameBufferSDL2 &fb);
|
||||
static bool isSupported(FBBackendSDL2& fb);
|
||||
|
||||
virtual ~QisBlitter();
|
||||
~QisBlitter() override;
|
||||
|
||||
virtual void reinitialize(
|
||||
SDL_Rect srcRect,
|
||||
|
@ -44,7 +44,7 @@ class QisBlitter : public Blitter {
|
|||
|
||||
private:
|
||||
|
||||
FrameBufferSDL2& myFB;
|
||||
FBBackendSDL2& myFB;
|
||||
|
||||
SDL_Texture* mySrcTexture{nullptr};
|
||||
SDL_Texture* mySecondarySrcTexture{nullptr};
|
||||
|
|
|
@ -605,7 +605,8 @@ bool CartDebug::removeLabel(const string& label)
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool CartDebug::getLabel(ostream& buf, uInt16 addr, bool isRead, int places) const
|
||||
bool CartDebug::getLabel(ostream& buf, uInt16 addr, bool isRead,
|
||||
int places, bool isRam) const
|
||||
{
|
||||
switch(addressType(addr))
|
||||
{
|
||||
|
@ -662,21 +663,24 @@ bool CartDebug::getLabel(ostream& buf, uInt16 addr, bool isRead, int places) con
|
|||
{
|
||||
// RAM can use user-defined labels; otherwise we default to
|
||||
// standard mnemonics
|
||||
auto iter = myUserLabels.find(addr);
|
||||
if(iter != myUserLabels.end())
|
||||
{
|
||||
buf << iter->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
uInt16 a = addr & 0xFF, offset = addr & 0xFF00;
|
||||
if((iter = myUserLabels.find(a)) != myUserLabels.end())
|
||||
AddrToLabel::const_iterator iter;
|
||||
uInt16 a = addr & 0xFF, offset = addr & 0xFF00;
|
||||
bool found = false;
|
||||
|
||||
// Search for nearest label
|
||||
for(uInt16 i = a; i >= 0x80; --i)
|
||||
if((iter = myUserLabels.find(i)) != myUserLabels.end())
|
||||
{
|
||||
buf << iter->second;
|
||||
else
|
||||
buf << ourZPMnemonic[a - 0x80];
|
||||
if(offset > 0)
|
||||
buf << "|$" << Base::HEX2 << offset;
|
||||
}
|
||||
if(a != i)
|
||||
buf << "+$" << Base::HEX1 << (a - i);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
if(!found)
|
||||
buf << ourZPMnemonic[a - 0x80];
|
||||
if(offset > 0)
|
||||
buf << "|$" << Base::HEX2 << offset;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -684,11 +688,28 @@ bool CartDebug::getLabel(ostream& buf, uInt16 addr, bool isRead, int places) con
|
|||
case AddrType::ROM:
|
||||
{
|
||||
// These addresses can never be in the system labels list
|
||||
const auto& iter = myUserLabels.find(addr);
|
||||
if(iter != myUserLabels.end())
|
||||
if(isRam) // cartridge RAM
|
||||
{
|
||||
buf << iter->second;
|
||||
return true;
|
||||
AddrToLabel::const_iterator iter;
|
||||
|
||||
// Search for nearest label
|
||||
for(uInt16 i = addr; i >= (addr & 0xf000); --i)
|
||||
if((iter = myUserLabels.find(i)) != myUserLabels.end())
|
||||
{
|
||||
buf << iter->second;
|
||||
if(addr != i)
|
||||
buf << "+$" << Base::HEX1 << (addr - i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto& iter = myUserLabels.find(addr);
|
||||
if(iter != myUserLabels.end())
|
||||
{
|
||||
buf << iter->second;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -713,10 +734,10 @@ bool CartDebug::getLabel(ostream& buf, uInt16 addr, bool isRead, int places) con
|
|||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
string CartDebug::getLabel(uInt16 addr, bool isRead, int places) const
|
||||
string CartDebug::getLabel(uInt16 addr, bool isRead, int places, bool isRam) const
|
||||
{
|
||||
ostringstream buf;
|
||||
getLabel(buf, addr, isRead, places);
|
||||
getLabel(buf, addr, isRead, places, isRam);
|
||||
return buf.str();
|
||||
}
|
||||
|
||||
|
|
|
@ -70,7 +70,7 @@ class CartDebug : public DebuggerSystem
|
|||
|
||||
public:
|
||||
CartDebug(Debugger& dbg, Console& console, const OSystem& osystem);
|
||||
virtual ~CartDebug() = default;
|
||||
~CartDebug() override = default;
|
||||
|
||||
const DebuggerState& getState() override;
|
||||
const DebuggerState& getOldState() override { return myOldState; }
|
||||
|
@ -211,8 +211,10 @@ class CartDebug : public DebuggerSystem
|
|||
If places is not -1 and a label hasn't been defined, return a
|
||||
formatted hexidecimal address
|
||||
*/
|
||||
bool getLabel(ostream& buf, uInt16 addr, bool isRead, int places = -1) const;
|
||||
string getLabel(uInt16 addr, bool isRead, int places = -1) const;
|
||||
bool getLabel(ostream& buf, uInt16 addr, bool isRead,
|
||||
int places = -1, bool isRam = false) const;
|
||||
string getLabel(uInt16 addr, bool isRead,
|
||||
int places = -1, bool isRam = false) const;
|
||||
int getAddress(const string& label) const;
|
||||
|
||||
/**
|
||||
|
|
|
@ -90,21 +90,18 @@ Debugger::~Debugger()
|
|||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
void Debugger::initialize()
|
||||
{
|
||||
const Common::Size& s = myOSystem.settings().getSize("dbg.res");
|
||||
mySize = myOSystem.settings().getSize("dbg.res");
|
||||
const Common::Size& d = myOSystem.frameBuffer().desktopSize();
|
||||
myWidth = s.w; myHeight = s.h;
|
||||
|
||||
// The debugger dialog is resizable, within certain bounds
|
||||
// We check those bounds now
|
||||
myWidth = std::max(myWidth, uInt32(DebuggerDialog::kSmallFontMinW));
|
||||
myHeight = std::max(myHeight, uInt32(DebuggerDialog::kSmallFontMinH));
|
||||
myWidth = std::min(myWidth, uInt32(d.w));
|
||||
myHeight = std::min(myHeight, uInt32(d.h));
|
||||
mySize.clamp(uInt32(DebuggerDialog::kSmallFontMinW), d.w,
|
||||
uInt32(DebuggerDialog::kSmallFontMinH), d.h);
|
||||
|
||||
myOSystem.settings().setValue("dbg.res", Common::Size(myWidth, myHeight));
|
||||
myOSystem.settings().setValue("dbg.res", mySize);
|
||||
|
||||
delete myDialog; myDialog = nullptr;
|
||||
myDialog = new DebuggerDialog(myOSystem, *this, 0, 0, myWidth, myHeight);
|
||||
myDialog = new DebuggerDialog(myOSystem, *this, 0, 0, mySize.w, mySize.h);
|
||||
|
||||
myCartDebug->setDebugWidget(&(myDialog->cartDebug()));
|
||||
|
||||
|
@ -115,12 +112,14 @@ void Debugger::initialize()
|
|||
FBInitStatus Debugger::initializeVideo()
|
||||
{
|
||||
string title = string("Stella ") + STELLA_VERSION + ": Debugger mode";
|
||||
return myOSystem.frameBuffer().createDisplay(title, FrameBuffer::BufferType::Debugger,
|
||||
myWidth, myHeight);
|
||||
return myOSystem.frameBuffer().createDisplay(
|
||||
title, BufferType::Debugger, mySize
|
||||
);
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool Debugger::start(const string& message, int address, bool read)
|
||||
bool Debugger::start(const string& message, int address, bool read,
|
||||
const string& toolTip)
|
||||
{
|
||||
if(myOSystem.eventHandler().enterDebugMode())
|
||||
{
|
||||
|
@ -131,6 +130,7 @@ bool Debugger::start(const string& message, int address, bool read)
|
|||
if(address > -1)
|
||||
buf << cartDebug().getLabel(address, read, 4);
|
||||
myDialog->message().setText(buf.str());
|
||||
myDialog->message().setToolTip(toolTip);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -877,23 +877,28 @@ std::array<Debugger::BuiltinFunction, 18> Debugger::ourBuiltinFunctions = { {
|
|||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// Names are defined here, but processed in YaccParser
|
||||
std::array<Debugger::PseudoRegister, 12> Debugger::ourPseudoRegisters = { {
|
||||
std::array<Debugger::PseudoRegister, 16> Debugger::ourPseudoRegisters = { {
|
||||
// Debugger::PseudoRegister Debugger::ourPseudoRegisters[NUM_PSEUDO_REGS] = {
|
||||
{ "_bank", "Currently selected bank" },
|
||||
{ "_cclocks", "Color clocks on current scanline" },
|
||||
{ "_cycleshi", "Higher 32 bits of number of cycles since emulation started" },
|
||||
{ "_cycleslo", "Lower 32 bits of number of cycles since emulation started" },
|
||||
{ "_fcount", "Number of frames since emulation started" },
|
||||
{ "_fcycles", "Number of cycles since frame started" },
|
||||
{ "_icycles", "Number of cycles of last instruction" },
|
||||
{ "_scan", "Current scanline count" },
|
||||
{ "_scanend", "Scanline count at end of last frame" },
|
||||
{ "_scycles", "Number of cycles in current scanline" },
|
||||
{ "_vblank", "Whether vertical blank is enabled (1 or 0)" },
|
||||
{ "_vsync", "Whether vertical sync is enabled (1 or 0)" }
|
||||
{ "_bank", "Currently selected bank" },
|
||||
{ "_cclocks", "Color clocks on current scanline" },
|
||||
{ "_cycleshi", "Higher 32 bits of number of cycles since emulation started" },
|
||||
{ "_cycleslo", "Lower 32 bits of number of cycles since emulation started" },
|
||||
{ "_fcount", "Number of frames since emulation started" },
|
||||
{ "_fcycles", "Number of cycles since frame started" },
|
||||
{ "_ftimreadcycles","Number of cycles used by timer reads since frame started" },
|
||||
{ "_fwsynccycles", "Number of cycles skipped by WSYNC since frame started" },
|
||||
{ "_icycles", "Number of cycles of last instruction" },
|
||||
{ "_scan", "Current scanline count" },
|
||||
{ "_scanend", "Scanline count at end of last frame" },
|
||||
{ "_scycles", "Number of cycles in current scanline" },
|
||||
{ "_timwrapread", "Timer read wrapped on this cycle" },
|
||||
{ "_timwrapwrite", "Timer write wrapped on this cycle" },
|
||||
{ "_vblank", "Whether vertical blank is enabled (1 or 0)" },
|
||||
{ "_vsync", "Whether vertical sync is enabled (1 or 0)" }
|
||||
// CPU address access functions:
|
||||
/*{ "_lastread", "last CPU read address" },
|
||||
{ "_lastwrite", "last CPU write address" },
|
||||
{ "__lastbaseread", "last CPU read base address" },
|
||||
{ "__lastbasewrite", "last CPU write base address" }*/
|
||||
} };
|
||||
//
|
||||
|
|
|
@ -44,6 +44,7 @@ class RewindManager;
|
|||
#include <map>
|
||||
|
||||
#include "Base.hxx"
|
||||
#include "Rect.hxx"
|
||||
#include "DialogContainer.hxx"
|
||||
#include "DebuggerDialog.hxx"
|
||||
#include "FrameBufferConstants.hxx"
|
||||
|
@ -73,7 +74,7 @@ class Debugger : public DialogContainer
|
|||
Create a new debugger parent object
|
||||
*/
|
||||
Debugger(OSystem& osystem, Console& console);
|
||||
virtual ~Debugger();
|
||||
~Debugger() override;
|
||||
|
||||
private:
|
||||
static const Int8 ANY_BANK = -1;
|
||||
|
@ -96,7 +97,8 @@ class Debugger : public DialogContainer
|
|||
@param message Message to display when entering debugger
|
||||
@param address An address associated with the message
|
||||
*/
|
||||
bool start(const string& message = "", int address = -1, bool read = true);
|
||||
bool start(const string& message = "", int address = -1, bool read = true,
|
||||
const string& toolTip = "");
|
||||
bool startWithFatalError(const string& message = "");
|
||||
|
||||
/**
|
||||
|
@ -352,8 +354,8 @@ class Debugger : public DialogContainer
|
|||
FunctionDefMap myFunctionDefs;
|
||||
|
||||
// Dimensions of the entire debugger window
|
||||
uInt32 myWidth{DebuggerDialog::kSmallFontMinW};
|
||||
uInt32 myHeight{DebuggerDialog::kSmallFontMinH};
|
||||
Common::Size mySize{DebuggerDialog::kSmallFontMinW,
|
||||
DebuggerDialog::kSmallFontMinH};
|
||||
|
||||
// Various builtin functions and operations
|
||||
struct BuiltinFunction {
|
||||
|
@ -363,7 +365,7 @@ class Debugger : public DialogContainer
|
|||
string name, help;
|
||||
};
|
||||
static std::array<BuiltinFunction, 18> ourBuiltinFunctions;
|
||||
static std::array<PseudoRegister, 12> ourPseudoRegisters;
|
||||
static std::array<PseudoRegister, 16> ourPseudoRegisters;
|
||||
|
||||
private:
|
||||
// rewind/unwind n states
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "bspf.hxx"
|
||||
#include "CartDebug.hxx"
|
||||
#include "CpuDebug.hxx"
|
||||
#include "RiotDebug.hxx"
|
||||
#include "TIADebug.hxx"
|
||||
#include "Debugger.hxx"
|
||||
#include "Expression.hxx"
|
||||
|
@ -310,6 +311,18 @@ class ShiftRightExpression : public Expression
|
|||
{ return myLHS->evaluate() >> myRHS->evaluate(); }
|
||||
};
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
class RiotMethodExpression : public Expression
|
||||
{
|
||||
public:
|
||||
RiotMethodExpression(RiotMethod method) : Expression(), myMethod(std::mem_fn(method)) { }
|
||||
Int32 evaluate() const override
|
||||
{ return myMethod(Debugger::debugger().riotDebug()); }
|
||||
|
||||
private:
|
||||
std::function<int(const RiotDebug&)> myMethod;
|
||||
};
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
class TiaMethodExpression : public Expression
|
||||
{
|
||||
|
|
|
@ -1747,9 +1747,13 @@ void DebuggerParser::executeRunTo()
|
|||
// Create a progress dialog box to show the progress searching through the
|
||||
// disassembly, since this may be a time-consuming operation
|
||||
ostringstream buf;
|
||||
buf << "RunTo searching through " << max_iterations << " disassembled instructions";
|
||||
ProgressDialog progress(debugger.baseDialog(), debugger.lfont(), buf.str());
|
||||
ProgressDialog progress(debugger.baseDialog(), debugger.lfont());
|
||||
|
||||
buf << "RunTo searching through " << max_iterations << " disassembled instructions"
|
||||
<< progress.ELLIPSIS;
|
||||
progress.setMessage(buf.str());
|
||||
progress.setRange(0, max_iterations, 5);
|
||||
progress.open();
|
||||
|
||||
bool done = false;
|
||||
do {
|
||||
|
@ -1763,8 +1767,8 @@ void DebuggerParser::executeRunTo()
|
|||
done = (BSPF::findIgnoreCase(next, argStrings[0]) != string::npos);
|
||||
}
|
||||
// Update the progress bar
|
||||
progress.setProgress(count);
|
||||
} while(!done && ++count < max_iterations);
|
||||
progress.incProgress();
|
||||
} while(!done && ++count < max_iterations && !progress.isCancelled());
|
||||
|
||||
progress.close();
|
||||
|
||||
|
@ -1789,13 +1793,15 @@ void DebuggerParser::executeRunToPc()
|
|||
|
||||
uInt32 count = 0;
|
||||
bool done = false;
|
||||
constexpr uInt32 max_iterations = 1000000;
|
||||
// Create a progress dialog box to show the progress searching through the
|
||||
// disassembly, since this may be a time-consuming operation
|
||||
ostringstream buf;
|
||||
buf << "RunTo PC searching through " << max_iterations << " instructions";
|
||||
ProgressDialog progress(debugger.baseDialog(), debugger.lfont(), buf.str());
|
||||
progress.setRange(0, max_iterations, 5);
|
||||
ProgressDialog progress(debugger.baseDialog(), debugger.lfont());
|
||||
|
||||
buf << " RunTo PC running" << progress.ELLIPSIS << " ";
|
||||
progress.setMessage(buf.str());
|
||||
progress.setRange(0, 100000, 5);
|
||||
progress.open();
|
||||
|
||||
do {
|
||||
debugger.step(false);
|
||||
|
@ -1803,8 +1809,9 @@ void DebuggerParser::executeRunToPc()
|
|||
// Update romlist to point to current PC
|
||||
int pcline = cartdbg.addressToLine(debugger.cpuDebug().pc());
|
||||
done = (pcline >= 0) && (list[pcline].address == args[0]);
|
||||
progress.setProgress(count);
|
||||
} while(!done && ++count < max_iterations/*list.size()*/);
|
||||
progress.incProgress();
|
||||
++count;
|
||||
} while(!done && !progress.isCancelled());
|
||||
progress.close();
|
||||
|
||||
if(done)
|
||||
|
@ -1953,20 +1960,24 @@ void DebuggerParser::executeStepwhile()
|
|||
Expression* expr = YaccParser::getResult();
|
||||
int ncycles = 0;
|
||||
uInt32 count = 0;
|
||||
constexpr uInt32 max_iterations = 1000000;
|
||||
|
||||
// Create a progress dialog box to show the progress searching through the
|
||||
// disassembly, since this may be a time-consuming operation
|
||||
ostringstream buf;
|
||||
buf << "stepwhile running through " << max_iterations << " disassembled instructions";
|
||||
ProgressDialog progress(debugger.baseDialog(), debugger.lfont(), buf.str());
|
||||
progress.setRange(0, max_iterations, 5);
|
||||
ProgressDialog progress(debugger.baseDialog(), debugger.lfont());
|
||||
|
||||
buf << "stepwhile running through disassembled instructions"
|
||||
<< progress.ELLIPSIS;
|
||||
progress.setMessage(buf.str());
|
||||
progress.setRange(0, 100000, 5);
|
||||
progress.open();
|
||||
|
||||
do {
|
||||
ncycles += debugger.step(false);
|
||||
|
||||
progress.setProgress(count);
|
||||
} while (expr->evaluate() && ++count < max_iterations);
|
||||
progress.incProgress();
|
||||
++count;
|
||||
} while (expr->evaluate() && !progress.isCancelled());
|
||||
|
||||
progress.close();
|
||||
commandResult << "executed " << ncycles << " cycles";
|
||||
|
|
|
@ -31,7 +31,7 @@ class DebuggerState
|
|||
{
|
||||
public:
|
||||
DebuggerState() = default;
|
||||
~DebuggerState() = default;
|
||||
virtual ~DebuggerState() = default;
|
||||
|
||||
DebuggerState(const DebuggerState&) = default;
|
||||
DebuggerState(DebuggerState&&) = delete;
|
||||
|
|
|
@ -68,6 +68,8 @@ const DebuggerState& RiotDebug::getState()
|
|||
myState.INTIMCLKS = intimClocks();
|
||||
myState.TIMDIV = timDivider();
|
||||
|
||||
myState.timReadCycles = timReadCycles();
|
||||
|
||||
return myState;
|
||||
}
|
||||
|
||||
|
@ -75,10 +77,11 @@ const DebuggerState& RiotDebug::getState()
|
|||
void RiotDebug::saveOldState()
|
||||
{
|
||||
// Port A & B registers
|
||||
myOldState.SWCHA_R = swcha();
|
||||
// read from myState where other widgets can update pins directly
|
||||
myOldState.SWCHA_R = myState.SWCHA_R; // swcha();
|
||||
myOldState.SWCHA_W = mySystem.m6532().myOutA;
|
||||
myOldState.SWACNT = swacnt();
|
||||
myOldState.SWCHB_R = swchb();
|
||||
myOldState.SWCHB_R = myState.SWCHB_R; // swchb();
|
||||
myOldState.SWCHB_W = mySystem.m6532().myOutB;
|
||||
myOldState.SWBCNT = swbcnt();
|
||||
Debugger::set_bits(myOldState.SWCHA_R, myOldState.swchaReadBits);
|
||||
|
@ -93,8 +96,9 @@ void RiotDebug::saveOldState()
|
|||
myOldState.INPT1 = inpt(1);
|
||||
myOldState.INPT2 = inpt(2);
|
||||
myOldState.INPT3 = inpt(3);
|
||||
myOldState.INPT4 = inpt(4);
|
||||
myOldState.INPT5 = inpt(5);
|
||||
// read from myState where other widgets can update pins directly
|
||||
myOldState.INPT4 = myState.INPT4; // inpt(4);
|
||||
myOldState.INPT5 = myState.INPT5; // inpt(5);
|
||||
|
||||
myOldState.INPTLatch = vblank(6);
|
||||
myOldState.INPTDump = vblank(7);
|
||||
|
@ -109,6 +113,8 @@ void RiotDebug::saveOldState()
|
|||
myOldState.TIMCLKS = timClocks();
|
||||
myOldState.INTIMCLKS = intimClocks();
|
||||
myOldState.TIMDIV = timDivider();
|
||||
|
||||
myOldState.timReadCycles = timReadCycles();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
@ -233,6 +239,24 @@ Int32 RiotDebug::timDivider() const
|
|||
return mySystem.m6532().myDivider;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
int RiotDebug::timWrappedOnRead() const
|
||||
{
|
||||
return mySystem.m6532().myTimWrappedOnRead;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
int RiotDebug::timWrappedOnWrite() const
|
||||
{
|
||||
return mySystem.m6532().myTimWrappedOnWrite;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
int RiotDebug::timReadCycles() const
|
||||
{
|
||||
return mySystem.m6532().myTimReadCycles;
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
bool RiotDebug::diffP0(int newVal)
|
||||
{
|
||||
|
|
|
@ -22,6 +22,10 @@ class M6532;
|
|||
class Debugger;
|
||||
class RiotDebug;
|
||||
|
||||
// Function type for RiotDebug instance methods
|
||||
class RiotDebug;
|
||||
using RiotMethod = int (RiotDebug::*)() const;
|
||||
|
||||
#include "DebuggerSystem.hxx"
|
||||
|
||||
class RiotState : public DebuggerState
|
||||
|
@ -37,6 +41,7 @@ class RiotState : public DebuggerState
|
|||
|
||||
uInt8 TIM1T{0}, TIM8T{0}, TIM64T{0}, T1024T{0}, INTIM{0}, TIMINT{0};
|
||||
Int32 TIMCLKS{0}, INTIMCLKS{0}, TIMDIV{0};
|
||||
uInt16 timReadCycles;
|
||||
|
||||
// These are actually from the TIA, but are I/O related
|
||||
uInt8 INPT0{0}, INPT1{0}, INPT2{0}, INPT3{0}, INPT4{0}, INPT5{0};
|
||||
|
@ -75,6 +80,11 @@ class RiotDebug : public DebuggerSystem
|
|||
Int32 timClocks() const;
|
||||
Int32 intimClocks() const;
|
||||
Int32 timDivider() const;
|
||||
/* Debugger pseudo-registers for timer accesses */
|
||||
int timWrappedOnRead() const;
|
||||
int timWrappedOnWrite() const;
|
||||
|
||||
int timReadCycles() const;
|
||||
|
||||
/* Console switches */
|
||||
bool diffP0(int newVal = -1);
|
||||
|
|
|
@ -149,6 +149,7 @@ const DebuggerState& TIADebug::getState()
|
|||
myState.info.push_back(scanlines());
|
||||
myState.info.push_back(scanlinesLastFrame());
|
||||
myState.info.push_back(clocksThisLine());
|
||||
myState.info.push_back(frameWsyncCycles());
|
||||
|
||||
return myState;
|
||||
}
|
||||
|
@ -258,6 +259,7 @@ void TIADebug::saveOldState()
|
|||
myOldState.info.push_back(scanlines());
|
||||
myOldState.info.push_back(scanlinesLastFrame());
|
||||
myOldState.info.push_back(clocksThisLine());
|
||||
myOldState.info.push_back(frameWsyncCycles());
|
||||
}
|
||||
|
||||
/* the set methods now use mySystem.poke(). This will save us the
|
||||
|
@ -909,6 +911,12 @@ int TIADebug::frameCycles() const
|
|||
return myTIA.frameCycles();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
int TIADebug::frameWsyncCycles() const
|
||||
{
|
||||
return myTIA.frameWSyncCycles();
|
||||
}
|
||||
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
int TIADebug::cyclesLo() const
|
||||
{
|
||||
|
|