Merge branch 'master' into feature/precise-audio

This commit is contained in:
Christian Speckner 2018-01-15 23:53:35 +01:00
commit 317f7391c2
619 changed files with 7574 additions and 4456 deletions

View File

@ -39,6 +39,7 @@
"memory": "cpp",
"ratio": "cpp",
"tuple": "cpp",
"type_traits": "cpp"
"type_traits": "cpp",
"stdexcept": "cpp"
}
}

View File

@ -1,21 +1,31 @@
===========================================================================
5.0.2 to 5.1: (January xx, 2018)
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
* Thumbulator support is not conditional any more.
===========================================================================
Release History
===========================================================================
* Don't trap write accesses to the datastream pointers in CDF and BUS.
This fixes -dev.thumb.trapfatal 1.
5.0.2 to 5.0.3: (August xx, 2017)
* Complete rework of TV mode and ystart autodetection. The new
implementation is more robust and reduces startup time.
* Huge improvements to the disassembly view in the debugger:
- TODO: add items ...
* Add two "grace lines" of black to the top of the frame when
autodetecting ystart.
* Support UNIX style builds (configure / make) on OSX with both
XCode / clang and g++.
* Huge improvements to the disassembly view in the debugger and
disassembly files created:
- reformatting in debugger for better space utilization
- much improved code and data detection
- access tracking and indicators for TIA/IO/RAM adresses in disassembly
- break vector is tracked (if used)
- improved cycle count (page penalties, sums created in disassembly)
- improved handling of instruction masking opcodes (e.g. BIT)
* Added "Time Machine" mode, which automatically creates save states
in user-defined intervals. The user can navigate back and forth within
these states inside the emulator and the debugger.
* Fixed Genesis controller autodetect (Stay Frosty 2, Scramble, etc).
@ -38,6 +48,9 @@
information). In the case of 'saveses', the filename is now named
based on the date and time of when the command was entered.
* Fixed change tracking bug during rewind; changes were accumulated
instead of being displayed only for the last rewind step.
* Fixed bug with saving snapshots in 1x mode; there was graphical
corruption in some cases. Such snapshots also now include any TV
effects / phosphor blending currently in use.
@ -50,24 +63,66 @@
CompuMate ROM; this controller type can no longer be manually
selected, and will be used automatically used for CompuMate ROMs.
* Fixed cheat codes, so 7 digits codes are now accepted as described in
the doc.
* Fixed swapped ports being displayed wrong in System Logs and debugger.
* Added options to erase the AtariVox/Savekey flash memory, either for
all ROMs or only the current one.
* Moved various developer related settings in new Developer Settings
dialog. These settings now come in two groups (player/developer) and
allow switching all settings at once.
* Added new interface palette 'Light'
* Improved tab auto-complete in debugger
* Added conditional traps and savestate creation to debugger
* Extended 'rewind' to take a second parameter which allows rewinding
multiple states.
* Added 'unwind' command, which undoes the latest rewind(s)
* Added '<' (unwind) button to debugger.
* Added 'Options...' button to debugger which gives access to the options
menu during debugging.
* Added debugger pseudo-register '_cyclesLo' and '_cyclesHi', which give
the number of CPU cycles that have occurred since emulation started.
* Added debugger pseudo-register '_fcycles', which gives the number of
CPU cycles that have occurred since the frame started.
* Added debugger pseudo-register '_icycles', which gives the number of
CPU cycles of the last instruction.
* Extended debugger 'dump' command to take a second argument, indicating
the end of the range to dump data.
* Improved change tracking; more values are tracked and change tracking
now works in case of a break too.
* Added widgets for trackball and SaveKey/AtariVox controllers
* Improved emulation of 'FE' bankswitch scheme (no user-visible changes,
but internally the emulation is much more accurate compared to the
real thing). Related to this, improved the debugger support for this
scheme (you can now switch banks in the debugger view).
* Added emulation of 7800 initial RAM values and Pause key.
* Added ROM properties for 'Scramble' ROMs, and updated info for all
"Champ Games" ROMs.
* Added ROM properties for 'Zippy the Porcupine' ROMs, and updated
info for all "Chris Spry (Sprybug)" ROMs.
* Fix error when building with uClibc-ng for ARM (thanks to Sergio Prado).
* Fixed error when building with uClibc-ng for ARM (thanks to Sergio
Prado).
* Updated included PNG library to latest stable version.

View File

@ -12,7 +12,7 @@
License Information and Copyright Notice
===========================================================================
Copyright (C) 1995-2017 by Bradford W. Mott, Stephen Anthony and the
Copyright (C) 1995-2018 by Bradford W. Mott, Stephen Anthony and the
Stella Team
This program is free software; you can redistribute it and/or modify it

104
config.guess vendored
View File

@ -2,7 +2,7 @@
# Attempt to guess a canonical system name.
# Copyright 1992-2017 Free Software Foundation, Inc.
timestamp='2017-03-05'
timestamp='2017-12-17'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
@ -15,7 +15,7 @@ timestamp='2017-03-05'
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, see <http://www.gnu.org/licenses/>.
# along with this program; if not, see <https://www.gnu.org/licenses/>.
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
@ -27,7 +27,7 @@ timestamp='2017-03-05'
# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
#
# You can get the latest version of this script from:
# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
#
# Please send patches to <config-patches@gnu.org>.
@ -39,7 +39,7 @@ Usage: $0 [OPTION]
Output the configuration name of the system \`$me' is run on.
Operation modes:
Options:
-h, --help print this help, then exit
-t, --time-stamp print date of last modification, then exit
-v, --version print version number, then exit
@ -244,6 +244,9 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'`
echo ${UNAME_MACHINE_ARCH}-unknown-libertybsd${UNAME_RELEASE}
exit ;;
*:MidnightBSD:*:*)
echo ${UNAME_MACHINE}-unknown-midnightbsd${UNAME_RELEASE}
exit ;;
*:ekkoBSD:*:*)
echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
exit ;;
@ -259,6 +262,12 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
*:Sortix:*:*)
echo ${UNAME_MACHINE}-unknown-sortix
exit ;;
*:Redox:*:*)
echo ${UNAME_MACHINE}-unknown-redox
exit ;;
mips:OSF1:*.*)
echo mips-dec-osf1
exit ;;
alpha:OSF1:*:*)
case $UNAME_RELEASE in
*4.0)
@ -315,15 +324,6 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
exitcode=$?
trap '' 0
exit $exitcode ;;
Alpha\ *:Windows_NT*:*)
# How do we know it's Interix rather than the generic POSIX subsystem?
# Should we change UNAME_MACHINE based on the output of uname instead
# of the specific Alpha model?
echo alpha-pc-interix
exit ;;
21064:Windows_NT:50:3)
echo alpha-dec-winnt3.5
exit ;;
Amiga*:UNIX_System_V:4.0:*)
echo m68k-unknown-sysv4
exit ;;
@ -485,13 +485,13 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
#endif
#if defined (host_mips) && defined (MIPSEB)
#if defined (SYSTYPE_SYSV)
printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0);
#endif
#if defined (SYSTYPE_SVR4)
printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0);
#endif
#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0);
#endif
#endif
exit (-1);
@ -614,7 +614,7 @@ EOF
*:AIX:*:*)
echo rs6000-ibm-aix
exit ;;
ibmrt:4.4BSD:*|romp-ibm:BSD:*)
ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*)
echo romp-ibm-bsd4.4
exit ;;
ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
@ -635,8 +635,8 @@ EOF
9000/[34678]??:HP-UX:*:*)
HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
case "${UNAME_MACHINE}" in
9000/31? ) HP_ARCH=m68000 ;;
9000/[34]?? ) HP_ARCH=m68k ;;
9000/31?) HP_ARCH=m68000 ;;
9000/[34]??) HP_ARCH=m68k ;;
9000/[678][0-9][0-9])
if [ -x /usr/bin/getconf ]; then
sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
@ -749,7 +749,7 @@ EOF
{ echo "$SYSTEM_NAME"; exit; }
echo unknown-hitachi-hiuxwe2
exit ;;
9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*)
echo hppa1.1-hp-bsd
exit ;;
9000/8??:4.3bsd:*:*)
@ -758,7 +758,7 @@ EOF
*9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
echo hppa1.0-hp-mpeix
exit ;;
hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*)
echo hppa1.1-hp-osf
exit ;;
hp8??:OSF1:*:*)
@ -855,10 +855,6 @@ EOF
*:MSYS*:*)
echo ${UNAME_MACHINE}-pc-msys
exit ;;
i*:windows32*:*)
# uname -m includes "-pc" on this system.
echo ${UNAME_MACHINE}-mingw32
exit ;;
i*:PW*:*)
echo ${UNAME_MACHINE}-pc-pw32
exit ;;
@ -874,27 +870,12 @@ EOF
echo ia64-unknown-interix${UNAME_RELEASE}
exit ;;
esac ;;
[345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
echo i${UNAME_MACHINE}-pc-mks
exit ;;
8664:Windows_NT:*)
echo x86_64-pc-mks
exit ;;
i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
# How do we know it's Interix rather than the generic POSIX subsystem?
# It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
# UNAME_MACHINE based on the output of uname instead of i386?
echo i586-pc-interix
exit ;;
i*:UWIN*:*)
echo ${UNAME_MACHINE}-pc-uwin
exit ;;
amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
echo x86_64-unknown-cygwin
exit ;;
p*:CYGWIN*:*)
echo powerpcle-unknown-cygwin
exit ;;
prep*:SunOS:5.*:*)
echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit ;;
@ -1097,7 +1078,7 @@ EOF
i*86:*DOS:*:*)
echo ${UNAME_MACHINE}-pc-msdosdjgpp
exit ;;
i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
i*86:*:4.*:*)
UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
@ -1304,14 +1285,21 @@ EOF
if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then
if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
(CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
grep IS_64BIT_ARCH >/dev/null
(CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
grep IS_64BIT_ARCH >/dev/null
then
case $UNAME_PROCESSOR in
i386) UNAME_PROCESSOR=x86_64 ;;
powerpc) UNAME_PROCESSOR=powerpc64 ;;
esac
fi
# On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc
if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \
(CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
grep IS_PPC >/dev/null
then
UNAME_PROCESSOR=powerpc
fi
fi
elif test "$UNAME_PROCESSOR" = i386 ; then
# Avoid executing cc on OS X 10.9, as it ships with a stub
@ -1335,16 +1323,16 @@ EOF
*:QNX:*:4*)
echo i386-pc-qnx
exit ;;
NEO-?:NONSTOP_KERNEL:*:*)
NEO-*:NONSTOP_KERNEL:*:*)
echo neo-tandem-nsk${UNAME_RELEASE}
exit ;;
NSE-*:NONSTOP_KERNEL:*:*)
echo nse-tandem-nsk${UNAME_RELEASE}
exit ;;
NSR-?:NONSTOP_KERNEL:*:*)
NSR-*:NONSTOP_KERNEL:*:*)
echo nsr-tandem-nsk${UNAME_RELEASE}
exit ;;
NSX-?:NONSTOP_KERNEL:*:*)
NSX-*:NONSTOP_KERNEL:*:*)
echo nsx-tandem-nsk${UNAME_RELEASE}
exit ;;
*:NonStop-UX:*:*)
@ -1418,16 +1406,28 @@ EOF
exit ;;
esac
echo "$0: unable to guess system type" >&2
case "${UNAME_MACHINE}:${UNAME_SYSTEM}" in
mips:Linux | mips64:Linux)
# If we got here on MIPS GNU/Linux, output extra information.
cat >&2 <<EOF
NOTE: MIPS GNU/Linux systems require a C compiler to fully recognize
the system type. Please install a C compiler and try again.
EOF
;;
esac
cat >&2 <<EOF
$0: unable to guess system type
This script (version $timestamp), has failed to recognize the
operating system you are using. If your script is old, overwrite
config.guess and config.sub with the latest versions from:
operating system you are using. If your script is old, overwrite *all*
copies of config.guess and config.sub with the latest versions from:
http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
and
http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
If $0 has already been updated, send the following data and any
information you think might be pertinent to config-patches@gnu.org to
@ -1459,7 +1459,7 @@ EOF
exit 1
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# eval: (add-hook 'write-file-functions 'time-stamp)
# time-stamp-start: "timestamp='"
# time-stamp-format: "%:y-%02m-%02d"
# time-stamp-end: "'"

