Merge branch 'master' into feature-highscores
|
@ -20,6 +20,7 @@ build/
|
||||||
src/macosx/M6502.ins
|
src/macosx/M6502.ins
|
||||||
*.dSYM
|
*.dSYM
|
||||||
.vscode/c_cpp_properties.json
|
.vscode/c_cpp_properties.json
|
||||||
|
.vscode/settings.json
|
||||||
src/windows/sdl/*
|
src/windows/sdl/*
|
||||||
src/windows/x64/*
|
src/windows/x64/*
|
||||||
src/windows/Win32/*
|
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
|
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
|
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
|
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.
|
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:
|
distributions currently available are:
|
||||||
|
|
||||||
* Binaries for Windows Vista/7/8/10 :
|
* Binaries for Windows 7/8/10 :
|
||||||
Stella-6.2.1-win32.exe (32-bit EXE installer)
|
Stella-6.4-win32.exe (32-bit EXE installer)
|
||||||
Stella-6.2.1-x64.exe (64-bit EXE installer)
|
Stella-6.4-x64.exe (64-bit EXE installer)
|
||||||
Stella-6.2.1-windows.zip (32/64 bit versions)
|
Stella-6.4-windows.zip (32/64 bit versions)
|
||||||
|
|
||||||
* Binary distribution for macOS 10.7 and above :
|
* 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 :
|
* Binary distribution for 64-bit Ubuntu :
|
||||||
stella_6.2.1-1_i386.deb
|
stella_6.4-1_amd64.deb
|
||||||
stella_6.2.1-1_amd64.deb
|
|
||||||
|
|
||||||
* Binary distribution in 32-bit & 64-bit RPM format :
|
* Binary distribution for 64-bit Redhat :
|
||||||
stella-6.2.1-2.i386.rpm
|
stella-6.4-2.x86_64.rpm
|
||||||
stella-6.2.1-2.x86_64.rpm
|
|
||||||
|
|
||||||
* Source code distribution for all platforms :
|
* Source code distribution for all platforms :
|
||||||
stella-6.2.1-src.tar.xz
|
stella-6.4-src.tar.xz
|
||||||
|
|
||||||
|
|
||||||
Distribution Site
|
Distribution Site
|
||||||
|
|
86
Changes.txt
|
@ -12,11 +12,65 @@
|
||||||
Release History
|
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 adjustable autofire.
|
||||||
|
|
||||||
* Added 'Dark' UI theme. (TODO: DOC)
|
* Added 'Dark' UI theme.
|
||||||
|
|
||||||
* Extended global hotkeys for debug options.
|
* Extended global hotkeys for debug options.
|
||||||
|
|
||||||
|
@ -33,16 +87,42 @@
|
||||||
Basically, you are now able to put many files that Stella uses inside
|
Basically, you are now able to put many files that Stella uses inside
|
||||||
one ZIP file, and distribute just that file.
|
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 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 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.
|
* Replaced "Re-disassemble" with "Disassemble @ current line" in debugger.
|
||||||
|
|
||||||
* Fixed bug when taking fullscreen snapshots; the dimensions were
|
* Fixed bug when taking fullscreen snapshots; the dimensions were
|
||||||
sometimes cut off.
|
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)
|
6.2 to 6.2.1: (June 20, 2020)
|
||||||
|
|
9
Makefile
|
@ -48,11 +48,11 @@ endif
|
||||||
CXXFLAGS+= -Wall -Wextra -Wno-unused-parameter
|
CXXFLAGS+= -Wall -Wextra -Wno-unused-parameter
|
||||||
|
|
||||||
ifdef HAVE_GCC
|
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
|
endif
|
||||||
|
|
||||||
ifdef HAVE_CLANG
|
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
|
endif
|
||||||
|
|
||||||
ifdef CLANG_WARNINGS
|
ifdef CLANG_WARNINGS
|
||||||
|
@ -80,6 +80,11 @@ else
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifdef RELEASE
|
||||||
|
CXXFLAGS += -flto -fno-rtti
|
||||||
|
LDFLAGS += -flto -fno-rtti
|
||||||
|
endif
|
||||||
|
|
||||||
#######################################################################
|
#######################################################################
|
||||||
# Misc stuff - you should never have to edit this #
|
# Misc stuff - you should never have to edit this #
|
||||||
#######################################################################
|
#######################################################################
|
||||||
|
|
|
@ -26,6 +26,7 @@ _build_sqlite=no
|
||||||
_build_static=no
|
_build_static=no
|
||||||
_build_profile=no
|
_build_profile=no
|
||||||
_build_debug=no
|
_build_debug=no
|
||||||
|
_build_release=no
|
||||||
|
|
||||||
# more defaults
|
# more defaults
|
||||||
_ranlib=ranlib
|
_ranlib=ranlib
|
||||||
|
@ -262,7 +263,9 @@ for ac_option in $@; do
|
||||||
--enable-profile) _build_profile=yes ;;
|
--enable-profile) _build_profile=yes ;;
|
||||||
--disable-profile) _build_profile=no ;;
|
--disable-profile) _build_profile=no ;;
|
||||||
--enable-debug) _build_debug=yes ;;
|
--enable-debug) _build_debug=yes ;;
|
||||||
--disable-debug) _build_debug=false ;;
|
--disable-debug) _build_debug=no ;;
|
||||||
|
--enable-release) _build_release=yes ;;
|
||||||
|
--disable-release) _build_release=no ;;
|
||||||
--with-sdl-prefix=*)
|
--with-sdl-prefix=*)
|
||||||
arg=`echo $ac_option | cut -d '=' -f 2`
|
arg=`echo $ac_option | cut -d '=' -f 2`
|
||||||
_sdlpath="$arg:$arg/bin"
|
_sdlpath="$arg:$arg/bin"
|
||||||
|
@ -382,7 +385,7 @@ else
|
||||||
fi
|
fi
|
||||||
|
|
||||||
for compiler in $compilers; do
|
for compiler in $compilers; do
|
||||||
if test_compiler "$compiler -std=c++14"; then
|
if test_compiler "$compiler -std=c++17"; then
|
||||||
CXX=$compiler
|
CXX=$compiler
|
||||||
echo $CXX
|
echo $CXX
|
||||||
break
|
break
|
||||||
|
@ -925,6 +928,10 @@ if test "$_build_debug" = no ; then
|
||||||
_build_debug=
|
_build_debug=
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if test "$_build_release" = no ; then
|
||||||
|
_build_release=
|
||||||
|
fi
|
||||||
|
|
||||||
echo "Creating config.mak"
|
echo "Creating config.mak"
|
||||||
cat > config.mak << EOF
|
cat > config.mak << EOF
|
||||||
# -------- Generated by configure -----------
|
# -------- Generated by configure -----------
|
||||||
|
@ -958,6 +965,7 @@ DOCDIR := $_docdir
|
||||||
DATADIR := $_datadir
|
DATADIR := $_datadir
|
||||||
PROFILE := $_build_profile
|
PROFILE := $_build_profile
|
||||||
DEBUG := $_build_debug
|
DEBUG := $_build_debug
|
||||||
|
RELEASE := $_build_release
|
||||||
|
|
||||||
$_make_def_HAVE_GCC
|
$_make_def_HAVE_GCC
|
||||||
$_make_def_HAVE_CLANG
|
$_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
|
stella (6.2.1-1) stable; urgency=high
|
||||||
|
|
||||||
* Version 6.2.1 release
|
* Version 6.2.1 release
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
9
|
10
|
||||||
|
|
|
@ -1,17 +1,39 @@
|
||||||
Source: stella
|
Source: stella
|
||||||
Section: games
|
|
||||||
Priority: optional
|
|
||||||
Maintainer: Stephen Anthony <sa666666@gmail.com>
|
Maintainer: Stephen Anthony <sa666666@gmail.com>
|
||||||
Standards-Version: 3.7.2
|
Section: otherosfs
|
||||||
Build-Depends: debhelper (>= 5.0.0), libsdl2-dev, libpng-dev
|
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
|
Package: stella
|
||||||
Architecture: any
|
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
|
Description: Atari 2600 Emulator for SDL2
|
||||||
The Atari 2600 Video Computer System (VCS), introduced in 1977, was
|
Stella is a portable emulator of the old Atari 2600 video-game
|
||||||
the most popular home video game system of the early 1980's. This
|
console. You can play most Atari 2600 games with it.
|
||||||
emulator will run most Atari ROM images, so that you can play your
|
|
||||||
favorite old Atari 2600 games on your PC.
|
|
||||||
.
|
.
|
||||||
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
|
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0
|
||||||
Thu, 7 Oct 1999 08:57:16 -0700.
|
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>
|
Files: src/common/ZipHandler.hxx
|
||||||
and the Stella Team
|
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.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
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
|
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
|
it under the terms of the GNU General Public License, version 2, as
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
published by the Free Software Foundation.
|
||||||
(at your option) any later version.
|
.
|
||||||
|
This package is distributed in the hope that it will be useful, but
|
||||||
This package is distributed in the hope that it will be useful,
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
General Public License for more details.
|
||||||
GNU General Public License for more details.
|
.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this package; if not, write to the Free Software
|
along with this package; if not, write to the Free Software
|
||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
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'.
|
||||||
|
|
||||||
On Debian systems, the complete text of the GNU General
|
Files: src/zlib/*
|
||||||
Public License can be found in `/usr/share/common-licenses/GPL'.
|
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.
|
# Uncomment this to turn on verbose mode.
|
||||||
#export DH_VERBOSE=1
|
#export DH_VERBOSE=1
|
||||||
|
|
||||||
# These are used for cross-compiling and for saving the configure script
|
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
|
||||||
# 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)
|
|
||||||
|
|
||||||
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
|
dh $@ --with autotools_dev
|
||||||
else
|
|
||||||
CXXFLAGS += -O2
|
|
||||||
endif
|
|
||||||
|
|
||||||
config.status: configure
|
override_dh_auto_clean:
|
||||||
dh_testdir
|
# Generate the minimal config.mak required for "make distclean"
|
||||||
CXXFLAGS="$(CXXFLAGS)" ./configure --prefix=/usr
|
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
|
override_dh_auto_install:
|
||||||
dh_testdir
|
dh_auto_install
|
||||||
$(MAKE)
|
# This is also installed as the upstream changelog
|
||||||
touch build-stamp
|
rm $(CURDIR)/debian/stella/usr/share/doc/stella/Changes.txt
|
||||||
|
# This is overridden by the copyright file
|
||||||
clean:
|
rm $(CURDIR)/debian/stella/usr/share/doc/stella/License.txt
|
||||||
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
|
|
||||||
|
|
|
@ -1,2 +1,4 @@
|
||||||
version=3
|
version=4
|
||||||
http://sf.net/stella/stella-(.*)-src\.tar\.gz
|
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>
|
<body>
|
||||||
|
|
||||||
<center><b><font size="7">Stella</font></b></center>
|
<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><h1><b>Integrated Debugger</b></h1></center>
|
||||||
<center><h4><b>(a work in progress)</b></h4></center>
|
<center><h4><b>(a work in progress)</b></h4></center>
|
||||||
<br>
|
<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
|
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>
|
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'
|
<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
|
command on the command line, or alternatively within the ROM launcher in
|
||||||
'Power-on options':
|
'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> _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> _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> _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> _icycles</td><td> Number of cycles of last instruction</td></tr>
|
||||||
<tr><td> _scan</td><td> Current scanline count</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> _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> _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> _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>
|
<tr><td> _vsync</td><td> Whether vertical sync is enabled (1 or 0)</td></tr>
|
||||||
</table>
|
</table>
|
||||||
|
@ -1131,16 +1143,20 @@ as illustrated:</p>
|
||||||
<!-- ///////////////////////////////////////////////////////////////////////// -->
|
<!-- ///////////////////////////////////////////////////////////////////////// -->
|
||||||
<br>
|
<br>
|
||||||
<h2><a name="TIAInfo"><u>(F)</u> TIA Information</a></h2>
|
<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><img src="graphics/debugger_tiainfo.png"></p>
|
||||||
<p>The indicators are as follows (note that all these are read-only):</p>
|
<p>The indicators are as follows (note that all these are read-only):</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li><b>Frame Count</b>: The number of frames since this ROM was loaded or reset.</li>
|
<li><b>Frame Cycls</b>: The number of CPU cycles that have been executed this frame since
|
||||||
<li><b>Frame Cycle</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>
|
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>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
|
<li><b>Delta</b>: The number of CPU cycles that have been executed since the last debugger
|
||||||
interrupt.</li>
|
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
|
<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
|
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>
|
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
|
<p>This is a spreadsheet-like GUI for inspecting and changing the contents
|
||||||
of the 2600's zero-page RAM.</p>
|
of the 2600's zero-page RAM.</p>
|
||||||
<p>You can navigate with either the mouse or the keyboard arrow keys.
|
<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
|
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
|
it's highlighted. Enter the new value (hex, other formats using the bottom textboxes), then
|
||||||
press Enter to make the change. If you change your mind, press Escape
|
press 'Enter' to make the change. The currently selected RAM cell
|
||||||
and the original value will be restored. The currently selected RAM cell
|
|
||||||
can also be changed by using the
|
can also be changed by using the
|
||||||
<a href="#DataOpButtons"><b>Data Operations Buttons</b></a> or the associated
|
<a href="#DataOpButtons"><b>Data Operations Buttons</b></a> or the associated
|
||||||
shortcut keys.</p>
|
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>
|
since you first made a change.</p>
|
||||||
<p>The UI objects at the bottom refer to the currently selected RAM cell.
|
<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),
|
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>
|
<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
|
<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,
|
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
|
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>
|
as follows:</p>
|
||||||
|
|
||||||
<p><img src="graphics/debugger_ram-f8sc.png"></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 |
589
docs/index.html
|
@ -58,7 +58,7 @@
|
||||||
|
|
||||||
<center><h1>Stella for RetroN 77</h1></center>
|
<center><h1>Stella for RetroN 77</h1></center>
|
||||||
<center><h2>Atari 2600 VCS emulator</h2></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>
|
<center><h2>Quick Navigation Guide</h2></center>
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ class BankRomCheat : public Cheat
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BankRomCheat(OSystem& os, const string& name, const string& code);
|
BankRomCheat(OSystem& os, const string& name, const string& code);
|
||||||
virtual ~BankRomCheat() = default;
|
~BankRomCheat() override = default;
|
||||||
|
|
||||||
bool enable() override;
|
bool enable() override;
|
||||||
bool disable() override;
|
bool disable() override;
|
||||||
|
|
|
@ -100,6 +100,7 @@ CheatCodeDialog::CheatCodeDialog(OSystem& osystem, DialogContainer& parent,
|
||||||
return (c >= 'a' && c <= 'f') || (c >= '0' && c <= '9');
|
return (c >= 'a' && c <= 'f') || (c >= '0' && c <= '9');
|
||||||
};
|
};
|
||||||
myCheatInput->setTextFilter(f1, 1);
|
myCheatInput->setTextFilter(f1, 1);
|
||||||
|
myCheatInput->setToolTip("See Stella documentation for details.", 1);
|
||||||
|
|
||||||
addToFocusList(wid);
|
addToFocusList(wid);
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ class CheatCodeDialog : public Dialog
|
||||||
public:
|
public:
|
||||||
CheatCodeDialog(OSystem& osystem, DialogContainer& parent,
|
CheatCodeDialog(OSystem& osystem, DialogContainer& parent,
|
||||||
const GUI::Font& font);
|
const GUI::Font& font);
|
||||||
virtual ~CheatCodeDialog();
|
~CheatCodeDialog() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void handleCommand(CommandSender* sender, int cmd, int data, int id) override;
|
void handleCommand(CommandSender* sender, int cmd, int data, int id) override;
|
||||||
|
|
|
@ -24,7 +24,7 @@ class CheetahCheat : public Cheat
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CheetahCheat(OSystem& os, const string& name, const string& code);
|
CheetahCheat(OSystem& os, const string& name, const string& code);
|
||||||
virtual ~CheetahCheat() = default;
|
~CheetahCheat() override = default;
|
||||||
|
|
||||||
bool enable() override;
|
bool enable() override;
|
||||||
bool disable() override;
|
bool disable() override;
|
||||||
|
|
|
@ -24,7 +24,7 @@ class RamCheat : public Cheat
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RamCheat(OSystem& os, const string& name, const string& code);
|
RamCheat(OSystem& os, const string& name, const string& code);
|
||||||
virtual ~RamCheat() = default;
|
~RamCheat() override = default;
|
||||||
|
|
||||||
bool enable() override;
|
bool enable() override;
|
||||||
bool disable() override;
|
bool disable() override;
|
||||||
|
|
|
@ -27,6 +27,15 @@ EventHandlerSDL2::EventHandlerSDL2(OSystem& osystem)
|
||||||
{
|
{
|
||||||
ASSERT_MAIN_THREAD;
|
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
|
#ifdef JOYSTICK_SUPPORT
|
||||||
if(SDL_InitSubSystem(SDL_INIT_JOYSTICK) < 0)
|
if(SDL_InitSubSystem(SDL_INIT_JOYSTICK) < 0)
|
||||||
{
|
{
|
||||||
|
@ -36,6 +45,8 @@ EventHandlerSDL2::EventHandlerSDL2(OSystem& osystem)
|
||||||
}
|
}
|
||||||
Logger::debug("EventHandlerSDL2::EventHandlerSDL2 SDL_INIT_JOYSTICK");
|
Logger::debug("EventHandlerSDL2::EventHandlerSDL2 SDL_INIT_JOYSTICK");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1");
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -58,6 +69,23 @@ void EventHandlerSDL2::enableTextEvents(bool enable)
|
||||||
SDL_StopTextInput();
|
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()
|
void EventHandlerSDL2::pollEvent()
|
||||||
{
|
{
|
||||||
|
@ -220,7 +248,6 @@ void EventHandlerSDL2::pollEvent()
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
EventHandlerSDL2::JoystickSDL2::JoystickSDL2(int idx)
|
EventHandlerSDL2::JoystickSDL2::JoystickSDL2(int idx)
|
||||||
: myStick(nullptr)
|
|
||||||
{
|
{
|
||||||
ASSERT_MAIN_THREAD;
|
ASSERT_MAIN_THREAD;
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ class EventHandlerSDL2 : public EventHandler
|
||||||
Create a new SDL2 event handler object
|
Create a new SDL2 event handler object
|
||||||
*/
|
*/
|
||||||
explicit EventHandlerSDL2(OSystem& osystem);
|
explicit EventHandlerSDL2(OSystem& osystem);
|
||||||
virtual ~EventHandlerSDL2();
|
~EventHandlerSDL2() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
|
@ -44,6 +44,12 @@ class EventHandlerSDL2 : public EventHandler
|
||||||
*/
|
*/
|
||||||
void enableTextEvents(bool enable) override;
|
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.
|
Collects and dispatches any pending SDL2 events.
|
||||||
*/
|
*/
|
||||||
|
@ -61,7 +67,7 @@ class EventHandlerSDL2 : public EventHandler
|
||||||
virtual ~JoystickSDL2();
|
virtual ~JoystickSDL2();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SDL_Joystick* myStick;
|
SDL_Joystick* myStick{nullptr};
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -27,11 +27,11 @@
|
||||||
|
|
||||||
#include "ThreadDebugging.hxx"
|
#include "ThreadDebugging.hxx"
|
||||||
#include "FBSurfaceSDL2.hxx"
|
#include "FBSurfaceSDL2.hxx"
|
||||||
#include "FrameBufferSDL2.hxx"
|
#include "FBBackendSDL2.hxx"
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
FrameBufferSDL2::FrameBufferSDL2(OSystem& osystem)
|
FBBackendSDL2::FBBackendSDL2(OSystem& osystem)
|
||||||
: FrameBuffer(osystem)
|
: myOSystem(osystem)
|
||||||
{
|
{
|
||||||
ASSERT_MAIN_THREAD;
|
ASSERT_MAIN_THREAD;
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ FrameBufferSDL2::FrameBufferSDL2(OSystem& osystem)
|
||||||
Logger::error(buf.str());
|
Logger::error(buf.str());
|
||||||
throw runtime_error("FATAL ERROR");
|
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
|
// We need a pixel format for palette value calculations
|
||||||
// It's done this way (vs directly accessing a FBSurfaceSDL2 object)
|
// 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;
|
ASSERT_MAIN_THREAD;
|
||||||
|
|
||||||
|
@ -61,12 +61,6 @@ FrameBufferSDL2::~FrameBufferSDL2()
|
||||||
|
|
||||||
if(myRenderer)
|
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);
|
SDL_DestroyRenderer(myRenderer);
|
||||||
myRenderer = nullptr;
|
myRenderer = nullptr;
|
||||||
}
|
}
|
||||||
|
@ -81,7 +75,7 @@ FrameBufferSDL2::~FrameBufferSDL2()
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FrameBufferSDL2::queryHardware(vector<Common::Size>& fullscreenRes,
|
void FBBackendSDL2::queryHardware(vector<Common::Size>& fullscreenRes,
|
||||||
vector<Common::Size>& windowedRes,
|
vector<Common::Size>& windowedRes,
|
||||||
VariantList& renderers)
|
VariantList& renderers)
|
||||||
{
|
{
|
||||||
|
@ -105,7 +99,7 @@ void FrameBufferSDL2::queryHardware(vector<Common::Size>& fullscreenRes,
|
||||||
|
|
||||||
string lastRes = "";
|
string lastRes = "";
|
||||||
|
|
||||||
for (int m = 0; m < numModes; m++)
|
for(int m = 0; m < numModes; ++m)
|
||||||
{
|
{
|
||||||
SDL_DisplayMode mode;
|
SDL_DisplayMode mode;
|
||||||
ostringstream res;
|
ostringstream res;
|
||||||
|
@ -196,7 +190,7 @@ void FrameBufferSDL2::queryHardware(vector<Common::Size>& fullscreenRes,
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool FrameBufferSDL2::isCurrentWindowPositioned() const
|
bool FBBackendSDL2::isCurrentWindowPositioned() const
|
||||||
{
|
{
|
||||||
ASSERT_MAIN_THREAD;
|
ASSERT_MAIN_THREAD;
|
||||||
|
|
||||||
|
@ -205,7 +199,7 @@ bool FrameBufferSDL2::isCurrentWindowPositioned() const
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
Common::Point FrameBufferSDL2::getCurrentWindowPos() const
|
Common::Point FBBackendSDL2::getCurrentWindowPos() const
|
||||||
{
|
{
|
||||||
ASSERT_MAIN_THREAD;
|
ASSERT_MAIN_THREAD;
|
||||||
|
|
||||||
|
@ -217,7 +211,7 @@ Common::Point FrameBufferSDL2::getCurrentWindowPos() const
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
Int32 FrameBufferSDL2::getCurrentDisplayIndex() const
|
Int32 FBBackendSDL2::getCurrentDisplayIndex() const
|
||||||
{
|
{
|
||||||
ASSERT_MAIN_THREAD;
|
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;
|
ASSERT_MAIN_THREAD;
|
||||||
|
|
||||||
|
@ -235,11 +230,7 @@ bool FrameBufferSDL2::setVideoMode(const string& title, const VideoMode& mode)
|
||||||
|
|
||||||
const bool fullScreen = mode.fsIndex != -1;
|
const bool fullScreen = mode.fsIndex != -1;
|
||||||
bool forceCreateRenderer = false;
|
bool forceCreateRenderer = false;
|
||||||
|
Int32 displayIndex = std::min(myNumDisplays, winIdx);
|
||||||
// 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());
|
|
||||||
|
|
||||||
int posX, posY;
|
int posX, posY;
|
||||||
|
|
||||||
|
@ -248,13 +239,13 @@ bool FrameBufferSDL2::setVideoMode(const string& title, const VideoMode& mode)
|
||||||
posX = posY = SDL_WINDOWPOS_CENTERED_DISPLAY(displayIndex);
|
posX = posY = SDL_WINDOWPOS_CENTERED_DISPLAY(displayIndex);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
posX = myWindowedPos.x;
|
posX = winPos.x;
|
||||||
posY = myWindowedPos.y;
|
posY = winPos.y;
|
||||||
|
|
||||||
// Make sure the window is at least partially visibile
|
// Make sure the window is at least partially visibile
|
||||||
int x0 = 0, y0 = 0, x1 = 0, y1 = 0;
|
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;
|
SDL_Rect rect;
|
||||||
|
|
||||||
|
@ -266,22 +257,28 @@ bool FrameBufferSDL2::setVideoMode(const string& title, const VideoMode& mode)
|
||||||
y1 = std::max(y1, rect.y + rect.h);
|
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);
|
posY = BSPF::clamp(posY, y0 + 50, y1 - 50);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ADAPTABLE_REFRESH_SUPPORT
|
#ifdef ADAPTABLE_REFRESH_SUPPORT
|
||||||
SDL_DisplayMode adaptedSdlMode;
|
SDL_DisplayMode adaptedSdlMode;
|
||||||
const bool shouldAdapt = fullScreen && myOSystem.settings().getBool("tia.fs_refresh")
|
const int gameRefreshRate =
|
||||||
&& gameRefreshRate()
|
myOSystem.hasConsole() ? myOSystem.console().gameRefreshRate() : 0;
|
||||||
|
const bool shouldAdapt = fullScreen
|
||||||
|
&& myOSystem.settings().getBool("tia.fs_refresh")
|
||||||
|
&& gameRefreshRate
|
||||||
// take care of 59.94 Hz
|
// take care of 59.94 Hz
|
||||||
&& refreshRate() % gameRefreshRate() != 0 && refreshRate() % (gameRefreshRate() - 1) != 0;
|
&& refreshRate() % gameRefreshRate != 0
|
||||||
const bool adaptRefresh = shouldAdapt && adaptRefreshRate(displayIndex, adaptedSdlMode);
|
&& refreshRate() % (gameRefreshRate - 1) != 0;
|
||||||
|
const bool adaptRefresh = shouldAdapt &&
|
||||||
|
adaptRefreshRate(displayIndex, adaptedSdlMode);
|
||||||
#else
|
#else
|
||||||
const bool adaptRefresh = false;
|
const bool adaptRefresh = false;
|
||||||
#endif
|
#endif
|
||||||
const uInt32 flags = SDL_WINDOW_ALLOW_HIGHDPI
|
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,
|
// 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
|
// 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;
|
int w, h;
|
||||||
|
|
||||||
SDL_GetWindowSize(myWindow, &w, &h);
|
SDL_GetWindowSize(myWindow, &w, &h);
|
||||||
if(d != displayIndex || uInt32(w) != mode.screen.w || uInt32(h) != mode.screen.h
|
if(d != displayIndex || uInt32(w) != mode.screenS.w ||
|
||||||
|| adaptRefresh)
|
uInt32(h) != mode.screenS.h || adaptRefresh)
|
||||||
{
|
{
|
||||||
SDL_DestroyWindow(myWindow);
|
SDL_DestroyWindow(myWindow);
|
||||||
myWindow = nullptr;
|
myWindow = nullptr;
|
||||||
|
@ -302,14 +299,14 @@ bool FrameBufferSDL2::setVideoMode(const string& title, const VideoMode& mode)
|
||||||
if(myWindow)
|
if(myWindow)
|
||||||
{
|
{
|
||||||
// Even though window size stayed the same, the title may have changed
|
// 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);
|
SDL_SetWindowPosition(myWindow, posX, posY);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
forceCreateRenderer = true;
|
forceCreateRenderer = true;
|
||||||
myWindow = SDL_CreateWindow(title.c_str(), posX, posY,
|
myWindow = SDL_CreateWindow(myScreenTitle.c_str(), posX, posY,
|
||||||
mode.screen.w, mode.screen.h, flags);
|
mode.screenS.w, mode.screenS.h, flags);
|
||||||
if(myWindow == nullptr)
|
if(myWindow == nullptr)
|
||||||
{
|
{
|
||||||
string msg = "ERROR: Unable to open SDL window: " + string(SDL_GetError());
|
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;
|
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());
|
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;
|
SDL_DisplayMode sdlMode;
|
||||||
|
|
||||||
if(SDL_GetCurrentDisplayMode(displayIndex, &sdlMode) != 0)
|
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 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)
|
// Take care of rounded refresh rates (e.g. 59.94 Hz)
|
||||||
float factor = std::min(float(currentRefreshRate) / wantedRefreshRate,
|
float factor = std::min(float(currentRefreshRate) / wantedRefreshRate,
|
||||||
float(currentRefreshRate) / (wantedRefreshRate - 1));
|
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:
|
// A new renderer is only created when necessary:
|
||||||
// - new myWindow (force = true)
|
// - new myWindow (force = true)
|
||||||
// - no renderer existing
|
// - 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;
|
ASSERT_MAIN_THREAD;
|
||||||
|
|
||||||
|
@ -461,7 +465,7 @@ void FrameBufferSDL2::setTitle(const string& title)
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
string FrameBufferSDL2::about() const
|
string FBBackendSDL2::about() const
|
||||||
{
|
{
|
||||||
ASSERT_MAIN_THREAD;
|
ASSERT_MAIN_THREAD;
|
||||||
|
|
||||||
|
@ -483,7 +487,7 @@ string FrameBufferSDL2::about() const
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FrameBufferSDL2::showCursor(bool show)
|
void FBBackendSDL2::showCursor(bool show)
|
||||||
{
|
{
|
||||||
ASSERT_MAIN_THREAD;
|
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;
|
ASSERT_MAIN_THREAD;
|
||||||
|
|
||||||
|
@ -499,7 +503,7 @@ void FrameBufferSDL2::grabMouse(bool grab)
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
bool FrameBufferSDL2::fullScreen() const
|
bool FBBackendSDL2::fullScreen() const
|
||||||
{
|
{
|
||||||
ASSERT_MAIN_THREAD;
|
ASSERT_MAIN_THREAD;
|
||||||
|
|
||||||
|
@ -511,7 +515,7 @@ bool FrameBufferSDL2::fullScreen() const
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
int FrameBufferSDL2::refreshRate() const
|
int FBBackendSDL2::refreshRate() const
|
||||||
{
|
{
|
||||||
ASSERT_MAIN_THREAD;
|
ASSERT_MAIN_THREAD;
|
||||||
|
|
||||||
|
@ -528,20 +532,7 @@ int FrameBufferSDL2::refreshRate() const
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
int FrameBufferSDL2::gameRefreshRate() const
|
void FBBackendSDL2::renderToScreen()
|
||||||
{
|
|
||||||
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()
|
|
||||||
{
|
{
|
||||||
ASSERT_MAIN_THREAD;
|
ASSERT_MAIN_THREAD;
|
||||||
|
|
||||||
|
@ -550,7 +541,7 @@ void FrameBufferSDL2::renderToScreen()
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FrameBufferSDL2::setWindowIcon()
|
void FBBackendSDL2::setWindowIcon()
|
||||||
{
|
{
|
||||||
#if !defined(BSPF_MACOS) && !defined(RETRON77)
|
#if !defined(BSPF_MACOS) && !defined(RETRON77)
|
||||||
#include "stella_icon.hxx"
|
#include "stella_icon.hxx"
|
||||||
|
@ -564,18 +555,19 @@ void FrameBufferSDL2::setWindowIcon()
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
unique_ptr<FBSurface> FrameBufferSDL2::createSurface(
|
unique_ptr<FBSurface> FBBackendSDL2::createSurface(
|
||||||
uInt32 w,
|
uInt32 w,
|
||||||
uInt32 h,
|
uInt32 h,
|
||||||
FrameBuffer::ScalingInterpolation interpolation,
|
ScalingInterpolation inter,
|
||||||
const uInt32* data
|
const uInt32* data
|
||||||
) const
|
) 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,
|
void FBBackendSDL2::readPixels(uInt8* pixels, uInt32 pitch,
|
||||||
const Common::Rect& rect) const
|
const Common::Rect& rect) const
|
||||||
{
|
{
|
||||||
ASSERT_MAIN_THREAD;
|
ASSERT_MAIN_THREAD;
|
||||||
|
@ -588,7 +580,7 @@ void FrameBufferSDL2::readPixels(uInt8* pixels, uInt32 pitch,
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FrameBufferSDL2::clear()
|
void FBBackendSDL2::clear()
|
||||||
{
|
{
|
||||||
ASSERT_MAIN_THREAD;
|
ASSERT_MAIN_THREAD;
|
||||||
|
|
||||||
|
@ -596,49 +588,34 @@ void FrameBufferSDL2::clear()
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
SDL_Renderer* FrameBufferSDL2::renderer()
|
void FBBackendSDL2::detectFeatures()
|
||||||
{
|
|
||||||
return myRenderer;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
bool FrameBufferSDL2::isInitialized() const
|
|
||||||
{
|
|
||||||
return myRenderer != nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
const SDL_PixelFormat& FrameBufferSDL2::pixelFormat() const
|
|
||||||
{
|
|
||||||
return *myPixelFormat;
|
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
|
||||||
void FrameBufferSDL2::detectFeatures()
|
|
||||||
{
|
{
|
||||||
myRenderTargetSupport = detectRenderTargetSupport();
|
myRenderTargetSupport = detectRenderTargetSupport();
|
||||||
|
|
||||||
if (myRenderer) {
|
if(myRenderer && !myRenderTargetSupport)
|
||||||
if (!myRenderTargetSupport) {
|
|
||||||
Logger::info("Render targets are not supported --- QIS not available");
|
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_RendererInfo info;
|
||||||
|
|
||||||
SDL_GetRendererInfo(myRenderer, &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);
|
int sdlError = SDL_SetRenderTarget(myRenderer, tex);
|
||||||
SDL_SetRenderTarget(myRenderer, nullptr);
|
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);
|
SDL_GetWindowSize(myWindow, &myWindowW, &myWindowH);
|
||||||
|
|
||||||
if (myRenderer == nullptr) {
|
if(myRenderer == nullptr)
|
||||||
|
{
|
||||||
myRenderW = myWindowW;
|
myRenderW = myWindowW;
|
||||||
myRenderH = myWindowH;
|
myRenderH = myWindowH;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
SDL_GetRendererOutputSize(myRenderer, &myRenderW, &myRenderH);
|
SDL_GetRendererOutputSize(myRenderer, &myRenderW, &myRenderH);
|
||||||
}
|
}
|
||||||
}
|
|
|
@ -15,8 +15,8 @@
|
||||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
#ifndef FRAMEBUFFER_SDL2_HXX
|
#ifndef FB_BACKEND_SDL2_HXX
|
||||||
#define FRAMEBUFFER_SDL2_HXX
|
#define FB_BACKEND_SDL2_HXX
|
||||||
|
|
||||||
#include "SDL_lib.hxx"
|
#include "SDL_lib.hxx"
|
||||||
|
|
||||||
|
@ -24,27 +24,55 @@ class OSystem;
|
||||||
class FBSurfaceSDL2;
|
class FBSurfaceSDL2;
|
||||||
|
|
||||||
#include "bspf.hxx"
|
#include "bspf.hxx"
|
||||||
#include "FrameBuffer.hxx"
|
#include "FBBackend.hxx"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This class implements a standard SDL2 2D, hardware accelerated framebuffer.
|
This class implements a standard SDL2 2D, hardware accelerated framebuffer
|
||||||
Behind the scenes, it may be using Direct3D, OpenGL(ES), etc.
|
backend. Behind the scenes, it may be using Direct3D, OpenGL(ES), etc.
|
||||||
|
|
||||||
@author Stephen Anthony
|
@author Stephen Anthony
|
||||||
*/
|
*/
|
||||||
class FrameBufferSDL2 : public FrameBuffer
|
class FBBackendSDL2 : public FBBackend
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
Creates a new SDL2 framebuffer
|
Creates a new SDL2 framebuffer
|
||||||
*/
|
*/
|
||||||
explicit FrameBufferSDL2(OSystem& osystem);
|
explicit FBBackendSDL2(OSystem& osystem);
|
||||||
virtual ~FrameBufferSDL2();
|
~FBBackendSDL2() override;
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
public:
|
||||||
// The following are derived from public methods in FrameBuffer.hxx
|
/**
|
||||||
//////////////////////////////////////////////////////////////////////
|
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.
|
Updates window title.
|
||||||
|
|
||||||
|
@ -93,7 +121,8 @@ class FrameBufferSDL2 : public FrameBuffer
|
||||||
@param pitch The pitch (in bytes) for the pixel data
|
@param pitch The pitch (in bytes) for the pixel data
|
||||||
@param rect The bounding rectangle for the buffer
|
@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
|
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
|
@return The position of the currently displayed window
|
||||||
*/
|
*/
|
||||||
Common::Point getCurrentWindowPos() const override;
|
Common::Point getCurrentWindowPos() const override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This method is called to query the video hardware for the index
|
This method is called to query the video hardware for the index
|
||||||
of the display the current window is displayed on
|
of the display the current window is displayed on
|
||||||
|
@ -124,40 +154,6 @@ class FrameBufferSDL2 : public FrameBuffer
|
||||||
*/
|
*/
|
||||||
void clear() override;
|
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
|
This method is called to query and initialize the video hardware
|
||||||
for desktop and fullscreen resolution information. Since several
|
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.
|
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
|
@return False on any errors, else true
|
||||||
*/
|
*/
|
||||||
bool setVideoMode(const string& title, const VideoMode& mode) override;
|
bool setVideoMode(const VideoModeHandler::Mode& mode,
|
||||||
|
int winIdx, const Common::Point& winPos) 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);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This method is called to create a surface with the given attributes.
|
This method is called to create a surface with the given attributes.
|
||||||
|
|
||||||
@param w The requested width of the new surface.
|
@param w The requested width of the new surface.
|
||||||
@param h The requested height of the new surface.
|
@param h The requested height of the new surface.
|
||||||
@param interpolation Interpolation mode
|
@param inter Interpolation mode
|
||||||
@param data If non-null, use the given data values as a static surface
|
@param data If non-null, use the given data values as a static surface
|
||||||
*/
|
*/
|
||||||
unique_ptr<FBSurface>
|
unique_ptr<FBSurface>
|
||||||
createSurface(
|
createSurface(
|
||||||
uInt32 w,
|
uInt32 w,
|
||||||
uInt32 h,
|
uInt32 h,
|
||||||
FrameBuffer::ScalingInterpolation interpolation,
|
ScalingInterpolation inter,
|
||||||
const uInt32* data
|
const uInt32* data
|
||||||
) const override;
|
) const override;
|
||||||
|
|
||||||
|
@ -222,28 +201,49 @@ class FrameBufferSDL2 : public FrameBuffer
|
||||||
void grabMouse(bool grab) override;
|
void grabMouse(bool grab) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Set the icon for the main SDL window.
|
This method is called to provide information about the backend.
|
||||||
*/
|
|
||||||
void setWindowIcon() override;
|
|
||||||
|
|
||||||
/**
|
|
||||||
This method is called to provide information about the FrameBuffer.
|
|
||||||
*/
|
*/
|
||||||
string about() const override;
|
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
|
This method must be called after all drawing is done, and indicates
|
||||||
that the buffers should be pushed to the physical screen.
|
that the buffers should be pushed to the physical screen.
|
||||||
*/
|
*/
|
||||||
void renderToScreen() override;
|
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.
|
After the renderer has been created, detect the features it supports.
|
||||||
*/
|
*/
|
||||||
void detectFeatures();
|
void detectFeatures();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Detect render target support;
|
Detect render target support.
|
||||||
*/
|
*/
|
||||||
bool detectRenderTargetSupport();
|
bool detectRenderTargetSupport();
|
||||||
|
|
||||||
|
@ -253,16 +253,13 @@ class FrameBufferSDL2 : public FrameBuffer
|
||||||
void determineDimensions();
|
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;
|
void setWindowIcon();
|
||||||
|
|
||||||
/**
|
|
||||||
Retrieve the current game's refresh rate, or 60 if no game
|
|
||||||
*/
|
|
||||||
int gameRefreshRate() const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
OSystem& myOSystem;
|
||||||
|
|
||||||
// The SDL video buffer
|
// The SDL video buffer
|
||||||
SDL_Window* myWindow{nullptr};
|
SDL_Window* myWindow{nullptr};
|
||||||
SDL_Renderer* myRenderer{nullptr};
|
SDL_Renderer* myRenderer{nullptr};
|
||||||
|
@ -273,22 +270,25 @@ class FrameBufferSDL2 : public FrameBuffer
|
||||||
// Center setting of current window
|
// Center setting of current window
|
||||||
bool myCenter{false};
|
bool myCenter{false};
|
||||||
|
|
||||||
// last position of windowed window
|
|
||||||
Common::Point myWindowedPos;
|
|
||||||
|
|
||||||
// Does the renderer support render targets?
|
// Does the renderer support render targets?
|
||||||
bool myRenderTargetSupport{false};
|
bool myRenderTargetSupport{false};
|
||||||
|
|
||||||
|
// Title of the main window/screen
|
||||||
|
string myScreenTitle;
|
||||||
|
|
||||||
|
// Number of displays
|
||||||
|
int myNumDisplays{1};
|
||||||
|
|
||||||
// Window and renderer dimensions
|
// Window and renderer dimensions
|
||||||
int myWindowW{0}, myWindowH{0}, myRenderW{0}, myRenderH{0};
|
int myWindowW{0}, myWindowH{0}, myRenderW{0}, myRenderH{0};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Following constructors and assignment operators not supported
|
// Following constructors and assignment operators not supported
|
||||||
FrameBufferSDL2() = delete;
|
FBBackendSDL2() = delete;
|
||||||
FrameBufferSDL2(const FrameBufferSDL2&) = delete;
|
FBBackendSDL2(const FBBackendSDL2&) = delete;
|
||||||
FrameBufferSDL2(FrameBufferSDL2&&) = delete;
|
FBBackendSDL2(FBBackendSDL2&&) = delete;
|
||||||
FrameBufferSDL2& operator=(const FrameBufferSDL2&) = delete;
|
FBBackendSDL2& operator=(const FBBackendSDL2&) = delete;
|
||||||
FrameBufferSDL2& operator=(FrameBufferSDL2&&) = delete;
|
FBBackendSDL2& operator=(FBBackendSDL2&&) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -22,16 +22,16 @@
|
||||||
#include "sdl_blitter/BlitterFactory.hxx"
|
#include "sdl_blitter/BlitterFactory.hxx"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
BlitterFactory::ScalingAlgorithm scalingAlgorithm(FrameBuffer::ScalingInterpolation interpolation)
|
BlitterFactory::ScalingAlgorithm scalingAlgorithm(ScalingInterpolation inter)
|
||||||
{
|
{
|
||||||
switch (interpolation) {
|
switch (inter) {
|
||||||
case FrameBuffer::ScalingInterpolation::none:
|
case ScalingInterpolation::none:
|
||||||
return BlitterFactory::ScalingAlgorithm::nearestNeighbour;
|
return BlitterFactory::ScalingAlgorithm::nearestNeighbour;
|
||||||
|
|
||||||
case FrameBuffer::ScalingInterpolation::blur:
|
case ScalingInterpolation::blur:
|
||||||
return BlitterFactory::ScalingAlgorithm::bilinear;
|
return BlitterFactory::ScalingAlgorithm::bilinear;
|
||||||
|
|
||||||
case FrameBuffer::ScalingInterpolation::sharp:
|
case ScalingInterpolation::sharp:
|
||||||
return BlitterFactory::ScalingAlgorithm::quasiInteger;
|
return BlitterFactory::ScalingAlgorithm::quasiInteger;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -41,12 +41,12 @@ namespace {
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
FBSurfaceSDL2::FBSurfaceSDL2(FrameBufferSDL2& buffer,
|
FBSurfaceSDL2::FBSurfaceSDL2(FBBackendSDL2& backend,
|
||||||
uInt32 width, uInt32 height,
|
uInt32 width, uInt32 height,
|
||||||
FrameBuffer::ScalingInterpolation interpolation,
|
ScalingInterpolation inter,
|
||||||
const uInt32* staticData)
|
const uInt32* staticData)
|
||||||
: myFB(buffer),
|
: myBackend(backend),
|
||||||
myInterpolationMode(interpolation)
|
myInterpolationMode(inter)
|
||||||
{
|
{
|
||||||
createSurface(width, height, staticData);
|
createSurface(width, height, staticData);
|
||||||
}
|
}
|
||||||
|
@ -104,41 +104,49 @@ const Common::Rect& FBSurfaceSDL2::dstRect() const
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FBSurfaceSDL2::setSrcPos(uInt32 x, uInt32 y)
|
void FBSurfaceSDL2::setSrcPos(uInt32 x, uInt32 y)
|
||||||
{
|
{
|
||||||
if(x != static_cast<uInt32>(mySrcR.x) || y != static_cast<uInt32>(mySrcR.y))
|
if(setSrcPosInternal(x, y))
|
||||||
{
|
|
||||||
setSrcPosInternal(x, y);
|
|
||||||
reinitializeBlitter();
|
reinitializeBlitter();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FBSurfaceSDL2::setSrcSize(uInt32 w, uInt32 h)
|
void FBSurfaceSDL2::setSrcSize(uInt32 w, uInt32 h)
|
||||||
{
|
{
|
||||||
if(w != static_cast<uInt32>(mySrcR.w) || h != static_cast<uInt32>(mySrcR.h))
|
if(setSrcSizeInternal(w, h))
|
||||||
{
|
|
||||||
setSrcSizeInternal(w, h);
|
|
||||||
reinitializeBlitter();
|
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)
|
void FBSurfaceSDL2::setDstPos(uInt32 x, uInt32 y)
|
||||||
{
|
{
|
||||||
if(x != static_cast<uInt32>(myDstR.x) || y != static_cast<uInt32>(myDstR.y))
|
if(setDstPosInternal(x, y))
|
||||||
{
|
|
||||||
setDstPosInternal(x, y);
|
|
||||||
reinitializeBlitter();
|
reinitializeBlitter();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FBSurfaceSDL2::setDstSize(uInt32 w, uInt32 h)
|
void FBSurfaceSDL2::setDstSize(uInt32 w, uInt32 h)
|
||||||
{
|
{
|
||||||
if(w != static_cast<uInt32>(myDstR.w) || h != static_cast<uInt32>(myDstR.h))
|
if(setDstSizeInternal(w, h))
|
||||||
{
|
|
||||||
setDstSizeInternal(w, h);
|
|
||||||
reinitializeBlitter();
|
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);
|
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()
|
void FBSurfaceSDL2::free()
|
||||||
{
|
{
|
||||||
|
@ -214,7 +238,7 @@ void FBSurfaceSDL2::createSurface(uInt32 width, uInt32 height,
|
||||||
ASSERT_MAIN_THREAD;
|
ASSERT_MAIN_THREAD;
|
||||||
|
|
||||||
// Create a surface in the same format as the parent GL class
|
// 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,
|
mySurface = SDL_CreateRGBSurface(0, width, height,
|
||||||
pf.BitsPerPixel, pf.Rmask, pf.Gmask, pf.Bmask, pf.Amask);
|
pf.BitsPerPixel, pf.Rmask, pf.Gmask, pf.Bmask, pf.Amask);
|
||||||
|
@ -242,11 +266,13 @@ void FBSurfaceSDL2::createSurface(uInt32 width, uInt32 height,
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void FBSurfaceSDL2::reinitializeBlitter()
|
void FBSurfaceSDL2::reinitializeBlitter()
|
||||||
{
|
{
|
||||||
if (!myBlitter && myFB.isInitialized())
|
if (!myBlitter && myBackend.isInitialized())
|
||||||
myBlitter = BlitterFactory::createBlitter(myFB, scalingAlgorithm(myInterpolationMode));
|
myBlitter = BlitterFactory::createBlitter(
|
||||||
|
myBackend, scalingAlgorithm(myInterpolationMode));
|
||||||
|
|
||||||
if (myBlitter)
|
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;
|
if (interpolation == myInterpolationMode) return;
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
|
|
||||||
#include "bspf.hxx"
|
#include "bspf.hxx"
|
||||||
#include "FBSurface.hxx"
|
#include "FBSurface.hxx"
|
||||||
#include "FrameBufferSDL2.hxx"
|
#include "FBBackendSDL2.hxx"
|
||||||
#include "sdl_blitter/Blitter.hxx"
|
#include "sdl_blitter/Blitter.hxx"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -32,10 +32,9 @@
|
||||||
class FBSurfaceSDL2 : public FBSurface
|
class FBSurfaceSDL2 : public FBSurface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FBSurfaceSDL2(FrameBufferSDL2& buffer, uInt32 width, uInt32 height,
|
FBSurfaceSDL2(FBBackendSDL2& backend, uInt32 width, uInt32 height,
|
||||||
FrameBuffer::ScalingInterpolation interpolation,
|
ScalingInterpolation inter, const uInt32* staticData);
|
||||||
const uInt32* staticData);
|
~FBSurfaceSDL2() override;
|
||||||
virtual ~FBSurfaceSDL2();
|
|
||||||
|
|
||||||
// Most of the surface drawing primitives are implemented in FBSurface;
|
// Most of the surface drawing primitives are implemented in FBSurface;
|
||||||
// the ones implemented here use SDL-specific code for extra performance
|
// 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;
|
const Common::Rect& dstRect() const override;
|
||||||
void setSrcPos(uInt32 x, uInt32 y) override;
|
void setSrcPos(uInt32 x, uInt32 y) override;
|
||||||
void setSrcSize(uInt32 w, uInt32 h) override;
|
void setSrcSize(uInt32 w, uInt32 h) override;
|
||||||
|
void setSrcRect(const Common::Rect& r) override;
|
||||||
void setDstPos(uInt32 x, uInt32 y) override;
|
void setDstPos(uInt32 x, uInt32 y) override;
|
||||||
void setDstSize(uInt32 w, uInt32 h) override;
|
void setDstSize(uInt32 w, uInt32 h) override;
|
||||||
|
void setDstRect(const Common::Rect& r) override;
|
||||||
|
|
||||||
void setVisible(bool visible) override;
|
void setVisible(bool visible) override;
|
||||||
|
|
||||||
void translateCoords(Int32& x, Int32& y) const override;
|
void translateCoords(Int32& x, Int32& y) const override;
|
||||||
bool render() override;
|
bool render() override;
|
||||||
void invalidate() override;
|
void invalidate() override;
|
||||||
|
void invalidateRect(uInt32 x, uInt32 y, uInt32 w, uInt32 h) override;
|
||||||
|
|
||||||
void free() override;
|
void free() override;
|
||||||
void reload() override;
|
void reload() override;
|
||||||
void resize(uInt32 width, uInt32 height) override;
|
void resize(uInt32 width, uInt32 height) override;
|
||||||
|
|
||||||
void setScalingInterpolation(FrameBuffer::ScalingInterpolation) override;
|
void setScalingInterpolation(ScalingInterpolation) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void applyAttributes() override;
|
void applyAttributes() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
inline void setSrcPosInternal(uInt32 x, uInt32 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;
|
mySrcR.x = x; mySrcR.y = y;
|
||||||
mySrcGUIR.moveTo(x, y);
|
mySrcGUIR.moveTo(x, y);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
inline void setSrcSizeInternal(uInt32 w, uInt32 h) {
|
return false;
|
||||||
|
}
|
||||||
|
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;
|
mySrcR.w = w; mySrcR.h = h;
|
||||||
mySrcGUIR.setWidth(w); mySrcGUIR.setHeight(h);
|
mySrcGUIR.setWidth(w); mySrcGUIR.setHeight(h);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
inline void setDstPosInternal(uInt32 x, uInt32 y) {
|
return false;
|
||||||
|
}
|
||||||
|
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;
|
myDstR.x = x; myDstR.y = y;
|
||||||
myDstGUIR.moveTo(x, y);
|
myDstGUIR.moveTo(x, y);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
inline void setDstSizeInternal(uInt32 w, uInt32 h) {
|
return false;
|
||||||
|
}
|
||||||
|
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;
|
myDstR.w = w; myDstR.h = h;
|
||||||
myDstGUIR.setWidth(w); myDstGUIR.setHeight(h);
|
myDstGUIR.setWidth(w); myDstGUIR.setHeight(h);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void createSurface(uInt32 width, uInt32 height, const uInt32* data);
|
void createSurface(uInt32 width, uInt32 height, const uInt32* data);
|
||||||
|
@ -95,14 +119,14 @@ class FBSurfaceSDL2 : public FBSurface
|
||||||
FBSurfaceSDL2& operator=(FBSurfaceSDL2&&) = delete;
|
FBSurfaceSDL2& operator=(FBSurfaceSDL2&&) = delete;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FrameBufferSDL2& myFB;
|
FBBackendSDL2& myBackend;
|
||||||
|
|
||||||
unique_ptr<Blitter> myBlitter;
|
unique_ptr<Blitter> myBlitter;
|
||||||
FrameBuffer::ScalingInterpolation myInterpolationMode
|
ScalingInterpolation myInterpolationMode
|
||||||
{FrameBuffer::ScalingInterpolation::none};
|
{ScalingInterpolation::none};
|
||||||
|
|
||||||
SDL_Surface* mySurface{nullptr};
|
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 myIsVisible{true};
|
||||||
bool myIsStatic{false};
|
bool myIsStatic{false};
|
||||||
|
|
|
@ -51,10 +51,10 @@
|
||||||
|
|
||||||
#if defined(__LIB_RETRO__)
|
#if defined(__LIB_RETRO__)
|
||||||
#include "EventHandlerLIBRETRO.hxx"
|
#include "EventHandlerLIBRETRO.hxx"
|
||||||
#include "FrameBufferLIBRETRO.hxx"
|
#include "FBBackendLIBRETRO.hxx"
|
||||||
#elif defined(SDL_SUPPORT)
|
#elif defined(SDL_SUPPORT)
|
||||||
#include "EventHandlerSDL2.hxx"
|
#include "EventHandlerSDL2.hxx"
|
||||||
#include "FrameBufferSDL2.hxx"
|
#include "FBBackendSDL2.hxx"
|
||||||
#else
|
#else
|
||||||
#error Unsupported backend!
|
#error Unsupported backend!
|
||||||
#endif
|
#endif
|
||||||
|
@ -128,12 +128,12 @@ class MediaFactory
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static unique_ptr<FrameBuffer> createVideo(OSystem& osystem)
|
static unique_ptr<FBBackend> createVideoBackend(OSystem& osystem)
|
||||||
{
|
{
|
||||||
#if defined(__LIB_RETRO__)
|
#if defined(__LIB_RETRO__)
|
||||||
return make_unique<FrameBufferLIBRETRO>(osystem);
|
return make_unique<FBBackendLIBRETRO>(osystem);
|
||||||
#elif defined(SDL_SUPPORT)
|
#elif defined(SDL_SUPPORT)
|
||||||
return make_unique<FrameBufferSDL2>(osystem);
|
return make_unique<FBBackendSDL2>(osystem);
|
||||||
#else
|
#else
|
||||||
#error Unsupported platform for FrameBuffer!
|
#error Unsupported platform for FrameBuffer!
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -123,8 +123,8 @@ int PhysicalJoystickHandler::add(const PhysicalJoystickPtr& stick)
|
||||||
{
|
{
|
||||||
StickInfo info("", stick);
|
StickInfo info("", stick);
|
||||||
myDatabase.emplace(stick->name, info);
|
myDatabase.emplace(stick->name, info);
|
||||||
setStickDefaultMapping(stick->ID, Event::NoType, EventMode::kEmulationMode, true);
|
setStickDefaultMapping(stick->ID, Event::NoType, EventMode::kEmulationMode);
|
||||||
setStickDefaultMapping(stick->ID, Event::NoType, EventMode::kMenuMode, true);
|
setStickDefaultMapping(stick->ID, Event::NoType, EventMode::kMenuMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
return stick->ID;
|
return stick->ID;
|
||||||
|
|
|
@ -29,6 +29,8 @@
|
||||||
|
|
||||||
#if defined(BSPF_MACOS) || defined(MACOS_KEYS)
|
#if defined(BSPF_MACOS) || defined(MACOS_KEYS)
|
||||||
static constexpr int MOD3 = KBDM_GUI;
|
static constexpr int MOD3 = KBDM_GUI;
|
||||||
|
static constexpr int CMD = KBDM_GUI;
|
||||||
|
static constexpr int OPTION = KBDM_ALT;
|
||||||
#else
|
#else
|
||||||
static constexpr int MOD3 = KBDM_ALT;
|
static constexpr int MOD3 = KBDM_ALT;
|
||||||
#endif
|
#endif
|
||||||
|
@ -60,6 +62,9 @@ PhysicalKeyboardHandler::PhysicalKeyboardHandler(OSystem& system, EventHandler&
|
||||||
|
|
||||||
setDefaultMapping(Event::NoType, EventMode::kEmulationMode, updateDefaults);
|
setDefaultMapping(Event::NoType, EventMode::kEmulationMode, updateDefaults);
|
||||||
setDefaultMapping(Event::NoType, EventMode::kMenuMode, 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
|
// Otherwise, only reset the given event
|
||||||
bool eraseAll = !updateDefaults && (event == Event::NoType);
|
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 (updateDefaults)
|
||||||
{
|
{
|
||||||
// if there is no existing mapping for the event and
|
// 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);
|
setDefaultKey(item, event, EventMode::kMenuMode, updateDefaults);
|
||||||
break;
|
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:
|
default:
|
||||||
break;
|
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
|
// determine controller events to use
|
||||||
switch(type)
|
switch(type)
|
||||||
|
@ -199,7 +224,8 @@ void PhysicalKeyboardHandler::enableEmulationMappings()
|
||||||
myKeyMap.eraseMode(EventMode::kEmulationMode);
|
myKeyMap.eraseMode(EventMode::kEmulationMode);
|
||||||
enableCommonMappings();
|
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)
|
switch (myRightMode)
|
||||||
{
|
{
|
||||||
case EventMode::kPaddlesMode:
|
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)
|
for (const auto& event : events)
|
||||||
enableMapping(event, mode);
|
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
|
// copy from controller mode into emulation mode
|
||||||
KeyMap::MappingArray mappings = myKeyMap.getEventMapping(event, 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)
|
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::kKeypadMode, key, mod);
|
||||||
myKeyMap.erase(EventMode::kCompuMateMode, 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
|
// erase identical mapping for kCommonMode
|
||||||
myKeyMap.erase(EventMode::kCommonMode, key, mod);
|
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
|
#ifdef BSPF_UNIX
|
||||||
// Swallow KBDK_TAB under certain conditions
|
// 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)
|
if(myAltKeyCounter > 1 && key == KBDK_TAB)
|
||||||
{
|
{
|
||||||
myAltKeyCounter = 0;
|
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::ConsoleSelect, KBDK_F1},
|
||||||
{Event::ConsoleReset, KBDK_F2},
|
{Event::ConsoleReset, KBDK_F2},
|
||||||
{Event::ConsoleColor, KBDK_F3},
|
{Event::ConsoleColor, KBDK_F3},
|
||||||
|
@ -470,6 +501,7 @@ PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultCommo
|
||||||
{Event::VCenterIncrease, KBDK_PAGEDOWN, MOD3},
|
{Event::VCenterIncrease, KBDK_PAGEDOWN, MOD3},
|
||||||
{Event::VSizeAdjustDecrease, KBDK_PAGEDOWN, KBDM_SHIFT | MOD3},
|
{Event::VSizeAdjustDecrease, KBDK_PAGEDOWN, KBDM_SHIFT | MOD3},
|
||||||
{Event::VSizeAdjustIncrease, KBDK_PAGEUP, KBDM_SHIFT | MOD3},
|
{Event::VSizeAdjustIncrease, KBDK_PAGEUP, KBDM_SHIFT | MOD3},
|
||||||
|
{Event::ToggleCorrectAspectRatio, KBDK_C, KBDM_CTRL},
|
||||||
{Event::VolumeDecrease, KBDK_LEFTBRACKET, MOD3},
|
{Event::VolumeDecrease, KBDK_LEFTBRACKET, MOD3},
|
||||||
{Event::VolumeIncrease, KBDK_RIGHTBRACKET, MOD3},
|
{Event::VolumeIncrease, KBDK_RIGHTBRACKET, MOD3},
|
||||||
{Event::SoundToggle, KBDK_RIGHTBRACKET, KBDM_CTRL},
|
{Event::SoundToggle, KBDK_RIGHTBRACKET, KBDM_CTRL},
|
||||||
|
@ -533,8 +565,8 @@ PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultCommo
|
||||||
{Event::ToggleTimeMachine, KBDK_T, MOD3},
|
{Event::ToggleTimeMachine, KBDK_T, MOD3},
|
||||||
|
|
||||||
#ifdef PNG_SUPPORT
|
#ifdef PNG_SUPPORT
|
||||||
{Event::ToggleContSnapshots, KBDK_S, MOD3},
|
{Event::ToggleContSnapshots, KBDK_S, MOD3 | KBDM_CTRL},
|
||||||
{Event::ToggleContSnapshotsFrame, KBDK_S, KBDM_SHIFT | MOD3},
|
{Event::ToggleContSnapshotsFrame, KBDK_S, KBDM_SHIFT | MOD3 | KBDM_CTRL},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
{Event::DecreaseAutoFire, KBDK_A, KBDM_SHIFT | KBDM_CTRL},
|
{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::UIUp, KBDK_UP},
|
||||||
{Event::UIDown, KBDK_DOWN},
|
{Event::UIDown, KBDK_DOWN},
|
||||||
{Event::UILeft, KBDK_LEFT},
|
{Event::UILeft, KBDK_LEFT},
|
||||||
{Event::UIRight, KBDK_RIGHT},
|
{Event::UIRight, KBDK_RIGHT},
|
||||||
{Event::UISelect, KBDK_RETURN},
|
{Event::UISelect, KBDK_RETURN},
|
||||||
|
{Event::UISelect, KBDK_SPACE},
|
||||||
|
|
||||||
{Event::UIHome, KBDK_HOME},
|
{Event::UIHome, KBDK_HOME},
|
||||||
{Event::UIEnd, KBDK_END},
|
{Event::UIEnd, KBDK_END},
|
||||||
|
@ -640,6 +674,88 @@ PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultMenuM
|
||||||
#endif
|
#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 = {
|
PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultJoystickMapping = {
|
||||||
{Event::JoystickZeroUp, KBDK_UP},
|
{Event::JoystickZeroUp, KBDK_UP},
|
||||||
|
@ -659,6 +775,7 @@ PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultJoyst
|
||||||
{Event::JoystickZeroFire9, KBDK_5},
|
{Event::JoystickZeroFire9, KBDK_5},
|
||||||
{Event::JoystickZeroFire9, KBDK_RCTRL},
|
{Event::JoystickZeroFire9, KBDK_RCTRL},
|
||||||
{Event::JoystickZeroFire9, KBDK_KP_3},
|
{Event::JoystickZeroFire9, KBDK_KP_3},
|
||||||
|
|
||||||
{Event::JoystickOneUp, KBDK_Y},
|
{Event::JoystickOneUp, KBDK_Y},
|
||||||
{Event::JoystickOneDown, KBDK_H},
|
{Event::JoystickOneDown, KBDK_H},
|
||||||
{Event::JoystickOneLeft, KBDK_G},
|
{Event::JoystickOneLeft, KBDK_G},
|
||||||
|
@ -666,10 +783,27 @@ PhysicalKeyboardHandler::EventMappingArray PhysicalKeyboardHandler::DefaultJoyst
|
||||||
{Event::JoystickOneFire, KBDK_F},
|
{Event::JoystickOneFire, KBDK_F},
|
||||||
{Event::JoystickOneFire5, KBDK_6},
|
{Event::JoystickOneFire5, KBDK_6},
|
||||||
{Event::JoystickOneFire9, KBDK_7},
|
{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::PaddleZeroDecrease, KBDK_RIGHT},
|
||||||
{Event::PaddleZeroIncrease, KBDK_LEFT},
|
{Event::PaddleZeroIncrease, KBDK_LEFT},
|
||||||
{Event::PaddleZeroFire, KBDK_SPACE},
|
{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::KeyboardZero1, KBDK_1},
|
||||||
{Event::KeyboardZero2, KBDK_2},
|
{Event::KeyboardZero2, KBDK_2},
|
||||||
{Event::KeyboardZero3, KBDK_3},
|
{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_LSHIFT},
|
||||||
{Event::CompuMateShift, KBDK_RSHIFT},
|
{Event::CompuMateShift, KBDK_RSHIFT},
|
||||||
{Event::CompuMateFunc, KBDK_LCTRL},
|
{Event::CompuMateFunc, KBDK_LCTRL},
|
||||||
|
|
|
@ -106,6 +106,7 @@ class PhysicalKeyboardHandler
|
||||||
void enableMappings(const Event::EventSet& events, EventMode mode);
|
void enableMappings(const Event::EventSet& events, EventMode mode);
|
||||||
void enableMapping(const Event::Type event, EventMode mode);
|
void enableMapping(const Event::Type event, EventMode mode);
|
||||||
|
|
||||||
|
private:
|
||||||
OSystem& myOSystem;
|
OSystem& myOSystem;
|
||||||
EventHandler& myHandler;
|
EventHandler& myHandler;
|
||||||
|
|
||||||
|
@ -132,6 +133,9 @@ class PhysicalKeyboardHandler
|
||||||
|
|
||||||
// Controller menu and common emulation mappings
|
// Controller menu and common emulation mappings
|
||||||
static EventMappingArray DefaultMenuMapping;
|
static EventMappingArray DefaultMenuMapping;
|
||||||
|
#ifdef GUI_SUPPORT
|
||||||
|
static EventMappingArray FixedEditMapping;
|
||||||
|
#endif
|
||||||
static EventMappingArray DefaultCommonMapping;
|
static EventMappingArray DefaultCommonMapping;
|
||||||
// Controller specific mappings
|
// Controller specific mappings
|
||||||
static EventMappingArray DefaultJoystickMapping;
|
static EventMappingArray DefaultJoystickMapping;
|
||||||
|
|
|
@ -267,7 +267,7 @@ void PNGLibrary::toggleContinuousSnapshots(bool perFrame)
|
||||||
buf << "Enabling snapshots in " << interval << " second intervals";
|
buf << "Enabling snapshots in " << interval << " second intervals";
|
||||||
interval *= uInt32(myOSystem.frameRate());
|
interval *= uInt32(myOSystem.frameRate());
|
||||||
}
|
}
|
||||||
myOSystem.frameBuffer().showMessage(buf.str());
|
myOSystem.frameBuffer().showTextMessage(buf.str());
|
||||||
setContinuousSnapInterval(interval);
|
setContinuousSnapInterval(interval);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -276,7 +276,7 @@ void PNGLibrary::toggleContinuousSnapshots(bool perFrame)
|
||||||
buf << "Disabling snapshots, generated "
|
buf << "Disabling snapshots, generated "
|
||||||
<< (mySnapCounter / mySnapInterval)
|
<< (mySnapCounter / mySnapInterval)
|
||||||
<< " files";
|
<< " files";
|
||||||
myOSystem.frameBuffer().showMessage(buf.str());
|
myOSystem.frameBuffer().showTextMessage(buf.str());
|
||||||
setContinuousSnapInterval(0);
|
setContinuousSnapInterval(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -296,7 +296,6 @@ void PNGLibrary::takeSnapshot(uInt32 number)
|
||||||
|
|
||||||
// Figure out the correct snapshot name
|
// Figure out the correct snapshot name
|
||||||
string filename;
|
string filename;
|
||||||
bool showmessage = number == 0;
|
|
||||||
string sspath = myOSystem.snapshotSaveDir().getPath() +
|
string sspath = myOSystem.snapshotSaveDir().getPath() +
|
||||||
(myOSystem.settings().getString("snapname") != "int" ?
|
(myOSystem.settings().getString("snapname") != "int" ?
|
||||||
myOSystem.romFile().getNameWithExt("")
|
myOSystem.romFile().getNameWithExt("")
|
||||||
|
@ -347,9 +346,9 @@ void PNGLibrary::takeSnapshot(uInt32 number)
|
||||||
VarList::push_back(comments, "TV Effects", myOSystem.frameBuffer().tiaSurface().effectsInfo());
|
VarList::push_back(comments, "TV Effects", myOSystem.frameBuffer().tiaSurface().effectsInfo());
|
||||||
|
|
||||||
// Now create a PNG snapshot
|
// Now create a PNG snapshot
|
||||||
|
string message = "Snapshot saved";
|
||||||
if(myOSystem.settings().getBool("ss1x"))
|
if(myOSystem.settings().getBool("ss1x"))
|
||||||
{
|
{
|
||||||
string message = "Snapshot saved";
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Common::Rect rect;
|
Common::Rect rect;
|
||||||
|
@ -360,8 +359,6 @@ void PNGLibrary::takeSnapshot(uInt32 number)
|
||||||
{
|
{
|
||||||
message = e.what();
|
message = e.what();
|
||||||
}
|
}
|
||||||
if(showmessage)
|
|
||||||
myOSystem.frameBuffer().showMessage(message);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -369,7 +366,6 @@ void PNGLibrary::takeSnapshot(uInt32 number)
|
||||||
myOSystem.frameBuffer().enableMessages(false);
|
myOSystem.frameBuffer().enableMessages(false);
|
||||||
myOSystem.frameBuffer().tiaSurface().renderForSnapshot();
|
myOSystem.frameBuffer().tiaSurface().renderForSnapshot();
|
||||||
|
|
||||||
string message = "Snapshot saved";
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
myOSystem.png().saveImage(filename, comments);
|
myOSystem.png().saveImage(filename, comments);
|
||||||
|
@ -381,9 +377,8 @@ void PNGLibrary::takeSnapshot(uInt32 number)
|
||||||
|
|
||||||
// Re-enable old messages
|
// Re-enable old messages
|
||||||
myOSystem.frameBuffer().enableMessages(true);
|
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 palette = toPaletteName(PaletteType(type));
|
||||||
const string message = MESSAGES[type] + " palette";
|
const string message = MESSAGES[type] + " palette";
|
||||||
|
|
||||||
myOSystem.frameBuffer().showMessage(message);
|
myOSystem.frameBuffer().showTextMessage(message);
|
||||||
|
|
||||||
setPalette(palette);
|
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()
|
void PaletteHandler::showAdjustableMessage()
|
||||||
{
|
{
|
||||||
const bool isPhaseShift = myAdjustables[myCurrentAdjustable].value == nullptr;
|
|
||||||
ostringstream msg, buf;
|
ostringstream msg, buf;
|
||||||
|
|
||||||
msg << "Palette " << myAdjustables[myCurrentAdjustable].name;
|
msg << "Palette " << myAdjustables[myCurrentAdjustable].name;
|
||||||
if(isPhaseShift)
|
if(isPhaseShift())
|
||||||
{
|
{
|
||||||
const ConsoleTiming timing = myOSystem.console().timing();
|
const ConsoleTiming timing = myOSystem.console().timing();
|
||||||
const bool isNTSC = timing == ConsoleTiming::ntsc;
|
const bool isNTSC = timing == ConsoleTiming::ntsc;
|
||||||
const float value =
|
const float value =
|
||||||
myOSystem.console().timing() == ConsoleTiming::pal ? myPhasePAL : myPhaseNTSC;
|
myOSystem.console().timing() == ConsoleTiming::pal ? myPhasePAL : myPhaseNTSC;
|
||||||
buf << std::fixed << std::setprecision(1) << value << DEGREE;
|
buf << std::fixed << std::setprecision(1) << value << DEGREE;
|
||||||
myOSystem.frameBuffer().showMessage(
|
myOSystem.frameBuffer().showGaugeMessage(
|
||||||
"Palette phase shift", buf.str(), value,
|
"Palette phase shift", buf.str(), value,
|
||||||
(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_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
|
else
|
||||||
{
|
{
|
||||||
const int value = scaleTo100(*myAdjustables[myCurrentAdjustable].value);
|
const int value = isRGBScale()
|
||||||
|
? scaleRGBTo100(*myAdjustables[myCurrentAdjustable].value)
|
||||||
|
: scaleTo100(*myAdjustables[myCurrentAdjustable].value);
|
||||||
buf << value << "%";
|
buf << value << "%";
|
||||||
myOSystem.frameBuffer().showMessage(
|
myOSystem.frameBuffer().showGaugeMessage(
|
||||||
msg.str(), buf.str(), value);
|
msg.str(), buf.str(), value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -106,15 +140,15 @@ void PaletteHandler::showAdjustableMessage()
|
||||||
void PaletteHandler::cycleAdjustable(int direction)
|
void PaletteHandler::cycleAdjustable(int direction)
|
||||||
{
|
{
|
||||||
const bool isCustomPalette = SETTING_CUSTOM == myOSystem.settings().getString("palette");
|
const bool isCustomPalette = SETTING_CUSTOM == myOSystem.settings().getString("palette");
|
||||||
bool isPhaseShift;
|
bool isCustomAdj;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
myCurrentAdjustable = BSPF::clampw(int(myCurrentAdjustable + direction), 0, NUM_ADJUSTABLES - 1);
|
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
|
// skip phase shift when 'Custom' palette is not selected
|
||||||
if(!direction && isPhaseShift && !isCustomPalette)
|
if(!direction && isCustomAdj && !isCustomPalette)
|
||||||
myCurrentAdjustable++;
|
myCurrentAdjustable++;
|
||||||
} while(isPhaseShift && !isCustomPalette);
|
} while(isCustomAdj && !isCustomPalette);
|
||||||
|
|
||||||
showAdjustableMessage();
|
showAdjustableMessage();
|
||||||
}
|
}
|
||||||
|
@ -122,29 +156,38 @@ void PaletteHandler::cycleAdjustable(int direction)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void PaletteHandler::changeAdjustable(int adjustable, 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;
|
myCurrentAdjustable = adjustable;
|
||||||
if(isPhaseShift && !isCustomPalette)
|
|
||||||
myCurrentAdjustable++;
|
|
||||||
|
|
||||||
changeCurrentAdjustable(direction);
|
changeCurrentAdjustable(direction);
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void PaletteHandler::changeCurrentAdjustable(int direction)
|
void PaletteHandler::changeCurrentAdjustable(int direction)
|
||||||
{
|
{
|
||||||
if(myAdjustables[myCurrentAdjustable].value == nullptr)
|
if(isPhaseShift())
|
||||||
changeColorPhaseShift(direction);
|
changeColorPhaseShift(direction);
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
if(isRGBScale())
|
||||||
|
{
|
||||||
|
int newVal = scaleRGBTo100(*myAdjustables[myCurrentAdjustable].value);
|
||||||
|
|
||||||
|
newVal = BSPF::clamp(newVal + direction * 1, 0, 100);
|
||||||
|
*myAdjustables[myCurrentAdjustable].value = scaleRGBFrom100(newVal);
|
||||||
|
}
|
||||||
|
else if(isRGBShift())
|
||||||
|
{
|
||||||
|
float newShift = *myAdjustables[myCurrentAdjustable].value;
|
||||||
|
|
||||||
|
newShift = BSPF::clamp(newShift + direction * 0.5F, -MAX_RGB_SHIFT, MAX_RGB_SHIFT);
|
||||||
|
*myAdjustables[myCurrentAdjustable].value = newShift;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
int newVal = scaleTo100(*myAdjustables[myCurrentAdjustable].value);
|
int newVal = scaleTo100(*myAdjustables[myCurrentAdjustable].value);
|
||||||
|
|
||||||
newVal = BSPF::clamp(newVal + direction * 1, 0, 100);
|
newVal = BSPF::clamp(newVal + direction * 1, 0, 100);
|
||||||
|
|
||||||
*myAdjustables[myCurrentAdjustable].value = scaleFrom100(newVal);
|
*myAdjustables[myCurrentAdjustable].value = scaleFrom100(newVal);
|
||||||
|
}
|
||||||
showAdjustableMessage();
|
showAdjustableMessage();
|
||||||
setPalette();
|
setPalette();
|
||||||
}
|
}
|
||||||
|
@ -162,7 +205,7 @@ void PaletteHandler::changeColorPhaseShift(int direction)
|
||||||
const float shift = isNTSC ? DEF_NTSC_SHIFT : DEF_PAL_SHIFT;
|
const float shift = isNTSC ? DEF_NTSC_SHIFT : DEF_PAL_SHIFT;
|
||||||
float newPhase = isNTSC ? myPhaseNTSC : myPhasePAL;
|
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)
|
if(isNTSC)
|
||||||
myPhaseNTSC = newPhase;
|
myPhaseNTSC = newPhase;
|
||||||
|
@ -181,9 +224,15 @@ void PaletteHandler::loadConfig(const Settings& settings)
|
||||||
{
|
{
|
||||||
// Load adjustables
|
// Load adjustables
|
||||||
myPhaseNTSC = BSPF::clamp(settings.getFloat("pal.phase_ntsc"),
|
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"),
|
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);
|
myHue = BSPF::clamp(settings.getFloat("pal.hue"), -1.0F, 1.0F);
|
||||||
mySaturation = BSPF::clamp(settings.getFloat("pal.saturation"), -1.0F, 1.0F);
|
mySaturation = BSPF::clamp(settings.getFloat("pal.saturation"), -1.0F, 1.0F);
|
||||||
|
@ -198,6 +247,12 @@ void PaletteHandler::saveConfig(Settings& settings) const
|
||||||
// Save adjustables
|
// Save adjustables
|
||||||
settings.setValue("pal.phase_ntsc", myPhaseNTSC);
|
settings.setValue("pal.phase_ntsc", myPhaseNTSC);
|
||||||
settings.setValue("pal.phase_pal", myPhasePAL);
|
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.hue", myHue);
|
||||||
settings.setValue("pal.saturation", mySaturation);
|
settings.setValue("pal.saturation", mySaturation);
|
||||||
|
@ -209,8 +264,14 @@ void PaletteHandler::saveConfig(Settings& settings) const
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void PaletteHandler::setAdjustables(const Adjustable& adjustable)
|
void PaletteHandler::setAdjustables(const Adjustable& adjustable)
|
||||||
{
|
{
|
||||||
myPhaseNTSC = adjustable.phaseNtsc / 10.F;
|
myPhaseNTSC = scaleFromAngles(adjustable.phaseNtsc);
|
||||||
myPhasePAL = adjustable.phasePal / 10.F;
|
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);
|
myHue = scaleFrom100(adjustable.hue);
|
||||||
mySaturation = scaleFrom100(adjustable.saturation);
|
mySaturation = scaleFrom100(adjustable.saturation);
|
||||||
|
@ -222,8 +283,14 @@ void PaletteHandler::setAdjustables(const Adjustable& adjustable)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void PaletteHandler::getAdjustables(Adjustable& adjustable) const
|
void PaletteHandler::getAdjustables(Adjustable& adjustable) const
|
||||||
{
|
{
|
||||||
adjustable.phaseNtsc = myPhaseNTSC * 10.F;
|
adjustable.phaseNtsc = scaleToAngles(myPhaseNTSC);
|
||||||
adjustable.phasePal = myPhasePAL * 10.F;
|
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.hue = scaleTo100(myHue);
|
||||||
adjustable.saturation = scaleTo100(mySaturation);
|
adjustable.saturation = scaleTo100(mySaturation);
|
||||||
|
@ -371,10 +438,9 @@ void PaletteHandler::generateCustomPalette(ConsoleTiming timing)
|
||||||
constexpr int NUM_LUMA = 8;
|
constexpr int NUM_LUMA = 8;
|
||||||
constexpr float SATURATION = 0.25F; // default saturation
|
constexpr float SATURATION = 0.25F; // default saturation
|
||||||
|
|
||||||
float color[NUM_CHROMA][2] = {{0.0F}};
|
|
||||||
|
|
||||||
if(timing == ConsoleTiming::ntsc)
|
if(timing == ConsoleTiming::ntsc)
|
||||||
{
|
{
|
||||||
|
vector2d IQ[NUM_CHROMA];
|
||||||
// YIQ is YUV shifted by 33°
|
// YIQ is YUV shifted by 33°
|
||||||
constexpr float offset = 33 * BSPF::PI_f / 180;
|
constexpr float offset = 33 * BSPF::PI_f / 180;
|
||||||
const float shift = myPhaseNTSC * 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
|
// color 0 is grayscale
|
||||||
for(int chroma = 1; chroma < NUM_CHROMA; chroma++)
|
for(int chroma = 1; chroma < NUM_CHROMA; chroma++)
|
||||||
{
|
{
|
||||||
color[chroma][0] = SATURATION * sinf(offset + shift * (chroma - 1));
|
IQ[chroma] = vector2d(SATURATION * sinf(offset + shift * (chroma - 1)),
|
||||||
color[chroma][1] = SATURATION * cosf(offset + shift * (chroma - 1) - BSPF::PI_f);
|
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++)
|
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++)
|
for(int luma = 0; luma < NUM_LUMA; luma++)
|
||||||
{
|
{
|
||||||
const float Y = 0.05F + luma / 8.24F; // 0.05..~0.90
|
const float Y = 0.05F + luma / 8.24F; // 0.05..~0.90
|
||||||
|
|
||||||
float R = Y + 0.956F * I + 0.621F * Q;
|
float R = Y + dotProduct(IQ[chroma], IQR);
|
||||||
float G = Y - 0.272F * I - 0.647F * Q;
|
float G = Y + dotProduct(IQ[chroma], IQG);
|
||||||
float B = Y - 1.106F * I + 1.703F * Q;
|
float B = Y + dotProduct(IQ[chroma], IQB);
|
||||||
|
|
||||||
|
|
||||||
if(R < 0) R = 0;
|
if(R < 0) R = 0;
|
||||||
if(G < 0) G = 0;
|
if(G < 0) G = 0;
|
||||||
|
@ -420,35 +487,37 @@ void PaletteHandler::generateCustomPalette(ConsoleTiming timing)
|
||||||
constexpr float offset = BSPF::PI_f;
|
constexpr float offset = BSPF::PI_f;
|
||||||
const float shift = myPhasePAL * BSPF::PI_f / 180;
|
const float shift = myPhasePAL * BSPF::PI_f / 180;
|
||||||
constexpr float fixedShift = 22.5F * 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
|
// colors 0, 1, 14 and 15 are grayscale
|
||||||
for(int chroma = 2; chroma < NUM_CHROMA - 2; chroma++)
|
for(int chroma = 2; chroma < NUM_CHROMA - 2; chroma++)
|
||||||
{
|
{
|
||||||
int idx = NUM_CHROMA - 1 - 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)
|
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
|
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++)
|
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++)
|
for(int luma = 0; luma < NUM_LUMA; luma++)
|
||||||
{
|
{
|
||||||
const float Y = 0.05F + luma / 8.24F; // 0.05..~0.90
|
const float Y = 0.05F + luma / 8.24F; // 0.05..~0.90
|
||||||
|
|
||||||
// Most sources
|
float R = Y + dotProduct(UV[chroma], UVR);
|
||||||
float R = Y + 1.403F * V;
|
float G = Y + dotProduct(UV[chroma], UVG);
|
||||||
float G = Y - 0.344F * U - 0.714F * V;
|
float B = Y + dotProduct(UV[chroma], UVB);
|
||||||
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;
|
|
||||||
|
|
||||||
if(R < 0) R = 0.0;
|
if(R < 0) R = 0.0;
|
||||||
if(G < 0) G = 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);
|
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 = {
|
const PaletteArray PaletteHandler::ourNTSCPalette = {
|
||||||
0x000000, 0, 0x4a4a4a, 0, 0x6f6f6f, 0, 0x8e8e8e, 0,
|
0x000000, 0, 0x4a4a4a, 0, 0x6f6f6f, 0, 0x8e8e8e, 0,
|
||||||
|
|
|
@ -35,26 +35,37 @@ class PaletteHandler
|
||||||
// Phase shift default and limits
|
// Phase shift default and limits
|
||||||
static constexpr float DEF_NTSC_SHIFT = 26.2F;
|
static constexpr float DEF_NTSC_SHIFT = 26.2F;
|
||||||
static constexpr float DEF_PAL_SHIFT = 31.3F; // ~= 360 / 11.5
|
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 {
|
enum Adjustables {
|
||||||
PHASE_SHIFT,
|
PHASE_SHIFT,
|
||||||
|
RED_SCALE,
|
||||||
|
GREEN_SCALE,
|
||||||
|
BLUE_SCALE,
|
||||||
|
RED_SHIFT,
|
||||||
|
GREEN_SHIFT,
|
||||||
|
BLUE_SHIFT,
|
||||||
HUE,
|
HUE,
|
||||||
SATURATION,
|
SATURATION,
|
||||||
CONTRAST,
|
CONTRAST,
|
||||||
BRIGHTNESS,
|
BRIGHTNESS,
|
||||||
GAMMA
|
GAMMA,
|
||||||
|
CUSTOM_START = PHASE_SHIFT,
|
||||||
|
CUSTOM_END = BLUE_SHIFT,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Externally used adjustment parameters
|
// Externally used adjustment parameters
|
||||||
struct Adjustable {
|
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};
|
uInt32 hue{0}, saturation{0}, contrast{0}, brightness{0}, gamma{0};
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PaletteHandler(OSystem& system);
|
PaletteHandler(OSystem& system);
|
||||||
virtual ~PaletteHandler() = default;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Cycle through available palettes.
|
Cycle through available palettes.
|
||||||
|
@ -109,6 +120,7 @@ class PaletteHandler
|
||||||
*/
|
*/
|
||||||
void setPalette();
|
void setPalette();
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr char DEGREE = 0x1c;
|
static constexpr char DEGREE = 0x1c;
|
||||||
|
|
||||||
|
@ -122,12 +134,43 @@ class PaletteHandler
|
||||||
MaxType = Custom
|
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
|
Convert adjustables from/to 100% scale
|
||||||
*/
|
*/
|
||||||
static constexpr float scaleFrom100(float x) { return (x / 50.F) - 1.F; }
|
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)); }
|
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.
|
Convert palette settings name to enumeration.
|
||||||
|
|
||||||
|
@ -187,6 +230,21 @@ class PaletteHandler
|
||||||
*/
|
*/
|
||||||
void adjustHueSaturation(int& R, int& G, int& B, float H, float S);
|
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
|
Loads a user-defined palette file (from OSystem::paletteFile), filling the
|
||||||
appropriate user-defined palette arrays.
|
appropriate user-defined palette arrays.
|
||||||
|
@ -194,7 +252,7 @@ class PaletteHandler
|
||||||
void loadUserPalette();
|
void loadUserPalette();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr int NUM_ADJUSTABLES = 6;
|
static constexpr int NUM_ADJUSTABLES = 12;
|
||||||
|
|
||||||
OSystem& myOSystem;
|
OSystem& myOSystem;
|
||||||
|
|
||||||
|
@ -208,6 +266,12 @@ class PaletteHandler
|
||||||
const std::array<AdjustableTag, NUM_ADJUSTABLES> myAdjustables =
|
const std::array<AdjustableTag, NUM_ADJUSTABLES> myAdjustables =
|
||||||
{ {
|
{ {
|
||||||
{ "phase shift", nullptr },
|
{ "phase shift", nullptr },
|
||||||
|
{ "red scale", &myRedScale },
|
||||||
|
{ "green scale", &myGreenScale },
|
||||||
|
{ "blue scale", &myBlueScale },
|
||||||
|
{ "red shift", &myRedShift },
|
||||||
|
{ "green shift", &myGreenShift },
|
||||||
|
{ "blue shift", &myBlueShift },
|
||||||
{ "hue", &myHue },
|
{ "hue", &myHue },
|
||||||
{ "saturation", &mySaturation },
|
{ "saturation", &mySaturation },
|
||||||
{ "contrast", &myContrast },
|
{ "contrast", &myContrast },
|
||||||
|
@ -218,6 +282,14 @@ class PaletteHandler
|
||||||
// NTSC and PAL color phase shifts
|
// NTSC and PAL color phase shifts
|
||||||
float myPhaseNTSC{DEF_NTSC_SHIFT};
|
float myPhaseNTSC{DEF_NTSC_SHIFT};
|
||||||
float myPhasePAL{DEF_PAL_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)
|
// range -1.0 to +1.0 (as in AtariNTSC)
|
||||||
// Basic parameters
|
// Basic parameters
|
||||||
float myHue{0.0F}; // -1 = -180 degrees +1 = +180 degrees
|
float myHue{0.0F}; // -1 = -180 degrees +1 = +180 degrees
|
||||||
|
|
|
@ -45,7 +45,7 @@ struct Point
|
||||||
x = y = 0;
|
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) {
|
friend ostream& operator<<(ostream& os, const Point& p) {
|
||||||
os << p.x << "x" << p.y;
|
os << p.x << "x" << p.y;
|
||||||
|
@ -69,12 +69,17 @@ struct Size
|
||||||
}
|
}
|
||||||
bool valid() const { return w > 0 && h > 0; }
|
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 w >= s.w && h >= s.h; }
|
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) {
|
friend ostream& operator<<(ostream& os, const Size& s) {
|
||||||
os << s.w << "x" << s.h;
|
os << s.w << "x" << s.h;
|
||||||
|
@ -170,6 +175,11 @@ struct Rect
|
||||||
return r.left != x || r.top != y;
|
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) {
|
friend ostream& operator<<(ostream& os, const Rect& r) {
|
||||||
os << r.point() << "," << r.size();
|
os << r.point() << "," << r.size();
|
||||||
return os;
|
return os;
|
||||||
|
|
|
@ -37,7 +37,6 @@ RewindManager::RewindManager(OSystem& system, StateManager& statemgr)
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void RewindManager::setup()
|
void RewindManager::setup()
|
||||||
{
|
{
|
||||||
myStateSize = 0;
|
|
||||||
myLastTimeMachineAdd = false;
|
myLastTimeMachineAdd = false;
|
||||||
|
|
||||||
const string& prefix = myOSystem.settings().getBool("dev.settings") ? "dev." : "plr.";
|
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
|
s.rewind(); // rewind Serializer internal buffers
|
||||||
if(myStateManager.saveState(s) && myOSystem.console().tia().saveDisplay(s))
|
if(myStateManager.saveState(s) && myOSystem.console().tia().saveDisplay(s))
|
||||||
{
|
{
|
||||||
myStateSize = std::max(myStateSize, uInt32(s.size()));
|
|
||||||
state.message = message;
|
state.message = message;
|
||||||
state.cycles = myOSystem.console().tia().cycles();
|
state.cycles = myOSystem.console().tia().cycles();
|
||||||
myLastTimeMachineAdd = timeMachine;
|
myLastTimeMachineAdd = timeMachine;
|
||||||
|
@ -183,7 +181,7 @@ uInt32 RewindManager::rewindStates(uInt32 numStates)
|
||||||
|
|
||||||
if(myOSystem.eventHandler().state() != EventHandlerState::TIMEMACHINE
|
if(myOSystem.eventHandler().state() != EventHandlerState::TIMEMACHINE
|
||||||
&& myOSystem.eventHandler().state() != EventHandlerState::PLAYBACK)
|
&& myOSystem.eventHandler().state() != EventHandlerState::PLAYBACK)
|
||||||
myOSystem.frameBuffer().showMessage(message);
|
myOSystem.frameBuffer().showTextMessage(message);
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -218,7 +216,7 @@ uInt32 RewindManager::unwindStates(uInt32 numStates)
|
||||||
|
|
||||||
if(myOSystem.eventHandler().state() != EventHandlerState::TIMEMACHINE
|
if(myOSystem.eventHandler().state() != EventHandlerState::TIMEMACHINE
|
||||||
&& myOSystem.eventHandler().state() != EventHandlerState::PLAYBACK)
|
&& myOSystem.eventHandler().state() != EventHandlerState::PLAYBACK)
|
||||||
myOSystem.frameBuffer().showMessage(message);
|
myOSystem.frameBuffer().showTextMessage(message);
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -256,18 +254,22 @@ string RewindManager::saveAllStates()
|
||||||
buf.str("");
|
buf.str("");
|
||||||
out.putString(STATE_HEADER);
|
out.putString(STATE_HEADER);
|
||||||
out.putShort(numStates);
|
out.putShort(numStates);
|
||||||
out.putInt(myStateSize);
|
|
||||||
|
|
||||||
unique_ptr<uInt8[]> buffer = make_unique<uInt8[]>(myStateSize);
|
|
||||||
for (uInt32 i = 0; i < numStates; ++i)
|
for (uInt32 i = 0; i < numStates; ++i)
|
||||||
{
|
{
|
||||||
RewindState& state = myStateList.current();
|
RewindState& state = myStateList.current();
|
||||||
Serializer& s = state.data;
|
Serializer& s = state.data;
|
||||||
|
uInt32 stateSize = uInt32(s.size());
|
||||||
|
unique_ptr<uInt8[]> buffer = make_unique<uInt8[]>(stateSize);
|
||||||
|
|
||||||
|
out.putInt(stateSize);
|
||||||
|
|
||||||
// Rewind Serializer internal buffers
|
// Rewind Serializer internal buffers
|
||||||
s.rewind();
|
s.rewind();
|
||||||
|
|
||||||
// Save state
|
// Save state
|
||||||
s.getByteArray(buffer.get(), myStateSize);
|
s.getByteArray(buffer.get(), stateSize);
|
||||||
out.putByteArray(buffer.get(), myStateSize);
|
out.putByteArray(buffer.get(), stateSize);
|
||||||
out.putString(state.message);
|
out.putString(state.message);
|
||||||
out.putLong(state.cycles);
|
out.putLong(state.cycles);
|
||||||
|
|
||||||
|
@ -310,25 +312,27 @@ string RewindManager::loadAllStates()
|
||||||
if (in.getString() != STATE_HEADER)
|
if (in.getString() != STATE_HEADER)
|
||||||
return "Incompatible all states file";
|
return "Incompatible all states file";
|
||||||
numStates = in.getShort();
|
numStates = in.getShort();
|
||||||
myStateSize = in.getInt();
|
|
||||||
|
|
||||||
unique_ptr<uInt8[]> buffer = make_unique<uInt8[]>(myStateSize);
|
|
||||||
for (uInt32 i = 0; i < numStates; ++i)
|
for (uInt32 i = 0; i < numStates; ++i)
|
||||||
{
|
{
|
||||||
if (myStateList.full())
|
if (myStateList.full())
|
||||||
compressStates();
|
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)
|
// Add new state at the end of the list (queue adds at end)
|
||||||
// This updates the 'current' iterator inside the list
|
// This updates the 'current' iterator inside the list
|
||||||
myStateList.addLast();
|
myStateList.addLast();
|
||||||
RewindState& state = myStateList.current();
|
RewindState& state = myStateList.current();
|
||||||
Serializer& s = state.data;
|
Serializer& s = state.data;
|
||||||
|
|
||||||
// Rewind Serializer internal buffers
|
// Rewind Serializer internal buffers
|
||||||
s.rewind();
|
s.rewind();
|
||||||
|
|
||||||
// Fill new state with saved values
|
// Fill new state with saved values
|
||||||
in.getByteArray(buffer.get(), myStateSize);
|
in.getByteArray(buffer.get(), stateSize);
|
||||||
s.putByteArray(buffer.get(), myStateSize);
|
s.putByteArray(buffer.get(), stateSize);
|
||||||
state.message = in.getString();
|
state.message = in.getString();
|
||||||
state.cycles = in.getLong();
|
state.cycles = in.getLong();
|
||||||
}
|
}
|
||||||
|
|
|
@ -144,7 +144,6 @@ class RewindManager
|
||||||
bool atLast() const { return myStateList.atLast(); }
|
bool atLast() const { return myStateList.atLast(); }
|
||||||
void resize(uInt32 size) { myStateList.resize(size); }
|
void resize(uInt32 size) { myStateList.resize(size); }
|
||||||
void clear() {
|
void clear() {
|
||||||
myStateSize = 0;
|
|
||||||
myStateList.clear();
|
myStateList.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,7 +175,6 @@ class RewindManager
|
||||||
uInt64 myHorizon{0};
|
uInt64 myHorizon{0};
|
||||||
double myFactor{0.0};
|
double myFactor{0.0};
|
||||||
bool myLastTimeMachineAdd{false};
|
bool myLastTimeMachineAdd{false};
|
||||||
uInt32 myStateSize{0};
|
|
||||||
|
|
||||||
struct RewindState {
|
struct RewindState {
|
||||||
Serializer data; // actual save state
|
Serializer data; // actual save state
|
||||||
|
|
|
@ -43,11 +43,7 @@ class SoundNull : public Sound
|
||||||
{
|
{
|
||||||
Logger::info("Sound disabled.\n");
|
Logger::info("Sound disabled.\n");
|
||||||
}
|
}
|
||||||
|
~SoundNull() override = default;
|
||||||
/**
|
|
||||||
Destructor
|
|
||||||
*/
|
|
||||||
virtual ~SoundNull() = default;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -117,7 +117,7 @@ bool SoundSDL2::openDevice()
|
||||||
if(myIsInitializedFlag)
|
if(myIsInitializedFlag)
|
||||||
SDL_CloseAudioDevice(myDevice);
|
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;
|
const char* device = myDeviceId ? myDevices.at(myDeviceId).first.c_str() : nullptr;
|
||||||
|
|
||||||
myDevice = SDL_OpenAudioDevice(device, 0, &desired, &myHardwareSpec,
|
myDevice = SDL_OpenAudioDevice(device, 0, &desired, &myHardwareSpec,
|
||||||
|
@ -224,7 +224,7 @@ bool SoundSDL2::toggleMute()
|
||||||
string message = "Sound ";
|
string message = "Sound ";
|
||||||
message += enabled ? "unmuted" : "muted";
|
message += enabled ? "unmuted" : "muted";
|
||||||
|
|
||||||
myOSystem.frameBuffer().showMessage(message);
|
myOSystem.frameBuffer().showTextMessage(message);
|
||||||
|
|
||||||
//ostringstream strval;
|
//ostringstream strval;
|
||||||
//uInt32 volume;
|
//uInt32 volume;
|
||||||
|
@ -282,7 +282,7 @@ void SoundSDL2::adjustVolume(int direction)
|
||||||
strval << percent << "%";
|
strval << percent << "%";
|
||||||
else
|
else
|
||||||
strval << "Off";
|
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
|
Destructor
|
||||||
*/
|
*/
|
||||||
virtual ~SoundSDL2();
|
~SoundSDL2() override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -132,9 +132,9 @@ void StateManager::toggleTimeMachine()
|
||||||
|
|
||||||
myActiveMode = myActiveMode == Mode::TimeMachine ? Mode::Off : Mode::TimeMachine;
|
myActiveMode = myActiveMode == Mode::TimeMachine ? Mode::Off : Mode::TimeMachine;
|
||||||
if(myActiveMode == Mode::TimeMachine)
|
if(myActiveMode == Mode::TimeMachine)
|
||||||
myOSystem.frameBuffer().showMessage("Time Machine enabled");
|
myOSystem.frameBuffer().showTextMessage("Time Machine enabled");
|
||||||
else
|
else
|
||||||
myOSystem.frameBuffer().showMessage("Time Machine disabled");
|
myOSystem.frameBuffer().showTextMessage("Time Machine disabled");
|
||||||
myOSystem.settings().setValue(devSettings ? "dev.timemachine" : "plr.timemachine", myActiveMode == Mode::TimeMachine);
|
myOSystem.settings().setValue(devSettings ? "dev.timemachine" : "plr.timemachine", myActiveMode == Mode::TimeMachine);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,7 +215,7 @@ void StateManager::loadState(int slot)
|
||||||
{
|
{
|
||||||
buf.str("");
|
buf.str("");
|
||||||
buf << "Can't open/load from state file " << slot;
|
buf << "Can't open/load from state file " << slot;
|
||||||
myOSystem.frameBuffer().showMessage(buf.str());
|
myOSystem.frameBuffer().showTextMessage(buf.str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -239,7 +239,7 @@ void StateManager::loadState(int slot)
|
||||||
buf << "Invalid data in state " << slot << " file";
|
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.str("");
|
||||||
buf << "Can't open/save to state file " << slot;
|
buf << "Can't open/save to state file " << slot;
|
||||||
myOSystem.frameBuffer().showMessage(buf.str());
|
myOSystem.frameBuffer().showTextMessage(buf.str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -274,7 +274,7 @@ void StateManager::saveState(int slot)
|
||||||
catch(...)
|
catch(...)
|
||||||
{
|
{
|
||||||
buf << "Error saving state " << slot;
|
buf << "Error saving state " << slot;
|
||||||
myOSystem.frameBuffer().showMessage(buf.str());
|
myOSystem.frameBuffer().showTextMessage(buf.str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -292,7 +292,7 @@ void StateManager::saveState(int slot)
|
||||||
else
|
else
|
||||||
buf << "Error saving state " << slot;
|
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;
|
buf << "Changed to state slot " << myCurrentSlot;
|
||||||
else
|
else
|
||||||
buf << "State slot " << myCurrentSlot;
|
buf << "State slot " << myCurrentSlot;
|
||||||
myOSystem.frameBuffer().showMessage(buf.str());
|
myOSystem.frameBuffer().showTextMessage(buf.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -318,7 +318,7 @@ void StateManager::toggleAutoSlot()
|
||||||
// Print appropriate message
|
// Print appropriate message
|
||||||
ostringstream buf;
|
ostringstream buf;
|
||||||
buf << "Automatic slot change " << (autoSlot ? "enabled" : "disabled");
|
buf << "Automatic slot change " << (autoSlot ? "enabled" : "disabled");
|
||||||
myOSystem.frameBuffer().showMessage(buf.str());
|
myOSystem.frameBuffer().showTextMessage(buf.str());
|
||||||
|
|
||||||
myOSystem.settings().setValue("autoslot", autoSlot);
|
myOSystem.settings().setValue("autoslot", autoSlot);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
#ifndef VERSION_HXX
|
#ifndef VERSION_HXX
|
||||||
#define VERSION_HXX
|
#define VERSION_HXX
|
||||||
|
|
||||||
#define STELLA_VERSION "6.3_pre"
|
#define STELLA_VERSION "6.5_pre"
|
||||||
#define STELLA_BUILD "6091"
|
#define STELLA_BUILD "6238"
|
||||||
|
|
||||||
#endif
|
#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);
|
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("");
|
static const string EmptyString("");
|
||||||
|
|
||||||
// This is defined by some systems, but Stella has other uses for it
|
// 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;
|
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
|
// Convert string to given case
|
||||||
inline const string& toUpperCase(string& s)
|
inline const string& toUpperCase(string& s)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
MODULE := src/common
|
MODULE := src/common
|
||||||
|
|
||||||
MODULE_OBJS := \
|
MODULE_OBJS := \
|
||||||
|
src/common/AudioQueue.o \
|
||||||
|
src/common/AudioSettings.o \
|
||||||
src/common/Base.o \
|
src/common/Base.o \
|
||||||
src/common/EventHandlerSDL2.o \
|
src/common/EventHandlerSDL2.o \
|
||||||
|
src/common/FBBackendSDL2.o \
|
||||||
src/common/FBSurfaceSDL2.o \
|
src/common/FBSurfaceSDL2.o \
|
||||||
src/common/FrameBufferSDL2.o \
|
src/common/FpsMeter.o \
|
||||||
src/common/FSNodeZIP.o \
|
src/common/FSNodeZIP.o \
|
||||||
src/common/HighScoresManager.o \
|
src/common/HighScoresManager.o \
|
||||||
src/common/JoyMap.o \
|
src/common/JoyMap.o \
|
||||||
|
@ -20,14 +23,12 @@ MODULE_OBJS := \
|
||||||
src/common/PNGLibrary.o \
|
src/common/PNGLibrary.o \
|
||||||
src/common/RewindManager.o \
|
src/common/RewindManager.o \
|
||||||
src/common/SoundSDL2.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/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/repository/KeyValueRepositoryConfigfile.o \
|
||||||
src/common/sdl_blitter/BilinearBlitter.o \
|
src/common/sdl_blitter/BilinearBlitter.o \
|
||||||
src/common/sdl_blitter/QisBlitter.o \
|
src/common/sdl_blitter/QisBlitter.o \
|
||||||
|
|
|
@ -15,12 +15,12 @@
|
||||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
#include "FrameBufferSDL2.hxx"
|
#include "FBBackendSDL2.hxx"
|
||||||
#include "ThreadDebugging.hxx"
|
#include "ThreadDebugging.hxx"
|
||||||
#include "BilinearBlitter.hxx"
|
#include "BilinearBlitter.hxx"
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
BilinearBlitter::BilinearBlitter(FrameBufferSDL2& fb, bool interpolate)
|
BilinearBlitter::BilinearBlitter(FBBackendSDL2& fb, bool interpolate)
|
||||||
: myFB(fb),
|
: myFB(fb),
|
||||||
myInterpolate(interpolate)
|
myInterpolate(interpolate)
|
||||||
{
|
{
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
#ifndef BILINEAR_BLITTER_HXX
|
#ifndef BILINEAR_BLITTER_HXX
|
||||||
#define BILINEAR_BLITTER_HXX
|
#define BILINEAR_BLITTER_HXX
|
||||||
|
|
||||||
class FrameBufferSDL2;
|
class FBBackendSDL2;
|
||||||
|
|
||||||
#include "Blitter.hxx"
|
#include "Blitter.hxx"
|
||||||
#include "SDL_lib.hxx"
|
#include "SDL_lib.hxx"
|
||||||
|
@ -27,9 +27,9 @@ class BilinearBlitter : public Blitter {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
BilinearBlitter(FrameBufferSDL2& fb, bool interpolate);
|
BilinearBlitter(FBBackendSDL2& fb, bool interpolate);
|
||||||
|
|
||||||
virtual ~BilinearBlitter();
|
~BilinearBlitter() override;
|
||||||
|
|
||||||
virtual void reinitialize(
|
virtual void reinitialize(
|
||||||
SDL_Rect srcRect,
|
SDL_Rect srcRect,
|
||||||
|
@ -41,7 +41,7 @@ class BilinearBlitter : public Blitter {
|
||||||
virtual void blit(SDL_Surface& surface) override;
|
virtual void blit(SDL_Surface& surface) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
FrameBufferSDL2& myFB;
|
FBBackendSDL2& myFB;
|
||||||
|
|
||||||
SDL_Texture* myTexture{nullptr};
|
SDL_Texture* myTexture{nullptr};
|
||||||
SDL_Texture* mySecondaryTexture{nullptr};
|
SDL_Texture* mySecondaryTexture{nullptr};
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
#include "BilinearBlitter.hxx"
|
#include "BilinearBlitter.hxx"
|
||||||
#include "QisBlitter.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()) {
|
if (!fb.isInitialized()) {
|
||||||
throw runtime_error("BlitterFactory requires an initialized framebuffer!");
|
throw runtime_error("BlitterFactory requires an initialized framebuffer!");
|
||||||
|
|
|
@ -21,8 +21,8 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "Blitter.hxx"
|
#include "Blitter.hxx"
|
||||||
|
#include "FBBackendSDL2.hxx"
|
||||||
#include "bspf.hxx"
|
#include "bspf.hxx"
|
||||||
#include "FrameBufferSDL2.hxx"
|
|
||||||
|
|
||||||
class BlitterFactory {
|
class BlitterFactory {
|
||||||
public:
|
public:
|
||||||
|
@ -35,7 +35,7 @@ class BlitterFactory {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
static unique_ptr<Blitter> createBlitter(FrameBufferSDL2& fb, ScalingAlgorithm scaling);
|
static unique_ptr<Blitter> createBlitter(FBBackendSDL2& fb, ScalingAlgorithm scaling);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // BLITTER_FACTORY_HXX
|
#endif // BLITTER_FACTORY_HXX
|
||||||
|
|
|
@ -15,12 +15,12 @@
|
||||||
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
#include "FrameBufferSDL2.hxx"
|
#include "FBBackendSDL2.hxx"
|
||||||
#include "ThreadDebugging.hxx"
|
#include "ThreadDebugging.hxx"
|
||||||
#include "QisBlitter.hxx"
|
#include "QisBlitter.hxx"
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
QisBlitter::QisBlitter(FrameBufferSDL2& fb)
|
QisBlitter::QisBlitter(FBBackendSDL2& fb)
|
||||||
: myFB(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");
|
if (!fb.isInitialized()) throw runtime_error("framebuffer not initialized");
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
#ifndef QIS_BLITTER_HXX
|
#ifndef QIS_BLITTER_HXX
|
||||||
#define QIS_BLITTER_HXX
|
#define QIS_BLITTER_HXX
|
||||||
|
|
||||||
class FrameBufferSDL2;
|
class FBBackendSDL2;
|
||||||
|
|
||||||
#include "Blitter.hxx"
|
#include "Blitter.hxx"
|
||||||
#include "SDL_lib.hxx"
|
#include "SDL_lib.hxx"
|
||||||
|
@ -27,11 +27,11 @@ class QisBlitter : public Blitter {
|
||||||
|
|
||||||
public:
|
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(
|
virtual void reinitialize(
|
||||||
SDL_Rect srcRect,
|
SDL_Rect srcRect,
|
||||||
|
@ -44,7 +44,7 @@ class QisBlitter : public Blitter {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
FrameBufferSDL2& myFB;
|
FBBackendSDL2& myFB;
|
||||||
|
|
||||||
SDL_Texture* mySrcTexture{nullptr};
|
SDL_Texture* mySrcTexture{nullptr};
|
||||||
SDL_Texture* mySecondarySrcTexture{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))
|
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
|
// RAM can use user-defined labels; otherwise we default to
|
||||||
// standard mnemonics
|
// standard mnemonics
|
||||||
auto iter = myUserLabels.find(addr);
|
AddrToLabel::const_iterator iter;
|
||||||
if(iter != myUserLabels.end())
|
|
||||||
{
|
|
||||||
buf << iter->second;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
uInt16 a = addr & 0xFF, offset = addr & 0xFF00;
|
uInt16 a = addr & 0xFF, offset = addr & 0xFF00;
|
||||||
if((iter = myUserLabels.find(a)) != myUserLabels.end())
|
bool found = false;
|
||||||
|
|
||||||
|
// Search for nearest label
|
||||||
|
for(uInt16 i = a; i >= 0x80; --i)
|
||||||
|
if((iter = myUserLabels.find(i)) != myUserLabels.end())
|
||||||
|
{
|
||||||
buf << iter->second;
|
buf << iter->second;
|
||||||
else
|
if(a != i)
|
||||||
|
buf << "+$" << Base::HEX1 << (a - i);
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(!found)
|
||||||
buf << ourZPMnemonic[a - 0x80];
|
buf << ourZPMnemonic[a - 0x80];
|
||||||
if(offset > 0)
|
if(offset > 0)
|
||||||
buf << "|$" << Base::HEX2 << offset;
|
buf << "|$" << Base::HEX2 << offset;
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -684,12 +688,29 @@ bool CartDebug::getLabel(ostream& buf, uInt16 addr, bool isRead, int places) con
|
||||||
case AddrType::ROM:
|
case AddrType::ROM:
|
||||||
{
|
{
|
||||||
// These addresses can never be in the system labels list
|
// These addresses can never be in the system labels list
|
||||||
|
if(isRam) // cartridge RAM
|
||||||
|
{
|
||||||
|
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);
|
const auto& iter = myUserLabels.find(addr);
|
||||||
if(iter != myUserLabels.end())
|
if(iter != myUserLabels.end())
|
||||||
{
|
{
|
||||||
buf << iter->second;
|
buf << iter->second;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
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;
|
ostringstream buf;
|
||||||
getLabel(buf, addr, isRead, places);
|
getLabel(buf, addr, isRead, places, isRam);
|
||||||
return buf.str();
|
return buf.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -70,7 +70,7 @@ class CartDebug : public DebuggerSystem
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CartDebug(Debugger& dbg, Console& console, const OSystem& osystem);
|
CartDebug(Debugger& dbg, Console& console, const OSystem& osystem);
|
||||||
virtual ~CartDebug() = default;
|
~CartDebug() override = default;
|
||||||
|
|
||||||
const DebuggerState& getState() override;
|
const DebuggerState& getState() override;
|
||||||
const DebuggerState& getOldState() override { return myOldState; }
|
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
|
If places is not -1 and a label hasn't been defined, return a
|
||||||
formatted hexidecimal address
|
formatted hexidecimal address
|
||||||
*/
|
*/
|
||||||
bool getLabel(ostream& buf, uInt16 addr, bool isRead, int places = -1) const;
|
bool getLabel(ostream& buf, uInt16 addr, bool isRead,
|
||||||
string getLabel(uInt16 addr, bool isRead, int places = -1) const;
|
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;
|
int getAddress(const string& label) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -90,21 +90,18 @@ Debugger::~Debugger()
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
void Debugger::initialize()
|
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();
|
const Common::Size& d = myOSystem.frameBuffer().desktopSize();
|
||||||
myWidth = s.w; myHeight = s.h;
|
|
||||||
|
|
||||||
// The debugger dialog is resizable, within certain bounds
|
// The debugger dialog is resizable, within certain bounds
|
||||||
// We check those bounds now
|
// We check those bounds now
|
||||||
myWidth = std::max(myWidth, uInt32(DebuggerDialog::kSmallFontMinW));
|
mySize.clamp(uInt32(DebuggerDialog::kSmallFontMinW), d.w,
|
||||||
myHeight = std::max(myHeight, uInt32(DebuggerDialog::kSmallFontMinH));
|
uInt32(DebuggerDialog::kSmallFontMinH), d.h);
|
||||||
myWidth = std::min(myWidth, uInt32(d.w));
|
|
||||||
myHeight = std::min(myHeight, uInt32(d.h));
|
|
||||||
|
|
||||||
myOSystem.settings().setValue("dbg.res", Common::Size(myWidth, myHeight));
|
myOSystem.settings().setValue("dbg.res", mySize);
|
||||||
|
|
||||||
delete myDialog; myDialog = nullptr;
|
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()));
|
myCartDebug->setDebugWidget(&(myDialog->cartDebug()));
|
||||||
|
|
||||||
|
@ -115,12 +112,14 @@ void Debugger::initialize()
|
||||||
FBInitStatus Debugger::initializeVideo()
|
FBInitStatus Debugger::initializeVideo()
|
||||||
{
|
{
|
||||||
string title = string("Stella ") + STELLA_VERSION + ": Debugger mode";
|
string title = string("Stella ") + STELLA_VERSION + ": Debugger mode";
|
||||||
return myOSystem.frameBuffer().createDisplay(title, FrameBuffer::BufferType::Debugger,
|
return myOSystem.frameBuffer().createDisplay(
|
||||||
myWidth, myHeight);
|
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())
|
if(myOSystem.eventHandler().enterDebugMode())
|
||||||
{
|
{
|
||||||
|
@ -131,6 +130,7 @@ bool Debugger::start(const string& message, int address, bool read)
|
||||||
if(address > -1)
|
if(address > -1)
|
||||||
buf << cartDebug().getLabel(address, read, 4);
|
buf << cartDebug().getLabel(address, read, 4);
|
||||||
myDialog->message().setText(buf.str());
|
myDialog->message().setText(buf.str());
|
||||||
|
myDialog->message().setToolTip(toolTip);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -877,7 +877,7 @@ std::array<Debugger::BuiltinFunction, 18> Debugger::ourBuiltinFunctions = { {
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
// Names are defined here, but processed in YaccParser
|
// 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] = {
|
// Debugger::PseudoRegister Debugger::ourPseudoRegisters[NUM_PSEUDO_REGS] = {
|
||||||
{ "_bank", "Currently selected bank" },
|
{ "_bank", "Currently selected bank" },
|
||||||
{ "_cclocks", "Color clocks on current scanline" },
|
{ "_cclocks", "Color clocks on current scanline" },
|
||||||
|
@ -885,10 +885,14 @@ std::array<Debugger::PseudoRegister, 12> Debugger::ourPseudoRegisters = { {
|
||||||
{ "_cycleslo", "Lower 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" },
|
{ "_fcount", "Number of frames since emulation started" },
|
||||||
{ "_fcycles", "Number of cycles since frame 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" },
|
{ "_icycles", "Number of cycles of last instruction" },
|
||||||
{ "_scan", "Current scanline count" },
|
{ "_scan", "Current scanline count" },
|
||||||
{ "_scanend", "Scanline count at end of last frame" },
|
{ "_scanend", "Scanline count at end of last frame" },
|
||||||
{ "_scycles", "Number of cycles in current scanline" },
|
{ "_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)" },
|
{ "_vblank", "Whether vertical blank is enabled (1 or 0)" },
|
||||||
{ "_vsync", "Whether vertical sync is enabled (1 or 0)" }
|
{ "_vsync", "Whether vertical sync is enabled (1 or 0)" }
|
||||||
// CPU address access functions:
|
// CPU address access functions:
|
||||||
|
@ -897,3 +901,4 @@ std::array<Debugger::PseudoRegister, 12> Debugger::ourPseudoRegisters = { {
|
||||||
{ "__lastbaseread", "last CPU read base address" },
|
{ "__lastbaseread", "last CPU read base address" },
|
||||||
{ "__lastbasewrite", "last CPU write base address" }*/
|
{ "__lastbasewrite", "last CPU write base address" }*/
|
||||||
} };
|
} };
|
||||||
|
//
|
||||||
|
|
|
@ -44,6 +44,7 @@ class RewindManager;
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#include "Base.hxx"
|
#include "Base.hxx"
|
||||||
|
#include "Rect.hxx"
|
||||||
#include "DialogContainer.hxx"
|
#include "DialogContainer.hxx"
|
||||||
#include "DebuggerDialog.hxx"
|
#include "DebuggerDialog.hxx"
|
||||||
#include "FrameBufferConstants.hxx"
|
#include "FrameBufferConstants.hxx"
|
||||||
|
@ -73,7 +74,7 @@ class Debugger : public DialogContainer
|
||||||
Create a new debugger parent object
|
Create a new debugger parent object
|
||||||
*/
|
*/
|
||||||
Debugger(OSystem& osystem, Console& console);
|
Debugger(OSystem& osystem, Console& console);
|
||||||
virtual ~Debugger();
|
~Debugger() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static const Int8 ANY_BANK = -1;
|
static const Int8 ANY_BANK = -1;
|
||||||
|
@ -96,7 +97,8 @@ class Debugger : public DialogContainer
|
||||||
@param message Message to display when entering debugger
|
@param message Message to display when entering debugger
|
||||||
@param address An address associated with the message
|
@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 = "");
|
bool startWithFatalError(const string& message = "");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -352,8 +354,8 @@ class Debugger : public DialogContainer
|
||||||
FunctionDefMap myFunctionDefs;
|
FunctionDefMap myFunctionDefs;
|
||||||
|
|
||||||
// Dimensions of the entire debugger window
|
// Dimensions of the entire debugger window
|
||||||
uInt32 myWidth{DebuggerDialog::kSmallFontMinW};
|
Common::Size mySize{DebuggerDialog::kSmallFontMinW,
|
||||||
uInt32 myHeight{DebuggerDialog::kSmallFontMinH};
|
DebuggerDialog::kSmallFontMinH};
|
||||||
|
|
||||||
// Various builtin functions and operations
|
// Various builtin functions and operations
|
||||||
struct BuiltinFunction {
|
struct BuiltinFunction {
|
||||||
|
@ -363,7 +365,7 @@ class Debugger : public DialogContainer
|
||||||
string name, help;
|
string name, help;
|
||||||
};
|
};
|
||||||
static std::array<BuiltinFunction, 18> ourBuiltinFunctions;
|
static std::array<BuiltinFunction, 18> ourBuiltinFunctions;
|
||||||
static std::array<PseudoRegister, 12> ourPseudoRegisters;
|
static std::array<PseudoRegister, 16> ourPseudoRegisters;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// rewind/unwind n states
|
// rewind/unwind n states
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include "bspf.hxx"
|
#include "bspf.hxx"
|
||||||
#include "CartDebug.hxx"
|
#include "CartDebug.hxx"
|
||||||
#include "CpuDebug.hxx"
|
#include "CpuDebug.hxx"
|
||||||
|
#include "RiotDebug.hxx"
|
||||||
#include "TIADebug.hxx"
|
#include "TIADebug.hxx"
|
||||||
#include "Debugger.hxx"
|
#include "Debugger.hxx"
|
||||||
#include "Expression.hxx"
|
#include "Expression.hxx"
|
||||||
|
@ -310,6 +311,18 @@ class ShiftRightExpression : public Expression
|
||||||
{ return myLHS->evaluate() >> myRHS->evaluate(); }
|
{ 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
|
class TiaMethodExpression : public Expression
|
||||||
{
|
{
|
||||||
|
|
|
@ -1747,9 +1747,13 @@ void DebuggerParser::executeRunTo()
|
||||||
// Create a progress dialog box to show the progress searching through the
|
// Create a progress dialog box to show the progress searching through the
|
||||||
// disassembly, since this may be a time-consuming operation
|
// disassembly, since this may be a time-consuming operation
|
||||||
ostringstream buf;
|
ostringstream buf;
|
||||||
buf << "RunTo searching through " << max_iterations << " disassembled instructions";
|
ProgressDialog progress(debugger.baseDialog(), debugger.lfont());
|
||||||
ProgressDialog progress(debugger.baseDialog(), debugger.lfont(), buf.str());
|
|
||||||
|
buf << "RunTo searching through " << max_iterations << " disassembled instructions"
|
||||||
|
<< progress.ELLIPSIS;
|
||||||
|
progress.setMessage(buf.str());
|
||||||
progress.setRange(0, max_iterations, 5);
|
progress.setRange(0, max_iterations, 5);
|
||||||
|
progress.open();
|
||||||
|
|
||||||
bool done = false;
|
bool done = false;
|
||||||
do {
|
do {
|
||||||
|
@ -1763,8 +1767,8 @@ void DebuggerParser::executeRunTo()
|
||||||
done = (BSPF::findIgnoreCase(next, argStrings[0]) != string::npos);
|
done = (BSPF::findIgnoreCase(next, argStrings[0]) != string::npos);
|
||||||
}
|
}
|
||||||
// Update the progress bar
|
// Update the progress bar
|
||||||
progress.setProgress(count);
|
progress.incProgress();
|
||||||
} while(!done && ++count < max_iterations);
|
} while(!done && ++count < max_iterations && !progress.isCancelled());
|
||||||
|
|
||||||
progress.close();
|
progress.close();
|
||||||
|
|
||||||
|
@ -1789,13 +1793,15 @@ void DebuggerParser::executeRunToPc()
|
||||||
|
|
||||||
uInt32 count = 0;
|
uInt32 count = 0;
|
||||||
bool done = false;
|
bool done = false;
|
||||||
constexpr uInt32 max_iterations = 1000000;
|
|
||||||
// Create a progress dialog box to show the progress searching through the
|
// Create a progress dialog box to show the progress searching through the
|
||||||
// disassembly, since this may be a time-consuming operation
|
// disassembly, since this may be a time-consuming operation
|
||||||
ostringstream buf;
|
ostringstream buf;
|
||||||
buf << "RunTo PC searching through " << max_iterations << " instructions";
|
ProgressDialog progress(debugger.baseDialog(), debugger.lfont());
|
||||||
ProgressDialog progress(debugger.baseDialog(), debugger.lfont(), buf.str());
|
|
||||||
progress.setRange(0, max_iterations, 5);
|
buf << " RunTo PC running" << progress.ELLIPSIS << " ";
|
||||||
|
progress.setMessage(buf.str());
|
||||||
|
progress.setRange(0, 100000, 5);
|
||||||
|
progress.open();
|
||||||
|
|
||||||
do {
|
do {
|
||||||
debugger.step(false);
|
debugger.step(false);
|
||||||
|
@ -1803,8 +1809,9 @@ void DebuggerParser::executeRunToPc()
|
||||||
// Update romlist to point to current PC
|
// Update romlist to point to current PC
|
||||||
int pcline = cartdbg.addressToLine(debugger.cpuDebug().pc());
|
int pcline = cartdbg.addressToLine(debugger.cpuDebug().pc());
|
||||||
done = (pcline >= 0) && (list[pcline].address == args[0]);
|
done = (pcline >= 0) && (list[pcline].address == args[0]);
|
||||||
progress.setProgress(count);
|
progress.incProgress();
|
||||||
} while(!done && ++count < max_iterations/*list.size()*/);
|
++count;
|
||||||
|
} while(!done && !progress.isCancelled());
|
||||||
progress.close();
|
progress.close();
|
||||||
|
|
||||||
if(done)
|
if(done)
|
||||||
|
@ -1953,20 +1960,24 @@ void DebuggerParser::executeStepwhile()
|
||||||
Expression* expr = YaccParser::getResult();
|
Expression* expr = YaccParser::getResult();
|
||||||
int ncycles = 0;
|
int ncycles = 0;
|
||||||
uInt32 count = 0;
|
uInt32 count = 0;
|
||||||
constexpr uInt32 max_iterations = 1000000;
|
|
||||||
|
|
||||||
// Create a progress dialog box to show the progress searching through the
|
// Create a progress dialog box to show the progress searching through the
|
||||||
// disassembly, since this may be a time-consuming operation
|
// disassembly, since this may be a time-consuming operation
|
||||||
ostringstream buf;
|
ostringstream buf;
|
||||||
buf << "stepwhile running through " << max_iterations << " disassembled instructions";
|
ProgressDialog progress(debugger.baseDialog(), debugger.lfont());
|
||||||
ProgressDialog progress(debugger.baseDialog(), debugger.lfont(), buf.str());
|
|
||||||
progress.setRange(0, max_iterations, 5);
|
buf << "stepwhile running through disassembled instructions"
|
||||||
|
<< progress.ELLIPSIS;
|
||||||
|
progress.setMessage(buf.str());
|
||||||
|
progress.setRange(0, 100000, 5);
|
||||||
|
progress.open();
|
||||||
|
|
||||||
do {
|
do {
|
||||||
ncycles += debugger.step(false);
|
ncycles += debugger.step(false);
|
||||||
|
|
||||||
progress.setProgress(count);
|
progress.incProgress();
|
||||||
} while (expr->evaluate() && ++count < max_iterations);
|
++count;
|
||||||
|
} while (expr->evaluate() && !progress.isCancelled());
|
||||||
|
|
||||||
progress.close();
|
progress.close();
|
||||||
commandResult << "executed " << ncycles << " cycles";
|
commandResult << "executed " << ncycles << " cycles";
|
||||||
|
|
|
@ -31,7 +31,7 @@ class DebuggerState
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DebuggerState() = default;
|
DebuggerState() = default;
|
||||||
~DebuggerState() = default;
|
virtual ~DebuggerState() = default;
|
||||||
|
|
||||||
DebuggerState(const DebuggerState&) = default;
|
DebuggerState(const DebuggerState&) = default;
|
||||||
DebuggerState(DebuggerState&&) = delete;
|
DebuggerState(DebuggerState&&) = delete;
|
||||||
|
|
|
@ -68,6 +68,8 @@ const DebuggerState& RiotDebug::getState()
|
||||||
myState.INTIMCLKS = intimClocks();
|
myState.INTIMCLKS = intimClocks();
|
||||||
myState.TIMDIV = timDivider();
|
myState.TIMDIV = timDivider();
|
||||||
|
|
||||||
|
myState.timReadCycles = timReadCycles();
|
||||||
|
|
||||||
return myState;
|
return myState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,10 +77,11 @@ const DebuggerState& RiotDebug::getState()
|
||||||
void RiotDebug::saveOldState()
|
void RiotDebug::saveOldState()
|
||||||
{
|
{
|
||||||
// Port A & B registers
|
// 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.SWCHA_W = mySystem.m6532().myOutA;
|
||||||
myOldState.SWACNT = swacnt();
|
myOldState.SWACNT = swacnt();
|
||||||
myOldState.SWCHB_R = swchb();
|
myOldState.SWCHB_R = myState.SWCHB_R; // swchb();
|
||||||
myOldState.SWCHB_W = mySystem.m6532().myOutB;
|
myOldState.SWCHB_W = mySystem.m6532().myOutB;
|
||||||
myOldState.SWBCNT = swbcnt();
|
myOldState.SWBCNT = swbcnt();
|
||||||
Debugger::set_bits(myOldState.SWCHA_R, myOldState.swchaReadBits);
|
Debugger::set_bits(myOldState.SWCHA_R, myOldState.swchaReadBits);
|
||||||
|
@ -93,8 +96,9 @@ void RiotDebug::saveOldState()
|
||||||
myOldState.INPT1 = inpt(1);
|
myOldState.INPT1 = inpt(1);
|
||||||
myOldState.INPT2 = inpt(2);
|
myOldState.INPT2 = inpt(2);
|
||||||
myOldState.INPT3 = inpt(3);
|
myOldState.INPT3 = inpt(3);
|
||||||
myOldState.INPT4 = inpt(4);
|
// read from myState where other widgets can update pins directly
|
||||||
myOldState.INPT5 = inpt(5);
|
myOldState.INPT4 = myState.INPT4; // inpt(4);
|
||||||
|
myOldState.INPT5 = myState.INPT5; // inpt(5);
|
||||||
|
|
||||||
myOldState.INPTLatch = vblank(6);
|
myOldState.INPTLatch = vblank(6);
|
||||||
myOldState.INPTDump = vblank(7);
|
myOldState.INPTDump = vblank(7);
|
||||||
|
@ -109,6 +113,8 @@ void RiotDebug::saveOldState()
|
||||||
myOldState.TIMCLKS = timClocks();
|
myOldState.TIMCLKS = timClocks();
|
||||||
myOldState.INTIMCLKS = intimClocks();
|
myOldState.INTIMCLKS = intimClocks();
|
||||||
myOldState.TIMDIV = timDivider();
|
myOldState.TIMDIV = timDivider();
|
||||||
|
|
||||||
|
myOldState.timReadCycles = timReadCycles();
|
||||||
}
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
@ -233,6 +239,24 @@ Int32 RiotDebug::timDivider() const
|
||||||
return mySystem.m6532().myDivider;
|
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)
|
bool RiotDebug::diffP0(int newVal)
|
||||||
{
|
{
|
||||||
|
|
|
@ -22,6 +22,10 @@ class M6532;
|
||||||
class Debugger;
|
class Debugger;
|
||||||
class RiotDebug;
|
class RiotDebug;
|
||||||
|
|
||||||
|
// Function type for RiotDebug instance methods
|
||||||
|
class RiotDebug;
|
||||||
|
using RiotMethod = int (RiotDebug::*)() const;
|
||||||
|
|
||||||
#include "DebuggerSystem.hxx"
|
#include "DebuggerSystem.hxx"
|
||||||
|
|
||||||
class RiotState : public DebuggerState
|
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};
|
uInt8 TIM1T{0}, TIM8T{0}, TIM64T{0}, T1024T{0}, INTIM{0}, TIMINT{0};
|
||||||
Int32 TIMCLKS{0}, INTIMCLKS{0}, TIMDIV{0};
|
Int32 TIMCLKS{0}, INTIMCLKS{0}, TIMDIV{0};
|
||||||
|
uInt16 timReadCycles;
|
||||||
|
|
||||||
// These are actually from the TIA, but are I/O related
|
// These are actually from the TIA, but are I/O related
|
||||||
uInt8 INPT0{0}, INPT1{0}, INPT2{0}, INPT3{0}, INPT4{0}, INPT5{0};
|
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 timClocks() const;
|
||||||
Int32 intimClocks() const;
|
Int32 intimClocks() const;
|
||||||
Int32 timDivider() const;
|
Int32 timDivider() const;
|
||||||
|
/* Debugger pseudo-registers for timer accesses */
|
||||||
|
int timWrappedOnRead() const;
|
||||||
|
int timWrappedOnWrite() const;
|
||||||
|
|
||||||
|
int timReadCycles() const;
|
||||||
|
|
||||||
/* Console switches */
|
/* Console switches */
|
||||||
bool diffP0(int newVal = -1);
|
bool diffP0(int newVal = -1);
|
||||||
|
|
|
@ -149,6 +149,7 @@ const DebuggerState& TIADebug::getState()
|
||||||
myState.info.push_back(scanlines());
|
myState.info.push_back(scanlines());
|
||||||
myState.info.push_back(scanlinesLastFrame());
|
myState.info.push_back(scanlinesLastFrame());
|
||||||
myState.info.push_back(clocksThisLine());
|
myState.info.push_back(clocksThisLine());
|
||||||
|
myState.info.push_back(frameWsyncCycles());
|
||||||
|
|
||||||
return myState;
|
return myState;
|
||||||
}
|
}
|
||||||
|
@ -258,6 +259,7 @@ void TIADebug::saveOldState()
|
||||||
myOldState.info.push_back(scanlines());
|
myOldState.info.push_back(scanlines());
|
||||||
myOldState.info.push_back(scanlinesLastFrame());
|
myOldState.info.push_back(scanlinesLastFrame());
|
||||||
myOldState.info.push_back(clocksThisLine());
|
myOldState.info.push_back(clocksThisLine());
|
||||||
|
myOldState.info.push_back(frameWsyncCycles());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* the set methods now use mySystem.poke(). This will save us the
|
/* the set methods now use mySystem.poke(). This will save us the
|
||||||
|
@ -909,6 +911,12 @@ int TIADebug::frameCycles() const
|
||||||
return myTIA.frameCycles();
|
return myTIA.frameCycles();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
int TIADebug::frameWsyncCycles() const
|
||||||
|
{
|
||||||
|
return myTIA.frameWSyncCycles();
|
||||||
|
}
|
||||||
|
|
||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
int TIADebug::cyclesLo() const
|
int TIADebug::cyclesLo() const
|
||||||
{
|
{
|
||||||
|
|