Compare commits

..

No commits in common. "master" and "6.5.2" have entirely different histories.

1044 changed files with 82084 additions and 173543 deletions

View File

@ -1,79 +0,0 @@
---
name: Build
on:
pull_request:
push:
permissions: {}
jobs:
linux:
name: Linux
runs-on: ubuntu-latest
env:
SDL3_VERSION: 3.2.14
steps:
- name: Check out the repository
uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8
- name: Install SDL3
run: |
wget https://github.com/libsdl-org/SDL/releases/download/release-${SDL3_VERSION}/SDL3-${SDL3_VERSION}.tar.gz
tar -xzf SDL3-${SDL3_VERSION}.tar.gz
mv SDL3-${SDL3_VERSION} SDL3
cd SDL3
cmake -DCMAKE_INSTALL_PREFIX="`pwd`/prefix" -DSDL_UNIX_CONSOLE_BUILD=ON .
make -j2 install
- name: Build Stella
run: |
CXXFLAGS="-I `pwd`/SDL3/prefix/include -O2 -g" PKG_CONFIG_PATH="`pwd`/SDL3/prefix/lib/pkgconfig/" ./configure
make -j2 all
macos:
name: macOS
runs-on: macos-latest
env:
SDL3_VERSION: 3.2.14
steps:
- uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: '16.2'
- name: Check out the repository
uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8
- name: Install SDL3
run: |
wget https://github.com/libsdl-org/SDL/releases/download/release-${SDL3_VERSION}/SDL3-${SDL3_VERSION}.dmg
hdiutil attach SDL3-${SDL3_VERSION}.dmg
mkdir -p src/os/macos/Frameworks
cp -Rv /Volumes/SDL3/SDL3.xcframework src/os/macos/Frameworks
hdiutil detach /Volumes/SDL3
- name: Build Stella
run: |
cd src/os/macos
xcodebuild
windows:
name: Windows
runs-on: windows-latest
strategy:
matrix:
platform: [x64]
env:
Platform: ${{ matrix.platform }}
SDL3_version: 3.2.14
steps:
- name: Check out the repository
uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8
- name: Set up MSBUILD
uses: microsoft/setup-msbuild@34cfbaee7f672c76950673338facd8a73f637506
- name: Install SDL3
shell: cmd
run: |
curl -o "C:\SDL3-devel.zip" "https://www.libsdl.org/release/SDL3-devel-%SDL3_version%-VC.zip"
7z x "C:\SDL3-devel.zip" -o"C:\"
xcopy /S "C:\SDL3-%SDL3_version%\include" src\common
if %Platform%==x64 xcopy /S "C:\SDL3-%SDL3_version%\lib\x64" src\os\windows
- name: Build Stella
run: |
msbuild src\os\windows\Stella.sln

20
.gitignore vendored
View File