46
config.sub vendored Normal file → Executable file
View File

@ -2,7 +2,7 @@
# Configuration validation subroutine script.
# Copyright 1992-2017 Free Software Foundation, Inc.
timestamp='2017-04-02'
timestamp='2017-11-23'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
@ -15,7 +15,7 @@ timestamp='2017-04-02'
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, see <http://www.gnu.org/licenses/>.
# along with this program; if not, see <https://www.gnu.org/licenses/>.
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
@ -33,7 +33,7 @@ timestamp='2017-04-02'
# Otherwise, we print the canonical config type on stdout and succeed.
# You can get the latest version of this script from:
# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
# This file is supposed to be the same for all GNU packages
# and recognize all the CPU types, system types and aliases
@ -57,7 +57,7 @@ Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS
Canonicalize a configuration name.
Operation modes:
Options:
-h, --help print this help, then exit
-t, --time-stamp print date of last modification, then exit
-v, --version print version number, then exit
@ -229,9 +229,6 @@ case $os in
-ptx*)
basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
;;
-windowsnt*)
os=`echo $os | sed -e 's/windowsnt/winnt/'`
;;
-psos*)
os=-psos
;;
@ -316,7 +313,6 @@ case $basic_machine in
| v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
| visium \
| wasm32 \
| we32k \
| x86 | xc16x | xstormy16 | xtensa \
| z8k | z80)
basic_machine=$basic_machine-unknown
@ -643,7 +639,7 @@ case $basic_machine in
basic_machine=rs6000-bull
os=-bosx
;;
dpx2* | dpx2*-bull)
dpx2*)
basic_machine=m68k-bull
os=-sysv3
;;
@ -905,7 +901,7 @@ case $basic_machine in
basic_machine=v70-nec
os=-sysv
;;
next | m*-next )
next | m*-next)
basic_machine=m68k-next
case $os in
-nextstep* )
@ -1259,6 +1255,9 @@ case $basic_machine in
basic_machine=hppa1.1-winbond
os=-proelf
;;
x64)
basic_machine=x86_64-pc
;;
xbox)
basic_machine=i686-pc
os=-mingw32
@ -1366,8 +1365,8 @@ esac
if [ x"$os" != x"" ]
then
case $os in
# First match some system type aliases
# that might get confused with valid system types.
# First match some system type aliases that might get confused
# with valid system types.
# -solaris* is a basic system type, with this one exception.
-auroraux)
os=-auroraux
@ -1387,9 +1386,9 @@ case $os in
-gnu/linux*)
os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
;;
# First accept the basic system types.
# Now accept the basic system types.
# The portable systems comes first.
# Each alternative MUST END IN A *, to match a version number.
# Each alternative MUST end in a * to match a version number.
# -sysv* is not here because it comes later, after sysvr4.
-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
| -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
@ -1492,7 +1491,7 @@ case $os in
-nova*)
os=-rtmk-nova
;;
-ns2 )
-ns2)
os=-nextstep2
;;
-nsk*)
@ -1547,6 +1546,19 @@ case $os in
-dicos*)
os=-dicos
;;
-pikeos*)
# Until real need of OS specific support for
# particular features comes up, bare metal
# configurations are quite functional.
case $basic_machine in
arm*)
os=-eabi
;;
*)
os=-elf
;;
esac
;;
-nacl*)
;;
-ios)
@ -1694,7 +1706,7 @@ case $basic_machine in
m88k-omron*)
os=-luna
;;
*-next )
*-next)
os=-nextstep
;;
*-sequent)
@ -1829,7 +1841,7 @@ echo $basic_machine$os
exit
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# eval: (add-hook 'write-file-functions 'time-stamp)
# time-stamp-start: "timestamp='"
# time-stamp-format: "%:y-%02m-%02d"
# time-stamp-end: "'"

17
configure vendored
View File

@ -22,7 +22,6 @@ _build_sound=yes
_build_debugger=yes
_build_joystick=yes
_build_cheats=yes
_build_thumb=yes
_build_static=no
_build_profile=no
@ -198,8 +197,6 @@ Optional Features:
--disable-joystick
--enable-cheats enable/disable cheatcode support [enabled]
--disable-cheats
--enable-thumb enable/disable Thumb ARM support [enabled]
--disable-thumb
--enable-windowed enable/disable windowed rendering modes [enabled]
--disable-windowed
--enable-shared build shared binary [enabled]
@ -239,8 +236,6 @@ for ac_option in $@; do
--disable-cheats) _build_cheats=no ;;
--enable-windowed) _build_windowed=yes ;;
--disable-windowed) _build_windowed=no ;;
--enable-thumb) _build_thumb=yes ;;
--disable-thumb) _build_thumb=no ;;
--enable-shared) _build_static=no ;;
--enable-static) _build_static=yes ;;
--disable-static) _build_static=no ;;
@ -660,14 +655,6 @@ else
echo
fi
if test "$_build_thumb" = yes ; then
echo_n " Thumb ARM emulation support enabled"
echo
else
echo_n " Thumb ARM emulation support disabled"
echo
fi
if test "$_build_static" = yes ; then
echo_n " Static binary enabled"
echo
@ -779,10 +766,6 @@ if test "$_build_cheats" = yes ; then
INCLUDES="$INCLUDES -I$CHEAT"
fi
if test "$_build_thumb" = yes ; then
DEFINES="$DEFINES -DTHUMB_SUPPORT"
fi
if test "$_build_profile" = no ; then
_build_profile=
fi

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 407 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.8 KiB

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.8 KiB

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 70 KiB