@ -5,15 +5,12 @@ src/**/*.so
src/**/*.dylib
src/**/*.dll
src/**/*.o
src/**/*.d
src/**/*.obj
src/**/*.tlog
out
out.pgo
out.pgen
out.test
stella
stella-test
stella-pgo
stella-pgo-generate
*.diff
@ -21,18 +18,15 @@ project.xcworkspace/
xcuserdata/
.DS_Store
build/
src/os/macos/M6502.ins
src/macosx/M6502.ins
*.dSYM
.vscode/c_cpp_properties.json
.vscode/settings.json
src/os/windows/sdl/*
src/os/windows/sdl3/*
src/os/windows/x64/*
src/os/windows/Win32/*
src/os/windows/Stella.vcxproj.user
src/os/windows/*.bak
src/os/libretro/x64/*
src/os/libretro/Stella.vcxproj.user
src/windows/sdl/*
src/windows/x64/*
src/windows/Win32/*
src/windows/Stella.vcxproj.user
src/windows/*.bak
.vs/*
.tgitconfig
src/**/*.psess
@ -44,5 +38,3 @@ src/tools/fonts/*
a.out
*.json
*.sqlite3
*.bak
debian/files

View File

@ -1,148 +1,60 @@
# DESCRIPTION: GitLab CI/CD for libRetro (NOT FOR GitLab-proper)
##############################################################################
################################# BOILERPLATE ################################
##############################################################################
# Core definitions
.core-defs:
variables:
JNI_PATH: src/os/libretro
MAKEFILE_PATH: src/os/libretro
JNI_PATH: src/libretro
MAKEFILE_PATH: src/libretro
CORENAME: stella
# Inclusion templates, required for the build to work
include:
################################## DESKTOPS ################################
# Windows 64-bit
- template: Jobs/Code-Quality.gitlab-ci.yml
- project: 'libretro-infrastructure/ci-templates'
file: '/windows-x64-mingw.yml'
# Linux 64-bit
file: '/libnx-static.yml'
- project: 'libretro-infrastructure/ci-templates'
file: '/linux-x64.yml'
# MacOS 64-bit
- project: 'libretro-infrastructure/ci-templates'
file: '/osx-x64.yml'
# MacOS ARM 64-bit
- project: 'libretro-infrastructure/ci-templates'
file: '/osx-arm64.yml'
################################## CELLULAR ################################
# Android
file: '/windows-x64-mingw.yml'
- project: 'libretro-infrastructure/ci-templates'
file: '/android-jni.yml'
# iOS
- project: 'libretro-infrastructure/ci-templates'
file: '/ios-arm64.yml'
# iOS (armv7)
- project: 'libretro-infrastructure/ci-templates'
file: '/ios9.yml'
################################## CONSOLES ################################
# Nintendo Switch
- project: 'libretro-infrastructure/ci-templates'
file: '/libnx-static.yml'
# tvOS (AppleTV)
- project: 'libretro-infrastructure/ci-templates'
file: '/tvos-arm64.yml'
#################################### MISC ##################################
# Stages for building
stages:
- build-prepare
- build-shared
- build-static
- test
#Desktop
libretro-build-linux-x64:
extends:
- .libretro-linux-x64-make-default
- .core-defs
##############################################################################
#################################### STAGES ##################################
##############################################################################
#
################################### DESKTOPS #################################
# Windows 64-bit
libretro-build-windows-x64:
extends:
- .libretro-windows-x64-mingw-make-default
- .core-defs
# Linux 64-bit
libretro-build-linux-x64:
# Android
android-armeabi-v7a:
extends:
- .libretro-linux-x64-make-default
- .core-defs
image: $CI_SERVER_HOST:5050/libretro-infrastructure/libretro-build-amd64-ubuntu:latest
before_script:
- export NUMPROC=$(($(nproc)/5))
- sudo apt-get update -qy
- sudo apt-get install -qy software-properties-common
- sudo add-apt-repository -y ppa:savoury1/build-tools
- sudo add-apt-repository -y ppa:savoury1/gcc-defaults-12
- sudo apt-get update -qy
- sudo apt-get install -qy gcc-12 g++-12
# This container's existing installations of gcc and CMake are way too old
variables:
CC: /usr/bin/gcc-12
CXX: /usr/bin/g++-12
CXXFLAGS: -Wno-deprecated-declarations # Deprecation warnings aren't helpful on the libretro Gitlab
# MacOS 64-bit
libretro-build-osx-x64:
tags:
- mac-apple-silicon
extends:
- .libretro-osx-x64-make-default
- .libretro-android-jni-armeabi-v7a
- .core-defs
# MacOS ARM 64-bit
libretro-build-osx-arm64:
tags:
- mac-apple-silicon
android-arm64-v8a:
extends:
- .libretro-osx-arm64-make-default
- .libretro-android-jni-arm64-v8a
- .core-defs
################################### CELLULAR #################################
# Android ARMv7a
# android-armeabi-v7a:
# extends:
# - .libretro-android-jni-armeabi-v7a
# - .core-defs
# Android ARMv8a
# android-arm64-v8a:
# extends:
# - .libretro-android-jni-arm64-v8a
# - .core-defs
# Android 64-bit x86
# android-x86_64:
# extends:
# - .libretro-android-jni-x86_64
# - .core-defs
# iOS
libretro-build-ios-arm64:
tags:
- mac-apple-silicon
android-x86_64:
extends:
- .libretro-ios-arm64-make-default
- .libretro-android-jni-x86_64
- .core-defs
# tvOS
libretro-build-tvos-arm64:
android-x86:
extends:
- .libretro-tvos-arm64-make-default
- .libretro-android-jni-x86
- .core-defs
################################### CONSOLES #################################
# Nintendo Switch
# libretro-build-libnx-aarch64:
# extends:
# - .libretro-libnx-static-retroarch-master
# - .core-defs
# Static
libretro-build-libnx-aarch64:
extends:
- .libretro-libnx-static-retroarch-master
- .core-defs

63
.travis.yml Normal file
View File

@ -0,0 +1,63 @@
# Build matrix / environment variables are explained on:
# http://about.travis-ci.org/docs/user/build-configuration/
# This file can be validated on: http://lint.travis-ci.org/
language: cpp
matrix:
include:
- os: linux
dist: xenial
compiler: gcc
env: GCC=9 CC=gcc-9 CXX=g++-9
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- gcc-9
- g++-9
update: true
- os: osx
osx_image: xcode11.3
compiler: clang
addons:
homebrew:
update: true
install:
- |
old_cwd=$(pwd)
cd ~
if [[ "$HOST" == macosx-* ]]; then
curl -O https://www.libsdl.org/release/SDL2-2.0.10.tar.gz
tar xzf SDL2-2.0.10.tar.gz
cd SDL2-2.0.10/Xcode/SDL
sed -i -e 's/@rpath//g' SDL.xcodeproj/project.pbxproj
xcodebuild -configuration Release
mkdir -p ~/Library/Frameworks/
ln -s `pwd`/build/Release/SDL2.framework ~/Library/Frameworks/
else
curl -O https://www.libsdl.org/release/SDL2-2.0.10.tar.gz
tar xzf SDL2-2.0.10.tar.gz
cd SDL2-2.0.10
mkdir build
cd build
../configure
make
sudo make install
fi
cd $old_cwd
script:
- |
./configure
make all

15
.vscode/settings.json vendored
View File

@ -14,7 +14,6 @@
"C_Cpp.intelliSenseEngine": "Default",
"files.insertFinalNewline": true,
"files.associations": {
"*.h": "cpp",
"__functional_base": "cpp",
"array": "cpp",
"istream": "cpp",
@ -104,18 +103,6 @@
"version": "cpp",
"shared_mutex": "cpp",
"compare": "cpp",
"concepts": "cpp",
"__verbose_abort": "cpp",
"any": "cpp",
"charconv": "cpp",
"csignal": "cpp",
"execution": "cpp",
"numbers": "cpp",
"span": "cpp",
"unordered_set": "cpp",
"variant": "cpp",
"hash_map": "cpp",
"format": "cpp",
"*.inc": "cpp"
"concepts": "cpp"
}
}

View File

@ -9,7 +9,7 @@
SSSS ttt eeeee llll llll aaaaa
===========================================================================
Release 7.0 for Linux, macOS and Windows
Release 6.5.2 for Linux, macOS and Windows
===========================================================================
The Atari 2600 Video Computer System (VCS), introduced in 1977, was the
@ -21,21 +21,25 @@ all of your favourite Atari 2600 games again! Stella was originally
developed for Linux by Bradford W. Mott, however, it has been ported to a
number of other platforms and is currently maintained by Stephen Anthony.
This is the 7.0 release of Stella for Linux, macOS and Windows. The
This is the 6.5.2 release of Stella for Linux, macOS and Windows. The
distributions currently available are:
* Binary for Windows 7/8/10/11 :
Stella-7.0-x64.exe (64-bit EXE installer)
Stella-7.0-windows.zip (64 bit ZIP version)
* Binaries for Windows 7/8/10 :
Stella-6.5.2-win32.exe (32-bit EXE installer)
Stella-6.5.2-x64.exe (64-bit EXE installer)
Stella-6.5.2-windows.zip (32/64 bit versions)
* Binary distribution for macOS 10.13 and above :
Stella-7.0-macos.dmg (ARM M1 and 64-bit Intel)
* Binary distribution for macOS 10.7 and above :
Stella-6.5.2-macos.dmg (64-bit Intel)
* Binary distribution for 64-bit Ubuntu :
stella_7.0-1_amd64.deb
stella_6.5.2-1_amd64.deb
* Binary distribution for 64-bit Redhat :
stella-6.5.2-2.x86_64.rpm
* Source code distribution for all platforms :
stella-7.0-src.tar.xz
stella-6.5.2-src.tar.xz
Distribution Site

View File

@ -12,204 +12,6 @@
Release History
===========================================================================
7.x to 8.0 (xxx x, 202x)
* Ported Stella to SDL3
* Added option for switching Stella's theme in sync with OS
7.0 to 7.1 (xxx x, 202x)
* Enhanced PAL-60 detection, searches for signature (e.g. PAL60) in ROM
* Enhanced VSYNC emulation, considers VBLANK now too
* Added developer option for disabling PlusROM support
6.7.1 to 7.0 (October 5, 2024)
* Enhanced ROM launcher to allow multiple images per ROM.
* Made heaps of additional images available for the ROM launcher.
* Added searching by filename for ROM launcher images.
* Added option to start random ROM.
* Added automatically enabled phosphor modes.
* Enhanced Game Properties dialog for multigame ROMs.
* Added 2nd UI theme and hotkey for toggling UI theme.
* Added bezel support (incl. Sinden Lightgun).
* Added optional type format detection based on colors used.
* Added Joy2B+ controller support.
* Added auto detection for QuadTari attached controllers.
* Enhanced Kid Vid support to play tape audio.
* Added port selection, used for controller default mapping.
* Added missing PlusROM support for E7 bankswitching.
* Enhanced movie cart (MVC) support.
* Accelerated emulation up to ~15% (ARM).
* Added limited GameLine Master Module bankswitching support.
* Added 03E0 bankswitching for Brazilian Parker Bros ROMs.
* Added WF8 bankswitching used by some certain Coleco white carts.
* Added JANE bankswitching used by Coleco's Tarzan prototype.
* Added ELF mapper for Mattress Monkeys.
* Added BUS bankswitching support for some older demos.
* Fixed broken 7800 pause key support.
* Added developer option for random hotspot peek values.
* Added user defined CPU cycle timers to debugger.
* Removed 'launcherroms' option, since it was causing some issues.
* Codebase now uses C++20 features, which means a minimum of gcc-11
or clang-10 for Linux/Mac, and Visual Studio 2022 for Windows.
-Have fun!
6.7 to 6.7.1 (January 15, 2024)
* Fixed broken mouse and Stelladaptor input for Driving Controller.
* For UNIX systems: Now defaults to using system-installed libsqlite3
when available, and fixes delay on exiting app experienced on some
systems.
6.6 to 6.7 (June 13, 2022)
* IMPORTANT NOTES:
- Because of fixes to JSON handling, all remappings will be reset
to defaults; if you had custom mappings, they will need to be
re-entered again.
- Because of internal changes, all state files are now invalid.
* Completely reworked the file launcher:
- Redesigned user interface
- Added tracking of user favorites, recently played and most popular
games
- Added virtual directories for selecting tracked games
- Added quick path navigation
- Added navigation history
- Added icons for files and directories
- Added option to show/hide file extensions
- Extended context menu and shortcuts
- Fixed sluggish behaviour when reading large and/or invalid files
* Added hotkey display to tooltips.
* Added option to automatically pause emulation when focus is lost.
* Added option to toggle autofire mode.
* Improved controller mappings for Paddles.
* Improved controller mappings for Driving controllers.
* Improved Mindlink support.
* Added another oddball TIA glitch option for score mode color.
* Enhanced TV jitter emulation (TODO: doc).
* Enhanced support for CDFJ+ bankswitching type.
* Added 0FA0 bankswitching for Fotomania ROMs.
* Added ARM chip auto detection.
* Extended support for older BUS (experimental) ROMs that worked
with an older, obsolete version of the BUS scheme; special thanks
to SpiceWare for the code.
* Fixed Stella crash due to invalid ZIP files.
* Fixed TV mode auto detection in some ARM ROMs.
* Fixed color loss when switching TV mode from/to PAL.
* Fixed score mode glitch emulation corner case.
* Fixed state messages staying on screen forever.
* Added M1 support for the macOS build.
* Debugger improvements:
- added PlusROM information
- fixed patching code in ZP-RAM
- improved bank origin detection
* Updated internal ROM properties database to ROM-Hunter version 17
(thanks go to RomHunter for his tireless research in this area).
Related to this, updated the snapshot collection.
6.5.3 to 6.6 (November 16, 2021)
* Added preliminary PlusROM support for saving high scores.
* Added preliminary support for 'MVC' bankswitching scheme by
Rob Bairos.
* Added web links for many games.
* Added dead zone and linearity settings for analog controllers.
* Added 'Check for Update' button to Help dialog.
* Added different mask patterns for scanline emulation.
* Fixed MindLink controller.
* Fixed SaveKey not working with QuadTari.
* Added TIA randomization on startup option.
* Added different debug color luminances for player and missile copies.
* Added hotkeys for TV roll speed and toggling 'Developer settings' sets.
* Debugger: enhanced prompt's auto complete and history.
* Debugger: added optional logging of breaks and traps.
* Debugger: added Thumb cycle counting.
6.5.2 to 6.5.3 (April 20, 2021)
* Added context-sensitive help.
* Improved support of multiple monitors with different resolutions.
* Improved analog input reading (Paddles, Keyboards...).
* Fixed QuadTari support for controller types other than Joysticks.
* Fixed palette and TV effects saving for Retron77.
* Fixed immediate disassembling when switching options in debugger.
6.5.1 to 6.5.2 (February 25, 2021)
* Fixed broken Driving Controller support for Stelladaptor/2600-daptor
@ -221,6 +23,8 @@
* Added CPU usage stats to ARM cart classes debug widgets.
-Have fun!
6.5 to 6.5.1 (January 24, 2021)

View File

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

View File

@ -8,7 +8,7 @@
## SS SS tt ee ll ll aa aa
## SSSS ttt eeeee llll llll aaaaa
##
## Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
## Copyright (c) 1995-2021 by Bradford W. Mott, Stephen Anthony
## and the Stella Team
##
## See the file "License.txt" for information on usage and redistribution of
@ -26,7 +26,6 @@ LDFLAGS := -pthread
INCLUDES :=
LIBS :=
OBJS :=
OBJS_TEST :=
PROF :=
MODULES :=
@ -48,53 +47,28 @@ else
CFLAGS:= -O2
endif
ifndef CXXFLAGS_TEST
CXXFLAGS_TEST := $(CXXFLAGS)
endif
ifndef CFLAGS_TEST
CFLAGS_TEST := $(CFLAGS)
endif
ifndef LDFLAGS_TEST
LDFLAGS_TEST := $(LDFLAGS)
endif
CXXFLAGS+= -Wall -Wextra -Wno-unused-parameter
CFLAGS+= -Wall -Wextra -Wno-unused-parameter
CXXFLAGS_TEST+= -Wall -Wextra -Wno-unused-parameter
CFLAGS_TEST+= -Wall -Wextra -Wno-unused-parameter
ifdef HAVE_GCC
CXXFLAGS+= -Wno-multichar -Wunused -Woverloaded-virtual -std=c++20
CFLAGS+= -Wunused
CXXFLAGS_TEST+= -Wno-multichar -Wunused -Woverloaded-virtual -std=c++20
CFLAGS_TEST+= -Wno-multichar -Wunused
CXXFLAGS+= -Wno-multichar -Wunused -Woverloaded-virtual -Wnon-virtual-dtor -std=c++17
CFLAGS+= -Wno-multichar -Wunused
endif
ifdef HAVE_CLANG
CXXFLAGS+= -Wunused -Woverloaded-virtual -std=c++20
CFLAGS+= -Wunused
CXXFLAGS_TEST+= -Wno-multichar -Wunused -Woverloaded-virtual -std=c++20
CFLAGS_TEST+= -Wno-multichar -Wunused
CXXFLAGS+= -Wno-multichar -Wunused -Woverloaded-virtual -Wnon-virtual-dtor -std=c++17
CFLAGS+= -Wno-multichar -Wunused
endif
ifdef CLANG_WARNINGS
EXTRA_WARN=-Wno-c++98-compat-pedantic -Wno-undefined-func-template \
EXTRA_WARN=-Weverything -Wno-c++17-extensions -Wno-c++98-compat-pedantic \
-Wno-switch-enum -Wno-conversion -Wno-covered-switch-default \
-Wno-documentation -Wno-float-equal \
-Wno-inconsistent-missing-destructor-override -Wno-float-equal \
-Wno-exit-time-destructors -Wno-global-constructors -Wno-weak-vtables \
-Wno-four-char-constants -Wno-padded -Wno-reserved-identifier \
-Wno-duplicate-enum -Wno-unsafe-buffer-usage
-Wno-four-char-constants -Wno-padded
CXXFLAGS+= $(EXTRA_WARN)
CFLAGS+= $(EXTRA_WARN)
CXXFLAGS_TEST+= $(EXTRA_WARN)
CFLAGS_TEST+= $(EXTRA_WARN)
endif
ifdef PROFILE
@ -104,8 +78,8 @@ ifdef PROFILE
endif
ifdef DEBUG
CXXFLAGS += -g -Wp,-D_GLIBCXX_DEBUG
CFLAGS += -g -Wp,-D_GLIBCXX_DEBUG
CXXFLAGS += -g
CFLAGS += -g
else
ifdef HAVE_GCC
CXXFLAGS+= -fomit-frame-pointer
@ -133,14 +107,12 @@ ifdef STELLA_BUILD_ROOT
else
OBJECT_ROOT := out
endif
OBJECT_ROOT_TEST := out.test
OBJECT_ROOT_PROFILE_GENERERATE := out.pgen
OBJECT_ROOT_PROFILE_USE := out.pgo
EXECUTABLE := stella$(EXEEXT)
EXECUTABLE_PROFILE_GENERATE := stella-pgo-generate$(EXEEXT)
EXECUTABLE_PROFILE_USE := stella-pgo$(EXEEXT)
EXECUTABLE_TEST := stella-test$(EXEEXT)
PROFILE_DIR = $(CURDIR)/test/roms/profile
PROFILE_OUT = $(PROFILE_DIR)/out
@ -173,17 +145,14 @@ ifdef HAVE_GCC
CFLAGS_PROFILE_USE += -fprofile-use -fprofile-dir=$(PROFILE_OUT)
LDFLAGS_PROFILE_GENERATE += -fprofile-generate
STELLA_PROFILE_GENERATE := $(STELLA_PROFILE_GENERATE) && \
(rm -fr $(PROFILE_OUT)/$(OBJECT_ROOT_PROFILE_USE) || true) && \
(mv $(PROFILE_OUT)/$(OBJECT_ROOT_PROFILE_GENERERATE) $(PROFILE_OUT)/$(OBJECT_ROOT_PROFILE_USE) || true)
rm -fr $(PROFILE_OUT)/$(OBJECT_ROOT_PROFILE_USE) && \
mv $(PROFILE_OUT)/$(OBJECT_ROOT_PROFILE_GENERERATE) $(PROFILE_OUT)/$(OBJECT_ROOT_PROFILE_USE)
endif
all: $(EXECUTABLE)
pgo: $(EXECUTABLE_PROFILE_USE)
test: $(EXECUTABLE_TEST)
./$(EXECUTABLE_TEST)
######################################################################
# Various minor settings
######################################################################
@ -206,8 +175,8 @@ MODULES += \
src/emucore \
src/emucore/tia \
src/emucore/tia/frame-manager \
src/emucore/elf \
src/common/repository/sqlite
src/common/repository/sqlite \
src/sqlite
######################################################################
# The build rules follow - normally you should have no need to
@ -225,7 +194,6 @@ DEPDIRS = $(addsuffix /$(DEPDIR),$(MODULE_DIRS))
DEPFILES =
OBJ=$(addprefix $(OBJECT_ROOT)/,$(OBJS))
OBJ_TEST=$(addprefix $(OBJECT_ROOT_TEST)/,$(OBJS_TEST))
OBJ_PROFILE_GENERATE=$(addprefix $(OBJECT_ROOT_PROFILE_GENERERATE)/,$(OBJS))
OBJ_PROFILE_USE=$(addprefix $(OBJECT_ROOT_PROFILE_USE)/,$(OBJS))
@ -233,9 +201,6 @@ OBJ_PROFILE_USE=$(addprefix $(OBJECT_ROOT_PROFILE_USE)/,$(OBJS))
$(EXECUTABLE): $(OBJ)
$(LD) $(LDFLAGS) $(PRE_OBJS_FLAGS) $+ $(POST_OBJS_FLAGS) $(LIBS) $(PROF) -o $@
$(EXECUTABLE_TEST): $(OBJ_TEST)
$(LD) $(LDFLAGS_TEST) $(PRE_OBJS_FLAGS) $+ $(POST_OBJS_FLAGS) $(LIBS) -lgtest -lgtest_main -o $@
$(EXECUTABLE_PROFILE_GENERATE): $(OBJ_PROFILE_GENERATE)
$(LD) $(LDFLAGS_PROFILE_GENERATE) $(PRE_OBJS_FLAGS) $+ $(POST_OBJS_FLAGS) $(LIBS) $(PROF) -o $@
@ -250,7 +215,7 @@ clean:
-$(RM) -fr \
$(OBJECT_ROOT) $(OBJECT_ROOT_PROFILE_GENERERATE) $(OBJECT_ROOT_PROFILE_USE) \
$(EXECUTABLE) $(EXECUTABLE_PROFILE_GENERATE) $(EXECUTABLE_PROFILE_USE) \
$(OBJECT_ROOT_TEST) $(PROFILE_OUT) $(PROFILE_STAMP)
$(PROFILE_OUT) $(PROFILE_STAMP)
.PHONY: all clean dist distclean
@ -278,16 +243,6 @@ $(OBJECT_ROOT)/%.o: %.cxx
$(merge_dep)
$(OBJECT_ROOT)/%.o: %.c
$(create_dir)
$(CC) $(CXX_UPDATE_DEP_FLAG) $(CFLAGS_TEST) $(CPPFLAGS) -c $(<) -o $@
$(merge_dep)
$(OBJECT_ROOT_TEST)/%.o: %.cxx
$(create_dir)
$(CXX) $(CXX_UPDATE_DEP_FLAG) $(CXXFLAGS_TEST) $(CPPFLAGS) -c $(<) -o $@
$(merge_dep)
$(OBJECT_ROOT_TEST)/%.o: %.c
$(create_dir)
$(CC) $(CXX_UPDATE_DEP_FLAG) $(CFLAGS) $(CPPFLAGS) -c $(<) -o $@
$(merge_dep)
@ -325,14 +280,6 @@ $(OBJECT_ROOT)/%.o: %.c
$(create_dir)
$(CC) $(CXX_UPDATE_DEP_FLAG) $(CFLAGS) $(CPPFLAGS) -c $(<) -o $@
$(OBJECT_ROOT_TEST)/%.o: %.cxx
$(create_dir)
$(CXX) $(CXX_UPDATE_DEP_FLAG) $(CXXFLAGS_TEST) $(CPPFLAGS) -c $(<) -o $@
$(OBJECT_ROOT_TEST)/%.o: %.c
$(create_dir)
$(CC) $(CXX_UPDATE_DEP_FLAG) $(CFLAGS_TEST) $(CPPFLAGS) -c $(<) -o $@
$(OBJECT_ROOT_PROFILE_GENERERATE)/%.o: %.cxx
$(create_dir)
$(CXX) $(CXX_UPDATE_DEP_FLAG) $(CXXFLAGS_PROFILE_GENERATE) $(CPPFLAGS) -c $(<) -o $@
@ -370,11 +317,11 @@ install: all
$(INSTALL) -d "$(DESTDIR)$(BINDIR)"
$(INSTALL) -c -m 755 "$(srcdir)/stella$(EXEEXT)" "$(DESTDIR)$(BINDIR)/stella$(EXEEXT)"
$(INSTALL) -d "$(DESTDIR)$(DOCDIR)"
$(INSTALL) -c -m 644 "$(srcdir)/Announce.txt" "$(srcdir)/Changes.txt" "$(srcdir)/Copyright.txt" "$(srcdir)/License.txt" "$(srcdir)/README-SDL.txt" "$(srcdir)/README.md" "$(srcdir)/Todo.txt" "$(srcdir)/docs/index.html" "$(srcdir)/docs/debugger.html" "$(DESTDIR)$(DOCDIR)/"
$(INSTALL) -c -m 644 "$(srcdir)/Announce.txt" "$(srcdir)/Changes.txt" "$(srcdir)/Copyright.txt" "$(srcdir)/License.txt" "$(srcdir)/README-SDL.txt" "$(srcdir)/Readme.txt" "$(srcdir)/Todo.txt" "$(srcdir)/docs/index.html" "$(srcdir)/docs/debugger.html" "$(DESTDIR)$(DOCDIR)/"
$(INSTALL) -d "$(DESTDIR)$(DOCDIR)/graphics"
$(INSTALL) -c -m 644 $(wildcard $(srcdir)/docs/graphics/*.png) "$(DESTDIR)$(DOCDIR)/graphics"
$(INSTALL) -d "$(DESTDIR)$(DATADIR)/applications"
$(INSTALL) -c -m 644 "$(srcdir)/src/os/unix/stella.desktop" "$(DESTDIR)$(DATADIR)/applications"
$(INSTALL) -c -m 644 "$(srcdir)/src/unix/stella.desktop" "$(DESTDIR)$(DATADIR)/applications"
$(INSTALL) -d "$(DESTDIR)$(DATADIR)/icons/hicolor/16x16/apps"
$(INSTALL) -d "$(DESTDIR)$(DATADIR)/icons/hicolor/22x22/apps"
$(INSTALL) -d "$(DESTDIR)$(DATADIR)/icons/hicolor/24x24/apps"
@ -410,7 +357,7 @@ src/emucore/M6502.ins: src/emucore/M6502.m4
m4 src/emucore/M6502.m4 > src/emucore/M6502.ins
# Special rule for windows icon stuff (there's probably a better way to do this ...)
src/os/windows/stella_icon.o: src/os/windows/stella.ico src/os/windows/stella.rc
windres --include-dir src/os/windows src/os/windows/stella.rc src/os/windows/stella_icon.o
src/windows/stella_icon.o: src/windows/stella.ico src/windows/stella.rc
windres --include-dir src/windows src/windows/stella.rc src/windows/stella_icon.o
.PHONY: deb bundle test install uninstall

View File

@ -15,10 +15,6 @@ Please check the list of known issues first (see below) before reporting new one
If you encounter any issues, please open a new issue on the project
[issue tracker](https://github.com/stella-emu/stella/issues).
Note: Please do **not** report issues regarding platforms other than PC and RetroN 77
(e.g. Libretro) here. The Stella Team is not responsible for these forks and cannot
help with them.
# Known issues
Please check out the [issue tracker](https://github.com/stella-emu/stella/issues) for

10
Readme.txt Normal file
View File

@ -0,0 +1,10 @@
Stella is a multi-platform Atari 2600 VCS emulator which allows you to
play all of your favourite Atari 2600 games on your PC. You'll find the
Stella Users Manual in the docs subdirectory. If you'd like to verify
that you have the latest release of Stella, visit the Stella Website at:
https://stella-emu.github.io
Enjoy,
The Stella Team

32
appveyor.yml Normal file
View File

@ -0,0 +1,32 @@
image: Visual Studio 2019
shallow_clone: true
environment:
matrix:
- Platform: x64
- Platform: Win32
Configuration: Release
SDL2_version: 2.0.12
install:
- cmd: |
curl -o "C:\SDL2-devel.zip" "https://www.libsdl.org/release/SDL2-devel-%SDL2_version%-VC.zip"
7z x "C:\SDL2-devel.zip" -o"C:\"
xcopy /S "C:\SDL2-%SDL2_version%\include" src\common
if %Platform%==x64 xcopy /S "C:\SDL2-%SDL2_version%\lib\x64" src\windows
if %Platform%==Win32 xcopy /S "C:\SDL2-%SDL2_version%\lib\x86" src\windows
build_script:
- cmd: |
msbuild src\windows\Stella.sln
artifacts:
- path: '**\stella.exe'

View File

@ -4,9 +4,7 @@
# contains the module name, a trick we use so we can keep multiple different
# module object lists, one for each module.
MODULE_OBJS-$(MODULE) := $(MODULE_OBJS)
MODULE_TEST_OBJS-$(MODULE) := $(MODULE_TEST_OBJS)
# If not building as a plugin, add the object files to the main OBJS list
#OBJS += $(MODULE_LIB-$(MODULE))
OBJS += $(MODULE_OBJS)
OBJS_TEST += $(MODULE_TEST_OBJS)

1595
config.guess vendored

File diff suppressed because it is too large Load Diff

3514
config.sub vendored

File diff suppressed because it is too large Load Diff

177
configure vendored
View File

@ -6,23 +6,13 @@
# * command line options to...
# - override the host settings (for cross compiles
# - whether to do a debug build (with -g) or an optimized build (-O3 etc.)
# * detect whether the chosen backend is available
# * detect whether the chosen backend is available (e.g. call sdl2-config)
# * ....
# use environment vars if set
CXXFLAGS="$CXXFLAGS $CPPFLAGS"
if test -n "$CXXFLAGS_TEST"; then
CXXFLAGS_TEST="$CXXFLAGS_TEST $CPPFLAGS"
else
CXXFLAGS_TEST="$CXXFLAGS"
fi
if test -z "$LDFLAGS_TEST"; then
LDFLAGS_TEST="$LDFLAGS"
fi
# default option behaviour yes/no
_build_gui=yes
_build_windowed=yes
@ -30,22 +20,18 @@ _build_sound=yes
_build_debugger=yes
_build_joystick=yes
_build_cheats=yes
_build_httplib=yes
_build_png=yes
_build_sqlite3=yes
_build_zip=yes
_build_static=no
_build_profile=no
_build_debug=no
_build_release=no
_build_mold=no
# more defaults
_ranlib=ranlib
_install=install
_ar="ar cru"
_strip=strip
_pkg_config=pkg-config
_mkdir="mkdir -p"
_echo=printf
_cat=cat
@ -54,6 +40,7 @@ _rm_rec="$_rm -r"
_zip="zip -q"
_cp=cp
_windowspath=""
_sdlconfig=sdl2-config
_sdlpath="$PATH"
_prefix=/usr/local
@ -227,15 +214,11 @@ Optional Features:
--disable-profile
--enable-debug build with debugging symbols [disabled]
--disable-debug
--enable-release build with all optimizations, for final release [disabled]
--disable-release
--use-mold-linker use mold linker (experimental) [disabled]
Optional Libraries:
--with-sdl-prefix=DIR Prefix where the sdl2-config script is installed (optional)
--with-libpng-prefix=DIR Prefix where libpng is installed (optional)
--with-zlib-prefix=DIR Prefix where zlib is installed (optional)
--with-gtest-prefix=DIR Prefix where googletest is installed (optional)
Some influential environment variables:
LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
@ -244,8 +227,6 @@ Some influential environment variables:
CXXFLAGS C++ compiler flags
CPPFLAGS C++ preprocessor flags, e.g. -I<include dir> if you have
headers in a nonstandard directory <include dir>
LDFLAGS_TEST linker flags for unit tests
CXXFLAGS_TEST C++ compiler flags for unit tests
EOF
exit 0
@ -279,7 +260,6 @@ for ac_option in $@; do
--disable-debug) _build_debug=no ;;
--enable-release) _build_release=yes ;;
--disable-release) _build_release=no ;;
--use-mold-linker) _build_mold=yes ;;
--with-sdl-prefix=*)
arg=`echo $ac_option | cut -d '=' -f 2`
_sdlpath="$arg:$arg/bin"
@ -293,11 +273,6 @@ for ac_option in $@; do
_prefix=`echo $ac_option | cut -d '=' -f 2`
ZLIB_CFLAGS="-I$_prefix/include"
ZLIB_LIBS="-L$_prefix/lib"
;;
--with-gtest-prefix=*)
_prefix=`echo $ac_option | cut -d '=' -f 2`
CXXFLAGS_TEST="$CXXFLAGS_TEST -I$_prefix/include"
LDFLAGS_TEST="$LDFLAGS_TEST -L$_prefix/lib"
;;
--host=*)
_host=`echo $ac_option | cut -d '=' -f 2`
@ -335,22 +310,20 @@ case $_host in
# _host_os=amigaos
# _host_cpu=ppc
# ;;
retron77)
_host_os=retron77
;;
mingw32-cross)
_host_os=mingw32msvc
_host_cpu=i386
_host_prefix=i386-mingw32msvc
;;
"")
*)
guessed_host=`$_srcdir/config.guess`
_host_cpu=`echo $guessed_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
_host_os=`echo $guessed_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'`
_host_vendor=`echo $guessed_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'`
;;
*)
_host_cpu=`echo "$_host" | sed 's/^\([^-]*\)-.*/\1/'`
_host_os=`echo "$_host" | sed 's/-\([^-]*\)-[^-]*$/\1/'`
_host_prefix="$_host"
;;
esac
#
@ -366,6 +339,9 @@ arm-riscos-aof)
psp)
EXEEXT=".elf"
;;
gp2x)
EXEEXT=""
;;
*)
EXEEXT=""
;;
@ -398,7 +374,7 @@ else
fi
for compiler in $compilers; do
if test_compiler "$compiler -std=c++20"; then
if test_compiler "$compiler -std=c++17"; then
CXX=$compiler
echo $CXX
break
@ -555,6 +531,13 @@ fi
if test -n "$_host"; then
# Cross-compiling mode - add your target here if needed
case "$_host" in
retron77)
echo "Compiling for $_host, disabling windowed mode, debugger and cheats."
_build_gui=yes
_build_windowed=no
_build_debugger=no
_build_cheats=no
;;
mingw32-cross)
echo "Cross-compiling for Windows using MinGW."
DEFINES="$DEFINES -DWIN32"
@ -620,9 +603,6 @@ fi
# Cross-compilers use their own commands for the following functions
if test -n "$_host_prefix"; then
_strip="$_host_prefix-$_strip"
if command -v "$_host_prefix-$_pkg_config" >/dev/null 2>&1; then
_pkg_config="$_host_prefix-$_pkg_config"
fi
fi
#
@ -636,7 +616,7 @@ if test "$_build_zip" = yes ; then
#include <zlib.h>
int main(void) { return strcmp(ZLIB_VERSION, zlibVersion()); }
EOF
cc_check $LDFLAGS $CXXFLAGS $ZLIB_CFLAGS $ZLIB_LIBS `$_pkg_config --libs zlib` && _zlib=yes
cc_check $LDFLAGS $CXXFLAGS $ZLIB_CFLAGS $ZLIB_LIBS -lz && _zlib=yes
if test "$_zlib" = yes ; then
echo "$_zlib"
@ -662,7 +642,7 @@ if test "$_build_png" = yes ; then
#include <png.h>
int main(void) { return printf("%s\n", PNG_HEADER_VERSION_STRING); }
EOF
cc_check $LDFLAGS $CXXFLAGS $LIBPNG_CFLAGS $LIBPNG_LIBS `$_pkg_config --libs libpng` && _libpng=yes
cc_check $LDFLAGS $CXXFLAGS $LIBPNG_CFLAGS $LIBPNG_LIBS `pkg-config --libs libpng` && _libpng=yes
if test "$_libpng" = yes ; then
echo "$_libpng"
@ -675,30 +655,6 @@ else
_build_png=no
fi
#
# Check for sqlite3
#
echocheck "libsqlite3"
if test "$_build_sqlite3" = yes ; then
_libsqlite3=no
cat > $TMPC << EOF
#include <stdio.h>
#include <sqlite3.h>
int main(void) { return printf("%s\n", SQLITE_VERSION); }
EOF
cc_check $LDFLAGS $CXXFLAGS `$_pkg_config --libs sqlite3` && _libsqlite3=yes
if test "$_libsqlite3" = yes ; then
echo "$_libsqlite3"
else
echo "built-in"
_build_sqlite3=yes
fi
else
echo "built-in"
_build_sqlite3=yes
fi
#
# figure out installation directories
#
@ -805,70 +761,62 @@ fi
#
# Now, add the appropriate defines/libraries/headers
#
#echo
#find_sdlconfig
echo
find_sdlconfig
SRC="src"
SRC_OS="$SRC/os"
SRC_LIB="$SRC/lib"
CORE="$SRC/emucore"
COMMON="$SRC/common"
TIA="$SRC/emucore/tia"
ELF="$SRC/emucore/elf"
TIA_FRAME_MANAGER="$SRC/emucore/tia/frame-manager"
TV="$SRC/common/tv_filters"
GUI="$SRC/gui"
DBG="$SRC/debugger"
DBGGUI="$SRC/debugger/gui"
YACC="$SRC/debugger/yacc"
YACC="$SRC/yacc"
CHEAT="$SRC/cheat"
LIBPNG="$SRC_LIB/libpng"
LIBJPG="$SRC_LIB/nanojpeg"
LIBJPGEXIF="$SRC_LIB/tinyexif"
ZLIB="$SRC_LIB/zlib"
LIBPNG="$SRC/libpng"
ZLIB="$SRC/zlib"
SQLITE_REPO="$SRC/common/repository/sqlite"
SQLITE_LIB="$SRC_LIB/sqlite"
JSON="$SRC_LIB/json"
HTTP_LIB="$SRC_LIB/httplib"
SQLITE_LIB="$SRC/sqlite"
JSON="$SRC/json"
INCLUDES="-I$CORE -I$COMMON -I$TV -I$TIA -I$TIA_FRAME_MANAGER -I$ELF -I$JSON -I$SQLITE_REPO"
INCLUDES="-I$CORE -I$COMMON -I$TV -I$TIA -I$TIA_FRAME_MANAGER -I$JSON -I$SQLITE_REPO -I$SQLITE_LIB"
#INCLUDES="$INCLUDES `$_sdlconfig --cflags`"
#if test "$_build_static" = yes ; then
# _sdl_conf_libs="--static-libs"
# LDFLAGS="-static $LDFLAGS"
#else
# _sdl_conf_libs="--libs"
#fi
#if test "$_libpng" = yes ; then #FIXME:
LIBS="$LIBS `$_pkg_config --libs sdl3`"
#fi
INCLUDES="$INCLUDES `$_sdlconfig --cflags`"
if test "$_build_static" = yes ; then
_sdl_conf_libs="--static-libs"
LDFLAGS="-static $LDFLAGS"
else
_sdl_conf_libs="--libs"
fi
LIBS="$LIBS `$_sdlconfig $_sdl_conf_libs`"
LD=$CXX
case $_host_os in
unix)
DEFINES="$DEFINES -DBSPF_UNIX"
MODULES="$MODULES $SRC_OS/unix"
INCLUDES="$INCLUDES -I$SRC_OS/unix"
MODULES="$MODULES $SRC/unix"
INCLUDES="$INCLUDES -I$SRC/unix"
;;
darwin)
DEFINES="$DEFINES -DBSPF_UNIX -DMACOS_KEYS"
MODULES="$MODULES $SRC_OS/unix"
INCLUDES="$INCLUDES -I$SRC_OS/unix"
MODULES="$MODULES $SRC/unix"
INCLUDES="$INCLUDES -I$SRC/unix"
if test "$have_clang" == yes; then
CXXFLAGS="$CXXFLAGS -Wno-poison-system-directories"
if test -n "$CXXFLAGS_TEST"; then
CXXFLAGS_TEST="$CXXFLAGS_TEST -Wno-poison-system-directories"
fi
fi
_libsqlite3=no
;;
retron77)
DEFINES="$DEFINES -DBSPF_UNIX -DRETRON77"
MODULES="$MODULES $SRC/unix $SRC/unix/r77"
INCLUDES="$INCLUDES -I$SRC/unix -I$SRC/unix/r77"
;;
win32)
DEFINES="$DEFINES -DBSPF_WINDOWS"
MODULES="$MODULES $SRC_OS/windows"
INCLUDES="$INCLUDES -I$SRC_OS/windows"
MODULES="$MODULES $SRC/windows"
INCLUDES="$INCLUDES -I$SRC/windows"
LIBS="$LIBS -lmingw32 -lwinmm"
;;
*)
@ -907,34 +855,20 @@ if test "$_build_cheats" = yes ; then
INCLUDES="$INCLUDES -I$CHEAT"
fi
if test "$_build_httplib" = yes ; then
DEFINES="$DEFINES -DHTTP_LIB_SUPPORT"
INCLUDES="$INCLUDES -I$HTTP_LIB"
fi
if test "$_build_png" = yes ; then
DEFINES="$DEFINES -DIMAGE_SUPPORT"
INCLUDES="$INCLUDES -I$LIBJPG -I$LIBJPGEXIF"
MODULES="$MODULES $LIBJPGEXIF"
DEFINES="$DEFINES -DPNG_SUPPORT"
if test "$_libpng" = yes ; then
LIBS="$LIBS `$_pkg_config --libs libpng`"
LIBS="$LIBS -lpng"
else
MODULES="$MODULES $LIBPNG"
INCLUDES="$INCLUDES -I$LIBPNG"
fi
fi
if test "$_libsqlite3" = yes ; then
LIBS="$LIBS `$_pkg_config --libs sqlite3`"
else
MODULES="$MODULES $SQLITE_LIB"
INCLUDES="$INCLUDES -I$SQLITE_LIB"
fi
if test "$_build_zip" = yes ; then
DEFINES="$DEFINES -DZIP_SUPPORT"
if test "$_zlib" = yes ; then
LIBS="$LIBS `$_pkg_config --libs zlib`"
LIBS="$LIBS -lz"
else
MODULES="$MODULES $ZLIB"
INCLUDES="$INCLUDES -I$ZLIB"
@ -953,24 +887,12 @@ if test "$_build_release" = no ; then
_build_release=
fi
if test "$_build_mold" = yes ; then
LDFLAGS="-fuse-ld=mold"
fi
# Workaround until we deal with autodetection of C compiler properly
# Or we remove C files from Stella entirely, by making them C++
if test -z "$CC"; then
CC=cc
fi
echo "Creating config.mak"
cat > config.mak << EOF
# -------- Generated by configure -----------
CC := $CC
CXX := $CXX
CXXFLAGS := $CXXFLAGS
CXXFLAGS_TEST := $CXXFLAGS_TEST
LD := $LD
LIBS += $LIBS
RANLIB := $_ranlib
@ -1008,7 +930,6 @@ INCLUDES += $INCLUDES
OBJS += $OBJS
DEFINES += $DEFINES
LDFLAGS += $LDFLAGS
LDFLAGS_TEST += $LDFLAGS_TEST
$_config_mk_data
EOF

28
debian/changelog vendored
View File

@ -1,31 +1,3 @@
stella (7.0) stable; urgency=high
* Version 7.0 release
-- Stephen Anthony <sa666666@gmail.com> Sat, 5 Oct 2024 17:09:59 -0230
stella (6.7) stable; urgency=high
* Version 6.7 release
-- Stephen Anthony <sa666666@gmail.com> Mon, 13 Jun 2022 17:09:59 -0230
stella (6.6) stable; urgency=high
* Version 6.6 release
-- Stephen Anthony <sa666666@gmail.com> Tue, 16 Nov 2021 17:09:59 -0230
stella (6.5.3) stable; urgency=high
* Version 6.5.3 release
-- Stephen Anthony <sa666666@gmail.com> Tue, 20 Apr 2021 17:09:59 -0230
stella (6.5.2) stable; urgency=high
* Version 6.5.2 release

5
debian/control vendored
View File

@ -3,9 +3,8 @@ Maintainer: Stephen Anthony <sa666666@gmail.com>
Section: otherosfs
Priority: optional
Build-Depends: debhelper (>= 10~),
libgtest-dev,
libpng-dev,
libsdl3-dev,
libsdl2-dev,
zlib1g-dev
Standards-Version: 4.5.0
Vcs-Browser: https://github.com/stella-emu/stella/
@ -19,7 +18,7 @@ Depends: ${misc:Depends},
${shlibs:Depends}
Recommends: joystick (>= 1:1.5.1)
Pre-Depends: ${misc:Pre-Depends}
Description: Atari 2600 Emulator for SDL
Description: Atari 2600 Emulator for SDL2
Stella is a portable emulator of the old Atari 2600 video-game
console. You can play most Atari 2600 games with it.
.

14
debian/copyright vendored
View File