File diff suppressed because it is too large Load Diff

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
@ -68,6 +68,10 @@ string Base::toString(int value, Common::Base::Format outputBase)
std::snprintf(vToS_buf, 6, "%5d", value);
break;
case Base::F_10_2: // base 10: 2 digits
std::snprintf(vToS_buf, 3, "%02d", value);
break;
case Base::F_16_1: // base 16: 1 byte wide
std::snprintf(vToS_buf, 2, myFmt[0], value);
break;

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
@ -47,6 +47,7 @@ class Base
F_16_4, // base 16: 4 bytes wide
F_16_8, // base 16: 8 bytes wide
F_10, // base 10: 3 or 5 bytes (depending on value)
F_10_2, // base 10: 2 digits
F_2, // base 2: 8 or 16 bits (depending on value)
F_2_8, // base 2: 1 byte (8 bits) wide
F_2_16, // base 2: 2 bytes (16 bits) wide

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
@ -60,22 +60,21 @@ void EventHandlerSDL2::pollEvent()
case SDL_MOUSEMOTION:
{
handleMouseMotionEvent(myEvent.motion.x, myEvent.motion.y,
myEvent.motion.xrel, myEvent.motion.yrel, 0);
myEvent.motion.xrel, myEvent.motion.yrel);
break;
}
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
{
bool pressed = myEvent.button.type == SDL_MOUSEBUTTONDOWN;
switch(myEvent.button.button)
{
case SDL_BUTTON_LEFT:
handleMouseButtonEvent(pressed ? EVENT_LBUTTONDOWN : EVENT_LBUTTONUP,
handleMouseButtonEvent(MouseButton::LEFT, myEvent.button.type == SDL_MOUSEBUTTONDOWN,
myEvent.button.x, myEvent.button.y);
break;
case SDL_BUTTON_RIGHT:
handleMouseButtonEvent(pressed ? EVENT_RBUTTONDOWN : EVENT_RBUTTONUP,
handleMouseButtonEvent(MouseButton::RIGHT, myEvent.button.type == SDL_MOUSEBUTTONDOWN,
myEvent.button.x, myEvent.button.y);
break;
}
@ -87,9 +86,9 @@ void EventHandlerSDL2::pollEvent()
int x, y;
SDL_GetMouseState(&x, &y); // we need mouse position too
if(myEvent.wheel.y < 0)
handleMouseButtonEvent(EVENT_WHEELDOWN, x, y);
handleMouseButtonEvent(MouseButton::WHEELDOWN, true, x, y);
else if(myEvent.wheel.y > 0)
handleMouseButtonEvent(EVENT_WHEELUP, x, y);
handleMouseButtonEvent(MouseButton::WHEELUP, true, x, y);
break;
}
@ -112,11 +111,15 @@ void EventHandlerSDL2::pollEvent()
case SDL_JOYHATMOTION:
{
int v = myEvent.jhat.value, value = 0;
if(v & SDL_HAT_UP) value |= EVENT_HATUP_M;
if(v & SDL_HAT_DOWN) value |= EVENT_HATDOWN_M;
if(v & SDL_HAT_LEFT) value |= EVENT_HATLEFT_M;
if(v & SDL_HAT_RIGHT) value |= EVENT_HATRIGHT_M;
if(v == SDL_HAT_CENTERED) value = EVENT_HATCENTER_M;
if(v & SDL_HAT_CENTERED)
value = EVENT_HATCENTER_M;
else
{
if(v & SDL_HAT_UP) value |= EVENT_HATUP_M;
if(v & SDL_HAT_DOWN) value |= EVENT_HATDOWN_M;
if(v & SDL_HAT_LEFT) value |= EVENT_HATLEFT_M;
if(v & SDL_HAT_RIGHT) value |= EVENT_HATRIGHT_M;
}
handleJoyHatEvent(myEvent.jhat.which, myEvent.jhat.hat, value);
break; // SDL_JOYHATMOTION
@ -144,42 +147,42 @@ void EventHandlerSDL2::pollEvent()
switch(myEvent.window.event)
{
case SDL_WINDOWEVENT_SHOWN:
handleSystemEvent(EVENT_WINDOW_SHOWN);
handleSystemEvent(SystemEvent::WINDOW_SHOWN);
break;
case SDL_WINDOWEVENT_HIDDEN:
handleSystemEvent(EVENT_WINDOW_HIDDEN);
handleSystemEvent(SystemEvent::WINDOW_HIDDEN);
break;
case SDL_WINDOWEVENT_EXPOSED:
handleSystemEvent(EVENT_WINDOW_EXPOSED);
handleSystemEvent(SystemEvent::WINDOW_EXPOSED);
break;
case SDL_WINDOWEVENT_MOVED:
handleSystemEvent(EVENT_WINDOW_MOVED,
handleSystemEvent(SystemEvent::WINDOW_MOVED,
myEvent.window.data1, myEvent.window.data1);
break;
case SDL_WINDOWEVENT_RESIZED:
handleSystemEvent(EVENT_WINDOW_RESIZED,
handleSystemEvent(SystemEvent::WINDOW_RESIZED,
myEvent.window.data1, myEvent.window.data1);
break;
case SDL_WINDOWEVENT_MINIMIZED:
handleSystemEvent(EVENT_WINDOW_MINIMIZED);
handleSystemEvent(SystemEvent::WINDOW_MINIMIZED);
break;
case SDL_WINDOWEVENT_MAXIMIZED:
handleSystemEvent(EVENT_WINDOW_MAXIMIZED);
handleSystemEvent(SystemEvent::WINDOW_MAXIMIZED);
break;
case SDL_WINDOWEVENT_RESTORED:
handleSystemEvent(EVENT_WINDOW_RESTORED);
handleSystemEvent(SystemEvent::WINDOW_RESTORED);
break;
case SDL_WINDOWEVENT_ENTER:
handleSystemEvent(EVENT_WINDOW_ENTER);
handleSystemEvent(SystemEvent::WINDOW_ENTER);
break;
case SDL_WINDOWEVENT_LEAVE:
handleSystemEvent(EVENT_WINDOW_LEAVE);
handleSystemEvent(SystemEvent::WINDOW_LEAVE);
break;
case SDL_WINDOWEVENT_FOCUS_GAINED:
handleSystemEvent(EVENT_WINDOW_FOCUS_GAINED);
handleSystemEvent(SystemEvent::WINDOW_FOCUS_GAINED);
break;
case SDL_WINDOWEVENT_FOCUS_LOST:
handleSystemEvent(EVENT_WINDOW_FOCUS_LOST);
handleSystemEvent(SystemEvent::WINDOW_FOCUS_LOST);
break;
}
break; // SDL_WINDOWEVENT

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
@ -122,8 +122,8 @@ void FBSurfaceSDL2::setVisible(bool visible)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void FBSurfaceSDL2::translateCoords(Int32& x, Int32& y) const
{
x -= myDstR.x;
y -= myDstR.y;
x -= myDstR.x; x /= myDstR.w / mySrcR.w;
y -= myDstR.y; y /= myDstR.h / mySrcR.h;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -210,9 +210,10 @@ void FBSurfaceSDL2::createSurface(uInt32 width, uInt32 height,
// We start out with the src and dst rectangles containing the same
// dimensions, indicating no scaling or re-positioning
mySrcR.x = mySrcR.y = myDstR.x = myDstR.y = 0;
mySrcR.w = myDstR.w = width;
mySrcR.h = myDstR.h = height;
setSrcPos(0, 0);
setDstPos(0, 0);
setSrcSize(width, height);
setDstSize(width, height);
////////////////////////////////////////////////////
// These *must* be set for the parent class

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
@ -84,15 +84,42 @@ void FrameBufferSDL2::queryHardware(vector<GUI::Size>& displays,
displays.emplace_back(display.w, display.h);
}
// For now, supported render types are hardcoded; eventually, SDL may
// provide a method to query this
#if defined(BSPF_WINDOWS)
VarList::push_back(renderers, "Direct3D", "direct3d");
#endif
VarList::push_back(renderers, "OpenGL", "opengl");
VarList::push_back(renderers, "OpenGLES2", "opengles2");
VarList::push_back(renderers, "OpenGLES", "opengles");
VarList::push_back(renderers, "Software", "software");
struct RenderName
{
string sdlName;
string stellaName;
};
// Create name map for all currently known SDL renderers
const int NUM_RENDERERS = 5;
static const RenderName RENDERER_NAMES[NUM_RENDERERS] = {
{ "direct3d", "Direct3D" },
{ "opengl", "OpenGL" },
{ "opengles", "OpenGLES" },
{ "opengles2", "OpenGLES2" },
{ "software", "Software" }
};
int numDrivers = SDL_GetNumRenderDrivers();
for(int i = 0; i < numDrivers; ++i)
{
SDL_RendererInfo info;
if(SDL_GetRenderDriverInfo(i, &info) == 0)
{
// Map SDL names into nicer Stella names (if available)
bool found = false;
for(int j = 0; j < NUM_RENDERERS; ++j)
{
if(RENDERER_NAMES[j].sdlName == info.name)
{
VarList::push_back(renderers, RENDERER_NAMES[j].stellaName, info.name);
found = true;
break;
}
}
if(!found)
VarList::push_back(renderers, info.name, info.name);
}
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -208,6 +235,14 @@ bool FrameBufferSDL2::setVideoMode(const string& title, const VideoMode& mode)
return true;
}
void FrameBufferSDL2::setTitle(const string& title)
{
myScreenTitle = title;
if(myWindow)
SDL_SetWindowTitle(myWindow, title.c_str());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string FrameBufferSDL2::about() const
{

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
@ -46,11 +46,13 @@ class FrameBufferSDL2 : public FrameBuffer
//////////////////////////////////////////////////////////////////////
// The following are derived from public methods in FrameBuffer.hxx
//////////////////////////////////////////////////////////////////////
/**
Toggles the use of grabmouse (only has effect in emulation mode).
The method changes the 'grabmouse' setting and saves it.
Updates window title
@param title The title of the application / window
*/
void toggleGrabMouse();
void setTitle(const string& title);
/**
Shows or hides the cursor based on the given boolean value.

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
@ -42,7 +42,8 @@
In the case of methods which wrap the C++ 'splice()' method, the
semantics of splice are followed wrt invalid/out-of-range/etc
iterators. See the applicable documentation for such behaviour.
iterators. See the applicable C++ STL documentation for such
behaviour.
@author Stephen Anthony
*/
@ -58,9 +59,8 @@ class LinkedObjectPool
/*
Create a pool of size CAPACITY; the active list starts out empty.
*/
LinkedObjectPool<T, CAPACITY>() : myCurrent(myList.end()) {
for(uInt32 i = 0; i < CAPACITY; ++i)
myPool.emplace_back(T());
LinkedObjectPool<T, CAPACITY>() : myCurrent(myList.end()), myCapacity(0) {
resize(CAPACITY);
}
/**
@ -70,13 +70,26 @@ class LinkedObjectPool
Make sure to call 'currentIsValid()' before accessing this method.
*/
T& current() { return *myCurrent; }
T& current() const { return *myCurrent; }
/**
Returns current's position in the list
SLOW, but only required for messages
*/
uInt32 currentIdx() const {
iter it = myCurrent;
uInt32 idx = 1;
while(it-- != myList.begin()) idx++;
return idx;
}
/**
Does the 'current' iterator point to a valid node in the active list?
This must be called before 'current()' is called.
*/
bool currentIsValid() { return myCurrent != myList.end(); }
bool currentIsValid() const { return myCurrent != myList.end(); }
/**
Advance 'current' iterator to previous position in the active list.
@ -96,17 +109,31 @@ class LinkedObjectPool
myCurrent = std::next(myCurrent, 1);
}
#if 0
/**
Return a reference to the element at the first node in the active list.
Return an iterator to the first node in the active list.
*/
T& first() { return myList.front(); }
const_iter first() const { return myList.begin(); }
/**
Return a reference to the element at the last node in the active list.
Return an iterator to the last node in the active list.
*/
T& last() { return myList.back(); }
#endif
const_iter last() const { return std::prev(myList.end(), 1); }
/**
Return an iterator to the previous node of 'i' in the active list.
*/
const_iter previous(const_iter i) const { return std::prev(i, 1); }
/**
Return an iterator to the next node to 'current' in the active list.
*/
const_iter next(const_iter i) const { return std::next(i, 1); }
/**
Answer whether 'current' is at the specified iterator.
*/
bool atFirst() const { return myCurrent == first(); }
bool atLast() const { return myCurrent == last(); }
/**
Add a new node at the beginning of the active list, and update 'current'
@ -131,7 +158,7 @@ class LinkedObjectPool
happens to be the one removed.
*/
void removeFirst() {
const_iter i = myList.begin();
const_iter i = myList.cbegin();
myPool.splice(myPool.end(), myList, i);
if(myCurrent == i) // did we just invalidate 'current'
moveToNext(); // if so, move to the next node
@ -148,25 +175,21 @@ class LinkedObjectPool
moveToPrevious(); // if so, move to the previous node
}
#if 0
/**
Convenience method to remove a single element from the active list at
position of the iterator +- the offset.
Remove a single element from the active list at position of the iterator.
*/
void remove(const_iter i, Int32 offset = 0) {
myPool.splice(myPool.end(), myList,
offset >= 0 ? std::next(i, offset) : std::prev(i, -offset));
void remove(const_iter i) {
myPool.splice(myPool.end(), myList, i);
}
/**
Convenience method to remove a single element from the active list by
index, offset from the beginning of the list. (ie, '0' means first
element, '1' is second, and so on).
Remove a single element from the active list by index, offset from
the beginning of the list. (ie, '0' means first element, '1' is second,
and so on).
*/
void remove(uInt32 index) {
myPool.splice(myPool.end(), myList, std::next(myList.begin(), index));
}
#endif
/**
Remove range of elements from the beginning of the active list to
@ -184,6 +207,22 @@ class LinkedObjectPool
myPool.splice(myPool.end(), myList, std::next(myCurrent, 1), myList.end());
}
/**
Resize the pool to specified size, invalidating the list in the process
(ie, the list essentially becomes empty again).
*/
void resize(uInt32 capacity) {
if(myCapacity != capacity) // only resize when necessary
{
myList.clear(); myPool.clear();
myCurrent = myList.end();
myCapacity = capacity;
for(uInt32 i = 0; i < myCapacity; ++i)
myPool.emplace_back(T());
}
}
/**
Erase entire contents of active list.
*/
@ -192,15 +231,11 @@ class LinkedObjectPool
myCurrent = myList.end();
}
/** Access the list with iterators, just as you would a normal C++ STL list */
iter begin() { return myList.begin(); }
iter end() { return myList.end(); }
const_iter begin() const { return myList.cbegin(); }
const_iter end() const { return myList.cend(); }
uInt32 capacity() const { return myCapacity; }
uInt32 size() const { return myList.size(); }
bool empty() const { return myList.size() == 0; }
bool full() const { return myList.size() >= CAPACITY; }
uInt32 size() const { return uInt32(myList.size()); }
bool empty() const { return size() == 0; }
bool full() const { return size() >= capacity(); }
private:
std::list<T> myList, myPool;
@ -208,6 +243,9 @@ class LinkedObjectPool
// Current position in the active list (end() indicates an invalid position)
iter myCurrent;
// Total capacity of the pool
uInt32 myCapacity;
private:
// Following constructors and assignment operators not supported
LinkedObjectPool(const LinkedObjectPool&) = delete;

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
@ -21,20 +21,98 @@
#include "Serializer.hxx"
#include "StateManager.hxx"
#include "TIA.hxx"
#include "EventHandler.hxx"
#include "RewindManager.hxx"
static int count = 1;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
RewindManager::RewindManager(OSystem& system, StateManager& statemgr)
: myOSystem(system),
myStateManager(statemgr)
{
setup();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool RewindManager::addState(const string& message)
void RewindManager::setup()
{
myLastTimeMachineAdd = false;
string prefix = myOSystem.settings().getBool("dev.settings") ? "dev." : "plr.";
mySize = myOSystem.settings().getInt(prefix + "tm.size");
if(mySize != myStateList.capacity())
myStateList.resize(mySize);
myUncompressed = myOSystem.settings().getInt(prefix + "tm.uncompressed");
myInterval = INTERVAL_CYCLES[0];
for(int i = 0; i < NUM_INTERVALS; ++i)
if(INT_SETTINGS[i] == myOSystem.settings().getString(prefix + "tm.interval"))
myInterval = INTERVAL_CYCLES[i];
myHorizon = HORIZON_CYCLES[NUM_HORIZONS-1];
for(int i = 0; i < NUM_HORIZONS; ++i)
if(HOR_SETTINGS[i] == myOSystem.settings().getString(prefix + "tm.horizon"))
myHorizon = HORIZON_CYCLES[i];
// calc interval growth factor
// this factor defines the backward horizon
const double MAX_FACTOR = 1E8;
double minFactor = 0, maxFactor = MAX_FACTOR;
myFactor = 1;
while(myUncompressed < mySize)
{
double interval = myInterval;
double cycleSum = interval * (myUncompressed + 1);
// calculate nextCycles factor
myFactor = (minFactor + maxFactor) / 2;
// horizon not reachable?
if(myFactor == MAX_FACTOR)
break;
// sum up interval cycles (first and last state are not compressed)
for(uInt32 i = myUncompressed + 1; i < mySize - 1; ++i)
{
interval *= myFactor;
cycleSum += interval;
}
double diff = cycleSum - myHorizon;
// exit loop if result is close enough
if(std::abs(diff) < myHorizon * 1E-5)
break;
// define new boundary
if(cycleSum < myHorizon)
minFactor = myFactor;
else
maxFactor = myFactor;
}
//cerr << "factor " << myFactor << endl;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool RewindManager::addState(const string& message, bool timeMachine)
{
// only check for Time Machine states, ignore for debugger
if(timeMachine && myStateList.currentIsValid())
{
// check if the current state has the right interval from the last state
RewindState& lastState = myStateList.current();
uInt32 interval = myInterval;
// adjust frame timed intervals to actual scanlines (vs 262)
if(interval >= 76 * 262 && interval <= 76 * 262 * 30)
{
const uInt32 scanlines = std::max(myOSystem.console().tia().scanlinesLastFrame(), 240u);
interval = interval * scanlines / 262;
}
if(myOSystem.console().tia().cycles() - lastState.cycles < interval)
return false;
}
// Remove all future states
myStateList.removeToLast();
@ -48,162 +126,174 @@ bool RewindManager::addState(const string& message)
RewindState& state = myStateList.current();
Serializer& s = state.data;
s.reset(); // rewind Serializer internal buffers
s.rewind(); // rewind Serializer internal buffers
if(myStateManager.saveState(s) && myOSystem.console().tia().saveDisplay(s))
{
state.message = message;
state.cycle = myOSystem.console().tia().cycles();
state.count = count++;
cerr << "add " << state.count << endl;
state.cycles = myOSystem.console().tia().cycles();
myLastTimeMachineAdd = timeMachine;
return true;
}
return false;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool RewindManager::rewindState()
uInt32 RewindManager::rewindState(uInt32 numStates)
{
if(myStateList.currentIsValid())
uInt64 startCycles = myOSystem.console().tia().cycles();
uInt32 i;
string message;
for(i = 0; i < numStates; ++i)
{
RewindState& state = myStateList.current();
Serializer& s = state.data;
string message = getMessage(state);
cerr << "rewind " << state.count << endl;
if(!atFirst())
{
if(!myLastTimeMachineAdd)
// Set internal current iterator to previous state (back in time),
// since we will now process this state...
myStateList.moveToPrevious();
else
// ...except when the last state was added automatically,
// because that already happened one interval before
myLastTimeMachineAdd = false;
s.reset(); // rewind Serializer internal buffers
myStateManager.loadState(s);
myOSystem.console().tia().loadDisplay(s);
// Show message indicating the rewind state
myOSystem.frameBuffer().showMessage(message);
// Set internal current iterator to previous state (back in time),
// since we've now processed this state
myStateList.moveToPrevious();
return true;
RewindState& state = myStateList.current();
Serializer& s = state.data;
s.rewind(); // rewind Serializer internal buffers
}
else
break;
}
if(i)
// Load the current state and get the message string for the rewind
message = loadState(startCycles, i);
else
return false;
message = "Rewind not possible";
if(myOSystem.eventHandler().state() != EventHandlerState::TIMEMACHINE)
myOSystem.frameBuffer().showMessage(message);
return i;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool RewindManager::unwindState()
uInt32 RewindManager::unwindState(uInt32 numStates)
{
#if 0
if(!atFirst()) // or last???
uInt64 startCycles = myOSystem.console().tia().cycles();
uInt32 i;
string message;
for(i = 0; i < numStates; ++i)
{
// TODO: get state next to the current state
/*RewindState& state = myStateList.???()
Serializer& s = state.data;
string message = getMessage(state);
if(!atLast())
{
// Set internal current iterator to nextCycles state (forward in time),
// since we will now process this state
myStateList.moveToNext();
s.reset(); // rewind Serializer internal buffers
myStateManager.loadState(s);
myOSystem.console().tia().loadDisplay(s);
// Show message indicating the rewind state
myOSystem.frameBuffer().showMessage(message);*/
return true;
RewindState& state = myStateList.current();
Serializer& s = state.data;
s.rewind(); // rewind Serializer internal buffers
}
else
break;
}
#endif
return false;
if(i)
// Load the current state and get the message string for the unwind
message = loadState(startCycles, i);
else
message = "Unwind not possible";
if(myOSystem.eventHandler().state() != EventHandlerState::TIMEMACHINE)
myOSystem.frameBuffer().showMessage(message);
return i;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void RewindManager::compressStates()
{
#if 0
myStateList.removeFirst(); // remove the oldest state file
#else
bool debugMode = myOSystem.eventHandler().state() == EventHandler::S_DEBUGGER;
// TODO: let user control these:
const double DENSITY = 1.15; // exponential growth of cycle intervals
const uInt32 STEP_STATES = 60; // single step rewind length
//const uInt32 SECONDS_STATES = 10; // TODO: one second rewind length
double expectedCycles = myInterval * myFactor * (1 + myFactor);
double maxError = 1.5;
uInt32 idx = myStateList.size() - 2;
//uInt32 removeIdx = 0;
// in case maxError is <= 1.5 remove first state by default:
Common::LinkedObjectPool<RewindState>::const_iter removeIter = myStateList.first();
if(myUncompressed < mySize)
// if compression is enabled, the first but one state is removed by default:
removeIter++;
uInt64 currentCycle = myOSystem.console().tia().cycles();
uInt64 lastCycle = currentCycle;
double expectedCycles = 76 * 262.0; // == cycles of 1 frame, TODO: use actual number of scanlines
double maxDelta = 0;
uInt32 removeIdx = 0;
uInt32 idx = 0;
for(auto it = myStateList.begin(); it != myStateList.end(); ++it)
//cerr << "idx: " << idx << endl;
// iterate from last but one to first but one
for(auto it = myStateList.previous(myStateList.last()); it != myStateList.first(); --it)
{
// test and never remove the very first saved state
if(++it == myStateList.end())
if(idx < mySize - myUncompressed)
{
break;
}
--it; // UGLY!
//cerr << *it << endl << endl; // debug code
expectedCycles *= myFactor;
if(idx >= STEP_STATES)
{
expectedCycles *= DENSITY;
uInt64 prevCycles = myStateList.previous(it)->cycles;
uInt64 nextCycles = myStateList.next(it)->cycles;
double error = expectedCycles / (nextCycles - prevCycles);
//cerr << "prevCycles: " << prevCycles << ", nextCycles: " << nextCycles << ", error: " << error << endl;
double expected = expectedCycles * (1 + DENSITY);
uInt64 prev = (--it)->cycle; ++it; // UGLY!
uInt64 next = (++it)->cycle; --it; // UGLY!
double delta = expected / (prev - next);
if(delta > maxDelta)
if(error > maxError)
{
maxDelta = delta;
removeIdx = idx;
maxError = error;
removeIter = it;
//removeIdx = idx;
}
}
lastCycle = it->cycle;
idx++;
--idx;
}
if (maxDelta < 1)
{
// the horizon is getting too big
//myStateList.remove(idx - 1); // remove oldest but one
}
else
{
//myStateList.remove(removeIdx); // remove
}
#endif
myStateList.remove(removeIter); // remove
//cerr << "remove " << removeIdx << endl;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string RewindManager::getMessage(RewindState& state)
string RewindManager::loadState(Int64 startCycles, uInt32 numStates)
{
Int64 diff = myOSystem.console().tia().cycles() - state.cycle;
RewindState& state = myStateList.current();
Serializer& s = state.data;
myStateManager.loadState(s);
myOSystem.console().tia().loadDisplay(s);
Int64 diff = startCycles - state.cycles;
stringstream message;
message << (diff >= 0 ? "Rewind" : "Unwind") << " " << getUnitString(diff);
message << " [" << myStateList.currentIdx() << "/" << myStateList.size() << "]";
// add optional message (TODO: when smart removal works, we have to do something smart with this part too)
if(!state.message.empty())
// add optional message
if(numStates == 1 && !state.message.empty())
message << " (" << state.message << ")";
return message.str();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string RewindManager::getUnitString(Int64 cycles)
{
const Int64 scanlines = std::max(myOSystem.console().tia().scanlinesLastFrame(), 240u);
const bool isNTSC = scanlines <= 285; // TODO: replace magic number
const Int64 NTSC_FREQ = 1193182; // ~76*262*60
const Int64 PAL_FREQ = 1182298; // ~76*312*50
const Int64 freq = isNTSC ? NTSC_FREQ : PAL_FREQ; // = cycles/second
const Int32 scanlines = std::max(myOSystem.console().tia().scanlinesLastFrame(), 240u);
const bool isNTSC = scanlines <= 287;
const Int32 NTSC_FREQ = 1193182; // ~76*262*60
const Int32 PAL_FREQ = 1182298; // ~76*312*50
const Int32 freq = isNTSC ? NTSC_FREQ : PAL_FREQ; // = cycles/second
// TODO: do we need hours here? don't think so
const Int32 NUM_UNITS = 5;
const string UNIT_NAMES[NUM_UNITS] = { "cycle", "scanline", "frame", "second", "minute" };
const Int64 UNIT_CYCLES[NUM_UNITS + 1] = { 1, 76, 76 * scanlines, freq, freq * 60, (Int64)1 << 63 };
const Int64 UNIT_CYCLES[NUM_UNITS + 1] = { 1, 76, 76 * scanlines, freq, freq * 60, Int64(1) << 62 };
stringstream result;
Int32 i;
cycles = abs(cycles);
cycles = std::abs(cycles);
for(i = 0; i < NUM_UNITS - 1; ++i)
{
// use the lower unit up to twice the next unit, except for an exact match of the next unit
// use the lower unit up to twice the nextCycles unit, except for an exact match of the nextCycles unit
// TODO: does the latter make sense, e.g. for ROMs with changing scanlines?
if(cycles < UNIT_CYCLES[i + 1] * 2 && cycles % UNIT_CYCLES[i + 1] != 0)
break;
@ -215,3 +305,26 @@ string RewindManager::getUnitString(Int64 cycles)
return result.str();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 RewindManager::getFirstCycles()
{
// TODO: check if valid
return Common::LinkedObjectPool<RewindState>::const_iter(myStateList.first())->cycles;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 RewindManager::getCurrentCycles()
{
if(myStateList.currentIsValid())
return myStateList.current().cycles;
else
return 0;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 RewindManager::getLastCycles()
{
// TODO: check if valid
return Common::LinkedObjectPool<RewindState>::const_iter(myStateList.last())->cycles;
}

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
@ -34,8 +34,9 @@ class StateManager;
Unwinding involves moving the internal iterator forwards in time (towards
the end of the list).
Any time a new state is added, the internal iterator moves back to the
insertion point of the data (the end of the list).
Any time a new state is added, all states from the current iterator position
to the end of the list (aka, all future states) are removed, and the internal
iterator moves to the insertion point of the data (the end of the list).
@author Stephen Anthony
*/
@ -45,28 +46,86 @@ class RewindManager
RewindManager(OSystem& system, StateManager& statemgr);
public:
static constexpr int NUM_INTERVALS = 7;
// cycle values for the intervals
const uInt32 INTERVAL_CYCLES[NUM_INTERVALS] = {
76 * 262,
76 * 262 * 3,
76 * 262 * 10,
76 * 262 * 30,
76 * 262 * 60,
76 * 262 * 60 * 3,
76 * 262 * 60 * 10
};
// settings values for the intervals
const string INT_SETTINGS[NUM_INTERVALS] = {
"1f",
"3f",
"10f",
"30f",
"1s",
"3s",
"10s"
};
static constexpr int NUM_HORIZONS = 8;
// cycle values for the horzions
const uInt64 HORIZON_CYCLES[NUM_HORIZONS] = {
76 * 262 * 60 * 3,
76 * 262 * 60 * 10,
76 * 262 * 60 * 30,
76 * 262 * 60 * 60,
76 * 262 * 60 * 60 * 3,
76 * 262 * 60 * 60 * 10,
uInt64(76) * 262 * 60 * 60 * 30,
uInt64(76) * 262 * 60 * 60 * 60
};
// settings values for the horzions
const string HOR_SETTINGS[NUM_HORIZONS] = {
"3s",
"10s",
"30s",
"1m",
"3m",
"10m",
"30m",
"60m"
};
/**
Initializes state list and calculates compression factor.
*/
void setup();
/**
Add a new state file with the given message; this message will be
displayed when the state is replayed.
@param message Message to display when replaying this state
*/
bool addState(const string& message);
bool addState(const string& message, bool timeMachine = false);
/**
Rewind one level of the state list, and display the message associated
with that state.
@param numStates Number of states to rewind
@return Number of states to rewinded
*/
bool rewindState();
uInt32 rewindState(uInt32 numStates = 1);
/**
Unwind one level of the state list, and display the message associated
with that state.
*/
bool unwindState();
bool atLast() const { return myStateList.empty(); }
bool atFirst() const { return false; } // TODO
@param numStates Number of states to unwind
@return Number of states to unwinded
*/
uInt32 unwindState(uInt32 numStates = 1);
bool atFirst() const { return myStateList.atFirst(); }
bool atLast() const { return myStateList.atLast(); }
void resize(uInt32 size) { myStateList.resize(size); }
void clear() { myStateList.clear(); }
/**
@ -74,32 +133,55 @@ class RewindManager
*/
string getUnitString(Int64 cycles);
private:
// Maximum number of states to save
static constexpr uInt32 MAX_SIZE = 100; // TODO: use a parameter here and allow user to define size in UI
uInt32 getCurrentIdx() { return myStateList.currentIdx(); }
uInt32 getLastIdx() { return myStateList.size(); }
uInt32 getFirstCycles();
uInt32 getCurrentCycles();
uInt32 getLastCycles();
private:
OSystem& myOSystem;
StateManager& myStateManager;
uInt32 mySize;
uInt32 myUncompressed;
uInt32 myInterval;
uInt64 myHorizon;
double myFactor;
bool myLastTimeMachineAdd;
struct RewindState {
Serializer data;
string message;
uInt64 cycle;
int count; // TODO - remove this
Serializer data; // actual save state
string message; // describes save state origin
uInt64 cycles; // cycles since emulation started
// We do nothing on object instantiation or copy
// The goal of LinkedObjectPool is to not do any allocations at all
RewindState() { }
RewindState(const RewindState&) { }
// Output object info; used for debugging only
friend ostream& operator<<(ostream& os, const RewindState& s) {
return os << "msg: " << s.message << " cycle: " << s.cycles;
}
};
// The linked-list to store states (internally it takes care of reducing
// frequent (de)-allocations)
Common::LinkedObjectPool<RewindState, MAX_SIZE> myStateList;
Common::LinkedObjectPool<RewindState> myStateList;
/**
Remove a save state from the list
*/
void compressStates();
string getMessage(RewindState& state);
/**
Load the current state and get the message string for the rewind/unwind
@return The message
*/
string loadState(Int64 startCycles, uInt32 numStates);
private:
// Following constructors and assignment operators not supported

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
@ -27,7 +27,7 @@
#include "StateManager.hxx"
#define STATE_HEADER "05000304state"
#define STATE_HEADER "05009901state"
// #define MOVIE_HEADER "03030000movie"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -129,29 +129,30 @@ void StateManager::toggleRecordMode()
#endif
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void StateManager::toggleRewindMode()
void StateManager::toggleTimeMachine()
{
myActiveMode = myActiveMode == Mode::Rewind ? Mode::Off : Mode::Rewind;
if(myActiveMode == Mode::Rewind)
myOSystem.frameBuffer().showMessage("Continuous rewind enabled");
bool devSettings = myOSystem.settings().getBool("dev.settings");
myActiveMode = myActiveMode == Mode::TimeMachine ? Mode::Off : Mode::TimeMachine;
if(myActiveMode == Mode::TimeMachine)
myOSystem.frameBuffer().showMessage("Time Machine enabled");
else
myOSystem.frameBuffer().showMessage("Continuous rewind disabled");
myOSystem.frameBuffer().showMessage("Time Machine disabled");
myOSystem.settings().setValue(devSettings ? "dev.timemachine" : "plr.timemachine", myActiveMode == Mode::TimeMachine);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool StateManager::rewindState()
bool StateManager::rewindState(uInt32 numStates)
{
RewindManager& r = myOSystem.state().rewindManager();
// TODO: add parameter to indicate rewinding from within emulation
return r.rewindState();
return r.rewindState(numStates);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool StateManager::unwindState()
bool StateManager::unwindState(uInt32 numStates)
{
RewindManager& r = myOSystem.state().rewindManager();
// TODO: add parameter to indicate unwinding from within emulation
return r.unwindState();
return r.unwindState(numStates);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -159,8 +160,8 @@ void StateManager::update()
{
switch(myActiveMode)
{
case Mode::Rewind:
myRewindManager->addState("add 1 frame");
case Mode::TimeMachine:
myRewindManager->addState("Time Machine", true);
break;
#if 0
@ -356,7 +357,7 @@ void StateManager::reset()
{
myRewindManager->clear();
myActiveMode = myOSystem.settings().getBool(
myOSystem.settings().getBool("dev.settings") ? "dev.rewind" : "plr.rewind") ? Mode::Rewind : Mode::Off;
myOSystem.settings().getBool("dev.settings") ? "dev.timemachine" : "plr.timemachine") ? Mode::TimeMachine : Mode::Off;
#if 0
myCurrentSlot = 0;

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
@ -35,7 +35,7 @@ class StateManager
public:
enum class Mode {
Off,
Rewind,
TimeMachine,
MovieRecord,
MoviePlayback
};
@ -63,23 +63,23 @@ class StateManager
Toggle state rewind recording mode; this uses the RewindManager
for its functionality.
*/
void toggleRewindMode();
void toggleTimeMachine();
/**
Sets state rewind recording mode; this uses the RewindManager
for its functionality.
*/
void setRewindMode(Mode mode) { myActiveMode = mode; };
void setRewindMode(Mode mode) { myActiveMode = mode; }
/**
Rewinds one state; this uses the RewindManager for its functionality.
*/
bool rewindState();
bool rewindState(uInt32 numStates = 1);
/**
Unwinds one state; this uses the RewindManager for its functionality.
*/
bool unwindState();
bool unwindState(uInt32 numStates = 1);
/**
Updates the state of the system based on the currently active mode.

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
@ -412,4 +412,27 @@ enum StellaMod
KBDM_GUI = (KBDM_LGUI|KBDM_RGUI)
};
// Test if specified modifier is pressed
namespace StellaModTest
{
inline bool isAlt(int mod)
{
#if defined(BSPF_MAC_OSX) || defined(OSX_KEYS)
return (mod & KBDM_GUI);
#else
return (mod & KBDM_ALT);
#endif
}
inline bool isControl(int mod)
{
return (mod & KBDM_CTRL);
}
inline bool isShift(int mod)
{
return (mod & KBDM_SHIFT);
}
};
#endif /* StellaKeys */

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
@ -18,7 +18,7 @@
#ifndef VERSION_HXX
#define VERSION_HXX
#define STELLA_VERSION "5.1_a1"
#define STELLA_VERSION "5.1_a2"
#define STELLA_BUILD "3826"
#endif

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of

View File

@ -8,7 +8,7 @@
// BB BB SS SS PP FF
// BBBBB SSSS PP FF
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of

View File

@ -8,14 +8,14 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 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 <time.h>
#include <ctime>
#include "bspf.hxx"
#include "System.hxx"
@ -831,9 +831,6 @@ string CartDebug::loadSymbolFile()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string CartDebug::loadConfigFile()
{
if(myConsole.cartridge().bankCount() > 1)
return DebuggerParser::red("config file for multi-bank ROM not yet supported");
// There are two possible locations for loading config files
// (in order of decreasing relevance):
// 1) ROM dir based on properties entry name
@ -934,15 +931,17 @@ string CartDebug::loadConfigFile()
}
myDebugger.rom().invalidate();
return "loaded " + node.getShortPath() + " OK";
stringstream retVal;
if(myConsole.cartridge().bankCount() > 1)
retVal << DebuggerParser::red("config file for multi-bank ROM not fully supported\n");
retVal << "loaded " << node.getShortPath() << " OK";
return retVal.str();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string CartDebug::saveConfigFile()
{
if(myConsole.cartridge().bankCount() > 1)
return DebuggerParser::red("config file for multi-bank ROM not yet supported");
// While there are two possible locations for loading config files,
// the main 'config' directory is used whenever possible when saving,
// unless the rom-specific file already exists
@ -977,7 +976,11 @@ string CartDebug::saveConfigFile()
getBankDirectives(out, myBankInfo[b]);
}
return "saved " + node.getShortPath() + " OK";
stringstream retVal;
if(myConsole.cartridge().bankCount() > 1)
retVal << DebuggerParser::red("config file for multi-bank ROM not fully supported\n");
retVal << "saved " << node.getShortPath() << " OK";
return retVal.str();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -1236,7 +1239,7 @@ string CartDebug::saveRom()
{
const string& rom = myConsole.properties().get(Cartridge_Name) + ".a26";
FilesystemNode node(myOSystem.defaultSaveDir() + "ROMs\\" + rom);
FilesystemNode node(myOSystem.defaultSaveDir() + rom);
ofstream out(node.getPath(), std::ios::binary);
if(out && myConsole.cartridge().saveROM(out))
return "saved ROM as " + node.getShortPath();
@ -1363,7 +1366,7 @@ void CartDebug::getBankDirectives(ostream& buf, BankInfo& info) const
buf << "ORG " << Base::HEX4 << info.offset << endl;
// Now consider each byte
uInt16 prev = info.offset, addr = prev + 1;
uInt32 prev = info.offset, addr = prev + 1;
DisasmType prevType = disasmTypeAbsolute(mySystem.getAccessFlags(prev));
for( ; addr < info.offset + info.size; ++addr)
{

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
@ -142,6 +142,12 @@ int CpuDebug::c() const
return mySystem.m6502().C;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int CpuDebug::icycles() const
{
return mySystem.m6502().icycles;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CpuDebug::setPC(int pc)
{
@ -220,6 +226,12 @@ void CpuDebug::setC(bool on)
my6502.C = on;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CpuDebug::setCycles(int cycles)
{
my6502.icycles = cycles;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CpuDebug::toggleN()
{

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
@ -61,6 +61,8 @@ class CpuDebug : public DebuggerSystem
int z() const;
int c() const;
int icycles() const;
void setPC(int pc);
void setSP(int sp);
void setPS(int ps);
@ -76,6 +78,8 @@ class CpuDebug : public DebuggerSystem
void setZ(bool on);
void setC(bool on);
void setCycles(int cycles);
void toggleN();
void toggleV();
void toggleB();

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
@ -22,6 +22,7 @@
#include "Version.hxx"
#include "OSystem.hxx"
#include "FrameBuffer.hxx"
#include "EventHandler.hxx"
#include "FSNode.hxx"
#include "Settings.hxx"
#include "DebuggerDialog.hxx"
@ -107,6 +108,8 @@ void Debugger::initialize()
myBaseDialog = myDialog;
myCartDebug->setDebugWidget(&(myDialog->cartDebug()));
saveOldState();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -270,8 +273,7 @@ void Debugger::loadState(int state)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
int Debugger::step()
{
saveOldState("1 step");
mySystem.clearDirtyPages();
saveOldState();
uInt64 startCycle = mySystem.cycles();
@ -279,6 +281,7 @@ int Debugger::step()
myOSystem.console().tia().updateScanlineByStep().flushLineCache();
lockBankswitchState();
addState("step");
return int(mySystem.cycles() - startCycle);
}
@ -297,8 +300,7 @@ int Debugger::trace()
// 32 is the 6502 JSR instruction:
if(mySystem.peek(myCpuDebug->pc()) == 32)
{
saveOldState("1 trace");
mySystem.clearDirtyPages();
saveOldState();
uInt64 startCycle = mySystem.cycles();
int targetPC = myCpuDebug->pc() + 3; // return address
@ -307,6 +309,7 @@ int Debugger::trace()
myOSystem.console().tia().updateScanlineByTrace(targetPC).flushLineCache();
lockBankswitchState();
addState("trace");
return int(mySystem.cycles() - startCycle);
}
else
@ -483,12 +486,9 @@ uInt32 Debugger::getBaseAddress(uInt32 addr, bool read)
void Debugger::nextScanline(int lines)
{
ostringstream buf;
buf << lines << " scanline";
if(lines > 1)
buf << "s";
buf << "scanline + " << lines;
saveOldState(buf.str());
mySystem.clearDirtyPages();
saveOldState();
unlockBankswitchState();
while(lines)
@ -498,6 +498,7 @@ void Debugger::nextScanline(int lines)
}
lockBankswitchState();
addState(buf.str());
myOSystem.console().tia().flushLineCache();
}
@ -505,12 +506,9 @@ void Debugger::nextScanline(int lines)
void Debugger::nextFrame(int frames)
{
ostringstream buf;
buf << frames << " frame";
if(frames > 1)
buf << "s";
buf << "frame + " << frames;
saveOldState(buf.str());
mySystem.clearDirtyPages();
saveOldState();
unlockBankswitchState();
while(frames)
@ -519,31 +517,28 @@ void Debugger::nextFrame(int frames)
--frames;
}
lockBankswitchState();
addState(buf.str());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Debugger::updateRewindbuttons(const RewindManager& r)
{
myDialog->rewindButton().setEnabled(!r.atLast());
myDialog->unwindButton().setEnabled(!r.atFirst());
myDialog->rewindButton().setEnabled(!r.atFirst());
myDialog->unwindButton().setEnabled(!r.atLast());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt16 Debugger::windStates(uInt16 states, bool unwind, string& message)
uInt16 Debugger::windStates(uInt16 numStates, bool unwind, string& message)
{
RewindManager& r = myOSystem.state().rewindManager();
mySystem.clearDirtyPages();
saveOldState();
unlockBankswitchState();
uInt16 winds = 0;
uInt64 startCycles = myOSystem.console().tia().cycles();
for(uInt16 i = 0; i < states; ++i)
if(unwind ? r.unwindState() : r.rewindState())
winds++;
else
break;
uInt16 winds = unwind ? r.unwindState(numStates) : r.rewindState(numStates);
message = r.getUnitString(myOSystem.console().tia().cycles() - startCycles);
lockBankswitchState();
@ -553,15 +548,15 @@ uInt16 Debugger::windStates(uInt16 states, bool unwind, string& message)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt16 Debugger::rewindStates(const uInt16 states, string& message)
uInt16 Debugger::rewindStates(const uInt16 numStates, string& message)
{
return windStates(states, false, message);
return windStates(numStates, false, message);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt16 Debugger::unwindStates(const uInt16 states, string& message)
uInt16 Debugger::unwindStates(const uInt16 numStates, string& message)
{
return windStates(states, true, message);
return windStates(numStates, true, message);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -596,20 +591,24 @@ bool Debugger::patchROM(uInt16 addr, uInt8 value)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Debugger::saveOldState(string rewindMsg)
void Debugger::saveOldState(bool clearDirtyPages)
{
if (clearDirtyPages)
mySystem.clearDirtyPages();
myCartDebug->saveOldState();
myCpuDebug->saveOldState();
myRiotDebug->saveOldState();
myTiaDebug->saveOldState();
}
// Add another rewind level to the Undo list
if(rewindMsg != "")
{
RewindManager& r = myOSystem.state().rewindManager();
r.addState(rewindMsg);
updateRewindbuttons(r);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Debugger::addState(string rewindMsg)
{
// Add another rewind level to the Time Machine buffer
RewindManager& r = myOSystem.state().rewindManager();
r.addState(rewindMsg);
updateRewindbuttons(r);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -618,11 +617,13 @@ void Debugger::setStartState()
// Lock the bus each time the debugger is entered, so we don't disturb anything
lockBankswitchState();
// Save initial state and add it to the rewind list (except when in currently rewinding)
RewindManager& r = myOSystem.state().rewindManager();
updateRewindbuttons(r);
// Save initial state, but don't add it to the rewind list
saveOldState();
// avoid invalidating future states when entering the debugger e.g. during rewind
if(myOSystem.eventHandler().state() == EventHandlerState::EMULATION)
addState("enter debugger");
else
updateRewindbuttons(r);
// Set the 're-disassemble' flag, but don't do it until the next scheduled time
myDialog->rom().invalidate(false);
@ -631,12 +632,11 @@ void Debugger::setStartState()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Debugger::setQuitState()
{
saveOldState();
// Bus must be unlocked for normal operation when leaving debugger mode
unlockBankswitchState();
// Save state when leaving the debugger
saveOldState("exit debugger");
// execute one instruction on quit. If we're
// sitting at a breakpoint/trap, this will get us past it.
// Somehow this feels like a hack to me, but I don't know why
@ -819,6 +819,7 @@ Debugger::PseudoRegister Debugger::ourPseudoRegisters[NUM_PSEUDO_REGS] = {
{ "_cycleslo", "Lower 32 bits of number of cycles since emulation started" },
{ "_fcount", "Number of frames since emulation started" },
{ "_fcycles", "Number of cycles since frame started" },
{ "_icycles", "Number of cycles of last instruction" },
{ "_rwport", "Address at which a read from a write port occurred" },
{ "_scan", "Current scanline count" },
{ "_scycles", "Number of cycles in current scanline" },

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
@ -20,6 +20,7 @@
class OSystem;
class Console;
class EventHandler;
class TiaInfoWidget;
class TiaOutputWidget;
class TiaZoomWidget;
@ -241,12 +242,15 @@ class Debugger : public DialogContainer
private:
/**
Save state of each debugger subsystem.
If a message is provided, we assume that a rewind state should
be saved with the given message.
Save state of each debugger subsystem and, by default, mark all
pages as clean (ie, turn off the dirty flag).
*/
void saveOldState(string rewindMsg = "");
void saveOldState(bool clearDirtyPages = true);
/**
Saves a rewind state with the given message.
*/
void addState(string rewindMsg);
/**
Set initial state before entering the debugger.
@ -262,8 +266,8 @@ class Debugger : public DialogContainer
int trace();
void nextScanline(int lines);
void nextFrame(int frames);
uInt16 rewindStates(const uInt16 states, string& message);
uInt16 unwindStates(const uInt16 states, string& message);
uInt16 rewindStates(const uInt16 numStates, string& message);
uInt16 unwindStates(const uInt16 numStates, string& message);
void toggleBreakPoint(uInt16 bp);
@ -315,13 +319,13 @@ class Debugger : public DialogContainer
string name, help;
};
static const uInt32 NUM_BUILTIN_FUNCS = 18;
static const uInt32 NUM_PSEUDO_REGS = 11;
static const uInt32 NUM_PSEUDO_REGS = 12;
static BuiltinFunction ourBuiltinFunctions[NUM_BUILTIN_FUNCS];
static PseudoRegister ourPseudoRegisters[NUM_PSEUDO_REGS];
private:
// rewind/unwind n states
uInt16 windStates(uInt16 states, bool unwind, string& message);
uInt16 windStates(uInt16 numStates, bool unwind, string& message);
// update the rewind/unwind button state
void updateRewindbuttons(const RewindManager& r);

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
@ -234,7 +234,7 @@ int DebuggerParser::decipher_arg(const string& str)
// Special cases (registers):
const CpuState& state = static_cast<const CpuState&>(debugger.cpuDebug().getState());
if(arg == "a") result = state.A;
if(arg == "a" && str != "$a") result = state.A;
else if(arg == "x") result = state.X;
else if(arg == "y") result = state.Y;
else if(arg == "p") result = state.PS;
@ -756,6 +756,7 @@ void DebuggerParser::executeBreakif()
{
if(condition == debugger.m6502().getCondBreakNames()[i])
{
args[0] = i;
executeDelbreakif();
return;
}
@ -1830,6 +1831,7 @@ void DebuggerParser::executeSavestateif()
{
if(condition == debugger.m6502().getCondSaveStateNames()[i])
{
args[0] = i;
executeDelsavestateif();
return;
}
@ -2177,7 +2179,6 @@ void DebuggerParser::executeWatch()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// wrapper function for rewind/unwind commands
// TODO: return and output (formatted) cycles
void DebuggerParser::executeWinds(bool unwind)
{
uInt16 states;
@ -2370,7 +2371,7 @@ DebuggerParser::Command DebuggerParser::commands[kNumCommands] = {
{
"d",
"Carry Flag: set (0 or 1), or toggle (no arg)",
"Decimal Flag: set (0 or 1), or toggle (no arg)",
"Example: d, d 0, d 1",
false,
true,
@ -2471,11 +2472,11 @@ DebuggerParser::Command DebuggerParser::commands[kNumCommands] = {
{
"dump",
"Dump data at address <xx> [to yy] [1..7]",
"Dump data at address <xx> [to yy] [1: memory; 2: CPU state; 4: input regs]",
"Example:\n"
" dump f000 - dumps 128 bytes @ f000\n"
" dump f000 f0ff - dumps all bytes from f000 to f0ff\n"
" dump f000 f0ff 7 - dumps all bytes from f000 to f0ff, CPU and input states into a file",
" dump f000 f0ff 7 - dumps all bytes from f000 to f0ff, CPU state and input registers into a file",
true,
false,
{ kARG_WORD, kARG_MULTI_BYTE },
@ -2796,7 +2797,7 @@ DebuggerParser::Command DebuggerParser::commands[kNumCommands] = {
{
"rewind",
"Rewind state to last [xx] steps/traces/scanlines/frames...",
"Rewind state by one or [xx] steps/traces/scanlines/frames...",
"Example: rewind, rewind 5",
false,
true,
@ -2878,8 +2879,8 @@ DebuggerParser::Command DebuggerParser::commands[kNumCommands] = {
{
"save",
"Save breaks, watches, traps to file xx",
"Example: save commands.txt",
"Save breaks, watches, traps and functions to file xx",
"Example: save commands.script",
true,
false,
{ kARG_FILE, kARG_END_ARGS },
@ -2920,7 +2921,7 @@ DebuggerParser::Command DebuggerParser::commands[kNumCommands] = {
{
"saveses",
"Save console session",
"Save console session (with default name)",
"Example: saveses\n"
"NOTE: saves to default save location",
false,
@ -3109,7 +3110,7 @@ DebuggerParser::Command DebuggerParser::commands[kNumCommands] = {
{
"unwind",
"Unwind state to next [xx] steps/traces/scanlines/frames...",
"Unwind state by one or [xx] steps/traces/scanlines/frames...",
"Example: unwind, unwind 5",
false,
true,

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
@ -51,7 +51,7 @@ class DebuggerParser
static inline string red(const string& msg = "")
{
return char(kDbgChangedColor) + msg;
return char(kDbgColorRed) + msg;
}
static inline string inverse(const string& msg = "")
{

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
@ -54,6 +54,9 @@ const DebuggerState& RiotDebug::getState()
myState.INPT4 = inpt(4);
myState.INPT5 = inpt(5);
myState.INPTLatch = vblank(6);
myState.INPTDump = vblank(7);
// Timer registers
myState.TIM1T = tim1T();
myState.TIM8T = tim8T();
@ -92,6 +95,9 @@ void RiotDebug::saveOldState()
myOldState.INPT4 = inpt(4);
myOldState.INPT5 = inpt(5);
myOldState.INPTLatch = vblank(6);
myOldState.INPTDump = vblank(7);
// Timer registers
myOldState.TIM1T = tim1T();
myOldState.TIM8T = tim8T();

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
@ -40,6 +40,7 @@ class RiotState : public DebuggerState
// These are actually from the TIA, but are I/O related
uInt8 INPT0, INPT1, INPT2, INPT3, INPT4, INPT5;
bool INPTLatch, INPTDump;
};
class RiotDebug : public DebuggerSystem

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
@ -60,6 +60,24 @@ const DebuggerState& TIADebug::getState()
myState.fixedCols.push_back(myTIA.myFixedColorPalette[mode][TIA::BL]);
myState.fixedCols.push_back(TIA::FixedColor::HBLANK_WHITE);
// Collisions
myState.cx.clear();
myState.cx.push_back(collP0_PF());
myState.cx.push_back(collP0_BL());
myState.cx.push_back(collM1_P0());
myState.cx.push_back(collM0_P0());
myState.cx.push_back(collP0_P1());
myState.cx.push_back(collP1_PF());
myState.cx.push_back(collP1_BL());
myState.cx.push_back(collM1_P1());
myState.cx.push_back(collM0_P1());
myState.cx.push_back(collM0_PF());
myState.cx.push_back(collM0_BL());
myState.cx.push_back(collM0_M1());
myState.cx.push_back(collM1_PF());
myState.cx.push_back(collM1_BL());
myState.cx.push_back(collBL_PF());
// Player 0 & 1 and Ball graphics registers
myState.gr.clear();
myState.gr.push_back(myTIA.myPlayer0.getGRPNew());
@ -69,6 +87,18 @@ const DebuggerState& TIADebug::getState()
myState.gr.push_back(myTIA.myBall.getENABLNew());
myState.gr.push_back(myTIA.myBall.getENABLOld());
// Player 0 & 1, Missile 0 & 1 and Ball graphics status registers
myState.ref.clear();
myState.ref.push_back(refP0());
myState.ref.push_back(refP1());
myState.vdel.clear();
myState.vdel.push_back(vdelP0());
myState.vdel.push_back(vdelP1());
myState.vdel.push_back(vdelBL());
myState.res.clear();
myState.res.push_back(resMP0());
myState.res.push_back(resMP1());
// Position registers
myState.pos.clear();
myState.pos.push_back(posP0());
@ -90,6 +120,9 @@ const DebuggerState& TIADebug::getState()
myState.pf.push_back(pf0());
myState.pf.push_back(pf1());
myState.pf.push_back(pf2());
myState.pf.push_back(refPF());
myState.pf.push_back(scorePF());
myState.pf.push_back(priorityPF());
// Size registers
myState.size.clear();
@ -108,6 +141,16 @@ const DebuggerState& TIADebug::getState()
myState.aud.push_back(audV0());
myState.aud.push_back(audV1());
// internal TIA state
myState.info.clear();
myState.info.push_back(frameCount());
myState.info.push_back(frameCycles());
myState.info.push_back(vsyncAsInt());
myState.info.push_back(vblankAsInt());
myState.info.push_back(scanlines());
myState.info.push_back(scanlinesLastFrame());
myState.info.push_back(clocksThisLine());
return myState;
}
@ -121,6 +164,24 @@ void TIADebug::saveOldState()
myOldState.coluRegs.push_back(coluPF());
myOldState.coluRegs.push_back(coluBK());
// Collisions
myOldState.cx.clear();
myOldState.cx.push_back(collP0_PF());
myOldState.cx.push_back(collP0_BL());
myOldState.cx.push_back(collM1_P0());
myOldState.cx.push_back(collM0_P0());
myOldState.cx.push_back(collP0_P1());
myOldState.cx.push_back(collP1_PF());
myOldState.cx.push_back(collP1_BL());
myOldState.cx.push_back(collM1_P1());
myOldState.cx.push_back(collM0_P1());
myOldState.cx.push_back(collM0_PF());
myOldState.cx.push_back(collM0_BL());
myOldState.cx.push_back(collM0_M1());
myOldState.cx.push_back(collM1_PF());
myOldState.cx.push_back(collM1_BL());
myOldState.cx.push_back(collBL_PF());
// Player 0 & 1 graphics registers
myOldState.gr.clear();
myOldState.gr.push_back(myTIA.myPlayer0.getGRPNew());
@ -130,6 +191,18 @@ void TIADebug::saveOldState()
myOldState.gr.push_back(myTIA.myBall.getENABLNew());
myOldState.gr.push_back(myTIA.myBall.getENABLOld());
// Player 0 & 1, Missile 0 & 1 and Ball graphics status registers
myOldState.ref.clear();
myOldState.ref.push_back(refP0());
myOldState.ref.push_back(refP1());
myOldState.vdel.clear();
myOldState.vdel.push_back(vdelP0());
myOldState.vdel.push_back(vdelP1());
myOldState.vdel.push_back(vdelBL());
myOldState.res.clear();
myOldState.res.push_back(resMP0());
myOldState.res.push_back(resMP1());
// Position registers
myOldState.pos.clear();
myOldState.pos.push_back(posP0());
@ -151,6 +224,9 @@ void TIADebug::saveOldState()
myOldState.pf.push_back(pf0());
myOldState.pf.push_back(pf1());
myOldState.pf.push_back(pf2());
myOldState.pf.push_back(refPF());
myOldState.pf.push_back(scorePF());
myOldState.pf.push_back(priorityPF());
// Size registers
myOldState.size.clear();
@ -168,6 +244,16 @@ void TIADebug::saveOldState()
myOldState.aud.push_back(audC1());
myOldState.aud.push_back(audV0());
myOldState.aud.push_back(audV1());
// internal TIA state
myOldState.info.clear();
myOldState.info.push_back(frameCount());
myOldState.info.push_back(frameCycles());
myOldState.info.push_back(vsyncAsInt());
myOldState.info.push_back(vblankAsInt());
myOldState.info.push_back(scanlines());
myOldState.info.push_back(scanlinesLastFrame());
myOldState.info.push_back(clocksThisLine());
}
/* the set methods now use mySystem.poke(). This will save us the
@ -331,25 +417,83 @@ bool TIADebug::priorityPF(int newVal)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool TIADebug::collision(CollisionBit id) const
bool TIADebug::collision(CollisionBit id, bool toggle) const
{
switch(id)
{
case Cx_M0P1: return myTIA.collCXM0P() & 0x80;
case Cx_M0P0: return myTIA.collCXM0P() & 0x40;
case Cx_M1P0: return myTIA.collCXM1P() & 0x80;
case Cx_M1P1: return myTIA.collCXM1P() & 0x40;
case Cx_P0PF: return myTIA.collCXP0FB() & 0x80;
case Cx_P0BL: return myTIA.collCXP0FB() & 0x40;
case Cx_P1PF: return myTIA.collCXP1FB() & 0x80;
case Cx_P1BL: return myTIA.collCXP1FB() & 0x40;
case Cx_M0PF: return myTIA.collCXM0FB() & 0x80;
case Cx_M0BL: return myTIA.collCXM0FB() & 0x40;
case Cx_M1PF: return myTIA.collCXM1FB() & 0x80;
case Cx_M1BL: return myTIA.collCXM1FB() & 0x40;
case Cx_BLPF: return myTIA.collCXBLPF() & 0x80;
case Cx_P0P1: return myTIA.collCXPPMM() & 0x80;
case Cx_M0M1: return myTIA.collCXPPMM() & 0x40;
case CollisionBit::M0P1:
if(toggle)
myTIA.toggleCollP1M0();
return myTIA.collCXM0P() & 0x80;
case CollisionBit::M0P0:
if(toggle)
myTIA.toggleCollP0M0();
return myTIA.collCXM0P() & 0x40;
case CollisionBit::M1P0:
if(toggle)
myTIA.toggleCollP0M1();
return myTIA.collCXM1P() & 0x80;
case CollisionBit::M1P1:
if(toggle)
myTIA.toggleCollP1M1();
return myTIA.collCXM1P() & 0x40;
case CollisionBit::P0PF:
if(toggle)
myTIA.toggleCollP0PF();
return myTIA.collCXP0FB() & 0x80;
case CollisionBit::P0BL:
if(toggle)
myTIA.toggleCollP0BL();
return myTIA.collCXP0FB() & 0x40;
case CollisionBit::P1PF:
if(toggle)
myTIA.toggleCollP1PF();
return myTIA.collCXP1FB() & 0x80;
case CollisionBit::P1BL:
if(toggle)
myTIA.toggleCollP1BL();
return myTIA.collCXP1FB() & 0x40;
case CollisionBit::M0PF:
if(toggle)
myTIA.toggleCollM0PF();
return myTIA.collCXM0FB() & 0x80;
case CollisionBit::M0BL:
if(toggle)
myTIA.toggleCollM0BL();
return myTIA.collCXM0FB() & 0x40;
case CollisionBit::M1PF:
if(toggle)
myTIA.toggleCollM1PF();
return myTIA.collCXM1FB() & 0x80;
case CollisionBit::M1BL:
if(toggle)
myTIA.toggleCollM1BL();
return myTIA.collCXM1FB() & 0x40;
case CollisionBit::BLPF:
if(toggle)
myTIA.toggleCollBLPF();
return myTIA.collCXBLPF() & 0x80;
case CollisionBit::P0P1:
if(toggle)
myTIA.toggleCollP0P1();
return myTIA.collCXPPMM() & 0x80;
case CollisionBit::M0M1:
if(toggle)
myTIA.toggleCollM0M1();
return myTIA.collCXPPMM() & 0x40;
}
return false; // make compiler happy
}
@ -869,17 +1013,17 @@ string TIADebug::debugColors() const
ostringstream buf;
int mode = myTIA.frameLayout() == FrameLayout::ntsc ? 0 : 1;
buf << " Red " << colorSwatch(myTIA.myFixedColorPalette[mode][TIA::P0])
buf << " " << myTIA.myFixedColorNames[TIA::P0] << " " << colorSwatch(myTIA.myFixedColorPalette[mode][TIA::P0])
<< " Player 0\n"
<< " Orange " << colorSwatch(myTIA.myFixedColorPalette[mode][TIA::M0])
<< " " << myTIA.myFixedColorNames[TIA::M0] << " " << colorSwatch(myTIA.myFixedColorPalette[mode][TIA::M0])
<< " Missile 0\n"
<< " Yellow " << colorSwatch(myTIA.myFixedColorPalette[mode][TIA::P1])
<< " " << myTIA.myFixedColorNames[TIA::P1] << " " << colorSwatch(myTIA.myFixedColorPalette[mode][TIA::P1])
<< " Player 1\n"
<< " Green " << colorSwatch(myTIA.myFixedColorPalette[mode][TIA::M1])
<< " " << myTIA.myFixedColorNames[TIA::M1] << " " << colorSwatch(myTIA.myFixedColorPalette[mode][TIA::M1])
<< " Missile 1\n"
<< " Blue " << colorSwatch(myTIA.myFixedColorPalette[mode][TIA::PF])
<< " " << myTIA.myFixedColorNames[TIA::PF] << " " << colorSwatch(myTIA.myFixedColorPalette[mode][TIA::PF])
<< " Playfield\n"
<< " Purple " << colorSwatch(myTIA.myFixedColorPalette[mode][TIA::BL])
<< " " << myTIA.myFixedColorNames[TIA::BL] << " " << colorSwatch(myTIA.myFixedColorPalette[mode][TIA::BL])
<< " Ball\n"
<< " Grey " << colorSwatch(TIA::FixedColor::BK_GREY)
<< " Background\n"

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2017 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2018 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
@ -39,12 +39,17 @@ class TiaState : public DebuggerState
public:
IntArray coluRegs;
IntArray fixedCols;
BoolArray cx;
IntArray gr;
BoolArray ref;
BoolArray vdel;
BoolArray res;
IntArray pos;
IntArray hm;
IntArray pf;
IntArray size;
IntArray aud;
IntArray info;
};
class TIADebug : public DebuggerSystem
@ -125,22 +130,25 @@ class TIADebug : public DebuggerSystem
bool scorePF(int newVal = -1);
bool priorityPF(int newVal = -1);
/** Get specific bits in the collision register (used by collXX_XX) */
bool collision(CollisionBit id, bool toggle = false) const;
// Collision registers
bool collM0_P1() const { return collision(Cx_M0P1); }
bool collM0_P0() const { return collision(Cx_M0P0); }
bool collM1_P0() const { return collision(Cx_M1P0); }
bool collM1_P1() const { return collision(Cx_M1P1); }
bool collP0_PF() const { return collision(Cx_P0PF); }
bool collP0_BL() const { return collision(Cx_P0BL); }
bool collP1_PF() const { return collision(Cx_P1PF); }
bool collP1_BL() const { return collision(Cx_P1BL); }
bool collM0_PF() const { return collision(Cx_M0PF); }
bool collM0_BL() const { return collision(Cx_M0BL); }
bool collM1_PF() const { return collision(Cx_M1PF); }
bool collM1_BL() const { return collision(Cx_M1BL); }
bool collBL_PF() const { return collision(Cx_BLPF); }
bool collP0_P1() const { return collision(Cx_P0P1); }
bool collM0_M1() const { return collision(Cx_M0M1); }
bool collM0_P1() const { return collision(CollisionBit::M0P1); }
bool collM0_P0() const { return collision(CollisionBit::M0P0); }
bool collM1_P0() const { return collision(CollisionBit::M1P0); }
bool collM1_P1() const { return collision(CollisionBit::M1P1); }
bool collP0_PF() const { return collision(CollisionBit::P0PF); }
bool collP0_BL() const { return collision(CollisionBit::P0BL); }
bool collP1_PF() const { return collision(CollisionBit::P1PF); }
bool collP1_BL() const { return collision(CollisionBit::P1BL); }
bool collM0_PF() const { return collision(CollisionBit::M0PF); }
bool collM0_BL() const { return collision(CollisionBit::M0BL); }
bool collM1_PF() const { return collision(CollisionBit::M1PF); }
bool collM1_BL() const { return collision(CollisionBit::M1BL); }
bool collBL_PF() const { return collision(CollisionBit::BLPF); }
bool collP0_P1() const { return collision(CollisionBit::P0P1); }
bool collM0_M1() const { return collision(CollisionBit::M0M1); }
// TIA strobe registers
void strobeWsync();
@ -174,9 +182,6 @@ class TIADebug : public DebuggerSystem
/** Display a color patch for color at given index in the palette */
string colorSwatch(uInt8 c) const;
/** Get specific bits in the collision register (used by collXX_XX) */
bool collision(CollisionBit id) const;
string audFreq(uInt8 div);
string booleanWithLabel(string label, bool value);

Some files were not shown because too many files have changed in this diff Show More