@ -1,18 +1,18 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0
Upstream-Name: stella
Source: https://stella-emu.github.io
Copyright: 1995-2025 Bradford W. Mott, Stephen Anthony and the Stella Team
Copyright: 1995-2021 Bradford W. Mott, Stephen Anthony and the Stella Team
License: GPL-2+
Files: *
Copyright: 1995-2025 Bradford W. Mott, Stephen Anthony and the Stella
Copyright: 1995-2021 Bradford W. Mott, Stephen Anthony and the Stella
Team
License: GPL-2+
Files: debian/*
Copyright: 1998-2004 Tom Lear <tom@trap.mtview.ca.us>
2006 Mario Iseli <admin@marioiseli.com>
2010-2025 Stephen Kitt <skitt@debian.org>
2010-2021 Stephen Kitt <skitt@debian.org>
License: GPL-2+
Files:
@ -73,7 +73,7 @@ License: RSA
These notices must be retained in any copies of any part of this
documentation and/or software.
Files: src/lib/libpng/*
Files: src/libpng/*
Copyright: 1995-1996 Guy Eric Schalnat, Group 42, Inc.
1996-1997 Andreas Dilger
1998-2013 Glenn Randers-Pehrson
@ -112,7 +112,7 @@ License: libpng
risk of satisfactory quality, performance, accuracy, and effort is
with the user.
Files: src/os/libretro/libretro.h
Files: src/libretro/libretro.h
Copyright: 2010-2017 The RetroArch team
License: MIT
Permission is hereby granted, free of charge, to any person obtaining
@ -135,7 +135,7 @@ License: MIT
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Files: src/os/macos/*
Files: src/macos/*
Copyright: 2005-2006 Mark Grebe
License: GPL-2+
@ -164,7 +164,7 @@ License: GPL-2
License version 2 can be found in
`/usr/share/common-licenses/GPL-2'.
Files: src/lib/zlib/*
Files: src/zlib/*
Copyright: 1995-2012, 2016 Jean-loup Gailly and Mark Adler
License: zlib
This software is provided 'as-is', without any express or implied

4
debian/docs vendored
View File

@ -2,7 +2,7 @@ Announce.txt
Changes.txt
Copyright.txt
README-SDL.txt
README.md
Readme.txt
docs/*.html
docs/graphics/*.png
doc/graphics/*.png
Todo.txt

View File

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

View File

@ -15,7 +15,7 @@
<body>
<center><b><font size="7">Stella</font></b></center>
<center><h4><b>Release 7.0</b></h4></center>
<center><h4><b>Release 6.5.2</b></h4></center>
<center><h1><b>Integrated Debugger</b></h1></center>
<center><h4><b>(a work in progress)</b></h4></center>
<br>
@ -45,7 +45,6 @@
<li><a href="#PseudoRegisters">Pseudo-Registers</a></li>
<li><a href="#Watches">Watches</a></li>
<li><a href="#Traps">Traps</a></li>
<li><a href="#Timers">Timers</a></li>
</ul>
</li>
<li><a href="#SaveWork">Save your work!</a></li>
@ -103,10 +102,10 @@ feature that no other 2600 debugger has; it's <b>completely</b> cross-platform.<
breakpoints as you want.</li>
<li>Conditional breakpoints - Break running program when some arbitrary
condition is true (e.g. "breakIf {a == $7f &amp;&amp; c}" will break when the Accumulator value is $7f and the Carry flag is true, no matter where
condition is true (e.g. "breakif {a == $7f &amp;&amp; c}" will break when the Accumulator value is $7f and the Carry flag is true, no matter where
in the program this happens). Unlike the cond breaks in PCAE, Stella's
are *fast*: the emulation will run at full speed unless you use lots
of breakIf's at the same time, or have a slow CPU.</li>
of breakif's at the same time, or have a slow CPU.</li>
<li>Watches - View contents of a location/register before every
debugger prompt.</li>
@ -173,7 +172,7 @@ feature that no other 2600 debugger has; it's <b>completely</b> cross-platform.<
<li>Data sources for the CPU SP/A/X/Y registers, showing the resolved/source
address of of load operands.</li>
<li>Scanline advance (like frame advance, break at beginning
of next scanLine).</li>
of next scanline).</li>
<li>TIA display is updated during step/trace, so we can see our
scanlines being drawn as it happens. This isn't 100% perfect: unlike
a real TIA, the one in Stella only updates when it's written to.</li>
@ -184,7 +183,7 @@ feature that no other 2600 debugger has; it's <b>completely</b> cross-platform.<
named after the ROM image.</li>
<li>Saving the current debugger state to a script file (including
breakpoints, traps, etc).</li>
<li>Built-in functions for use with "breakIf", to support common conditions
<li>Built-in functions for use with "breakif", to support common conditions
(such as breaking when the user presses Game Select...)</li>
<li>Patching ROM in-place.</li>
<li>Save patched ROM</li>
@ -252,9 +251,9 @@ command on the command line, or alternatively within the ROM launcher in
</p>
<p>Using the ` key will always enter the debugger at the end of
the frame (for NTSC games usually scanLine 262). This is because Stella only checks
the frame (for NTSC games usually scanline 262). This is because Stella only checks
for keystrokes once per frame. Once in the debugger, you can control
execution by stepping one instruction, scanLine, or frame at a time
execution by stepping one instruction, scanline, or frame at a time
(or more than one at a time, using commands in the prompt). You can
also set breakpoints or traps, which will cause the emulator to enter
the debugger when they are triggered, even if it happens in mid-frame.</p>
@ -311,7 +310,7 @@ more convenient.
</li>
<li>
"&lt;rom_filename&gt;.sym" (located in the same directory as the ROM)</br>
If you provide the -l and -s parameters DASM will create these two files during
If you provied the -l and -s parameters DASM will create these two files during
assembly. Stella uses the file content to display the correct labels.
</li>
</ul>
@ -346,57 +345,56 @@ size can be configured e.g. in the
<p>
<table BORDER=1 cellpadding=4>
<tr>
<th>Function</th>
<th>Key</th>
<th>Function</th>
</tr>
<tr>
<td>Step &#185;</td>
<td>Control + S</td>
<td>Step</td>
</tr>
<tr>
<td>Trace &#185;</td>
<td>Control + T</td>
<td>Trace</td>
</tr>
<tr>
<td>Scan +1 &#185;</td>
<td>Control + L</td>
<td>Scan +1</td>
</tr>
<tr>
<td>Frame +1 &#185;</td>
<td>Control + F</td>
<td>Frame +1</td>
</tr>
<tr>
<td>Rewind 1</td>
<td>Alt + Left arrow</td>
<td>Rewind 1</td>
</tr>
<tr>
<td>Rewind 10</td>
<td>Shift-Alt + Left arrow</td>
<td>Rewind 10</td>
</tr>
<tr>
<td>Rewind all</td>
<td>Alt + Down arrow</td>
<td>Rewind all</td>
</tr>
<tr>
<td>Unwind 1</td>
<td>Alt + Right arrow</td>
<td>Unwind 1</td>
</tr>
<tr>
<td>Unwind 10</td>
<td>Shift-Alt + Right arrow</td>
<td>Unwind 10</td>
</tr>
<tr>
<td>Unwind all</td>
<td>Alt + Up arrow</td>
<td>Unwind all</td>
</tr>
<tr>
<td>Backquote (`)</td>
<td>Run, exits debugger</td>
<td>Backquote (`), Escape</td>
</tr>
</table>
</p>
For MacOS use 'Cmd' instead of &nbsp;'Alt' key.
<p>&#185;: External I/O input is ignored, the state of the <a href="#IOTab">I/O Tab</a> remains unchanged.</p>
<p>To the left of the global buttons, you find the 'Options...' button.</p>
<ul>
<p><img src="graphics/debugger_options.png"></p>
@ -410,7 +408,7 @@ in detail in the <a href="index.html">User's Guide</a>.</p>
<p>The debugger tracks changes to the CPU, TIA and RIOT registers and RAM by
displaying changed locations or registers with a red background after each step,
trace, scanLine, or frame advance. This sounds simple, and it is, but
trace, scanline, or frame advance. This sounds simple, and it is, but
it's also amazingly useful.</p>
<p>One clarification about the change tracking: it only tracks when values
@ -430,28 +428,25 @@ or Supermon for the C=64.</p>
Bash-style commands are also supported:</p>
<table border="1" cellpadding=4>
<tr><th>Function</th><th>Key</th></tr>
<tr><td>Move cursor to beginning of line</td><td>Home</td></tr>
<tr><td>Move cursor to end of line</td><td>End</td></tr>
<tr><td>Remove character to right of cursor</td><td>Delete</td></tr>
<tr><td>Remove character to left of cursor</td><td>Backspace</td></tr>
<tr><td>Same function as 'Home'</td><td>Control + A</td></tr>
<tr><td>Same function as 'End'</td><td>Control + E</td></tr>
<tr><td>Same function as 'Delete'</td><td>Control + D</td></tr>
<tr><td>Remove all characters from cursor to end of line</td><td>Control + K</td></tr>
<tr><td>Remove all characters from cursor to beginning of line</td><td>Control + U</td></tr>
<tr><td>Remove entire word to left of cursor</td><td>Control + W</td></tr>
<tr><td>Copy current line</td><td>Control + C</td></tr>
<tr><td>Cut current line</td><td>Control + X</td></tr>
<tr><td>Paste over current line</td><td>Control + V</td></tr>
<tr><td>Scroll up through previous commands one screen/page</td><td>Shift + PgUp</td></tr>
<tr><td>Scroll down through previous commands one screen/page</td><td>Shift + PgDown</td></tr>
<tr><td>Scroll up through previous commands one line</td><td>Shift + Up</td></tr>
<tr><td>Scroll down through previous commands one line</td><td>Shift + Down</td></tr>
<tr><td>Scroll to beginning of commands</td><td>Shift + Home</td></tr>
<tr><td>Scroll to end of commands</td><td>Shift + End</td></tr>
<tr><th>Key</th><th>Function</th></tr>
<tr><td>Home</td><td>Move cursor to beginning of line</td></tr>
<tr><td>End</td><td>Move cursor to end of line</td></tr>
<tr><td>Delete</td><td>Remove character to right of cursor</td></tr>
<tr><td>Backspace</td><td>Remove character to left of cursor</td></tr>
<tr><td>Control + A</td><td>Same function as 'Home'</td></tr>
<tr><td>Control + E</td><td>Same function as 'End'</td></tr>
<tr><td>Control + D</td><td>Same function as 'Delete'</td></tr>
<tr><td>Control + K</td><td>Remove all characters from cursor to end of line</td></tr>
<tr><td>Control + U</td><td>Remove all characters from cursor to beginning of line</td></tr>
<tr><td>Control + W</td><td>Remove entire word to left of cursor</td></tr>
<tr><td>Shift + PgUp</td><td>Scroll up through previous commands one screen/page</td></tr>
<tr><td>Shift + PgDown</td><td>Scroll down through previous commands one screen/page</td></tr>
<tr><td>Shift + Up</td><td>Scroll up through previous commands one line</td></tr>
<tr><td>Shift + Down</td><td>Scroll down through previous commands one line</td></tr>
<tr><td>Shift + Home</td><td>Scroll to beginning of commands</td></tr>
<tr><td>Shift + End</td><td>Scroll to end of commands</td></tr>
</table>
<p>You can also scroll with the mouse. Copy and paste is currently only supported for a complete line.</p>
<p>You can also scroll with the mouse. Copy and paste is not yet supported.</p>
<p>To see the available commands, enter "help". For extended help, type "help cmd",
where 'cmd' is the command you wish to know about. The available commands are listed
@ -472,16 +467,16 @@ just by re-running the relevant commands in the prompt.</p>
<h3><a name="TabCompletion">Tab Key Auto-Complete</a></h3>
<p>While entering a command, label or function, you can type a partial name and
press the (Shift +) Tab key to attempt to auto-complete it. If you've ever used
press the Tab key to attempt to auto-complete it. If you've ever used
"bash", this will be immediately familiar. If not, try it: load up
a ROM, go to the debugger, type "g" (but don't press Enter),
then hit Tab. The "g" will change to "gfx" (since this is the only
built-in command starting with a "g"). If there are multiple possible
completions (try with "tr" instead of "g"), you can tab through them.
completions (try with "tr" instead of "g"), you'll see a list of them,
and your partial name will be completed as far as possible.
After the first character, the autocompletion considers all
characters in the right order as a match (e.g. "twf" will be completed to
"trapWriteIf"). Alternatively you can make use of the camel case names and type
e.g. "tWI" ("trapWriteIf") or "lAS" ("LoadAllStates").</p>
"trapwriteif").</p>
<p>Tab completion works on all labels: built-in, loaded from a symbol file,
or set during debugging with the "define" command. It also works with
@ -614,7 +609,7 @@ command that takes arguments.</p>
<h4><a name="Breakpoints">Breakpoints</a></h4>
<p>A breakpoint is a "hotspot" in your program that causes the emulator
to stop emulating and jump into the debugger &#185;. You can set as many
to stop emulating and jump into the debugger. You can set as many
breakpoints as you like. The command is "break xx yy" where xx is any
expression and yy a bank number. Both arguments are optional. If you have
created a symbol file, you can use labels for the expression.</p>
@ -635,11 +630,8 @@ set it. In the example, "break kernel" will remove the breakpoint.
The "break" command can be thought of as a *toggle*: it turns the
breakpoint on &amp; off, like a light switch.</p>
<p>You could also use "clearBreaks" to remove all the breakpoints. Also,
there is a "listBreaks" command that will list them all.</p>
<p>&#185; By enabling "logBreaks" you can log the current state into
the System Log and continue emulation instead.</p>
<p>You could also use "clearbreaks" to remove all the breakpoints. Also,
there is a "listbreaks" command that will list them all.</p>
<h4><a name="ConditionalBreaks">Conditional Breaks</a></h4>
@ -669,10 +661,10 @@ is the "!" operator): !(*SWCHB&amp;1). The parentheses are necessary as
we want to apply the ! to the result of the &amp;, not just the first term
(the "*SWCHB").</p>
<p>"breakIf !(*SWCHB&amp;1)" will do the job for us. However, it's an ugly mess
<p>"breakif !(*SWCHB&amp;1)" will do the job for us. However, it's an ugly mess
of letters, numbers, and punctuation. We can do a little better:</p>
<p>"breakIf { !(*SWCHB &amp; 1 ) }" is a lot more readable, isn't it? If
<p>"breakif { !(*SWCHB &amp; 1 ) }" is a lot more readable, isn't it? If
you're going to use readable expressions with spaces in them,
enclose the entire expression in curly braces.</p>
@ -681,9 +673,9 @@ condition that depends on input (like SWCHB) will always happen at the
end of a frame. This is different from how a real 2600 works, but most
ROMs only check for input once per frame anyway.</p>
<p>Conditional breaks appear in "listBreaks", numbered starting from
zero. You can remove a cond-break with "delBreakIf number", where
the number comes from "listBreaks" or by entering the same conditional break again.</p>
<p>Conditional breaks appear in "listbreaks", numbered starting from
zero. You can remove a cond-break with "delbreakif number", where
the number comes from "listbreaks" or by entering the same conditional break again.</p>
<p>Any time the debugger is entered due to a trap, breakpoint, or
conditional break, the reason will be displayed in the
@ -692,16 +684,16 @@ conditional break, the reason will be displayed in the
<h4><a name="Functions">Functions</a></h4>
<p>There is one annoyance about complex expressions: once we
remove the conditional break with "delBreakIf" or "clearBreaks",
remove the conditional break with "delbreakif" or "clearbreaks",
we'd have to retype it (or search backwards with the up-arrow key)
if we wanted to use it again.</p>
<p>We can avoid this by defining the expression as a function, then using
"breakIf function_name":</p>
"breakif function_name":</p>
<pre>
function gameReset { !(*SWCHB &amp; 1 ) }
breakIf gameReset
breakif gameReset
</pre>
<p>Now we have a meaningful name for the condition, so we can use it again.
@ -711,16 +703,16 @@ if the Game Select switch is pressed. We want to break when the user
presses both Select and Reset:</p>
<pre>
breakIf { gameReset &amp;&amp; gameSelect }
breakif { gameReset &amp;&amp; gameSelect }
</pre>
<p>User-defined functions appear in "listFunctions", which shows the label
<p>User-defined functions appear in "listfunctions", which shows the label
and expression for each function. Functions can be removed with
"delFunction label", where the labels come from "listFunctions".</p>
"delfunction label", where the labels come from "listfunctions".</p>
<h4><a name="BuiltInFunctions">Built-in Functions</a></h4>
<p>Stella has some pre-defined functions for use with the "breakIf"
<p>Stella has some pre-defined functions for use with the "breakif"
command. These allow you to break and enter the debugger on various
conditions without having to define the conditions yourself.</p>
@ -731,24 +723,24 @@ Stella debugger.</p>
<table border="1" cellpadding=4>
<tr><th>Function</th><th>Definition</th><th>Description</th></tr>
<tr><td> _joy0Left</td><td> !(*SWCHA &amp; $40)</td><td> Left joystick moved left</td></tr>
<tr><td> _joy0Right</td><td> !(*SWCHA &amp; $80)</td><td> Left joystick moved right</td></tr>
<tr><td> _joy0Up</td><td> !(*SWCHA &amp; $10)</td><td> Left joystick moved up</td></tr>
<tr><td> _joy0Down</td><td> !(*SWCHA &amp; $20)</td><td> Left joystick moved down</td></tr>
<tr><td> _joy0Fire</td><td> !(*INPT4 &amp; $80)</td><td> Left joystick fire button pressed</td></tr>
<tr><td> _joy1Left</td><td> !(*SWCHA &amp; $04)</td><td> Right joystick moved left</td></tr>
<tr><td> _joy1Right</td><td> !(*SWCHA &amp; $08)</td><td> Right joystick moved right</td></tr>
<tr><td> _joy1Up</td><td> !(*SWCHA &amp; $01)</td><td> Right joystick moved up</td></tr>
<tr><td> _joy1Down</td><td> !(*SWCHA &amp; $02)</td><td> Right joystick moved down</td></tr>
<tr><td> _joy1Fire</td><td> !(*INPT5 &amp; $80)</td><td> Right joystick fire button pressed</td></tr>
<tr><td> _joy0left</td><td> !(*SWCHA &amp; $40)</td><td> Left joystick moved left</td></tr>
<tr><td> _joy0right</td><td> !(*SWCHA &amp; $80)</td><td> Left joystick moved right</td></tr>
<tr><td> _joy0up</td><td> !(*SWCHA &amp; $10)</td><td> Left joystick moved up</td></tr>
<tr><td> _joy0down</td><td> !(*SWCHA &amp; $20)</td><td> Left joystick moved down</td></tr>
<tr><td> _joy0button</td><td> !(*INPT4 &amp; $80)</td><td> Left joystick button pressed</td></tr>
<tr><td> _joy1left</td><td> !(*SWCHA &amp; $04)</td><td> Right joystick moved left</td></tr>
<tr><td> _joy1right</td><td> !(*SWCHA &amp; $08)</td><td> Right joystick moved right</td></tr>
<tr><td> _joy1up</td><td> !(*SWCHA &amp; $01)</td><td> Right joystick moved up</td></tr>
<tr><td> _joy1down</td><td> !(*SWCHA &amp; $02)</td><td> Right joystick moved down</td></tr>
<tr><td> _joy1button</td><td> !(*INPT5 &amp; $80)</td><td> Right joystick button pressed</td></tr>
<tr><td> _select</td><td> !(*SWCHB &amp; $02)</td><td> Game Select pressed</td></tr>
<tr><td> _reset</td><td> !(*SWCHB &amp; $01)</td><td> Game Reset pressed</td></tr>
<tr><td> _color</td><td> *SWCHB &amp; $08</td><td> Color/BW set to Color</td></tr>
<tr><td> _bw</td><td> !(*SWCHB &amp; $08)</td><td> Color/BW set to BW</td></tr>
<tr><td> _diff0B</td><td> !(*SWCHB &amp; $40)</td><td> Left difficulty set to B (easy)</td></tr>
<tr><td> _diff0A</td><td> *SWCHB &amp; $40</td><td> Left difficulty set to A (hard)</td></tr>
<tr><td> _diff1B</td><td> !(*SWCHB &amp; $80)</td><td> Right difficulty set to B (easy)</td></tr>
<tr><td> _diff1A</td><td> *SWCHB &amp; $80</td><td> Right difficulty set to A (hard)</td></tr>
<tr><td> _diff0b</td><td> !(*SWCHB &amp; $40)</td><td> Left difficulty set to B (easy)</td></tr>
<tr><td> _diff0a</td><td> *SWCHB &amp; $40</td><td> Left difficulty set to A (hard)</td></tr>
<tr><td> _diff1b</td><td> !(*SWCHB &amp; $80)</td><td> Right difficulty set to B (easy)</td></tr>
<tr><td> _diff1a</td><td> *SWCHB &amp; $80</td><td> Right difficulty set to A (hard)</td></tr>
</table>
<p>Don't worry about memorizing them all: the Prompt "help" command
@ -764,38 +756,36 @@ that holds 'number of scanlines' on an actual console).</p>
<table border="1" cellpadding=4>
<tr><th>Function</th><th>Description</th></tr>
<tr><td> _bank</td><td> Currently selected bank</td></tr>
<tr><td> _cClocks</td><td> Color clocks on a scanLine</td></tr>
<tr><td> _cyclesHi</td><td> Higher 32 bits of number of cycles since emulation started</td></tr>
<tr><td> _cyclesLo</td><td> Lower 32 bits of number of cycles since emulation started</td></tr>
<tr><td> _fCount</td><td> Number of frames since emulation started</td></tr>
<tr><td> _fCycles</td><td> Number of cycles since frame started</td></tr>
<tr><td> _fTimReadCycles</td><td>Number of cycles used by timer reads since frame started</td></tr>
<tr><td> _fWsyncCycles</td><td>Number of cycles skipped by WSYNC since frame started</td></tr>
<tr><td> _iCycles</td><td> Number of cycles of last instruction</td></tr>
<tr><td> _inTim</td><td> Current INTIM value</td></tr>
<tr><td> _scan</td><td> Current scanLine count</td></tr>
<tr><td> _scanEnd</td><td> Scanline count at end of last frame</td></tr>
<tr><td> _sCycles</td><td> Number of cycles in current scanLine</td></tr>
<tr><td> _timInt</td><td> Current TIMINT value</td></tr>
<tr><td> _timWrapRead</td><td> Timer read wrapped on this cycle</td></tr>
<tr><td> _timWrapWrite</td><td> Timer write wrapped on this cycle</td></tr>
<tr><td> _vBlank</td><td> Whether vertical blank is enabled (1 or 0)</td></tr>
<tr><td> _vSync</td><td> Whether vertical sync is enabled (1 or 0)</td></tr>
<tr><td> _cclocks</td><td> Color clocks on a scanline</td></tr>
<tr><td> _cycleshi</td><td> Higher 32 bits of number of cycles since emulation started</td></tr>
<tr><td> _cycleslo</td><td> Lower 32 bits of number of cycles since emulation started</td></tr>
<tr><td> _fcount</td><td> Number of frames since emulation started</td></tr>
<tr><td> _fcycles</td><td> Number of cycles since frame started</td></tr>
<tr><td> _ftimreadcycles</td><td>Number of cycles used by timer reads since frame started</td></tr>
<tr><td> _fwsynccycles</td><td>Number of cycles skipped by WSYNC since frame started</td></tr>
<tr><td> _icycles</td><td> Number of cycles of last instruction</td></tr>
<tr><td> _scan</td><td> Current scanline count</td></tr>
<tr><td> _scanend</td><td> Scanline count at end of last frame</td></tr>
<tr><td> _scycles</td><td> Number of cycles in current scanline</td></tr>
<tr><td> _timwrapread</td><td> Timer read wrapped on this cycle</td></tr>
<tr><td> _timwrapwrite</td><td> Timer write wrapped on this cycle</td></tr>
<tr><td> _vblank</td><td> Whether vertical blank is enabled (1 or 0)</td></tr>
<tr><td> _vsync</td><td> Whether vertical sync is enabled (1 or 0)</td></tr>
</table>
<p><b>_scan</b> always contains the current scanLine count. You can use
<p><b>_scan</b> always contains the current scanline count. You can use
this to break your program in the middle of your kernel. Example:</p>
<pre>
breakIf _scan==#64
breakif _scan==#64
</pre>
<p>This will cause Stella to enter the debugger when the TIA reaches the
beginning of the 64th scanLine.</p>
beginning of the 64th scanline.</p>
<p><b>_bank</b> always contains the currently selected bank. For 2K or 4K
(non-bankswitched) ROMs, it will always contain 0. One useful use is:</p>
<pre>
breakIf { pc==myLabel &amp;&amp; _bank==1 }
breakif { pc==myLabel &amp;&amp; _bank==1 }
</pre>
<p>This is similar to setting a regular breakpoint, but it will only trigger
@ -814,8 +804,8 @@ pointed to by the Y register, even if the Y register changes.</p>
<p>The watches are numbered. The numbers are printed along with the
watches, so you can tell which is which. To delete a watch use the
"delWatch" command with the watch number (1 to whatever). You can
also delete them all with the "clearWatches" command.</p>
"delwatch" command with the watch number (1 to whatever). You can
also delete them all with the "clearwatches" command.</p>
<p>Note that there's no real point in watching a label or CPU register
without dereferencing it: Labels are constants, and CPU registers
@ -828,7 +818,7 @@ accesses to a memory address, rather than specific location in the
program. They're useful for finding code that modifies TIA registers
or memory.</p>
<p>Traps can also combined with a condition ("trapIf"). If an access
<p>Traps can also combined with a condition ("trapif"). If an access
to a memory address is caught, the condition is evaluated additionally.
Only if the condition is true too, the emulations stops. For details
about conditions see <a href="#ConditionalBreaks"><b>Conditional Breaks</b></a> described above.</p>
@ -852,28 +842,12 @@ so the best we can do is stop before the next instruction runs.</p>
<p>Traps come in two varieties: read access traps and write access traps.
It is possible to set both types of trap on the same address (that's
what the plain "trap" command does). To set a read or write only trap,
use "trapRead(if)" or "trapWrite(if)".
use "trapread(if)" or "trapwrite(if)".
<p>All traps appear in "listTraps", numbered starting from zero. You
can remove a trap with "delTrap number", where the number comes from
"listTraps" or by entering the identical trap again. You can get rid of
all traps at once with the "clearTraps" command.</p></p>
<h4><a name="Timers">Timers</a></h4>
<p>Timers are used to measure cycles used between two timer points. They
measure the minimum, maximum and average cycles executed between their two
timer points. Start and end points can be set via prompt command or ROM
Disassembly settings dialog.</p>
<p>If the timer point is defined without an address or bank, the current PC
address or bank are used. If a '+' is added, both timer points use address
mirrors too, a '*' triggers both timer points in any bank.</p>
<p>All timers can be shown in detail with "listTimers", a single timer
with "printTimer number". "resetTimers" allows resetting all timer statistics,
"delTimer number" removes a single timer. All timers can be deleted with the
"clearTimers" command.</p>
<p>All traps appear in "listtraps", numbered starting from zero. You
can remove a trap with "deltrap number", where the number comes from
"listtraps" or by entering the identical trap again. You can get rid of
all traps at once with the "cleartraps" command.</p></p>
</br>
<h3><a name="SaveWork">Save your work!</a></h3>
@ -882,61 +856,58 @@ later re-use.</p>
<ul>
<li>
<b><a name="savecmd">save</a></b>: If you've defined a lot of complex
functions, you probably will want to re-use them in future runs of the
debugger. You can save all your functions, breakpoints, conditional breaks,
traps and watches with the "save" command. By default it is saved in the
user directory with the same as the ROM filename. In this case it will be
auto-loaded next time you load the same ROM in Stella. The saved file is
just a plain text file called "&lt;rom_filename&gt;.script", so you can
edit it and add more functions, etc.
<p>Use "autoSave" to automatically execute the "save" command when
exiting the debugger.</p>
<b><a name="savecmd">save</a></b>: If you've defined a lot of complex functions, you probably will
want to re-use them in future runs of the debugger. You can save all
your functions, breakpoints, conditional breaks, traps and watches with the
"save" command. If you name your saved file the same as the ROM filename
and place it in the ROM directory, it will be auto-loaded next time you
load the same ROM in Stella. The saved file is just a plain text file
called "&lt;rom_filename&gt;.script", so you can edit it and add new functions, etc.
<p>Note: While "save" is ROM specific, you can also create a file called
"autoexec.script" which will be loaded when the debugger starts, no matter
what ROM you have loaded.<p>
See <a href="#Startup"><b>Startup</b></a> for details.
</li>
<li>
<b>saveConfig</b>: The "saveConfig" command creates a
<b>saveconfig</b>: The "saveconfig" command creates a
<a href="#DistellaConfiguration"><b>DiStella Configuration File</b></a> which is
based on Stella's dynamic and static analysis of the current ROM.
<p>This will be automatically loaded the next time your start the debugger.
From there on, you can continue analyzing the ROM and then use "saveConfig"
again to update the configuration. You can also use "loadConfig" to load it
From there on, you can continue analyzing the ROM and then use "saveconfig"
again to update the configuration. You can also use "loadconfig" to load it
manually.
<p>Note that this is not tested for multi-banked ROMs.</p>
</li>
<li>
<b>saveDis</b>:
<b>savedis</b>:
While your are playing or debugging a game, Stella will gather dynamic
information about the ROM. It can then use that information together with
a static analysis of the ROM and therefore create a better disassembly
than DiStella alone. "saveDis" allows you to save that disassembly as the
than DiStella alone. "savedis" allows you to save that disassembly as the
result of this combined analysis.
<p>Note that this currently only works for single banked ROMs. For larger
ROMs, the created disassembly is incomplete.</p>
</li>
<li>
<p><b>saveRom</b>:
If you have manipulated a ROM, you can save it with "saveRom". The file is
<p><b>saverom</b>:
If you have manipulated a ROM, you can save it with "saverom". The file is
named "&lt;rom_filename&gt;.a26".</p>
</li>
<li>
<p><b>saveSes</b>:
The "saveSes" command dumps the whole prompt session into a file named
<p><b>saveses</b>:
The "saveses" command dumps the whole prompt session into a file named
"&lt;YYYY-MM-DD_HH-mm-ss&gt;.txt". So you can later lookup what you did exactly
when you were debugging at that time.</p>
</li>
<li>
<p><b>saveAllStates</b>:
<p><b>saveallstates</b>:
This command works identical to the save all states hotkey (Alt + F9) during emulation.
The saved states can be loaded with "loadAllStates".</p>
The saved states can be loaded with "loadallstates".</p>
</li>
<li>
<p><b>saveState</b>:
<p><b>savestate</b>:
This command works identical to the save state hotkey (F9) during emulation.
Any previously saved state can be loaded with "loadState" plus the slot
Any previously saved state can be loaded with "loadstate" plus the slot
number (0-9).</p>
</li>
</ul>
@ -950,107 +921,97 @@ Type "help 'cmd'" to see extended information about the given command.</p>
<pre>
a - Set Accumulator to &lt;value&gt;
aud - Mark 'AUD' range in disassembly
autoSave - Automatically execute "save" when exiting the debugger
base - Set default number base to &lt;base&gt; (bin, dec, hex)
bCol - Mark 'BCOL' range in disassembly
bcol - Mark 'BCOL' range in disassembly
break - Set/clear breakpoint at &lt;address&gt; and &lt;bank&gt;
breakIf - Set/clear breakpoint on &lt;condition&gt;
breakLabel - Set/clear breakpoint on &lt;address&gt; (no mirrors, all banks)
breakif - Set/clear breakpoint on &lt;condition&gt;
breaklabel - Set/clear breakpoint on &lt;address&gt; (no mirrors, all banks)
c - Carry Flag: set (0 or 1), or toggle (no arg)
cheat - Use a cheat code (see manual for cheat types)
clearBreaks - Clear all breakpoints
clearConfig - Clear DiStella config directives [bank xx]
clearHistory - Clear the prompt history
clearSaveStateIfs - Clear all saveState points
clearTimers - Clear all timers
clearTraps - Clear all traps
clearWatches - Clear all watches
clearbreaks - Clear all breakpoints
clearconfig - Clear DiStella config directives [bank xx]
clearsavestateifs - Clear all savestate points
cleartraps - Clear all traps
clearwatches - Clear all watches
cls - Clear prompt area of text
code - Mark 'CODE' range in disassembly
col - Mark 'COL' range in disassembly
colorTest - Show value xx as TIA color
colortest - Show value xx as TIA color
d - Decimal Mode Flag: set (0 or 1), or toggle (no arg)
data - Mark 'DATA' range in disassembly
debugColors - Show Fixed Debug Colors information
debugcolors - Show Fixed Debug Colors information
define - Define label xx for address yy
delBreakIf - Delete conditional breakIf &lt;xx&gt;
delFunction - Delete function with label xx
delSaveStateIf - Delete conditional saveState point &lt;xx&gt;
delTrap - Delete trap &lt;xx&gt;
delTimer - Delete timer &lt;xx&gt;
delWatch - Delete watch &lt;xx&gt;
disAsm - Disassemble address xx [yy lines] (default=PC)
delbreakif - Delete conditional breakif &lt;xx&gt;
delfunction - Delete function with label xx
delsavestateif - Delete conditional savestate point &lt;xx&gt;
deltrap - Delete trap &lt;xx&gt;
delwatch - Delete watch &lt;xx&gt;
disasm - Disassemble address xx [yy lines] (default=PC)
dump - Dump data at address &lt;xx&gt; [to yy] [1: memory; 2: CPU state; 4: input regs] [?]
exec - Execute script file &lt;xx&gt; [prefix]
exitRom - Exit emulator, return to ROM launcher
exitrom - Exit emulator, return to ROM launcher
frame - Advance emulation by &lt;xx&gt; frames (default=1)
function - Define function name xx for expression yy
gfx - Mark 'GFX' range in disassembly
help - help &lt;command&gt;
joy0Up - Set joystick 0 up direction to value &lt;x&gt; (0 or 1), or toggle (no arg)
joy0Down - Set joystick 0 down direction to value &lt;x&gt; (0 or 1), or toggle (no arg)
joy0Left - Set joystick 0 left direction to value &lt;x&gt; (0 or 1), or toggle (no arg)
joy0Right - Set joystick 0 right direction to value <x> (0 or 1), or toggle (no arg)
joy0Fire - Set joystick 0 fire button to value &lt;x&gt; (0 or 1), or toggle (no arg)
joy1Up - Set joystick 1 up direction to value &lt;x&gt; (0 or 1), or toggle (no arg)
joy1Down - Set joystick 1 down direction to value &lt;x&gt; (0 or 1), or toggle (no arg)
joy1Left - Set joystick 1 left direction to value &lt;x&gt; (0 or 1), or toggle (no arg)
joy1Right - Set joystick 1 right direction to value &lt;x&gt; (0 or 1), or toggle (no arg)
joy1Fire - Set joystick 1 fire button to value &lt;x&gt; (0 or 1), or toggle (no arg)
joy0up - Set joystick 0 up direction to value &lt;x&gt; (0 or 1), or toggle (no arg)
joy0down - Set joystick 0 down direction to value &lt;x&gt; (0 or 1), or toggle (no arg)
joy0left - Set joystick 0 left direction to value &lt;x&gt; (0 or 1), or toggle (no arg)
joy0right - Set joystick 0 right direction to value <x> (0 or 1), or toggle (no arg)
joy0fire - Set joystick 0 fire button to value &lt;x&gt; (0 or 1), or toggle (no arg)
joy1up - Set joystick 1 up direction to value &lt;x&gt; (0 or 1), or toggle (no arg)
joy1down - Set joystick 1 down direction to value &lt;x&gt; (0 or 1), or toggle (no arg)
joy1left - Set joystick 1 left direction to value &lt;x&gt; (0 or 1), or toggle (no arg)
joy1right - Set joystick 1 right direction to value &lt;x&gt; (0 or 1), or toggle (no arg)
joy1fire - Set joystick 1 fire button to value &lt;x&gt; (0 or 1), or toggle (no arg)
jump - Scroll disassembly to address xx
listBreaks - List breakpoints
listConfig - List DiStella config directives [bank xx]
listFunctions - List user-defined functions
listSaveStateIfs - List saveState points
listTraps - List traps
loadConfig - Load DiStella config file
loadAllStates - Load all emulator states
loadState - Load emulator state xx (0-9)
logBreaks - Logs breaks and traps and continues emulation
logTrace - Logs emulation (note: emulation may slow down and the log becomes huge soon)
listbreaks - List breakpoints
listconfig - List DiStella config directives [bank xx]
listfunctions - List user-defined functions
listsavestateifs - List savestate points
listtraps - List traps
loadconfig - Load DiStella config file
loadallstates - Load all emulator states
loadstate - Load emulator state xx (0-9)
n - Negative Flag: set (0 or 1), or toggle (no arg)
palette - Show current TIA palette
pc - Set Program Counter to address xx
pCol - Mark 'PCOL' range in disassembly
pGfx - Mark 'PGFX' range in disassembly
pcol - Mark 'PCOL' range in disassembly
pgfx - Mark 'PGFX' range in disassembly
print - Evaluate/print expression xx in hex/dec/binary
printTimer - Print details of timer xx
ram - Show ZP RAM, or set address xx to yy1 [yy2 ...]
reset - Reset system to power-on state
resetTimers - Reset all timers' statistics
rewind - Rewind state by one or [xx] steps/traces/scanlines/frames...
riot - Show RIOT timer/input status
rom - Set ROM address xx to yy1 [yy2 ...]
row - Mark 'ROW' range in disassembly
run - Exit debugger, return to emulator
runTo - Run until string xx in disassembly
runToPc - Run until PC is set to value xx
runto - Run until string xx in disassembly
runtopc - Run until PC is set to value xx
s - Set Stack Pointer to value xx
save - Save breaks, watches, traps and functions to file [xx or ?]
saveAccess - Save access counters to CSV file [?]
saveConfig - Save DiStella config file (with default name)
saveDis - Save DiStella disassembly to file [?]
saveRom - Save (possibly patched) ROM to file [?]
saveSes - Save console session to file [?]
saveSnap - Save current TIA image to PNG file
saveAllStates - Save all emulator states
saveState - Save emulator state xx (valid args 0-9)
saveStateIf - Create saveState on &lt;condition&gt;
scanLine - Advance emulation by &lt;xx&gt; scanlines (default=1)
save - Save breaks, watches, traps and functions to file <xx or ?>
saveaccess - Save access counters to CSV file [?]
saveconfig - Save DiStella config file (with default name)
savedis - Save DiStella disassembly to file [?]
saverom - Save (possibly patched) ROM to file [?]
saveses - Save console session to file [?]
savesnap - Save current TIA image to PNG file
saveallstates - Save all emulator states
savestate - Save emulator state xx (valid args 0-9)
savestateif - Create savestate on &lt;condition&gt;
scanline - Advance emulation by &lt;xx&gt; scanlines (default=1)
step - Single step CPU [with count xx]
stepWhile - Single step CPU while &lt;condition&gt; is true
swchb - Set SWCHB to value xx
stepwhile - Single step CPU while &lt;condition&gt; is true
tia - Show TIA state
timer - Set a timer point
trace - Single step CPU over subroutines [with count xx]
trap - Trap read/write access to address(es) xx [yy]
trapIf - On &lt;condition&gt; trap R/W access to address(es) xx [yy]
trapRead - Trap read access to address(es) xx [yy]
trapReadIf - On &lt;condition&gt; trap read access to address(es) xx [yy]
trapWrite - Trap write access to address(es) xx [yy]
trapWriteIf - On &lt;condition&gt; trap write access to address(es) xx [yy]
trapif - On &lt;condition&gt; trap R/W access to address(es) xx [yy]
trapread - Trap read access to address(es) xx [yy]
trapreadif - On &lt;condition&gt; trap read access to address(es) xx [yy]
trapwrite - Trap write access to address(es) xx [yy]
trapwriteif - On &lt;condition&gt; trap write access to address(es) xx [yy]
type - Show disassembly type for address xx [yy]
uHex - Toggle upper/lowercase HEX display
uhex - Toggle upper/lowercase HEX display
undef - Undefine label xx (if defined)
unwind - Unwind state state by one or [xx] steps/traces/scanlines/frames...
v - Overflow Flag: set (0 or 1), or toggle (no arg)
@ -1108,7 +1069,7 @@ VDELBL selects the register that is used to control the ball. This is
visualized in the debugger in the same way as the two copies of GRP0 and
GRP1</p>
<p>For many registers, writes don't take effect immediately as the
<p>For many registers, writes don't take effect immediatelly as the
TIA takes some color clocks to change state. In Stella's TIA core, this
is implemented by queueing the writes, and the contents of this queue
are visualized in the debugger in the "Queued Writes" area of the TIA tab.</p>
@ -1123,11 +1084,11 @@ in another part of the debugger).</p>
<p><img src="graphics/debugger_iotab.png"></p>
<p>As with the TIA tab, most of the values here will be self-explanatory to a 2600
developer, and many can be modified. However, the SWCHx registers need
developer, and almost all can be modified. However, the SWCHx registers need
further explanation:<p>
<p>SWCHx(W/R) can be modified; here (W) stands for write, (R) for read.
Similarly, SWxCNT can be directly modified. However, the results of reading
back from the SWCHx register are influenced by SWxCNT, and SWCHx(R) is
<p>SWCHx(W) can be modified; here, the (W) stands for write. Similarly,
SWACNT/SWBCNT can be directly modified. However, the results of reading back from
the SWCHx register are influenced by SWACNT/SWBCNT, and SWCHx(R) is a read-only display
reflecting this result.</p>
@ -1150,12 +1111,12 @@ volume resulting from the two channel volumes.</p>
<p>In the upper left of the debugger, you'll see the current frame of
video as generated by the TIA. If a complete frame hasn't been drawn,
the partial contents of the current frame will be displayed up to the
current scanLine, with the contents of the old frame (in black &amp;
current scanline, with the contents of the old frame (in black &amp;
white) filling the rest of the display. Note that if 'phosphor mode'
or TV effects are enabled, you won't see the effects here; this shows the
<b>raw</b> TIA image only.</p>
<p>To e.g. watch the TIA draw the frame one scanLine at a time, you can
<p>To e.g. watch the TIA draw the frame one scanline at a time, you can
use the 'Scan+1' button, the prompt "scan" command or the Control-L key.</p>
<p>You can also right-click anywhere in this window to show a context menu,
@ -1163,10 +1124,10 @@ as illustrated:</p>
<p><img src="graphics/debugger_tiaoutcmenu.png"></p>
<p>The options are as follows:</p>
<ul>
<li><b>Fill to scanLine</b>: This option will draw all scanlines up to the
<li><b>Fill to scanline</b>: This option will draw all scanlines up to the
vertical position where the mouse was clicked (see also <a href="#TIAZoom"><b>TIA Zoom</b></a>).</li>
<li><b>Toggle breakpoint</b>: Will toggle a conditional breakpoint at the
scanLine where the mouse was clicked. You can also use a left-click or
scanline where the mouse was clicked. You can also use a left-click or
the Prompt Tab commands to list and turn off the breakpoint
(see also <a href="#TIAZoom"><b>TIA Zoom</b></a>).</li>
<li><b>Set zoom position</b>: Influences what is shown in the TIA
@ -1187,27 +1148,27 @@ as illustrated:</p>
<p>The indicators are as follows (note that all these are read-only):</p>
<ul>
<li><b>Frame Cycls</b>: The number of CPU cycles that have been executed this frame since
VSYNC was cleared at scanLine 0.</li>
VSYNC was cleared at scanline 0.</li>
<li><b>WSync Cycls</b>: The number of CPU cycles that have been skipped by WSYNC this frame since
VSYNC was cleared at scanLine 0.</li>
VSYNC was cleared at scanline 0.</li>
<li><b>Timer Cycls</b>: The number of CPU cycles (approximately) that have been used by timer read loops since
VSYNC was cleared at scanLine 0.</li>
VSYNC was cleared at scanline 0.</li>
<li><b>Total</b>: The total number of CPU cycles since this ROM was loaded or reset.</li>
<li><b>Delta</b>: The number of CPU cycles that have been executed since the last debugger
interrupt.</li>
<li><b>Frame Cnt.</b>: The number of frames since this ROM was loaded or reset.</li>
<li><b>Scanline</b>: The scanLine that's currently being drawn, and the count from the
<li><b>Scanline</b>: The scanline that's currently being drawn, and the count from the
previous frame. Scanline 0 is the one on which VSYNC is cleared (after being set for
3 scanlines, as per the Stella Programmer's Guide).</li>
<li><b>Scan Cycle</b>: The number of CPU cycles that have been executed since the beginning
of the current scanLine.</li>
of the current scanline.</li>
<li><b>Pixel Pos</b>: The current number of visible color clocks that have been displayed on
the current scanLine, starting from the beginning of the Horizontal Blank period.
the current scanline, starting from the beginning of the Horizontal Blank period.
During HBLANK, this value will be negative (representing the number of clocks
until the first visible one). Since there are 68 color clocks per HBLANK and
160 visible clocks per scanLine, the Pixel Position will range from -68 to 159.</li>
160 visible clocks per scanline, the Pixel Position will range from -68 to 159.</li>
<li><b>Color Clock</b>: The current number of total color clocks since the beginning of this
scanLine's HBLANK. This counter starts at zero, but otherwise displays the same
scanline's HBLANK. This counter starts at zero, but otherwise displays the same
information as the Pixel Position (so Color Clock will always be 68 more than Pixel
Position, and will range from 0 to 228).</li>
</ul>
@ -1225,10 +1186,10 @@ as illustrated:</p>
<p><img src="graphics/debugger_tiazoomcmenu.png"></p>
<p>These options allow you to:</p>
<ul>
<li><b>Fill to scanLine</b>: This option will draw all scanlines up to the
<li><b>Fill to scanline</b>: This option will draw all scanlines up to the
vertical position where the mouse was clicked.</li>
<li><b>Toggle breakpoint</b>: Will toggle a conditional breakpoint at the
scanLine where the mouse was clicked. You can also
scanline where the mouse was clicked. You can also
the Prompt Tab commands to list and turn off the breakpoint.</li>
<li><b>2x|4x|8x zoom</b>: Zoom in on the image for even greater detail.</li>
</ul>
@ -1327,40 +1288,13 @@ are lost (they will NOT end up in the Carry flag).</p>
<h2><a name="M6532"><u>(K)</u> M6532/RIOT RAM</a></h2>
<p>This is a spreadsheet-like GUI for inspecting and changing the contents
of the 2600's zero-page RAM.</p>
<p>You can navigate with either the mouse or the keyboard (see below).
<p>You can navigate with either the mouse or the keyboard arrow keys.
To change a RAM location, either double-click on it or press 'Enter' while
it's highlighted. Enter the new value (hex, other formats using the bottom textboxes), then
press 'Enter' to make the change. The currently selected RAM cell
can also be changed by using the
<a href="#DataOpButtons"><b>Data Operations Buttons</b></a> or the associated
shortcut keys.</p>
<p>You can navigate all RAM grids (and other data grids too) using the following keyboard shortcuts.</p>
<table border="1" cellpadding=4>
<tr>
<th>Shortut</th><th>Description</th>
</tr>
<tr>
<td>Left arrow</td><td>Move to left cell.</td>
</tr><tr>
<td>Right arrow</td><td>Move to right cell.</td>
</tr><tr>
<td>Home</td><td>Move to leftmost cell.</td>
</tr><tr>
<td>End</td><td>Move to rightmost cell.</td>
</tr><tr>
<td>Up arrow</td><td>Move to cell above.</td>
</tr><tr>
<td>Down arrow</td><td>Move to cell below.</td>
</tr><tr>
<td>Page Up</td><td>Move to top visible row.</td>
</tr><tr>
<td>Page Down</td><td>Move to bottom visible row.</td>
</tr><tr>
<td>Shift + Page Up</td><td>Scroll one page up.</td>
</tr><tr>
<td>Shift + Page Down</td><td>Scroll one page down.</td>
</table>
<p><img src="graphics/debugger_ram.png"></p>
<p>The 'Undo' button in the upper right should be self-explanatory; it will
undo the most previous operation to one cell only. The 'Revert' button is
@ -1441,7 +1375,7 @@ labels. Normally there will be nothing there: this indicates that there's
no breakpoint set at that address. You can set and clear breakpoints by
clicking in this area. When a breakpoint is set, there will be a
red circle in this area. These are the same breakpoints as used
by the <a href="#Breakpoints">break</a> command, <b>not</b> the conditional "breakIf" breakpoints
by the <a href="#Breakpoints">break</a> command, <b>not</b> the conditional "breakif" breakpoints
(which makes sense: conditional breaks can break on any condition, the Program
Counter isn't necessarily involved).</li>
<li><b>Labels</b>: Any labels assigned to the given address, either generated
@ -1539,7 +1473,7 @@ or lowercase for "illegal" 6502 instructions (like "dcp"). If automatic resolvin
of code sections has been disabled for any reason, you'll likely see a lot
of illegal opcodes if you scroll to a data table in ROM. This can also
occur if the disassembler hasn't yet encountered addresses in the PC.
If you step/trace/scanLine/frame advance into such an area, the disassembler
If you step/trace/scanline/frame advance into such an area, the disassembler
will make note of it, and disassemble it correctly from that point on.</p>
<!-- TODO - is this true any longer?
@ -1586,16 +1520,13 @@ matches the address of the disassembly line where the mouse was clicked.</li>
<li><b>Disassemble @ current line</b>: Disassemble from the disassembly line where the mouse was clicked.
This allows to fill gaps in the disassembly and is most useful for bankswitched ROMs.</li>
<li><b>Set timer @ current line</b>: Set a timer point using the current
disassembly line's address and bank</li>
<li><b>Show tentative code</b>: Allow DiStella to do a static analysis/disassembly.</li>
<li><b>Show PC addresses</b>: Show Program Counter addresses as labels (where there
isn't already a defined label).</li>
<li><b>Show GFX as binary</b>: Switch between displaying/editing GFX and PGFX sections
in either binary or hexadecimal.</li>
in either binary or hexidecimal.</li>
<li><b>Use address relocation</b>: Corresponds to the DiStella '-r' option
(Relocate calls out of address range).</br>
@ -1610,7 +1541,7 @@ Note: The code will continue to run fine, but the ROM image will be altered.</li
<li>The ROM Widget only works on ROM or zero-page RAM separately. If your game runs
code from zero-page RAM, the disassembly will show addresses $80 to $FF (zero-page
RAM address space) only. Once your RAM routine returns, the ROM Widget will switch
back to ROM space ($1000 - $1FFF and mirrors). The same is true of the "disAsm"
back to ROM space ($1000 - $1FFF and mirrors). The same is true of the "disasm"
command; it will show either ROM or RAM space, not both at the same time.</li>
<li>The standard VCS memory map has the cartridge port at locations
@ -1679,13 +1610,13 @@ space with the appropriate directive, there are times when it will fail. There a
several options in this case:</p>
<ol>
<li><b>Manually set the directives</b>: Directives can be set in the debugger
prompt with the aud/code/col/bcol/gfx/pCol/pGfx/data/row commands. These accept an address range
prompt with the aud/code/col/bcol/gfx/pcol/pgfx/data/row commands. These accept an address range
for the given directive type. Setting a range with the same type a second time
will remove that directive from the range.</li>
<li><b>Use configuration files</b>: Configuration files can be used to automatically
load a list of directives when a ROM is loaded. These files can be generated with the
'saveConfig' command, and loaded with the 'loadConfig' command. There are also
'listConfig' and 'clearConfig' commands to show and erase (respectively) the current
'saveconfig' command, and loaded with the 'loadconfig' command. There are also
'listconfig' and 'clearconfig' commands to show and erase (respectively) the current
directive listing. Upon opening the debugger for the first time, Stella attempts
to load a configuration file from the folder containing the ROM. Assuming a ROM named "rr.a26" exists, the config file must be named <i>rr.cfg</i>.
</ul>
@ -1758,7 +1689,7 @@ but it helps to know at least a little about 6502 programming.</p>
(for that, we have to disable the collision checking code, which means
we have to find and understand it first!)</li>
<li>Set a Write Trap on the lives counter address: "trapWrite $ba"
<li>Set a Write Trap on the lives counter address: "trapwrite $ba"
in the Prompt. Exit the debugger and play until you get killed. When
you die, the trap will cause the emulator to enter the debugger with the
Program Counter pointing to the instruction *after* the one that wrote
@ -1806,7 +1737,7 @@ but it helps to know at least a little about 6502 programming.</p>
will *still* see 3 lives: Success! We've hacked Battlezone to give us
infinite lives.</li>
<li>Save your work. In the prompt: "saveRom". You now
<li>Save your work. In the prompt: "saverom". You now
have your very own infinite-lives version of Battlezone. The file will
be saved in your HOME directory (NOT your ROM directory), so you might
want to move it to your ROM directory if it isn't the current directory.

View File

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.9 KiB

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 380 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 187 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.6 KiB

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 194 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 218 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 171 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 196 B

File diff suppressed because it is too large Load Diff

View File

@ -58,7 +58,7 @@
<center><h1>Stella for RetroN 77</h1></center>
<center><h2>Atari 2600 VCS emulator</h2></center>
<center>Release 7.0</center>
<center>Release 6.5.2</center>
<center><h2>Quick Navigation Guide</h2></center>
<br/>
@ -77,7 +77,7 @@
<tr>
<th width=110px>Joystick</th>
<th width=100px>Button</th>
<th width=200px>Action</th>
<th width=170px>Action</th>
</tr>
<tr>
<td>Button 4</td>
@ -95,17 +95,17 @@
<td>Open settings</td>
</tr>
<tr>
<td>Button 8</td>
<td>Button 7</td>
<td>-</td>
<td>Rewind game</td>
</tr>
<tr>
<td>Button 9</td>
<td>Button 8</td>
<td>MODE</td>
<td>Select</td>
</tr>
<tr>
<td>Button 10</td>
<td>Button 9</td>
<td>RESET</td>
<td>Reset</td>
</tr>
@ -119,7 +119,7 @@
<tr>
<th width=110px>Joystick</th>
<th width=100px>Button</th>
<th width=200px>Action</th>
<th width=170px>Action</th>
</tr>
<tr>
<td>Up</td>
@ -147,40 +147,10 @@
<td>Start selected game</td>
</tr>
<tr>
<td>Hold Button 1</td>
<td>-</td>
<td>Open a context menu with the following choices:
<ul>
<li>Add to favorites</li>
<li>Power-On options...</li>
<li>Go to initial directory</li>
<li>Go to parent directory</li>
<li><a href="#Settings">Settings...</a></li>
</ul>
Button 2 or 6 close the menu without any action.
</td>
</tr>
<tr>
<td>Button 1 + Left</td>
<td>-</td>
<td>Display previous image</td>
</tr>
<tr>
<td>Button 1 + Right</td>
<td>-</td>
<td>Display next image</td>
</tr>
<tr>
<td>Button 1 + Up</td>
<td>-</td>
<td>Toggle image zoom</td>
</tr>
<tr>
<td>Button 2</td>
<td>Button 2 or</br>hold Button 1</td>
<td>SKILL P2</td>
<td>Open Power-On options</td>
</tr>
<tr>
<td>Button 4</td>
<td>COLOR, B/W</td>
@ -196,7 +166,7 @@
<tr>
<th width=110px>Joystick</th>
<th width=100px>Button</th>
<th width=200px>Action</th>
<th width=170px>Action</th>
</tr>
<tr>
<td>Up</td>
@ -264,7 +234,7 @@
<td width="41%">This dialog is similar to the PC version's
<a href="index.html#CommandMenu"><b>Command Menu</b></a>, but with some
commands especially selected for the RetroN&nbsp;77.</td>
<td><p><img src="graphics/commandsmenu_r77.png"></p></td>
<td><p><img src="commandsmenu_r77.png"></p></td>
</tr>
</table>
</p>
@ -309,7 +279,7 @@
</tr>
</table>
</td>
<td><p><img src="graphics/basic_settings.png"></p></td>
<td><p><img src="basic_settings.png"></p></td>
</tr>
</table>
</p>

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2021 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
@ -21,19 +21,19 @@
#include "BankRomCheat.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
BankRomCheat::BankRomCheat(OSystem& os, string_view name, string_view code)
BankRomCheat::BankRomCheat(OSystem& os, const string& name, const string& code)
: Cheat(os, name, code)
{
if(myCode.length() == 7)
myCode = "0" + string{code};
myCode = "0" + code;
bank = BSPF::stoi<16>(myCode.substr(0, 2));
address = 0xf000 + BSPF::stoi<16>(myCode.substr(2, 3));
value = static_cast<uInt8>(BSPF::stoi<16>(myCode.substr(5, 2)));
count = static_cast<uInt8>(BSPF::stoi<16>(myCode.substr(7, 1)) + 1);
bank = unhex(myCode.substr(0, 2));
address = 0xf000 + unhex(myCode.substr(2, 3));
value = uInt8(unhex(myCode.substr(5, 2)));
count = uInt8(unhex(myCode.substr(7, 1)) + 1);
// Back up original data; we need this if the cheat is ever disabled
for(int i = 0; std::cmp_less(i, count); ++i)
for(int i = 0; i < count; ++i)
savedRom[i] = myOSystem.console().cartridge().peek(address + i);
}
@ -47,10 +47,10 @@ bool BankRomCheat::enable()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool BankRomCheat::disable()
{
const int oldBank = myOSystem.console().cartridge().getBank(address);
int oldBank = myOSystem.console().cartridge().getBank(address);
myOSystem.console().cartridge().bank(bank);
for(int i = 0; std::cmp_less(i, count); ++i)
for(int i = 0; i < count; ++i)
myOSystem.console().cartridge().patch(address + i, savedRom[i]);
myOSystem.console().cartridge().bank(oldBank);
@ -63,10 +63,10 @@ void BankRomCheat::evaluate()
{
if(!myEnabled)
{
const int oldBank = myOSystem.console().cartridge().getBank(address);
int oldBank = myOSystem.console().cartridge().getBank(address);
myOSystem.console().cartridge().bank(bank);
for(int i = 0; std::cmp_less(i, count); ++i)
for(int i = 0; i < count; ++i)
myOSystem.console().cartridge().patch(address + i, value);
myOSystem.console().cartridge().bank(oldBank);

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2021 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
@ -23,7 +23,7 @@
class BankRomCheat : public Cheat
{
public:
BankRomCheat(OSystem& os, string_view name, string_view code);
BankRomCheat(OSystem& os, const string& name, const string& code);
~BankRomCheat() override = default;
bool enable() override;
@ -31,7 +31,7 @@ class BankRomCheat : public Cheat
void evaluate() override;
private:
std::array<uInt8, 16> savedRom{};
std::array<uInt8, 16> savedRom;
uInt16 address{0};
uInt8 value{0};
uInt8 count{0};

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2021 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
@ -25,9 +25,9 @@ class OSystem;
class Cheat
{
public:
Cheat(OSystem& osystem, string_view name, string_view code)
Cheat(OSystem& osystem, const string& name, const string& code)
: myOSystem{osystem},
myName{name.empty() ? code : name},
myName{name == "" ? code : name},
myCode{code} { }
virtual ~Cheat() = default;
@ -40,6 +40,23 @@ class Cheat
virtual void evaluate() = 0;
protected:
static uInt16 unhex(const string& hex)
{
int ret = 0;
for(char c: hex)
{
ret *= 16;
if(c >= '0' && c <= '9')
ret += c - '0';
else if(c >= 'A' && c <= 'F')
ret += c - 'A' + 10;
else
ret += c - 'a' + 10;
}
return ret;
}
protected:
OSystem& myOSystem;

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2021 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
@ -25,6 +25,7 @@
#include "Font.hxx"
#include "InputTextDialog.hxx"
#include "OSystem.hxx"
#include "Props.hxx"
#include "Widget.hxx"
#include "CheatCodeDialog.hxx"
@ -42,15 +43,16 @@ CheatCodeDialog::CheatCodeDialog(OSystem& osystem, DialogContainer& parent,
VGAP = Dialog::vGap(),
VBORDER = Dialog::vBorder(),
HBORDER = Dialog::hBorder();
int xpos, ypos;
WidgetArray wid;
ButtonWidget* b = nullptr;
ButtonWidget* b;
// Set real dimensions
_w = 45 * fontWidth + HBORDER * 2;
_h = _th + 11 * (lineHeight + 4) + VBORDER * 2;
// List of cheats, with checkboxes to enable/disable
int xpos = HBORDER, ypos = _th + VBORDER;
xpos = HBORDER; ypos = _th + VBORDER;
myCheatList =
new CheckListWidget(this, font, xpos, ypos, _w - buttonWidth - HBORDER * 2 - fontWidth,
_h - _th - buttonHeight - VBORDER * 3);
@ -82,18 +84,18 @@ CheatCodeDialog::CheatCodeDialog(OSystem& osystem, DialogContainer& parent,
// Inputbox which will pop up when adding/editing a cheat
StringList labels;
labels.emplace_back("Name ");
labels.emplace_back("Code (hex) ");
labels.push_back("Name ");
labels.push_back("Code (hex) ");
myCheatInput = make_unique<InputTextDialog>(this, font, labels, "Cheat code");
myCheatInput->setTarget(this);
// Add filtering for each textfield
const EditableWidget::TextFilter f0 = [](char c) {
EditableWidget::TextFilter f0 = [](char c) {
return isprint(c) && c != '\"' && c != ':';
};
myCheatInput->setTextFilter(f0, 0);
const EditableWidget::TextFilter f1 = [](char c) {
EditableWidget::TextFilter f1 = [](char c) {
return (c >= 'a' && c <= 'f') || (c >= '0' && c <= '9');
};
myCheatInput->setTextFilter(f1, 1);
@ -105,12 +107,10 @@ CheatCodeDialog::CheatCodeDialog(OSystem& osystem, DialogContainer& parent,
wid.clear();
addOKCancelBGroup(wid, font);
addBGroupToFocusList(wid);
setHelpAnchor("Cheats");
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CheatCodeDialog::~CheatCodeDialog() // NOLINT (we need an empty d'tor)
CheatCodeDialog::~CheatCodeDialog()
{
}
@ -127,14 +127,14 @@ void CheatCodeDialog::loadConfig()
for(const auto& c: list)
{
l.push_back(c->name());
b.push_back(c->enabled());
b.push_back(bool(c->enabled()));
}
myCheatList->setList(l, b);
// Redraw the list, auto-selecting the first item if possible
myCheatList->setSelected(!l.empty() ? 0 : -1);
myCheatList->setSelected(l.size() > 0 ? 0 : -1);
const bool enabled = !list.empty();
bool enabled = (list.size() > 0);
myEditButton->setEnabled(enabled);
myRemoveButton->setEnabled(enabled);
}
@ -167,7 +167,7 @@ void CheatCodeDialog::addCheat()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CheatCodeDialog::editCheat()
{
const int idx = myCheatList->getSelected();
int idx = myCheatList->getSelected();
if(idx < 0)
return;
@ -232,7 +232,7 @@ void CheatCodeDialog::handleCommand(CommandSender* sender, int cmd,
{
const string& name = myCheatInput->getResult(0);
const string& code = myCheatInput->getResult(1);
if(CheatManager::isValidCode(code))
if(instance().cheat().isValidCode(code))
{
myCheatInput->close();
instance().cheat().add(name, code);
@ -247,9 +247,9 @@ void CheatCodeDialog::handleCommand(CommandSender* sender, int cmd,
{
const string& name = myCheatInput->getResult(0);
const string& code = myCheatInput->getResult(1);
const bool enable = myCheatList->getSelectedState();
const int idx = myCheatList->getSelected();
if(CheatManager::isValidCode(code))
bool enable = myCheatList->getSelectedState();
int idx = myCheatList->getSelected();
if(instance().cheat().isValidCode(code))
{
myCheatInput->close();
instance().cheat().add(name, code, enable, idx);
@ -272,7 +272,7 @@ void CheatCodeDialog::handleCommand(CommandSender* sender, int cmd,
{
const string& name = myCheatInput->getResult(0);
const string& code = myCheatInput->getResult(1);
if(CheatManager::isValidCode(code))
if(instance().cheat().isValidCode(code))
{
myCheatInput->close();
instance().cheat().addOneShot(name, code);

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2021 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-2025 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2021 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
@ -16,6 +16,7 @@
//============================================================================
#include "OSystem.hxx"
#include "Console.hxx"
#include "Cheat.hxx"
#include "Settings.hxx"
#include "CheetahCheat.hxx"
@ -32,10 +33,10 @@ CheatManager::CheatManager(OSystem& osystem)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CheatManager::add(string_view name, string_view code,
bool CheatManager::add(const string& name, const string& code,
bool enable, int idx)
{
const shared_ptr<Cheat> cheat = createCheat(name, code);
shared_ptr<Cheat> cheat = createCheat(name, code);
if(!cheat)
return false;
@ -67,7 +68,7 @@ bool CheatManager::add(string_view name, string_view code,
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CheatManager::remove(int idx)
{
if(static_cast<size_t>(idx) < myCheatList.size())
if(uInt32(idx) < myCheatList.size())
{
// This will also remove it from the per-frame list (if applicable)
myCheatList[idx]->disable();
@ -78,7 +79,7 @@ void CheatManager::remove(int idx)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CheatManager::addPerFrame(string_view name, string_view code, bool enable)
void CheatManager::addPerFrame(const string& name, const string& code, bool enable)
{
// The actual cheat will always be in the main list; we look there first
shared_ptr<Cheat> cheat;
@ -92,8 +93,8 @@ void CheatManager::addPerFrame(string_view name, string_view code, bool enable)
}
// Make sure there are no duplicates
bool found{false};
uInt32 i{0};
bool found = false;
uInt32 i;
for(i = 0; i < myPerFrameList.size(); ++i)
{
if(myPerFrameList[i]->code() == cheat->code())
@ -116,16 +117,16 @@ void CheatManager::addPerFrame(string_view name, string_view code, bool enable)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CheatManager::addOneShot(string_view name, string_view code)
void CheatManager::addOneShot(const string& name, const string& code)
{
// Evaluate this cheat once, and then immediately discard it
const shared_ptr<Cheat> cheat = createCheat(name, code);
shared_ptr<Cheat> cheat = createCheat(name, code);
if(cheat)
cheat->evaluate();
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
shared_ptr<Cheat> CheatManager::createCheat(string_view name, string_view code) const
shared_ptr<Cheat> CheatManager::createCheat(const string& name, const string& code) const
{
if(!isValidCode(code))
return nullptr;
@ -135,14 +136,14 @@ shared_ptr<Cheat> CheatManager::createCheat(string_view name, string_view code)
{
case 4: return make_shared<RamCheat>(myOSystem, name, code);
case 6: return make_shared<CheetahCheat>(myOSystem, name, code);
case 7: [[fallthrough]];
case 7: return make_shared<BankRomCheat>(myOSystem, name, code);
case 8: return make_shared<BankRomCheat>(myOSystem, name, code);
default: return nullptr;
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CheatManager::parse(string_view cheats)
void CheatManager::parse(const string& cheats)
{
StringList s;
string::size_type lastPos = cheats.find_first_not_of(',', 0);
@ -185,9 +186,6 @@ void CheatManager::parse(string_view cheats)
code = s[1];
add(name, code, s[2] == "1");
break;
default:
break;
}
s.clear();
@ -197,7 +195,7 @@ void CheatManager::parse(string_view cheats)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CheatManager::enable(string_view code, bool enable)
void CheatManager::enable(const string& code, bool enable)
{
for(const auto& cheat: myCheatList)
{
@ -220,17 +218,18 @@ void CheatManager::loadCheatDatabase()
catch(...) { return; }
string line, md5, cheat;
string::size_type one, two, three, four;
// Loop reading cheats
while(getline(in, line))
{
if(line.empty())
if(line.length() == 0)
continue;
const string::size_type one = line.find('\"', 0);
const string::size_type two = line.find('\"', one + 1);
const string::size_type three = line.find('\"', two + 1);
const string::size_type four = line.find('\"', three + 1);
one = line.find('\"', 0);
two = line.find('\"', one + 1);
three = line.find('\"', two + 1);
four = line.find('\"', three + 1);
// Invalid line if it doesn't contain 4 quotes
if((one == string::npos) || (two == string::npos) ||
@ -255,14 +254,14 @@ void CheatManager::saveCheatDatabase()
stringstream out;
for(const auto& [md5, cheat]: myCheatMap)
out << "\"" << md5 << "\" " << "\"" << cheat << "\"\n";
out << "\"" << md5 << "\" " << "\"" << cheat << "\"" << endl;
try { myOSystem.cheatFile().write(out); }
catch(...) { return; }
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CheatManager::loadCheats(string_view md5sum)
void CheatManager::loadCheats(const string& md5sum)
{
myPerFrameList.clear();
myCheatList.clear();
@ -271,11 +270,11 @@ void CheatManager::loadCheats(string_view md5sum)
// Set up any cheatcodes that was on the command line
// (and remove the key from the settings, so they won't get set again)
const string& cheats = myOSystem.settings().getString("cheat");
if(!cheats.empty())
if(cheats != "")
myOSystem.settings().setValue("cheat", "");
const auto& iter = myCheatMap.find(md5sum);
if(iter == myCheatMap.end() && cheats.empty())
if(iter == myCheatMap.end() && cheats == "")
return;
// Remember the cheats for this ROM
@ -286,7 +285,7 @@ void CheatManager::loadCheats(string_view md5sum)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void CheatManager::saveCheats(string_view md5sum)
void CheatManager::saveCheats(const string& md5sum)
{
ostringstream cheats;
for(uInt32 i = 0; i < myCheatList.size(); ++i)
@ -298,20 +297,20 @@ void CheatManager::saveCheats(string_view md5sum)
cheats << ",";
}
const bool changed = cheats.view() != myCurrentCheat;
bool changed = cheats.str() != myCurrentCheat;
// Only update the list if absolutely necessary
if(changed)
{
const auto iter = myCheatMap.find(md5sum);
auto iter = myCheatMap.find(md5sum);
// Erase old entry and add a new one only if it's changed
if(iter != myCheatMap.end())
myCheatMap.erase(iter);
// Add new entry only if there are any cheats defined
if(!cheats.view().empty())
myCheatMap.emplace(md5sum, cheats.view());
if(cheats.str() != "")
myCheatMap.emplace(md5sum, cheats.str());
}
// Update the dirty flag
@ -321,12 +320,12 @@ void CheatManager::saveCheats(string_view md5sum)
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CheatManager::isValidCode(string_view code)
bool CheatManager::isValidCode(const string& code) const
{
for(const auto c: code)
for(char c: code)
if(!isxdigit(c))
return false;
const size_t length = code.length();
uInt32 length = uInt32(code.length());
return (length == 4 || length == 6 || length == 7 || length == 8);
}

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2021 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
@ -38,7 +38,6 @@ class CheatManager
{
public:
explicit CheatManager(OSystem& osystem);
~CheatManager() = default;
/**
Adds the specified cheat to an internal list.
@ -50,7 +49,7 @@ class CheatManager
@return Whether the cheat was created and enabled.
*/
bool add(string_view name, string_view code,
bool add(const string& name, const string& code,
bool enable = true, int idx = -1);
/**
@ -69,7 +68,7 @@ class CheatManager
@param code The actual cheatcode
@param enable Add or remove the cheat to the per-frame list
*/
void addPerFrame(string_view name, string_view code, bool enable);
void addPerFrame(const string& name, const string& code, bool enable);
/**
Creates and enables a one-shot cheat. One-shot cheats are the
@ -79,7 +78,7 @@ class CheatManager
@param name Name of the cheat (not absolutely required)
@param code The actual cheatcode (in hex)
*/
void addOneShot(string_view name, string_view code);
void addOneShot(const string& name, const string& code);
/**
Enable/disabled the cheat specified by the given code.
@ -87,7 +86,7 @@ class CheatManager
@param code The actual cheatcode to search for
@param enable Enable/disable the cheat
*/
void enable(string_view code, bool enable);
void enable(const string& code, bool enable);
/**
Returns the game cheatlist.
@ -112,17 +111,17 @@ class CheatManager
/**
Load cheats for ROM with given MD5sum to cheatlist(s).
*/
void loadCheats(string_view md5sum);
void loadCheats(const string& md5sum);
/**
Saves cheats for ROM with given MD5sum to cheat map.
*/
void saveCheats(string_view md5sum);
void saveCheats(const string& md5sum);
/**
Checks if a code is valid.
*/
static bool isValidCode(string_view code);
bool isValidCode(const string& code) const;
private:
/**
@ -133,14 +132,14 @@ class CheatManager
@return The cheat (if was created), else nullptr.
*/
shared_ptr<Cheat> createCheat(string_view name, string_view code) const;
shared_ptr<Cheat> createCheat(const string& name, const string& code) const;
/**
Parses a list of cheats and adds/enables each one.
@param cheats Comma-separated list of cheats (without any names)
*/
void parse(string_view cheats);
void parse(const string& cheats);
private:
OSystem& myOSystem;
@ -148,7 +147,7 @@ class CheatManager
CheatList myCheatList;
CheatList myPerFrameList;
std::map<string,string, std::less<>> myCheatMap;
std::map<string,string> myCheatMap;
string myCheatFile;
// This is set each time a new cheat/ROM is loaded, for later

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2021 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
@ -21,14 +21,14 @@
#include "CheetahCheat.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CheetahCheat::CheetahCheat(OSystem& os, string_view name, string_view code)
CheetahCheat::CheetahCheat(OSystem& os, const string& name, const string& code)
: Cheat(os, name, code),
address{static_cast<uInt16>(0xf000 + BSPF::stoi<16>(code.substr(0, 3)))},
value{static_cast<uInt8>(BSPF::stoi<16>(code.substr(3, 2)))},
count{static_cast<uInt8>(BSPF::stoi<16>(code.substr(5, 1)) + 1)}
address{uInt16(0xf000 + unhex(code.substr(0, 3)))},
value{uInt8(unhex(code.substr(3, 2)))},
count{uInt8(unhex(code.substr(5, 1)) + 1)}
{
// Back up original data; we need this if the cheat is ever disabled
for(uInt8 i = 0; i < count; ++i)
for(int i = 0; i < count; ++i)
savedRom[i] = myOSystem.console().cartridge().peek(address + i);
}
@ -42,7 +42,7 @@ bool CheetahCheat::enable()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool CheetahCheat::disable()
{
for(uInt8 i = 0; i < count; ++i)
for(int i = 0; i < count; ++i)
myOSystem.console().cartridge().patch(address + i, savedRom[i]);
return myEnabled = false;
@ -53,7 +53,7 @@ void CheetahCheat::evaluate()
{
if(!myEnabled)
{
for(uInt8 i = 0; i < count; ++i)
for(int i = 0; i < count; ++i)
myOSystem.console().cartridge().patch(address + i, value);
myEnabled = true;

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2021 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
@ -23,7 +23,7 @@
class CheetahCheat : public Cheat
{
public:
CheetahCheat(OSystem& os, string_view name, string_view code);
CheetahCheat(OSystem& os, const string& name, const string& code);
~CheetahCheat() override = default;
bool enable() override;
@ -31,7 +31,7 @@ class CheetahCheat : public Cheat
void evaluate() override;
private:
std::array<uInt8, 16> savedRom{};
std::array<uInt8, 16> savedRom;
uInt16 address{0};
uInt8 value{0};
uInt8 count{0};

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2021 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
@ -23,10 +23,10 @@
#include "RamCheat.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
RamCheat::RamCheat(OSystem& os, string_view name, string_view code)
RamCheat::RamCheat(OSystem& os, const string& name, const string& code)
: Cheat(os, name, code),
address{static_cast<uInt16>(BSPF::stoi<16>(myCode.substr(0, 2)))},
value{static_cast<uInt8>(BSPF::stoi<16>(myCode.substr(2, 2)))}
address{uInt16(unhex(myCode.substr(0, 2)))},
value{uInt8(unhex(myCode.substr(2, 2)))}
{
}
@ -55,5 +55,5 @@ bool RamCheat::disable()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void RamCheat::evaluate()
{
myOSystem.console().system().pokeOob(address, value);
myOSystem.console().system().poke(address, value);
}

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2021 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
@ -23,7 +23,7 @@
class RamCheat : public Cheat
{
public:
RamCheat(OSystem& os, string_view name, string_view code);
RamCheat(OSystem& os, const string& name, const string& code);
~RamCheat() override = default;
bool enable() override;

View File

@ -7,8 +7,6 @@ MODULE_OBJS := \
src/cheat/BankRomCheat.o \
src/cheat/RamCheat.o
MODULE_TEST_OBJS =
MODULE_DIRS += \
src/cheat

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2021 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
@ -29,32 +29,28 @@ AudioQueue::AudioQueue(uInt32 fragmentSize, uInt32 capacity, bool isStereo)
{
const uInt8 sampleSize = myIsStereo ? 2 : 1;
myFragmentBuffer = make_unique<Int16[]>(
static_cast<size_t>(myFragmentSize) * sampleSize * (capacity + 2));
myFragmentBuffer = make_unique<Int16[]>(myFragmentSize * sampleSize * (capacity + 2));
for (uInt32 i = 0; i < capacity; ++i)
myFragmentQueue[i] = myAllFragments[i] = myFragmentBuffer.get() +
static_cast<size_t>(myFragmentSize) * sampleSize * i;
myFragmentQueue[i] = myAllFragments[i] = myFragmentBuffer.get() + i * sampleSize * myFragmentSize;
myAllFragments[capacity] = myFirstFragmentForEnqueue =
myFragmentBuffer.get() + static_cast<size_t>(myFragmentSize) * sampleSize *
capacity;
myFragmentBuffer.get() + capacity * sampleSize * myFragmentSize;
myAllFragments[capacity + 1] = myFirstFragmentForDequeue =
myFragmentBuffer.get() + static_cast<size_t>(myFragmentSize) * sampleSize *
(capacity + 1);
myFragmentBuffer.get() + (capacity + 1) * sampleSize * myFragmentSize;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 AudioQueue::capacity() const
{
return static_cast<uInt32>(myFragmentQueue.size());
return uInt32(myFragmentQueue.size());
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 AudioQueue::size() const
{
const lock_guard<mutex> guard(myMutex);
lock_guard<mutex> guard(myMutex);
return mySize;
}
@ -74,9 +70,9 @@ uInt32 AudioQueue::fragmentSize() const
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Int16* AudioQueue::enqueue(Int16* fragment)
{
const lock_guard<mutex> guard(myMutex);
lock_guard<mutex> guard(myMutex);
Int16* newFragment = nullptr;
Int16* newFragment;
if (!fragment) {
if (!myFirstFragmentForEnqueue) throw runtime_error("enqueue called empty");
@ -87,7 +83,7 @@ Int16* AudioQueue::enqueue(Int16* fragment)
return newFragment;
}
const auto capacity = static_cast<uInt8>(myFragmentQueue.size());
const uInt8 capacity = uInt8(myFragmentQueue.size());
const uInt8 fragmentIndex = (myNextFragment + mySize) % capacity;
newFragment = myFragmentQueue.at(fragmentIndex);
@ -105,7 +101,7 @@ Int16* AudioQueue::enqueue(Int16* fragment)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Int16* AudioQueue::dequeue(Int16* fragment)
{
const lock_guard<mutex> guard(myMutex);
lock_guard<mutex> guard(myMutex);
if (mySize == 0) return nullptr;
@ -128,7 +124,7 @@ Int16* AudioQueue::dequeue(Int16* fragment)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void AudioQueue::closeSink(Int16* fragment)
{
const lock_guard<mutex> guard(myMutex);
lock_guard<mutex> guard(myMutex);
if (myFirstFragmentForDequeue && fragment)
throw runtime_error("attempt to return unknown buffer on closeSink");

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2021 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
@ -24,7 +24,7 @@
#include "StaggeredLogger.hxx"
/**
This class implements an audio queue that acts both like a ring buffer
This class implements a an audio queue that acts both like a ring buffer
and a pool of audio fragments. The TIA emulation core fills a fragment
with samples and then returns it to the queue, receiving a new fragment
in return. The sound driver removes fragments for playback from the
@ -46,7 +46,6 @@ class AudioQueue
@param isStereo Whether samples are stereo or mono.
*/
AudioQueue(uInt32 fragmentSize, uInt32 capacity, bool isStereo);
~AudioQueue() = default;
/**
Capacity getter.
@ -134,6 +133,7 @@ class AudioQueue
StaggeredLogger myOverflowLogger{"audio buffer overflow", Logger::Level::INFO};
private:
AudioQueue() = delete;
AudioQueue(const AudioQueue&) = delete;
AudioQueue(AudioQueue&&) = delete;

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2021 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
@ -19,12 +19,12 @@
#include "Settings.hxx"
namespace {
constexpr uInt32 lboundInt(int x, int defaultValue)
uInt32 lboundInt(int x, int defaultValue)
{
return x <= 0 ? defaultValue : x;
}
constexpr AudioSettings::Preset normalizedPreset(int numericPreset)
AudioSettings::Preset normalizedPreset(int numericPreset)
{
return (
numericPreset >= static_cast<int>(AudioSettings::Preset::custom) &&
@ -32,14 +32,14 @@ namespace {
) ? static_cast<AudioSettings::Preset>(numericPreset) : AudioSettings::DEFAULT_PRESET;
}
constexpr AudioSettings::ResamplingQuality normalizeResamplingQuality(int numericResamplingQuality)
AudioSettings::ResamplingQuality normalizeResamplingQuality(int numericResamplingQuality)
{
return (
numericResamplingQuality >= static_cast<int>(AudioSettings::ResamplingQuality::nearestNeighbour) &&
numericResamplingQuality >= static_cast<int>(AudioSettings::ResamplingQuality::nearestNeightbour) &&
numericResamplingQuality <= static_cast<int>(AudioSettings::ResamplingQuality::lanczos_3)
) ? static_cast<AudioSettings::ResamplingQuality>(numericResamplingQuality) : AudioSettings::DEFAULT_RESAMPLING_QUALITY;
}
} // namespace
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
AudioSettings::AudioSettings(Settings& settings)
@ -51,10 +51,9 @@ AudioSettings::AudioSettings(Settings& settings)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void AudioSettings::normalize(Settings& settings)
{
const int settingPreset = settings.getInt(SETTING_PRESET);
const Preset preset = normalizedPreset(settingPreset);
if (static_cast<int>(preset) != settingPreset)
settings.setValue(SETTING_PRESET, static_cast<int>(DEFAULT_PRESET));
int settingPreset = settings.getInt(SETTING_PRESET);
Preset preset = normalizedPreset(settingPreset);
if (static_cast<int>(preset) != settingPreset) settings.setValue(SETTING_PRESET, static_cast<int>(DEFAULT_PRESET));
switch (settings.getInt(SETTING_SAMPLE_RATE)) {
case 44100:
@ -67,19 +66,32 @@ void AudioSettings::normalize(Settings& settings)
break;
}
const int settingBufferSize = settings.getInt(SETTING_BUFFER_SIZE);
switch (settings.getInt(SETTING_FRAGMENT_SIZE)) {
case 128:
case 256:
case 512:
case 1024:
case 2048:
case 4096:
break;
default:
settings.setValue(SETTING_FRAGMENT_SIZE, DEFAULT_FRAGMENT_SIZE);
break;
}
int settingBufferSize = settings.getInt(SETTING_BUFFER_SIZE);
if (settingBufferSize < 0 || settingBufferSize > MAX_BUFFER_SIZE) settings.setValue(SETTING_BUFFER_SIZE, DEFAULT_BUFFER_SIZE);
const int settingHeadroom = settings.getInt(SETTING_HEADROOM);
int settingHeadroom = settings.getInt(SETTING_HEADROOM);
if (settingHeadroom < 0 || settingHeadroom > MAX_HEADROOM) settings.setValue(SETTING_HEADROOM, DEFAULT_HEADROOM);
const int settingResamplingQuality = settings.getInt(SETTING_RESAMPLING_QUALITY);
const ResamplingQuality resamplingQuality =
normalizeResamplingQuality(settingResamplingQuality);
int settingResamplingQuality = settings.getInt(SETTING_RESAMPLING_QUALITY);
ResamplingQuality resamplingQuality = normalizeResamplingQuality(settingResamplingQuality);
if (static_cast<int>(resamplingQuality) != settingResamplingQuality)
settings.setValue(SETTING_RESAMPLING_QUALITY, static_cast<int>(DEFAULT_RESAMPLING_QUALITY));
const int settingVolume = settings.getInt(SETTING_VOLUME);
int settingVolume = settings.getInt(SETTING_VOLUME);
if (settingVolume < 0 || settingVolume > 100) settings.setValue(SETTING_VOLUME, DEFAULT_VOLUME);
}
@ -101,7 +113,7 @@ uInt32 AudioSettings::sampleRate()
uInt32 AudioSettings::fragmentSize()
{
updatePresetFromSettings();
return myPresetFragmentSize; // No longer configurable in sound backend
return customSettings() ? lboundInt(mySettings.getInt(SETTING_FRAGMENT_SIZE), DEFAULT_FRAGMENT_SIZE) : myPresetFragmentSize;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@ -141,6 +153,12 @@ uInt32 AudioSettings::volume() const
return lboundInt(mySettings.getInt(SETTING_VOLUME), 0);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 AudioSettings::device() const
{
return mySettings.getInt(SETTING_DEVICE);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool AudioSettings::enabled() const
{
@ -165,13 +183,15 @@ void AudioSettings::setPreset(AudioSettings::Preset preset)
case Preset::lowQualityMediumLag:
myPresetSampleRate = 44100;
myPresetFragmentSize = 1024;
myPresetBufferSize = 6;
myPresetHeadroom = 5;
myPresetResamplingQuality = ResamplingQuality::nearestNeighbour;
myPresetResamplingQuality = ResamplingQuality::nearestNeightbour;
break;
case Preset::highQualityMediumLag:
myPresetSampleRate = 44100;
myPresetFragmentSize = 1024;
myPresetBufferSize = 6;
myPresetHeadroom = 5;
myPresetResamplingQuality = ResamplingQuality::lanczos_2;
@ -179,6 +199,7 @@ void AudioSettings::setPreset(AudioSettings::Preset preset)
case Preset::highQualityLowLag:
myPresetSampleRate = 48000;
myPresetFragmentSize = 512;
myPresetBufferSize = 3;
myPresetHeadroom = 2;
myPresetResamplingQuality = ResamplingQuality::lanczos_2;
@ -186,6 +207,7 @@ void AudioSettings::setPreset(AudioSettings::Preset preset)
case Preset::ultraQualityMinimalLag:
myPresetSampleRate = 96000;
myPresetFragmentSize = 128;
myPresetBufferSize = 0;
myPresetHeadroom = 0;
myPresetResamplingQuality = ResamplingQuality::lanczos_3;
@ -207,6 +229,15 @@ void AudioSettings::setSampleRate(uInt32 sampleRate)
normalize(mySettings);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void AudioSettings::setFragmentSize(uInt32 fragmentSize)
{
if (!myIsPersistent) return;
mySettings.setValue(SETTING_FRAGMENT_SIZE, fragmentSize);
normalize(mySettings);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void AudioSettings::setBufferSize(uInt32 bufferSize)
{
@ -259,6 +290,14 @@ void AudioSettings::setVolume(uInt32 volume)
normalize(mySettings);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void AudioSettings::setDevice(uInt32 device)
{
if(!myIsPersistent) return;
mySettings.setValue(SETTING_DEVICE, device);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void AudioSettings::setEnabled(bool isEnabled)
{

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2021 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
@ -26,7 +26,7 @@ class AudioSettings
{
public:
enum class Preset: uInt8 {
enum class Preset {
custom = 1,
lowQualityMediumLag = 2,
highQualityMediumLag = 3,
@ -34,21 +34,23 @@ class AudioSettings
ultraQualityMinimalLag = 5
};
enum class ResamplingQuality: uInt8 {
nearestNeighbour = 1,
enum class ResamplingQuality {
nearestNeightbour = 1,
lanczos_2 = 2,
lanczos_3 = 3
};
static constexpr string_view SETTING_PRESET = "audio.preset";
static constexpr string_view SETTING_SAMPLE_RATE = "audio.sample_rate";
static constexpr string_view SETTING_BUFFER_SIZE = "audio.buffer_size";
static constexpr string_view SETTING_HEADROOM = "audio.headroom";
static constexpr string_view SETTING_RESAMPLING_QUALITY = "audio.resampling_quality";
static constexpr string_view SETTING_STEREO = "audio.stereo";
static constexpr string_view SETTING_VOLUME = "audio.volume";
static constexpr string_view SETTING_ENABLED = "audio.enabled";
static constexpr string_view SETTING_DPC_PITCH = "audio.dpc_pitch";
static constexpr const char* SETTING_PRESET = "audio.preset";
static constexpr const char* SETTING_SAMPLE_RATE = "audio.sample_rate";
static constexpr const char* SETTING_FRAGMENT_SIZE = "audio.fragment_size";
static constexpr const char* SETTING_BUFFER_SIZE = "audio.buffer_size";
static constexpr const char* SETTING_HEADROOM = "audio.headroom";
static constexpr const char* SETTING_RESAMPLING_QUALITY = "audio.resampling_quality";
static constexpr const char* SETTING_STEREO = "audio.stereo";
static constexpr const char* SETTING_VOLUME = "audio.volume";
static constexpr const char* SETTING_DEVICE = "audio.device";
static constexpr const char* SETTING_ENABLED = "audio.enabled";
static constexpr const char* SETTING_DPC_PITCH = "audio.dpc_pitch";
static constexpr Preset DEFAULT_PRESET = Preset::highQualityMediumLag;
static constexpr uInt32 DEFAULT_SAMPLE_RATE = 44100;
@ -125,16 +127,15 @@ class AudioSettings
private:
Settings& mySettings; // NOLINT: we want a reference here
Settings& mySettings;
Preset myPreset{Preset::custom};
uInt32 myPresetSampleRate{0};
uInt32 myPresetFragmentSize{1024}; // no longer configurable in sound backend
uInt32 myPresetFragmentSize{0};
uInt32 myPresetBufferSize{0};
uInt32 myPresetHeadroom{0};
ResamplingQuality myPresetResamplingQuality{ResamplingQuality::nearestNeighbour};
ResamplingQuality myPresetResamplingQuality{ResamplingQuality::nearestNeightbour};
bool myIsPersistent{true};
};

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2021 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
@ -24,7 +24,7 @@ string Base::toString(int value, Common::Base::Fmt outputBase)
{
static char vToS_buf[32]; // NOLINT : One place where C-style is acceptable
if(outputBase == Base::Fmt::DEFAULT)
if(outputBase == Base::Fmt::_DEFAULT)
outputBase = myDefaultBase;
switch(outputBase)
@ -47,83 +47,74 @@ string Base::toString(int value, Common::Base::Fmt outputBase)
case Base::Fmt::_10: // base 10: 3 or 5 bytes (depending on value)
if(value > -0x100 && value < 0x100)
std::ignore = std::snprintf(vToS_buf, 5, "%3d", static_cast<Int16>(value));
std::snprintf(vToS_buf, 5, "%3d", Int16(value));
else
std::ignore = std::snprintf(vToS_buf, 6, "%5d", value);
std::snprintf(vToS_buf, 6, "%5d", value);
break;
case Base::Fmt::_10_02: // base 10: 2 digits (with leading zero)
std::ignore = std::snprintf(vToS_buf, 3, "%02d", value);
std::snprintf(vToS_buf, 3, "%02d", value);
break;
case Base::Fmt::_10_3: // base 10: 3 digits
std::ignore = std::snprintf(vToS_buf, 4, "%3d", value);
std::snprintf(vToS_buf, 4, "%3d", value);
break;
case Base::Fmt::_10_4: // base 10: 4 digits
std::ignore = std::snprintf(vToS_buf, 5, "%4d", value);
std::snprintf(vToS_buf, 5, "%4d", value);
break;
case Base::Fmt::_10_5: // base 10: 5 digits
std::ignore = std::snprintf(vToS_buf, 6, "%5d", value);
std::snprintf(vToS_buf, 6, "%5d", value);
break;
case Base::Fmt::_10_6: // base 10: 6 digits
std::ignore = std::snprintf(vToS_buf, 7, "%6d", value);
std::snprintf(vToS_buf, 7, "%6d", value);
break;
case Base::Fmt::_10_8: // base 10: 8 digits
std::ignore = std::snprintf(vToS_buf, 9, "%8d", value);
std::snprintf(vToS_buf, 9, "%8d", value);
break;
case Base::Fmt::_16_1: // base 16: 1 byte wide
std::ignore = std::snprintf(
vToS_buf, 2, hexUppercase() ? "%1X" : "%1x", value);
std::snprintf(vToS_buf, 2, hexUppercase() ? "%1X" : "%1x", value);
break;
case Base::Fmt::_16_2: // base 16: 2 bytes wide
std::ignore = std::snprintf(
vToS_buf, 3, hexUppercase() ? "%02X" : "%02x", value);
std::snprintf(vToS_buf, 3, hexUppercase() ? "%02X" : "%02x", value);
break;
case Base::Fmt::_16_2_2:
std::ignore = std::snprintf(
vToS_buf, 6, hexUppercase() ? "%02X.%02X" : "%02x.%02x",
std::snprintf(vToS_buf, 6, hexUppercase() ? "%02X.%02X" : "%02x.%02x",
value >> 8, value & 0xff );
break;
case Base::Fmt::_16_3_2:
std::ignore = std::snprintf(
vToS_buf, 7, hexUppercase() ? "%03X.%02X" : "%03x.%02x",
std::snprintf(vToS_buf, 7, hexUppercase() ? "%03X.%02X" : "%03x.%02x",
value >> 8, value & 0xff );
break;
case Base::Fmt::_16_4: // base 16: 4 bytes wide
std::ignore = std::snprintf(
vToS_buf, 5, hexUppercase() ? "%04X" : "%04x", value);
std::snprintf(vToS_buf, 5, hexUppercase() ? "%04X" : "%04x", value);
break;
case Base::Fmt::_16_8: // base 16: 8 bytes wide
std::ignore = std::snprintf(
vToS_buf, 9, hexUppercase() ? "%08X" : "%08x", value);
std::snprintf(vToS_buf, 9, hexUppercase() ? "%08X" : "%08x", value);
break;
case Base::Fmt::_16: // base 16: 2, 4, 8 bytes (depending on value)
default:
if(value < 0x100)
std::ignore = std::snprintf(
vToS_buf, 3, hexUppercase() ? "%02X" : "%02x", value);
std::snprintf(vToS_buf, 3, hexUppercase() ? "%02X" : "%02x", value);
else if(value < 0x10000)
std::ignore = std::snprintf(
vToS_buf, 5, hexUppercase() ? "%04X" : "%04x", value);
std::snprintf(vToS_buf, 5, hexUppercase() ? "%04X" : "%04x", value);
else
std::ignore = std::snprintf(
vToS_buf, 9, hexUppercase() ? "%08X" : "%08x", value);
std::snprintf(vToS_buf, 9, hexUppercase() ? "%08X" : "%08x", value);
break;
}
return {vToS_buf};
return string(vToS_buf);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Base::Fmt Base::myDefaultBase = Base::Fmt::_16;
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
std::ios_base::fmtflags Base::myHexflags = std::ios_base::hex; // NOLINT
std::ios_base::fmtflags Base::myHexflags = std::ios_base::hex;
} // namespace Common
} // Namespace Common

View File

@ -8,7 +8,7 @@
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
// Copyright (c) 1995-2021 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
@ -38,7 +38,7 @@ class Base
// The base to use for conversion from integers to strings
// Note that the actual number of places will be determined by
// the magnitude of the value itself in the general case
enum class Fmt: uInt8 {
enum class Fmt {
_16, // base 16: 2, 4, 8 bytes (depending on value)
_16_1, // base 16: 1 byte wide
_16_2, // base 16: 2 bytes wide
@ -56,7 +56,7 @@ class Base
_2, // base 2: 8 or 16 bits (depending on value)
_2_8, // base 2: 1 byte (8 bits) wide
_2_16, // base 2: 2 bytes (16 bits) wide
DEFAULT
_DEFAULT
};
public:
@ -72,31 +72,31 @@ class Base
static bool hexUppercase() { return myHexflags & std::ios_base::uppercase; }
/** Output HEX digits in 0.5/1/2/4 byte format */
static std::ostream& HEX1(std::ostream& os) {
static inline std::ostream& HEX1(std::ostream& os) {
os.flags(myHexflags);
return os << std::setw(1);
}
static std::ostream& HEX2(std::ostream& os) {
static inline std::ostream& HEX2(std::ostream& os) {
os.flags(myHexflags);
return os << std::setw(2) << std::setfill('0');
}
static std::ostream& HEX3(std::ostream& os)
static inline std::ostream& HEX3(std::ostream& os)
{
os.flags(myHexflags);
return os << std::setw(3) << std::setfill('0');
}
static std::ostream& HEX4(std::ostream& os) {
static inline std::ostream& HEX4(std::ostream& os) {
os.flags(myHexflags);
return os << std::setw(4) << std::setfill('0');
}
static std::ostream& HEX8(std::ostream& os) {
static inline std::ostream& HEX8(std::ostream& os) {
os.flags(myHexflags);
return os << std::setw(8) << std::setfill('0');
}
/** Convert integer to a string in the given base format */
static string toString(int value,
Common::Base::Fmt outputBase = Common::Base::Fmt::DEFAULT);
Common::Base::Fmt outputBase = Common::Base::Fmt::_DEFAULT);
private:
// Default format to use when none is specified
@ -108,7 +108,6 @@ class Base
private:
// Following constructors and assignment operators not supported
Base() = delete;
~Base() = delete;
Base(const Base&) = delete;
Base(Base&&) = delete;
Base& operator=(const Base&) = delete;

View File

@ -1,251 +0,0 @@
//============================================================================
//
// SSSS tt lll lll
// SS SS tt ll ll
// SS tttttt eeee ll ll aaaa
// SSSS tt ee ee ll ll aa
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2025 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 <cmath>
#include "OSystem.hxx"
#include "Console.hxx"
#include "EventHandler.hxx"
#include "FBSurface.hxx"
#include "PNGLibrary.hxx"
#include "PropsSet.hxx"
#include "Bezel.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Bezel::Bezel(OSystem& osystem)
: myOSystem{osystem},
myFB{osystem.frameBuffer()}
{
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string Bezel::getName(const string& path, const Properties& props)
{
string imageName;
int index = 1; // skip property name
do
{
imageName = getName(props, index);
if(imageName != EmptyString)
{
// Note: JPG does not support transparency
const string imagePath = path + imageName + ".png";
const FSNode node(imagePath);
if(node.exists())
break;
}
} while(index != -1);
return imageName;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string Bezel::getName(const Properties& props, int& index)
{
if(++index == 1)
return props.get(PropType::Bezel_Name);
// Try to generate bezel name from cart name
const string& cartName = props.get(PropType::Cart_Name);
size_t pos = cartName.find_first_of('(');
if(pos == std::string::npos)
pos = cartName.length() + 1;
if(index < 10 && pos != std::string::npos && pos > 0)
{
// The following suffixes are from "The Official No-Intro Convention",
// covering all used combinations by "The Bezel Project" (except single ones)
// (Unl) = unlicensed (Homebrews)
const std::array<string, 8> suffixes = {
" (USA)", " (USA) (Proto)", " (USA) (Unl)", " (USA) (Hack)",
" (Europe)", " (Germany)", " (France) (Unl)", " (Australia)"
};
return cartName.substr(0, pos - 1) + suffixes[index - 2];
}
if(index == 10)
{
return "Atari-2600";
}
if(index == 11)
{
index = -1;
return "default";
}
return "";
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string Bezel::getName(int& index) const
{
return getName(myOSystem.console().properties(), index);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
uInt32 Bezel::borderSize(uInt32 x, uInt32 y, uInt32 size, Int32 step) const
{
uInt32 *pixels{nullptr}, pitch{0};
mySurface->basePtr(pixels, pitch);
pixels += x + y * pitch;
for(uInt32 i = 0; i < size; ++i, pixels += step)
{
uInt8 r{0}, g{0}, b{0}, a{0};
myFB.getRGBA(*pixels, &r, &g, &b, &a);
if(a < 255) // transparent pixel?
return i;
}
return size - 1;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
bool Bezel::load()
{
const Settings& settings = myOSystem.settings();
bool isValid = false;
string imageName;
#ifdef IMAGE_SUPPORT
const bool show = myOSystem.eventHandler().inTIAMode() &&
settings.getBool("bezel.show") &&
(settings.getBool("fullscreen") ||
settings.getBool("bezel.windowed"));
if(show)
{
if(!mySurface)
mySurface = myFB.allocateSurface(1, 1); // dummy size
try
{
const string& path = myOSystem.bezelDir().getPath();
VariantList metaData;
int index = 0;
do
{
imageName = getName(index);
if(imageName != EmptyString)
{
// Note: JPG does not support transparency
const string imagePath = path + imageName + ".png";
const FSNode node(imagePath);
if(node.exists())
{
isValid = true;
myOSystem.png().loadImage(imagePath, *mySurface, metaData);
break;
}
}
} while(index != -1);
}
catch(const runtime_error&) { cerr << "ERROR: Bezel load\n"; }
}
#else
const bool show = false;
#endif
if(isValid)
{
const Int32 w = mySurface->width();
const Int32 h = mySurface->height();
uInt32 top{0}, bottom{0}, left{0}, right{0};
if(settings.getBool("bezel.win.auto"))
{
// Determine transparent window inside bezel image
const uInt32 xCenter = w >> 1;
top = borderSize(xCenter, 0, h, w);
bottom = h - 1 - borderSize(xCenter, h - 1, h, -w);
const uInt32 yCenter = (bottom + top) >> 1;
left = borderSize(0, yCenter, w, 1);
right = w - 1 - borderSize(w - 1, yCenter, w, -1);
}
else
{
// BP: 13, 13, 0, 0%
// HY: 12, 12, 0, 0%
// P1: 25, 25, 11, 22%
// P2: 23, 23, 7, 20%
left = std::min(w - 1, static_cast<Int32>(w * settings.getInt("bezel.win.left") / 100. + .5)); // NOLINT
right = w - 1 - std::min(w - 1, static_cast<Int32>(w * settings.getInt("bezel.win.right") / 100. + .5)); // NOLINT
top = std::min(h - 1, static_cast<Int32>(h * settings.getInt("bezel.win.top") / 100. + .5)); // NOLINT
bottom = h - 1 - std::min(h - 1, static_cast<Int32>(h * settings.getInt("bezel.win.bottom") / 100. + .5)); // NOLINT
}
//cerr << (int)(right - left + 1) << " x " << (int)(bottom - top + 1) << " = "
// << double((int)(right - left + 1)) / double((int)(bottom - top + 1));
// Disable bezel is no transparent window was found
if(left < right && top < bottom)
myInfo = Info(Common::Size(w, h), Common::Rect(left, top, right, bottom));
else
{
if(mySurface)
myFB.deallocateSurface(mySurface);
mySurface = nullptr;
myInfo = Info();
myFB.showTextMessage("Invalid bezel image ('" + imageName + "')!");
isValid = false;
}
}
else
{
myInfo = Info();
if(show)
myFB.showTextMessage("No bezel image found");
}
return isValid;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Bezel::apply()
{
if(isShown())
{
const uInt32 bezelW =
std::min(myFB.screenSize().w,
static_cast<uInt32>(std::round(myFB.imageRect().w() * myInfo.ratioW())));
const uInt32 bezelH =
std::min(myFB.screenSize().h,
static_cast<uInt32>(std::round(myFB.imageRect().h() * myInfo.ratioH())));
// Position and scale bezel
mySurface->setDstSize(bezelW, bezelH);
mySurface->setDstPos((myFB.screenSize().w - bezelW) / 2, // center
(myFB.screenSize().h - bezelH) / 2);
mySurface->setScalingInterpolation(ScalingInterpolation::sharp);
// Note: Variable bezel window positions are handled in VideoModeHandler::Mode
// Enable blending to allow overlaying the bezel over the TIA output
mySurface->enableBlend(true);
mySurface->setBlendLevel(100);
mySurface->setVisible(true);
}
else
if(mySurface)
mySurface->setVisible(false);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void Bezel::render()
{
if(mySurface)
mySurface->render();
}

View File

@ -1,151 +0,0 @@
//============================================================================
//
// SSSS tt lll lll
// SS SS tt ll ll
// SS tttttt eeee ll ll aaaa
// SSSS tt ee ee ll ll aa
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================
#ifndef BEZEL_HXX
#define BEZEL_HXX
class OSystem;
class FBSurface;
class FrameBuffer;
class Properties;
#include "Rect.hxx"
/**
This class handles the bezels.
Bezels are loaded using a file name which is either a bezel name property or
is autogenerated from the cart name property. The bezels can be any size and
their transparent emulation window can be at any position. The position of
the window can be determined automatically.
+--------------------------------------+
| | display.h
+--------------------------------------+
| |
| +---------------+ |
| | window | |
| | | |
| | tia.h * zoom | |
| | | | bezel.h * zoom
| | | |
| +---------------+ |
| |
+--------------------------------------+ size
| |
+--------------------------------------+
The bezel and window sizes and their ratios are used for correct scaling.
@author Thomas Jentzsch
*/
class Bezel
{
public:
explicit Bezel(OSystem& osystem);
~Bezel() = default;
struct Info
{
private:
bool _isShown{false}; // Is bezel shown?
Common::Size _size{1, 1}; // Bezel size
Common::Rect _window{1, 1}; // Area of transparent TIA window inside bezel
public:
explicit Info() = default;
explicit Info(Common::Size size, Common::Rect window)
: _isShown{true}, _size{size}, _window{window} { }
bool isShown() const { return _isShown; }
Common::Size size() const { return _size; }
Common::Rect window() const { return _window; }
// Ratios between bezel sizes and TIA window sizes
double ratioW() const { return static_cast<double>(size().w) / window().w(); }
double ratioH() const { return static_cast<double>(size().h) / window().h(); }
};
// Structure access methods
const Info& info() const { return myInfo; }
bool isShown() const { return myInfo.isShown(); }
Common::Size size() const { return myInfo.size(); }
Common::Rect window() const { return myInfo.window(); }
// Ratio between bezel size and TIA window size
double ratioW() const { return myInfo.ratioW(); }
double ratioH() const { return myInfo.ratioH(); }
/*
Calculate size of a bezel border.
*/
uInt32 borderSize(uInt32 x, uInt32 y, uInt32 size, Int32 step) const;
/*
Load the bezel.
*/
bool load();
/*
Display scaled bezel.
*/
void apply();
/*
Render bezel surface
*/
void render();
/*
Generate bezel file name.
*/
static string getName(const string& path, const Properties& props);
private:
/*
Generate bezel file name.
*/
static string getName(const Properties& props, int& index);
/*
Generate bezel file name.
*/
string getName(int& index) const;
private:
// The parent system for the bezel
OSystem& myOSystem;
// Pointer to the FrameBuffer object
FrameBuffer& myFB;
// The bezel surface which blends over the TIA surface
shared_ptr<FBSurface> mySurface;
// Bezel info structure
Info myInfo;
private:
// Following constructors and assignment operators not supported
Bezel() = delete;
Bezel(const Bezel&) = delete;
Bezel(Bezel&&) = delete;
Bezel& operator=(const Bezel&) = delete;
Bezel& operator=(Bezel&&) = delete;
};
#endif

View File

@ -1,250 +0,0 @@
//============================================================================
//
// SSSS tt lll lll
// SS SS tt ll ll
// SS tttttt eeee ll ll aaaa
// SSSS tt ee ee ll ll aa
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2025 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 "Console.hxx"
#include "EventHandler.hxx"
#include "M6502.hxx"
#include "OSystem.hxx"
#include "RewindManager.hxx"
#include "Settings.hxx"
#include "StateManager.hxx"
#include "TIA.hxx"
#include "Cart.hxx"
#include "CartELF.hxx"
#include "DevSettingsHandler.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
DevSettingsHandler::DevSettingsHandler(OSystem& osystem)
: myOSystem{osystem}
{
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void DevSettingsHandler::loadSettings(SettingsSet set)
{
const bool devSettings = set == SettingsSet::developer;
const string& prefix = devSettings ? "dev." : "plr.";
const Settings& settings = myOSystem.settings();
myFrameStats[set] = settings.getBool(prefix + "stats");
myDetectedInfo[set] = settings.getBool(prefix + "detectedinfo");
// AtariVox/SaveKey/PlusROM access
myExternAccess[set] = settings.getBool(prefix + "extaccess");
myConsole[set] = settings.getString(prefix + "console") == "7800" ? 1 : 0;
myPlusROM[set] = devSettings ? settings.getBool("dev.plusroms.on") : true;
// Randomization
myRandomBank[set] = settings.getBool(prefix + "bankrandom");
myRandomizeTIA[set] = settings.getBool(prefix + "tiarandom");
myRandomizeRAM[set] = settings.getBool(prefix + "ramrandom");
myRandomizeCPU[set] = settings.getString(prefix + "cpurandom");
// Random hotspot peeks
myRandomHotspots[set] = devSettings ? settings.getBool("dev.hsrandom") : false;
// Undriven TIA pins
myUndrivenPins[set] = devSettings ? settings.getBool("dev.tiadriven") : false;
#ifdef DEBUGGER_SUPPORT
// Read from write ports break
myRWPortBreak[set] = devSettings ? settings.getBool("dev.rwportbreak") : false;
// Write to read ports break
myWRPortBreak[set] = devSettings ? settings.getBool("dev.wrportbreak") : false;
#endif
// Thumb ARM emulation exception
myThumbException[set] = devSettings ? settings.getBool("dev.thumb.trapfatal") : false;
myArmSpeed[set] = devSettings ? settings.getInt("dev.arm.mips") : CartridgeELF::MIPS_MAX;
// TIA tab
myTIAType[set] = devSettings ? settings.getString("dev.tia.type") : "standard";
myPlInvPhase[set] = devSettings ? settings.getBool("dev.tia.plinvphase") : false;
myMsInvPhase[set] = devSettings ? settings.getBool("dev.tia.msinvphase") : false;
myBlInvPhase[set] = devSettings ? settings.getBool("dev.tia.blinvphase") : false;
myPlLateHMove[set] = devSettings ? settings.getBool("dev.tia.pllatehmove") : false;
myMsLateHMove[set] = devSettings ? settings.getBool("dev.tia.mslatehmove") : false;
myBlLateHMove[set] = devSettings ? settings.getBool("dev.tia.bllatehmove") : false;
myPFBits[set] = devSettings ? settings.getBool("dev.tia.delaypfbits") : false;
myPFColor[set] = devSettings ? settings.getBool("dev.tia.delaypfcolor") : false;
myPFScore[set] = devSettings ? settings.getBool("dev.tia.pfscoreglitch") : false;
myBKColor[set] = devSettings ? settings.getBool("dev.tia.delaybkcolor") : false;
myPlSwap[set] = devSettings ? settings.getBool("dev.tia.delayplswap") : false;
myBlSwap[set] = devSettings ? settings.getBool("dev.tia.delayblswap") : false;
// Debug colors
myDebugColors[set] = settings.getBool(prefix + "debugcolors");
// PAL color-loss effect
myColorLoss[set] = settings.getBool(prefix + "colorloss");
// Jitter
myTVJitter[set] = settings.getBool(prefix + "tv.jitter");
myTVJitterSense[set] = settings.getInt(prefix + "tv.jitter_sense");
myTVJitterRec[set] = settings.getInt(prefix + "tv.jitter_recovery");
// States
myTimeMachine[set] = settings.getBool(prefix + "timemachine");
myStateSize[set] = settings.getInt(prefix + "tm.size");
myUncompressed[set] = settings.getInt(prefix + "tm.uncompressed");
myStateInterval[set] = settings.getString(prefix + "tm.interval");
myStateHorizon[set] = settings.getString(prefix + "tm.horizon");
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void DevSettingsHandler::saveSettings(SettingsSet set)
{
const bool devSettings = set == SettingsSet::developer;
const string& prefix = devSettings ? "dev." : "plr.";
Settings& settings = myOSystem.settings();
settings.setValue(prefix + "stats", myFrameStats[set]);
settings.setValue(prefix + "detectedinfo", myDetectedInfo[set]);
settings.setValue(prefix + "console", myConsole[set] == 1 ? "7800" : "2600");
if(myOSystem.hasConsole())
myOSystem.eventHandler().set7800Mode();
// Randomization
settings.setValue(prefix + "bankrandom", myRandomBank[set]);
settings.setValue(prefix + "tiarandom", myRandomizeTIA[set]);
settings.setValue(prefix + "ramrandom", myRandomizeRAM[set]);
settings.setValue(prefix + "cpurandom", myRandomizeCPU[set]);
if(devSettings)
{
settings.setValue("dev.plusroms.on", myPlusROM[set]);
settings.setValue("dev.hsrandom", myRandomHotspots[set]);
// Undriven TIA pins
settings.setValue("dev.tiadriven", myUndrivenPins[set]);
#ifdef DEBUGGER_SUPPORT
// Read from write ports break
settings.setValue("dev.rwportbreak", myRWPortBreak[set]);
// Write to read ports break
settings.setValue("dev.wrportbreak", myWRPortBreak[set]);
#endif
// Thumb ARM emulation exception
settings.setValue("dev.thumb.trapfatal", myThumbException[set]);
settings.setValue("dev.arm.mips", myArmSpeed[set]);
}
// AtariVox/SaveKey/PlusROM access
settings.setValue(prefix + "extaccess", myExternAccess[set]);
// TIA tab
if(devSettings)
{
settings.setValue("dev.tia.type", myTIAType[set]);
if(BSPF::equalsIgnoreCase("custom", myTIAType[set]))
{
settings.setValue("dev.tia.plinvphase", myPlInvPhase[set]);
settings.setValue("dev.tia.msinvphase", myMsInvPhase[set]);
settings.setValue("dev.tia.blinvphase", myBlInvPhase[set]);
settings.setValue("dev.tia.pllatehmove", myPlLateHMove[set]);
settings.setValue("dev.tia.mslatehmove", myMsLateHMove[set]);
settings.setValue("dev.tia.bllatehmove", myBlLateHMove[set]);
settings.setValue("dev.tia.delaypfbits", myPFBits[set]);
settings.setValue("dev.tia.delaypfcolor", myPFColor[set]);
settings.setValue("dev.tia.pfscoreglitch", myPFScore[set]);
settings.setValue("dev.tia.delaybkcolor", myBKColor[set]);
settings.setValue("dev.tia.delayplswap", myPlSwap[set]);
settings.setValue("dev.tia.delayblswap", myBlSwap[set]);
}
}
// Debug colors
settings.setValue(prefix + "debugcolors", myDebugColors[set]);
// PAL color loss
settings.setValue(prefix + "colorloss", myColorLoss[set]);
// Jitter
settings.setValue(prefix + "tv.jitter", myTVJitter[set]);
settings.setValue(prefix + "tv.jitter_sense", myTVJitterSense[set]);
settings.setValue(prefix + "tv.jitter_recovery", myTVJitterRec[set]);
// States
settings.setValue(prefix + "timemachine", myTimeMachine[set]);
settings.setValue(prefix + "tm.size", myStateSize[set]);
settings.setValue(prefix + "tm.uncompressed", myUncompressed[set]);
settings.setValue(prefix + "tm.interval", myStateInterval[set]);
settings.setValue(prefix + "tm.horizon", myStateHorizon[set]);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void DevSettingsHandler::applySettings(SettingsSet set)
{
// *** Emulation tab ***
myOSystem.frameBuffer().showFrameStats(myFrameStats[set]);
if(myOSystem.hasConsole())
{
myOSystem.console().cartridge().enableRandomHotspots(myRandomHotspots[set]);
myOSystem.console().tia().driveUnusedPinsRandom(myUndrivenPins[set]);
myOSystem.console().cartridge().enablePlusROM(myPlusROM[set]);
// Notes:
// - thumb exceptions not updated, because set in cart constructor
// - other missing settings are used on-the-fly
}
#ifdef DEBUGGER_SUPPORT
// Read from write ports and write to read ports breaks
if(myOSystem.hasConsole())
{
myOSystem.console().system().m6502().setReadFromWritePortBreak(myRWPortBreak[set]);
myOSystem.console().system().m6502().setWriteToReadPortBreak(myWRPortBreak[set]);
}
#endif
// *** TIA tab ***
if(myOSystem.hasConsole())
{
myOSystem.console().tia().setPlInvertedPhaseClock(myPlInvPhase[set]);
myOSystem.console().tia().setMsInvertedPhaseClock(myMsInvPhase[set]);
myOSystem.console().tia().setBlInvertedPhaseClock(myBlInvPhase[set]);
myOSystem.console().tia().setPlShortLateHMove(myPlLateHMove[set]);
myOSystem.console().tia().setMsShortLateHMove(myMsLateHMove[set]);
myOSystem.console().tia().setBlShortLateHMove(myBlLateHMove[set]);
myOSystem.console().tia().setPFBitsDelay(myPFBits[set]);
myOSystem.console().tia().setPFColorDelay(myPFColor[set]);
myOSystem.console().tia().setPFScoreGlitch(myPFScore[set]);
myOSystem.console().tia().setBKColorDelay(myBKColor[set]);
myOSystem.console().tia().setPlSwapDelay(myPlSwap[set]);
myOSystem.console().tia().setBlSwapDelay(myBlSwap[set]);
}
// *** Video tab ***
if(myOSystem.hasConsole())
{
// TV Jitter
myOSystem.console().tia().toggleJitter(myTVJitter[set] ? 1 : 0);
myOSystem.console().tia().setJitterSensitivity(myTVJitterSense[set]);
myOSystem.console().tia().setJitterRecoveryFactor(myTVJitterRec[set]);
// PAL color loss
myOSystem.console().enableColorLoss(myColorLoss[set]);
}
// Debug colours
handleEnableDebugColors(myDebugColors[set]);
// *** Time Machine tab ***
// update RewindManager
myOSystem.state().rewindManager().setup();
myOSystem.state().setRewindMode(myTimeMachine[set] ?
StateManager::Mode::TimeMachine : StateManager::Mode::Off);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void DevSettingsHandler::handleEnableDebugColors(bool enable)
{
if(myOSystem.hasConsole())
{
const bool fixed = myOSystem.console().tia().usingFixedColors();
if(fixed != enable)
myOSystem.console().tia().toggleFixedColors();
}
}

View File

@ -1,104 +0,0 @@
//============================================================================
//
// SSSS tt lll lll
// SS SS tt ll ll
// SS tttttt eeee ll ll aaaa
// SSSS tt ee ee ll ll aa
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2025 by Bradford W. Mott, Stephen Anthony
// and the Stella Team
//
// See the file "License.txt" for information on usage and redistribution of
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
//============================================================================
#ifndef DEV_SETTINGS_HANDLER_HXX
#define DEV_SETTINGS_HANDLER_HXX
class OSystem;
#include <array>
#include "bspf.hxx"
/**
This class takes care of developer settings sets.
@author Thomas Jentzsch
*/
class DevSettingsHandler
{
public:
enum SettingsSet: uInt8 {
player,
developer,
numSets
};
explicit DevSettingsHandler(OSystem& osystem);
~DevSettingsHandler() = default;
void loadSettings(SettingsSet set);
void saveSettings(SettingsSet set);
void applySettings(SettingsSet set);
protected:
OSystem& myOSystem;
// Emulator sets
std::array<bool, numSets> myFrameStats{};
std::array<bool, numSets> myDetectedInfo{};
std::array<bool, numSets> myExternAccess{};
std::array<int, numSets> myConsole{};
std::array<int, numSets> myPlusROM{};
std::array<bool, numSets> myRandomBank{};
std::array<bool, numSets> myRandomizeTIA{};
std::array<bool, numSets> myRandomizeRAM{};
std::array<string, numSets> myRandomizeCPU{};
std::array<bool, numSets> myColorLoss{};
std::array<bool, numSets> myTVJitter{};
std::array<int, numSets> myTVJitterSense{};
std::array<int, numSets> myTVJitterRec{};
std::array<bool, numSets> myDebugColors{};
std::array<bool, numSets> myRandomHotspots{};
std::array<bool, numSets> myUndrivenPins{};
#ifdef DEBUGGER_SUPPORT
std::array<bool, numSets> myRWPortBreak{};
std::array<bool, numSets> myWRPortBreak{};
#endif
std::array<bool, numSets> myThumbException{};
std::array<int, numSets> myArmSpeed{};
// TIA sets
std::array<string, numSets> myTIAType{};
std::array<bool, numSets> myPlInvPhase{};
std::array<bool, numSets> myMsInvPhase{};
std::array<bool, numSets> myBlInvPhase{};
std::array<bool, numSets> myPlLateHMove{};
std::array<bool, numSets> myMsLateHMove{};
std::array<bool, numSets> myBlLateHMove{};
std::array<bool, numSets> myPFBits{};
std::array<bool, numSets> myPFColor{};
std::array<bool, numSets> myPFScore{};
std::array<bool, numSets> myBKColor{};
std::array<bool, numSets> myPlSwap{};
std::array<bool, numSets> myBlSwap{};
// States sets
std::array<bool, numSets> myTimeMachine{};
std::array<int, numSets> myStateSize{};
std::array<int, numSets> myUncompressed{};
std::array<string, numSets> myStateInterval{};
std::array<string, numSets> myStateHorizon{};
private:
void handleEnableDebugColors(bool enable);
// Following constructors and assignment operators not supported
DevSettingsHandler() = delete;
DevSettingsHandler(const DevSettingsHandler&) = delete;
DevSettingsHandler(DevSettingsHandler&&) = delete;
DevSettingsHandler& operator=(const DevSettingsHandler&) = delete;
DevSettingsHandler& operator=(DevSettingsHandler&&) = delete;
};
#endif

View File

@ -1,288 +0,0 @@
//============================================================================
//
// SSSS tt lll lll
// SS SS tt ll ll
// SS tttttt eeee ll ll aaaa
// SSSS tt ee ee ll ll aa
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
// SS SS tt ee ll ll aa aa
// SSSS ttt eeeee llll llll aaaaa
//
// Copyright (c) 1995-2025 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 "Logger.hxx"
#include "OSystem.hxx"
#include "EventHandlerSDL.hxx"
#include "ThreadDebugging.hxx"
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EventHandlerSDL::EventHandlerSDL(OSystem& osystem)
: EventHandler{osystem}
{
ASSERT_MAIN_THREAD;
#ifdef GUI_SUPPORT
{
ostringstream buf;
myQwertz = int{'y'} == static_cast<int>
(SDL_GetKeyFromScancode(static_cast<SDL_Scancode>(KBDK_Z), static_cast<SDL_Keymod>(StellaMod::KBDM_NONE), false));
buf << "Keyboard: " << (myQwertz ? "QWERTZ" : "QWERTY");
Logger::debug(buf.view());
}
#endif
#ifdef JOYSTICK_SUPPORT
if(!SDL_InitSubSystem(SDL_INIT_JOYSTICK))
{
ostringstream buf;
buf << "ERROR: Couldn't initialize SDL joystick support: "
<< SDL_GetError() << '\n';
Logger::error(buf.view());
}
Logger::debug("EventHandlerSDL::EventHandlerSDL SDL_INIT_JOYSTICK");
#endif
SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1");
//SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_SYSTEM_SCALE, "1");
//SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_MODE_CENTER, "0");
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EventHandlerSDL::~EventHandlerSDL()
{
ASSERT_MAIN_THREAD;
if(SDL_WasInit(SDL_INIT_JOYSTICK))
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandlerSDL::copyText(const string& text) const
{
SDL_SetClipboardText(text.c_str());
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
string EventHandlerSDL::pasteText(string& text) const
{
if(SDL_HasClipboardText())
text = SDL_GetClipboardText();
else
text = "";
return text;
};
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void EventHandlerSDL::pollEvent()
{
ASSERT_MAIN_THREAD;
while(SDL_PollEvent(&myEvent))
{
switch(myEvent.type)
{
// keyboard events
case SDL_EVENT_KEY_UP:
case SDL_EVENT_KEY_DOWN:
{
handleKeyEvent(static_cast<StellaKey>(myEvent.key.scancode),
static_cast<StellaMod>(myEvent.key.mod),
myEvent.type == SDL_EVENT_KEY_DOWN,
myEvent.key.repeat);
break;
}
case SDL_EVENT_TEXT_INPUT:
{
handleTextEvent(*(myEvent.text.text));
break;
}
case SDL_EVENT_MOUSE_MOTION:
{
handleMouseMotionEvent(myEvent.motion.x, myEvent.motion.y,
myEvent.motion.xrel, myEvent.motion.yrel);
break;
}
case SDL_EVENT_MOUSE_BUTTON_DOWN:
case SDL_EVENT_MOUSE_BUTTON_UP:
{
// ToDo: check support of more buttons and double-click
MouseButton b{MouseButton::NONE};
switch(myEvent.button.button)
{
case SDL_BUTTON_LEFT:
b = MouseButton::LEFT;
break;
case SDL_BUTTON_RIGHT:
b = MouseButton::RIGHT;
break;
case SDL_BUTTON_MIDDLE:
b = MouseButton::MIDDLE;
break;
default:
break;
}
handleMouseButtonEvent(b, myEvent.button.type == SDL_EVENT_MOUSE_BUTTON_DOWN,
myEvent.button.x, myEvent.button.y);
break;
}
case SDL_EVENT_MOUSE_WHEEL:
{
// TODO: SDL now uses float for mouse coords, but the core still
// uses int throughout; maybe this is sufficient?
float x{0.F}, y{0.F};
SDL_GetMouseState(&x, &y); // we need mouse position too
if(myEvent.wheel.y < 0)
handleMouseButtonEvent(MouseButton::WHEELDOWN, true,
static_cast<int>(x), static_cast<int>(y));
else if(myEvent.wheel.y > 0)
handleMouseButtonEvent(MouseButton::WHEELUP, true,
static_cast<int>(x), static_cast<int>(y));
break;
}
#ifdef JOYSTICK_SUPPORT
case SDL_EVENT_JOYSTICK_BUTTON_UP:
case SDL_EVENT_JOYSTICK_BUTTON_DOWN:
{
handleJoyBtnEvent(myEvent.jbutton.which, myEvent.jbutton.button,
myEvent.jbutton.down);
break;
}
case SDL_EVENT_JOYSTICK_AXIS_MOTION:
{
handleJoyAxisEvent(myEvent.jaxis.which, myEvent.jaxis.axis,
myEvent.jaxis.value);
break;
}
case SDL_EVENT_JOYSTICK_HAT_MOTION:
{
int value = 0;
const int v = myEvent.jhat.value;
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;
}
case SDL_EVENT_JOYSTICK_ADDED:
{
addPhysicalJoystick(make_shared<JoystickSDL>(myEvent.jdevice.which));
break;
}
case SDL_EVENT_JOYSTICK_REMOVED:
{
removePhysicalJoystick(myEvent.jdevice.which);
break;
}
#endif
case SDL_EVENT_QUIT:
{
handleEvent(Event::Quit);
break;
}
case SDL_EVENT_WINDOW_SHOWN:
handleSystemEvent(SystemEvent::WINDOW_SHOWN);
break;
case SDL_EVENT_WINDOW_HIDDEN:
handleSystemEvent(SystemEvent::WINDOW_HIDDEN);
break;
case SDL_EVENT_WINDOW_EXPOSED:
handleSystemEvent(SystemEvent::WINDOW_EXPOSED);
break;
case SDL_EVENT_WINDOW_MOVED:
handleSystemEvent(SystemEvent::WINDOW_MOVED,
myEvent.window.data1, myEvent.window.data1);
break;
case SDL_EVENT_WINDOW_RESIZED:
handleSystemEvent(SystemEvent::WINDOW_RESIZED,
myEvent.window.data1, myEvent.window.data1);
break;
case SDL_EVENT_WINDOW_MINIMIZED:
handleSystemEvent(SystemEvent::WINDOW_MINIMIZED);
break;
case SDL_EVENT_WINDOW_MAXIMIZED:
handleSystemEvent(SystemEvent::WINDOW_MAXIMIZED);
break;
case SDL_EVENT_WINDOW_RESTORED:
handleSystemEvent(SystemEvent::WINDOW_RESTORED);
break;
case SDL_EVENT_WINDOW_MOUSE_ENTER:
handleSystemEvent(SystemEvent::WINDOW_ENTER);
break;
case SDL_EVENT_WINDOW_MOUSE_LEAVE:
handleSystemEvent(SystemEvent::WINDOW_LEAVE);
break;
case SDL_EVENT_WINDOW_FOCUS_GAINED:
handleSystemEvent(SystemEvent::WINDOW_FOCUS_GAINED);
break;
case SDL_EVENT_WINDOW_FOCUS_LOST:
handleSystemEvent(SystemEvent::WINDOW_FOCUS_LOST);
break;
case SDL_EVENT_SYSTEM_THEME_CHANGED:
handleSystemEvent(SystemEvent::THEME_CHANGED);
break;
default:
break;
}
}
}
#ifdef JOYSTICK_SUPPORT
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EventHandlerSDL::JoystickSDL::JoystickSDL(int idx)
{
ASSERT_MAIN_THREAD;
// NOLINTNEXTLINE: we want to initialize here, not in the member list
myStick = SDL_OpenJoystick(idx);
if(myStick)
{
// In Windows, all XBox controllers using the XInput API seem to name
// the controller as "XInput Controller". This would be fine, except
// it also appends " #x", where x seems to vary. Obviously this wreaks
// havoc with the idea that a joystick will always have the same name.
// So we truncate the number.
const char* const sdlname = SDL_GetJoystickName(myStick);
const string& desc = BSPF::startsWithIgnoreCase(sdlname, "XInput Controller")
? "XInput Controller" : sdlname;
initialize(SDL_GetJoystickID(myStick), desc,
SDL_GetNumJoystickAxes(myStick),
SDL_GetNumJoystickButtons(myStick),
SDL_GetNumJoystickHats(myStick),
SDL_GetNumJoystickBalls(myStick));
}
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
EventHandlerSDL::JoystickSDL::~JoystickSDL()
{
ASSERT_MAIN_THREAD;
if(SDL_WasInit(SDL_INIT_JOYSTICK) && myStick)
SDL_CloseJoystick(myStick);
}
#endif

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