From d797125e57a3ca72dff64afb97bc933559791bdd Mon Sep 17 00:00:00 2001 From: "(no author)" <(no author)@8b62c5a3-ac7e-4cc8-8f21-d9a121418aba> Date: Thu, 15 Jul 2004 19:59:55 +0000 Subject: [PATCH] This commit was manufactured by cvs2svn to create tag 'release-1_4'. git-svn-id: svn://svn.code.sf.net/p/stella/code/tags/release-1_4@323 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba --- CVSROOT/checkoutlist | 14 - CVSROOT/commitinfo | 15 - CVSROOT/config | 11 - CVSROOT/cvswrappers | 23 - CVSROOT/editinfo | 21 - CVSROOT/loginfo | 29 - CVSROOT/modules | 26 - CVSROOT/notify | 12 - CVSROOT/rcsinfo | 13 - CVSROOT/syncmail | 221 -- CVSROOT/taginfo | 20 - CVSROOT/verifymsg | 21 - stella/docs/stella.html | 2379 ------------------ stella/src/build/makefile | 345 --- stella/src/common/FrameBufferSDL.cxx | 268 -- stella/src/common/FrameBufferSDL.hxx | 176 -- stella/src/emucore/MediaSrc.cxx | 44 - stella/src/emucore/MediaSrc.hxx | 109 - stella/src/emucore/Sound.cxx | 114 - stella/src/emucore/StellaEvent.hxx | 97 - stella/src/emucore/TIASound.c | 689 ----- stella/src/emucore/TIASound.h | 61 - stella/src/emucore/TIASound.txt | 297 --- stella/src/emucore/m6502/src/D6502.cxx | 187 -- stella/src/emucore/m6502/src/D6502.hxx | 152 -- stella/src/macosx/.DS_Store | Bin 12292 -> 0 bytes stella/src/macosx/English.lproj/.DS_Store | Bin 6148 -> 0 bytes stella/src/macosx/SDLMain.nib/.DS_Store | Bin 6148 -> 0 bytes stella/src/macosx/build/.DS_Store | Bin 6148 -> 0 bytes stella/src/macosx/mainSDL.cxx | 1199 --------- stella/src/macosx/stella.pbproj/.DS_Store | Bin 6148 -> 0 bytes stella/src/win32/README-SDL.txt | 47 - stella/src/win32/SDL_mmjoystick_1.2.7.diff | 696 ----- stella/src/win32/Stella/Stella.ncb | Bin 470016 -> 0 bytes stella/src/win32/Stella/Stella.sln | 21 - stella/src/win32/Stella/Stella.suo | Bin 8192 -> 0 bytes stella/src/win32/Stella/Stella.vcproj | 487 ---- stella/src/win32/StellaX/AboutPage.cxx | 47 - stella/src/win32/StellaX/AboutPage.hxx | 44 - stella/src/win32/StellaX/BrowseForFolder.cxx | 121 - stella/src/win32/StellaX/BrowseForFolder.hxx | 74 - stella/src/win32/StellaX/ConfigPage.cxx | 260 -- stella/src/win32/StellaX/ConfigPage.hxx | 46 - stella/src/win32/StellaX/CoolCaption.cxx | 249 -- stella/src/win32/StellaX/CoolCaption.hxx | 62 - stella/src/win32/StellaX/FileDialog.cxx | 69 - stella/src/win32/StellaX/FileDialog.hxx | 51 - stella/src/win32/StellaX/Game.cxx | 37 - stella/src/win32/StellaX/Game.hxx | 77 - stella/src/win32/StellaX/GlobalData.cxx | 42 - stella/src/win32/StellaX/GlobalData.hxx | 56 - stella/src/win32/StellaX/HeaderCtrl.cxx | 168 -- stella/src/win32/StellaX/HeaderCtrl.hxx | 57 - stella/src/win32/StellaX/HyperLink.cxx | 334 --- stella/src/win32/StellaX/HyperLink.hxx | 76 - stella/src/win32/StellaX/MainDlg.cxx | 877 ------- stella/src/win32/StellaX/MainDlg.hxx | 101 - stella/src/win32/StellaX/PropertySheet.cxx | 233 -- stella/src/win32/StellaX/PropertySheet.hxx | 92 - stella/src/win32/StellaX/RoundButton.cxx | 553 ---- stella/src/win32/StellaX/RoundButton.hxx | 50 - stella/src/win32/StellaX/StellaX.aps | Bin 41076 -> 0 bytes stella/src/win32/StellaX/StellaX.ico | Bin 1078 -> 0 bytes stella/src/win32/StellaX/StellaX.rc | 299 --- stella/src/win32/StellaX/StellaX.vcproj | 275 -- stella/src/win32/StellaX/StellaXMain.cxx | 60 - stella/src/win32/StellaX/StellaXMain.hxx | 40 - stella/src/win32/StellaX/TextButton3d.cxx | 178 -- stella/src/win32/StellaX/TextButton3d.hxx | 43 - stella/src/win32/StellaX/Wnd.cxx | 77 - stella/src/win32/StellaX/Wnd.hxx | 46 - stella/src/win32/StellaX/debug.cxx | 80 - stella/src/win32/StellaX/debug.hxx | 111 - stella/src/win32/StellaX/main.cxx | 94 - stella/src/win32/StellaX/pch.cxx | 75 - stella/src/win32/StellaX/pch.hxx | 60 - stella/src/win32/StellaX/resource.h | 75 - stella/src/win32/StellaX/tile.bmp | Bin 27318 -> 0 bytes stella/src/win32/Stella_Emulator.sln | 29 - 79 files changed, 13112 deletions(-) delete mode 100644 CVSROOT/checkoutlist delete mode 100644 CVSROOT/commitinfo delete mode 100644 CVSROOT/config delete mode 100644 CVSROOT/cvswrappers delete mode 100644 CVSROOT/editinfo delete mode 100644 CVSROOT/loginfo delete mode 100644 CVSROOT/modules delete mode 100644 CVSROOT/notify delete mode 100644 CVSROOT/rcsinfo delete mode 100755 CVSROOT/syncmail delete mode 100644 CVSROOT/taginfo delete mode 100644 CVSROOT/verifymsg delete mode 100644 stella/docs/stella.html delete mode 100644 stella/src/build/makefile delete mode 100644 stella/src/common/FrameBufferSDL.cxx delete mode 100644 stella/src/common/FrameBufferSDL.hxx delete mode 100644 stella/src/emucore/MediaSrc.cxx delete mode 100644 stella/src/emucore/MediaSrc.hxx delete mode 100644 stella/src/emucore/Sound.cxx delete mode 100644 stella/src/emucore/StellaEvent.hxx delete mode 100644 stella/src/emucore/TIASound.c delete mode 100644 stella/src/emucore/TIASound.h delete mode 100644 stella/src/emucore/TIASound.txt delete mode 100644 stella/src/emucore/m6502/src/D6502.cxx delete mode 100644 stella/src/emucore/m6502/src/D6502.hxx delete mode 100644 stella/src/macosx/.DS_Store delete mode 100644 stella/src/macosx/English.lproj/.DS_Store delete mode 100644 stella/src/macosx/SDLMain.nib/.DS_Store delete mode 100644 stella/src/macosx/build/.DS_Store delete mode 100644 stella/src/macosx/mainSDL.cxx delete mode 100644 stella/src/macosx/stella.pbproj/.DS_Store delete mode 100644 stella/src/win32/README-SDL.txt delete mode 100644 stella/src/win32/SDL_mmjoystick_1.2.7.diff delete mode 100644 stella/src/win32/Stella/Stella.ncb delete mode 100644 stella/src/win32/Stella/Stella.sln delete mode 100644 stella/src/win32/Stella/Stella.suo delete mode 100644 stella/src/win32/Stella/Stella.vcproj delete mode 100644 stella/src/win32/StellaX/AboutPage.cxx delete mode 100644 stella/src/win32/StellaX/AboutPage.hxx delete mode 100644 stella/src/win32/StellaX/BrowseForFolder.cxx delete mode 100644 stella/src/win32/StellaX/BrowseForFolder.hxx delete mode 100644 stella/src/win32/StellaX/ConfigPage.cxx delete mode 100644 stella/src/win32/StellaX/ConfigPage.hxx delete mode 100644 stella/src/win32/StellaX/CoolCaption.cxx delete mode 100644 stella/src/win32/StellaX/CoolCaption.hxx delete mode 100644 stella/src/win32/StellaX/FileDialog.cxx delete mode 100644 stella/src/win32/StellaX/FileDialog.hxx delete mode 100755 stella/src/win32/StellaX/Game.cxx delete mode 100755 stella/src/win32/StellaX/Game.hxx delete mode 100644 stella/src/win32/StellaX/GlobalData.cxx delete mode 100644 stella/src/win32/StellaX/GlobalData.hxx delete mode 100644 stella/src/win32/StellaX/HeaderCtrl.cxx delete mode 100644 stella/src/win32/StellaX/HeaderCtrl.hxx delete mode 100644 stella/src/win32/StellaX/HyperLink.cxx delete mode 100644 stella/src/win32/StellaX/HyperLink.hxx delete mode 100644 stella/src/win32/StellaX/MainDlg.cxx delete mode 100644 stella/src/win32/StellaX/MainDlg.hxx delete mode 100644 stella/src/win32/StellaX/PropertySheet.cxx delete mode 100644 stella/src/win32/StellaX/PropertySheet.hxx delete mode 100644 stella/src/win32/StellaX/RoundButton.cxx delete mode 100644 stella/src/win32/StellaX/RoundButton.hxx delete mode 100644 stella/src/win32/StellaX/StellaX.aps delete mode 100644 stella/src/win32/StellaX/StellaX.ico delete mode 100644 stella/src/win32/StellaX/StellaX.rc delete mode 100644 stella/src/win32/StellaX/StellaX.vcproj delete mode 100644 stella/src/win32/StellaX/StellaXMain.cxx delete mode 100644 stella/src/win32/StellaX/StellaXMain.hxx delete mode 100644 stella/src/win32/StellaX/TextButton3d.cxx delete mode 100644 stella/src/win32/StellaX/TextButton3d.hxx delete mode 100644 stella/src/win32/StellaX/Wnd.cxx delete mode 100644 stella/src/win32/StellaX/Wnd.hxx delete mode 100644 stella/src/win32/StellaX/debug.cxx delete mode 100644 stella/src/win32/StellaX/debug.hxx delete mode 100644 stella/src/win32/StellaX/main.cxx delete mode 100644 stella/src/win32/StellaX/pch.cxx delete mode 100644 stella/src/win32/StellaX/pch.hxx delete mode 100644 stella/src/win32/StellaX/resource.h delete mode 100644 stella/src/win32/StellaX/tile.bmp delete mode 100644 stella/src/win32/Stella_Emulator.sln diff --git a/CVSROOT/checkoutlist b/CVSROOT/checkoutlist deleted file mode 100644 index ad89cad9b..000000000 --- a/CVSROOT/checkoutlist +++ /dev/null @@ -1,14 +0,0 @@ -# The "checkoutlist" file is used to support additional version controlled -# administrative files in $CVSROOT/CVSROOT, such as template files. -# -# The first entry on a line is a filename which will be checked out from -# the corresponding RCS file in the $CVSROOT/CVSROOT directory. -# The remainder of the line is an error message to use if the file cannot -# be checked out. -# -# File format: -# -# [] -# -# comment lines begin with '#' -syncmail Couldn't check out syncmail script. diff --git a/CVSROOT/commitinfo b/CVSROOT/commitinfo deleted file mode 100644 index b19e7b7a6..000000000 --- a/CVSROOT/commitinfo +++ /dev/null @@ -1,15 +0,0 @@ -# The "commitinfo" file is used to control pre-commit checks. -# The filter on the right is invoked with the repository and a list -# of files to check. A non-zero exit of the filter program will -# cause the commit to be aborted. -# -# The first entry on a line is a regular expression which is tested -# against the directory that the change is being committed to, relative -# to the $CVSROOT. For the first match that is found, then the remainder -# of the line is the name of the filter to run. -# -# If the repository name does not match any of the regular expressions in this -# file, the "DEFAULT" line is used, if it is specified. -# -# If the name "ALL" appears as a regular expression it is always used -# in addition to the first matching regex or "DEFAULT". diff --git a/CVSROOT/config b/CVSROOT/config deleted file mode 100644 index 8069cad5d..000000000 --- a/CVSROOT/config +++ /dev/null @@ -1,11 +0,0 @@ -# Set this to "no" if pserver shouldn't check system users/passwords -#SystemAuth=no - -# Set `PreservePermissions' to `yes' to save file status information -# in the repository. -#PreservePermissions=no - -# Set `TopLevelAdmin' to `yes' to create a CVS directory at the top -# level of the new working directory when using the `cvs checkout' -# command. -#TopLevelAdmin=no diff --git a/CVSROOT/cvswrappers b/CVSROOT/cvswrappers deleted file mode 100644 index 0accaf1b1..000000000 --- a/CVSROOT/cvswrappers +++ /dev/null @@ -1,23 +0,0 @@ -# This file affects handling of files based on their names. -# -# The -t/-f options allow one to treat directories of files -# as a single file, or to transform a file in other ways on -# its way in and out of CVS. -# -# The -m option specifies whether CVS attempts to merge files. -# -# The -k option specifies keyword expansion (e.g. -kb for binary). -# -# Format of wrapper file ($CVSROOT/CVSROOT/cvswrappers or .cvswrappers) -# -# wildcard [option value][option value]... -# -# where option is one of -# -f from cvs filter value: path to filter -# -t to cvs filter value: path to filter -# -m update methodology value: MERGE or COPY -# -k expansion mode value: b, o, kkv, &c -# -# and value is a single-quote delimited value. -# For example: -#*.gif -k 'b' diff --git a/CVSROOT/editinfo b/CVSROOT/editinfo deleted file mode 100644 index d78886c15..000000000 --- a/CVSROOT/editinfo +++ /dev/null @@ -1,21 +0,0 @@ -# The "editinfo" file is used to allow verification of logging -# information. It works best when a template (as specified in the -# rcsinfo file) is provided for the logging procedure. Given a -# template with locations for, a bug-id number, a list of people who -# reviewed the code before it can be checked in, and an external -# process to catalog the differences that were code reviewed, the -# following test can be applied to the code: -# -# Making sure that the entered bug-id number is correct. -# Validating that the code that was reviewed is indeed the code being -# checked in (using the bug-id number or a seperate review -# number to identify this particular code set.). -# -# If any of the above test failed, then the commit would be aborted. -# -# Actions such as mailing a copy of the report to each reviewer are -# better handled by an entry in the loginfo file. -# -# One thing that should be noted is the the ALL keyword is not -# supported. There can be only one entry that matches a given -# repository. diff --git a/CVSROOT/loginfo b/CVSROOT/loginfo deleted file mode 100644 index c663c1d0e..000000000 --- a/CVSROOT/loginfo +++ /dev/null @@ -1,29 +0,0 @@ -# The "loginfo" file controls where "cvs commit" log information -# is sent. The first entry on a line is a regular expression which must match -# the directory that the change is being made to, relative to the -# $CVSROOT. If a match is found, then the remainder of the line is a filter -# program that should expect log information on its standard input. -# -# If the repository name does not match any of the regular expressions in this -# file, the "DEFAULT" line is used, if it is specified. -# -# If the name ALL appears as a regular expression it is always used -# in addition to the first matching regex or DEFAULT. -# -# You may specify a format string as part of the -# filter. The string is composed of a `%' followed -# by a single format character, or followed by a set of format -# characters surrounded by `{' and `}' as separators. The format -# characters are: -# -# s = file name -# V = old version number (pre-checkin) -# v = new version number (post-checkin) -# -# For example: -#DEFAULT (echo ""; id; echo %s; date; cat) >> $CVSROOT/CVSROOT/commitlog -# or -#DEFAULT (echo ""; id; echo %{sVv}; date; cat) >> $CVSROOT/CVSROOT/commitlog -CVSROOT $CVSROOT/CVSROOT/syncmail %{sVv} bwmott@acm.org -DEFAULT $CVSROOT/CVSROOT/syncmail %{sVv} stella-commits@lists.sourceforge.net - diff --git a/CVSROOT/modules b/CVSROOT/modules deleted file mode 100644 index cb9e9efc9..000000000 --- a/CVSROOT/modules +++ /dev/null @@ -1,26 +0,0 @@ -# Three different line formats are valid: -# key -a aliases... -# key [options] directory -# key [options] directory files... -# -# Where "options" are composed of: -# -i prog Run "prog" on "cvs commit" from top-level of module. -# -o prog Run "prog" on "cvs checkout" of module. -# -e prog Run "prog" on "cvs export" of module. -# -t prog Run "prog" on "cvs rtag" of module. -# -u prog Run "prog" on "cvs update" of module. -# -d dir Place module in directory "dir" instead of module name. -# -l Top-level directory only -- do not recurse. -# -# NOTE: If you change any of the "Run" options above, you'll have to -# release and re-checkout any working directories of these modules. -# -# And "directory" is a path to a directory relative to $CVSROOT. -# -# The "-a" option specifies an alias. An alias is interpreted as if -# everything on the right of the "-a" had been typed on the command line. -# -# You can encode a module within a module by using the special '&' -# character to interpose another module into the current module. This -# can be useful for creating a module that consists of many directories -# spread out over the entire source repository. diff --git a/CVSROOT/notify b/CVSROOT/notify deleted file mode 100644 index 34f0bc288..000000000 --- a/CVSROOT/notify +++ /dev/null @@ -1,12 +0,0 @@ -# The "notify" file controls where notifications from watches set by -# "cvs watch add" or "cvs edit" are sent. The first entry on a line is -# a regular expression which is tested against the directory that the -# change is being made to, relative to the $CVSROOT. If it matches, -# then the remainder of the line is a filter program that should contain -# one occurrence of %s for the user to notify, and information on its -# standard input. -# -# "ALL" or "DEFAULT" can be used in place of the regular expression. -# -# For example: -#ALL mail %s -s "CVS notification" diff --git a/CVSROOT/rcsinfo b/CVSROOT/rcsinfo deleted file mode 100644 index 49e59f4d0..000000000 --- a/CVSROOT/rcsinfo +++ /dev/null @@ -1,13 +0,0 @@ -# The "rcsinfo" file is used to control templates with which the editor -# is invoked on commit and import. -# -# The first entry on a line is a regular expression which is tested -# against the directory that the change is being made to, relative to the -# $CVSROOT. For the first match that is found, then the remainder of the -# line is the name of the file that contains the template. -# -# If the repository name does not match any of the regular expressions in this -# file, the "DEFAULT" line is used, if it is specified. -# -# If the name "ALL" appears as a regular expression it is always used -# in addition to the first matching regex or "DEFAULT". diff --git a/CVSROOT/syncmail b/CVSROOT/syncmail deleted file mode 100755 index 60b5e4429..000000000 --- a/CVSROOT/syncmail +++ /dev/null @@ -1,221 +0,0 @@ -#! /usr/bin/python -# -*- Python -*- - -"""Complicated notification for CVS checkins. - -This script is used to provide email notifications of changes to the CVS -repository. These email changes will include context diffs of the changes. -Really big diffs will be trimmed. - -This script is run from a CVS loginfo file (see $CVSROOT/CVSROOT/loginfo). To -set this up, create a loginfo entry that looks something like this: - - mymodule /path/to/this/script %%s some-email-addr@your.domain - -In this example, whenever a checkin that matches `mymodule' is made, this -script is invoked, which will generate the diff containing email, and send it -to some-email-addr@your.domain. - - Note: This module used to also do repository synchronizations via - rsync-over-ssh, but since the repository has been moved to SourceForge, - this is no longer necessary. The syncing functionality has been ripped - out in the 3.0, which simplifies it considerably. Access the 2.x versions - to refer to this functionality. Because of this, the script is misnamed. - -It no longer makes sense to run this script from the command line. Doing so -will only print out this usage information. - -Usage: - - %(PROGRAM)s [options] <%%S> email-addr [email-addr ...] - -Where options is: - - --cvsroot= - Use as the environment variable CVSROOT. Otherwise this - variable must exist in the environment. - - --help - -h - Print this text. - - --context=# - -C # - Include # lines of context around lines that differ (default: 2). - - -c - Produce a context diff (default). - - -u - Produce a unified diff (smaller, but harder to read). - - <%%S> - CVS %%s loginfo expansion. When invoked by CVS, this will be a single - string containing the directory the checkin is being made in, relative - to $CVSROOT, followed by the list of files that are changing. If the - %%s in the loginfo file is %%{sVv}, context diffs for each of the - modified files are included in any email messages that are generated. - - email-addrs - At least one email address. - -""" - - -import os -import sys -import string -import time -import getopt - -# Notification command -MAILCMD = '/bin/mail -s "CVS: %(SUBJECT)s" %(PEOPLE)s 2>&1 > /dev/null' - -# Diff trimming stuff -DIFF_HEAD_LINES = 20 -DIFF_TAIL_LINES = 20 -DIFF_TRUNCATE_IF_LARGER = 1000 - -PROGRAM = sys.argv[0] - - - -def usage(code, msg=''): - print __doc__ % globals() - if msg: - print msg - sys.exit(code) - - - -def calculate_diff(filespec, contextlines): - try: - file, oldrev, newrev = string.split(filespec, ',') - except ValueError: - # No diff to report - return '***** Bogus filespec: %s' % filespec - if oldrev == 'NONE': - try: - if os.path.exists(file): - fp = open(file) - else: - update_cmd = 'cvs -fn update -r %s -p %s' % (newrev, file) - fp = os.popen(update_cmd) - lines = fp.readlines() - fp.close() - lines.insert(0, '--- NEW FILE: %s ---\n' % file) - except IOError, e: - lines = ['***** Error reading new file: ', - str(e), '\n***** file: ', file, ' cwd: ', os.getcwd()] - elif newrev == 'NONE': - lines = ['--- %s DELETED ---\n' % file] - else: - # This /has/ to happen in the background, otherwise we'll run into CVS - # lock contention. What a crock. - if contextlines > 0: - difftype = "-C " + str(contextlines) - else: - difftype = "-u" - diffcmd = "/usr/bin/cvs -f diff -kk %s --minimal -r %s -r %s '%s'" % ( - difftype, oldrev, newrev, file) - fp = os.popen(diffcmd) - lines = fp.readlines() - sts = fp.close() - # ignore the error code, it always seems to be 1 :( -## if sts: -## return 'Error code %d occurred during diff\n' % (sts >> 8) - if len(lines) > DIFF_TRUNCATE_IF_LARGER: - removedlines = len(lines) - DIFF_HEAD_LINES - DIFF_TAIL_LINES - del lines[DIFF_HEAD_LINES:-DIFF_TAIL_LINES] - lines.insert(DIFF_HEAD_LINES, - '[...%d lines suppressed...]\n' % removedlines) - return string.join(lines, '') - - - - -def blast_mail(mailcmd, filestodiff, contextlines): - # cannot wait for child process or that will cause parent to retain cvs - # lock for too long. Urg! - if not os.fork(): - # in the child - # give up the lock you cvs thang! - time.sleep(2) - fp = os.popen(mailcmd, 'w') - fp.write(sys.stdin.read()) - fp.write('\n') - # append the diffs if available - for file in filestodiff: - fp.write(calculate_diff(file, contextlines)) - fp.write('\n') - fp.close() - # doesn't matter what code we return, it isn't waited on - os._exit(0) - - - -# scan args for options -def main(): - contextlines = 2 - try: - opts, args = getopt.getopt(sys.argv[1:], 'hC:cu', - ['context=', 'cvsroot=', 'help']) - except getopt.error, msg: - usage(1, msg) - - # parse the options - for opt, arg in opts: - if opt in ('-h', '--help'): - usage(0) - elif opt == '--cvsroot': - os.environ['CVSROOT'] = arg - elif opt in ('-C', '--context'): - contextlines = int(arg) - elif opt == '-c': - if contextlines <= 0: - contextlines = 2 - elif opt == '-u': - contextlines = 0 - - # What follows is the specification containing the files that were - # modified. The argument actually must be split, with the first component - # containing the directory the checkin is being made in, relative to - # $CVSROOT, followed by the list of files that are changing. - if not args: - usage(1, 'No CVS module specified') - SUBJECT = args[0] - specs = string.split(args[0]) - del args[0] - - # The remaining args should be the email addresses - if not args: - usage(1, 'No recipients specified') - - # Now do the mail command - PEOPLE = string.join(args) - mailcmd = MAILCMD % vars() - - print 'Mailing %s...' % PEOPLE - if specs == ['-', 'Imported', 'sources']: - return - if specs[-3:] == ['-', 'New', 'directory']: - del specs[-3:] - elif len(specs) > 2: - L = specs[:2] - for s in specs[2:]: - prev = L[-1] - if string.count(prev, ",") < 2: - L[-1] = "%s %s" % (prev, s) - else: - L.append(s) - specs = L - print 'Generating notification message...' - blast_mail(mailcmd, specs[1:], contextlines) - print 'Generating notification message... done.' - - - -if __name__ == '__main__': - main() - sys.exit(0) - diff --git a/CVSROOT/taginfo b/CVSROOT/taginfo deleted file mode 100644 index 274a46dd5..000000000 --- a/CVSROOT/taginfo +++ /dev/null @@ -1,20 +0,0 @@ -# The "taginfo" file is used to control pre-tag checks. -# The filter on the right is invoked with the following arguments: -# -# $1 -- tagname -# $2 -- operation "add" for tag, "mov" for tag -F, and "del" for tag -d -# $3 -- repository -# $4-> file revision [file revision ...] -# -# A non-zero exit of the filter program will cause the tag to be aborted. -# -# The first entry on a line is a regular expression which is tested -# against the directory that the change is being committed to, relative -# to the $CVSROOT. For the first match that is found, then the remainder -# of the line is the name of the filter to run. -# -# If the repository name does not match any of the regular expressions in this -# file, the "DEFAULT" line is used, if it is specified. -# -# If the name "ALL" appears as a regular expression it is always used -# in addition to the first matching regex or "DEFAULT". diff --git a/CVSROOT/verifymsg b/CVSROOT/verifymsg deleted file mode 100644 index 86f747ce2..000000000 --- a/CVSROOT/verifymsg +++ /dev/null @@ -1,21 +0,0 @@ -# The "verifymsg" file is used to allow verification of logging -# information. It works best when a template (as specified in the -# rcsinfo file) is provided for the logging procedure. Given a -# template with locations for, a bug-id number, a list of people who -# reviewed the code before it can be checked in, and an external -# process to catalog the differences that were code reviewed, the -# following test can be applied to the code: -# -# Making sure that the entered bug-id number is correct. -# Validating that the code that was reviewed is indeed the code being -# checked in (using the bug-id number or a seperate review -# number to identify this particular code set.). -# -# If any of the above test failed, then the commit would be aborted. -# -# Actions such as mailing a copy of the report to each reviewer are -# better handled by an entry in the loginfo file. -# -# One thing that should be noted is the the ALL keyword is not -# supported. There can be only one entry that matches a given -# repository. diff --git a/stella/docs/stella.html b/stella/docs/stella.html deleted file mode 100644 index 10349bedb..000000000 --- a/stella/docs/stella.html +++ /dev/null @@ -1,2379 +0,0 @@ - - -Stella - A multi-platform Atari 2600 VCS emulator - - - - - -
Stella
-

-

A multi-platform Atari 2600 VCS emulator

- -

Release 1.4

-

- -

User's Guide

-

- -
    -
  1. Introduction
  2. -
  3. What You Will Need
  4. -
  5. Installation
  6. -
  7. Games
  8. -
  9. Starting A Game
  10. -
  11. Settings File
  12. -
  13. Keyboard Layout
  14. -
  15. Event Remapping
  16. -
  17. Game Properties
  18. -
  19. Stelladaptor Support
  20. -
  21. Acknowledgments
  22. -
  23. License and Disclaimer
  24. -
- -


- -
February 1999 - July 2004
-
The Stella Team
-
Stella Homepage
- -


- -

-

A Brief History of the Atari 2600

-
- -

- In the early 1970's, video arcade games gained commercial success for the - first time. The American public was introduced to Pong, Tank, and other - interactive video games which populated amusement parks, bars, and arcades. - The games were successful enough to create interest for home versions, so in - 1975 Atari released Home Pong and it was a smash hit. Other companies such as - Magnavox and Coleco followed suit and released their own dedicated console - games. Then in 1976, Fairchild Camera and Instrument introduced the Channel F - system, the first cartridge based home video game system. The industry - recognized that cartridge systems were the future of video gaming, and began - development in that direction. In January 1977, RCA released the Studio II, - another cartridge based system, although it only projected in black and white - and seemed to be focused on educational titles. Then, in October 1977, Atari - released the Atari VCS (Video Computer System) with an initial offering of nine - games. This system, later renamed the Atari 2600, took the industry by storm - and dominated the marketplace for years to come. -

- -

- Because of oversupply, the Christmas season of 1977 was very rough on the - video game industry, and the Atari 2600 was the only system that managed to - emerge unscathed. Atari enjoyed strong sales in 1978 and a fantastic holiday - season, as Atari released more games such as Outlaw, Spacewar, and Breakout. - Internally however, Atari was at odds. Nolan Bushnell, the inventor of pong and - founder of Atari, wound up leaving the company and purchased Pizza Time Theater, - which later became the successful Chuck E. Cheese! In 1979 Atari continued - their trend and released 12 more games which met with continued success. - However, Atari was now facing some stiffer competition from the Mattel - Intellivision and the Magnavox Odyssey2. -

- -

- Atari needed a mega-hit in 1980 in order to squash the competition, and they - found it in the home version of a game from Japan called Space Invaders. It was - so popular that people were buying the Atari 2600 just so they could play Space - Invaders at home. Following that, Atari released Adventure, which was the first - video game to contain an Easter Egg - placing an object in a certain area - revealed the programmer's name, Warren Robinett. 1980 was important for another - reason - the creation of the first ever third party software producer, Activision. - The company was formed by four Atari employees who were unsatisfied with the - working conditions at the company. They released four games initially: Dragster, - Fishing Derby, Checkers and Boxing. The games were very well received by the - public, and revealed that the Atari 2600 was capable of better games than - Atari themselves had been producing. Atari tried to prevent Activision from - selling games, but they failed and Activision grossed $70 million that year. -

- -

- By 1981, the video game industry was basically a horse race between the 2600 - and the Intellivision. While the Intellivision was technologically superior in - some respects, the 2600 continued to lead in sales. Atari released the home - version of Asteroids, which was a huge success. Inspired by the success of - Activision, another software development group called Imagic was formed. They - would not release any games until 1982 however. Another company, Games by Apollo, - was formed in Texas and released several games that year. -

- -

- Coleco entered the market in 1982 with the release of the graphically - superior Colecovision. To combat this new system, Atari produced the 5200, - a technologically comparable system. The 2600 dropped $100 in price in order - to remain competitive. Then a company called Arcadia released a peripheral - called the Supercharger which played games in an audio cassette medium. This - allowed for multiple loads and expanded the 2600's capabilities. -

- Atari released Pac-Man and E.T. that year, two incredibly hyped games which - were critical flops. - Although Pac-Man sold many copies, it was considered to be a poor - translation of the arcade hit. However, there were many fantastic games - produced for the 2600 during this period, and it was still selling strong. -

- -

- Ever since the inception of Activision, Atari had been fighting to keep third - parties from producing cartridges which they felt were stealing profits from - them. Finally the issue was settled when Atari agreed to allow third party - manufacturing in exchange for a royalty. Suddenly software companies began - popping up all over, and 1982 saw releases from companies like Venturevision, - Spectravision, Telesys, CBS, 20th Century Fox, US Games, M Network, Tigervision, - Data Age, Imagic and Coleco. There was even a company that released a line of - X-Rated games for the 2600 called Mystique. The year was financially successful - for Atari, however there seemed to be a glut of software. Although there were - many quality titles still produced, there was an increasing number of rushed - games as manufacturers attempted to cash in on the craze. -

- -

- More companies jumped on the band wagon in 1983. Zimag, Ultravision, Amiga, - and others were also producing games and peripherals. It seemed as if there was - just too much product to meet the demand, and as it turned out there was. By - the end of the year, companies began folding. US Games, Data Age, Games by - Apollo, Telesys and others all closed their doors from poor sales. A video - game crash was occurring, and all companies were taking it on the chin. -

- -

- 1984 was a much more subdued year for the Atari 2600, and the price of the - system had now dropped to $40-$50. Many were saying that the video game - industry was dead. However, Atari surprised everyone by announcing the release - of the 7800, and also promising more 2600 games with improved graphics and - sound. Unfortunately, neither of these things happened in 1984 because Atari - sold their home video game division to Jack Tramiel who believed that home - computers would replace video game systems. No further mention of the 2600 or - 7800 was made that year, and it appeared that they might be dead. -

- -

- 1985 was another very quiet year for Atari and video games in general, and only - a few games were released for the 2600. Activision produced Cosmic Commuter and - Ghostbusters, but with little fanfare or marketing, these games did not sell - well. However, because of the huge game library and cheap price, Atari still - sold over a million 2600 consoles in 1985. -

- -

- There were very few plans for home video game systems by any company in 1986, - since the market appeared to be dead. Then, to most people's surprise, Nintendo - brought the NES to America and it was a smash hit, proving that video games - still had a place in the US. Atari decided that maybe it would be a good idea - to release the 7800 units it had in storage, and produce some more 2600 games. - The 7800 was released with only 3 games initially available, although it was - compatible with the 2600 library. They also redesigned the 2600 as the 2600 Jr., - a machine with the same abilities, but a new look and marketing campaign. It - was sold for less than $50. -

- -

- Video games were once again selling phenomenally in 1987. Atari released - several new titles, including Jr. Pac-Man, and also licensed a number of games - from other companies such as Donkey Kong and Q*Bert. These new titles sold for - $10-$15. Interestingly, a number of titles began appearing again from third - part companies such as Epyx, Froggo, and Exus. It seemed that the 2600 was not - dead yet! -

- In 1988, Atari rehired Nolan Bushnell and announced a number of new - titles, including Secret Quest, a game written by Mr. Bushnell himself. Atari - continued to manufacture these games even until 1989. However, it was apparent - that the 2600, after its introduction over a decade ago, was finally at the end - of its run. Although it was still produced and marketed outside of the US, the - Atari 2600 finished its run in America. No other console has had such a long - history or sold as many systems in the U.S. -

- -

- Today, the 2600 still has a large number of fans who remember the countless - games played over the years, and the years to come. There are even games being - produced by hobbyists, some of them quite professionally, being released on - newly burnt cartridges with labels and manuals. And the recent trend in - retrogaming has brought many more video game fans to rediscover the 2600, and - it continues to live on 22 years after its release! -

- -

Alexander Bilstein
February 1999

- -

-

- 1. Introduction

-
- -

- Stella is a freely distributed multi-platform Atari 2600 VCS emulator; originally - developed for Linux by Bradford W. Mott. Stella allows you to enjoy all of - your favorite 2600 games once again by emulating the 2600's hardware with - software. Stella is written in C++, which allows it to be ported to other - operating systems and architectures. Since its original release Stella has - been ported to AcornOS, AmigaOS, DOS, FreeBSD, Linux, MacOS, OpenStep, OS/2, - Sega Dreamcast, Unix, and Windows. -

- -

New in Release 1.4

- -
    -
  • Codebase ported to SDL. The DOS and X11 ports have been discontinued.
  • -
  • Sound code ported to SDL. For the Linux versions, ALSA and OSS sound - support has been discontinued.
  • -
  • The Linux, MacOSX and Windows ports are now based on the same codebase and - are actively maintained. That means simultaneous (and hopefully - more frequent) releases.
  • -
  • A new Windows port has been created, with the GUI based on StellaX. - This is the first new release for Windows since Stella 1.2. - (software mode is not yet optimized; OpenGL mode works much better)
  • -
  • A new Mac OSX port has been created by Mark Grebe. This is the first new - release for Mac OSX since Stella 1.2.
  • -
  • Added OpenGL rendering support.
  • -
  • Added more refined in-game GUI.
  • -
  • Added event remapping. Emulation keys can now be remapped to the keyboard - or up to 4 joysticks.
  • -
  • Added native Stelladaptor support. Joysticks, paddles, and driving controllers - have been tested.
  • -
  • Digital sound support (used in games like Quadrun and Pitfall2) has been - greatly improved. Sound generation is now more tightly synchronized with - video updates.
  • -
  • Added support for switchable palettes. Currently you can switch between the - current Stella palette, original Stella palette (pre-1.2 versions), and - the z26 palette.
  • -
  • Added support for UA Limited style bankswitching (Funky Fish and Pleiades).
  • -
  • Switched to using high compatibility M6502 mode by default. This - means old state saves from previous Stella versions will no longer work.
  • -
  • The meaning of the "-sound" command line option has been changed. - This option now accepts either 'true' or 'false (1 or 0) to enable/disable - sound.
  • -
  • Changed sound mixer functionality. The system volume/mixer settings will - never be changed; volume changes in Stella will only affect the emulation - itself.
  • -
  • Added "-video" command line option. This option accepts either 'soft' - or 'gl', to use software/OpenGL rendering.
  • -
  • Added "-gl_filter" command line option. This option accepts either - 'nearest' or 'linear', to use GL_NEAREST or GL_LINEAR filtering.
  • -
  • Added "-gl_aspect" command line option. This option accepts a decimal - value specifying how much to scale the width of the emulation image (useful - for giving an authentic 'square-looking' 4:3 mode).
  • -
  • Added "-gl_fsmax" command line option. This option accepts either - 'true' or 'false, and specifies to use the maximum possible resolution when - in fullscreen OpenGL mode (useful for Linux and for Windows on laptops).
  • -
  • Added "-fragsize" command line option. This option accepts the - size to use for sound fragments. Linux/MacOSX works well with 512, - Windows seems to need 2048. This value must be a power of two.
  • -
  • Modified "-volume" command line option. If you specify '-1', - Stella will use the system volume.
  • -
  • Renamed the "-pro" command line option to "-altpro".
  • -
  • Renamed the "-fps" command line option to "-framerate".
  • -
  • Removed the "-center" command line option. Stella now automatically - centers the window when possible.
  • -
  • Removed the "-paddle real" command line option, since it never really - worked correctly (and Stelladaptor support adds that functionality - anyway).
  • -
  • Removed all command line options relating to the X11 port - (owncmap, display).
  • -
- -

-

Features

- -
    -
  • High speed emulation using optimized C++ code
  • -
  • Supports high quality sound emulation using Ron Fries' TIA Sound Emulation - library
  • -
  • Emulates the Atari 2600 Joystick Controllers using your computer's keyboard - or joysticks
  • -
  • Emulates the Atari 2600 Keyboard Controllers using your computer's keyboard
  • -
  • Emulates one Atari 2600 Paddle Controller using your computer's mouse
  • -
  • Support for real Atari 2600 controllers using the - Stelladaptor
  • -
  • Emulates the Atari 2600 Driving Controllers using your computer's keyboard - or joysticks
  • -
  • Emulates the CBS Booster-Grip Controller using your computer's keyboard or - joysticks
  • -
  • Supports cartridges using Atari's standard 2K and 4K format
  • -
  • Supports cartridges using Atari's 8K, 16K, and 32K bank-switching schemes
  • -
  • Supports cartridges using Activision's 8K bank-switching scheme - (Robot Tank and Decathlon)
  • -
  • Supports cartridges using CBS Electronics' 12K bank-switching scheme
  • -
  • Supports cartridges using Chris Wilkson's Megacart 128K bank-switching - scheme
  • -
  • Supports cartridges using Commavid bank-switching scheme
  • -
  • Supports cartridges using M-Network's 16K bank-switching scheme
  • -
  • Supports cartridges using Parker Brothers' 8K bank-switching scheme
  • -
  • Supports cartridges using Tigervision's bank-switching scheme with up to - 512K ROM
  • -
  • Supports Supercharger single-load and multi-load games
  • -
  • Supports property file for setting the properties associated with games
  • -
  • Supports user specified frame rate
  • -
  • Supports the NTSC and PAL television palettes
  • -
  • Supports several "undocumented features" of the TIA graphics chip used by - some games
  • -
  • TIA emulation supports full collision checking
  • -
  • Linux version of Stella works with the KStella frontend by Stephen Anthony
  • -
- -

-

- 2. What You Will Need

-
- -

The following sections outline the basic system requirements for running - Stella under various operating systems. -

- -

Note that for this version of Stella, you are required to have a - stella.pro file. It is no longer optional as it was for past versions.

- -

-

General (required for all versions of Stella)

-
    -
  • Enough RAM for the OS + 16MB RAM for the emulation; 32MB highly recommended
  • -
  • 15 bit color minimum; 16 bit color graphics card highly recommended
  • -
  • SDL version 1.2.0 or greater
  • -
  • Latest versions of the libpng and zlib libraries
  • -
  • Joysticks or gamepads are highly recommended
  • -
  • Mouse or Stelladaptor with real paddles required for paddle emulation
  • -
  • Some ROM images (no, we won't tell you where to find them)
  • -
- -

-

Linux/UNIX

-

The Linux version of Stella is designed to work on a Linux Workstation with - the following:

-
    -
  • Linux Kernel 2.4.x, Linux Kernel 2.6.x is highly recommended
  • -
  • GNU C++ compiler version 2.95 and the make utility are required for compiling - the Stella source code; GNU C++ compiler version 3.2.x or later is highly - recommended
  • -
  • 486/120 MHz required; 586/166 MHz highly recommended (Stella may - compile on other architectures, but it hasn't been tested)
  • -
- -

-

Macintosh

- -

The MacLinux version of Stella is designed to work on a Power Macintosh with - the following:

-
    -
  • Mac OSX 10.1 or Above
  • -
  • 500 MHz highly recommended
  • -
- -

-

Windows

- -

The Windows version of Stella is designed to work on Windows 95/98/ME/2000/XP with - the following:

- -
    -
  • Visual C++ 7 compiler is required to compile the StellaX GUI frontend
  • -
  • Visual C++ 7 or MinGW compiler is required to compile the Stella - executable
  • -
  • 486/120 MHz required; 586/166 MHz highly recommended
  • -
- -

-

- 3. Installation

-
-

Stella is distributed in both source and binary form. Once you have a Stella - distribution you should follow the instructions for your operating system given - below.

- -

If you have a supported joystick and driver installed and SDL can access the device, - you can play games using joysticks.

- -

Currently, sound is supported using SDL. As long as SDL can see your sound card, - Stella will be able to produce sound.

- -

-

Linux/UNIX

-
    -
  • Compressed tarball (stella-release-src.tar.gz)
  • -
      -
    1. Extract files from the distribution: -
         tar zxvf stella-release-src.tar.gz
    2. -
    3. Change directories to the stella-release/src/build directory
    4. -
    5. Edit the makefile to meet your needs
    6. -
    7. Build the executable with the following command: -
         make linux (or make linux-gl)
    8. -
    9. Copy the executable to a directory that's in your path: -
         cp stella /usr/local/bin
    10. -
    11. Copy the supplied stella.pro properties file to the system-wide location: -
         cp stella.pro /etc
      or to your home directory: -
         mkdir ~/.stella
      cp stella.pro ~/.stella
    12. -
    -
  • Source RPM (stella-release-1.src.rpm)
  • -
      -
    1. Rebuild the archive with the following command: -
         rpmbuild --rebuild stella-release-1.src.rpm
    2. -
    3. Follow the instructions under Binary RPM to install - the stella-release-1.ix86.rpm file
    4. -
    -
  • Binary RPM (stella-release-1.ix86.rpm)
  • -
      -
    1. Install the binary RPM with the following command: -
         rpm -Uvh stella-release-1.ix86.rpm
    2. -
    -
- -

-

Macintosh

- -

To install the Mac binary, simply download the StellaOSX1.4.dmg disk - image.  Mount the disk image, then copy the StellaOSX1.4 folder to - your hard drive.
-

- -

-

Windows

-
    -
  • Compressed tarball (stella-release-src.tar.gz)
  • -
      -
    1. Extract files from the distribution using Winzip, - Total Commander, or some other archiving program that supports - gzipped tar files
    2. -
    3. If compiling the Stella executable using MinGW:
    4. -
        -
      • Change directories to the stella-release/src/build - directory
      • -
      • Edit the makefile to meet your needs
      • -
      • Build the executable with the following command: -
           make win32 (or make win32-gl)
      • -
      • Copy the Stella (commandline executable) and stella.pro - files to some directory
      • -
      -
    5. If compiling using Visual C++ 7:
    6. -
        -
      • Open the stella-release/src/win32/Stella_Emulator.sln - file using Visual C++ 7
      • -
      • Build both Stella.exe (commandline emulator) and StellaX.exe - (GUI frontend)
      • -
      • Copy the Stella.exe, StellaX.exe and stella.pro files - to some directory
      • -
      -
    -
  • Binary ZIP file (stella-release-win32.zip)
  • -
      -
    1. Unzip the binary ZIP file using Winzip or Total Commander - and copy that directory somewhere
    2. -
    -
- -

-

- 4. Games

-
- -

Stella allows you to play games using ROM images of cartridges and cassettes.

- -

-

Cartridges

- -

Most games for the Atari 2600 came on cartridges. A cartridge usually - consists of a single Read Only Memory (ROM) chip which contains the data and - code for the game. Plugging a cartridge into the Atari 2600 allows the 2600's - microprocessor to access the program stored on the cartridge.

- -

In a similar way you must "plug" a copy of a cartridge into Stella when you - want to play it. Having a ROM image, BIN file, of the cartridge allows you to - do this. A ROM image is a file, which contains the actual data and code read - from the cartridge. There are several ways to obtain a ROM image of a - cartridge:

- -
    -
  1. If you're handy with a soldering iron then you can design and build a - device that plugs into the printer port of a PC and read the data from the - cartridge
  2. - -
  3. You can purchase the Atari 2600 Action Packs by Activision and use - their ROM images
  4. - -
  5. You can search around the internet and find ROM images to download
  6. -
- -

WARNING: It is illegal to use ROM images of games that you do not - actually own since these games are still copyrighted.

- -

-

Supercharger Cassettes

- -

Supercharger games were not stored on cartridges instead they were stored - on cassette tapes. The Supercharger, which plugged into the Atari 2600's - cartridge slot, loaded games into its 6K of Random Access Memory (RAM) using a - standard audio cassette player. The Supercharger also supported multi-loading, - which allowed games to be broken into several segments and loaded at different - times. This was useful for large games which had distinct parts such as role - playing games.

- -

Most of the available Supercharger ROM images are stored in 8448 bytes files. - However, ROM images of multi-load games are sometimes stored in a set of 8448 - byte files. The names of these files have a two character sequence number in - them which indicates what load they are. The sequence starts with zero, skips - a few numbers and then increments by one.

- -

Stella supports multi-load games, however, the set of ROM images must be - combined into a single ROM image file. For example to create a multi-load ROM - image file for Survival Island you would do the following under Unix: - -

   % cat survivl0.bin survivl6.bin survivl7.bin > survivl.bin
- - or to create it under DOS you would: - -
   % copy /b survivl0.bin+survivl6.bin+survivl7.bin survivl.bin
- -

Once you have the multi-load ROM image file, survivl.bin in this case, you - can play the game using it.

- -

-

- 5. Starting A Game

-
- -

Once Stella is installed and you have some ROM images you're ready to start - playing. To play a game follow the directions for your operating system.

- -

-

Linux/Unix

- -

The Linux version of Stella uses command line arguments to specify the game - you'd like to play as well as other options. To see the list of available - arguments, simply run stella without any options or filename.

- -

The KDE frontend KStella can - also be used, which provides a graphical, point-and-click interface for changing - most Stella options.

- -

To run Stella from the commandline, use the following format:

- -
   stella [options ...] filename.bin
- -

Options ('0' or 'false' indicates false, '1' or 'true' indicates true, - others are self-explanatory):

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ArgumentDescription
-video <soft|gl>
Use SDL software or OpenGL mode.
-gl_filter <nearest|linear>
Use GL_NEAREST or GL_LINEAR filtering. GL_NEAREST results in a scaled, - pixelated image, while GL_LINEAR introduces blurring.
-gl_aspect <number>
Specify the aspect ratio of the window. Normal TV mode would be 4:3, - so you would specify 1.3333. But since many video modes do not use - square pixels, you may have to try different values. I find 1.6 - gives the most authentic look.
-gl_fsmax <0|1>
Use the maximum possible resolution when switching to fullscreen OpenGL - mode. Under Linux (and Windows on laptops), this is usually the current - desktop resolution, so a video-mode switch can be avoided.
-sound <0|1>
Disable or enable sound.
-fragsize <number>
Specify the sound fragment size to use. Linux/Mac seems to work - with 512, Windows may need 2048.
-framerate <number>
Display the given number of frames per second.
-zoom <size>
Makes window be 'size' times normal.
-fullscreen <0|1>
Play the game in fullscreen mode.
-grabmouse <0|1>
Keeps the mouse in the game window.
-hidecursor <0|1>
Hides the mouse cursor in the game window.
-volume <number>
Set the volume (0 - 100). Use -1 to completely disable - changing the volume.
-paddle <0|1|2|3>
Indicates which paddle the mouse should emulate (defaults to paddle 0).
-altpro <props file>
Use the given properties file instead of stella.pro.
-showinfo <0|1>
Shows some game info when the program exits.
-accurate <0|1>
Accurate game timing (uses more CPU). This setting seems to work - better with the Linux 2.4 kernel. Newer kernels, Mac and Windows - should probably not use this.
-ssdir <path>
The directory to save snapshot files to.
-ssname <romname|md5sum>
How to name the snapshot. Option 'romname' will use the filename - provided in stella.pro, while 'md5sum' will use the calculated - MD5 sum of the rom.
-sssingle <0|1>
Generate single snapshot instead of many.
-mergeprops <0|1>
Save the current properties to a separate file in the users' home directory, - or merge them into the users' stella.pro file.
- -

-

Macintosh

- -

The Mac version of Stella is a native Cocoa-based application.  - When the application starts, a dialog box will ask you to select the - cartridge file that you want to play.  If you do not want to - select a cartridge, but want to use the applications help or about - boxes, you may cancel out of the dialog box, and you Cmd-O to open a - cartridge file later.
-

-

A cartridge may also be selected by dragging the cartridge file to - the application icon, either to start the application, or once it is - running.
-

-

Most of the options of the Macintosh version are selectable by using - the menus, or the Cmd keys associated with the menu entries.  - Note, most of the non-remappable keys are different for the Mac version - than those listed in Section 7 - Keyboard Layout. -

-

The menu choices/Cmd keys for the Mac version are as follows:
-

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FunctionKey
Open New Cartridge (start new game)Cmd + o
Quit StellaCmd + q
Pause StellaCmd + p
Resize window to next larger sizeCmd + =
Resize window to next smaller sizeCmd + -
Toggle Speed (Frame Rate) LimiterCmd + l
Toggle fullscreen/windowed modeCmd + Enter
Toggle OpenGL filtering modesCmd + f
Toggle Display PaletteCmd + Shift + p
Toggle display format between NTSC and PALCmd + Shift + f
Set Mouse to Emulate Paddle 0Cmd + 0
Set Mouse to Emulate Paddle 1Cmd + 1
Set Mouse to Emulate Paddle 2Cmd + 2
Set Mouse to Emulate Paddle 3Cmd + 3
Grab mouse/hide cursor (keep mouse in game window)Cmd + g
Minimize Game WindowCmd + m
Change Game PreferencesCmd + ,
Display this file in Help ViewerCmd + ?
- -

Developer Keys

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FunctionKey
Set "Display.YStart" to next larger valueCmd + PageUp
Set "Display.YStart" to next smaller valueCmd + PageDown
Set "Display.XStart" to next larger valueCmd + End
Set "Display.XStart" to next smaller valueCmd + Home
Set "Display.Width" to next larger valueCmd + Shift + End
Set "Display.Width" to next smaller valueCmd + Shift + Home
Set "Display.Height" to next larger valueCmd + Shift + PageUp
Set "Display.Height" to next smaller valueCmd + Shift + PageDown
- -

-

Windows

- -

The Windows version of Stella is either commandline based or can use a GUI. -

    -
  • If using the commandline version (Stella.exe), the options are the same as - for the Linux version (described above). -
  • If using the GUI version (StellaX.exe), the 'Config' page contains some of - the options as listed for the Linux version (described above). The other - options can be selected from within the emulation itself (see - Section 7 - Keyboard Layout).
  • -
- -

-

- 6. Settings File

-
- -

Stella will remember when you change a setting either at the command line - or while the emulation is running, and use the settings the next time - you start the emulator. The settings are saved in a text file which can - be edited outside of Stella. This file can contain your default options, - and eliminates the need to specify them on the command line. Any - options specified on the command line will override those in the settings file.

- -

The syntax for the settings file is very straightforward. Any line starting with - a ';' character is considered a comment and is ignored. Other lines must be of - the form: command = value, where command is the same as that - specified on the command line (without the '-' character), and value - is dependent on the command.

- -

For example, the following table illustrates how command line and settings entries - are similar:

- - - - - - - - - - - - - - - - - - - - - -
Command LineSettings File
-video glvideo = gl
-volume 75volume = 75
-showinfo 1showinfo = 1 (or showinfo = true)
- -

The settings file has a special name/location depending on which version of Stella - you use:

- -

-

Linux/UNIX

-

The Linux and UNIX version of Stella searches for the stellarc file in - two places. First, it will look for stellarc in your $HOME/.stella directory. - Then, it will look for stellarc in the /etc directory.

- -

-

Macintosh

-

The Macintosh version does not use an INI file, but stores it - preferences in the expected location for application preferences, in - the Users home directory, in the Library/Preferences/StellaOSX.plist - file.
- -

-

Windows

-

The Windows version of Stella looks for the stella.ini file in the same - directory containing the application. Future versions of Stella for Windows may look in - user-specific locations (C:\Documents and Settings\...).

- -

-

- 7. Keyboard Layout

-
- -

The Atari 2600 console controls and controllers are mapped to the computer's - keyboard as shown in the following tables.

- -

As of Stella 1.4, most of these events can be remapped to other keys on your keyboard - or buttons on your joystick (see Section 8 - - Event Remapping). The tables below show the default - settings.

- -

Console Controls

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FunctionKey
Exit emulator (can't be remapped)Escape
Exit submenu in menu mode (can't be remapped)Escape
Enter/exit menu mode (can't be remapped)Tab
Select GameF1
Reset GameF2
Color TVF3
Black/White TVF4
Left Player Difficulty BF5
Left Player Difficulty AF6
Right Player Difficulty BF7
Right Player Difficulty AF8
Save state to current slotF9
Change current state slotF10
Load state from current slotF11
Save PNG snapshotF12
Pause/resume emulationPause
- - -

Joystick Controller

- - - - - - - - - - - - -
Left JoystickRight Joystick
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FunctionKey
Joystick UpUp arrow
Joystick DownDown arrow
Joystick LeftLeft arrow
Joystick RightRight arrow
Fire ButtonSpace
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FunctionKey
Joystick UpY
Joystick DownH
Joystick LeftG
Joystick RightJ
Fire ButtonF
-
- -

Booster-Grip Controller

- - - - - - - - - - - - -
Left Booster-GripRight Booster-Grip
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FunctionKey
Booster-Grip UpSame as left joystick
Booster-Grip DownSame as left joystick
Booster-Grip LeftSame as left joystick
Booster-Grip RightSame as left joystick
Fire ButtonSame as left joystick
Trigger Button4
Booster Button5
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FunctionKey
Booster-Grip UpSame as right joystick
Booster-Grip DownSame as right joystick
Booster-Grip LeftSame as right joystick
Booster-Grip RightSame as right joystick
Fire ButtonSame as right joystick
Trigger Button6
Booster Button7
-
- -

Driving Controller

- - - - - - - - - - - - -
Left DrivingRight Driving
- - - - - - - - - - - - - - - - - - - - -
FunctionKey
Left DirectionInsert
Right DirectionPage Up
Fire ButtonHome
-
- - - - - - - - - - - - - - - - - - - - -
FunctionKey
Left DirectionDelete
Right DirectionPage Down
Fire ButtonEnd
-
- -

Keypad Controller

- - - - - - - - - - - - -
Left KeypadRight Keypad
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Pad ButtonKey
11
22
33
4Q
5W
6E
7A
8S
9D
.Z
0X
#C
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Pad ButtonKey
18
29
30
4I
5O
6P
7K
8L
9;
.,
0.
#/
-
- -

Developer Keys (can't be remapped)

- -

The following keys are activated only if developer support has - been included:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FunctionKey
Set "Display.YStart" to next larger valueAlt + PageUp
Set "Display.YStart" to next smaller valueAlt + PageDown
Set "Display.Height" to next larger valueControl + PageUp
Set "Display.Height" to next smaller valueControl + PageDown
Set "Display.XStart" to next larger valueAlt + End
Set "Display.XStart" to next smaller valueAlt + Home
Set "Display.Width" to next larger valueControl + End
Set "Display.Width" to next smaller valueControl + Home
- -

Other Keys (can't be remapped)

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FunctionKey
Resize window to next larger sizeAlt + =
Resize window to next smaller sizeAlt + -
Grab mouse (keep mouse in game window)Control + g
Hide cursor (hide cursor in game window)Control + h
Toggle fullscreen/windowed modeAlt + Enter
Toggle OpenGL filtering modesAlt + f
Toggle display format between NTSC and PALControl + f
Save (or merge) the current propertiesControl + s
- -


-

- 8. Event Remapping

-
- -

This version of Stella has event remapping. Almost every event in the emulator - can be remapped to another key on the keyboard or to buttons on up to four - joysticks/gamepads (see Section 7 - Keyboard Layout - for those event which can/cannot be remapped).

- -

To remap an event: -

    -
  1. Enter menu mode be pressing Tab.
  2. -
  3. Press Cursor Up/Down to move up/down one line at a time, - or PageUp/PageDown to move up/down 5 lines at a time. The arrows on - the left and right sides of the menu indicate which item is currently - selected.
  4. -
  5. Select Event Remapping and press Enter.
  6. -
  7. Move up/down to select the event you want to remap and press Enter - to change the mapping, or Escape to go to the parent menu.
  8. -
  9. Triangle brackets will appear around the event to be remapped. At this - point you can press any keyboard key or gamepad button to set that key/button - to this event. Or you can press Escape to erase the mapping for this - event.
  10. -
  11. Return to step 4 to remap another event, press Escape to move to the - parent menu, or press Tab again to exit menu mode.
  12. -
- -


-

- 9. Game Properties

-
- -

Stella uses game properties to specify the "best" emulator settings for a - game. As of Version 1.2 of Stella, there are no longer any properties built-in. - You must use the included stella.pro file. Otherwise, the emulator - will try to guess the best settings for the game.

- -

-

Linux/Unix

-

The Linux and Unix versions of Stella looks for the property file - in your $HOME/.stella directory. If this file is not found there, - Stella will look in the /etc/ directory. - -

-

Macintosh

-

The Mac version of Stella looks for the property file  in the - directory containing the application.

- -

-

Windows

-

The Windows version of Stella looks for the property file in the same directory - containing the application. Future versions of Stella for Windows may look in - user-specific locations (C:\Documents and Settings\...).

- -

-

Property File

- -

A property file consists of some number of blocks. Each block in the file - contains the properties for a single game. For example the general format of - a property file is:

- -

-

-   ; Comments
-   "Cartridge.Name"      "Value"
-   "Property"            "Value"
-   ""
-
-   ; Comments
-   "Cartridge.Name"      "Value"
-   "Property"            "Value"
-   ""
-
-   . . .
-
-   ; Comments
-   "Cartridge.Name"      "Value"
-   "Property"            "Value"
-   ""
- -

Every block in the property file must have a unique value for the - Cartridge.Name and Cartridge.MD5 properties.

- -

-

Properties

- -

Each block in a property file consists of a set of properties for a single - game. Stella supports the properties described below:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Cartridge.Filename:This property indicates the name of the file containing the ROM image. -
Cartridge.MD5:This property indicates the MD5 checksum of the ROM image as a - string of hexadecimal digits. Stella uses this property while - attempting to match a game with its block of properties. If the - value of the property matches the MD5 checksum of the ROM image then - Stella uses that block of properties for the game. You can use the - GNU md5sum program, which is included with most Linux distributions, - to calculate the MD5 checksum of a ROM image.
Cartridge.Manufacturer:This property indicates the game's manufacturer. Currently this - property is not being used, however, future versions of Stella will - probably allow the user to view this information.
Cartridge.ModelNo:This property indicates the manufacturer's model number for the - game. Currently this property is not being used, however, future - versions of Stella will probably allow the user to view this information.
Cartridge.Name:This property indicates the actual name of the game. It is very - important that this property's value be unique from all other cartridge - names in the property file.
Cartridge.Note:This property contains any special notes about playing the game. - Currently this property is not being used, however, future versions of - Stella will probably allow the user to view this information.
Cartridge.Type:This property indicates the bank-switching type for the game. - The value of this property must be: Auto-detect, 2K, 3F, 4K, AR, E0, - E7, F4SC, F6, F6SC, F8, F8SC, FASC, or FE. For more information about - bank-switching see Kevin Horton's 2600 bank-switching document.
Console.LeftDifficulty:This property indicates the default difficulty setting for the left - player. The value of this property must be A or B.
Console.RightDifficulty:This property indicates the default difficulty setting for the - right player. The value of this property must be A or B.
Console.TelevisionType:This property indicates the default television setting for the - game. The value of this property must be Color or BlankAndWhite.
Controller.Left:This property indicates what type of controller the left player - uses. The value of this property must be Booster-Grip, Driving, - Keyboard, Paddles, or Joystick.
Controller.Right:This property indicates what type of controller the right player - uses. The value of this property must be Booster-Grip, Driving, - Keyboard, Paddles, or Joystick.
Display.Format:This property indicates the television format the game was - designed for. The value of this property must be NTSC or PAL.
Display.XStart:This property indicates the horizontal location to start displaying - pixels at on a scan-line. The value of this property must be n - such that 0 <= n <= 80 and n is divisible by 4.
Display.Width:This property indicates the number of pixels to display per - scan-line. The value of this property must be n such that - 80 <= n <= 160 and n is divisible by 4.
Display.YStart:This property indicates the scan-line to start displaying at. - The value of this property must be n such that - 0 <= n <= 64.
Display.Height:This property indicates the number of scan-lines to display. - The value of this property must be n such that - 100 <= n <= 256.
Emulation.CPU:This property indicates the CPU emulation quality. The value of - this property must be High or Low.
Emulation.HmoveBlanks:This property indicates whether the TIA HMOVE blank bug should be - emulated or not. The value of this property must be Yes or No.
- -

-

- 10. Stelladaptor Support

-
- -

Stella supports real Atari 2600 joysticks, paddles and driving controllers - using the Stelladaptor device.

- -

Stella can use up to two Stelladaptors; any extra ones are ignored. - Stelladaptor devices will be automatically detected and configured. Devices - can be plugged/unplugged while the emulation is running; Stella will detect the - change and act accordingly.

- -

The detection and configuration is as follows: - -

    -
  • The first Stelladaptor found will act as the left game port - on a real Atari. Depending on the device, Stella will detect it as - either the left joystick, paddles 1 & 2, or the left driving controller.
  • - -
  • The second Stelladaptor found will act as the right game port - on a real Atari. Depending on the device, Stella will detect it as - either the right joystick, paddles 3 & 4, or the right driving controller.
  • - -
  • Any other Stelladaptors will be ignored.
  • -
- -

-

- 11. Acknowledgments

-
- -

Bradford W. Mott started developing Stella during the fall of 1995 and since - then a number of people from around the world have contributed to the project. - Some people have provided technical help while others have offered suggestions - and praise. The Stella Team is grateful for all the help and support it has - received over the years. The following is an incomplete list of the people who have - played a part in bringing Stella to you:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Stephen AnthonyPorted Stella 1.1 to SDL. Added extra command line options to X11/SDL - versions. Added INI file support, faster startup, snapshot support, - and pause functionality to core. Converted Stella 1.1 manual to HTML. - Ported codebase to SDL for Windows/MacOSX. Added OpenGL support and - Stelladaptor support. Current maintainer for the Linux and Windows versions.
David AspellPorted release 0.7 of Stella to Java
Christopher BennettHelped discover a Superchanger emulation bug in release 1.0 of Stella
Alexander BilsteinProvided "A Brief History of the Atari 2600" for this manual
Dan BorisProvided technical information on the Supercharger
Piero CavinaAllowed "Oystron" to be included in the Stella distribution
Bob ColbertAllowed "Okie Dokie" to be included in the Stella distribution
Joe D'AndreaAuthor of the IRIX port of Stella until release 1.2
Renato FerreiraProvided code to support private colormaps under Unix
Ron FriesAuthor of the awesome TIA Sound library
Aaron GilesAuthor of the Power Macintosh version of Stella until release 1.1
Mark GrebeAuthor of the Macintosh OSX version of Stella starting with the - 1.4 release. Helped with Stelladaptor support.
Mark HahnAllowed "Elk Attack" to be included in the Stella distribution and - provided help with the TIA HMOVE blank bug
Kevin HortonAuthor of the definitive Atari 2600 bank-switching document
Thomas JentzschProvided updated NTSC palette and many ideas
Erik KovachAuthor of the property file for release 0.7, 1.0, 1.1, and 1.2 of Stella
Daniel MarksProvided improved keyboard joystick support for Stella release 0.1
James McclainProvided patches for the 1.2 release to get Stella to compile with GCC 3.0
David McEwenAuthor of the Acorn version of Stella
Jeff MillerAuthor of the Windows version of Stella until release 1.2
Dan MowczanProvided a Supercharger to help with Stella's development
Jack NuttingAuthor of the OpenStep version of Stella
Manuel PolikAuthor of the Windows version of Stella starting with the 1.2 release
Jim PragitAuthor of the "Game Menu" emulator game shell
John SaegerParticipated in a helpful discussion on understanding the TIA's - RESPx multi-sprite trick
Chris SalomonProvided information and code to help implement Supercharger support
Jason ScottOrganizer of the property file archive for early versions of - Stella; now he's helping with the web site
David ShawProvided make targets for the BSDI platform
Raul SilvaHelped with design and graphics for an early version of the Stella - web site
Chris SnellMaintained a mirror of the Stella FTP site
Darrell Spice Jr.Author of the OS/2 version of Stella
John StilesMaintained the Macintosh version of Stella until release 1.2
Eckhard StolbergProvided a description of the TIA bug that produces the star field - effect in Cosmic Ark, provided the PAL television palette, and - participated in a helpful discussion on understanding the TIA's RESPx - multi-sprite trick. He also provided the Commavid and Megaboy support - for Stella as well as some improved Supercharger BIOS code.
Matthew StroupAuthor of the Amiga version of Stella
Joel SuttonAuthor of the FreeBSD version of Stella
Greg TroutmanAllowed "This Planet Sucks" to be included in the Stella distribution
Curt VendelProvided schematics of the TIA which are being used to improve the - TIA emulation.
Brian WatsonHelped with getting the illegal CPU instruction support working with Stella. - Brian also submitted a number of other changes, such as debugger support, which - will be integrated into the 1.5 release of Stella.
Keith WilkinsMaintained the DOS version of Stella until release 0.7
Jeff WisniaProvided technical data sheet for the 6532 RIOT chip
- -

-

- 12. License and Disclaimer

-
- -

-

GNU GENERAL PUBLIC LICENSE

-

-Version 2, June 1991 - -

- -
-Copyright (C) 1989, 1991 Free Software Foundation, Inc.  
-59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
-
-Everyone is permitted to copy and distribute verbatim copies
-of this license document, but changing it is not allowed.
-
- - - -

Preamble

- -

- The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Library General Public License instead.) You can apply it to -your programs, too. - -

-

- When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - -

-

- To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - -

-

- For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - -

-

- We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - -

-

- Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - -

-

- Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - -

-

- The precise terms and conditions for copying, distribution and -modification follow. - -

- - -

TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION

- - -

- -0. - This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". -

- -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - -

- -1. - You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. -

- -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. -

- -2. - You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: -

- -

    - -
  • a) - You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - -

    -

  • b) - You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - -

    -

  • c) - If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) -
- -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. -

- -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. -

- -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - -

- -3. - You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - - - -

    - -
  • a) - Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - -

    -

  • b) - Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - -

    -

  • c) - Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) -
- -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. -

- -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. -

- -4. - You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - -

- -5. - You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - -

- -6. - Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - -

- -7. - If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. -

- -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. -

- -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. -

- -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - -

- -8. - If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - -

- -9. - The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. -

- -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - -

- - -10. - If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - - -

NO WARRANTY

- -

- -11. - BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - -

- -12. - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - - diff --git a/stella/src/build/makefile b/stella/src/build/makefile deleted file mode 100644 index 622b32a25..000000000 --- a/stella/src/build/makefile +++ /dev/null @@ -1,345 +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-1999 by Bradford W. Mott -## -## See the file "license" for information on usage and redistribution of -## this file, and for a DISCLAIMER OF ALL WARRANTIES. -## -## $Id: makefile,v 1.56 2004-07-14 16:49:45 stephena Exp $ -##============================================================================ - -##============================================================================ -## Development environment options -## -## The following options are used during compiling. -## Comment a line out to disable that option, remove comment to enable it. -##============================================================================ - -### add your own compiler optimizations here -### if none are provided, the defaults will be used -OPTIMIZATIONS = - -### to include joystick support - JOYSTICK_SUPPORT = 1 - -### to include support for saving snapshots in png format -### (requires PNG library) - SNAPSHOT_SUPPORT = 1 - -### to include support for game developers -### enables some extra commandline options that allow the user -### to override some emulation defaults - DEVELOPER_SUPPORT = 1 - -### to build on SMP (or distcc-based) machines -### change to number of CPU's you have - NUMBER_CPU = 1 - -##============================================================================ -## All done, type make to get a list of frontends -## No configurable options below this line ... -##============================================================================ - -CXX = g++ -LD = g++ - -LDFLAGS = `sdl-config --cflags` -LDLIBS = `sdl-config --libs` -OBJECTS = mainSDL.o SoundSDL.o FrameBufferSDL.o FrameBufferSoft.o -OPTIONS = -EXE_NAME = -SMP = - -SRC = .. -CORE = $(SRC)/emucore -COMMON = $(SRC)/common - -INCLUDES = -I. -I$(CORE) -I$(CORE)/m6502/src \ - -I$(CORE)/m6502/src/bspf/src -I$(COMMON) -I$(SRC)/unix -I$(SRC)/win32 - -## set some sane optimizations if none have been provided -ifndef OPTIMIZATIONS - ifdef CXXFLAGS - OPTIMIZATIONS = $(CXXFLAGS) - else - OPTIMIZATIONS = -O2 - endif -endif - -ifndef NUMBER_CPU - SMP = -j1 -else - SMP = -j$(NUMBER_CPU) -endif - -FLAGS = $(OPTIMIZATIONS) -Wall -Wunused $(INCLUDES) $(SYS_INCLUDES) - -ifdef JOYSTICK_SUPPORT - OPTIONS += -DJOYSTICK_SUPPORT -endif - -ifdef SNAPSHOT_SUPPORT - OBJECTS += Snapshot.o - OPTIONS += -DSNAPSHOT_SUPPORT - LDLIBS += -lpng -lz -endif - -ifdef DEVELOPER_SUPPORT - OPTIONS += -DDEVELOPER_SUPPORT -endif - - -default: - @echo "" - @echo "To build Stella type: 'make '" - @echo "You should edit the makefile for extra options" - @echo "" - @echo " is one of:" - @echo "" - @echo " linux Linux/UNIX version" - @echo " linux-gl Linux/UNIX version with OpenGL support" - @echo " win32 Windows 9x/ME/2000/XP version" - @echo " win32-gl Windows 9x/ME/2000/XP version with OpenGL support" - @echo "" - @echo "Hopefully new versions will be added soon!" - @echo "" - -linux: - $(MAKE) $(SMP) stella \ - EXE_NAME="stella" \ - OPTIONS="$(OPTIONS) -DBSPF_UNIX -DUNIX -DHAVE_GETTIMEOFDAY" \ - OBJS="$(OBJECTS) SettingsUNIX.o" - -linux-gl: - $(MAKE) $(SMP) stella \ - EXE_NAME="stella" \ - LDFLAGS="$(LDFLAGS) -L/usr/X11R6/lib" \ - LDLIBS="$(LDLIBS) -lGL" \ - OPTIONS="$(OPTIONS) -DBSPF_UNIX -DUNIX -DHAVE_GETTIMEOFDAY -DDISPLAY_OPENGL" \ - OBJS="$(OBJECTS) FrameBufferGL.o SettingsUNIX.o" - -win32: - $(MAKE) $(SMP) stella \ - EXE_NAME="stella.exe" \ - OPTIONS="$(OPTIONS) -DBSPF_WIN32 -DWIN32" \ - OBJS="$(OBJECTS) SettingsWin32.o" - -win32-gl: - $(MAKE) $(SMP) stella \ - EXE_NAME="stella.exe" \ - LDLIBS="$(LDLIBS) -lopengl32" \ - OPTIONS="$(OPTIONS) -DBSPF_WIN32 -DWIN32 -DDISPLAY_OPENGL -DTEXTURES_ARE_LOST" \ - OBJS="$(OBJECTS) FrameBufferGL.o SettingsWin32.o" - - -############################################################################### -## List of "core" object files -############################################################################### -M6502_OBJS = D6502.o Device.o M6502.o M6502Low.o M6502Hi.o NullDev.o System.o - -CORE_OBJS = Booster.o Cart.o Cart2K.o Cart3F.o Cart4K.o CartAR.o CartDPC.o \ - CartE0.o CartE7.o CartF4.o CartF4SC.o CartF6.o CartF6SC.o \ - CartF8.o CartF8SC.o CartFASC.o CartFE.o CartMC.o CartCV.o \ - CartMB.o CartUA.o Console.o Control.o Driving.o \ - Event.o Joystick.o Keyboard.o M6532.o MD5.o MediaSrc.o Paddles.o \ - Props.o PropsSet.o Random.o Sound.o Switches.o Settings.o TIA.o \ - Serializer.o Deserializer.o TIASound.o EventHandler.o FrameBuffer.o \ - $(M6502_OBJS) - -stella: $(CORE_OBJS) $(OBJS) - $(LD) -o $(EXE_NAME) $(CORE_OBJS) $(OBJS) $(LDFLAGS) $(LDLIBS) - strip $(EXE_NAME) - -M6502Low.ins: $(CORE)/m6502/src/M6502Low.m4 $(CORE)/m6502/src/M6502.m4 - m4 $(CORE)/m6502/src/M6502Low.m4 $(CORE)/m6502/src/M6502.m4 > $(CORE)/m6502/src/M6502Low.ins - -M6502Hi.ins: $(CORE)/m6502/src/M6502Hi.m4 $(CORE)/m6502/src/M6502.m4 - m4 $(CORE)/m6502/src/M6502Hi.m4 $(CORE)/m6502/src/M6502.m4 > $(CORE)/m6502/src/M6502Hi.ins - -#M6502Low.o: M6502Low.ins -#M6502Hi.o: M6502Hi.ins - -clean: - rm -f *.o stella stella.exe core - -Driving.o: $(CORE)/Driving.cxx $(CORE)/Driving.hxx - $(CXX) -c $(FLAGS) $(OPTIONS) $(CORE)/Driving.cxx - -Event.o: $(CORE)/Event.cxx $(CORE)/Event.hxx - $(CXX) -c $(FLAGS) $(OPTIONS) $(CORE)/Event.cxx - -EventHandler.o: $(CORE)/EventHandler.cxx $(CORE)/EventHandler.hxx - $(CXX) -c $(FLAGS) $(OPTIONS) $(CORE)/EventHandler.cxx - -Control.o: $(CORE)/Control.cxx $(CORE)/Control.hxx - $(CXX) -c $(FLAGS) $(OPTIONS) $(CORE)/Control.cxx - -Joystick.o: $(CORE)/Joystick.cxx $(CORE)/Joystick.hxx - $(CXX) -c $(FLAGS) $(OPTIONS) $(CORE)/Joystick.cxx - -Keyboard.o: $(CORE)/Keyboard.cxx $(CORE)/Keyboard.hxx - $(CXX) -c $(FLAGS) $(OPTIONS) $(CORE)/Keyboard.cxx - -Paddles.o: $(CORE)/Paddles.cxx $(CORE)/Paddles.hxx - $(CXX) -c $(FLAGS) $(OPTIONS) $(CORE)/Paddles.cxx - -Booster.o: $(CORE)/Booster.cxx $(CORE)/Booster.hxx - $(CXX) -c $(FLAGS) $(OPTIONS) $(CORE)/Booster.cxx - -Cart.o: $(CORE)/Cart.cxx $(CORE)/Cart.hxx - $(CXX) -c $(FLAGS) $(OPTIONS) $(CORE)/Cart.cxx - -Cart2K.o: $(CORE)/Cart2K.cxx $(CORE)/Cart2K.hxx - $(CXX) -c $(FLAGS) $(OPTIONS) $(CORE)/Cart2K.cxx - -Cart3F.o: $(CORE)/Cart3F.cxx $(CORE)/Cart3F.hxx - $(CXX) -c $(FLAGS) $(OPTIONS) $(CORE)/Cart3F.cxx - -Cart4K.o: $(CORE)/Cart4K.cxx $(CORE)/Cart4K.hxx - $(CXX) -c $(FLAGS) $(OPTIONS) $(CORE)/Cart4K.cxx - -CartAR.o: $(CORE)/CartAR.cxx $(CORE)/CartAR.hxx - $(CXX) -c $(FLAGS) $(OPTIONS) $(CORE)/CartAR.cxx - -CartCV.o: $(CORE)/CartCV.cxx $(CORE)/CartCV.hxx - $(CXX) -c $(FLAGS) $(OPTIONS) $(CORE)/CartCV.cxx - -CartDPC.o: $(CORE)/CartDPC.cxx $(CORE)/CartDPC.hxx - $(CXX) -c $(FLAGS) $(OPTIONS) $(CORE)/CartDPC.cxx - -CartE0.o: $(CORE)/CartE0.cxx $(CORE)/CartE0.hxx - $(CXX) -c $(FLAGS) $(OPTIONS) $(CORE)/CartE0.cxx - -CartE7.o: $(CORE)/CartE7.cxx $(CORE)/CartE7.hxx - $(CXX) -c $(FLAGS) $(OPTIONS) $(CORE)/CartE7.cxx - -CartF4.o: $(CORE)/CartF4.cxx $(CORE)/CartF4.hxx - $(CXX) -c $(FLAGS) $(OPTIONS) $(CORE)/CartF4.cxx - -CartF4SC.o: $(CORE)/CartF4SC.cxx $(CORE)/CartF4SC.hxx - $(CXX) -c $(FLAGS) $(OPTIONS) $(CORE)/CartF4SC.cxx - -CartF6.o: $(CORE)/CartF6.cxx $(CORE)/CartF6.hxx - $(CXX) -c $(FLAGS) $(OPTIONS) $(CORE)/CartF6.cxx - -CartF6SC.o: $(CORE)/CartF6SC.cxx $(CORE)/CartF6SC.hxx - $(CXX) -c $(FLAGS) $(OPTIONS) $(CORE)/CartF6SC.cxx - -CartF8.o: $(CORE)/CartF8.cxx $(CORE)/CartF8.hxx - $(CXX) -c $(FLAGS) $(OPTIONS) $(CORE)/CartF8.cxx - -CartF8SC.o: $(CORE)/CartF8SC.cxx $(CORE)/CartF8SC.hxx - $(CXX) -c $(FLAGS) $(OPTIONS) $(CORE)/CartF8SC.cxx - -CartFASC.o: $(CORE)/CartFASC.cxx $(CORE)/CartFASC.hxx - $(CXX) -c $(FLAGS) $(OPTIONS) $(CORE)/CartFASC.cxx - -CartFE.o: $(CORE)/CartFE.cxx $(CORE)/CartFE.hxx - $(CXX) -c $(FLAGS) $(OPTIONS) $(CORE)/CartFE.cxx - -CartMB.o: $(CORE)/CartMB.cxx $(CORE)/CartMB.hxx - $(CXX) -c $(FLAGS) $(OPTIONS) $(CORE)/CartMB.cxx - -CartMC.o: $(CORE)/CartMC.cxx $(CORE)/CartMC.hxx - $(CXX) -c $(FLAGS) $(OPTIONS) $(CORE)/CartMC.cxx - -CartUA.o: $(CORE)/CartUA.cxx $(CORE)/CartUA.hxx - $(CXX) -c $(FLAGS) $(OPTIONS) $(CORE)/CartUA.cxx - -M6532.o: $(CORE)/M6532.cxx $(CORE)/M6532.hxx - $(CXX) -c $(FLAGS) $(OPTIONS) $(CORE)/M6532.cxx - -TIA.o: $(CORE)/TIA.cxx $(CORE)/TIA.hxx - $(CXX) -c $(FLAGS) $(OPTIONS) $(CORE)/TIA.cxx - -TIASound.o: $(CORE)/TIASound.c $(CORE)/TIASound.h - $(CXX) -c -DWIN32 $(FLAGS) $(OPTIONS) $(CORE)/TIASound.c - -Console.o: $(CORE)/Console.cxx $(CORE)/Console.hxx - $(CXX) -c $(FLAGS) $(OPTIONS) $(CORE)/Console.cxx - -MD5.o: $(CORE)/MD5.cxx $(CORE)/MD5.hxx - $(CXX) -c $(FLAGS) $(OPTIONS) $(CORE)/MD5.cxx - -MediaSrc.o: $(CORE)/MediaSrc.cxx $(CORE)/MediaSrc.hxx - $(CXX) -c $(FLAGS) $(OPTIONS) $(CORE)/MediaSrc.cxx - -FrameBuffer.o: $(CORE)/FrameBuffer.cxx $(CORE)/FrameBuffer.hxx - $(CXX) -c $(FLAGS) $(OPTIONS) $(CORE)/FrameBuffer.cxx - -PropsSet.o: $(CORE)/PropsSet.cxx $(CORE)/PropsSet.hxx - $(CXX) -c $(FLAGS) $(OPTIONS) $(CORE)/PropsSet.cxx - -Props.o: $(CORE)/Props.cxx $(CORE)/Props.hxx - $(CXX) -c $(FLAGS) $(OPTIONS) $(CORE)/Props.cxx - -Random.o: $(CORE)/Random.cxx $(CORE)/Random.hxx - $(CXX) -c $(FLAGS) $(OPTIONS) $(CORE)/Random.cxx - -Sound.o: $(CORE)/Sound.cxx $(CORE)/Sound.hxx - $(CXX) -c $(FLAGS) $(OPTIONS) $(LDFLAGS) $(CORE)/Sound.cxx - -Switches.o: $(CORE)/Switches.cxx $(CORE)/Switches.hxx - $(CXX) -c $(FLAGS) $(OPTIONS) $(CORE)/Switches.cxx - -Serializer.o: $(CORE)/Serializer.cxx $(CORE)/Serializer.hxx - $(CXX) -c $(FLAGS) $(OPTIONS) $(CORE)/Serializer.cxx - -Deserializer.o: $(CORE)/Deserializer.cxx $(CORE)/Deserializer.hxx - $(CXX) -c $(FLAGS) $(OPTIONS) $(CORE)/Deserializer.cxx - -Settings.o: $(CORE)/Settings.cxx $(CORE)/Settings.hxx - $(CXX) -c $(FLAGS) $(OPTIONS) $(LDFLAGS) $(CORE)/Settings.cxx - -SettingsUNIX.o: $(SRC)/unix/SettingsUNIX.cxx $(SRC)/unix/SettingsUNIX.hxx - $(CXX) -c $(FLAGS) $(OPTIONS) $(LDFLAGS) $(SRC)/unix/SettingsUNIX.cxx - -SettingsWin32.o: $(SRC)/win32/SettingsWin32.cxx $(SRC)/win32/SettingsWin32.hxx - $(CXX) -c $(FLAGS) $(OPTIONS) $(LDFLAGS) $(SRC)/win32/SettingsWin32.cxx - -SoundSDL.o: $(COMMON)/SoundSDL.cxx $(COMMON)/SoundSDL.hxx - $(CXX) -c $(FLAGS) $(OPTIONS) $(LDFLAGS) $(COMMON)/SoundSDL.cxx - -mainSDL.o: $(COMMON)/mainSDL.cxx - $(CXX) -c $(FLAGS) $(OPTIONS) $(LDFLAGS) $(COMMON)/mainSDL.cxx - -FrameBufferSDL.o: $(COMMON)/FrameBufferSDL.cxx $(COMMON)/FrameBufferSDL.hxx - $(CXX) -c $(FLAGS) $(OPTIONS) $(LDFLAGS) $(COMMON)/FrameBufferSDL.cxx - -FrameBufferSoft.o: $(COMMON)/FrameBufferSoft.cxx $(COMMON)/FrameBufferSoft.hxx - $(CXX) -c $(FLAGS) $(OPTIONS) $(LDFLAGS) $(COMMON)/FrameBufferSoft.cxx - -FrameBufferGL.o: $(COMMON)/FrameBufferGL.cxx $(COMMON)/FrameBufferGL.hxx - $(CXX) -c $(FLAGS) $(OPTIONS) $(LDFLAGS) $(COMMON)/FrameBufferGL.cxx - -Snapshot.o: $(COMMON)/Snapshot.cxx $(COMMON)/Snapshot.hxx - $(CXX) -c $(FLAGS) $(OPTIONS) $(LDFLAGS) $(COMMON)/Snapshot.cxx - -D6502.o: $(CORE)/m6502/src/D6502.cxx - $(CXX) -c $(FLAGS) $(OPTIONS) $(CORE)/m6502/src/D6502.cxx - -Device.o: $(CORE)/m6502/src/Device.cxx - $(CXX) -c $(FLAGS) $(OPTIONS) $(CORE)/m6502/src/Device.cxx - -M6502.o: $(CORE)/m6502/src/M6502.cxx - $(CXX) -c $(FLAGS) $(OPTIONS) $(CORE)/m6502/src/M6502.cxx - -M6502Low.o: $(CORE)/m6502/src/M6502Low.cxx - $(CXX) -c $(FLAGS) $(OPTIONS) $(CORE)/m6502/src/M6502Low.cxx - -M6502Hi.o: $(CORE)/m6502/src/M6502Hi.cxx - $(CXX) -c $(FLAGS) $(OPTIONS) $(CORE)/m6502/src/M6502Hi.cxx - -NullDev.o: $(CORE)/m6502/src/NullDev.cxx $(CORE)/m6502/src/NullDev.hxx - $(CXX) -c $(FLAGS) $(OPTIONS) $(CORE)/m6502/src/NullDev.cxx - -System.o: $(CORE)/m6502/src/System.cxx $(CORE)/m6502/src/System.hxx - $(CXX) -c $(FLAGS) $(OPTIONS) $(CORE)/m6502/src/System.cxx diff --git a/stella/src/common/FrameBufferSDL.cxx b/stella/src/common/FrameBufferSDL.cxx deleted file mode 100644 index 63fd0863e..000000000 --- a/stella/src/common/FrameBufferSDL.cxx +++ /dev/null @@ -1,268 +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-1999 by Bradford W. Mott -// -// See the file "license" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -// -// $Id: FrameBufferSDL.cxx,v 1.1 2004-05-24 17:18:22 stephena Exp $ -//============================================================================ - -#include -#include -#include - -#include "Console.hxx" -#include "FrameBuffer.hxx" -#include "FrameBufferSDL.hxx" -#include "MediaSrc.hxx" -#include "Settings.hxx" - -#include "stella.xpm" // The Stella icon - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -FrameBufferSDL::FrameBufferSDL() - : x11Available(false), - theZoomLevel(1), - theMaxZoomLevel(1), - theAspectRatio(1.0), - myPauseStatus(false) -{ -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -FrameBufferSDL::~FrameBufferSDL() -{ -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void FrameBufferSDL::pauseEvent(bool status) -{ - myPauseStatus = status; - setupPalette(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void FrameBufferSDL::setupPalette() -{ - // Shade the palette to 75% normal value in pause mode - float shade = 1.0; - if(myPauseStatus) - shade = 0.75; - - const uInt32* gamePalette = myMediaSource->palette(); - for(uInt32 i = 0; i < 256; ++i) - { - Uint8 r, g, b; - - r = (Uint8) (((gamePalette[i] & 0x00ff0000) >> 16) * shade); - g = (Uint8) (((gamePalette[i] & 0x0000ff00) >> 8) * shade); - b = (Uint8) ((gamePalette[i] & 0x000000ff) * shade); - - myPalette[i] = mapRGB(r, g, b); - } - - theRedrawEntireFrameIndicator = true; -} - - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void FrameBufferSDL::toggleFullscreen() -{ - bool isFullscreen = !myConsole->settings().getBool("fullscreen"); - - // Update the settings - myConsole->settings().setBool("fullscreen", isFullscreen); - - if(isFullscreen) - mySDLFlags |= SDL_FULLSCREEN; - else - mySDLFlags &= ~SDL_FULLSCREEN; - - if(!createScreen()) - return; - - if(isFullscreen) // now in fullscreen mode - { - grabMouse(true); - showCursor(false); - } - else // now in windowed mode - { - grabMouse(myConsole->settings().getBool("grabmouse")); - showCursor(!myConsole->settings().getBool("hidecursor")); - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void FrameBufferSDL::resize(int mode) -{ - // reset size to that given in properties - // this is a special case of allowing a resize while in fullscreen mode - if(mode == 0) - { - myWidth = myMediaSource->width() << 1; - myHeight = myMediaSource->height(); - } - else if(mode == 1) // increase size - { - if(myConsole->settings().getBool("fullscreen")) - return; - - if(theZoomLevel == theMaxZoomLevel) - theZoomLevel = 1; - else - theZoomLevel++; - } - else if(mode == -1) // decrease size - { - if(myConsole->settings().getBool("fullscreen")) - return; - - if(theZoomLevel == 1) - theZoomLevel = theMaxZoomLevel; - else - theZoomLevel--; - } - - if(!createScreen()) - return; - - // Update the settings - myConsole->settings().setInt("zoom", theZoomLevel); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void FrameBufferSDL::showCursor(bool show) -{ - if(show) - SDL_ShowCursor(SDL_ENABLE); - else - SDL_ShowCursor(SDL_DISABLE); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void FrameBufferSDL::grabMouse(bool grab) -{ - if(grab) - SDL_WM_GrabInput(SDL_GRAB_ON); - else - SDL_WM_GrabInput(SDL_GRAB_OFF); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool FrameBufferSDL::fullScreen() -{ - return myConsole->settings().getBool("fullscreen"); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt32 FrameBufferSDL::maxWindowSizeForScreen() -{ - if(!x11Available) - return 4; - -#ifdef UNIX - // Otherwise, lock the screen and get the width and height - myWMInfo.info.x11.lock_func(); - Display* theX11Display = myWMInfo.info.x11.display; - myWMInfo.info.x11.unlock_func(); - - int screenWidth = DisplayWidth(theX11Display, DefaultScreen(theX11Display)); - int screenHeight = DisplayHeight(theX11Display, DefaultScreen(theX11Display)); - - uInt32 multiplier = screenWidth / myWidth; - bool found = false; - - while(!found && (multiplier > 0)) - { - // Figure out the desired size of the window - int width = (int) (myWidth * multiplier * theAspectRatio); - int height = myHeight * multiplier; - - if((width < screenWidth) && (height < screenHeight)) - found = true; - else - multiplier--; - } - - if(found) - return multiplier; - else - return 1; -#endif - - return 4; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void FrameBufferSDL::setWindowAttributes() -{ - // Set the window title - ostringstream name; - name << "Stella: \"" << myConsole->properties().get("Cartridge.Name") << "\""; - SDL_WM_SetCaption(name.str().c_str(), "stella"); - -#ifndef MAC_OSX - // Set the window icon - uInt32 w, h, ncols, nbytes; - uInt32 rgba[256], icon[32 * 32]; - uInt8 mask[32][4]; - - sscanf(stella_icon[0], "%d %d %d %d", &w, &h, &ncols, &nbytes); - if((w != 32) || (h != 32) || (ncols > 255) || (nbytes > 1)) - { - cerr << "ERROR: Couldn't load the icon.\n"; - return; - } - - for(uInt32 i = 0; i < ncols; i++) - { - unsigned char code; - char color[32]; - uInt32 col; - - sscanf(stella_icon[1 + i], "%c c %s", &code, color); - if(!strcmp(color, "None")) - col = 0x00000000; - else if(!strcmp(color, "black")) - col = 0xFF000000; - else if (color[0] == '#') - { - sscanf(color + 1, "%06x", &col); - col |= 0xFF000000; - } - else - { - cerr << "ERROR: Couldn't load the icon.\n"; - return; - } - rgba[code] = col; - } - - memset(mask, 0, sizeof(mask)); - for(h = 0; h < 32; h++) - { - const char* line = stella_icon[1 + ncols + h]; - for(w = 0; w < 32; w++) - { - icon[w + 32 * h] = rgba[(int)line[w]]; - if(rgba[(int)line[w]] & 0xFF000000) - mask[h][w >> 3] |= 1 << (7 - (w & 0x07)); - } - } - - SDL_Surface *surface = SDL_CreateRGBSurfaceFrom(icon, 32, 32, 32, - 32 * 4, 0xFF0000, 0x00FF00, 0x0000FF, 0xFF000000); - SDL_WM_SetIcon(surface, (unsigned char *) mask); - SDL_FreeSurface(surface); -#endif -} diff --git a/stella/src/common/FrameBufferSDL.hxx b/stella/src/common/FrameBufferSDL.hxx deleted file mode 100644 index 4c79dc1ee..000000000 --- a/stella/src/common/FrameBufferSDL.hxx +++ /dev/null @@ -1,176 +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-1999 by Bradford W. Mott -// -// See the file "license" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -// -// $Id: FrameBufferSDL.hxx,v 1.3 2004-06-23 00:15:32 stephena Exp $ -//============================================================================ - -#ifndef FRAMEBUFFER_SDL_HXX -#define FRAMEBUFFER_SDL_HXX - -#include -#include - -#include "FrameBuffer.hxx" -#include "Settings.hxx" -#include "bspf.hxx" - -/** - This class is a base class for the SDL framebuffer and is derived from - the core FrameBuffer class. - - It defines all common code shared between the software - and OpenGL video modes, as well as required methods defined in - the core FrameBuffer. - - @author Stephen Anthony - @version $Id: FrameBufferSDL.hxx,v 1.3 2004-06-23 00:15:32 stephena Exp $ -*/ -class FrameBufferSDL : public FrameBuffer -{ - public: - /** - Creates a new SDL framebuffer - */ - FrameBufferSDL(); - - /** - Destructor - */ - virtual ~FrameBufferSDL(); - - /** - Toggles between fullscreen and window mode. Grabmouse and hidecursor - activated when in fullscreen mode. - */ - void toggleFullscreen(); - - /** - This routine is called when the user wants to resize the window. - A '1' argument indicates that the window should increase in size, while '-1' - indicates that the windows should decrease in size. A '0' indicates that - the window should be sized according to the current properties. - Can't resize in fullscreen mode. Will only resize up to the maximum size - of the screen. - */ - void resize(int mode); - - /** - Shows or hides the cursor based on the given boolean value. - */ - void showCursor(bool show); - - /** - Grabs or ungrabs the mouse based on the given boolean value. - */ - void grabMouse(bool grab); - - /** - Answers if the display is currently in fullscreen mode. - */ - bool fullScreen(); - - /** - Answers the current zoom level of the SDL - */ - uInt32 zoomLevel() { return theZoomLevel; } - - /** - Calculate the maximum window size that the current screen can hold. - Only works in X11 for now. If not running under X11, always return 4. - */ - uInt32 maxWindowSizeForScreen(); - - /** - This routine is called to get the width of the onscreen image. - */ - uInt32 imageWidth() { return myDimensions.w; } - - /** - This routine is called to get the height of the onscreen image. - */ - uInt32 imageHeight() { return myDimensions.h; } - - /** - Set the title and icon for the main SDL window. - */ - void setWindowAttributes(); - - /** - Set up the palette for a screen of any depth > 8. - */ - void setupPalette(); - - ////////////////////////////////////////////////////////////////////// - // The following methods are derived from FrameBuffer.hxx - ////////////////////////////////////////////////////////////////////// - /** - This routine is called when the emulation has been paused. - - @param status Toggle pause based on status - */ - void pauseEvent(bool status); - - ////////////////////////////////////////////////////////////////////// - // The following methods must be defined in child classes - ////////////////////////////////////////////////////////////////////// - /** - This routine is called whenever the screen needs to be recreated. - It updates the global screen variable. - */ - virtual bool createScreen() = 0; - - /** - This routine is called to map a given r,g,b triple to the screen palette. - - @param r The red component of the color. - @param g The green component of the color. - @param b The blue component of the color. - */ - virtual Uint32 mapRGB(Uint8 r, Uint8 g, Uint8 b) = 0; - - protected: - // The SDL video buffer - SDL_Surface* myScreen; - - // SDL initialization flags - uInt32 mySDLFlags; - - // SDL palette - Uint32 myPalette[256]; - - // Used to get window-manager specifics - SDL_SysWMinfo myWMInfo; - - // Indicates the width/height and origin x/y of the onscreen image - // (these may be different than the screen/window dimensions) - SDL_Rect myDimensions; - - // Indicates if we are running under X11 - bool x11Available; - - // Indicates the current zoom level of the SDL screen - uInt32 theZoomLevel; - - // Indicates the maximum zoom of the SDL screen - uInt32 theMaxZoomLevel; - - // The aspect ratio of the window - float theAspectRatio; - - // Indicates whether the emulation has paused - bool myPauseStatus; -}; - -#endif diff --git a/stella/src/emucore/MediaSrc.cxx b/stella/src/emucore/MediaSrc.cxx deleted file mode 100644 index 2ca5840cf..000000000 --- a/stella/src/emucore/MediaSrc.cxx +++ /dev/null @@ -1,44 +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-1998 by Bradford W. Mott -// -// See the file "license" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -// -// $Id: MediaSrc.cxx,v 1.1.1.1 2001-12-27 19:54:22 bwmott Exp $ -//============================================================================ - -#include -#include "MediaSrc.hxx" - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -MediaSource::MediaSource() -{ -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -MediaSource::~MediaSource() -{ -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -MediaSource::MediaSource(const MediaSource&) -{ -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -MediaSource& MediaSource::operator = (const MediaSource&) -{ - assert(false); - - return *this; -} - diff --git a/stella/src/emucore/MediaSrc.hxx b/stella/src/emucore/MediaSrc.hxx deleted file mode 100644 index da9505417..000000000 --- a/stella/src/emucore/MediaSrc.hxx +++ /dev/null @@ -1,109 +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-2002 by Bradford W. Mott -// -// See the file "license" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -// -// $Id: MediaSrc.hxx,v 1.8 2004-07-14 16:15:06 stephena Exp $ -//============================================================================ - -#ifndef MEDIASOURCE_HXX -#define MEDIASOURCE_HXX - -#include - -class MediaSource; - -#include "bspf.hxx" - -/** - This class provides an interface for accessing graphics and audio data. - - @author Bradford W. Mott - @version $Id: MediaSrc.hxx,v 1.8 2004-07-14 16:15:06 stephena Exp $ -*/ -class MediaSource -{ - public: - /** - Create a new media source - */ - MediaSource(); - - /** - Destructor - */ - virtual ~MediaSource(); - - public: - /** - This method should be called at an interval corresponding to the - desired frame rate to update the media source. Invoking this method - will update the graphics buffer and generate the corresponding audio - samples. - */ - virtual void update() = 0; - - /** - Answers the current frame buffer - - @return Pointer to the current frame buffer - */ - virtual uInt8* currentFrameBuffer() const = 0; - - /** - Answers the previous frame buffer - - @return Pointer to the previous frame buffer - */ - virtual uInt8* previousFrameBuffer() const = 0; - - public: - /** - Get the palette which maps frame data to RGB values. - - @return Array of integers which represent the palette (RGB) - */ - virtual const uInt32* palette() const = 0; - - /** - Answers the height of the frame buffer - - @return The frame's height - */ - virtual uInt32 height() const = 0; - - /** - Answers the width of the frame buffer - - @return The frame's width - */ - virtual uInt32 width() const = 0; - - public: - /** - Answers the total number of scanlines the media source generated - in producing the current frame buffer. - - @return The total number of scanlines generated - */ - virtual uInt32 scanlines() const = 0; - - private: - // Copy constructor isn't supported by this class so make it private - MediaSource(const MediaSource&); - - // Assignment operator isn't supported by this class so make it private - MediaSource& operator = (const MediaSource&); -}; -#endif - diff --git a/stella/src/emucore/Sound.cxx b/stella/src/emucore/Sound.cxx deleted file mode 100644 index 5d0138121..000000000 --- a/stella/src/emucore/Sound.cxx +++ /dev/null @@ -1,114 +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-2004 by Bradford W. Mott -// -// See the file "license" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -// -// $Id: Sound.cxx,v 1.12 2004-06-13 04:54:25 bwmott Exp $ -//============================================================================ - -#include "Serializer.hxx" -#include "Deserializer.hxx" - -#include "Sound.hxx" - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Sound::Sound(uInt32 fragsize) - : myLastRegisterSetCycle(0) -{ -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Sound::~Sound() -{ -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Sound::adjustCycleCounter(Int32 amount) -{ - myLastRegisterSetCycle += amount; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Sound::mute(bool state) -{ -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Sound::init(Console* console, MediaSource* mediasrc, System* system) -{ - myConsole = console; - myMediaSource = mediasrc; - mySystem = system; - myLastRegisterSetCycle = 0; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool Sound::isSuccessfullyInitialized() const -{ - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Sound::reset() -{ -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Sound::set(uInt16 addr, uInt8 value, Int32 cycle) -{ - myLastRegisterSetCycle = cycle; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void Sound::setVolume(Int32 volume) -{ -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool Sound::load(Deserializer& in) -{ - string soundDevice = "TIASound"; - if(in.getString() != soundDevice) - return false; - - uInt8 reg; - reg = (uInt8) in.getLong(); - reg = (uInt8) in.getLong(); - reg = (uInt8) in.getLong(); - reg = (uInt8) in.getLong(); - reg = (uInt8) in.getLong(); - reg = (uInt8) in.getLong(); - - myLastRegisterSetCycle = (Int32)in.getLong(); - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool Sound::save(Serializer& out) -{ - out.putString("TIASound"); - - uInt8 reg = 0; - out.putLong(reg); - out.putLong(reg); - out.putLong(reg); - out.putLong(reg); - out.putLong(reg); - out.putLong(reg); - - out.putLong(myLastRegisterSetCycle); - - return true; -} - diff --git a/stella/src/emucore/StellaEvent.hxx b/stella/src/emucore/StellaEvent.hxx deleted file mode 100644 index 7611a720a..000000000 --- a/stella/src/emucore/StellaEvent.hxx +++ /dev/null @@ -1,97 +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-1998 by Bradford W. Mott -// -// See the file "license" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -// -// $Id: StellaEvent.hxx,v 1.9 2004-05-06 00:06:19 stephena Exp $ -//============================================================================ - -#ifndef STELLAEVENT_HXX -#define STELLAEVENT_HXX - -/** - This file defines the global STELLA events that the frontends - will use to communicate with the Event Handler. - - Only the standard keys are defined here. Function and - navigation (HOME, END, etc) keys are special and must be handled - by the frontends directly. - - @author Stephen Anthony - @version $Id: StellaEvent.hxx,v 1.9 2004-05-06 00:06:19 stephena Exp $ -*/ -class StellaEvent -{ - public: - /** - Enumeration of keyboard keycodes - - Note that the order of these codes is related to - UserInterface::ourEventName. If these are ever changed or rearranged, - that array must be updated as well. - */ - enum KeyCode - { - KCODE_a, KCODE_b, KCODE_c, KCODE_d, KCODE_e, KCODE_f, KCODE_g, KCODE_h, - KCODE_i, KCODE_j, KCODE_k, KCODE_l, KCODE_m, KCODE_n, KCODE_o, KCODE_p, - KCODE_q, KCODE_r, KCODE_s, KCODE_t, KCODE_u, KCODE_v, KCODE_w, KCODE_x, - KCODE_y, KCODE_z, - - KCODE_0, KCODE_1, KCODE_2, KCODE_3, KCODE_4, KCODE_5, KCODE_6, KCODE_7, - KCODE_8, KCODE_9, - - KCODE_KP0, KCODE_KP1, KCODE_KP2, KCODE_KP3, KCODE_KP4, KCODE_KP5, KCODE_KP6, - KCODE_KP7, KCODE_KP8, KCODE_KP9, KCODE_KP_PERIOD, KCODE_KP_DIVIDE, - KCODE_KP_MULTIPLY, KCODE_KP_MINUS, KCODE_KP_PLUS, KCODE_KP_ENTER, - KCODE_KP_EQUALS, - - KCODE_BACKSPACE, KCODE_TAB, KCODE_CLEAR, KCODE_RETURN, - KCODE_ESCAPE, KCODE_SPACE, KCODE_COMMA, KCODE_MINUS, KCODE_PERIOD, - KCODE_SLASH, KCODE_BACKSLASH, KCODE_SEMICOLON, KCODE_EQUALS, - KCODE_QUOTE, KCODE_BACKQUOTE, KCODE_LEFTBRACKET, KCODE_RIGHTBRACKET, - - KCODE_PRTSCREEN, KCODE_SCRLOCK, KCODE_PAUSE, - KCODE_INSERT, KCODE_HOME, KCODE_PAGEUP, - KCODE_DELETE, KCODE_END, KCODE_PAGEDOWN, - - KCODE_LCTRL, KCODE_RCTRL, KCODE_LALT, KCODE_RALT, KCODE_LWIN, - KCODE_RWIN, KCODE_MENU, KCODE_UP, KCODE_DOWN, KCODE_LEFT, KCODE_RIGHT, - - KCODE_F1, KCODE_F2, KCODE_F3, KCODE_F4, KCODE_F5, KCODE_F6, KCODE_F7, - KCODE_F8, KCODE_F9, KCODE_F10, KCODE_F11, KCODE_F12, KCODE_F13, - KCODE_F14, KCODE_F15, - - LastKCODE - }; - - /** - Enumeration of joystick codes and states - */ - enum JoyStick - { - JSTICK_0, JSTICK_1, JSTICK_2, JSTICK_3, JSTICK_4, JSTICK_5, - LastJSTICK - }; - - enum JoyCode - { - JAXIS_UP, JAXIS_DOWN, JAXIS_LEFT, JAXIS_RIGHT, - JBUTTON_0, JBUTTON_1, JBUTTON_2, JBUTTON_3, JBUTTON_4, - JBUTTON_5, JBUTTON_6, JBUTTON_7, JBUTTON_8, JBUTTON_9, - JBUTTON_10, JBUTTON_11, JBUTTON_12, JBUTTON_13, JBUTTON_14, - JBUTTON_15, JBUTTON_16, JBUTTON_17, JBUTTON_18, JBUTTON_19, - LastJCODE - }; -}; - -#endif diff --git a/stella/src/emucore/TIASound.c b/stella/src/emucore/TIASound.c deleted file mode 100644 index 315558cf2..000000000 --- a/stella/src/emucore/TIASound.c +++ /dev/null @@ -1,689 +0,0 @@ -/*****************************************************************************/ -/* */ -/* Module: TIA Chip Sound Simulator */ -/* Purpose: To emulate the sound generation hardware of the Atari TIA chip. */ -/* Author: Ron Fries */ -/* */ -/* Revision History: */ -/* 10-Sep-96 - V1.0 - Initial Release */ -/* 14-Jan-97 - V1.1 - Cleaned up sound output by eliminating counter */ -/* reset. */ -/* */ -/*****************************************************************************/ -/* */ -/* License Information and Copyright Notice */ -/* ======================================== */ -/* */ -/* TiaSound is Copyright(c) 1996 by Ron Fries */ -/* */ -/* This library is free software; you can redistribute it and/or modify it */ -/* under the terms of version 2 of the GNU Library General Public License */ -/* as published by the Free Software Foundation. */ -/* */ -/* This library is distributed in the hope that it will be useful, but */ -/* WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library */ -/* General Public License for more details. */ -/* To obtain a copy of the GNU Library General Public License, write to the */ -/* Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* */ -/* Any permitted reproduction of these routines, in whole or in part, must */ -/* bear this legend. */ -/* */ -/*****************************************************************************/ - -#ifdef __cplusplus -extern "C" { -#endif - -#include -#include -#include - - -/* define some data types to keep it platform independent */ -#ifdef WIN32 -#define int8 char -#define int16 short -#define int32 int -#else -#define int8 char -#define int16 int -#define int32 long -#endif - -#define uint8 unsigned int8 -#define uint16 unsigned int16 -#define uint32 unsigned int32 - - -/* CONSTANT DEFINITIONS */ - -/* definitions for AUDCx (15, 16) */ -#define SET_TO_1 0x00 /* 0000 */ -#define POLY4 0x01 /* 0001 */ -#define DIV31_POLY4 0x02 /* 0010 */ -#define POLY5_POLY4 0x03 /* 0011 */ -#define PURE 0x04 /* 0100 */ -#define PURE2 0x05 /* 0101 */ -#define DIV31_PURE 0x06 /* 0110 */ -#define POLY5_2 0x07 /* 0111 */ -#define POLY9 0x08 /* 1000 */ -#define POLY5 0x09 /* 1001 */ -#define DIV31_POLY5 0x0a /* 1010 */ -#define POLY5_POLY5 0x0b /* 1011 */ -#define DIV3_PURE 0x0c /* 1100 */ -#define DIV3_PURE2 0x0d /* 1101 */ -#define DIV93_PURE 0x0e /* 1110 */ -#define DIV3_POLY5 0x0f /* 1111 */ - -#define DIV3_MASK 0x0c - -#define AUDC0 0x15 -#define AUDC1 0x16 -#define AUDF0 0x17 -#define AUDF1 0x18 -#define AUDV0 0x19 -#define AUDV1 0x1a - -/* the size (in entries) of the 4 polynomial tables */ -#define POLY4_SIZE 0x000f -#define POLY5_SIZE 0x001f -#define POLY9_SIZE 0x01ff - -/* channel definitions */ -#define CHAN1 0 -#define CHAN2 1 - -#define FALSE 0 -#define TRUE 1 - - -/* LOCAL GLOBAL VARIABLE DEFINITIONS */ - -/* structures to hold the 6 tia sound control bytes */ -static uint8 AUDC[2]; /* AUDCx (15, 16) */ -static uint8 AUDF[2]; /* AUDFx (17, 18) */ -static uint8 AUDV[2]; /* AUDVx (19, 1A) */ - -static uint8 Outvol[2]; /* last output volume for each channel */ - -static uint32 volume; /* output sample volume percentage */ - -/* Initialze the bit patterns for the polynomials. */ - -/* The 4bit and 5bit patterns are the identical ones used in the tia chip. */ -/* Though the patterns could be packed with 8 bits per byte, using only a */ -/* single bit per byte keeps the math simple, which is important for */ -/* efficient processing. */ - -static uint8 Bit4[POLY4_SIZE] = - { 1,1,0,1,1,1,0,0,0,0,1,0,1,0,0 }; - -static uint8 Bit5[POLY5_SIZE] = - { 0,0,1,0,1,1,0,0,1,1,1,1,1,0,0,0,1,1,0,1,1,1,0,1,0,1,0,0,0,0,1 }; - -/* I've treated the 'Div by 31' counter as another polynomial because of */ -/* the way it operates. It does not have a 50% duty cycle, but instead */ -/* has a 13:18 ratio (of course, 13+18 = 31). This could also be */ -/* implemented by using counters. */ - -static uint8 Div31[POLY5_SIZE] = - { 0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0 }; - -/* Rather than have a table with 511 entries, I use a random number */ -/* generator. */ - -static uint8 Bit9[POLY9_SIZE]; - -static uint8 P4[2]; /* Position pointer for the 4-bit POLY array */ -static uint8 P5[2]; /* Position pointer for the 5-bit POLY array */ -static uint16 P9[2]; /* Position pointer for the 9-bit POLY array */ - -static uint8 Div_n_cnt[2]; /* Divide by n counter. one for each channel */ -static uint8 Div_n_max[2]; /* Divide by n maximum, one for each channel */ - - -/* In my routines, I treat the sample output as another divide by N counter. */ -/* For better accuracy, the Samp_n_cnt has a fixed binary decimal point */ -/* which has 8 binary digits to the right of the decimal point. */ - -static uint16 Samp_n_max; /* Sample max, multiplied by 256 */ -static uint16 Samp_n_cnt; /* Sample cnt. */ - - - -/*****************************************************************************/ -/* Module: Tia_sound_init() */ -/* Purpose: to handle the power-up initialization functions */ -/* these functions should only be executed on a cold-restart */ -/* */ -/* Author: Ron Fries */ -/* Date: September 10, 1996 */ -/* */ -/* Inputs: sample_freq - the value for the '30 Khz' Tia audio clock */ -/* playback_freq - the playback frequency in samples per second */ -/* */ -/* Outputs: Adjusts local globals - no return value */ -/* */ -/*****************************************************************************/ - -void Tia_sound_init (uint16 sample_freq, uint16 playback_freq) -{ - uint8 chan; - int16 n; - - /* fill the 9bit polynomial with random bits */ - for (n=0; n 1) - { - /* decrement and loop */ - Div_n_cnt[chan]--; - } - /* otherwise if we've reached the bottom */ - else if (Div_n_cnt[chan] == 1) - { - /* reset the counter */ - Div_n_cnt[chan] = Div_n_max[chan]; - - /* the P5 counter has multiple uses, so we inc it here */ - P5[chan]++; - if (P5[chan] == POLY5_SIZE) - P5[chan] = 0; - - /* check clock modifier for clock tick */ - - /* if we're using pure tones OR - we're using DIV31 and the DIV31 bit is set OR - we're using POLY5 and the POLY5 bit is set */ - if (((AUDC[chan] & 0x02) == 0) || - (((AUDC[chan] & 0x01) == 0) && Div31[P5[chan]]) || - (((AUDC[chan] & 0x01) == 1) && Bit5[P5[chan]])) - { - if (AUDC[chan] & 0x04) /* pure modified clock selected */ - { - if (Outvol[chan]) /* if the output was set */ - Outvol[chan] = 0; /* turn it off */ - else - Outvol[chan] = AUDV[chan]; /* else turn it on */ - } - else if (AUDC[chan] & 0x08) /* check for p5/p9 */ - { - if (AUDC[chan] == POLY9) /* check for poly9 */ - { - /* inc the poly9 counter */ - P9[chan]++; - if (P9[chan] == POLY9_SIZE) - P9[chan] = 0; - - if (Bit9[P9[chan]]) /* if poly9 bit is set */ - Outvol[chan] = AUDV[chan]; - else - Outvol[chan] = 0; - } - else /* must be poly5 */ - { - if (Bit5[P5[chan]]) - Outvol[chan] = AUDV[chan]; - else - Outvol[chan] = 0; - } - } - else /* poly4 is the only remaining option */ - { - /* inc the poly4 counter */ - P4[chan]++; - if (P4[chan] == POLY4_SIZE) - P4[chan] = 0; - - if (Bit4[P4[chan]]) - Outvol[chan] = AUDV[chan]; - else - Outvol[chan] = 0; - } - } - } - } - - /* decrement the sample counter - value is 256 since the lower - byte contains the fractional part */ - Samp_n_cnt -= 256; - - /* if the count down has reached zero */ - if (Samp_n_cnt < 256) - { - /* adjust the sample counter */ - Samp_n_cnt += Samp_n_max; - - /* calculate the latest output value and place in buffer */ - *(buffer++) = Outvol[0] + Outvol[1]; - - /* and indicate one less byte to process */ - n--; - } - } -} - - -/*****************************************************************************/ -/* Module: Tia_process() */ -/* Purpose: To fill the output buffer with the sound output based on the */ -/* tia chip parameters. This routine has been optimized. */ -/* */ -/* Author: Ron Fries */ -/* Date: September 10, 1996 */ -/* */ -/* Inputs: *buffer - pointer to the buffer where the audio output will */ -/* be placed */ -/* n - size of the playback buffer */ -/* */ -/* Outputs: the buffer will be filled with n bytes of audio - no return val */ -/* */ -/*****************************************************************************/ - -void Tia_process (register unsigned char *buffer, register uint16 n) -{ - register uint8 audc0,audv0,audc1,audv1; - register uint8 div_n_cnt0,div_n_cnt1; - register uint8 p5_0, p5_1,outvol_0,outvol_1; - - audc0 = AUDC[0]; - audv0 = AUDV[0]; - audc1 = AUDC[1]; - audv1 = AUDV[1]; - - /* make temporary local copy */ - p5_0 = P5[0]; - p5_1 = P5[1]; - outvol_0 = Outvol[0]; - outvol_1 = Outvol[1]; - div_n_cnt0 = Div_n_cnt[0]; - div_n_cnt1 = Div_n_cnt[1]; - - /* loop until the buffer is filled */ - while (n) - { - /* Process channel 0 */ - if (div_n_cnt0 > 1) - { - div_n_cnt0--; - } - else if (div_n_cnt0 == 1) - { - div_n_cnt0 = Div_n_max[0]; - - /* the P5 counter has multiple uses, so we inc it here */ - p5_0++; - if (p5_0 == POLY5_SIZE) - p5_0 = 0; - - /* check clock modifier for clock tick */ - if (((audc0 & 0x02) == 0) || - (((audc0 & 0x01) == 0) && Div31[p5_0]) || - (((audc0 & 0x01) == 1) && Bit5[p5_0])) - { - if (audc0 & 0x04) /* pure modified clock selected */ - { - if (outvol_0) /* if the output was set */ - outvol_0 = 0; /* turn it off */ - else - outvol_0 = audv0; /* else turn it on */ - } - else if (audc0 & 0x08) /* check for p5/p9 */ - { - if (audc0 == POLY9) /* check for poly9 */ - { - /* inc the poly9 counter */ - P9[0]++; - if (P9[0] == POLY9_SIZE) - P9[0] = 0; - - if (Bit9[P9[0]]) - outvol_0 = audv0; - else - outvol_0 = 0; - } - else /* must be poly5 */ - { - if (Bit5[p5_0]) - outvol_0 = audv0; - else - outvol_0 = 0; - } - } - else /* poly4 is the only remaining option */ - { - /* inc the poly4 counter */ - P4[0]++; - if (P4[0] == POLY4_SIZE) - P4[0] = 0; - - if (Bit4[P4[0]]) - outvol_0 = audv0; - else - outvol_0 = 0; - } - } - } - - - /* Process channel 1 */ - if (div_n_cnt1 > 1) - { - div_n_cnt1--; - } - else if (div_n_cnt1 == 1) - { - div_n_cnt1 = Div_n_max[1]; - - /* the P5 counter has multiple uses, so we inc it here */ - p5_1++; - if (p5_1 == POLY5_SIZE) - p5_1 = 0; - - /* check clock modifier for clock tick */ - if (((audc1 & 0x02) == 0) || - (((audc1 & 0x01) == 0) && Div31[p5_1]) || - (((audc1 & 0x01) == 1) && Bit5[p5_1])) - { - if (audc1 & 0x04) /* pure modified clock selected */ - { - if (outvol_1) /* if the output was set */ - outvol_1 = 0; /* turn it off */ - else - outvol_1 = audv1; /* else turn it on */ - } - else if (audc1 & 0x08) /* check for p5/p9 */ - { - if (audc1 == POLY9) /* check for poly9 */ - { - /* inc the poly9 counter */ - P9[1]++; - if (P9[1] == POLY9_SIZE) - P9[1] = 0; - - if (Bit9[P9[1]]) - outvol_1 = audv1; - else - outvol_1 = 0; - } - else /* must be poly5 */ - { - if (Bit5[p5_1]) - outvol_1 = audv1; - else - outvol_1 = 0; - } - } - else /* poly4 is the only remaining option */ - { - /* inc the poly4 counter */ - P4[1]++; - if (P4[1] == POLY4_SIZE) - P4[1] = 0; - - if (Bit4[P4[1]]) - outvol_1 = audv1; - else - outvol_1 = 0; - } - } - } - - /* decrement the sample counter - value is 256 since the lower - byte contains the fractional part */ - Samp_n_cnt -= 256; - - /* if the count down has reached zero */ - if (Samp_n_cnt < 256) - { - /* adjust the sample counter */ - Samp_n_cnt += Samp_n_max; - - /* calculate the latest output value and place in buffer */ -#ifdef MAC_OSX - *(buffer++) = ((uint8) ((((uint32)outvol_0 + (uint32)outvol_1) * volume) / 100))/2 + 128; -#else - *(buffer++) = ((((uint32)outvol_0 + (uint32)outvol_1) * volume) / 100); -#endif - /* and indicate one less byte to process */ - n--; - } - } - - /* save for next round */ - P5[0] = p5_0; - P5[1] = p5_1; - Outvol[0] = outvol_0; - Outvol[1] = outvol_1; - Div_n_cnt[0] = div_n_cnt0; - Div_n_cnt[1] = div_n_cnt1; -} - - -/*****************************************************************************/ -/* Module: Tia_get_registers() */ -/* Purpose: Returns the 6 TIA sound registers for use in state */ -/* loading and saving. */ -/* */ -/* Author: Stephen Anthony */ -/* Date: October 31, 2002 */ -/* */ -/* Inputs: reg .. reg6 - pointers to the variables where the registers */ -/* will be placed */ -/* */ -/*****************************************************************************/ - -void Tia_get_registers (unsigned char *reg1, unsigned char *reg2, unsigned char *reg3, - unsigned char *reg4, unsigned char *reg5, unsigned char *reg6) -{ - *reg1 = AUDC[0]; - *reg2 = AUDC[1]; - *reg3 = AUDF[0]; - *reg4 = AUDF[1]; - *reg5 = AUDV[0]; - *reg6 = AUDV[1]; -} - - -/*****************************************************************************/ -/* Module: Tia_set_registers() */ -/* Purpose: Sets the 6 TIA sound registers for use in state */ -/* loading and saving. */ -/* */ -/* Author: Stephen Anthony */ -/* Date: October 31, 2002 */ -/* */ -/* Inputs: reg .. reg6 - the registers to be set */ -/* */ -/*****************************************************************************/ - -void Tia_set_registers (unsigned char reg1, unsigned char reg2, unsigned char reg3, - unsigned char reg4, unsigned char reg5, unsigned char reg6) -{ - AUDC[0] = reg1; - AUDC[1] = reg2; - AUDF[0] = reg3; - AUDF[1] = reg4; - AUDV[0] = reg5; - AUDV[1] = reg6; -} - - -/*****************************************************************************/ -/* Module: Tia_volume() */ -/* Purpose: Set volume to the specified percentage */ -/* */ -/* Author: Bradford W. Mott */ -/* Date: June 12, 2004 */ -/* */ -/*****************************************************************************/ -void Tia_volume (unsigned int percent) -{ - if((percent >= 0) && (percent <= 100)) - { - volume = percent; - } -} - -#ifdef __cplusplus -} -#endif diff --git a/stella/src/emucore/TIASound.h b/stella/src/emucore/TIASound.h deleted file mode 100644 index 13e8fc2d8..000000000 --- a/stella/src/emucore/TIASound.h +++ /dev/null @@ -1,61 +0,0 @@ -/*****************************************************************************/ -/* */ -/* Module: TIA Chip Sound Simulator Includes, V1.1 */ -/* Purpose: Define global function prototypes and structures for the TIA */ -/* Chip Sound Simulator. */ -/* Author: Ron Fries */ -/* */ -/* Revision History: */ -/* 10-Sep-96 - V1.0 - Initial Release */ -/* 14-Jan-97 - V1.1 - Added compiler directives to facilitate compilation */ -/* on a C++ compiler. */ -/* */ -/*****************************************************************************/ -/* */ -/* License Information and Copyright Notice */ -/* ======================================== */ -/* */ -/* TiaSound is Copyright(c) 1997 by Ron Fries */ -/* */ -/* This library is free software; you can redistribute it and/or modify it */ -/* under the terms of version 2 of the GNU Library General Public License */ -/* as published by the Free Software Foundation. */ -/* */ -/* This library is distributed in the hope that it will be useful, but */ -/* WITHOUT ANY WARRANTY; without even the implied warranty of */ -/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library */ -/* General Public License for more details. */ -/* To obtain a copy of the GNU Library General Public License, write to the */ -/* Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* */ -/* Any permitted reproduction of these routines, in whole or in part, must */ -/* bear this legend. */ -/* */ -/*****************************************************************************/ - -#ifndef _TIASOUND_H -#define _TIASOUND_H - -#ifdef __cplusplus -extern "C" { -#endif - -void Tia_sound_init (unsigned int sample_freq, unsigned int playback_freq); -void Update_tia_sound (unsigned int addr, unsigned char val); -void Tia_process_2 (register unsigned char *buffer, - register unsigned int n); -void Tia_process (register unsigned char *buffer, - register unsigned int n); - -void Tia_get_registers (unsigned char *reg1, unsigned char *reg2, unsigned char *reg3, - unsigned char *reg4, unsigned char *reg5, unsigned char *reg6); -void Tia_set_registers (unsigned char reg1, unsigned char reg2, unsigned char reg3, - unsigned char reg4, unsigned char reg5, unsigned char reg6); - -void Tia_volume (unsigned int percent); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/stella/src/emucore/TIASound.txt b/stella/src/emucore/TIASound.txt deleted file mode 100644 index 2819ef9ed..000000000 --- a/stella/src/emucore/TIASound.txt +++ /dev/null @@ -1,297 +0,0 @@ - TIASOUND.C - TIA SOUND EMULATION V1.0 - ===================================== - -As I'm sure you've already discovered, the Stella manual isn't always -correct. My observations show what I believe to be several discrepancies -in the description of the distortions. Of course, I could be wrong on a few -of these, so if some of the games don't sound right, please let me know -which ones. If possible, it would be best if you could send me a wave file -of what it is supposed to sound like, preferably at 44 KHz. Only a few -seconds should be necessary. - - -TIA AUDIO CIRCUITRY -=================== - - -THE HARDWARE ------------- - -In general, the sound hardware can be described as follows: - - -Selecting the Clock Modifier - Bits D0 and D1 ---------------------------------------------- - -Bits D0 and D1 select the output clock modifier: - - D1 D0 - ------- - 0 0 - direct clock (pure) - 0 1 - direct clock (pure) - 1 0 - divide by 31 - 1 1 - 5-bit polynomial - -The 'divide by 31' isn't simply the input clock divided by 31. It is, in -essence, a 5-bit polynomial with only two bits set. The resulting square -wave actually has a 13:18 ratio. This may be implemented in the hardware -as a pair of traps on a 5-bit counter. - - -Selecting the Source Pattern - Bits D2 and D3 ---------------------------------------------- - -Bits D2 and D3 select the source to be clocked: - - D3 D2 - ------- - 0 0 - 4-bit polynomial - 0 1 - pure (Q') - 1 0 - 5-bit polynomial - 1 1 - pure (Q') - -The 'pure' tones are generated by toggling the output. Whenever a clock -tick is received, the output will change states. I've used the notation Q' -to indicate the 'logical NOT of the last output'. Note that since the output -toggles, this can be thought of as a divide by 2 since the output frequency -will be half of the input frequency. This is only true for the pure tones. - - -Selecting the Source Clock - Bits D2 and D3 -------------------------------------------- - -When bits D2 and D3 are both set, it affects the source clock. I believe -the '30KHz' clock is actually the 3.58MHz clock divided by 114. When bits -D2 and D3 are set, the input source is switched to the 1.19MHz clock, so the -'30KHz' source clock is reduced to approximately 10KHz. - - -Exceptions - Selecting No Output or the 9-bit Polynomial --------------------------------------------------------- - -There are two exceptions that occur when bits D0-D2 are all 0. If AUDC is -zero (0000), then I believe the output is set equal to the volume. If AUDC is -equal to 8 (1000), the 9-bit polynomial is selected as the source to be -clocked. - - -Updated Detailed Functions for AUDC ------------------------------------ - -From my observations, I would describe the distortion selections as follows: - - HEX D3 D2 D1 D0 Clock Source Clock Modifier Source Pattern - --- ------------- -------------- ---------------- ---------------- - 0 0 0 0 0 3.58 MHz/114 -> none (pure) -> none - 1 0 0 0 1 3.58 MHz/114 -> none (pure) -> 4-bit poly - 2 0 0 1 0 3.58 MHz/114 -> divide by 31 -> 4-bit poly - 3 0 0 1 1 3.58 MHz/114 -> 5-bit poly -> 4-bit poly - 4 0 1 0 0 3.58 MHz/114 -> none (pure) -> pure (~Q) - 5 0 1 0 1 3.58 MHz/114 -> none (pure) -> pure (~Q) - 6 0 1 1 0 3.58 MHz/114 -> divide by 31 -> pure (~Q) - 7 0 1 1 1 3.58 MHz/114 -> 5-bit poly -> pure (~Q) - 8 1 0 0 0 3.58 MHz/114 -> none (pure) -> 9-bit poly - 9 1 0 0 1 3.58 MHz/114 -> none (pure) -> 5-bit poly - A 1 0 1 0 3.58 MHz/114 -> divide by 31 -> 5-bit poly - B 1 0 1 1 3.58 MHz/114 -> 5-bit poly -> 5-bit poly - C 1 1 0 0 1.19 MHz/114 -> none (pure) -> pure (~Q) - D 1 1 0 1 1.19 MHz/114 -> none (pure) -> pure (~Q) - E 1 1 1 0 1.19 MHz/114 -> divide by 31 -> pure (~Q) - F 1 1 1 1 1.19 MHz/114 -> 5-bit poly -> pure (~Q) - -For the most part, this follows the Stella manual, but there are a few -differences. Probably the most notable are hex entries 'A' and 'B', which -are listed in the Stella manual as 'div 31: pure tone' and 'set last 4 bits -to 1'. - -On entries 'A' and 'B', both the data source and the clock have the same -number of entries (31). Because of this, they will always align in the -same way. Entry 'A' will then reduce to a pure 'div by 31' output which -is identical to entry '6'. On 'B', both the source and the clock align -in such a way that the output will always be 1. - - - -THE POLYNOMIALS ---------------- - -The 4-bit, 5-bit, and 9-bit polynomials are essentially tables containing -a random series of bits (they are implemented in hardware as shift -registers). Because the tables are fixed in length, the 'random' pattern -will repeat periodically. - -The size of the table is described by its name. The actual size of the -table is 2^x - 1, where x is either the 4, 5 or 9. The 4-bit polynomial -has 15 entries, the 5-bit polynomial has 31 entries, and the 9-bit -polynomial has 511 entries. - -I've performed some analysis on the output of the actual Atari 2600, and -believe I have the actual 4-bit and 5-bit polynomials used by the Atari. -These have been encoded as byte arrays in my routines. For the 9-bit -polynomial, I use a random number generator which should produce -approximately the same results. - - -THE CLOCK ---------- - -I believe the input clock for the audio is a division of the main system -clock. With this assumption, I determined that the input clock for the -audio is equal to the 3.58MHz system clock divided by 114. Note that this -produces an actual audio clock of 31.4 KHz. This value closely matches the -frequencies I recorded from my unit. The Stella manual describes the Audio -Clock as approximately 30KHz, which I suppose is correct if you consider 5% -to be approximate. - -If both bits D2 and D3 of the AUDC register are set, I believe the TIA chip -uses the 1.19MHz clock for the base audio clock instead of the 3.58MHz. -This, of course, produces the 'divide by 3' functionality described in the -Stella manual. - - - -TIASOUND.C -========== - -The TIASOUND.C file is the heart of the TIA Sound Emulation program. -Although the routines in the file must work together, no other files are -modules are required for operation. A header file, 'TIASOUND.H', has -been included for use in other modules, and provides the necessary -function prototypes. I've attempted to make the routines as portable as -possible, so the file should compile on almost any compiler with little -or no modification. - -I have made some attempts at optimizing the routines, though I am sure -more optimization can be done. They are currently only available in 'C'. -I'll be happy to convert them to assembly language if desired. Please feel -free to send me e-mail (see below). - -The routines are easy to use. Detailed descriptions on the function calls -are listed below. - - -GENERAL OVERVIEW ----------------- - -On start-up of the system, a single call should be made to Tia_sound_init. -This routine will prepare the structures for sound output. This routine -can be called again if necessary during warm-start or other reset. - -Once in the main loop, there are two other functions that will be used. -Whenever the system needs to write to either the AUDC, AUDV or AUDF values, -a call should be made to the Update_tia_sound routine. This routine will -take care of updating the internal registers. It will pre-calculate several -values to help with optimization. - -The only other routine that is called is the Tia_process function. This -function will fill a audio buffer with a specified number of bytes. This -function should be called whenever a new audio buffer is required. - -For best results, I recommend using at least two output buffers. Using this -scheme, the sound card can be playing one buffer while the system is filling -the other. - - -DETAILED FUNCTION DESCRIPTIONS ------------------------------- - -Tia_sound_init(uint16 sample_freq, uint16 playback_freq) --------------------------------------------------------- - -This function initializes the structures used by the TiaSound.C routines. -This function takes two parameters: the sample frequency and the playback -frequency. The sample frequency is the frequency of the 30KHz source clock. -For my calculations, this clock is about 31.4 KHz, though any 16-bit -unsigned integer value can be used (1-65535). - -The playback frequency is the frequency of the sound playback (the frequency -used by the sound card). For best results, both the playback frequency and -the sample frequency should be identical. In the case where the sound card -cannot support 31.4 KHz (i.e. the original SB and many 'SB compatible' cards), -there are three options: - -1) Set the sample frequency to 31400 and the playback frequency to the - maximum possible (e.g. 22050). Though the system will reproduce all - output values, a significant amount of aliasing is introduced. - -2) Set the sample frequency and the playback frequency to the maximum possible - (e.g. 22050). In this case, all output values are reproduced with no - distortions; however, the pitch is about 2/3 of an octave low. - -3) Set the sample frequency to 31400 and the playback frequency to exactly - 1/2 of the sample frequency (15700). In this case, the output frequency - is correct and the aliasing is minimized. The aliasing is only - noticeable on the higher frequencies. Most notably, the highest pure tone - (AUDF = 0) is inaudible. - -Feel free to experiment to find other alternatives as well. - -This function has no return value (void). - - -Update_tia_sound (uint16 addr, uint8 val) ------------------------------------------ - -This function should be called each time an AUDC, AUDF or AUDV value -changes. This function takes two parameters: the address to change and -the new value. The address should be one of the following values: - - Addr Description - ---- ----------- - 0x15 AUDC0 - 0x16 AUDC1 - 0x17 AUDF0 - 0x18 AUDF1 - 0x19 AUDV0 - 0x1A AUDV1 - -Any values outside of this range will be ignored. - -The routine pre-calculates several values that are needed by the -processing function. This is done to optimize performance. - -This function has no return value (void). - - -Tia_process (unsigned char *buffer, uint16 n) ---------------------------------------------- - -This function calculates and fills a buffer with unsigned 8-bit mono audio. -This function takes two parameters: a pointer to the buffer to fill and -the size of the buffer (limited to 65535). This function fills the -buffer based on the requested size and returns. It automatically -updates the pointers for the next call, so subsequent calls to this function -will provide a continuous stream of data. - -The size of the buffer that is needed depends on the playback frequency. -It is best to keep the buffer as small as possible to maximize response time -to changes in the sound. Of course, the minimum size is dependent on -system and emulator performance. - -Selecting the correct buffer size is a careful balance. Selecting a buffer -size that is too small will produce noticeable clicks in the output, though -selecting a size that is too large will cause a poor response time and -possible delays in the system when the new buffer is filled. - -This function has no return value (void). - - -License Information and Copyright Notice -======================================== - -TiaSound is Copyright(c) 1996 by Ron Fries - -This library is free software; you can redistribute it and/or modify it under -the terms of version 2 of the GNU Library General Public License as published -by the Free Software Foundation. - -This library is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more -details. - -To obtain a copy of the GNU Library General Public License, write to the Free -Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -Any permitted reproduction of these routines, in whole or in part, must bear -this legend. diff --git a/stella/src/emucore/m6502/src/D6502.cxx b/stella/src/emucore/m6502/src/D6502.cxx deleted file mode 100644 index 9cac63592..000000000 --- a/stella/src/emucore/m6502/src/D6502.cxx +++ /dev/null @@ -1,187 +0,0 @@ -//============================================================================ -// -// MM MM 6666 555555 0000 2222 -// MMMM MMMM 66 66 55 00 00 22 22 -// MM MMM MM 66 55 00 00 22 -// MM M MM 66666 55555 00 00 22222 -- "A 6502 Microprocessor Emulator" -// MM MM 66 66 55 00 00 22 -// MM MM 66 66 55 55 00 00 22 -// MM MM 6666 5555 0000 222222 -// -// Copyright (c) 1995-1998 by Bradford W. Mott -// -// See the file "license" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -// -// $Id: D6502.cxx,v 1.1.1.1 2001-12-27 19:54:29 bwmott Exp $ -//============================================================================ - -#include -#include "D6502.hxx" -#include "M6502.hxx" -#include "System.hxx" - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -D6502::D6502(System* system) - : mySystem(system) -{ -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -D6502::~D6502() -{ -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -static uInt16 dpeek(System* system, uInt16 address) -{ - return (uInt16)system->peek(address) | - (((uInt16)system->peek(address + 1)) << 8); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 D6502::disassemble(uInt16 address, char* buffer) -{ - uInt8 opcode = mySystem->peek(address); - - switch(M6502::ourAddressingModeTable[opcode]) - { - case M6502::Absolute: - sprintf(buffer, "%s $%04X", M6502::ourInstructionMnemonicTable[opcode], - dpeek(mySystem, address + 1)); - return 3; - - case M6502::AbsoluteX: - sprintf(buffer, "%s $%04X,x", M6502::ourInstructionMnemonicTable[opcode], - dpeek(mySystem, address + 1)); - return 3; - - case M6502::AbsoluteY: - sprintf(buffer, "%s $%04X,y", M6502::ourInstructionMnemonicTable[opcode], - dpeek(mySystem, address + 1)); - return 3; - - case M6502::Immediate: - sprintf(buffer, "%s #$%02X", M6502::ourInstructionMnemonicTable[opcode], - mySystem->peek(address + 1)); - return 2; - - case M6502::Implied: - sprintf(buffer, "%s", M6502::ourInstructionMnemonicTable[opcode]); - return 1; - - case M6502::Indirect: - sprintf(buffer, "%s ($%04X)", M6502::ourInstructionMnemonicTable[opcode], - dpeek(mySystem, address + 1)); - return 3; - - case M6502::IndirectX: - sprintf(buffer, "%s ($%02X,x)", - M6502::ourInstructionMnemonicTable[opcode], - mySystem->peek(address + 1)); - return 2; - - case M6502::IndirectY: - sprintf(buffer, "%s ($%02X),y", - M6502::ourInstructionMnemonicTable[opcode], - mySystem->peek(address + 1)); - return 2; - - case M6502::Relative: - sprintf(buffer, "%s $%04X", M6502::ourInstructionMnemonicTable[opcode], - address + 2 + ((Int16)(Int8)mySystem->peek(address + 1))); - return 2; - - case M6502::Zero: - sprintf(buffer, "%s $%02X", M6502::ourInstructionMnemonicTable[opcode], - mySystem->peek(address + 1)); - return 2; - - case M6502::ZeroX: - sprintf(buffer, "%s $%02X,x", M6502::ourInstructionMnemonicTable[opcode], - mySystem->peek(address + 1)); - return 2; - - case M6502::ZeroY: - sprintf(buffer, "%s $%02X,y", M6502::ourInstructionMnemonicTable[opcode], - mySystem->peek(address + 1)); - return 2; - - default: - sprintf(buffer, "dc $%02X", opcode); - return 1; - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt8 D6502::a() -{ - return mySystem->m6502().A; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void D6502::a(uInt8 value) -{ - mySystem->m6502().A = value; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt16 D6502::pc() -{ - return mySystem->m6502().PC; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void D6502::pc(uInt16 value) -{ - mySystem->m6502().PC = value; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt8 D6502::ps() -{ - return mySystem->m6502().PS(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void D6502::ps(uInt8 value) -{ - mySystem->m6502().PS(value); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt8 D6502::sp() -{ - return mySystem->m6502().SP; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void D6502::sp(uInt8 value) -{ - mySystem->m6502().SP = value; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt8 D6502::x() -{ - return mySystem->m6502().X; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void D6502::x(uInt8 value) -{ - mySystem->m6502().X = value; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -uInt8 D6502::y() -{ - return mySystem->m6502().Y; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void D6502::y(uInt8 value) -{ - mySystem->m6502().Y = value; -} - diff --git a/stella/src/emucore/m6502/src/D6502.hxx b/stella/src/emucore/m6502/src/D6502.hxx deleted file mode 100644 index 8fb6aa8f1..000000000 --- a/stella/src/emucore/m6502/src/D6502.hxx +++ /dev/null @@ -1,152 +0,0 @@ -//============================================================================ -// -// MM MM 6666 555555 0000 2222 -// MMMM MMMM 66 66 55 00 00 22 22 -// MM MMM MM 66 55 00 00 22 -// MM M MM 66666 55555 00 00 22222 -- "A 6502 Microprocessor Emulator" -// MM MM 66 66 55 00 00 22 -// MM MM 66 66 55 55 00 00 22 -// MM MM 6666 5555 0000 222222 -// -// Copyright (c) 1995-1998 by Bradford W. Mott -// -// See the file "license" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -// -// $Id: D6502.hxx,v 1.1.1.1 2001-12-27 19:54:29 bwmott Exp $ -//============================================================================ - -#ifndef D6502_HXX -#define D6502_HXX - -class D6502; -class M6502; -class System; - -#include "bspf.hxx" - -/** - This is a base class for 6502 debuggers. This class provides the - basic functionality needed for interactive debuggers. - - @author Bradford W. Mott - @version $Id: D6502.hxx,v 1.1.1.1 2001-12-27 19:54:29 bwmott Exp $ -*/ -class D6502 -{ - public: - /** - Create a new 6502 debugger for the specified system - - @param system The system the debugger should operate on - */ - D6502(System* system); - - /** - Destructor - */ - virtual ~D6502(); - - public: - /** - Disassemble a single instruction at the specified address into - the given buffer and answer the number of bytes disassembled. - The buffer should be at least 20 characters long. - - @param address The address to disassemble code at - @param buffer The buffer where the ASCII disassemble should be stored - @return The number of bytes disassembled - */ - uInt16 disassemble(uInt16 address, char* buffer); - - public: - /** - Get the value of the accumulator - - @return The accumulator's value - */ - uInt8 a(); - - /** - Change value of the accumulator - - @param value The value to set the accumulator to - */ - void a(uInt8 value); - - /** - Get value of the program counter - - @return The program counter's value - */ - uInt16 pc(); - - /** - Change value of the program counter - - @param value The value to set the program counter to - */ - void pc(uInt16 value); - - /** - Get the value of the processor status register - - @return The processor status register's value - */ - uInt8 ps(); - - /** - Change value of the processor status register - - @param value The value to set the processor status register to - */ - void ps(uInt8 value); - - /** - Get the value of the stack pointer - - @return The stack pointer's value - */ - uInt8 sp(); - - /** - Change value of the stack pointer - - @param value The value to set the stack pointer to - */ - void sp(uInt8 value); - - /** - Get the value of the X index register - - @return The X register's value - */ - uInt8 x(); - - /** - Change value of the X index register - - @param value The value to set the X register to - */ - void x(uInt8 value); - - /** - Get the value of the Y index register - - @return The Y register's value - */ - uInt8 y(); - - /** - Change value of the Y index register - - @param value The value to set the Y register to - */ - void y(uInt8 value); - - protected: - // Pointer to the system I'm debugging - System* mySystem; -}; -#endif - diff --git a/stella/src/macosx/.DS_Store b/stella/src/macosx/.DS_Store deleted file mode 100644 index e16232a0cd4ce3f59325f97a25eae85a7fb25ace..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12292 zcmeHLOKuZE5Pcnj2sjof8?ph-2@tH<8pl~6VSyBc*oF8%Xfk8rG0rZ&4M*V+9D*aj ztL_%+`Pp6}gsZLY8qL(}s(RHu<7xn=yBxg$P5~UTi+t4LP}AhO^h!JMcb-xj;(;7p zWVpdI%qrS?Lm5y8lmTTx8BhlP1qS%dmUh(e-FHuQR0foRy<|Y%4-vb_j+bjE?W==> zEdeMGdD}K#vktJB$jgqGYbPy~bGqumc&PCuhH-E{k3^la-J?>zrRkh;ULKdd@ft+lKt^7+jv!vxh`VNlM?2* z#!iYDgA(pX33pP#y~miR3^_g!J;qAT8;WySe=h@ncbTKk|8S1GWNAr@2}VV0Mm%oN zoUG#K0gqG!;$iyLzEy!>&dF-AO0slHg)i*ElX$q8`#Hjcm}8t#bBqyv%CWGgE;+7| z6uq-td<(c};~Xibj3Xv$MqGk9XUg!oh_o5p5jk26lR=gx65j>`4WYE?_7&Ypae*G* z(4`?0d{c5qX#N=lau0ompE4;n_@cIiZC*BN*Ce~3-Nrjh?t~VE+DGKcSM$K zS`Tjn5AXZv`<{!+vX+FH&4`i>>s^RwRczQTxMi6(q6$m4L8~F>C-h{@g`3;FPswec z8~qG#dH-Yc3NYUT#av=9!q9H+G9IOU)Jsl1M;DwvL!YbSY!?e8B1==Z;_n6Syv kK^ag6lmTTx8Bhk40cAiLPzIC%Wk4BF29yD1;J;zuH$Z>5djJ3c diff --git a/stella/src/macosx/English.lproj/.DS_Store b/stella/src/macosx/English.lproj/.DS_Store deleted file mode 100644 index c0482546f324c6150c0e0bf7cb4b3da9ce99c9fd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeH~u}T9$5QhKJ6akx9X}M1z_y$XeMLNL;P@*WpkprXsb$RUg&&(MT|=49@psbj2&KaG0FZu;I*e%V~a=h zqk7-vg}ZI>gx$L9?>Ak)VYdI&Tl(1{j5C=Ch=2%)fCz}d?+JMCrOi)LHHv@;h`=WS z|2`DDYi&BD#;1crTmh&vhQm0Iy9Bj(fLfalsf^GpOQ~6E?TTSp&Uk5gwds(W<*+!J z`?Qm--B2t}XS_r@tfp!d0TCDzIL_t5`~MaFhx`AyNGlN#fqzB7W~-aklCRWy>*VFU v*B1I6{ll0W=^UaJQ==7g;jQ@mOJ4CgpVy{CYLqh`N1q*# diff --git a/stella/src/macosx/SDLMain.nib/.DS_Store b/stella/src/macosx/SDLMain.nib/.DS_Store deleted file mode 100644 index 803d86d12b92cbce69d825abf053dd9f43035dd0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeH~!Ab)$5Qb;8hr(WZ(~FQN5PXBB)PrXqK;2cLvbcxpJ@4tm=>N}*#jbl45t)JH zPm`Hs^Ffo0i0JzD{z7CWB1;sivN2=qo*g<0=VPea96NcCot(?FY-c9=i(UNoMtT|K z4qyKD`@5@Q?7Ly?;6Xe$C@1e`Xc5U4`+Sr!_B-*{vx$EL&rY5|sF#;LrD@dLB#JAg zC4nT61d>1!_(=k|vuVr5HR~jh1d_m>0MCblLTy8p>1e& z#RyD26zZWGDTaDD`b+q=q1DyHMI-spSot$~QCl7J7jqYFU9(OCN#KwGb6?ns_x~mS zGP6m(xnz|DlE8l@po`7*W{us&-TG~xylV@}Eeef(l?@o$2af>!;5l+?gFar^hF=?6 UT{#Q;EgYH;0Rxg%68HrIA40x0s{jB1 diff --git a/stella/src/macosx/build/.DS_Store b/stella/src/macosx/build/.DS_Store deleted file mode 100644 index 5008ddfcf53c02e82d7eee2e57c38e5672ef89f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0 -#include -#include -#include -#include - -#ifdef HAVE_GETTIMEOFDAY - #include - #include -#endif - -#include - -#include "bspf.hxx" -#include "Console.hxx" -#include "Event.hxx" -#include "StellaEvent.hxx" -#include "EventHandler.hxx" -#include "FrameBuffer.hxx" -#include "FrameBufferSDL.hxx" -#include "FrameBufferSoft.hxx" -#include "PropsSet.hxx" -#include "Sound.hxx" -#include "SoundSDL.hxx" -#include "Settings.hxx" - -#ifdef DISPLAY_OPENGL - #include "FrameBufferGL.hxx" - - // Indicates whether to use OpenGL mode - static bool theUseOpenGLFlag; -#endif - -#include "SettingsMACOSX.hxx" - -extern "C" { -int stellaMain(int argc, char* argv[]); -void setPaddleMode(int mode); -void setLeftJoystickMode(int mode); -void setRightJoystickMode(int mode); -void getPrefsSettings(int *gl, int *volume, float *aspect); -void setPrefsSettings(int gl, int volume, float aspect); -char *browseFile(void); -void prefsStart(void); -void hideApp(void); -void showHelp(void); -void miniturizeWindow(void); -void centerAppWindow(void); -void setPaddleMenu(int number); -void setSpeedLimitMenu(int number); -void initVideoMenu(bool theUseOpenGLFlag); -void enableGameMenus(void); -void AboutBoxScroll(void); -} - -static void cleanup(); -static bool setupJoystick(); -static void handleEvents(); -static bool handleInitialEvents(); -static bool setupProperties(PropertiesSet& set); -static double Atari_time(void); - -#ifdef JOYSTICK_SUPPORT -// static uInt32 thePaddleNumber; - - // Lookup table for joystick numbers and events - StellaEvent::JoyStick joyList[StellaEvent::LastJSTICK] = { - StellaEvent::JSTICK_0, StellaEvent::JSTICK_1, StellaEvent::JSTICK_2, - StellaEvent::JSTICK_3, StellaEvent::JSTICK_5, StellaEvent::JSTICK_5 - }; - StellaEvent::JoyCode joyButtonList[StellaEvent::LastJCODE] = { - StellaEvent::JBUTTON_0, StellaEvent::JBUTTON_1, StellaEvent::JBUTTON_2, - StellaEvent::JBUTTON_3, StellaEvent::JBUTTON_4, StellaEvent::JBUTTON_5, - StellaEvent::JBUTTON_6, StellaEvent::JBUTTON_7, StellaEvent::JBUTTON_8, - StellaEvent::JBUTTON_9, StellaEvent::JBUTTON_10, StellaEvent::JBUTTON_11, - StellaEvent::JBUTTON_12, StellaEvent::JBUTTON_13, StellaEvent::JBUTTON_14, - StellaEvent::JBUTTON_15, StellaEvent::JBUTTON_16, StellaEvent::JBUTTON_17, - StellaEvent::JBUTTON_18, StellaEvent::JBUTTON_19 - }; - - enum JoyType { JT_NONE, JT_REGULAR, JT_STELLADAPTOR_1, JT_STELLADAPTOR_2 }; - - struct Stella_Joystick - { - SDL_Joystick* stick; - JoyType type; - }; - - static Stella_Joystick theJoysticks[StellaEvent::LastJSTICK]; - - // Static lookup tables for Stelladaptor axis support - static Event::Type SA_Axis[2][2][3] = { - Event::JoystickZeroLeft, Event::JoystickZeroRight, Event::PaddleZeroResistance, - Event::JoystickZeroUp, Event::JoystickZeroDown, Event::PaddleOneResistance, - Event::JoystickOneLeft, Event::JoystickOneRight, Event::PaddleTwoResistance, - Event::JoystickOneUp, Event::JoystickOneDown, Event::PaddleThreeResistance - }; - static Event::Type SA_DrivingValue[2] = { - Event::DrivingZeroValue, Event::DrivingOneValue - }; -#endif - -// Pointer to the console object or the null pointer -static Console* theConsole = (Console*) NULL; - -// Pointer to the display object or the null pointer -static FrameBufferSDL* theDisplay = (FrameBufferSDL*) NULL; - -// Pointer to the sound object or the null pointer -static Sound* theSound = (Sound*) NULL; - -// Pointer to the settings object or the null pointer -static Settings* theSettings = (Settings*) NULL; - -// Indicates if the mouse should be grabbed -static bool theGrabMouseIndicator = false; - -// Indicates if the mouse cursor should be hidden -static bool theHideCursorIndicator = false; - -// Indicates the current paddle mode -static Int32 thePaddleMode; - -// Indicates relative mouse position horizontally -static Int32 mouseX = 0; - -// Indicates whether to show information during program execution -static bool theShowInfoFlag; - -// Indicates user wants to play a new game, not quit -static bool newGame; - -// Indicates the time per frame, which is the inverse of the framerate -static double timePerFrame; - -// Pointer to hold the name of the next game to play -static char *gameFile; - -static bool fileToLoad = false; - - -struct Switches -{ - SDLKey scanCode; - StellaEvent::KeyCode keyCode; -}; - -// Place the most used keys first to speed up access -// Todo - initialize this array in the same order as the SDLK -// keys are defined, so it can be a constant-time LUT -static Switches keyList[] = { - { SDLK_F1, StellaEvent::KCODE_F1 }, - { SDLK_F2, StellaEvent::KCODE_F2 }, - { SDLK_F3, StellaEvent::KCODE_F3 }, - { SDLK_F4, StellaEvent::KCODE_F4 }, - { SDLK_F5, StellaEvent::KCODE_F5 }, - { SDLK_F6, StellaEvent::KCODE_F6 }, - { SDLK_F7, StellaEvent::KCODE_F7 }, - { SDLK_F8, StellaEvent::KCODE_F8 }, - { SDLK_F9, StellaEvent::KCODE_F9 }, - { SDLK_F10, StellaEvent::KCODE_F10 }, - { SDLK_F11, StellaEvent::KCODE_F11 }, - { SDLK_F12, StellaEvent::KCODE_F12 }, - { SDLK_F13, StellaEvent::KCODE_F13 }, - { SDLK_F14, StellaEvent::KCODE_F14 }, - { SDLK_F15, StellaEvent::KCODE_F15 }, - - { SDLK_UP, StellaEvent::KCODE_UP }, - { SDLK_DOWN, StellaEvent::KCODE_DOWN }, - { SDLK_LEFT, StellaEvent::KCODE_LEFT }, - { SDLK_RIGHT, StellaEvent::KCODE_RIGHT }, - { SDLK_SPACE, StellaEvent::KCODE_SPACE }, - { SDLK_LCTRL, StellaEvent::KCODE_LCTRL }, - { SDLK_RCTRL, StellaEvent::KCODE_RCTRL }, - { SDLK_LALT, StellaEvent::KCODE_LALT }, - { SDLK_RALT, StellaEvent::KCODE_RALT }, - { SDLK_LSUPER, StellaEvent::KCODE_LWIN }, - { SDLK_RSUPER, StellaEvent::KCODE_RWIN }, - { SDLK_MENU, StellaEvent::KCODE_MENU }, - - { SDLK_a, StellaEvent::KCODE_a }, - { SDLK_b, StellaEvent::KCODE_b }, - { SDLK_c, StellaEvent::KCODE_c }, - { SDLK_d, StellaEvent::KCODE_d }, - { SDLK_e, StellaEvent::KCODE_e }, - { SDLK_f, StellaEvent::KCODE_f }, - { SDLK_g, StellaEvent::KCODE_g }, - { SDLK_h, StellaEvent::KCODE_h }, - { SDLK_i, StellaEvent::KCODE_i }, - { SDLK_j, StellaEvent::KCODE_j }, - { SDLK_k, StellaEvent::KCODE_k }, - { SDLK_l, StellaEvent::KCODE_l }, - { SDLK_m, StellaEvent::KCODE_m }, - { SDLK_n, StellaEvent::KCODE_n }, - { SDLK_o, StellaEvent::KCODE_o }, - { SDLK_p, StellaEvent::KCODE_p }, - { SDLK_q, StellaEvent::KCODE_q }, - { SDLK_r, StellaEvent::KCODE_r }, - { SDLK_s, StellaEvent::KCODE_s }, - { SDLK_t, StellaEvent::KCODE_t }, - { SDLK_u, StellaEvent::KCODE_u }, - { SDLK_v, StellaEvent::KCODE_v }, - { SDLK_w, StellaEvent::KCODE_w }, - { SDLK_x, StellaEvent::KCODE_x }, - { SDLK_y, StellaEvent::KCODE_y }, - { SDLK_z, StellaEvent::KCODE_z }, - - { SDLK_0, StellaEvent::KCODE_0 }, - { SDLK_1, StellaEvent::KCODE_1 }, - { SDLK_2, StellaEvent::KCODE_2 }, - { SDLK_3, StellaEvent::KCODE_3 }, - { SDLK_4, StellaEvent::KCODE_4 }, - { SDLK_5, StellaEvent::KCODE_5 }, - { SDLK_6, StellaEvent::KCODE_6 }, - { SDLK_7, StellaEvent::KCODE_7 }, - { SDLK_8, StellaEvent::KCODE_8 }, - { SDLK_9, StellaEvent::KCODE_9 }, - - { SDLK_KP0, StellaEvent::KCODE_KP0 }, - { SDLK_KP1, StellaEvent::KCODE_KP1 }, - { SDLK_KP2, StellaEvent::KCODE_KP2 }, - { SDLK_KP3, StellaEvent::KCODE_KP3 }, - { SDLK_KP4, StellaEvent::KCODE_KP4 }, - { SDLK_KP5, StellaEvent::KCODE_KP5 }, - { SDLK_KP6, StellaEvent::KCODE_KP6 }, - { SDLK_KP7, StellaEvent::KCODE_KP7 }, - { SDLK_KP8, StellaEvent::KCODE_KP8 }, - { SDLK_KP9, StellaEvent::KCODE_KP9 }, - { SDLK_KP_PERIOD, StellaEvent::KCODE_KP_PERIOD }, - { SDLK_KP_DIVIDE, StellaEvent::KCODE_KP_DIVIDE }, - { SDLK_KP_MULTIPLY, StellaEvent::KCODE_KP_MULTIPLY}, - { SDLK_KP_MINUS, StellaEvent::KCODE_KP_MINUS }, - { SDLK_KP_PLUS, StellaEvent::KCODE_KP_PLUS }, - { SDLK_KP_ENTER, StellaEvent::KCODE_KP_ENTER }, - { SDLK_KP_EQUALS, StellaEvent::KCODE_KP_EQUALS }, - - { SDLK_BACKSPACE, StellaEvent::KCODE_BACKSPACE }, - { SDLK_TAB, StellaEvent::KCODE_TAB }, - { SDLK_CLEAR, StellaEvent::KCODE_CLEAR }, - { SDLK_RETURN, StellaEvent::KCODE_RETURN }, - { SDLK_ESCAPE, StellaEvent::KCODE_ESCAPE }, - { SDLK_COMMA, StellaEvent::KCODE_COMMA }, - { SDLK_MINUS, StellaEvent::KCODE_MINUS }, - { SDLK_PERIOD, StellaEvent::KCODE_PERIOD }, - { SDLK_SLASH, StellaEvent::KCODE_SLASH }, - { SDLK_BACKSLASH, StellaEvent::KCODE_BACKSLASH }, - { SDLK_SEMICOLON, StellaEvent::KCODE_SEMICOLON }, - { SDLK_EQUALS, StellaEvent::KCODE_EQUALS }, - { SDLK_QUOTE, StellaEvent::KCODE_QUOTE }, - { SDLK_BACKQUOTE, StellaEvent::KCODE_BACKQUOTE }, - { SDLK_LEFTBRACKET, StellaEvent::KCODE_LEFTBRACKET}, - { SDLK_RIGHTBRACKET,StellaEvent::KCODE_RIGHTBRACKET}, - - { SDLK_PRINT, StellaEvent::KCODE_PRTSCREEN }, - { SDLK_MODE, StellaEvent::KCODE_SCRLOCK }, - { SDLK_PAUSE, StellaEvent::KCODE_PAUSE }, - { SDLK_INSERT, StellaEvent::KCODE_INSERT }, - { SDLK_HOME, StellaEvent::KCODE_HOME }, - { SDLK_PAGEUP, StellaEvent::KCODE_PAGEUP }, - { SDLK_DELETE, StellaEvent::KCODE_DELETE }, - { SDLK_END, StellaEvent::KCODE_END }, - { SDLK_PAGEDOWN, StellaEvent::KCODE_PAGEDOWN } - }; - -void setPaddleMode(int mode) -{ - thePaddleMode = mode; - theSettings->setInt("paddle",thePaddleMode); -} - -void getPrefsSettings(int *gl, int *volume, float *aspect) -{ - if (theSettings->getString("video") == "gl") - *gl = 1; - else - *gl = 0; - - *volume = theSettings->getInt("volume"); - if (*volume == -1) - *volume = 100; - - *aspect = theSettings->getFloat("gl_aspect"); -} - -void setPrefsSettings(int gl, int volume, float aspect) -{ - if (gl) - theSettings->setString("video","gl"); - else - theSettings->setString("video","soft"); - - theSettings->setInt("volume",volume); - theSound->setVolume(volume); - - theSettings->setFloat("gl_aspect",aspect); -} - -/** - This routine should be called once setupDisplay is called - to create the joystick stuff. -*/ -bool setupJoystick() -{ -#ifdef JOYSTICK_SUPPORT - // Keep track of how many Stelladaptors we've found - uInt8 saCount = 0; - - // First clear the joystick array - for(uInt32 i = 0; i < StellaEvent::LastJSTICK; i++) - { - theJoysticks[i].stick = (SDL_Joystick*) NULL; - theJoysticks[i].type = JT_NONE; - } - - // Initialize the joystick subsystem - if((SDL_InitSubSystem(SDL_INIT_JOYSTICK) == -1) || (SDL_NumJoysticks() <= 0)) - { - if(theShowInfoFlag) - cout << "No joysticks present, use the keyboard.\n"; - - return true; - } - - // Try to open 4 regular joysticks and 2 Stelladaptor devices - uInt32 limit = SDL_NumJoysticks() <= StellaEvent::LastJSTICK ? - SDL_NumJoysticks() : StellaEvent::LastJSTICK; - for(uInt32 i = 0; i < limit; i++) - { - string name = SDL_JoystickName(i); - theJoysticks[i].stick = SDL_JoystickOpen(i); - - // Skip if we couldn't open it for any reason - if(theJoysticks[i].stick == NULL) - continue; - - // Figure out what type of joystick this is - if(name.find("Stelladaptor", 0) != string::npos) - { - saCount++; - if(saCount > 2) // Ignore more than 2 Stelladaptors - { - theJoysticks[i].type = JT_NONE; - continue; - } - else if(saCount == 1) - { - name = "Left Stelladaptor (Left joystick, Paddles 0 and 1, Left driving controller)"; - theJoysticks[i].type = JT_STELLADAPTOR_1; - } - else if(saCount == 2) - { - name = "Right Stelladaptor (Right joystick, Paddles 2 and 3, Right driving controller)"; - theJoysticks[i].type = JT_STELLADAPTOR_2; - } - - if(theShowInfoFlag) - cout << "Joystick " << i << ": " << name << endl; - } - else - { - theJoysticks[i].type = JT_REGULAR; - if(theShowInfoFlag) - { - cout << "Joystick " << i << ": " << SDL_JoystickName(i) - << " with " << SDL_JoystickNumButtons(theJoysticks[i].stick) - << " buttons.\n"; - } - } - } -#endif - - return true; -} - -/** - This routine is called to handle events if user cancels initial open panel -*/ -bool handleInitialEvents(void) -{ - SDL_Event event; - SDLKey key; - SDLMod mod; - bool status; - - // Check for an event - while(1) - { - while(SDL_PollEvent(&event)) - { - // keyboard events - if(event.type == SDL_KEYDOWN) - { - key = event.key.keysym.sym; - mod = event.key.keysym.mod; - - if((mod & KMOD_META) && !(mod & KMOD_SHIFT)) - { - if(key == SDLK_q) // Command-q quits - { - return(false); - } - else if(key == SDLK_o) // Command-o starts a new game - { - return(true); - } - } - } - else if(event.type == SDL_QUIT) - { - return(false); - } - } - AboutBoxScroll(); - usleep(16667); - } - return status; -} - -/** - This routine should be called regularly to handle events -*/ -void handleEvents() -{ - SDL_Event event; - Uint8 type; - SDLKey key; - SDLMod mod; - - // Check for an event - while(SDL_PollEvent(&event)) - { - // keyboard events - if(event.type == SDL_KEYDOWN) - { - key = event.key.keysym.sym; - mod = event.key.keysym.mod; - type = event.type; - - // An attempt to speed up event processing - // All SDL-specific event actions are accessed by either - // Control or Alt keys. So we quickly check for those. - if((mod & KMOD_META) && (mod & KMOD_SHIFT)) - { - if(key == SDLK_p) // Shift-Command-p toggles different palettes - { - theConsole->togglePalette(); - theDisplay->setupPalette(); - } - else if(key == SDLK_f) // Command-f toggles NTSC/PAL mode - { - theConsole->toggleFormat(); - theDisplay->setupPalette(); - } -#ifdef DEVELOPER_SUPPORT - else if(key == SDLK_END) // Command-Shift-End increases Width - { - theConsole->changeWidth(1); - theDisplay->resize(0); - } - else if(key == SDLK_HOME) // Command-Shift-Home decreases Width - { - theConsole->changeWidth(0); - theDisplay->resize(0); - } - else if(key == SDLK_PAGEUP) // Command-Shift-PageUp increases Height - { - theConsole->changeHeight(1); - theDisplay->resize(0); - } - else if(key == SDLK_PAGEDOWN) // Command-Shift-PageDown decreases Height - { - theConsole->changeHeight(0); - theDisplay->resize(0); - } -#endif - } - else if((mod & KMOD_META) && !(mod & KMOD_SHIFT)) - { - if(key == SDLK_EQUALS) { - theDisplay->resize(1); - centerAppWindow(); - } - else if(key == SDLK_MINUS) { - theDisplay->resize(-1); - centerAppWindow(); - } - else if(key == SDLK_RETURN) - { - theDisplay->toggleFullscreen(); - centerAppWindow(); - } - else if(key == SDLK_q) // Command-q quits - { - newGame = false; - theConsole->eventHandler().sendEvent(Event::Quit, 1); - } - else if(key == SDLK_o) // Command-o starts a new game - { - char *file; - bool wasFullscreen; - - wasFullscreen = theDisplay->fullScreen(); - if (wasFullscreen) { - theDisplay->toggleFullscreen(); - centerAppWindow(); - } - theDisplay->grabMouse(false); - theDisplay->showCursor(true); - file = browseFile(); - if (file) - { - newGame = true; - fileToLoad = true; - gameFile = file; - if (wasFullscreen) { - theDisplay->toggleFullscreen(); - centerAppWindow(); - } - theConsole->eventHandler().sendEvent(Event::Quit, 1); - } - } - else if(key == SDLK_g) - { - // don't change grabmouse in fullscreen mode - if(!theDisplay->fullScreen()) - { - theGrabMouseIndicator = !theGrabMouseIndicator; - theSettings->setBool("grabmouse", theGrabMouseIndicator); - theDisplay->grabMouse(theGrabMouseIndicator); - theHideCursorIndicator = !theHideCursorIndicator; - theSettings->setBool("hidecursor", theHideCursorIndicator); - theDisplay->showCursor(!theHideCursorIndicator); - } - } -#ifdef DISPLAY_OPENGL - else if(key == SDLK_f && theUseOpenGLFlag) - ((FrameBufferGL*)theDisplay)->toggleFilter(); -#endif - else if(key == SDLK_l) // Command-l toggles frame limit - { - if (theSettings->getInt("framerate") != 10000000) - { - theSettings->setInt("framerate",10000000); - timePerFrame = 1.0 / 10000000.0; - setSpeedLimitMenu(0); - } - else - { - theSettings->setInt("framerate",60); - timePerFrame = 1.0 / 60.0; - setSpeedLimitMenu(1); - } - } - else if(key == SDLK_p) // Command-p toggles pause mode - { - theConsole->eventHandler().sendEvent(Event::Pause, 1); - } - else if(key == SDLK_h) // Command-h hides the application - { - if(!theDisplay->fullScreen()) - hideApp(); - } - else if(key == SDLK_m) // Command-m minimizes the window - { - if(!theDisplay->fullScreen()) - miniturizeWindow(); - } - else if(key == SDLK_COMMA) // Command-, runs the preferences pane. - { - if(!theDisplay->fullScreen()) - prefsStart(); - } - else if(key == SDLK_SLASH) // Command-? runs the help. - { - if(!theDisplay->fullScreen()) - showHelp(); - } - else if (key == SDLK_0) // Command-0 sets the mouse to paddle 0 - { - setPaddleMode(0); - setPaddleMenu(0); - } - else if (key == SDLK_1) // Command-0 sets the mouse to paddle 1 - { - setPaddleMode(1); - setPaddleMenu(1); - } - else if (key == SDLK_2) // Command-0 sets the mouse to paddle 2 - { - setPaddleMode(2); - setPaddleMenu(2); - } - else if (key == SDLK_3) // Command-0 sets the mouse to paddle 3 - { - setPaddleMode(3); - setPaddleMenu(3); - } -#ifdef DEVELOPER_SUPPORT - else if(key == SDLK_END) // Alt-End increases XStart - { - theConsole->changeXStart(1); - theDisplay->resize(0); - } - else if(key == SDLK_HOME) // Alt-Home decreases XStart - { - theConsole->changeXStart(0); - theDisplay->resize(0); - } - else if(key == SDLK_PAGEUP) // Alt-PageUp increases YStart - { - theConsole->changeYStart(1); - theDisplay->resize(0); - } - else if(key == SDLK_PAGEDOWN) // Alt-PageDown decreases YStart - { - theConsole->changeYStart(0); - theDisplay->resize(0); - } -#endif - } - else // check all the other keys - { - for(unsigned int i = 0; i < sizeof(keyList) / sizeof(Switches); ++i) - { - if(keyList[i].scanCode == key) - theConsole->eventHandler().sendKeyEvent(keyList[i].keyCode, 1); - } - } - } - else if(event.type == SDL_KEYUP) - { - key = event.key.keysym.sym; - type = event.type; - - for(unsigned int i = 0; i < sizeof(keyList) / sizeof(Switches); ++i) - { - if(keyList[i].scanCode == key) - theConsole->eventHandler().sendKeyEvent(keyList[i].keyCode, 0); - } - } - else if(event.type == SDL_MOUSEMOTION ) - { - Int32 resistance; - uInt32 zoom = theDisplay->zoomLevel(); - Int32 width = theDisplay->width() * zoom; - Event::Type type = Event::NoType; - - // Grabmouse and hidecursor introduce some lag into the mouse movement, - // so we need to fudge the numbers a bit - if(theGrabMouseIndicator && theHideCursorIndicator) - { - mouseX = (int)((float)mouseX + (float)event.motion.xrel - * 1.5 * (float) zoom); - } - else - { - mouseX = mouseX + event.motion.xrel * zoom; - } - - // Check to make sure mouseX is within the game window - if(mouseX < 0) - mouseX = 0; - else if(mouseX > width) - mouseX = width; - - resistance = (Int32)(1000000.0 * (width - mouseX) / width); - - // Now, set the event of the correct paddle to the calculated resistance - if(thePaddleMode == 0) - type = Event::PaddleZeroResistance; - else if(thePaddleMode == 1) - type = Event::PaddleOneResistance; - else if(thePaddleMode == 2) - type = Event::PaddleTwoResistance; - else if(thePaddleMode == 3) - type = Event::PaddleThreeResistance; - - theConsole->eventHandler().sendEvent(type, resistance); - } - else if(event.type == SDL_MOUSEBUTTONDOWN || event.type == SDL_MOUSEBUTTONUP) - { - Event::Type type = Event::LastType; - Int32 value; - - if(event.type == SDL_MOUSEBUTTONDOWN) - value = 1; - else - value = 0; - - if(thePaddleMode == 0) - type = Event::PaddleZeroFire; - else if(thePaddleMode == 1) - type = Event::PaddleOneFire; - else if(thePaddleMode == 2) - type = Event::PaddleTwoFire; - else if(thePaddleMode == 3) - type = Event::PaddleThreeFire; - - theConsole->eventHandler().sendEvent(type, value); - } - else if(event.type == SDL_ACTIVEEVENT) - { - static bool appActivateWasPaused; - static bool appInputWasPaused; - - if (event.active.state & (SDL_APPACTIVE)) { - if (event.active.gain == 0) { - appActivateWasPaused = theConsole->eventHandler().doPause(); - if (!appActivateWasPaused) - theConsole->eventHandler().sendEvent(Event::Pause, 1); - } - else { - if (!appActivateWasPaused) - theConsole->eventHandler().sendEvent(Event::Pause, 1); - } - } - if (event.active.state & (SDL_APPINPUTFOCUS)) { - if (event.active.gain == 0) { - appInputWasPaused = theConsole->eventHandler().doPause() || - theDisplay->fullScreen(); - if (!appInputWasPaused) - theConsole->eventHandler().sendEvent(Event::Pause, 1); - } - else { - if (!appInputWasPaused) - theConsole->eventHandler().sendEvent(Event::Pause, 1); - } - } - } - else if(event.type == SDL_QUIT) - { - newGame = false; - theConsole->eventHandler().sendEvent(Event::Quit, 1); - } - else if(event.type == SDL_VIDEOEXPOSE) - { - theDisplay->refresh(); - } - else if(event.type == SDL_USEREVENT) - { - if (event.user.code == 1) - { - newGame = true; - fileToLoad = true; - gameFile = (char *) event.user.data1; - theConsole->eventHandler().sendEvent(Event::Quit, 1); - } - } - -#ifdef JOYSTICK_SUPPORT - // Read joystick events and modify event states - StellaEvent::JoyStick stick; - StellaEvent::JoyCode code; - Int32 state; - Uint8 axis; - Uint8 button; - Int32 resistance; - Sint16 value; - JoyType type; - - if(event.jbutton.which >= StellaEvent::LastJSTICK) - return; - - stick = joyList[event.jbutton.which]; - type = theJoysticks[event.jbutton.which].type; - - // Figure put what type of joystick we're dealing with - // Stelladaptors behave differently, and can't be remapped - switch(type) - { - case JT_NONE: - break; - - case JT_REGULAR: - - if((event.type == SDL_JOYBUTTONDOWN) || (event.type == SDL_JOYBUTTONUP)) - { - if(event.jbutton.button >= StellaEvent::LastJCODE) - return; - - code = joyButtonList[event.jbutton.button]; - state = event.jbutton.state == SDL_PRESSED ? 1 : 0; - - theConsole->eventHandler().sendJoyEvent(stick, code, state); - } - else if(event.type == SDL_JOYAXISMOTION) - { - axis = event.jaxis.axis; - value = event.jaxis.value; - - if(axis == 0) // x-axis - { - theConsole->eventHandler().sendJoyEvent(stick, StellaEvent::JAXIS_LEFT, - (value < -16384) ? 1 : 0); - theConsole->eventHandler().sendJoyEvent(stick, StellaEvent::JAXIS_RIGHT, - (value > 16384) ? 1 : 0); - } - else if(axis == 1) // y-axis - { - theConsole->eventHandler().sendJoyEvent(stick, StellaEvent::JAXIS_UP, - (value < -16384) ? 1 : 0); - theConsole->eventHandler().sendJoyEvent(stick, StellaEvent::JAXIS_DOWN, - (value > 16384) ? 1 : 0); - } - } - break; // Regular joystick - - case JT_STELLADAPTOR_1: - case JT_STELLADAPTOR_2: - - if((event.type == SDL_JOYBUTTONDOWN) || (event.type == SDL_JOYBUTTONUP)) - { - button = event.jbutton.button; - state = event.jbutton.state == SDL_PRESSED ? 1 : 0; - - // Send button events for the joysticks/paddles - if(button == 0) - { - if(type == JT_STELLADAPTOR_1) - { - theConsole->eventHandler().sendEvent(Event::JoystickZeroFire, state); - theConsole->eventHandler().sendEvent(Event::DrivingZeroFire, state); - theConsole->eventHandler().sendEvent(Event::PaddleZeroFire, state); - } - else - { - theConsole->eventHandler().sendEvent(Event::JoystickOneFire, state); - theConsole->eventHandler().sendEvent(Event::DrivingOneFire, state); - theConsole->eventHandler().sendEvent(Event::PaddleTwoFire, state); - } - } - else if(button == 1) - { - if(type == JT_STELLADAPTOR_1) - theConsole->eventHandler().sendEvent(Event::PaddleOneFire, state); - else - theConsole->eventHandler().sendEvent(Event::PaddleThreeFire, state); - } - } - else if(event.type == SDL_JOYAXISMOTION) - { - axis = event.jaxis.axis; - value = event.jaxis.value; - - // Send axis events for the joysticks - theConsole->eventHandler().sendEvent(SA_Axis[type-2][axis][0], - (value < -16384) ? 1 : 0); - theConsole->eventHandler().sendEvent(SA_Axis[type-2][axis][1], - (value > 16384) ? 1 : 0); - - // Send axis events for the paddles - resistance = (Int32) (1000000.0 * (32767 - value) / 65534); - theConsole->eventHandler().sendEvent(SA_Axis[type-2][axis][2], resistance); - - // Send events for the driving controllers - if (axis == 1) - { - if (value <= -16384-4096) - { - theConsole->eventHandler().sendEvent(SA_DrivingValue[type-2],2); - } - else if (value > 16384+4096) - { - theConsole->eventHandler().sendEvent(SA_DrivingValue[type-2],1); - } - else if (value >= 16384-4096) - { - theConsole->eventHandler().sendEvent(SA_DrivingValue[type-2],0); - } - else - { - theConsole->eventHandler().sendEvent(SA_DrivingValue[type-2],3); - } - } - } - break; // Stelladaptor joystick - - default: - break; - } -#endif - } -} - - -/** - Setup the properties set by first checking for a user file - "$HOME/.stella/stella.pro", then a system-wide file "/etc/stella.pro". - Return false if neither file is found, else return true. - - @param set The properties set to setup -*/ -bool setupProperties(PropertiesSet& set) -{ - bool useMemList = false; - string theAlternateProFile = theSettings->getString("altpro"); - string theUserProFile = theSettings->userPropertiesFilename(); - string theSystemProFile = theSettings->systemPropertiesFilename(); - -#ifdef DEVELOPER_SUPPORT - // If the user wishes to merge any property modifications to the - // PropertiesSet file, then the PropertiesSet file MUST be loaded - // into memory. - useMemList = theSettings->getBool("mergeprops"); -#endif - - // Check to see if the user has specified an alternate .pro file. - - if(theAlternateProFile != "") - { - set.load(theAlternateProFile, useMemList); - return true; - } - - if(theUserProFile != "") - { - set.load(theUserProFile, useMemList); - return true; - } - else if(theSystemProFile != "") - { - set.load(theSystemProFile, useMemList); - return true; - } - else - { - set.load("", false); - return true; - } -} - - -/** - Does general in case any operation failed (or at end of program). -*/ -void cleanup() -{ -#ifdef JOYSTICK_SUPPORT - if(SDL_WasInit(SDL_INIT_JOYSTICK) & SDL_INIT_JOYSTICK) - { - for(uInt32 i = 0; i < StellaEvent::LastJSTICK; i++) - { - if(SDL_JoystickOpened(i)) - SDL_JoystickClose(theJoysticks[i].stick); - } - } -#endif - - if(theSettings) - delete theSettings; - - if(theConsole) - delete theConsole; - - if(theSound) - delete theSound; - - if(theDisplay) - delete theDisplay; - - if(SDL_WasInit(SDL_INIT_VIDEO) & SDL_INIT_VIDEO) - SDL_Quit(); -} - - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -int stellaMain(int argc, char* argv[]) -{ - theSettings = new SettingsMACOSX(); - - if(!theSettings) - { - cleanup(); - return 0; - } - theSettings->loadConfig(); - - // Cache some settings so they don't have to be repeatedly searched for - thePaddleMode = theSettings->getInt("paddle"); - setPaddleMenu(thePaddleMode); - theShowInfoFlag = theSettings->getBool("showinfo"); - theGrabMouseIndicator = theSettings->getBool("grabmouse"); - theHideCursorIndicator = theSettings->getBool("hidecursor"); - timePerFrame = 1.0 / (double)theSettings->getInt("framerate"); - if (theSettings->getInt("framerate") == 60) - setSpeedLimitMenu(1); - - // Initialize SDL Library - Uint32 initflags = SDL_INIT_VIDEO | SDL_INIT_TIMER; - if(SDL_Init(initflags) < 0) - { - return(0); - } - - // Create an SDL window - string videodriver = theSettings->getString("video"); - if(videodriver == "soft") - { - theDisplay = new FrameBufferSoft(); - if(theShowInfoFlag) - cout << "Using software mode for video.\n"; - } -#ifdef DISPLAY_OPENGL - else if(videodriver == "gl") - { - theDisplay = new FrameBufferGL(); - theUseOpenGLFlag = true; - if(theShowInfoFlag) - cout << "Using OpenGL mode for video.\n"; - } -#endif - else // a driver that doesn't exist was requested, so use software mode - { - theDisplay = new FrameBufferSoft(); - if(theShowInfoFlag) - cout << "Using software mode for video.\n"; - } - - initVideoMenu(theUseOpenGLFlag); - - if(!theDisplay) - { - cerr << "ERROR: Couldn't set up display.\n"; - cleanup(); - return 0; - } - - // Create a sound object for playing audio - if(theSettings->getBool("sound")) - { - uInt32 fragsize = theSettings->getInt("fragsize"); - theSound = new SoundSDL(fragsize); - if(theShowInfoFlag) - { - cout << "Sound enabled, using fragment size = " << fragsize; - cout << "." << endl; - } - } - else // even if sound has been disabled, we still need a sound object - { - theSound = new Sound(); - if(theShowInfoFlag) - cout << "Sound disabled.\n"; - } - theSound->setVolume(theSettings->getInt("volume")); - - if (argv[1] != NULL) - { - fileToLoad = true; - gameFile = argv[1]; - } - -while(1) { - // Get a pointer to the file which contains the cartridge ROM - char* file; - - if (fileToLoad) - { - file = gameFile; - } - else - { - do - { - file = browseFile(); - if (file == NULL) - { - if (!handleInitialEvents()) - return 0; - } - } while (file == NULL); - } - fileToLoad = false; - - // Open the cartridge image and read it in - ifstream in(file, ios_base::binary); - if(!in) - { - cerr << "ERROR: Couldn't open " << file << "..." << endl; - cleanup(); - return 0; - } - - uInt8* image = new uInt8[512 * 1024]; - in.read((char*)image, 512 * 1024); - uInt32 size = in.gcount(); - in.close(); - - // Create a properties set for us to use and set it up - PropertiesSet propertiesSet; - if(!setupProperties(propertiesSet)) - { - delete[] image; - cleanup(); - return 0; - } - - // Get just the filename of the file containing the ROM image - const char* filename = (!strrchr(file, '/')) ? file : strrchr(file, '/') + 1; - - // Create the 2600 game console - theConsole = new Console(image, size, filename, *theSettings, propertiesSet, - *theDisplay, *theSound); - - // Free the image since we don't need it any longer - delete[] image; - free(file); - - // Setup the SDL joysticks - // This must be done after the console is created - if(!setupJoystick()) - { - cerr << "ERROR: Couldn't set up joysticks.\n"; - cleanup(); - return 0; - } - - double lasttime = Atari_time(); - double frametime = 0.1; /* measure time between two runs */ - - enableGameMenus(); - - // Set the base for the timers - // Main game loop - for(;;) - { - // Exit if the user wants to quit - if(theConsole->eventHandler().doQuit()) - { - break; - } - - handleEvents(); - theConsole->update(); - - double lastcurtime = 0; - double curtime, delaytime; - - if (timePerFrame > 0.0) - { - curtime = Atari_time(); - delaytime = lasttime + timePerFrame - curtime; - if (delaytime > 0) - usleep((int) (delaytime * 1e6)); - curtime = Atari_time(); - - /* make average time */ - frametime = (frametime * 4.0 + curtime - lastcurtime) * 0.2; - // fps = 1.0 / frametime; - lastcurtime = curtime; - - lasttime += timePerFrame; - if ((lasttime + timePerFrame) < curtime) - lasttime = curtime; - } - AboutBoxScroll(); - } - - delete theConsole; - theConsole = NULL; - - if (!newGame) - break; - newGame = false; -} - - // Cleanup time ... - cleanup(); - - return 0; -} - -static double Atari_time(void) -{ - struct timeval tp; - - gettimeofday(&tp, NULL); - return 1000000 * tp.tv_sec + 1e-6 * tp.tv_usec; -} - - diff --git a/stella/src/macosx/stella.pbproj/.DS_Store b/stella/src/macosx/stella.pbproj/.DS_Store deleted file mode 100644 index 7f419608e81a6945d662c21f925d3d92f6a80795..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHK%Sr=55UkN00v-%r^dig`2>!tk;vr}K08NabtgdJTkNcl~j8=6|#Ep9nBHb`u zvpwBC(*-*Z0BQPmdk#zhjM;=qodJ<~aA>bO3zOwoVTm=)@QlSkqQ7X;+7G$j7qoc5 z&-K4=tn;Q_E}B*qk*0J?JpMGXf{t*-xJP<7xMB4x%<+Uf<`WMM?(vHCR*sLY9F{0l zFc1s`1HnKruoDJ&W=qBgj-i8rU?3RyWo%U?*NX0R9Fc1v%8QAyFiO&BE z{xXA){C-G$1p~prKVu+`W|y-mi>hbqukv)(X0~fKiTpZsDD3wx0sPQDa$ - #include /* For the definition of NULL */ - - #include "SDL_error.h" -@@ -35,12 +42,28 @@ - #include "SDL_sysjoystick.h" - #include "SDL_joystick_c.h" - --#include --#include -+#ifdef _XBOX -+ #include -+#else -+ #include -+#endif -+ -+#define DIRECTINPUT_VERSION 0x0500 -+#include -+ -+#include "SDL_active.h" -+ -+#define INPUT_QSIZE 32 /* Buffer up to 32 input messages */ -+ -+extern HRESULT (WINAPI *DInputCreate)(HINSTANCE hinst, DWORD dwVersion, LPDIRECTINPUT *ppDI, LPUNKNOWN punkOuter); -+ -+static LPDIRECTINPUT dinput = NULL; -+extern HINSTANCE SDL_Instance; - - #define MAX_JOYSTICKS 16 - #define MAX_AXES 6 /* each joystick can have up to 6 axes */ - #define MAX_BUTTONS 32 /* and 32 buttons */ -+#define MAX_INPUTS 256 /* each joystick can have up to 256 inputs */ - #define AXIS_MIN -32768 /* minimum value for axis coordinate */ - #define AXIS_MAX 32767 /* maximum value for axis coordinate */ - /* limit axis to 256 possible positions to filter out noise */ -@@ -48,27 +71,148 @@ - #define JOY_BUTTON_FLAG(n) (1<= MAX_JOYSTICKS ) -+ return DIENUM_STOP; - -+ return DIENUM_CONTINUE; -+} -+ -+static BOOL CALLBACK DIJoystick_EnumDevObjectsProc(LPCDIDEVICEOBJECTINSTANCE dev, -+ LPVOID pvRef) -+{ -+ SDL_Joystick *joystick = (SDL_Joystick*)pvRef; -+ HRESULT result; -+ input_t *in = &joystick->hwdata->Inputs[joystick->hwdata->NumInputs]; -+ const int SupportedMask = DIDFT_BUTTON | DIDFT_POV | DIDFT_AXIS; -+ if(!(dev->dwType & SupportedMask)) -+ return DIENUM_CONTINUE; /* unsupported */ -+ -+ in->ofs = dev->dwOfs; -+ -+ if(dev->dwType & DIDFT_BUTTON) { -+ in->type = BUTTON; -+ in->num = joystick->nbuttons; -+ joystick->nbuttons++; -+ } else if(dev->dwType & DIDFT_POV) { -+ in->type = HAT; -+ in->num = joystick->nhats; -+ joystick->nhats++; -+ } else { /* dev->dwType & DIDFT_AXIS */ -+ DIPROPRANGE diprg; -+ DIPROPDWORD dilong; -+ -+ in->type = AXIS; -+ in->num = joystick->naxes; -+ -+ diprg.diph.dwSize = sizeof(diprg); -+ diprg.diph.dwHeaderSize = sizeof(diprg.diph); -+ diprg.diph.dwObj = dev->dwOfs; -+ diprg.diph.dwHow = DIPH_BYOFFSET; -+ diprg.lMin = AXIS_MIN; -+ diprg.lMax = AXIS_MAX; -+ -+ result = IDirectInputDevice2_SetProperty(joystick->hwdata->InputDevice, DIPROP_RANGE, &diprg.diph); -+ if ( result != DI_OK ) -+ return DIENUM_CONTINUE; /* don't use this axis */ -+ -+ /* Set dead zone to 0. */ -+ dilong.diph.dwSize = sizeof(dilong); -+ dilong.diph.dwHeaderSize = sizeof(dilong.diph); -+ dilong.diph.dwObj = dev->dwOfs; -+ dilong.diph.dwHow = DIPH_BYOFFSET; -+ dilong.dwData = 0; -+ result = IDirectInputDevice2_SetProperty(joystick->hwdata->InputDevice, DIPROP_DEADZONE, &dilong.diph); -+ if ( result != DI_OK ) -+ return DIENUM_CONTINUE; /* don't use this axis */ -+ -+ joystick->naxes++; -+ } -+ -+ joystick->hwdata->NumInputs++; -+ -+ if(joystick->hwdata->NumInputs == MAX_INPUTS) -+ return DIENUM_STOP; /* too many */ -+ -+ return DIENUM_CONTINUE; -+} - - /* Function to scan the system for joysticks. - * This function should set SDL_numjoysticks to the number of available -@@ -77,51 +221,32 @@ - */ - int SDL_SYS_JoystickInit(void) - { -- int i; -- int maxdevs; -- int numdevs; -- JOYINFOEX joyinfo; -- JOYCAPS joycaps; -- MMRESULT result; -+ HRESULT result; - -- numdevs = 0; -- maxdevs = joyGetNumDevs(); -- -- if ( maxdevs > MAX_JOYSTICKS ) { -- maxdevs = MAX_JOYSTICKS; -- } -+ SYS_NumJoysticks = 0; - -- -- for ( i = 0; i < MAX_JOYSTICKS; i++ ) { -- SYS_JoystickID[i] = JOYSTICKID1 + i; -+ /* Create the DirectInput object */ -+ result = DInputCreate(SDL_Instance, DIRECTINPUT_VERSION, -+ &dinput, NULL); -+ if ( result != DI_OK ) { -+ SetDIerror("DirectInputCreate", result); -+ return(-1); - } - -+ result = IDirectInput_EnumDevices(dinput, -+ DIDEVTYPE_JOYSTICK, -+ EnumJoysticksCallback, -+ NULL, -+ DIEDFL_ATTACHEDONLY ); - -- for ( i = 0; (i < maxdevs); ++i ) { -- -- /* added 8/31/2001 By Vitaliy Mikitchenko */ -- joyinfo.dwSize = sizeof(joyinfo); -- joyinfo.dwFlags = JOY_RETURNALL; -- /* end addition */ -- -- result = joyGetPosEx(SYS_JoystickID[i], &joyinfo); -- if ( result == JOYERR_NOERROR ) { -- result = joyGetDevCaps(SYS_JoystickID[i], &joycaps, sizeof(joycaps)); -- if ( result == JOYERR_NOERROR ) { -- SYS_JoystickID[numdevs] = SYS_JoystickID[i]; -- SYS_Joystick[numdevs] = joycaps; -- numdevs++; -- } -- } -- } -- return(numdevs); -+ return SYS_NumJoysticks; - } - - /* Function to get the device-dependent name of a joystick */ - const char *SDL_SYS_JoystickName(int index) - { - /***-> test for invalid index ? */ -- return(SYS_Joystick[index].szPname); -+ return(SYS_Joystick[index].tszProductName); - } - - /* Function to open a joystick for use. -@@ -131,26 +256,8 @@ - */ - int SDL_SYS_JoystickOpen(SDL_Joystick *joystick) - { -- int index, i; -- int caps_flags[MAX_AXES-2] = -- { JOYCAPS_HASZ, JOYCAPS_HASR, JOYCAPS_HASU, JOYCAPS_HASV }; -- int axis_min[MAX_AXES], axis_max[MAX_AXES]; -- -- -- /* shortcut */ -- index = joystick->index; -- axis_min[0] = SYS_Joystick[index].wXmin; -- axis_max[0] = SYS_Joystick[index].wXmax; -- axis_min[1] = SYS_Joystick[index].wYmin; -- axis_max[1] = SYS_Joystick[index].wYmax; -- axis_min[2] = SYS_Joystick[index].wZmin; -- axis_max[2] = SYS_Joystick[index].wZmax; -- axis_min[3] = SYS_Joystick[index].wRmin; -- axis_max[3] = SYS_Joystick[index].wRmax; -- axis_min[4] = SYS_Joystick[index].wUmin; -- axis_max[4] = SYS_Joystick[index].wUmax; -- axis_min[5] = SYS_Joystick[index].wVmin; -- axis_max[5] = SYS_Joystick[index].wVmax; -+ HRESULT result; -+ LPDIRECTINPUTDEVICE device; - - /* allocate memory for system specific hardware data */ - joystick->hwdata = (struct joystick_hwdata *) malloc(sizeof(*joystick->hwdata)); -@@ -160,52 +267,114 @@ - return(-1); - } - memset(joystick->hwdata, 0, sizeof(*joystick->hwdata)); -+ joystick->hwdata->buffered = 1; -+ -+ result = IDirectInput_CreateDevice(dinput, &SYS_Joystick[joystick->index].guidInstance, -+ &device, NULL); -+ if ( result != DI_OK ) { -+ SetDIerror("DirectInput::CreateDevice", result); -+ return(-1); -+ } - -- /* set hardware data */ -- joystick->hwdata->id = SYS_JoystickID[index]; -- for ( i = 0; i < MAX_AXES; ++i ) { -- if ( (i<2) || (SYS_Joystick[index].wCaps & caps_flags[i-2]) ) { -- joystick->hwdata->transaxis[i].offset = -- AXIS_MIN - axis_min[i]; -- joystick->hwdata->transaxis[i].scale = -- (float)(AXIS_MAX - AXIS_MIN) / (axis_max[i] - axis_min[i]); -- } else { -- joystick->hwdata->transaxis[i].offset = 0; -- joystick->hwdata->transaxis[i].scale = 1.0; /* Just in case */ -- } -+ result = IDirectInputDevice_QueryInterface(device, -+ &IID_IDirectInputDevice2, (LPVOID *)&joystick->hwdata->InputDevice); -+ IDirectInputDevice_Release(device); -+ if ( result != DI_OK ) { -+ SetDIerror("DirectInputDevice::QueryInterface", result); -+ return(-1); - } - -- /* fill nbuttons, naxes, and nhats fields */ -- joystick->nbuttons = SYS_Joystick[index].wNumButtons; -- joystick->naxes = SYS_Joystick[index].wNumAxes; -- if ( SYS_Joystick[index].wCaps & JOYCAPS_HASPOV ) { -- joystick->nhats = 1; -- } else { -- joystick->nhats = 0; -+ result = IDirectInputDevice2_SetCooperativeLevel(joystick->hwdata->InputDevice, SDL_Window, -+ DISCL_NONEXCLUSIVE | DISCL_BACKGROUND); -+ if ( result != DI_OK ) { -+ SetDIerror("DirectInputDevice::SetCooperativeLevel", result); -+ return(-1); -+ } -+ -+ result = IDirectInputDevice2_SetDataFormat(joystick->hwdata->InputDevice, &c_dfDIJoystick); -+ if ( result != DI_OK ) { -+ SetDIerror("DirectInputDevice::SetDataFormat", result); -+ return(-1); -+ } -+ -+ IDirectInputDevice2_EnumObjects(joystick->hwdata->InputDevice, -+ DIJoystick_EnumDevObjectsProc, -+ joystick, -+ DIDFT_BUTTON | DIDFT_AXIS | DIDFT_POV); -+ -+ { -+ DIPROPDWORD dipdw; -+ memset(&dipdw, 0, sizeof(dipdw)); -+ dipdw.diph.dwSize = sizeof(dipdw); -+ dipdw.diph.dwHeaderSize = sizeof(dipdw.diph); -+ dipdw.diph.dwObj = 0; -+ dipdw.diph.dwHow = DIPH_DEVICE; -+ dipdw.dwData = INPUT_QSIZE; -+ result = IDirectInputDevice2_SetProperty(joystick->hwdata->InputDevice, -+ DIPROP_BUFFERSIZE, &dipdw.diph); -+ -+ if ( result == DI_POLLEDDEVICE ) -+ { -+ /* This device doesn't support buffering, so we're forced -+ * to use less reliable polling. */ -+ joystick->hwdata->buffered = 0; -+ } else if ( result != DI_OK ) { -+ SetDIerror("DirectInputDevice::SetProperty", result); -+ return(-1); -+ } - } -+ - return(0); - } - - static Uint8 TranslatePOV(DWORD value) - { -- Uint8 pos; -+ const int HAT_VALS[] = { -+ SDL_HAT_UP, -+ SDL_HAT_UP | SDL_HAT_RIGHT, -+ SDL_HAT_RIGHT, -+ SDL_HAT_DOWN | SDL_HAT_RIGHT, -+ SDL_HAT_DOWN, -+ SDL_HAT_DOWN | SDL_HAT_LEFT, -+ SDL_HAT_LEFT, -+ SDL_HAT_UP | SDL_HAT_LEFT -+ }; -+ -+ if(LOWORD(value) == 0xFFFF) -+ return SDL_HAT_CENTERED; -+ -+ /* Round the value up: */ -+ value += 4500 / 2; -+ value %= 36000; -+ value /= 4500; -+ -+ if(value >= 8) -+ return SDL_HAT_CENTERED; /* shouldn't happen */ -+ -+ return HAT_VALS[value]; -+} - -- pos = SDL_HAT_CENTERED; -- if ( value != JOY_POVCENTERED ) { -- if ( (value > JOY_POVLEFT) || (value < JOY_POVRIGHT) ) { -- pos |= SDL_HAT_UP; -- } -- if ( (value > JOY_POVFORWARD) && (value < JOY_POVBACKWARD) ) { -- pos |= SDL_HAT_RIGHT; -- } -- if ( (value > JOY_POVRIGHT) && (value < JOY_POVLEFT) ) { -- pos |= SDL_HAT_DOWN; -- } -- if ( value > JOY_POVBACKWARD ) { -- pos |= SDL_HAT_LEFT; -- } -- } -- return(pos); -+/* SDL_PrivateJoystick* doesn't discard duplicate events, so we need to -+ * do it. */ -+static int SDL_PrivateJoystickAxis_Int(SDL_Joystick *joystick, Uint8 axis, Sint16 value) -+{ -+ if(joystick->axes[axis] != value) -+ return SDL_PrivateJoystickAxis(joystick, axis, value); -+ return 0; -+} -+ -+static int SDL_PrivateJoystickHat_Int(SDL_Joystick *joystick, Uint8 hat, Uint8 value) -+{ -+ if(joystick->hats[hat] != value) -+ return SDL_PrivateJoystickHat(joystick, hat, value); -+ return 0; -+} -+ -+static int SDL_PrivateJoystickButton_Int(SDL_Joystick *joystick, Uint8 button, Uint8 state) -+{ -+ if(joystick->buttons[button] != state) -+ return SDL_PrivateJoystickButton(joystick, button, state); -+ return 0; - } - - /* Function to update the state of a joystick - called as a device poll. -@@ -213,76 +382,126 @@ - * but instead should call SDL_PrivateJoystick*() to deliver events - * and update joystick device state. - */ --void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick) -+void SDL_SYS_JoystickUpdate_Polled(SDL_Joystick *joystick) - { -- MMRESULT result; -+ DIJOYSTATE state; -+ HRESULT result; - int i; -- DWORD flags[MAX_AXES] = { JOY_RETURNX, JOY_RETURNY, JOY_RETURNZ, -- JOY_RETURNR, JOY_RETURNU, JOY_RETURNV }; -- DWORD pos[MAX_AXES]; -- struct _transaxis *transaxis; -- int value, change; -- JOYINFOEX joyinfo; -- -- joyinfo.dwSize = sizeof(joyinfo); -- joyinfo.dwFlags = JOY_RETURNALL|JOY_RETURNPOVCTS; -- if ( ! joystick->hats ) { -- joyinfo.dwFlags &= ~(JOY_RETURNPOV|JOY_RETURNPOVCTS); -- } -- result = joyGetPosEx(joystick->hwdata->id, &joyinfo); -- if ( result != JOYERR_NOERROR ) { -- SetMMerror("joyGetPosEx", result); -- return; -- } -- -- /* joystick motion events */ -- pos[0] = joyinfo.dwXpos; -- pos[1] = joyinfo.dwYpos; -- pos[2] = joyinfo.dwZpos; -- pos[3] = joyinfo.dwRpos; -- pos[4] = joyinfo.dwUpos; -- pos[5] = joyinfo.dwVpos; -- -- transaxis = joystick->hwdata->transaxis; -- for (i = 0; i < joystick->naxes; i++) { -- if (joyinfo.dwFlags & flags[i]) { -- value = (int)(((float)pos[i] + transaxis[i].offset) * transaxis[i].scale); -- change = (value - joystick->axes[i]); -- if ( (change < -JOY_AXIS_THRESHOLD) || (change > JOY_AXIS_THRESHOLD) ) { -- SDL_PrivateJoystickAxis(joystick, (Uint8)i, (Sint16)value); -+ -+ result = IDirectInputDevice2_GetDeviceState(joystick->hwdata->InputDevice, sizeof(state), &state); -+ if ( result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED ) { -+ IDirectInputDevice2_Acquire(joystick->hwdata->InputDevice); -+ result = IDirectInputDevice2_GetDeviceState(joystick->hwdata->InputDevice, sizeof(state), &state); -+ } -+ -+ /* Set each known axis, button and POV. */ -+ for(i = 0; i < joystick->hwdata->NumInputs; ++i) -+ { -+ const input_t *in = &joystick->hwdata->Inputs[i]; -+ -+ switch(in->type) -+ { -+ case AXIS: -+ switch(in->ofs) -+ { -+ case DIJOFS_X: SDL_PrivateJoystickAxis_Int(joystick, in->num, (Sint16)state.lX); break; -+ case DIJOFS_Y: SDL_PrivateJoystickAxis_Int(joystick, in->num, (Sint16)state.lY); break; -+ case DIJOFS_Z: SDL_PrivateJoystickAxis_Int(joystick, in->num, (Sint16)state.lZ); break; -+ case DIJOFS_RX: SDL_PrivateJoystickAxis_Int(joystick, in->num, (Sint16)state.lRx); break; -+ case DIJOFS_RY: SDL_PrivateJoystickAxis_Int(joystick, in->num, (Sint16)state.lRy); break; -+ case DIJOFS_RZ: SDL_PrivateJoystickAxis_Int(joystick, in->num, (Sint16)state.lRz); break; -+ case DIJOFS_SLIDER(0): SDL_PrivateJoystickAxis_Int(joystick, in->num, (Sint16)state.rglSlider[0]); break; -+ case DIJOFS_SLIDER(1): SDL_PrivateJoystickAxis_Int(joystick, in->num, (Sint16)state.rglSlider[0]); break; - } -+ -+ break; -+ -+ case BUTTON: -+ SDL_PrivateJoystickButton_Int(joystick, in->num, (Uint8) (state.rgbButtons[in->ofs - DIJOFS_BUTTON0]?SDL_PRESSED:SDL_RELEASED)); -+ break; -+ case HAT: -+ { -+ Uint8 pos = TranslatePOV(state.rgdwPOV[in->ofs - DIJOFS_POV(0)]); -+ SDL_PrivateJoystickHat_Int(joystick, in->num, pos); -+ break; -+ } - } - } -+} -+ -+void SDL_SYS_JoystickUpdate_Buffered(SDL_Joystick *joystick) -+{ -+ int i; -+ HRESULT result; -+ DWORD numevents; -+ DIDEVICEOBJECTDATA evtbuf[INPUT_QSIZE]; -+ -+ numevents = INPUT_QSIZE; -+ result = IDirectInputDevice2_GetDeviceData( -+ joystick->hwdata->InputDevice, sizeof(DIDEVICEOBJECTDATA), -+ evtbuf, &numevents, 0); -+ if ( result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED ) { -+ IDirectInputDevice2_Acquire(joystick->hwdata->InputDevice); -+ result = IDirectInputDevice2_GetDeviceData( -+ joystick->hwdata->InputDevice, sizeof(DIDEVICEOBJECTDATA), -+ evtbuf, &numevents, 0); -+ } -+ -+ /* Handle the events */ -+ if ( result != DI_OK ) -+ return; -+ -+ for(i = 0; i < (int) numevents; ++i) -+ { -+ int j; -+ -+ for(j = 0; j < joystick->hwdata->NumInputs; ++j) -+ { -+ const input_t *in = &joystick->hwdata->Inputs[j]; - -- /* joystick button events */ -- if ( joyinfo.dwFlags & JOY_RETURNBUTTONS ) { -- for ( i = 0; i < joystick->nbuttons; ++i ) { -- if ( joyinfo.dwButtons & JOY_BUTTON_FLAG(i) ) { -- if ( ! joystick->buttons[i] ) { -- SDL_PrivateJoystickButton(joystick, (Uint8)i, SDL_PRESSED); -- } -- } else { -- if ( joystick->buttons[i] ) { -- SDL_PrivateJoystickButton(joystick, (Uint8)i, SDL_RELEASED); -- } -+ if(evtbuf[i].dwOfs != in->ofs) -+ continue; -+ -+ switch(in->type) -+ { -+ case AXIS: -+ SDL_PrivateJoystickAxis(joystick, in->num, (Sint16)evtbuf[i].dwData); -+ break; -+ case BUTTON: -+ SDL_PrivateJoystickButton(joystick, in->num, (Uint8) (evtbuf[i].dwData?SDL_PRESSED:SDL_RELEASED)); -+ break; -+ case HAT: -+ { -+ Uint8 pos = TranslatePOV(evtbuf[i].dwData); -+ SDL_PrivateJoystickHat(joystick, in->num, pos); -+ } - } - } - } -+} - -- /* joystick hat events */ -- if ( joyinfo.dwFlags & JOY_RETURNPOV ) { -- Uint8 pos; -- -- pos = TranslatePOV(joyinfo.dwPOV); -- if ( pos != joystick->hats[0] ) { -- SDL_PrivateJoystickHat(joystick, 0, pos); -- } -+void SDL_SYS_JoystickUpdate(SDL_Joystick *joystick) -+{ -+ HRESULT result; -+ -+ result = IDirectInputDevice2_Poll(joystick->hwdata->InputDevice); -+ if (result == DIERR_INPUTLOST || result == DIERR_NOTACQUIRED) { -+ IDirectInputDevice2_Acquire(joystick->hwdata->InputDevice); -+ IDirectInputDevice2_Poll(joystick->hwdata->InputDevice); - } -+ -+ if(joystick->hwdata->buffered) -+ SDL_SYS_JoystickUpdate_Buffered(joystick); -+ else -+ SDL_SYS_JoystickUpdate_Polled(joystick); - } - - /* Function to close a joystick after use */ - void SDL_SYS_JoystickClose(SDL_Joystick *joystick) - { -+ IDirectInputDevice2_Unacquire(joystick->hwdata->InputDevice); -+ IDirectInputDevice2_Release(joystick->hwdata->InputDevice); -+ - if (joystick->hwdata != NULL) { - /* free system specific hardware data */ - free(joystick->hwdata); -@@ -292,48 +511,6 @@ - /* Function to perform any system-specific joystick related cleanup */ - void SDL_SYS_JoystickQuit(void) - { -- return; --} -- -- --/* implementation functions */ --void SetMMerror(char *function, int code) --{ -- static char *error; -- static char errbuf[BUFSIZ]; -- -- errbuf[0] = 0; -- switch (code) -- { -- case MMSYSERR_NODRIVER: -- error = "Joystick driver not present"; -- break; -- -- case MMSYSERR_INVALPARAM: -- case JOYERR_PARMS: -- error = "Invalid parameter(s)"; -- break; -- -- case MMSYSERR_BADDEVICEID: -- error = "Bad device ID"; -- break; -- -- case JOYERR_UNPLUGGED: -- error = "Joystick not attached"; -- break; -- -- case JOYERR_NOCANDO: -- error = "Can't capture joystick input"; -- break; -- -- default: -- sprintf(errbuf, "%s: Unknown Multimedia system error: 0x%x", -- function, code); -- break; -- } -- -- if ( ! errbuf[0] ) { -- sprintf(errbuf, "%s: %s", function, error); -- } -- SDL_SetError("%s", errbuf); -+ IDirectInput_Release(dinput); -+ dinput = NULL; - } diff --git a/stella/src/win32/Stella/Stella.ncb b/stella/src/win32/Stella/Stella.ncb deleted file mode 100644 index ab584b34a376147bc9fc10aefce06ea9cddce350..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 470016 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%0ASKIybc& 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 diff --git a/stella/src/win32/Stella/Stella.sln b/stella/src/win32/Stella/Stella.sln deleted file mode 100644 index 4d5b89f64..000000000 --- a/stella/src/win32/Stella/Stella.sln +++ /dev/null @@ -1,21 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 8.00 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Stella", "Stella.vcproj", "{D7FCEC7F-33E1-49DD-A4B0-D5FC222250AD}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfiguration) = preSolution - Debug = Debug - Release = Release - EndGlobalSection - GlobalSection(ProjectConfiguration) = postSolution - {D7FCEC7F-33E1-49DD-A4B0-D5FC222250AD}.Debug.ActiveCfg = Debug|Win32 - {D7FCEC7F-33E1-49DD-A4B0-D5FC222250AD}.Debug.Build.0 = Debug|Win32 - {D7FCEC7F-33E1-49DD-A4B0-D5FC222250AD}.Release.ActiveCfg = Release|Win32 - {D7FCEC7F-33E1-49DD-A4B0-D5FC222250AD}.Release.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - EndGlobalSection - GlobalSection(ExtensibilityAddIns) = postSolution - EndGlobalSection -EndGlobal diff --git a/stella/src/win32/Stella/Stella.suo b/stella/src/win32/Stella/Stella.suo deleted file mode 100644 index cd3bfd52af348491dfe55f593e32e63c31c6020e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8192 zcmeHLO>k3H6h3J|+5!cXAFYa!@+Z<-Cl+hU% zIy&RHbf?ZR?ihy|#|@5-j2l-tZrr$#g`+!NAff{C`|i6pf27Gv8yAe6%*nm)zI*RE z_r7z!bMF1_>WZH}zSMS2O6YlMlsnmGd7z-(gF0E!a*+m9_GFuwO3?3Umw-Z8EJFZfCQ+>UZRcmsGNcoTRt_$lxf@Y7%;s}uESz+JkH>%LEO+ksc!{ozLU^?2`_ zuT6cjd-Ag(Y-vsOyN^*~?nK+24{<#0;Gpc0Q5hB={?qWIFiQGWRALfAJqWL|P>;dC zMzuhe^OdisLbfFG2H2#!{?FeA8Lwi{ z^(6KxZ;9r)c8mP4G;;JbzR%61SCymkE4q8U8OwNDO7m&sTyDpg%B}Ue)cyjn_c*MM zdEkil1zXO}>V;dOsWN>1=SDtrHM8^dcOr8NUPtuHBc;gF^O~_Dt6;(8)`e` zIZW+GZ9nRLh?pIC+KFC1L{R6q6RrEvdLGd=0_!f8dsIcALaDTv;y%UJ$-Yf0Z>^_p zJ@P``S33whkAZpWv1CTYxfpia*tp|oCt>yDXl4Fl-awTy1poIimeQWx+8@tLuWEoh ziWqkq7QkF-HXkn|HrKRv4*2sJMi1*5eAo@{MOx)x7Hpw5EqMOp*@qV5cKtlZXz@84 zCk`f|3z3&-=vW)^t};Nl&?TW(%)F%#H}BTcSqD$2eb71# zyyFSWLKei^Hz&jAZ3pk*B1LmKaVDwc5Q&{zA?`{klIK0SmR&mzi9{Xe>qT;S zJPQKL(z-d|Zz28_+HzR|RT^98Ab%a^jOqAe?)l99Ul5o<4CWmiqhhrk0RAf6CH9i4 zsH{cZsm8N?-ghG|H^Chl8cHHR~ZlH zPCQF5^IMbAu;umHiA>6lDU(^|OHHRUp_q5jO4_N6YFpqBWmFd5aw2fp8w{Va;_7j! zKN^bJ3sJE z2ZsWOIa#YO7EO-Xp;W{>7)>x#%Ax~S!b*h{@XU8S=bH!BBZ+4kn~%T6A#nyS%&Wn4 zL67`31rNIua5X3G8r9ItD+ngZop>{a-wb}|WH-RO8~@uicgVA-cY!-_@Yseh#pB0r z{C25B2QTaR8&EAf(aM9#b{slL1!twrmCi~Ha;vUsSIJ%-Lf#uhJo0PgH<4x - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/stella/src/win32/StellaX/AboutPage.cxx b/stella/src/win32/StellaX/AboutPage.cxx deleted file mode 100644 index 3c6b8df6b..000000000 --- a/stella/src/win32/StellaX/AboutPage.cxx +++ /dev/null @@ -1,47 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll XX XX -// SS SS tt ll ll XX XX -// SS tttttt eeee ll ll aaaa XX XX -// SSSS tt ee ee ll ll aa XXX -// SS tt eeeeee ll ll aaaaa XX XX -// SS SS tt ee ll ll aa aa XX XX -// SSSS ttt eeeee llll llll aaaaa XX XX -// -// Copyright (c) 1995-2000 by Jeff Miller -// Copyright (c) 2004 by Stephen Anthony -// -// See the file "license" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -// -// $Id: AboutPage.cxx,v 1.2 2004-07-15 03:03:26 stephena Exp $ -//============================================================================ - -#include "pch.hxx" -#include "AboutPage.hxx" -#include "resource.h" - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -CHelpPage::CHelpPage() - : CPropertyPage(IDD_ABOUT_PAGE) -{ -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -BOOL CHelpPage::OnInitDialog( HWND hwnd ) -{ - m_hlMail_JSM.SubclassDlgItem( hwnd, IDC_EMAIL_MAINTAINER ); - m_hlMail_JSM.SetURL( _T("mailto:sa666_666@hotmail.com?Subject=StellaX") ); - - m_hlWWW_JSM.SubclassDlgItem( hwnd, IDC_WEB_MAINTAINER ); - m_hlWWW_JSM.SetURL( _T("http://minbar.org") ); - - m_hlMail_Stella.SubclassDlgItem( hwnd, IDC_EMAIL_STELLA ); - m_hlMail_Stella.SetURL( _T("mailto:stella-main@lists.sourceforge.net") ); - - m_hlWWW_Stella.SubclassDlgItem( hwnd, IDC_WEB_STELLA ); - m_hlWWW_Stella.SetURL( _T("http://stella.sf.net") ); - - // return FALSE if SetFocus is called - return TRUE; -} diff --git a/stella/src/win32/StellaX/AboutPage.hxx b/stella/src/win32/StellaX/AboutPage.hxx deleted file mode 100644 index 9bd606f97..000000000 --- a/stella/src/win32/StellaX/AboutPage.hxx +++ /dev/null @@ -1,44 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll XX XX -// SS SS tt ll ll XX XX -// SS tttttt eeee ll ll aaaa XX XX -// SSSS tt ee ee ll ll aa XXX -// SS tt eeeeee ll ll aaaaa XX XX -// SS SS tt ee ll ll aa aa XX XX -// SSSS ttt eeeee llll llll aaaaa XX XX -// -// Copyright (c) 1995-2000 by Jeff Miller -// Copyright (c) 2004 by Stephen Anthony -// -// See the file "license" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -// -// $Id: AboutPage.hxx,v 1.3 2004-07-15 03:03:27 stephena Exp $ -//============================================================================ - -#ifndef ABOUT_PAGE_HXX -#define ABOUT_PAGE_HXX - -#include "PropertySheet.hxx" -#include "HyperLink.hxx" - -class CHelpPage : public CPropertyPage -{ - public: - CHelpPage(); - - protected: - virtual BOOL OnInitDialog( HWND hwnd ); - - private: - CHyperLink m_hlMail_JSM; - CHyperLink m_hlWWW_JSM; - CHyperLink m_hlMail_Stella; - CHyperLink m_hlWWW_Stella; - - CHelpPage( const CHelpPage& ); // no implementation - void operator=( const CHelpPage& ); // no implementation -}; - -#endif diff --git a/stella/src/win32/StellaX/BrowseForFolder.cxx b/stella/src/win32/StellaX/BrowseForFolder.cxx deleted file mode 100644 index 330d6a3a0..000000000 --- a/stella/src/win32/StellaX/BrowseForFolder.cxx +++ /dev/null @@ -1,121 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll XX XX -// SS SS tt ll ll XX XX -// SS tttttt eeee ll ll aaaa XX XX -// SSSS tt ee ee ll ll aa XXX -// SS tt eeeeee ll ll aaaaa XX XX -// SS SS tt ee ll ll aa aa XX XX -// SSSS ttt eeeee llll llll aaaaa XX XX -// -// Copyright (c) 1998 Scott D. Killen -// Copyright (c) 2004 by Stephen Anthony -// -// See the file "license" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -// -// $Id: BrowseForFolder.cxx,v 1.4 2004-07-15 03:03:27 stephena Exp $ -//============================================================================ - -#include "pch.hxx" -#include "BrowseForFolder.hxx" - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -CBrowseForFolder::CBrowseForFolder( - const HWND hParent, - const LPITEMIDLIST pidl, - LPCTSTR strTitle) -{ - myHwnd = NULL; - - myBrowseInfo.pidlRoot = pidl; - myBrowseInfo.hwndOwner = NULL; - myBrowseInfo.pszDisplayName = mySelected; - myBrowseInfo.lpszTitle = strTitle; - myBrowseInfo.ulFlags = BIF_RETURNONLYFSDIRS|BIF_RETURNFSANCESTORS; - myBrowseInfo.lParam = reinterpret_cast( this ); - myBrowseInfo.lpfn = BrowseCallbackProc; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -CBrowseForFolder::~CBrowseForFolder() -{ -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -LPCTSTR CBrowseForFolder::GetSelectedFolder() const -{ - return mySelected; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool CBrowseForFolder::SelectFolder() -{ - bool bRet = false; - - LPITEMIDLIST pidl; - if ((pidl = SHBrowseForFolder(&myBrowseInfo)) != NULL) - { - if (SUCCEEDED(SHGetPathFromIDList(pidl, mySelected))) - bRet = true; - - LPMALLOC pMalloc; - //Retrieve a pointer to the shell's IMalloc interface - if (SUCCEEDED(SHGetMalloc(&pMalloc))) - { - // free the PIDL that SHBrowseForFolder returned to us. - pMalloc->Free(pidl); - // release the shell's IMalloc interface - (void)pMalloc->Release(); - } - } - myHwnd = NULL; - - return bRet; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CBrowseForFolder::OnSelChanged(const LPITEMIDLIST pidl) const -{ - (void)pidl; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CBrowseForFolder::EnableOK(const bool bEnable) const -{ - if (myHwnd == NULL) - return; - - // (void)SendMessage(myHwnd, BFFM_ENABLEOK, static_cast(bEnable), NULL); - (void)SendMessage( myHwnd, BFFM_ENABLEOK, NULL, static_cast(bEnable) ); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CBrowseForFolder::SetSelection(const LPITEMIDLIST pidl) const -{ - if (myHwnd == NULL) - return; - - (void)SendMessage(myHwnd, BFFM_SETSELECTION, FALSE, reinterpret_cast(pidl)); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CBrowseForFolder::SetSelection(LPCTSTR strPath) const -{ - if (myHwnd == NULL) - return; - - (void)SendMessage(myHwnd, BFFM_SETSELECTION, TRUE, reinterpret_cast(strPath)); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -int __stdcall CBrowseForFolder::BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData) -{ - CBrowseForFolder* pbff = reinterpret_cast( lpData ); - pbff->myHwnd = hwnd; - - if (uMsg == BFFM_SELCHANGED) - pbff->OnSelChanged( reinterpret_cast( lParam )); - - return 0; -} diff --git a/stella/src/win32/StellaX/BrowseForFolder.hxx b/stella/src/win32/StellaX/BrowseForFolder.hxx deleted file mode 100644 index f6160ca2a..000000000 --- a/stella/src/win32/StellaX/BrowseForFolder.hxx +++ /dev/null @@ -1,74 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll XX XX -// SS SS tt ll ll XX XX -// SS tttttt eeee ll ll aaaa XX XX -// SSSS tt ee ee ll ll aa XXX -// SS tt eeeeee ll ll aaaaa XX XX -// SS SS tt ee ll ll aa aa XX XX -// SSSS ttt eeeee llll llll aaaaa XX XX -// -// Copyright (c) 1995-2000 by Jeff Miller -// Copyright (c) 2004 by Stephen Anthony -// -// See the file "license" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -// -// $Id: BrowseForFolder.hxx,v 1.4 2004-07-15 03:03:27 stephena Exp $ -//============================================================================ - -#ifndef BROWSE_FOR_FOLDER_HXX -#define BROWSE_FOR_FOLDER_HXX - -#include - -class CBrowseForFolder -{ - public: - CBrowseForFolder(const HWND hParent = NULL, - const LPITEMIDLIST pidl = NULL, - LPCTSTR strTitle = NULL ); - - virtual ~CBrowseForFolder(); - - public: - // Call GetSelectedFolder to retrieve the folder selected by the user. - LPCTSTR GetSelectedFolder() const; - - // Call SelectFolder to display the dialog and get a selection from the user. Use - // GetSelectedFolder and GetImage to get the results of the dialog. - bool SelectFolder(); - - protected: - // OnSelChanged is called whenever the user selects a different directory. pidl is - // the LPITEMIDLIST of the new selection. Use SHGetPathFromIDList to retrieve the - // path of the selection. - virtual void OnSelChanged(const LPITEMIDLIST pidl) const; - - // Call EnableOK to enable the OK button on the active dialog. If bEnable is true - // then the button is enabled, otherwise it is disabled. - // NOTE -- This function should only be called within overrides of OnInit and - // OnSelChanged. - void EnableOK(const bool bEnable) const; - - // Call SetSelection to set the selection in the active dialog. pidl is the - // LPITEMIDLIST - // of the path to be selected. strPath is a CString containing the path to be - // selected. - // NOTE -- This function should only be called within overrides of OnInit and - // OnSelChanged. - void SetSelection(const LPITEMIDLIST pidl) const; - void SetSelection(LPCTSTR strPath) const; - - private: - static int __stdcall BrowseCallbackProc(HWND hwnd, - UINT uMsg, - LPARAM lParam, - LPARAM lpData); - - BROWSEINFO myBrowseInfo; - char mySelected[MAX_PATH]; - HWND myHwnd; -}; - -#endif diff --git a/stella/src/win32/StellaX/ConfigPage.cxx b/stella/src/win32/StellaX/ConfigPage.cxx deleted file mode 100644 index eff373692..000000000 --- a/stella/src/win32/StellaX/ConfigPage.cxx +++ /dev/null @@ -1,260 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll XX XX -// SS SS tt ll ll XX XX -// SS tttttt eeee ll ll aaaa XX XX -// SSSS tt ee ee ll ll aa XXX -// SS tt eeeeee ll ll aaaaa XX XX -// SS SS tt ee ll ll aa aa XX XX -// SSSS ttt eeeee llll llll aaaaa XX XX -// -// Copyright (c) 1995-2000 by Jeff Miller -// Copyright (c) 2004 by Stephen Anthony -// -// See the file "license" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -// -// $Id: ConfigPage.cxx,v 1.5 2004-07-15 03:03:27 stephena Exp $ -//============================================================================ - -#include "pch.hxx" -#include "ConfigPage.hxx" -#include "resource.h" -#include "BrowseForFolder.hxx" - -#include "bspf.hxx" -#include "Settings.hxx" - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -CConfigPage::CConfigPage( CGlobalData& rGlobalData ) - : myGlobalData( rGlobalData ), - CPropertyPage( IDD_CONFIG_PAGE ) -{ -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -BOOL CConfigPage::OnInitDialog( HWND hwnd ) -{ - m_hwnd = hwnd; - HWND hwndCtrl; - - // Reload settings just in case the emulation changed them - myGlobalData.settings().loadConfig(); - - // Get romdir - hwndCtrl = GetDlgItem( hwnd, IDC_ROMPATH ); - SendMessage( hwndCtrl, EM_LIMITTEXT, MAX_PATH, 0 ); - SetWindowText( hwndCtrl, myGlobalData.settings().getString("romdir").c_str() ); - - // Get ssname - int ssname = 0; - hwndCtrl = GetDlgItem( hwnd, IDC_SNAPSHOT_TYPE ); - SendMessage( hwndCtrl, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)"ROM Name" ); - SendMessage( hwndCtrl, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)"ROM MD5" ); - if(myGlobalData.settings().getString("ssname") == "romname") - ssname = 0; - else if(myGlobalData.settings().getString("ssname") == "md5sum") - ssname = 1; - SendMessage( hwndCtrl, CB_SETCURSEL, ssname, 0 ); - - // Get sssingle - hwndCtrl = GetDlgItem( hwnd, IDC_SNAPSHOT_MULTIPLE ); - SendMessage( hwndCtrl, BM_SETCHECK, - myGlobalData.settings().getBool("sssingle") - ? BST_UNCHECKED : BST_CHECKED, 0 ); - - // Get paddle - hwndCtrl = GetDlgItem( hwnd, IDC_PADDLE ); - TCHAR psz[4] = _T("0"); - TCHAR i; - for ( i = 0; i < 4; ++i ) - { - psz[0] = _T('0') + i; - SendMessage( hwndCtrl, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)psz ); - } - SendMessage( hwndCtrl, CB_SETCURSEL, myGlobalData.settings().getInt("paddle"), 0 ); - - // Get video - int videomode = 0; - hwndCtrl = GetDlgItem( hwnd, IDC_VIDEO ); - SendMessage( hwndCtrl, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)"Software" ); - SendMessage( hwndCtrl, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)"OpenGL" ); - if(myGlobalData.settings().getString("video") == "soft") - videomode = 0; - else if(myGlobalData.settings().getString("video") == "gl") - videomode = 1; - SendMessage( hwndCtrl, CB_SETCURSEL, videomode, 0 ); - - // Get gl_aspect - hwndCtrl = GetDlgItem( hwnd, IDC_GL_ASPECT ); - SendMessage( hwndCtrl, EM_LIMITTEXT, MAX_PATH, 0 ); - SetWindowText( hwndCtrl, myGlobalData.settings().getString("gl_aspect").c_str() ); - - // Get gl_fsmax - hwndCtrl = GetDlgItem( hwnd, IDC_GL_FSMAX ); - SendMessage( hwndCtrl, BM_SETCHECK, - myGlobalData.settings().getBool("gl_fsmax") - ? BST_CHECKED : BST_UNCHECKED, 0 ); - - // Get volume -// hwndCtrl = GetDlgItem( hwnd, IDC_SOUND_VOLUME_SPIN ); -// CSpinButtonCtrl spin = (CSpinButtonCtrl) hwndCtrl; - hwndCtrl = GetDlgItem( hwnd, IDC_SOUND_VOLUME ); - SendMessage( hwndCtrl, EM_LIMITTEXT, MAX_PATH, 0 ); - SetWindowText( hwndCtrl, myGlobalData.settings().getString("volume").c_str() ); - - // Get fragsize - int fragindex = 2, fragsize = 2048; - hwndCtrl = GetDlgItem( hwnd, IDC_SOUND_FRAGSIZE ); - SendMessage( hwndCtrl, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)"512" ); - SendMessage( hwndCtrl, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)"1024" ); - SendMessage( hwndCtrl, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)"2048" ); - SendMessage( hwndCtrl, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)"4096" ); - fragsize = myGlobalData.settings().getInt("fragsize"); - if(fragsize == 512) - fragindex = 0; - else if(fragsize == 1024) - fragindex = 1; - else if(fragsize == 2048) - fragindex = 2; - else if(fragsize == 4096) - fragindex = 3; - SendMessage( hwndCtrl, CB_SETCURSEL, fragindex, 0 ); - - // Get sound - hwndCtrl = GetDlgItem( hwnd, IDC_SOUND_ENABLE ); - SendMessage( hwndCtrl, BM_SETCHECK, - myGlobalData.settings().getBool("sound") - ? BST_UNCHECKED : BST_CHECKED, 0 ); - - return TRUE; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CConfigPage::OnDestroy( void ) -{ -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -LONG CConfigPage::OnApply( LPPSHNOTIFY lppsn ) -{ - UNUSED_ALWAYS( lppsn ); - - HWND hwndCtrl; - TCHAR buffer[ MAX_PATH ]; - string str; - int i; - bool b; - - // Set romdir - hwndCtrl = GetDlgItem( m_hwnd, IDC_ROMPATH ); - ASSERT( hwndCtrl ); - GetWindowText( hwndCtrl, buffer, MAX_PATH ); - myGlobalData.settings().setString( "romdir", buffer ); - - // Set ssname - hwndCtrl = GetDlgItem( m_hwnd, IDC_SNAPSHOT_TYPE ); - ASSERT( hwndCtrl ); - i = SendMessage( hwndCtrl, CB_GETCURSEL, 0, 0 ); - if( i == 0 ) - str = "romname"; - else if( i == 1 ) - str = "md5sum"; - else - str = "romname"; - myGlobalData.settings().setString( "ssname", str ); - - // Set sssingle - hwndCtrl = GetDlgItem( m_hwnd, IDC_SNAPSHOT_MULTIPLE ); - ASSERT( hwndCtrl ); - if( SendMessage( hwndCtrl, BM_GETCHECK, 0, 0 ) == BST_CHECKED ) - b = false; - else - b = true; - myGlobalData.settings().setBool( "sssingle", b ); - - // Set paddle - hwndCtrl = GetDlgItem( m_hwnd, IDC_PADDLE ); - ASSERT( hwndCtrl ); - myGlobalData.settings().setInt( "paddle", - SendMessage( hwndCtrl, CB_GETCURSEL, 0, 0 ) ); - - // Set video - hwndCtrl = GetDlgItem( m_hwnd, IDC_VIDEO ); - ASSERT( hwndCtrl ); - i = ::SendMessage( hwndCtrl, CB_GETCURSEL, 0, 0 ); - if( i == 0 ) - str = "soft"; - else if( i == 1 ) - str = "gl"; - else - str = "soft"; - myGlobalData.settings().setString( "video", str ); - - // Set gl_aspect - hwndCtrl = GetDlgItem( m_hwnd, IDC_GL_ASPECT ); - ASSERT( hwndCtrl ); - GetWindowText( hwndCtrl, buffer, MAX_PATH ); - myGlobalData.settings().setString( "gl_aspect", buffer ); - - // Set gl_fsmax - hwndCtrl = GetDlgItem( m_hwnd, IDC_GL_FSMAX ); - ASSERT( hwndCtrl ); - if( SendMessage( hwndCtrl, BM_GETCHECK, 0, 0 ) == BST_CHECKED ) - b = true; - else - b = false; - myGlobalData.settings().setBool( "gl_fsmax", b ); - - // Set volume - hwndCtrl = GetDlgItem( m_hwnd, IDC_SOUND_VOLUME ); - ASSERT( hwndCtrl ); - GetWindowText( hwndCtrl, buffer, MAX_PATH ); - myGlobalData.settings().setString( "volume", buffer ); - - // Set fragsize - hwndCtrl = GetDlgItem( m_hwnd, IDC_SOUND_FRAGSIZE ); - ASSERT( hwndCtrl ); - i = SendMessage( hwndCtrl, CB_GETCURSEL, 0, 0 ); - if( i == 0 ) - str = "512"; - else if( i == 1 ) - str = "1024"; - else if( i == 2 ) - str = "2048"; - else if( i == 3 ) - str = "4096"; - else - str = "2048"; - myGlobalData.settings().setString( "fragsize", str ); - - // Set sound - hwndCtrl = GetDlgItem( m_hwnd, IDC_SOUND_ENABLE ); - ASSERT( hwndCtrl ); - if( SendMessage( hwndCtrl, BM_GETCHECK, 0, 0 ) == BST_CHECKED ) - b = false; - else - b = true; - myGlobalData.settings().setBool( "sound", b ); - - // Finally, save the config file - myGlobalData.settings().saveConfig(); - - return PSNRET_NOERROR; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -BOOL CConfigPage::OnCommand( WORD wNotifyCode, WORD wID, HWND hwndCtl ) -{ - UNUSED_ALWAYS( wNotifyCode ); - UNUSED_ALWAYS( hwndCtl ); - - if ( wID == IDC_BROWSE ) - { - CBrowseForFolder bff( m_hwnd, NULL, "Open ROM Folder " ); - if ( bff.SelectFolder() ) - SetDlgItemText( m_hwnd, IDC_ROMPATH, bff.GetSelectedFolder() ); - } - - return FALSE; -} diff --git a/stella/src/win32/StellaX/ConfigPage.hxx b/stella/src/win32/StellaX/ConfigPage.hxx deleted file mode 100644 index ca165fc9f..000000000 --- a/stella/src/win32/StellaX/ConfigPage.hxx +++ /dev/null @@ -1,46 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll XX XX -// SS SS tt ll ll XX XX -// SS tttttt eeee ll ll aaaa XX XX -// SSSS tt ee ee ll ll aa XXX -// SS tt eeeeee ll ll aaaaa XX XX -// SS SS tt ee ll ll aa aa XX XX -// SSSS ttt eeeee llll llll aaaaa XX XX -// -// Copyright (c) 1995-2000 by Jeff Miller -// Copyright (c) 2004 by Stephen Anthony -// -// See the file "license" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -// -// $Id: ConfigPage.hxx,v 1.2 2004-07-15 03:03:27 stephena Exp $ -//============================================================================ - -#ifndef CONFIG_PAGE_HXX -#define CONFIG_PAGE_HXX - -#include "PropertySheet.hxx" -#include "GlobalData.hxx" - -class CConfigPage : public CPropertyPage -{ - public: - CConfigPage( CGlobalData& rGlobalData ); - - protected: - virtual BOOL OnInitDialog( HWND hwnd ); - virtual void OnDestroy(); - virtual LONG OnApply( LPPSHNOTIFY lppsn ); - - virtual BOOL OnCommand( WORD /* wNotifyCode */, WORD /* wID */, HWND /* hwndCtl */ ); - - private: - CGlobalData& myGlobalData; - HWND m_hwnd; - - CConfigPage( const CConfigPage& ); // no implementation - void operator=( const CConfigPage& ); // no implementation -}; - -#endif diff --git a/stella/src/win32/StellaX/CoolCaption.cxx b/stella/src/win32/StellaX/CoolCaption.cxx deleted file mode 100644 index d1bf606f0..000000000 --- a/stella/src/win32/StellaX/CoolCaption.cxx +++ /dev/null @@ -1,249 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll XX XX -// SS SS tt ll ll XX XX -// SS tttttt eeee ll ll aaaa XX XX -// SSSS tt ee ee ll ll aa XXX -// SS tt eeeeee ll ll aaaaa XX XX -// SS SS tt ee ll ll aa aa XX XX -// SSSS ttt eeeee llll llll aaaaa XX XX -// -// Copyright (c) 1995-2000 by Jeff Miller -// Copyright (c) 2004 by Stephen Anthony -// -// See the file "license" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -// -// $Id: CoolCaption.cxx,v 1.2 2004-07-15 03:03:27 stephena Exp $ -//============================================================================ - -#include "pch.hxx" -#include "CoolCaption.hxx" - -// MAKE SURE STYLE IS JUST "TITLE BAR" ! - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -CCoolCaption::CCoolCaption() - : m_hfont( NULL ), - m_tszCaption( NULL ), - m_fIsActive( FALSE ), - m_hDlg( NULL ) -{ -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CCoolCaption::OnInitDialog( HWND hDlg ) -{ - m_hDlg = hDlg; - CalculateNCArea(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CCoolCaption::OnDestroy( void ) -{ - if ( m_hDlg == NULL ) - return; - - if ( m_hfont ) - DeleteObject( m_hfont ); - - delete[] m_tszCaption; - m_tszCaption = NULL; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CCoolCaption::CalculateNCArea() -{ - if ( m_hDlg == NULL ) - return; - - GetWindowRect(m_hDlg, &m_rcWindow); - m_cxWindow = (m_rcWindow.right - m_rcWindow.left); - m_cyWindow = (m_rcWindow.bottom - m_rcWindow.top); - - m_cxFrame = ::GetSystemMetrics(SM_CXFRAME); - m_cyFrame = ::GetSystemMetrics(SM_CYFRAME); - - m_cxButtonSize = ::GetSystemMetrics(SM_CXSIZE); - - const int cyCaption = ::GetSystemMetrics(SM_CYCAPTION); - - // This is the size of the caption - SetRect(&m_rcCaption, 0, 0, m_cxWindow, cyCaption + m_cyFrame); - - // calculate position of buttons - SetRect(&m_rcClose, - m_cxWindow - m_cxFrame - m_cxButtonSize + 1, - m_rcCaption.top + m_cyFrame + 1, - m_cxWindow - m_cxFrame - 1, - m_rcCaption.bottom - m_cyFrame - ); - - CopyRect(&m_rcMin, &m_rcClose); - OffsetRect(&m_rcMin, -(m_cxButtonSize-2), 0); - - // figure out union of all buttons - RECT rcButtons; - UnionRect(&rcButtons, &m_rcClose, &m_rcMin); - - SetRect(&m_rcTextArea, m_cxFrame, m_rcCaption.top+m_cyFrame, - rcButtons.left-m_cxFrame, m_rcCaption.bottom-m_cyFrame); - - // Make bold caption font - m_hfont = (HFONT)SendMessage(m_hDlg, WM_GETFONT, 0, 0); - LOGFONT lf; - GetObject(m_hfont, sizeof(lf), &lf); - lf.lfWeight = FW_BOLD; - m_hfont = CreateFontIndirect(&lf); - - // Get caption text - int nCaptionLength = GetWindowTextLength(m_hDlg); - m_tszCaption = new TCHAR[nCaptionLength + 2]; - GetWindowText(m_hDlg, m_tszCaption, nCaptionLength+1); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CCoolCaption::OnNcPaint( HRGN hrgn ) -{ - UNUSED_ALWAYS( hrgn ); - - if ( m_hDlg == NULL ) - return; - - HDC hdc = GetWindowDC(m_hDlg); - - // Fill in the NC area with the proper color - HPEN hpen, hpenOld; - - hpen = CreatePen(PS_SOLID, 1, m_fIsActive ? - GetSysColor(COLOR_ACTIVECAPTION) : \ - GetSysColor(COLOR_INACTIVECAPTION)); - hpenOld = (HPEN)SelectObject(hdc, hpen); - - for (long x = 0; x < m_cxWindow; ++x) - { - if (x < m_cxFrame-1 || x > m_cxWindow-m_cxFrame) - { - // left, right must go from top to bottom - MoveToEx(hdc, x, 0, NULL); - LineTo(hdc, x, m_rcWindow.bottom); - } - else - { - // otherwise just do top and bottom - MoveToEx(hdc, x, 0, NULL); - LineTo(hdc, x, m_rcCaption.bottom); - - MoveToEx(hdc, x, m_cyWindow-m_cyFrame, NULL); - LineTo(hdc, x, m_cyWindow); - } - } - - SelectObject(hdc, hpenOld); - DeleteObject(hpen); - - // Draw the close button - DrawFrameControl(hdc, &m_rcClose, DFC_CAPTION, DFCS_CAPTIONCLOSE); - - // draw the minimize button - DrawFrameControl(hdc, &m_rcMin, DFC_CAPTION, DFCS_CAPTIONMIN); - - // Draw the caption text - SetTextColor(hdc, m_fIsActive ? GetSysColor(COLOR_CAPTIONTEXT) : \ - GetSysColor(COLOR_INACTIVECAPTIONTEXT)); - SetBkMode(hdc, TRANSPARENT); - - HFONT hfontOld = (HFONT)SelectObject(hdc, m_hfont); - - // calculate width / height of text - SIZE sizeText; - GetTextExtentPoint(hdc, m_tszCaption, lstrlen(m_tszCaption), &sizeText); - - DrawText(hdc, m_tszCaption, -1, &m_rcTextArea, - DT_END_ELLIPSIS | DT_EXTERNALLEADING | - DT_NOPREFIX | DT_SINGLELINE | DT_VCENTER); - - SelectObject(hdc, hfontOld); - - // Draw the docking grippers - const int nTextRight = m_rcTextArea.left + sizeText.cx + m_cxFrame; - - // right top - COLORREF cr3dHilight = GetSysColor(COLOR_3DHILIGHT); - COLORREF cr3dShadow = GetSysColor(COLOR_3DSHADOW); - - Draw3dRect(hdc, nTextRight+m_cxFrame, 8, - m_rcTextArea.right-(nTextRight+m_cxFrame), 3, - cr3dHilight, cr3dShadow); - - // right bottom - Draw3dRect(hdc, nTextRight+m_cxFrame, 12, - m_rcTextArea.right-(nTextRight+m_cxFrame), 3, - cr3dHilight, cr3dShadow); - - ReleaseDC(m_hDlg, hdc); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CCoolCaption::OnNcActivate( BOOL fActive ) -{ - if (m_hDlg == NULL) - return; - - m_fIsActive = fActive; - - // This fixes a problem where alt-tab wont repaint the NC area - RedrawWindow(m_hDlg, NULL, NULL, - RDW_INVALIDATE | RDW_FRAME | RDW_UPDATENOW | RDW_ERASE); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -BOOL CCoolCaption::OnNCLButtonDown( INT nHitTest, POINTS pts ) -{ - UNUSED_ALWAYS( nHitTest ); - - if ( m_hDlg == NULL ) - return FALSE; - - // Get the point in client units - RECT rcWindow; - GetWindowRect(m_hDlg, &rcWindow); - - POINT pt = { pts.x, pts.y }; - pt.x -= rcWindow.left; - pt.y -= rcWindow.top; - - if (PtInRect(&m_rcClose, pt)) - { - SendMessage(m_hDlg, WM_CLOSE, 0, 0); - return TRUE; - } - - if (PtInRect(&m_rcMin, pt)) - { - ShowWindow(m_hDlg, SW_MINIMIZE); - return TRUE; - } - - return FALSE; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CCoolCaption::FillSolidRect( HDC hdc, int x, int y, int cx, int cy, - COLORREF clr ) -{ - COLORREF cr = SetBkColor(hdc, clr); - RECT rect = { x, y, x+cx, y+cy }; - ExtTextOut(hdc, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL); - SetBkColor(hdc, cr); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CCoolCaption::Draw3dRect( HDC hdc, int x, int y, int cx, int cy, - COLORREF clrTopLeft, COLORREF clrBottomRight ) -{ - FillSolidRect(hdc, x, y, cx - 1, 1, clrTopLeft); - FillSolidRect(hdc, x, y, 1, cy - 1, clrTopLeft); - FillSolidRect(hdc, x + cx, y, -1, cy, clrBottomRight); - FillSolidRect(hdc, x, y + cy, cx, -1, clrBottomRight); -} diff --git a/stella/src/win32/StellaX/CoolCaption.hxx b/stella/src/win32/StellaX/CoolCaption.hxx deleted file mode 100644 index 9757143e5..000000000 --- a/stella/src/win32/StellaX/CoolCaption.hxx +++ /dev/null @@ -1,62 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll XX XX -// SS SS tt ll ll XX XX -// SS tttttt eeee ll ll aaaa XX XX -// SSSS tt ee ee ll ll aa XXX -// SS tt eeeeee ll ll aaaaa XX XX -// SS SS tt ee ll ll aa aa XX XX -// SSSS ttt eeeee llll llll aaaaa XX XX -// -// Copyright (c) 1995-2000 by Jeff Miller -// Copyright (c) 2004 by Stephen Anthony -// -// See the file "license" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -// -// $Id: CoolCaption.hxx,v 1.2 2004-07-15 03:03:27 stephena Exp $ -//============================================================================ - -#ifndef COOL_CAPTION_HXX -#define COOL_CAPTION_HXX - -class CCoolCaption -{ - public: - CCoolCaption(); - - void OnInitDialog(HWND hDlg); - void OnDestroy(); - - void OnNcPaint(HRGN); - void OnNcActivate(BOOL); - BOOL OnNCLButtonDown(INT, POINTS); - - protected: - HWND m_hDlg; - - private: - void CalculateNCArea(void); - void FillSolidRect(HDC hdc, int x, int y, int cx, int cy, COLORREF clr); - void Draw3dRect(HDC hdc, int x, int y, int cx, int cy, - COLORREF clrTopLeft, COLORREF clrBottomRight); - - BOOL m_fIsActive; - RECT m_rcWindow; - int m_cxWindow; - int m_cyWindow; - int m_cxFrame; - int m_cyFrame; - int m_cxButtonSize; - RECT m_rcClose; - RECT m_rcMin; - RECT m_rcCaption; - RECT m_rcTextArea; - HFONT m_hfont; - LPTSTR m_tszCaption; - - CCoolCaption( const CCoolCaption& ); // no implementation - void operator=( const CCoolCaption& ); // no implementation -}; - -#endif diff --git a/stella/src/win32/StellaX/FileDialog.cxx b/stella/src/win32/StellaX/FileDialog.cxx deleted file mode 100644 index 663a02804..000000000 --- a/stella/src/win32/StellaX/FileDialog.cxx +++ /dev/null @@ -1,69 +0,0 @@ -// -// StellaX -// Jeff Miller 05/01/2000 -// -#include "pch.hxx" -#include "FileDialog.hxx" - -CFileDialog::CFileDialog( - BOOL bOpenFileDialog, // TRUE for FileOpen, FALSE for FileSaveAs - LPCTSTR lpszDefExt /* = NULL */, - LPCTSTR lpszFileName /* = NULL */, - DWORD dwFlags /* = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT */, - LPCTSTR lpszFilter /* = NULL */, - HWND hwndParent /* = NULL */ - ) -{ - UNUSED_ALWAYS( hwndParent ); - - memset(&m_ofn, 0, sizeof(m_ofn)); // initialize structure to 0/NULL - m_szFileName[0] = '\0'; - m_szFileTitle[0] = '\0'; - - m_bOpenFileDialog = bOpenFileDialog; - - m_ofn.lStructSize = sizeof(m_ofn); - m_ofn.lpstrFile = m_szFileName; - m_ofn.nMaxFile = _countof(m_szFileName); - m_ofn.lpstrDefExt = lpszDefExt; - m_ofn.lpstrFileTitle = (LPTSTR)m_szFileTitle; - m_ofn.nMaxFileTitle = _countof(m_szFileTitle); - m_ofn.Flags = (dwFlags | OFN_EXPLORER); - m_ofn.hInstance = NULL; - - // setup initial file name - if (lpszFileName != NULL) - lstrcpyn(m_szFileName, lpszFileName, _countof(m_szFileName)); - - // Translate filter into commdlg format (lots of \0) - if (lpszFilter != NULL) - { - lstrcpy(m_szFilter, lpszFilter); - LPTSTR pch = m_szFilter; // modify the buffer in place - // MFC delimits with '|' not '\0' - while ((pch = _tcschr(pch, '|')) != NULL) - *pch++ = '\0'; - m_ofn.lpstrFilter = m_szFilter; - // do not call ReleaseBuffer() since the string contains '\0' characters - } -} - -int CFileDialog::DoModal( - void - ) -{ - int nResult; - - if (m_bOpenFileDialog) - { - nResult = ::GetOpenFileName(&m_ofn); - } - else - { - nResult = ::GetSaveFileName(&m_ofn); - } - - return nResult ? nResult : IDCANCEL; -} - - diff --git a/stella/src/win32/StellaX/FileDialog.hxx b/stella/src/win32/StellaX/FileDialog.hxx deleted file mode 100644 index 65dcb4fd7..000000000 --- a/stella/src/win32/StellaX/FileDialog.hxx +++ /dev/null @@ -1,51 +0,0 @@ -// -// StellaX -// Jeff Miller 05/01/2000 -// -#ifndef FILEDLG_H -#define FILEDLG_H -#pragma once - -class CFileDialog -{ -public: - - OPENFILENAME m_ofn; - - CFileDialog(BOOL bOpenFileDialog, // TRUE for FileOpen, FALSE for FileSaveAs - LPCTSTR lpszDefExt = NULL, - LPCTSTR lpszFileName = NULL, - DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, - LPCTSTR lpszFilter = NULL, - HWND hwndParent = NULL); - - virtual int DoModal(); - - LPCTSTR GetPathName() const - { - return m_ofn.lpstrFile; - } - - LPCTSTR GetFileName() const - { - return m_ofn.lpstrFileTitle; - } - -protected: - - BOOL m_bOpenFileDialog; // TRUE for file open, FALSE for file save - - TCHAR m_szFilter[1024]; // filter string - // separate fields with '|', terminate with '||\0' - - TCHAR m_szFileTitle[64]; // contains file title after return - TCHAR m_szFileName[_MAX_PATH]; // contains full path name after return - -private: - - CFileDialog( const CFileDialog& ); // no implementation - void operator=( const CFileDialog& ); // no implementation - -}; - -#endif \ No newline at end of file diff --git a/stella/src/win32/StellaX/Game.cxx b/stella/src/win32/StellaX/Game.cxx deleted file mode 100755 index 04a764bf7..000000000 --- a/stella/src/win32/StellaX/Game.cxx +++ /dev/null @@ -1,37 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll XX XX -// SS SS tt ll ll XX XX -// SS tttttt eeee ll ll aaaa XX XX -// SSSS tt ee ee ll ll aa XXX -// SS tt eeeeee ll ll aaaaa XX XX -// SS SS tt ee ll ll aa aa XX XX -// SSSS ttt eeeee llll llll aaaaa XX XX -// -// Copyright (c) 1995-2000 by Jeff Miller -// Copyright (c) 2004 by Stephen Anthony -// -// See the file "license" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -// -// $Id: Game.cxx,v 1.2 2004-07-15 03:03:27 stephena Exp $ -//============================================================================ - -#include "Game.hxx" - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Game::Game( void ) -{ - _available = false; - _rom = " "; - _md5 = " "; - _name = " "; - _rarity = " "; - _manufacturer = " "; - _note = " "; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Game::~Game( void ) -{ -} diff --git a/stella/src/win32/StellaX/Game.hxx b/stella/src/win32/StellaX/Game.hxx deleted file mode 100755 index 04fa4adab..000000000 --- a/stella/src/win32/StellaX/Game.hxx +++ /dev/null @@ -1,77 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll XX XX -// SS SS tt ll ll XX XX -// SS tttttt eeee ll ll aaaa XX XX -// SSSS tt ee ee ll ll aa XXX -// SS tt eeeeee ll ll aaaaa XX XX -// SS SS tt ee ll ll aa aa XX XX -// SSSS ttt eeeee llll llll aaaaa XX XX -// -// Copyright (c) 1995-2000 by Jeff Miller -// Copyright (c) 2004 by Stephen Anthony -// -// See the file "license" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -// -// $Id: Game.hxx,v 1.2 2004-07-15 03:03:27 stephena Exp $ -//============================================================================ - -#ifndef GAME_HXX -#define GAME_HXX - -#include "bspf.hxx" - -/** Hold game info for an Atari2600 game. */ -class Game -{ - public: - Game( void ); - ~Game( void ); - - /** sets the rom of a game */ - void setAvailable( bool available ) { _available = available; } - /** returns the rom of a game */ - bool isAvailable( void ) { return _available; } - - /** sets the rom of a game */ - void setRom( const string& rom ) { _rom = rom; }; - /** returns the rom of a game */ - string rom( void ) const { return _rom; } - - /** sets the md5 sum of a game */ - void setMd5( const string& md5 ) { _md5 = md5; }; - /** returns the md5 sum of a game */ - string md5( void ) const { return _md5; } - - /** sets the name of a game */ - void setName( const string& name ) { _name = name; } - /** returns the name of a game */ - string name( void ) const { return _name; } - - /** sets the rarity of a game */ - void setRarity( const string& rarity ) { _rarity = rarity; } - /** returns the rarity of a game */ - string rarity( void ) const { return _rarity; } - - /** sets the manufacturer of a game */ - void setManufacturer( const string& manufacturer) { _manufacturer = manufacturer; } - /** returns the manufacturer of a game */ - string manufacturer( void ) const { return _manufacturer; } - - /** sets the note of a game */ - void setNote( const string& note ) { _note = note; } - /** returns the note of a game */ - string note( void ) const { return _note; } - - protected: - bool _available; - string _rom; - string _md5; - string _name; - string _rarity; - string _manufacturer; - string _note; -}; - -#endif diff --git a/stella/src/win32/StellaX/GlobalData.cxx b/stella/src/win32/StellaX/GlobalData.cxx deleted file mode 100644 index 4141f0acf..000000000 --- a/stella/src/win32/StellaX/GlobalData.cxx +++ /dev/null @@ -1,42 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll XX XX -// SS SS tt ll ll XX XX -// SS tttttt eeee ll ll aaaa XX XX -// SSSS tt ee ee ll ll aa XXX -// SS tt eeeeee ll ll aaaaa XX XX -// SS SS tt ee ll ll aa aa XX XX -// SSSS ttt eeeee llll llll aaaaa XX XX -// -// Copyright (c) 1995-2000 by Jeff Miller -// Copyright (c) 2004 by Stephen Anthony -// -// See the file "license" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -// -// $Id: GlobalData.cxx,v 1.4 2004-07-15 03:03:27 stephena Exp $ -//============================================================================ - -#include "pch.hxx" -#include "resource.h" - -#include "bspf.hxx" -#include "Settings.hxx" -#include "SettingsWin32.hxx" -#include "GlobalData.hxx" - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -CGlobalData::CGlobalData( HINSTANCE hInstance ) - : mySettings(0), - myInstance(hInstance) -{ - mySettings = new SettingsWin32(); - mySettings->loadConfig(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -CGlobalData::~CGlobalData() -{ - if(mySettings) - delete mySettings; -} diff --git a/stella/src/win32/StellaX/GlobalData.hxx b/stella/src/win32/StellaX/GlobalData.hxx deleted file mode 100644 index e35245fa8..000000000 --- a/stella/src/win32/StellaX/GlobalData.hxx +++ /dev/null @@ -1,56 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll XX XX -// SS SS tt ll ll XX XX -// SS tttttt eeee ll ll aaaa XX XX -// SSSS tt ee ee ll ll aa XXX -// SS tt eeeeee ll ll aaaaa XX XX -// SS SS tt ee ll ll aa aa XX XX -// SSSS ttt eeeee llll llll aaaaa XX XX -// -// Copyright (c) 1995-2000 by Jeff Miller -// Copyright (c) 2004 by Stephen Anthony -// -// See the file "license" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -// -// $Id: GlobalData.hxx,v 1.3 2004-07-15 03:03:27 stephena Exp $ -//============================================================================ - -#ifndef GLOBAL_DATA_HXX -#define GLOBAL_DATA_HXX - -#include "pch.hxx" -#include "bspf.hxx" - -class CConfigPage; -class Settings; - -class CGlobalData -{ - friend CConfigPage; - - public: - CGlobalData( HINSTANCE hInstance ); - ~CGlobalData( void ); - - HINSTANCE ModuleInstance( void ) const - { - return myInstance; - } - - Settings& settings( void ) - { - return *mySettings; - } - - private: - Settings* mySettings; - - HINSTANCE myInstance; - - CGlobalData( const CGlobalData& ); // no implementation - void operator=( const CGlobalData& ); // no implementation -}; - -#endif diff --git a/stella/src/win32/StellaX/HeaderCtrl.cxx b/stella/src/win32/StellaX/HeaderCtrl.cxx deleted file mode 100644 index bf92b1b45..000000000 --- a/stella/src/win32/StellaX/HeaderCtrl.cxx +++ /dev/null @@ -1,168 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll XX XX -// SS SS tt ll ll XX XX -// SS tttttt eeee ll ll aaaa XX XX -// SSSS tt ee ee ll ll aa XXX -// SS tt eeeeee ll ll aaaaa XX XX -// SS SS tt ee ll ll aa aa XX XX -// SSSS ttt eeeee llll llll aaaaa XX XX -// -// Copyright (c) 1995-2000 by Jeff Miller -// Copyright (c) 2004 by Stephen Anthony -// -// See the file "license" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -// -// $Id: HeaderCtrl.cxx,v 1.3 2004-07-15 03:03:27 stephena Exp $ -//============================================================================ - -#include "pch.hxx" -#include "HeaderCtrl.hxx" - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -CHeaderCtrl::CHeaderCtrl() - : m_nSortCol(0), - m_fSortAsc(TRUE) -{ -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -LRESULT CHeaderCtrl::WndProc( HWND hWnd, UINT msg, WPARAM wParam, - LPARAM lParam, BOOL& rfHandled ) -{ - switch ( msg ) - { - case WM_DRAWITEM: - rfHandled = TRUE; - OnDrawItem(hWnd, (UINT)wParam, (LPDRAWITEMSTRUCT)lParam); - return TRUE; - } - - return 0; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CHeaderCtrl::SetSortCol( int nCol, BOOL bAsc ) -{ - m_nSortCol = nCol; - m_fSortAsc = bAsc; - - // change this item to owner draw - HWND hwndHeader = ::GetDlgItem( *this, 0 ); - HDITEM hdi; - hdi.mask = HDI_FORMAT; - Header_GetItem(hwndHeader, nCol, &hdi); - hdi.fmt |= HDF_OWNERDRAW; - Header_SetItem(hwndHeader, nCol, &hdi); - - // repaint the header - InvalidateRect(hwndHeader, NULL, TRUE); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CHeaderCtrl::OnDrawItem( HWND hwnd, UINT idCtl, LPDRAWITEMSTRUCT lpdis ) -{ - UNUSED_ALWAYS( idCtl ); - HDC hdc = lpdis->hDC; - RECT rcLabel; - - CopyRect( &rcLabel, &(lpdis->rcItem) ); - - /* save the DC */ - int nSavedDC = ::SaveDC( hdc ); - - /* set clip region to column */ - HRGN hrgn = ::CreateRectRgnIndirect( &rcLabel ); - SelectObject( hdc, hrgn ); - DeleteObject( hrgn ); - - /* draw the background */ - FillRect( hdc, &rcLabel, ::GetSysColorBrush(COLOR_3DFACE) ); - - /* offset the label */ - SIZE size; - GetTextExtentPoint32( hdc, _T(" "), 1, &size ); - int nOffset = size.cx * 2; - - /* get the column text and format */ - TCHAR tszText[255 + 1]; - HDITEM hdi; - hdi.mask = HDI_TEXT | HDI_FORMAT; - hdi.pszText = tszText; - hdi.cchTextMax = 255; - Header_GetItem( GetDlgItem(hwnd, 0), lpdis->itemID, &hdi ); - - /* determine format for drawing label */ - UINT uFormat = DT_SINGLELINE | DT_NOPREFIX | DT_NOCLIP | DT_VCENTER | DT_END_ELLIPSIS; - - /* determine justification */ - if (hdi.fmt & HDF_CENTER) - uFormat |= DT_CENTER; - else if (hdi.fmt & HDF_RIGHT) - uFormat |= DT_RIGHT; - else - uFormat |= DT_LEFT; - - /* adjust the rect if selected */ - if (lpdis->itemState & ODS_SELECTED) - { - rcLabel.left++; - rcLabel.top += 2; - rcLabel.right++; - } - - /* adjust rect for sort arrow */ - if ( lpdis->itemID == m_nSortCol ) - rcLabel.right -= (3 * nOffset); - - rcLabel.left += nOffset; - rcLabel.right -= nOffset; - - /* draw label */ - if ( rcLabel.left < rcLabel.right ) - DrawText(hdc, tszText, -1, &rcLabel, uFormat ); - - /* draw the arrow */ - if ( lpdis->itemID == m_nSortCol ) - { - RECT rcIcon; - HPEN hpenLight, hpenShadow, hpenOld; - - CopyRect( &rcIcon, &(lpdis->rcItem) ); - - hpenLight = ::CreatePen( PS_SOLID, 1, GetSysColor(COLOR_3DHILIGHT) ); - hpenShadow = ::CreatePen( PS_SOLID, 1, GetSysColor(COLOR_3DSHADOW) ); - hpenOld = (HPEN)::SelectObject( hdc, hpenLight ); - - if (m_fSortAsc) - { - /* draw triangle pointing up */ - MoveToEx( hdc, rcIcon.right - 2 * nOffset, nOffset - 1, NULL ); - LineTo( hdc, rcIcon.right - 3 * nOffset / 2, rcIcon.bottom - nOffset ); - LineTo( hdc, rcIcon.right - 5 * nOffset / 2 - 2, rcIcon.bottom - nOffset ); - MoveToEx( hdc, rcIcon.right - 5 * nOffset / 2 - 1, rcIcon.bottom - nOffset, NULL ); - - SelectObject( hdc, hpenShadow ); - LineTo( hdc, rcIcon.right - 2 * nOffset, nOffset - 2 ); - } - else - { - /* draw triangle pointing down */ - MoveToEx( hdc, rcIcon.right - 3 * nOffset / 2, nOffset - 1, NULL ); - LineTo( hdc, rcIcon.right - 2 * nOffset - 1, rcIcon.bottom - nOffset ); - LineTo( hdc, rcIcon.right - 2 * nOffset - 1, rcIcon.bottom - nOffset ); - MoveToEx( hdc, rcIcon.right - 2 * nOffset - 1, rcIcon.bottom - nOffset, NULL ); - - SelectObject( hdc, hpenShadow ); - LineTo( hdc, rcIcon.right - 5 * nOffset / 2 - 1, nOffset - 1 ); - LineTo( hdc, rcIcon.right - 3 * nOffset / 2, nOffset - 1 ); - } - - SelectObject( hdc, hpenOld ); - DeleteObject( hpenShadow ); - DeleteObject( hpenLight ); - } - - RestoreDC( hdc, nSavedDC ); -} diff --git a/stella/src/win32/StellaX/HeaderCtrl.hxx b/stella/src/win32/StellaX/HeaderCtrl.hxx deleted file mode 100644 index e356d218f..000000000 --- a/stella/src/win32/StellaX/HeaderCtrl.hxx +++ /dev/null @@ -1,57 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll XX XX -// SS SS tt ll ll XX XX -// SS tttttt eeee ll ll aaaa XX XX -// SSSS tt ee ee ll ll aa XXX -// SS tt eeeeee ll ll aaaaa XX XX -// SS SS tt ee ll ll aa aa XX XX -// SSSS ttt eeeee llll llll aaaaa XX XX -// -// Copyright (c) 1995-2000 by Jeff Miller -// Copyright (c) 2004 by Stephen Anthony -// -// See the file "license" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -// -// $Id: HeaderCtrl.hxx,v 1.3 2004-07-15 03:03:27 stephena Exp $ -//============================================================================ - -#ifndef HEADER_CTRL_HXX -#define HEADER_CTRL_HXX - -#include "Wnd.hxx" - -class CHeaderCtrl : public CWnd -{ - public: - CHeaderCtrl(); - - void SetSortCol(int col, BOOL fAscending); - int GetSortCol(void) const; - BOOL GetSortAsc(void) const; - - protected: - LRESULT WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, BOOL& rfHandled); - - private: - void OnDrawItem(HWND hwnd, UINT idCtl, LPDRAWITEMSTRUCT lpdis); - - UINT m_nSortCol; - BOOL m_fSortAsc; - - CHeaderCtrl( const CHeaderCtrl& ); // no implementation - void operator=( const CHeaderCtrl& ); // no implementation -}; - -inline int CHeaderCtrl::GetSortCol( void ) const -{ - return m_nSortCol; -} - -inline BOOL CHeaderCtrl::GetSortAsc( void ) const -{ - return m_fSortAsc; -} - -#endif diff --git a/stella/src/win32/StellaX/HyperLink.cxx b/stella/src/win32/StellaX/HyperLink.cxx deleted file mode 100644 index 15be531bb..000000000 --- a/stella/src/win32/StellaX/HyperLink.cxx +++ /dev/null @@ -1,334 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll XX XX -// SS SS tt ll ll XX XX -// SS tttttt eeee ll ll aaaa XX XX -// SSSS tt ee ee ll ll aa XXX -// SS tt eeeeee ll ll aaaaa XX XX -// SS SS tt ee ll ll aa aa XX XX -// SSSS ttt eeeee llll llll aaaaa XX XX -// -// Copyright (c) 1995-2000 by Jeff Miller -// Copyright (c) 2004 by Stephen Anthony -// -// See the file "license" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -// -// $Id: HyperLink.cxx,v 1.2 2004-07-15 03:03:27 stephena Exp $ -//============================================================================ - -#include "pch.hxx" -#include "HyperLink.hxx" - -#include - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -CHyperLink::CHyperLink() - : m_bOverControl(FALSE), - m_bVisited(FALSE), - m_hFont(NULL), - m_hLinkCursor(NULL) -{ - m_crLinkColor = RGB( 0, 0, 238); // Blue - m_crVisitedColor = RGB( 85, 26, 139); // Purple - m_crHoverColor = ::GetSysColor(COLOR_HIGHLIGHT); - - SetDefaultCursor(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -CHyperLink::~CHyperLink() -{ - if (m_hFont) - { - DeleteObject( m_hFont ); - m_hFont = NULL; - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CHyperLink::SetURL( LPCTSTR ctszURL ) -{ - if (ctszURL == NULL) - return; - - lstrcpy(m_tszURL, ctszURL); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CHyperLink::PreSubclassWindow( HWND hwnd ) -{ - GetWindowText( hwnd, m_tszText, MAX_HYPERLINK_TEXT_LEN ); - m_hFont = (HFONT)::SendMessage(hwnd, WM_GETFONT, 0, 0); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -LRESULT CHyperLink::WndProc( HWND hwnd, UINT msg, WPARAM wParam, - LPARAM lParam, BOOL& rfHandled ) -{ - switch (msg) - { - case WM_PAINT: - rfHandled = TRUE; - return OnPaint(hwnd); - - case WM_SETCURSOR: - rfHandled = TRUE; - return OnSetCursor(hwnd, LOWORD(lParam), HIWORD(lParam)); - - case WM_LBUTTONUP: - rfHandled = TRUE; - return OnLButtonUp(hwnd, wParam, LOWORD(lParam), HIWORD(lParam)); - - case WM_MOUSEMOVE: - rfHandled = TRUE; - return OnMouseMove(hwnd, wParam, LOWORD(lParam), HIWORD(lParam)); - } - - return 0; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -LRESULT CHyperLink::OnPaint( HWND hwnd ) -{ - PAINTSTRUCT ps; - HDC hdc = BeginPaint(hwnd, &ps); - - SelectObject(hdc, m_hFont); - - if (m_bOverControl) - SetTextColor(hdc, m_crHoverColor); - else if (m_bVisited) - SetTextColor(hdc, m_crVisitedColor); - else - SetTextColor(hdc, m_crLinkColor); - - SetBkMode( hdc, TRANSPARENT ); - TextOut( hdc, 0, 0, m_tszText, lstrlen(m_tszText) ); - EndPaint(hwnd, &ps); - - return 0; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -BOOL CHyperLink::OnSetCursor( HWND hwnd, WORD nHittest, WORD wMouseMsg ) -{ - UNUSED_ALWAYS( hwnd ); - UNUSED_ALWAYS( nHittest ); - UNUSED_ALWAYS( wMouseMsg ); - - if (m_hLinkCursor) - { - SetCursor(m_hLinkCursor); - return TRUE; - } - - return FALSE; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -LRESULT CHyperLink::OnLButtonUp( HWND hwnd, WPARAM fwKeys, WORD xPos, WORD yPos ) -{ - UNUSED_ALWAYS( fwKeys ); - UNUSED_ALWAYS( xPos ); - UNUSED_ALWAYS( yPos ); - - int result = (int)GotoURL(m_tszURL, SW_SHOW); - m_bVisited = (result > HINSTANCE_ERROR); - if (!m_bVisited) - { - MessageBeep(MB_ICONEXCLAMATION); - ReportError(result); - } - else - { - m_bVisited = TRUE; - InvalidateRect(hwnd, NULL, FALSE); - } - - return 0; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -LRESULT CHyperLink::OnMouseMove( HWND hwnd, WPARAM fwKeys, WORD xPos, WORD yPos ) -{ - UNUSED_ALWAYS( fwKeys ); - - // call defwindowproc? - if (m_bOverControl) - { - RECT rc; - GetClientRect(hwnd, &rc); - - POINT pt = { xPos, yPos }; - if (!PtInRect(&rc, pt)) - { - m_bOverControl = FALSE; - ReleaseCapture(); - RedrawWindow(hwnd, NULL, NULL, - RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE); - } - } - else - { - m_bOverControl = TRUE; - RedrawWindow(hwnd, NULL, NULL, - RDW_INVALIDATE | RDW_UPDATENOW | RDW_ERASE); - SetCapture(hwnd); - } - - return 0; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// The following appeared in Paul DiLascia's Jan 1998 MSJ articles. -// It loads a "hand" cursor from the winhlp32.exe module -void CHyperLink::SetDefaultCursor() -{ - if (m_hLinkCursor == NULL) // No cursor handle - load our own - { - // Get the windows directory - TCHAR tszWndDir[MAX_PATH + 1]; - GetWindowsDirectory(tszWndDir, MAX_PATH); - - lstrcat(tszWndDir, _T("\\winhlp32.exe")); - - // This retrieves cursor #106 from winhlp32.exe, which is a hand pointer - HMODULE hModule = LoadLibrary(tszWndDir); - if (hModule) - { - HCURSOR hHandCursor = ::LoadCursor(hModule, MAKEINTRESOURCE(106)); - if (hHandCursor) - m_hLinkCursor = CopyCursor(hHandCursor); - } - FreeLibrary(hModule); - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -LONG CHyperLink::GetRegKey( HKEY key, LPCTSTR subkey, LPTSTR retdata ) -{ - HKEY hkey; - LONG retval = RegOpenKeyEx(key, subkey, 0, KEY_QUERY_VALUE, &hkey); - - if (retval == ERROR_SUCCESS) - { - long datasize = MAX_PATH; - TCHAR data[MAX_PATH]; - RegQueryValue(hkey, NULL, data, &datasize); - lstrcpy(retdata,data); - RegCloseKey(hkey); - } - - return retval; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CHyperLink::ReportError( int nError ) -{ - TCHAR tsz[MAX_HYPERLINK_TEXT_LEN + 1]; - - switch (nError) - { - case 0: - lstrcpy(tsz, _T("The operating system is out\nof memory or resources.")); - break; - - case SE_ERR_PNF: - lstrcpy(tsz, _T("The specified path was not found.")); - break; - - case SE_ERR_FNF: - lstrcpy(tsz, _T("The specified file was not found.")); - break; - - case ERROR_BAD_FORMAT: - lstrcpy(tsz, _T("The .EXE file is invalid\n(non-Win32 .EXE or error in .EXE image).")); - break; - - case SE_ERR_ACCESSDENIED: - lstrcpy(tsz, _T("The operating system denied\naccess to the specified file.")); - break; - - case SE_ERR_ASSOCINCOMPLETE: - lstrcpy(tsz,_T("The filename association is\nincomplete or invalid.")); - break; - - case SE_ERR_DDEBUSY: - lstrcpy(tsz, _T("The DDE transaction could not\nbe completed because other DDE transactions\nwere being processed.")); - break; - - case SE_ERR_DDEFAIL: - lstrcpy(tsz, _T("The DDE transaction failed.")); - break; - - case SE_ERR_DDETIMEOUT: - lstrcpy(tsz, _T("The DDE transaction could not\nbe completed because the request timed out.")); - break; - - case SE_ERR_DLLNOTFOUND: - lstrcpy(tsz, _T("The specified dynamic-link library was not found.")); - break; - - case SE_ERR_NOASSOC: - lstrcpy(tsz, __T("There is no application associated\nwith the given filename extension.")); - break; - - case SE_ERR_OOM: - lstrcpy(tsz, _T("There was not enough memory to complete the operation.")); - break; - - case SE_ERR_SHARE: - lstrcpy(tsz, _T("A sharing violation occurred.")); - break; - - default: - wsprintf(tsz, _T("Unknown error %d occurred."), nError); - break; - } - - TCHAR tszCaption[MAX_HYPERLINK_TEXT_LEN + 1]; - lstrcpy(tszCaption, _T("Unable to open hyperlink")); - - MessageBox(NULL, tsz, tszCaption, MB_ICONEXCLAMATION | MB_OK); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -HINSTANCE CHyperLink::GotoURL( LPCTSTR url, int showcmd ) -{ - TCHAR key[MAX_PATH + MAX_PATH]; - - // First try ShellExecute() - HINSTANCE result = ShellExecute(NULL, _T("open"), url, NULL,NULL, showcmd); - - // If it failed, get the .htm regkey and lookup the program - if ((UINT)result <= HINSTANCE_ERROR) - { - if (GetRegKey(HKEY_CLASSES_ROOT, _T(".htm"), key) == ERROR_SUCCESS) - { - lstrcat(key, _T("\\shell\\open\\command")); - - if (GetRegKey(HKEY_CLASSES_ROOT,key,key) == ERROR_SUCCESS) - { - TCHAR *pos; - pos = _tcsstr(key, _T("\"%1\"")); - if (pos == NULL) - { // No quotes found - pos = strstr(key, _T("%1")); // Check for %1, without quotes - if (pos == NULL) // No parameter at all... - pos = key+lstrlen(key)-1; - else - *pos = '\0'; // Remove the parameter - } - else - *pos = '\0'; // Remove the parameter - - lstrcat(pos, _T(" ")); - lstrcat(pos, url); - result = (HINSTANCE) WinExec(key,showcmd); - } - } - } - - return result; -} diff --git a/stella/src/win32/StellaX/HyperLink.hxx b/stella/src/win32/StellaX/HyperLink.hxx deleted file mode 100644 index 0a133bd73..000000000 --- a/stella/src/win32/StellaX/HyperLink.hxx +++ /dev/null @@ -1,76 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll XX XX -// SS SS tt ll ll XX XX -// SS tttttt eeee ll ll aaaa XX XX -// SSSS tt ee ee ll ll aa XXX -// SS tt eeeeee ll ll aaaaa XX XX -// SS SS tt ee ll ll aa aa XX XX -// SSSS ttt eeeee llll llll aaaaa XX XX -// -// Copyright (c) 1995-2000 by Jeff Miller -// Copyright (c) 2004 by Stephen Anthony -// -// See the file "license" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -// -// $Id: HyperLink.hxx,v 1.2 2004-07-15 03:03:27 stephena Exp $ -//============================================================================ - -#ifndef HYPER_LINK_HXX -#define HYPER_LINK_HXX - -#define MAX_HYPERLINK_TEXT_LEN 256 -#define MAX_HYPERLINK_URL 256 - -#include "Wnd.hxx" - -class CHyperLink : public CWnd -{ - public: - CHyperLink(); - ~CHyperLink(); - - void SetURL(LPCTSTR ctszURL); - - protected: - virtual void PreSubclassWindow(HWND hwnd); - virtual LRESULT WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, - BOOL& rfHandled); - - private: - void SetDefaultCursor(); - LONG GetRegKey(HKEY key, LPCTSTR subkey, LPTSTR retdata); - void ReportError(int nError); - HINSTANCE GotoURL(LPCTSTR url, int showcmd); - - static LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, - WPARAM wParam, LPARAM lParam); - - HBRUSH OnCtlColorStatic(HWND hwnd, HDC hdcStatic, HWND hwndStatic); - BOOL OnSetCursor(HWND hwnd, WORD nHittest, WORD wMouseMsg); - LRESULT OnPaint(HWND hwnd); - LRESULT OnLButtonUp(HWND, WPARAM, WORD, WORD); - LRESULT OnMouseMove(HWND, WPARAM, WORD, WORD); - - // Stuff from the control - TCHAR m_tszText[MAX_HYPERLINK_TEXT_LEN + 1]; - HFONT m_hFont; - - // link specific - COLORREF m_crLinkColor; - COLORREF m_crVisitedColor; - COLORREF m_crHoverColor; - - BOOL m_bOverControl; - BOOL m_bVisited; - - HCURSOR m_hLinkCursor; - - TCHAR m_tszURL[MAX_HYPERLINK_URL + 1]; - - CHyperLink( const CHyperLink& ); // no implementation - void operator=( const CHyperLink& ); // no implementation -}; - -#endif diff --git a/stella/src/win32/StellaX/MainDlg.cxx b/stella/src/win32/StellaX/MainDlg.cxx deleted file mode 100644 index fa0e46574..000000000 --- a/stella/src/win32/StellaX/MainDlg.cxx +++ /dev/null @@ -1,877 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll XX XX -// SS SS tt ll ll XX XX -// SS tttttt eeee ll ll aaaa XX XX -// SSSS tt ee ee ll ll aa XXX -// SS tt eeeeee ll ll aaaaa XX XX -// SS SS tt ee ll ll aa aa XX XX -// SSSS ttt eeeee llll llll aaaaa XX XX -// -// Copyright (c) 1995-2000 by Jeff Miller -// Copyright (c) 2004 by Stephen Anthony -// -// See the file "license" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -// -// $Id: MainDlg.cxx,v 1.7 2004-07-15 03:03:27 stephena Exp $ -//============================================================================ - -#include "pch.hxx" -#include "MainDlg.hxx" -#include "Game.hxx" -#include "GlobalData.hxx" -#include "PropertySheet.hxx" -#include "AboutPage.hxx" -#include "ConfigPage.hxx" -#include "resource.h" -#include "Settings.hxx" -#include "PropsSet.hxx" -#include "MD5.hxx" - -#define BKGND_BITMAP_TOP 64 -#define BKGND_BITMAP_BOTTOM 355 - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -MainDlg::MainDlg( CGlobalData& rGlobalData, HINSTANCE hInstance ) - : myGlobalData(rGlobalData), - myHInstance(hInstance) -{ -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -MainDlg::~MainDlg( void ) -{ - // Just to be safe, make sure we don't have a memory leak - ListView_Clear(); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -int MainDlg::DoModal( HWND hwndParent ) -{ - return DialogBoxParam( myHInstance, - MAKEINTRESOURCE(IDD), - hwndParent, - StaticDialogFunc, - (LPARAM)this ); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -BOOL CALLBACK -MainDlg::StaticDialogFunc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) -{ - MainDlg* pDlg; - - switch ( uMsg ) - { - case WM_INITDIALOG: - pDlg = reinterpret_cast( lParam ); - pDlg->myHwnd = hDlg; - (void)::SetWindowLong( hDlg, DWL_USER, reinterpret_cast( pDlg ) ); - break; - - default: - pDlg = reinterpret_cast( ::GetWindowLong( hDlg, DWL_USER ) ); - if ( pDlg == NULL ) - return FALSE; - break; - } - - return pDlg->DialogFunc( uMsg, wParam, lParam ); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -BOOL CALLBACK -MainDlg::DialogFunc( UINT uMsg, WPARAM wParam, LPARAM lParam ) -{ - BOOL b; - - switch (uMsg) - { - case WM_COMMAND: - return OnCommand( LOWORD(wParam), (HWND)lParam, HIWORD(wParam) ); - - case WM_CTLCOLORSTATIC: - b = (BOOL)OnCtlColorStatic( (HDC)wParam, (HWND)lParam ); - if (b) - return b; - break; - - case WM_ERASEBKGND: - if ( OnEraseBkgnd( (HDC)wParam ) ) - return TRUE; - break; - - case WM_INITDIALOG: - return OnInitDialog(); - - case WM_NOTIFY: - return OnNotify( (int)wParam, (LPNMHDR)lParam ); - - case WM_PALETTECHANGED: - TRACE( "WM_PALETTECHANGED from maindlg" ); - return FALSE; - - case WM_QUERYNEWPALETTE: - TRACE( "WM_QUERYNEWPALETTE from maindlg" ); - return FALSE; - - // Cool caption handlers - case WM_DESTROY: - OnDestroy(); - break; - - case WM_DRAWITEM: - // Forward this onto the control - ::SendMessage( ((LPDRAWITEMSTRUCT)lParam)->hwndItem, WM_DRAWITEM, wParam, lParam ); - return TRUE; - - case WM_NCPAINT: - // DefWindowProc(hDlg, uMsg, wParam, lParam); - OnNcPaint( (HRGN)wParam ); - return TRUE; - - case WM_NCACTIVATE: - OnNcActivate( (BOOL)wParam ); - // When the fActive parameter is FALSE, an application should return - // TRUE to indicate that the system should proceed with the default - // processing - SetWindowLong( myHwnd, DWL_MSGRESULT, TRUE ); - return TRUE; - - case WM_NCLBUTTONDOWN: - return OnNcLButtonDown( (INT)wParam, MAKEPOINTS(lParam) ); - - case WM_CLOSE: - Quit(); - break; - } - - // Message not handled - return FALSE; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -BOOL MainDlg::OnInitDialog( void ) -{ - DWORD dwRet; - - HWND hwnd = *this; - - // Set dialog icon - HICON hicon = ::LoadIcon(myHInstance, MAKEINTRESOURCE(IDI_APP)); - ::SendMessage( hwnd, WM_SETICON, ICON_BIG, (LPARAM)hicon ); - ::SendMessage( hwnd, WM_SETICON, ICON_SMALL, (LPARAM)hicon ); - - // Make the Rom note have bold text - HWND hwndCtrl; - hwndCtrl = ::GetDlgItem( hwnd, IDC_ROMNOTE ); - HFONT hfont = (HFONT)::SendMessage( hwndCtrl, WM_GETFONT, 0, 0 ); - - LOGFONT lf; - ::GetObject( hfont, sizeof(LOGFONT), &lf ); - lf.lfWeight = FW_BOLD; - - m_hfontRomNote = ::CreateFontIndirect( &lf ); - if ( m_hfontRomNote ) - ::SendMessage( hwndCtrl, WM_SETFONT, (WPARAM)m_hfontRomNote, 0 ); - - // Do subclassing - myCoolCaption.OnInitDialog( hwnd ); - myHeader.SubclassDlgItem( hwnd, IDC_ROMLIST ); - myAppTitle.SubclassDlgItem( hwnd, IDC_TITLE ); - myPlayButton.SubclassDlgItem( hwnd, IDC_PLAY ); - myReloadButton.SubclassDlgItem( hwnd, IDC_RELOAD ); - myHelpButton.SubclassDlgItem( hwnd, IDC_ABOUT ); - myConfigButton.SubclassDlgItem( hwnd, IDC_CONFIG ); - myExitButton.SubclassDlgItem( hwnd, IDC_EXIT ); - - const int nMaxString = 256; - TCHAR psz[nMaxString + 1]; - - // Initialize the list view - myHwndList = ::GetDlgItem( hwnd, IDC_ROMLIST ); - ASSERT( myHwndList ); - - // LVS_EX_ONECLICKACTIVATE was causing a/vs in kernel32 - ::SendMessage( myHwndList, LVM_SETEXTENDEDLISTVIEWSTYLE, - 0, LVS_EX_FULLROWSELECT ); - - RECT rc; - ::GetClientRect( myHwndList, &rc ); - - // Declare the column headings - int columnHeader[] = { IDS_NAME, IDS_MANUFACTURER, IDS_RARITY }; - - // Set the column widths - int columnWidth[3]; - columnWidth[0] = myGlobalData.settings().getInt("namecolwidth"); - columnWidth[1] = myGlobalData.settings().getInt("manufacturercolwidth"); - columnWidth[2] = myGlobalData.settings().getInt("raritycolwidth"); - - // Make sure there are sane values for the column widths - if (columnWidth[0] <= 0 || columnWidth[1] <= 0 || columnWidth[2] <= 0) - { - LONG lTotalWidth = rc.right-rc.left - GetSystemMetrics(SM_CXVSCROLL); - columnWidth[0] = (int) (0.58 * lTotalWidth); - columnWidth[1] = (int) (0.25 * lTotalWidth); - columnWidth[2] = lTotalWidth - columnWidth[0] - columnWidth[1]; - } - - // Set up the column headings - for (int i = 0; i < 3; ++i) - { - LoadString( myHInstance, columnHeader[i], psz, nMaxString ); - - LV_COLUMN lvc; - lvc.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH; - lvc.fmt = LVCFMT_LEFT; - lvc.cx = columnWidth[i]; - lvc.pszText = psz; - ListView_InsertColumn( myHwndList, i, &lvc ); - } - - // Update the ROM game list - UpdateRomList(); - - // Set default button - SendMessage( hwnd, DM_SETDEFID, IDC_PLAY, 0 ); - - // return FALSE if SetFocus is called - return TRUE; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -BOOL MainDlg::OnCommand( int id, HWND hwndCtl, UINT codeNotify ) -{ - UNUSED_ALWAYS( hwndCtl ); - UNUSED_ALWAYS( codeNotify ); - - HWND hwnd = *this; - Game* g; - string romfile; - int nItem; - - switch (id) - { - case IDC_PLAY: - nItem = (int)::SendMessage( myHwndList, LVM_GETNEXTITEM, - (WPARAM)-1, MAKELPARAM( LVNI_SELECTED, 0 ) ); - ASSERT( nItem != -1 ); - if ( nItem == -1 ) - { - MessageBox( myHInstance, hwnd, IDS_NO_ITEM_SELECTED ); - return TRUE; - } - - g = (Game*) ListView_GetItemData( myHwndList, nItem ); - romfile = myGlobalData.settings().getString("romdir") + "\\" + g->rom(); - (void)m_stella.PlayROM( romfile, myGlobalData ); - - // Set focus back to the rom list - SetFocus( myHwndList ); - - return TRUE; - break; // case IDC_PLAY - - case IDC_EXIT: - Quit(); - return TRUE; - break; // case IDC_EXIT - - case IDC_CONFIG: - { - CPropertySheet ps( _T("Configure"), hwnd ); - - CConfigPage pgConfig( myGlobalData ); - ps.AddPage( &pgConfig ); - - (void)ps.DoModal(); - - return TRUE; - break; // case IDC_CONFIG - } - - case IDC_ABOUT: - { - CPropertySheet ps(_T("Help"), hwnd); - - CHelpPage pgAbout; - ps.AddPage(&pgAbout); - - ps.DoModal(); - return TRUE; - break; // case IDC_ABOUT - } - - case IDC_RELOAD: - { - UpdateRomList( true ); - return TRUE; - break; // case IDC_RELOAD - } - } - - return FALSE; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -BOOL MainDlg::OnNotify( int idCtrl, LPNMHDR pnmh ) -{ - UNUSED_ALWAYS( idCtrl ); - - switch ( pnmh->code ) - { - case LVN_ITEMCHANGED: - OnItemChanged( (LPNMLISTVIEW)pnmh ); - return TRUE; - - case LVN_COLUMNCLICK: - OnColumnClick( (LPNMLISTVIEW)pnmh ); - return TRUE; - - case NM_DBLCLK: - // send out an ok click to play - SendDlgItemMessage( *this, IDC_PLAY, BM_CLICK, 0, 0 ); - return TRUE; - } - - // not handled - return FALSE; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void MainDlg::OnItemChanged( LPNMLISTVIEW pnmv ) -{ - HWND hwnd = *this; - - HWND hwndNote = ::GetDlgItem( hwnd, IDC_ROMNOTE ); - - RECT rc; - GetWindowRect(hwndNote, &rc); - ScreenToClient( hwnd, (LPPOINT)&rc ); - ScreenToClient( hwnd, ((LPPOINT)&rc)+1 ); - - int iItem = ListView_GetNextItem(pnmv->hdr.hwndFrom, -1, LVNI_SELECTED); - if (iItem == -1) - { - SetWindowText( hwndNote, _T("") ); - EnableWindow( GetDlgItem( hwnd, IDC_PLAY ), FALSE ); - InvalidateRect( hwnd, &rc, TRUE ); - return; - } - - Game* g = (Game*)ListView_GetItemData( pnmv->hdr.hwndFrom, pnmv->iItem ); - SetWindowText( hwndNote, g->note().c_str() ); - InvalidateRect( hwnd, &rc, TRUE ); - EnableWindow( GetDlgItem( hwnd, IDC_PLAY ), TRUE ); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void MainDlg::OnColumnClick( LPNMLISTVIEW pnmv ) -{ - ListView_SortByColumn( pnmv->hdr.hwndFrom, pnmv->iSubItem ); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -static void ScreenToClient( HWND hwnd, LPRECT lpRect ) -{ - ::ScreenToClient(hwnd, (LPPOINT)lpRect); - ::ScreenToClient(hwnd, ((LPPOINT)lpRect)+1); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -static void FillSolidRect( HDC hdc, LPCRECT lpRect, COLORREF clr ) -{ - COLORREF crOld = ::SetBkColor(hdc, clr); - ::ExtTextOut(hdc, 0, 0, ETO_OPAQUE, lpRect, NULL, 0, NULL); - ::SetBkColor(hdc, crOld); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -BOOL MainDlg::OnEraseBkgnd( HDC hdc ) -{ - // don't do this in 256 color - - if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) - return FALSE; - - RECT rcWindow; - ::GetWindowRect( *this, &rcWindow ); - ::ScreenToClient( *this, &rcWindow ); - - FillSolidRect( hdc, &rcWindow, ::GetSysColor( COLOR_3DFACE ) ); - - RECT rc; - ::SetRect( &rc, rcWindow.left, BKGND_BITMAP_TOP, rcWindow.right, BKGND_BITMAP_BOTTOM ); - - long lWidth = rc.right - rc.left; - long lHeight = rc.bottom - rc.top; - - HDC hdcMem = CreateCompatibleDC(hdc); - - HBITMAP hbmpTile = LoadBitmap( myHInstance, MAKEINTRESOURCE(IDB_TILE) ); - - BITMAP bm; - GetObject(hbmpTile, sizeof(bm), &bm); - - HBITMAP hbmpOld = (HBITMAP)SelectObject(hdcMem, hbmpTile); - - for (long x = 0; x < lWidth; x += bm.bmWidth) - { - for (long y = 0; y < lHeight; y += bm.bmHeight) - { - ::BitBlt( hdc, - rc.left + x, rc.top + y, - ( (rc.left + x + bm.bmWidth) > rc.right ) ? rc.right-(rc.left+x) : bm.bmWidth, - ( (rc.top + y + bm.bmHeight) > rc.bottom ) ? rc.bottom-(rc.top+y) : bm.bmHeight, - hdcMem, - 0, 0, SRCCOPY ); - } - } - - SelectObject(hdcMem, hbmpOld); - DeleteObject(hbmpTile); - DeleteDC(hdcMem); - - return TRUE; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -HBRUSH MainDlg::OnCtlColorStatic( HDC hdcStatic, HWND hwndStatic ) -{ - // don't do this in 256 color - - if (GetDeviceCaps(hdcStatic, RASTERCAPS) & RC_PALETTE) - return FALSE; - - if ((GetWindowLong(hwndStatic, GWL_STYLE) & SS_ICON) == SS_ICON) - return NULL; - - SetBkMode(hdcStatic, TRANSPARENT); - - return (HBRUSH)GetStockObject(NULL_BRUSH); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void MainDlg::Quit() -{ - // OK, reload the settings to make sure we have the most current ones - myGlobalData.settings().loadConfig(); - - // Save the current sort column - int sortcol = myHeader.GetSortCol(); - myGlobalData.settings().setInt("sortcol", sortcol); - - // Save the column widths - myGlobalData.settings().setInt("namecolwidth", - ListView_GetColWidth( myHwnd, 0 )); - myGlobalData.settings().setInt("manufacturercolwidth", - ListView_GetColWidth( myHwnd, 1 )); - myGlobalData.settings().setInt("raritycolwidth", - ListView_GetColWidth( myHwnd, 2 )); - - // Now, save the settings - myGlobalData.settings().saveConfig(); - - ListView_Clear(); - EndDialog( myHwnd, IDCANCEL ); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void MainDlg::UpdateRomList( bool forceReload ) -{ - HWND hwndText; - RECT rc; - TCHAR psz[256 + 1]; - TCHAR pszStatus[256 + 1]; - - // Erase status text - LoadString(myHInstance, IDS_STATUSTEXT, pszStatus, 256); - wsprintf( psz, pszStatus, 0 ); - hwndText = GetDlgItem( *this, IDC_ROMCOUNT ); - GetWindowRect(hwndText, &rc); - ScreenToClient( *this, (LPPOINT)&rc ); - ScreenToClient( *this, ((LPPOINT)&rc)+1 ); - SetWindowText( hwndText, psz ); - InvalidateRect( *this, &rc, TRUE ); - - // Erase rom path - hwndText = GetDlgItem( *this, IDC_ROMPATH ); - GetWindowRect(hwndText, &rc); - ScreenToClient( *this, (LPPOINT)&rc ); - ScreenToClient( *this, ((LPPOINT)&rc)+1 ); - SetWindowText( hwndText, "" ); - InvalidateRect( *this, &rc, TRUE ); - - // Get the ROM gamelist, either from disk or cache - PopulateRomList( forceReload ); - - // if items added, select first item and enable play button - int nCount = ListView_GetItemCount( myHwndList ); - if (nCount == 0) - EnableWindow(GetDlgItem( *this, IDC_PLAY), FALSE ); - - // Show status text - LoadString(myHInstance, IDS_STATUSTEXT, pszStatus, 256); - wsprintf( psz, pszStatus, nCount ); - hwndText = GetDlgItem( *this, IDC_ROMCOUNT ); - GetWindowRect(hwndText, &rc); - ScreenToClient( *this, (LPPOINT)&rc ); - ScreenToClient( *this, ((LPPOINT)&rc)+1 ); - SetWindowText( hwndText, psz ); - InvalidateRect( *this, &rc, TRUE ); - - // Show rom path - hwndText = GetDlgItem( *this, IDC_ROMPATH ); - GetWindowRect(hwndText, &rc); - ScreenToClient( *this, (LPPOINT)&rc ); - ScreenToClient( *this, ((LPPOINT)&rc)+1 ); - SetWindowText( hwndText, myGlobalData.settings().getString("romdir").c_str() ); - InvalidateRect( *this, &rc, TRUE ); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool MainDlg::PopulateRomList( bool forceReload ) -{ - bool result = false; - bool cacheFileExists = myGlobalData.settings().fileExists("stellax.cache"); - bool cacheIsStale = false; // FIXME - add romdir status checking - - if (forceReload) - result = LoadRomListFromDisk(); - else if (cacheFileExists && !cacheIsStale) - { - result = LoadRomListFromCache(); - if (!result) - { - MessageBox( myHInstance, myHwnd, IDS_CORRUPT_CACHE_FILE ); - result = LoadRomListFromDisk(); - } - } - else - { - if (!cacheFileExists) - MessageBox( myHInstance, myHwnd, IDS_NO_CACHE_FILE ); - else if (cacheIsStale) - MessageBox( myHInstance, myHwnd, IDS_ROMDIR_CHANGED ); - - result = LoadRomListFromDisk(); - } - - ListView_SortByColumn( myHwndList, myGlobalData.settings().getInt("sortcol") ); - return result; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool MainDlg::LoadRomListFromDisk() -{ - ListView_Clear(); - - // Get the location of the romfiles (*.bin) - string romdir = myGlobalData.settings().getString("romdir"); - romdir += "\\"; - string romfiles = romdir + "*.bin"; - - WIN32_FIND_DATA ffd; - HANDLE hFind = FindFirstFile( romfiles.c_str(), &ffd ); - - ListView_SetItemCount( myHwndList, 100 ); - - int iItem = 0; - bool done = (hFind == INVALID_HANDLE_VALUE); - while(!done) - { - Game* g = new Game(); - if( g == NULL ) - return false; - - LV_ITEM lvi; - lvi.mask = LVIF_TEXT | LVIF_PARAM; - lvi.iItem = iItem++; - lvi.iSubItem = 0; - lvi.pszText = ""; - lvi.lParam = (LPARAM) g; - int nItem = ListView_InsertItem( myHwndList, &lvi ); - - ASSERT( nItem != -1 ); - - g->setAvailable( true ); - g->setRom( ffd.cFileName ); - - // Set the name (shown onscreen) to be the rom - // It will be overwritten later if a name is found in the properties set - g->setName( ffd.cFileName ); - - // go to the next rom file - done = !FindNextFile(hFind, &ffd); - } - - if( hFind != INVALID_HANDLE_VALUE ) - VERIFY( ::FindClose( hFind ) ); - - // Create a propertiesset object and load the properties - // We don't create the propsSet until we need it, since it's - // a time-consuming process - PropertiesSet propsSet; - string theUserProFile = myGlobalData.settings().userPropertiesFilename(); - string theSystemProFile = myGlobalData.settings().systemPropertiesFilename(); - if(theUserProFile != "") - propsSet.load(theUserProFile, true); - else if(theSystemProFile != "") - propsSet.load(theSystemProFile, true); - else - propsSet.load("", false); - - // Now, rescan the items in the listview and update the onscreen - // text and game properties - // Also generate a cache file so the program will start faster next time - ofstream cache("stellax.cache"); - int count = ListView_GetItemCount( myHwndList ); - cache << count << endl; - for (int i = 0; i < count; ++i) - { - Game* g = (Game*) ListView_GetItemData(myHwndList, i); - - // Get the MD5sum for this rom - // Use it to lookup the rom in the properties set - string rom = romdir + g->rom(); - ifstream in(rom.c_str(), ios_base::binary); - if(!in) - return false; - uInt8* image = new uInt8[512 * 1024]; - in.read((char*)image, 512 * 1024); - uInt32 size = in.gcount(); - in.close(); - string md5 = MD5( image, size ); - delete[] image; - - // Get the properties for this rom - Properties props; - propsSet.getMD5( md5, props ); - - // For some braindead reason, the ListView_SetItemText won't - // allow std::string::c_str(), so we create C-strings instead - char name[256], manufacturer[256], rarity[256]; - strncpy(name, props.get("Cartridge.Name").c_str(), 255); - strncpy(manufacturer, props.get("Cartridge.Manufacturer").c_str(), 255); - strncpy(rarity, props.get("Cartridge.Rarity").c_str(), 255); - - // Make sure the onscreen 'Name' field isn't blank - if(props.get("Cartridge.Name") == "") - strncpy(name, g->name().c_str(), 255); - - // Update the current game - g->setMd5( md5 ); - g->setName( name ); - g->setRarity( rarity ); - g->setManufacturer( manufacturer ); - g->setNote( props.get("Cartridge.Note") ); - - // Update the cachefile with this game - cache << g->rom() << endl - << md5 << endl - << name << endl - << rarity << endl - << manufacturer << endl - << g->note() << endl; - - // Finally, update the listview itself - ListView_SetItemText( myHwndList, i, 0, name ); - ListView_SetItemText( myHwndList, i, 1, manufacturer ); - ListView_SetItemText( myHwndList, i, 2, rarity ); - } - cache.close(); - SetFocus( myHwndList ); - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool MainDlg::LoadRomListFromCache() -{ - ListView_Clear(); - char count[10], rom[256], md5[256], name[256], rarity[256], - manufacturer[256], note[256]; - - // We don't scan the roms at all; just load directly from the cache file - ifstream in("stellax.cache"); - if (!in) - return false; - - in.getline(count, 9); - int numRoms = atoi(count); - ListView_SetItemCount( myHwndList, 100 ); - - int iItem = 0; - for(int i = 0; i < numRoms; i++) - { - string line; - Game* g = new Game(); - if( g == NULL ) - return false; - - // Get the data from the cache file - in.getline(rom, 255); - in.getline(md5, 255); - in.getline(name, 255); - in.getline(rarity, 255); - in.getline(manufacturer, 255); - in.getline(note, 255); - - // And save it to this game object - g->setAvailable( true ); - g->setRom( rom ); - g->setMd5( md5 ); - g->setName( name ); - g->setRarity( rarity ); - g->setManufacturer( manufacturer ); - g->setNote( note ); - - LV_ITEM lvi; - lvi.mask = LVIF_TEXT | LVIF_PARAM; - lvi.iItem = iItem++; - lvi.iSubItem = 0; - lvi.pszText = ""; - lvi.lParam = (LPARAM) g; - int nItem = ListView_InsertItem( myHwndList, &lvi ); - - ASSERT( nItem != -1 ); - - ListView_SetItemText( myHwndList, nItem, 0, name ); - ListView_SetItemText( myHwndList, nItem, 1, manufacturer ); - ListView_SetItemText( myHwndList, nItem, 2, rarity ); - } - SetFocus( myHwndList ); - - return true; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// Cool caption message handlers -void MainDlg::OnDestroy( void ) -{ - myCoolCaption.OnDestroy(); - - if ( m_hfontRomNote ) - { - DeleteObject( m_hfontRomNote ); - m_hfontRomNote = NULL; - } -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void MainDlg::OnNcPaint( HRGN hrgn ) -{ - myCoolCaption.OnNcPaint( hrgn ); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void MainDlg::OnNcActivate( BOOL fActive ) -{ - myCoolCaption.OnNcActivate( fActive ); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -BOOL MainDlg::OnNcLButtonDown( INT nHitTest, POINTS pts ) -{ - return myCoolCaption.OnNCLButtonDown( nHitTest, pts ); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -LPARAM MainDlg::ListView_GetItemData( HWND hwndList, int iItem ) -{ - LVITEM lvi; - lvi.mask = LVIF_PARAM; - lvi.iItem = iItem; - lvi.iSubItem = 0; - - ListView_GetItem(hwndList, &lvi); - - return lvi.lParam; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void MainDlg::ListView_SortByColumn( HWND hwndList, int col ) -{ - HCURSOR hcur = SetCursor(LoadCursor(NULL, IDC_WAIT)); - - int nCount = ListView_GetItemCount( hwndList ); - if (nCount != 0) - { - myHeader.SetSortCol( col, TRUE ); - ListView_SortItems( hwndList, ListViewCompareFunc, (LPARAM)this ); - ListView_SetItemState( hwndList, 0, LVIS_SELECTED | LVIS_FOCUSED, - LVIS_SELECTED | LVIS_FOCUSED ); - } - - // ensure the selected item is visible - int nItem = ListView_GetNextItem( myHwndList, -1, LVNI_SELECTED ); - if (nItem != -1) - ListView_EnsureVisible( myHwndList, nItem, TRUE ); - - SetCursor(hcur); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -int MainDlg::ListView_GetColWidth( HWND hwndList, int col ) -{ - // Although there seems to be a similar function in the Win32 API - // to do this, I couldn't get it to work, so it's quicker to - // write this one and use it ... - LV_COLUMN lvc; - lvc.mask = LVCF_WIDTH; - if (ListView_GetColumn( myHwndList, col, &lvc ) == TRUE) - return lvc.cx; - else - return 0; // the next time StellaX starts, it will recreate a sane value -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void MainDlg::ListView_Clear( void ) -{ - int nCount = ListView_GetItemCount( myHwndList ); - - for (int i = 0; i < nCount; ++i) - delete (Game*) ListView_GetItemData( myHwndList, i ); - - ListView_DeleteAllItems( myHwndList ); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -int CALLBACK -MainDlg::ListViewCompareFunc( LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort ) -{ - MainDlg* dlg = reinterpret_cast( lParamSort ); - - int sortCol = dlg->myHeader.GetSortCol(); - - Game* g1 = reinterpret_cast( lParam1 ); - Game* g2 = reinterpret_cast( lParam2 ); - - string s1 = "", s2 = ""; - switch (sortCol) - { - case 0: - s1 = g1->name(); - s2 = g2->name(); - break; - - case 1: - s1 = g1->manufacturer(); - s2 = g2->manufacturer(); - break; - - case 2: - s1 = g1->rarity(); - s2 = g2->rarity(); - break; - } - - if (s1 > s2) - return 1; - else if (s1 < s2) - return -1; - else - return 0; -} diff --git a/stella/src/win32/StellaX/MainDlg.hxx b/stella/src/win32/StellaX/MainDlg.hxx deleted file mode 100644 index 45070872b..000000000 --- a/stella/src/win32/StellaX/MainDlg.hxx +++ /dev/null @@ -1,101 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll XX XX -// SS SS tt ll ll XX XX -// SS tttttt eeee ll ll aaaa XX XX -// SSSS tt ee ee ll ll aa XXX -// SS tt eeeeee ll ll aaaaa XX XX -// SS SS tt ee ll ll aa aa XX XX -// SSSS ttt eeeee llll llll aaaaa XX XX -// -// Copyright (c) 1995-2000 by Jeff Miller -// Copyright (c) 2004 by Stephen Anthony -// -// See the file "license" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -// -// $Id: MainDlg.hxx,v 1.6 2004-07-15 03:03:27 stephena Exp $ -//============================================================================ - -#ifndef MAIN_DLG_HXX -#define MAIN_DLG_HXX - -#include "resource.h" - -class CGlobalData; - -#include "StellaXMain.hxx" -#include "CoolCaption.hxx" -#include "TextButton3d.hxx" -#include "HeaderCtrl.hxx" -#include "RoundButton.hxx" - -class MainDlg -{ - public: - enum { IDD = IDD_MAIN }; - - MainDlg( CGlobalData& rGlobalData, HINSTANCE hInstance ); - virtual ~MainDlg( void ); - - virtual int DoModal( HWND hwndParent ); - - operator HWND( void ) const { return myHwnd; } - - private: - HWND myHwnd; - - CCoolCaption myCoolCaption; - CTextButton3d myAppTitle; - CHeaderCtrl myHeader; - CRoundButton myPlayButton; - CRoundButton myHelpButton; - CRoundButton myReloadButton; - CRoundButton myConfigButton; - CRoundButton myExitButton; - - // Message handlers - BOOL OnInitDialog( void ); - BOOL OnCommand( int id, HWND hwndCtl, UINT codeNotify ); - BOOL OnNotify( int idCtrl, LPNMHDR pnmh ); - BOOL OnEraseBkgnd( HDC hdc ); - HBRUSH OnCtlColorStatic( HDC hdcStatic, HWND hwndStatic ); - - // wm_notify handlers - void OnItemChanged( LPNMLISTVIEW pnmv ); - void OnColumnClick( LPNMLISTVIEW pnmv ); - - // cool caption handlers - void OnDestroy( void ); - void OnNcPaint( HRGN hrgn ); - void OnNcActivate( BOOL fActive ); - void Quit(); - BOOL OnNcLButtonDown( INT nHitTest, POINTS pts ); - - // callback methods - BOOL CALLBACK DialogFunc( UINT uMsg, WPARAM wParam, LPARAM lParam ); - static BOOL CALLBACK StaticDialogFunc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ); - static int CALLBACK ListViewCompareFunc( LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort ); - - // internal data - void UpdateRomList( bool forceReload = false ); - bool PopulateRomList( bool forceReload = false ); - bool LoadRomListFromDisk(); - bool LoadRomListFromCache(); - - HINSTANCE myHInstance; - - HWND myHwndList; - LPARAM ListView_GetItemData( HWND hwndList, int iItem ); - void ListView_SortByColumn( HWND hwndList, int col ); - int ListView_GetColWidth( HWND hwndList, int col ); - void ListView_Clear(); - - HFONT m_hfontRomNote; - - // Stella stuff - CGlobalData& myGlobalData; - CStellaXMain m_stella; -}; - -#endif diff --git a/stella/src/win32/StellaX/PropertySheet.cxx b/stella/src/win32/StellaX/PropertySheet.cxx deleted file mode 100644 index 341fc1499..000000000 --- a/stella/src/win32/StellaX/PropertySheet.cxx +++ /dev/null @@ -1,233 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll XX XX -// SS SS tt ll ll XX XX -// SS tttttt eeee ll ll aaaa XX XX -// SSSS tt ee ee ll ll aa XXX -// SS tt eeeeee ll ll aaaaa XX XX -// SS SS tt ee ll ll aa aa XX XX -// SSSS ttt eeeee llll llll aaaaa XX XX -// -// Copyright (c) 1995-2000 by Jeff Miller -// Copyright (c) 2004 by Stephen Anthony -// -// See the file "license" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -// -// $Id: PropertySheet.cxx,v 1.2 2004-07-15 03:03:27 stephena Exp $ -//============================================================================ - -#include "pch.hxx" -#include "PropertySheet.hxx" - -#pragma comment(lib, "comctl32") -#include - -typedef struct DLGTEMPLATEEX -{ - WORD dlgVer; - WORD signature; - DWORD helpID; - DWORD exStyle; - DWORD style; - WORD cDlgItems; - short x; - short y; - short cx; - short cy; -} DLGTEMPLATEEX, *LPDLGTEMPLATEEX; - -#include - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -CPropertyPage::CPropertyPage( UINT nIDTemplate, UINT nIDCaption /* = 0 */ ) -{ - UNUSED_ALWAYS( nIDCaption ); - - ZeroMemory(&m_psp, sizeof(m_psp)); - m_psp.dwSize = sizeof(m_psp); - m_psp.dwFlags = PSP_USECALLBACK; - // m_psp.hInstance = hInstance; - m_psp.pszTemplate = MAKEINTRESOURCE(nIDTemplate); - m_psp.pfnDlgProc = StaticDlgProc; - m_psp.lParam = (LPARAM)this; - m_psp.pfnCallback = StaticCallback; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -UINT CALLBACK -CPropertyPage::StaticCallback( HWND hwnd, UINT uMsg, LPPROPSHEETPAGE ppsp ) -{ - UNUSED_ALWAYS( hwnd ); - UNUSED_ALWAYS( ppsp ); - - switch (uMsg) - { - case PSPCB_CREATE: - // ppsp->lParam holds create lParam - return TRUE; - - case PSPCB_RELEASE: - break; - } - - return 0; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -BOOL CALLBACK -CPropertyPage::StaticDlgProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) -{ - CPropertyPage* pPage = NULL; - - switch ( uMsg ) - { - case WM_INITDIALOG: - pPage = reinterpret_cast( - reinterpret_cast( lParam )->lParam ); - (void)::SetWindowLong( hwnd, DWL_USER, reinterpret_cast( pPage ) ); - break; - - default: - pPage = reinterpret_cast( GetWindowLong( hwnd, DWL_USER ) ); - if ( pPage == NULL ) - return FALSE; - break; - } - - return pPage->DlgProc( hwnd, uMsg, wParam, lParam ); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -BOOL CALLBACK -CPropertyPage::DlgProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam ) -{ - switch (msg) - { - case WM_ACTIVATE: - OnActivate( (UINT)LOWORD(wParam), (HWND)lParam, (BOOL)HIWORD(wParam) ); - return TRUE; - - case WM_INITDIALOG: - return OnInitDialog( hwnd ); - - case WM_DESTROY: - OnDestroy( ); - return TRUE; - - case WM_COMMAND: - return OnCommand( HIWORD(wParam), LOWORD(wParam), (HWND)lParam ); - - case WM_NOTIFY: - // Handle PSN_QUERYCANCEL? - // Handle PSN_KILLACTIVE? - switch (((LPNMHDR)lParam)->code) - { - case PSN_SETACTIVE: - SetWindowLong(hwnd, DWL_MSGRESULT, OnSetActive( (LPPSHNOTIFY)lParam ) ); - return TRUE; - - case PSN_KILLACTIVE: - SetWindowLong(hwnd, DWL_MSGRESULT, OnKillActive( (LPPSHNOTIFY)lParam ) ); - return TRUE; - - case PSN_APPLY: - SetWindowLong( hwnd, DWL_MSGRESULT, OnApply( (LPPSHNOTIFY)lParam) ); - return TRUE; - - case PSN_RESET: - OnReset( (LPPSHNOTIFY)lParam ); - return TRUE; - } - return OnNotify( (int)wParam, (LPNMHDR)lParam ); - } - - return FALSE; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -CPropertySheet::CPropertySheet( LPCTSTR pszCaption, HWND hwndParent, - UINT nStartPage /* = 0 */ ) - : m_strCaption( pszCaption ) -{ - ZeroMemory(&m_psh, sizeof(m_psh)); - m_psh.dwSize = sizeof(m_psh); - m_psh.dwFlags = PSH_NOAPPLYNOW | PSH_PROPSHEETPAGE | PSH_USECALLBACK; - m_psh.hwndParent = hwndParent; - m_psh.hInstance = (HINSTANCE)GetWindowLong(hwndParent, GWL_HINSTANCE); - m_psh.pszCaption = m_strCaption.c_str(); - m_psh.nStartPage = nStartPage; - m_psh.pfnCallback = StaticCallback; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -CPropertySheet::~CPropertySheet() -{ - // BUGBUG: This is static! - -/* if ( m_hfontLogo ) - { - DeleteObject( m_hfontLogo ); - m_hfontLogo = NULL; - }*/ -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CPropertySheet::AddPage( CPropertyPage* pPage ) -{ - if (pPage) - m_pages.push_back(pPage); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -int CPropertySheet::DoModal() -{ - int nSize = m_pages.size(); - - if (nSize == 0) - return IDCANCEL; - - PROPSHEETPAGE* pspage = new PROPSHEETPAGE[nSize]; - for (int i = 0; i < nSize; ++i) - { - CopyMemory(&(pspage[i]), m_pages[i]->GetPropSheetPage(), - sizeof(PROPSHEETPAGE)); - pspage[i].hInstance = m_psh.hInstance; - } - - m_psh.nPages = nSize; - m_psh.ppsp = pspage; - - int nRet = ::PropertySheet( &m_psh ); - - delete[] pspage; - - return nRet; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -int CALLBACK -CPropertySheet::StaticCallback( HWND hwnd, UINT uMsg, LPARAM lParam ) -{ - UNUSED_ALWAYS( hwnd ); - - switch (uMsg) - { - case PSCB_INITIALIZED: - // Property sheet is being initialized - return TRUE; - - case PSCB_PRECREATE: - // Property sheet is about to be created - // Remove the DS_CONTEXTHELP style from the dialog template - // (This will remove the "?" in the top right corner) - if ( ( (LPDLGTEMPLATEEX)lParam )->signature == 0xFFFF) - ( (LPDLGTEMPLATEEX)lParam )->style &= ~DS_CONTEXTHELP; - else - ( (LPDLGTEMPLATE)lParam )->style &= ~DS_CONTEXTHELP; - - return TRUE; - } - - return 0; -} diff --git a/stella/src/win32/StellaX/PropertySheet.hxx b/stella/src/win32/StellaX/PropertySheet.hxx deleted file mode 100644 index 7510c919c..000000000 --- a/stella/src/win32/StellaX/PropertySheet.hxx +++ /dev/null @@ -1,92 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll XX XX -// SS SS tt ll ll XX XX -// SS tttttt eeee ll ll aaaa XX XX -// SSSS tt ee ee ll ll aa XXX -// SS tt eeeeee ll ll aaaaa XX XX -// SS SS tt ee ll ll aa aa XX XX -// SSSS ttt eeeee llll llll aaaaa XX XX -// -// Copyright (c) 1995-2000 by Jeff Miller -// Copyright (c) 2004 by Stephen Anthony -// -// See the file "license" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -// -// $Id: PropertySheet.hxx,v 1.2 2004-07-15 03:03:27 stephena Exp $ -//============================================================================ - -#ifndef PROPERTY_SHEET_HXX -#define PROPERTY_SHEET_HXX - -#include -#include -#include - -class CPropertyPage -{ - public: - CPropertyPage( UINT nIDTemplate, UINT nIDCaption = 0 ); - - const PROPSHEETPAGE* GetPropSheetPage(); - - protected: - // Overridable callbacks - virtual void OnActivate( UINT state, HWND hwndActDeact, BOOL fMinimized ) {} - - virtual BOOL OnInitDialog( HWND /* hwnd */ ) { return FALSE; } - - virtual void OnDestroy( void ) {} - - virtual BOOL OnSetActive( LPPSHNOTIFY /* lppsn */ ) { return 0; } - - virtual BOOL OnKillActive( LPPSHNOTIFY /* lppsn */ ) { return FALSE; } - - virtual LONG OnApply( LPPSHNOTIFY /* lppsn */ ) { return PSNRET_NOERROR; } - - virtual void OnReset( LPPSHNOTIFY /* lppsn */ ) {} - - virtual BOOL OnCommand( WORD /* wNotifyCode */, WORD /* wID */, - HWND /* hwndCtl */ ) { return FALSE; } - - virtual BOOL OnNotify( int /* idCtrl */, LPNMHDR /* pnmh */ ) { return FALSE; } - - private: - static UINT CALLBACK StaticCallback( HWND hwnd, UINT uMsg, LPPROPSHEETPAGE ppsp ); - - static BOOL CALLBACK StaticDlgProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam ); - BOOL CALLBACK DlgProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam ); - - PROPSHEETPAGE m_psp; - - CPropertyPage( const CPropertyPage& ); // no implementation - void operator=( const CPropertyPage& ); // no implementation -}; - -inline const PROPSHEETPAGE* CPropertyPage::GetPropSheetPage() -{ - return &m_psp; -} - -class CPropertySheet -{ - public: - CPropertySheet( LPCTSTR pszCaption, HWND hwndParent, UINT nStartPage = 0 ); - ~CPropertySheet( ); - - void AddPage( CPropertyPage* pPage ); - virtual int DoModal( void ); - - private: - static int CALLBACK StaticCallback( HWND hwndDlg, UINT uMsg, LPARAM lParam ); - - PROPSHEETHEADER m_psh; - std::vector m_pages; - std::string m_strCaption; - - CPropertySheet( const CPropertySheet& ); // no implementation - void operator=( const CPropertySheet& ); // no implementation -}; - -#endif diff --git a/stella/src/win32/StellaX/RoundButton.cxx b/stella/src/win32/StellaX/RoundButton.cxx deleted file mode 100644 index 8815c6072..000000000 --- a/stella/src/win32/StellaX/RoundButton.cxx +++ /dev/null @@ -1,553 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll XX XX -// SS SS tt ll ll XX XX -// SS tttttt eeee ll ll aaaa XX XX -// SSSS tt ee ee ll ll aa XXX -// SS tt eeeeee ll ll aaaaa XX XX -// SS SS tt ee ll ll aa aa XX XX -// SSSS ttt eeeee llll llll aaaaa XX XX -// -// Copyright (c) 1995-2000 by Jeff Miller -// Copyright (c) 2004 by Stephen Anthony -// -// See the file "license" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -// -// $Id: RoundButton.cxx,v 1.2 2004-07-15 03:03:27 stephena Exp $ -//============================================================================ - -#include "pch.hxx" -#include "RoundButton.hxx" -#include -#include - -// prototypes -COLORREF GetColour(double dAngle, COLORREF crBright, COLORREF crDark); - -void DrawCircle( HDC hdc, const POINT& p, LONG lRadius, - COLORREF crColour, BOOL bDashed = FALSE); - -void DrawCircleLeft( HDC hdc, const POINT& p, LONG lRadius, - COLORREF crBright, COLORREF crDark); - -void DrawCircleRight( HDC hdc, const POINT& p, LONG lRadius, - COLORREF crBright, COLORREF crDark); - -// Calculate colour for a point at the given angle by performing a linear -// interpolation between the colours crBright and crDark based on the cosine -// of the angle between the light source and the point. -// -// Angles are measured from the +ve x-axis (i.e. (1,0) = 0 degrees, (0,1) = 90 degrees ) -// But remember: +y points down! - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -COLORREF GetColour( double dAngle, COLORREF crBright, COLORREF crDark ) -{ - #define Rad2Deg 180.0/3.1415 - - // For better light-continuity along the edge of a stretched button: - // LIGHT_SOURCE_ANGLE == -1.88 - - //#define LIGHT_SOURCE_ANGLE -2.356 // -2.356 radians = -135 degrees, i.e. From top left - #define LIGHT_SOURCE_ANGLE -1.88 - - ASSERT(dAngle > -3.1416 && dAngle < 3.1416); - double dAngleDifference = LIGHT_SOURCE_ANGLE - dAngle; - - if (dAngleDifference < -3.1415) - dAngleDifference = 6.293 + dAngleDifference; - else if (dAngleDifference > 3.1415) - dAngleDifference = 6.293 - dAngleDifference; - - double Weight = 0.5*(cos(dAngleDifference)+1.0); - - BYTE Red = (BYTE) (Weight*GetRValue(crBright) + (1.0-Weight)*GetRValue(crDark)); - BYTE Green = (BYTE) (Weight*GetGValue(crBright) + (1.0-Weight)*GetGValue(crDark)); - BYTE Blue = (BYTE) (Weight*GetBValue(crBright) + (1.0-Weight)*GetBValue(crDark)); - - //TRACE("LightAngle = %0.0f, Angle = %3.0f, Diff = %3.0f, Weight = %0.2f, RGB %3d,%3d,%3d\n", - // LIGHT_SOURCE_ANGLE*Rad2Deg, dAngle*Rad2Deg, dAngleDifference*Rad2Deg, Weight,Red,Green,Blue); - - return RGB(Red, Green, Blue); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void DrawCircle( HDC hdc, const POINT& p, LONG lRadius, COLORREF crColour, - BOOL bDashed ) -{ - const int nDashLength = 1; - LONG lError, lXoffset, lYoffset; - int nDash = 0; - BOOL bDashOn = TRUE; - - // Check to see that the coordinates are valid - ASSERT( (p.x + lRadius <= LONG_MAX) && (p.y + lRadius <= LONG_MAX) ); - ASSERT( (p.x - lRadius >= LONG_MIN) && (p.y - lRadius >= LONG_MIN) ); - - // Set starting values - lXoffset = lRadius; - lYoffset = 0; - lError = -lRadius; - - do - { - if (bDashOn) - { - SetPixelV(hdc, p.x + lXoffset, p.y + lYoffset, crColour); - SetPixelV(hdc, p.x + lXoffset, p.y - lYoffset, crColour); - SetPixelV(hdc, p.x + lYoffset, p.y + lXoffset, crColour); - SetPixelV(hdc, p.x + lYoffset, p.y - lXoffset, crColour); - SetPixelV(hdc, p.x - lYoffset, p.y + lXoffset, crColour); - SetPixelV(hdc, p.x - lYoffset, p.y - lXoffset, crColour); - SetPixelV(hdc, p.x - lXoffset, p.y + lYoffset, crColour); - SetPixelV(hdc, p.x - lXoffset, p.y - lYoffset, crColour); - } - - // Advance the error term and the constant X axis step - lError += lYoffset++; - - // Check to see if error term has overflowed - if ((lError += lYoffset) >= 0) - lError -= --lXoffset * 2; - - if (bDashed && (++nDash == nDashLength)) - { - nDash = 0; - bDashOn = !bDashOn; - } - } while (lYoffset <= lXoffset); // Continue until halfway point -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// The original Drawcircle function is split up into DrawCircleRight and -// DrawCircleLeft to make stretched buttons -void DrawCircleRight( HDC hdc, const POINT& p, LONG lRadius, COLORREF crBright, - COLORREF crDark ) -{ - LONG lError, lXoffset, lYoffset; - - // Check to see that the coordinates are valid - ASSERT( (p.x + lRadius <= LONG_MAX) && (p.y + lRadius <= LONG_MAX) ); - ASSERT( (p.x - lRadius >= LONG_MIN) && (p.y - lRadius >= LONG_MIN) ); - - // Set starting values - lXoffset = lRadius; - lYoffset = 0; - lError = -lRadius; - - do - { - const double Pi = 3.141592654, Pi_on_2 = Pi * 0.5; - COLORREF crColour; - long double dAngle = atan2((long double)lYoffset, (long double)lXoffset); - - // Draw the current pixel, reflected across all four arcs - crColour = GetColour(dAngle, crBright, crDark); - SetPixelV(hdc, p.x + lXoffset, p.y + lYoffset, crColour); - - crColour = GetColour(Pi_on_2 - dAngle, crBright, crDark); - SetPixelV(hdc, p.x + lYoffset, p.y + lXoffset, crColour); - - crColour = GetColour(-Pi_on_2 + dAngle, crBright, crDark); - SetPixelV(hdc, p.x + lYoffset, p.y - lXoffset, crColour); - - crColour = GetColour(-dAngle, crBright, crDark); - SetPixelV(hdc, p.x + lXoffset, p.y - lYoffset, crColour); - - // Advance the error term and the constant X axis step - lError += lYoffset++; - - // Check to see if error term has overflowed - if ((lError += lYoffset) >= 0) - lError -= --lXoffset * 2; - - } while (lYoffset <= lXoffset); // Continue until halfway point -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// The original Drawcircle function is split up into DrawCircleRight and -// DrawCircleLeft to make stretched buttons -void DrawCircleLeft( HDC hdc, const POINT& p, LONG lRadius, COLORREF crBright, - COLORREF crDark ) -{ - LONG lError, lXoffset, lYoffset; - - // Check to see that the coordinates are valid - ASSERT( (p.x + lRadius <= LONG_MAX) && (p.y + lRadius <= LONG_MAX) ); - ASSERT( (p.x - lRadius >= LONG_MIN) && (p.y - lRadius >= LONG_MIN) ); - - // Set starting values - lXoffset = lRadius; - lYoffset = 0; - lError = -lRadius; - - do - { - const double Pi = 3.141592654, Pi_on_2 = Pi * 0.5; - COLORREF crColour; - long double dAngle = atan2((long double)lYoffset, (long double)lXoffset); - - // Draw the current pixel, reflected across all eight arcs - crColour = GetColour(Pi_on_2 + dAngle, crBright, crDark); - SetPixelV(hdc, p.x - lYoffset, p.y + lXoffset, crColour); - - crColour = GetColour(Pi - dAngle, crBright, crDark); - SetPixelV(hdc, p.x - lXoffset, p.y + lYoffset, crColour); - - crColour = GetColour(-Pi + dAngle, crBright, crDark); - SetPixelV(hdc, p.x - lXoffset, p.y - lYoffset, crColour); - - crColour = GetColour(-Pi_on_2 - dAngle, crBright, crDark); - SetPixelV(hdc, p.x - lYoffset, p.y - lXoffset, crColour); - - // Advance the error term and the constant X axis step - lError += lYoffset++; - - // Check to see if error term has overflowed - if ((lError += lYoffset) >= 0) - lError -= --lXoffset * 2; - - } while (lYoffset <= lXoffset); // Continue until halfway point -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -static void ClientToScreen( HWND hwnd, LPRECT lpRect ) -{ - ClientToScreen(hwnd, (LPPOINT)lpRect); - ClientToScreen(hwnd, ((LPPOINT)lpRect)+1); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -static void ScreenToClient( HWND hwnd, LPRECT lpRect ) -{ - ScreenToClient(hwnd, (LPPOINT)lpRect); - ScreenToClient(hwnd, ((LPPOINT)lpRect)+1); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -static void FillSolidRect( HDC hdc, LPCRECT lpRect, COLORREF clr ) -{ - COLORREF crOld = ::SetBkColor(hdc, clr); - ExtTextOut(hdc, 0, 0, ETO_OPAQUE, lpRect, NULL, 0, NULL); - SetBkColor(hdc, crOld); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -CRoundButton::CRoundButton() - : m_hrgn( NULL ), - m_fDrawDashedFocusCircle( TRUE ), - m_fStretch( FALSE ) -{ -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -CRoundButton::~CRoundButton() -{ - if ( m_hrgn ) - DeleteObject( m_hrgn ); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CRoundButton::PreSubclassWindow( HWND hwnd ) -{ - RECT rect; - GetClientRect( hwnd, &rect ); - - m_fStretch = (rect.right-rect.left) > (rect.bottom-rect.top); - if ( ! m_fStretch ) - rect.bottom = rect.right = min ( rect.bottom, rect.right ); - - m_ptCenter.x = m_ptLeft.x = m_ptRight.x = ((rect.right-rect.left)/2); - m_ptCenter.y = m_ptLeft.y = m_ptRight.y = ((rect.bottom-rect.top)/2); - - m_nRadius = rect.bottom/2 - 1; - - m_ptLeft.x = m_nRadius; - m_ptRight.x = rect.right - m_nRadius - 1; - - SetWindowRgn( hwnd, NULL, FALSE ); - m_hrgn = ::CreateEllipticRgnIndirect( &rect ); - SetWindowRgn( hwnd, m_hrgn, TRUE ); - - ClientToScreen( hwnd, &rect ); - - HWND hwndParent = ::GetParent( hwnd ); - if ( hwndParent ) - ScreenToClient( hwndParent, &rect ); - - if ( ! m_fStretch ) - MoveWindow( hwnd, rect.left, rect.top, - rect.right-rect.left, rect.bottom-rect.top, TRUE ); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -LRESULT CRoundButton::WndProc( HWND hWnd, UINT msg, WPARAM wParam, - LPARAM lParam, BOOL& rfHandled ) -{ - switch (msg) - { - case WM_DRAWITEM: - rfHandled = TRUE; - OnDrawItem(hWnd, (UINT)wParam, (LPDRAWITEMSTRUCT)lParam); - return TRUE; - - case WM_ERASEBKGND: - // don't do erasing - return TRUE; - } - - return 0; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CRoundButton::OnDrawItem( HWND hwnd, UINT idCtl, LPDRAWITEMSTRUCT lpdis ) -{ - UNUSED_ALWAYS( idCtl ); - - HDC hdc = lpdis->hDC; - RECT& rect = lpdis->rcItem; - UINT state = lpdis->itemState; - UINT nStyle = GetWindowLong(hwnd, GWL_STYLE); - int nRadius = m_nRadius; - - int nSavedDC = ::SaveDC( hdc ); - - SelectObject( hdc, ::GetStockObject( NULL_BRUSH ) ); - FillSolidRect( hdc, &rect, ::GetSysColor(COLOR_BTNFACE) ); - - // Draw the focus circle around the button for non-stretched buttons - if ( (state & ODS_FOCUS) && m_fDrawDashedFocusCircle && !m_fStretch ) - DrawCircle( hdc, m_ptCenter, nRadius--, RGB( 0, 0, 0) ); - - // Draw the raised/sunken edges of the button (unless flat) - if ( nStyle & BS_FLAT ) - { - if ( m_fStretch ) - { - // for stretched buttons: draw left and right arcs and connect the with lines - HPEN hpenOld; - - RECT rectLeftBound; - SetRect( &rectLeftBound, 0, 0, nRadius*2, nRadius*2 ); - - RECT rectRightBound; - SetRect( &rectRightBound, m_ptRight.x-nRadius, 0, m_ptRight.x+nRadius, nRadius*2 ); - - hpenOld = (HPEN)::SelectObject( hdc, - CreatePen( PS_SOLID, 1, ::GetSysColor(COLOR_3DDKSHADOW) ) ); - - Arc( hdc, rectLeftBound.left, rectLeftBound.top, rectLeftBound.right, - rectLeftBound.bottom, m_ptLeft.x, 0, m_ptLeft.x, nRadius*2 ); - - Arc( hdc, rectRightBound.left, rectRightBound.top, rectRightBound.right, - rectRightBound.bottom, m_ptRight.x, nRadius*2, m_ptRight.x, 0 ); - - MoveToEx( hdc, m_ptLeft.x, 0, NULL ); - LineTo( hdc, m_ptRight.x, 0 ); - - MoveToEx( hdc, m_ptLeft.x, nRadius*2-1, NULL ); - LineTo( hdc, m_ptRight.x, nRadius*2-1 ); - - nRadius--; - - InflateRect( &rectLeftBound, -1, -1 ); - InflateRect( &rectRightBound, -1, -1 ); - - DeleteObject( ::SelectObject( hdc, - CreatePen( PS_SOLID, 1, ::GetSysColor( COLOR_3DHIGHLIGHT ) ) ) ); - - Arc( hdc, rectLeftBound.left, rectLeftBound.top, rectLeftBound.right, - rectLeftBound.bottom, m_ptLeft.x, 1, m_ptLeft.x, nRadius*2 ); - - Arc( hdc, rectRightBound.left, rectRightBound.top, rectRightBound.right, - rectRightBound.bottom, m_ptRight.x, nRadius*2, m_ptRight.x, 0 ); - - MoveToEx( hdc, m_ptLeft.x, 1, NULL ); - LineTo( hdc, m_ptRight.x, 1 ); - - MoveToEx( hdc, m_ptLeft.x, nRadius*2, NULL ); - LineTo( hdc, m_ptRight.x, nRadius*2 ); - - DeleteObject( ::SelectObject( hdc, hpenOld ) ); - } - else - { - // for non-stretched buttons: draw two circles - DrawCircle( hdc, m_ptCenter, nRadius--, ::GetSysColor(COLOR_3DDKSHADOW) ); - DrawCircle( hdc, m_ptCenter, nRadius--, ::GetSysColor(COLOR_3DHIGHLIGHT) ); - } - } - else - { - if (state & ODS_SELECTED) - { - // draw the circular segments for stretched AND non-stretched buttons - DrawCircleLeft( hdc, m_ptLeft, nRadius, - GetSysColor(COLOR_3DDKSHADOW), ::GetSysColor(COLOR_3DHIGHLIGHT) ); - DrawCircleRight( hdc, m_ptRight, nRadius, - GetSysColor(COLOR_3DDKSHADOW), ::GetSysColor(COLOR_3DHIGHLIGHT) ); - DrawCircleLeft( hdc, m_ptLeft, nRadius-1, - GetSysColor(COLOR_3DSHADOW), ::GetSysColor(COLOR_3DLIGHT) ); - DrawCircleRight( hdc, m_ptRight, nRadius-1, - GetSysColor(COLOR_3DSHADOW), ::GetSysColor(COLOR_3DLIGHT) ); - - if ( m_fStretch ) - { - // draw connecting lines for stretched buttons only - HPEN hpenOld; - hpenOld = (HPEN)::SelectObject( hdc, - (HPEN)::CreatePen( PS_SOLID, 1, ::GetSysColor(COLOR_3DDKSHADOW) ) ); - - MoveToEx( hdc, m_ptLeft.x, 1, NULL ); - LineTo( hdc, m_ptRight.x, 1 ); - - DeleteObject( ::SelectObject( hdc, - CreatePen( PS_SOLID, 1, ::GetSysColor(COLOR_3DSHADOW) ) ) ); - - MoveToEx( hdc, m_ptLeft.x, 2, NULL ); - LineTo( hdc, m_ptRight.x, 2 ); - - DeleteObject( ::SelectObject( hdc, - CreatePen( PS_SOLID, 1, ::GetSysColor( COLOR_3DLIGHT ) ) ) ); - - MoveToEx( hdc, m_ptLeft.x, m_ptLeft.y + nRadius-1, NULL ); - LineTo( hdc, m_ptRight.x, m_ptLeft.y + nRadius-1 ); - - DeleteObject( ::SelectObject( hdc, - CreatePen( PS_SOLID, 1, ::GetSysColor( COLOR_3DHIGHLIGHT ) ) ) ); - - MoveToEx( hdc, m_ptLeft.x, m_ptLeft.y + nRadius, NULL ); - LineTo( hdc, m_ptRight.x, m_ptLeft.y + nRadius ); - - DeleteObject( ::SelectObject( hdc, hpenOld ) ); - } - } - else - { - // draw the circular segments for stretched AND non-stretched buttons - DrawCircleLeft( hdc, m_ptLeft, nRadius, - GetSysColor(COLOR_3DHIGHLIGHT), ::GetSysColor(COLOR_3DDKSHADOW) ); - - DrawCircleRight( hdc, m_ptRight, nRadius, - GetSysColor(COLOR_3DHIGHLIGHT), ::GetSysColor(COLOR_3DDKSHADOW) ); - - DrawCircleLeft( hdc, m_ptLeft, nRadius - 1, - GetSysColor(COLOR_3DLIGHT), ::GetSysColor(COLOR_3DSHADOW) ); - - DrawCircleRight( hdc, m_ptRight, nRadius - 1, - GetSysColor(COLOR_3DLIGHT), ::GetSysColor(COLOR_3DSHADOW) ); - - // draw connecting lines for stretch buttons - if ( m_fStretch ) - { - HPEN hpenOld; - hpenOld = (HPEN)::SelectObject( hdc, - CreatePen( PS_SOLID, 1, - GetPixel( hdc, m_ptLeft.x, 1 ) ) ); - - MoveToEx( hdc, m_ptLeft.x, 1, NULL ); - LineTo( hdc, m_ptRight.x , 1); - - DeleteObject( ::SelectObject( hdc, - ::CreatePen( PS_SOLID, 1, - ::GetPixel( hdc, m_ptLeft.x, 2 ) ) ) ); - - MoveToEx( hdc, m_ptLeft.x, 2, NULL ); - LineTo( hdc, m_ptRight.x, 2 ); - - DeleteObject( ::SelectObject( hdc, - ::CreatePen( PS_SOLID, 1, - ::GetPixel( hdc, m_ptLeft.x, m_ptLeft.y+nRadius ) ) ) ); - - MoveToEx( hdc, m_ptLeft.x, m_ptLeft.y + nRadius, NULL ); - LineTo( hdc, m_ptRight.x, m_ptLeft.y + nRadius ); - - DeleteObject( ::SelectObject( hdc, - ::CreatePen( PS_SOLID, 1, - ::GetPixel( hdc, m_ptLeft.x, m_ptLeft.y+nRadius-1 ) ) ) ); - - MoveToEx( hdc, m_ptLeft.x, m_ptLeft.y + nRadius - 1, NULL ); - LineTo( hdc, m_ptRight.x, m_ptLeft.y + nRadius - 1 ); - - DeleteObject( ::SelectObject( hdc, hpenOld ) ); - } - } - } - - // Draw the text if there is any - TCHAR pszText[ 256 ]; - int cch = ::GetWindowText( hwnd, pszText, 255 ); - if ( cch != 0 ) - { - HRGN hrgn; - - if ( m_fStretch ) - hrgn = CreateRectRgn( m_ptLeft.x - nRadius / 2, m_ptCenter.y - nRadius, - m_ptRight.x + nRadius / 2, m_ptCenter.y + nRadius ); - else - hrgn = CreateEllipticRgn( m_ptCenter.x - nRadius, m_ptCenter.y - nRadius, - m_ptCenter.x + nRadius, m_ptCenter.y + nRadius ); - - SelectClipRgn( hdc, hrgn ); - - SIZE size; - GetTextExtentPoint32( hdc, pszText, cch, &size ); - - POINT pt = { m_ptCenter.x - size.cx / 2, m_ptCenter.y - size.cy / 2 - 1 }; - POINT pt2 = { m_ptCenter.x + size.cx/2, m_ptCenter.y + size.cy/2 + 1 }; - - if ( state & ODS_SELECTED ) - { - ++( pt.x ); - ++( pt.y ); - } - - SetBkMode( hdc, TRANSPARENT ); - -#if 0 - if ( state & ODS_DISABLED ) - DrawState( hdc, NULL, NULL, (LPARAM)pszText, (WPARAM)cch, - pt.x, pt.y, size.cx, size.cy, DSS_DISABLED ); - else -#endif - { - // give text a 3d-look - RECT pos; - SetRect( &pos, pt.x, pt.y, pt2.x, pt2.y ); - - COLORREF crOld = SetTextColor( hdc, - ( state & ODS_DISABLED ) ? - GetSysColor( COLOR_GRAYTEXT ) : - GetSysColor( COLOR_WINDOWTEXT ) ); - - if ( state & ODS_FOCUS ) - { - LOGFONT lf; - GetObject( (HFONT)::SendMessage( hwnd, WM_GETFONT, 0, 0 ), sizeof(LOGFONT), &lf ); - - lf.lfWeight = FW_BOLD; - HFONT hfontOld = (HFONT)::SelectObject( hdc, ::CreateFontIndirect( &lf ) ); - - DrawText( hdc, pszText, -1, &pos, DT_SINGLELINE | DT_CENTER ); - - DeleteObject( ::SelectObject( hdc, hfontOld) ); - } - else - DrawText( hdc, pszText, -1, &pos, DT_SINGLELINE | DT_CENTER ); - - SetTextColor( hdc, crOld ); - } - - SelectClipRgn( hdc, NULL ); - DeleteObject( hrgn ); - } - -#if 0 - // draw the focus circle on the inside - if ( (state & ODS_FOCUS) && m_fDrawDashedFocusCircle && !m_fStretch ) - DrawCircle( hdc, m_ptCenter, nRadius-2, RGB(0, 0, 0), TRUE ); -#endif - - RestoreDC( hdc, nSavedDC ); -} diff --git a/stella/src/win32/StellaX/RoundButton.hxx b/stella/src/win32/StellaX/RoundButton.hxx deleted file mode 100644 index 16a51f69a..000000000 --- a/stella/src/win32/StellaX/RoundButton.hxx +++ /dev/null @@ -1,50 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll XX XX -// SS SS tt ll ll XX XX -// SS tttttt eeee ll ll aaaa XX XX -// SSSS tt ee ee ll ll aa XXX -// SS tt eeeeee ll ll aaaaa XX XX -// SS SS tt ee ll ll aa aa XX XX -// SSSS ttt eeeee llll llll aaaaa XX XX -// -// Copyright (c) 1995-2000 by Jeff Miller -// Copyright (c) 2004 by Stephen Anthony -// -// See the file "license" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -// -// $Id: RoundButton.hxx,v 1.2 2004-07-15 03:03:27 stephena Exp $ -//============================================================================ - -#ifndef ROUND_BUTTON_HXX -#define ROUND_BUTTON_HXX - -#include "Wnd.hxx" - -class CRoundButton : public CWnd -{ - public: - CRoundButton(); - ~CRoundButton(); - - protected: - LRESULT WndProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& fHandled ); - virtual void PreSubclassWindow(HWND hwnd); - - private: - void OnDrawItem(HWND hwnd, UINT idCtl, LPDRAWITEMSTRUCT lpdis); - - HRGN m_hrgn; - POINT m_ptCenter; - POINT m_ptLeft; - POINT m_ptRight; - int m_nRadius; - BOOL m_fDrawDashedFocusCircle; - BOOL m_fStretch; - - CRoundButton( const CRoundButton& ); // no implementation - void operator=( const CRoundButton& ); // no implementation -}; - -#endif diff --git a/stella/src/win32/StellaX/StellaX.aps b/stella/src/win32/StellaX/StellaX.aps deleted file mode 100644 index 63ed383de3dbea0f003afc70f7f26ce86d516315..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41076 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 diff --git a/stella/src/win32/StellaX/StellaX.ico b/stella/src/win32/StellaX/StellaX.ico deleted file mode 100644 index f5d8e9433a6d6a772c94293d2379f1c1756db23a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1078 zcmd5*yKcfj5S$}OX;983Rd5yY8Of*QFX-4$^QTazbeSrfnOy=LMj}#(#M-m3xjjEL z2NcZE_Z?&(GvI}>>#|-K;OPNav)2=^M8TXMFs{99Mv{zK270C#hJjIp#|?L71TVGZ z{@bdLd_)bWbXrF@nB?0!XEh&t?DuMF4zSLR#h=w`)bT*af~MxQuH&D$xBB>IH_xbn z#%%Lk0?TEwQ&5IRd;+Ued;wd*t@y9dJk4D??}(l_=$!dwGisa+H64MT>7R5i;pjwE t-g5HlNE2~b;5DUDtJ);4#8@Tut#a_YF#d+zJ2y diff --git a/stella/src/win32/StellaX/StellaX.rc b/stella/src/win32/StellaX/StellaX.rc deleted file mode 100644 index 4ee8adba9..000000000 --- a/stella/src/win32/StellaX/StellaX.rc +++ /dev/null @@ -1,299 +0,0 @@ -// Microsoft Visual C++ generated resource script. -// -#include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#define APSTUDIO_HIDDEN_SYMBOLS -#include "winresrc.h" -#undef APSTUDIO_HIDDEN_SYMBOLS -#include "resource.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// English (U.S.) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -#ifdef _WIN32 -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US -#pragma code_page(1252) -#endif //_WIN32 - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE -BEGIN - "resource.h\0" -END - -2 TEXTINCLUDE -BEGIN - "#define APSTUDIO_HIDDEN_SYMBOLS\r\n" - "#include ""winresrc.h""\r\n" - "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n" - "#include ""resource.h""\r\n" - "\0" -END - -3 TEXTINCLUDE -BEGIN - "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// Version -// - -VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,4,0,0 - PRODUCTVERSION 1,4,0,0 - FILEFLAGSMASK 0x3fL -#ifdef _DEBUG - FILEFLAGS 0x29L -#else - FILEFLAGS 0x28L -#endif - FILEOS 0x40004L - FILETYPE 0x1L - FILESUBTYPE 0x0L -BEGIN - BLOCK "StringFileInfo" - BEGIN - BLOCK "040904b0" - BEGIN - VALUE "Comments", "This version of StellaX is released under the GPL." - VALUE "CompanyName", "Stephen Anthony (sa666_666@hotmail.com)" - VALUE "FileDescription", "StellaX" - VALUE "FileVersion", "1, 4, 0, 0" - VALUE "InternalName", "StellaX" - VALUE "LegalCopyright", "Copyright (C) 2000 Jeff Miller, Copyright (C) 2004 Stephen Anthony" - VALUE "LegalTrademarks", "n/a" - VALUE "OriginalFilename", "StellaX.exe" - VALUE "PrivateBuild", "n/a" - VALUE "ProductName", "StellaX" - VALUE "ProductVersion", "1, 4, 0, 0" - VALUE "SpecialBuild", "n/a" - END - END - BLOCK "VarFileInfo" - BEGIN - VALUE "Translation", 0x409, 1200 - END -END - - -///////////////////////////////////////////////////////////////////////////// -// -// Dialog -// - -IDD_MAIN DIALOGEX 0, 0, 409, 249 -STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | - WS_VISIBLE | WS_CAPTION -CAPTION "StellaX" -FONT 8, "MS Shell Dlg", 0, 0, 0x0 -BEGIN - CONTROL "&Files found in:",-1,"Static",SS_LEFTNOWORDWRAP | - WS_GROUP,7,45,44,8 - CONTROL "List1",IDC_ROMLIST,"SysListView32",LVS_REPORT | - LVS_SINGLESEL | LVS_SHOWSELALWAYS | LVS_AUTOARRANGE | - WS_BORDER | WS_TABSTOP,7,57,395,143,WS_EX_STATICEDGE - CONTROL "&Play",IDC_PLAY,"Button",BS_OWNERDRAW | WS_TABSTOP,7, - 226,149,16 - CONTROL "&Options",IDC_CONFIG,"Button",BS_OWNERDRAW | WS_TABSTOP, - 230,226,54,16 - CONTROL "&Help",IDC_ABOUT,"Button",BS_OWNERDRAW | WS_TABSTOP,289, - 226,54,16 - CONTROL "E&xit",IDC_EXIT,"Button",BS_OWNERDRAW | WS_TABSTOP,348, - 226,54,16 - CTEXT "Written by Jeff Miller (miller@zipcon.net)\nUpdated by Stephen Anthony (sa666_666@hotmail.com)\nStella core by Bradford W. Mott (bwmott@acm.org)", - IDC_STATIC_TEXT,175,7,227,28,SS_NOPREFIX - RTEXT "",IDC_ROMCOUNT,322,45,80,8,SS_NOPREFIX - CONTROL "",-1,"Static",SS_ETCHEDHORZ,0,39,411,1 - CONTROL "",-1,"Static",SS_ETCHEDHORZ,0,218,411,1 - CONTROL "StellaX v1.4",IDC_TITLE,"Button",BS_OWNERDRAW | - BS_CENTER | BS_TOP | WS_DISABLED | WS_TABSTOP,7,7,145,22 - CONTROL "Static",IDC_ROMPATH,"Static",SS_LEFTNOWORDWRAP | - SS_NOPREFIX | WS_GROUP,57,45,254,8 - CONTROL "",IDC_ROMNOTE,"Static",SS_LEFTNOWORDWRAP | SS_NOPREFIX | - WS_GROUP,105,205,297,8 - LTEXT "Game notes (if available):",-1,7,205,98,8 - CONTROL "&Reload",IDC_RELOAD,"Button",BS_OWNERDRAW | WS_TABSTOP, - 172,226,54,16 -END - -IDD_ABOUT_PAGE DIALOGEX 0, 0, 299, 86 -STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION -CAPTION "Information" -FONT 8, "MS Shell Dlg", 0, 0, 0x0 -BEGIN - LTEXT "You must own legal copies of all ROM images you are using. The Stella team can't tell you where to find ROM images so DON'T ASK. All requests will either be deleted or sent to the appropriate authorities. StellaX is GPL software.", - -1,7,7,284,30,SS_NOPREFIX - LTEXT "If you have a question or a problem, please try one of these contacts:", - -1,7,44,284,8,SS_NOPREFIX - LTEXT "Steve Anthony:",-1,7,58,53,8,SS_NOPREFIX - LTEXT "sa666_666@hotmail.com",IDC_EMAIL_MAINTAINER,73,58,122,8, - SS_NOPREFIX | SS_NOTIFY - LTEXT "http://minbar.org",IDC_WEB_MAINTAINER,202,58,72,8, - SS_NOPREFIX | SS_NOTIFY - LTEXT "Stella dev team:",-1,7,70,60,8,SS_NOPREFIX - LTEXT "stella-main@lists.sourceforge.net",IDC_EMAIL_STELLA,73, - 70,122,8,SS_NOPREFIX | SS_NOTIFY - LTEXT "http://stella.sf.net",IDC_WEB_STELLA,202,70,68,8, - SS_NOPREFIX | SS_NOTIFY - CONTROL "",-1,"Static",SS_ETCHEDHORZ,7,37,284,1 -END - -IDD_CONFIG_PAGE DIALOGEX 0, 0, 269, 158 -STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_DISABLED | WS_CAPTION -CAPTION "Options" -FONT 8, "MS Shell Dlg", 0, 0, 0x0 -BEGIN - GROUPBOX "File Locations",-1,7,7,254,39 - LTEXT "ROM Directory:",-1,14,25,55,8 - EDITTEXT IDC_ROMPATH,67,23,171,13,ES_AUTOHSCROLL - PUSHBUTTON "...",IDC_BROWSE,241,23,13,12 - GROUPBOX "Snapshot Settings",-1,7,49,148,43 - LTEXT "Save Snapshot as:",-1,14,61,67,10 - COMBOBOX IDC_SNAPSHOT_TYPE,86,60,60,37,CBS_DROPDOWNLIST | - CBS_SORT | WS_VSCROLL | WS_TABSTOP - CONTROL "Generate multiple snapshots",IDC_SNAPSHOT_MULTIPLE, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,27,75,109,11 - GROUPBOX "Paddle Emulation",-1,161,49,100,43 - LTEXT "Mouse is paddle:",-1,167,61,65,8 - COMBOBOX IDC_PADDLE,225,60,30,82,CBS_DROPDOWNLIST | WS_VSCROLL | - WS_TABSTOP - GROUPBOX "Video Settings",-1,7,95,118,57 - LTEXT "Driver:",-1,14,108,28,10 - COMBOBOX IDC_VIDEO,62,106,52,35,CBS_DROPDOWNLIST | CBS_SORT | - WS_VSCROLL | WS_TABSTOP - LTEXT "Aspect Ratio:",-1,14,122,50,10 - EDITTEXT IDC_GL_ASPECT,62,120,51,12,ES_AUTOHSCROLL - CONTROL "Maximize FS OpenGL",IDC_GL_FSMAX,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,25,135,86,12 - GROUPBOX "Sound Settings",-1,132,95,96,57 - LTEXT "Volume:",-1,140,108,28,8 - EDITTEXT IDC_SOUND_VOLUME,176,106,29,12,ES_AUTOHSCROLL - CONTROL "",IDC_SOUND_VOLUME_SPIN,"msctls_updown32", - UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | - UDS_ARROWKEYS,205,106,11,12 - LTEXT "Frag Size:",-1,140,122,36,8 - COMBOBOX IDC_SOUND_FRAGSIZE,176,120,41,51,CBS_DROPDOWNLIST | - CBS_SORT | WS_VSCROLL | WS_TABSTOP - CONTROL "Disable &Sound",IDC_SOUND_ENABLE,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,147,135,62,10 -END - - -///////////////////////////////////////////////////////////////////////////// -// -// DESIGNINFO -// - -#ifdef APSTUDIO_INVOKED -GUIDELINES DESIGNINFO -BEGIN - IDD_MAIN, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 402 - TOPMARGIN, 7 - BOTTOMMARGIN, 242 - END - - IDD_ABOUT_PAGE, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 291 - TOPMARGIN, 7 - BOTTOMMARGIN, 78 - END - - IDD_CONFIG_PAGE, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 262 - TOPMARGIN, 7 - BOTTOMMARGIN, 152 - END -END -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// Icon -// - -// Icon with lowest ID value placed first to ensure application icon -// remains consistent on all systems. -IDI_APP ICON "STELLAX.ICO" - -///////////////////////////////////////////////////////////////////////////// -// -// Bitmap -// - -IDB_TILE BITMAP "tile.bmp" - -///////////////////////////////////////////////////////////////////////////// -// -// String Table -// - -STRINGTABLE -BEGIN - IDS_STATUSTEXT "%d files found" - IDS_STELLA "StellaX" - IDS_NO_CACHE_FILE "No ROM cache file was found. Regenerating the cache will take some time." - IDS_CORRUPT_CACHE_FILE "The ROM cache file was corrupt. Regenerating the cache will take some time." - IDS_ROMDIR_CHANGED "The ROM directory has changed. The ROM cache will be regenerated." -END - -STRINGTABLE -BEGIN - IDS_ALREADYRUNNING "StellaX is already running!" -END - -STRINGTABLE -BEGIN - IDS_FILENAME "Filename" - IDS_MANUFACTURER "Manufacturer" - IDS_NAME "Name" - IDS_RARITY "Rarity" -END - -STRINGTABLE -BEGIN - IDS_NO_ITEM_SELECTED "Before pressing play you must first select a game from the list!" -END - -#endif // English (U.S.) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED - diff --git a/stella/src/win32/StellaX/StellaX.vcproj b/stella/src/win32/StellaX/StellaX.vcproj deleted file mode 100644 index 7214549f6..000000000 --- a/stella/src/win32/StellaX/StellaX.vcproj +++ /dev/null @@ -1,275 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/stella/src/win32/StellaX/StellaXMain.cxx b/stella/src/win32/StellaX/StellaXMain.cxx deleted file mode 100644 index f5edc7061..000000000 --- a/stella/src/win32/StellaX/StellaXMain.cxx +++ /dev/null @@ -1,60 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll XX XX -// SS SS tt ll ll XX XX -// SS tttttt eeee ll ll aaaa XX XX -// SSSS tt ee ee ll ll aa XXX -// SS tt eeeeee ll ll aaaaa XX XX -// SS SS tt ee ll ll aa aa XX XX -// SSSS ttt eeeee llll llll aaaaa XX XX -// -// Copyright (c) 1995-2000 by Jeff Miller -// Copyright (c) 2004 by Stephen Anthony -// -// See the file "license" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -// -// $Id: StellaXMain.cxx,v 1.5 2004-07-15 03:03:27 stephena Exp $ -//============================================================================ - -#include -#include -#include -#include -#include - -#include "GlobalData.hxx" -#include "Settings.hxx" -#include "pch.hxx" -#include "StellaXMain.hxx" - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -CStellaXMain::CStellaXMain() -{ -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -CStellaXMain::~CStellaXMain() -{ -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CStellaXMain::PlayROM( string& romfile, CGlobalData& globaldata ) -{ - ostringstream buf; - - // Make sure the specfied ROM exists - if(!globaldata.settings().fileExists(romfile)) - { - buf << "\"" << romfile << "\" doesn't exist"; - - MessageBox( NULL, buf.str().c_str(), "Unknown ROM", MB_ICONEXCLAMATION|MB_OK); - return; - } - - // Assume that the ROM file does exist, attempt to run external Stella - // Since all settings are saved to the stella.ini file, we don't need - // to pass any arguments here ... - buf << "\"" << romfile << "\""; - ShellExecute(NULL, "open", "stella.exe", buf.str().c_str(), NULL, 0); -} diff --git a/stella/src/win32/StellaX/StellaXMain.hxx b/stella/src/win32/StellaX/StellaXMain.hxx deleted file mode 100644 index 0bcbb5f52..000000000 --- a/stella/src/win32/StellaX/StellaXMain.hxx +++ /dev/null @@ -1,40 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll XX XX -// SS SS tt ll ll XX XX -// SS tttttt eeee ll ll aaaa XX XX -// SSSS tt ee ee ll ll aa XXX -// SS tt eeeeee ll ll aaaaa XX XX -// SS SS tt ee ll ll aa aa XX XX -// SSSS ttt eeeee llll llll aaaaa XX XX -// -// Copyright (c) 1995-2000 by Jeff Miller -// Copyright (c) 2004 by Stephen Anthony -// -// See the file "license" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -// -// $Id: StellaXMain.hxx,v 1.4 2004-07-15 03:03:27 stephena Exp $ -//============================================================================ - -#ifndef STELLAX_MAIN_HXX -#define STELLAX_MAIN_HXX - -#include "bspf.hxx" - -class CGlobalData; - -class CStellaXMain -{ - public: - CStellaXMain(); - ~CStellaXMain(); - - void PlayROM( string& romfile, CGlobalData& globaldata ); - - private: - CStellaXMain( const CStellaXMain& ); // no implementation - void operator=( const CStellaXMain& ); // no implementation -}; - -#endif diff --git a/stella/src/win32/StellaX/TextButton3d.cxx b/stella/src/win32/StellaX/TextButton3d.cxx deleted file mode 100644 index 6a4499da8..000000000 --- a/stella/src/win32/StellaX/TextButton3d.cxx +++ /dev/null @@ -1,178 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll XX XX -// SS SS tt ll ll XX XX -// SS tttttt eeee ll ll aaaa XX XX -// SSSS tt ee ee ll ll aa XXX -// SS tt eeeeee ll ll aaaaa XX XX -// SS SS tt ee ll ll aa aa XX XX -// SSSS ttt eeeee llll llll aaaaa XX XX -// -// Copyright (c) 1995-2000 by Jeff Miller -// Copyright (c) 2004 by Stephen Anthony -// -// See the file "license" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -// -// $Id: TextButton3d.cxx,v 1.2 2004-07-15 03:03:27 stephena Exp $ -//============================================================================ - -#include "pch.hxx" -#include "TextButton3d.hxx" - -// button style should be VISIBLE / DISABLED / OWNERDRAW - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -CTextButton3d::CTextButton3d() -{ -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -LRESULT CTextButton3d::WndProc( HWND hWnd, UINT msg, WPARAM wParam, - LPARAM lParam, BOOL& rfHandled ) -{ - switch (msg) - { -#if 0 - // TODO: re do this now that I send this message here - case WM_DRAWITEM: - rfHandled = TRUE; - pThis->OnDrawItem(hWnd, (UINT)wParam, (LPDRAWITEMSTRUCT)lParam); - return TRUE; -#endif - - case WM_PAINT: - rfHandled = TRUE; - OnPaint(hWnd, (HDC)wParam); - return TRUE; - - case WM_ERASEBKGND: - rfHandled = TRUE; - return OnEraseBkgnd(hWnd, (HDC)wParam); - } - - return 0; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CTextButton3d::OnPaint( HWND hwnd, HDC hdcPaint ) -{ - PAINTSTRUCT ps; - HDC hdc = BeginPaint(hwnd, &ps); - - int cxClient, cyClient; - - RECT rc; - GetClientRect(hwnd, &rc); - - RECT rcClient; - CopyRect(&rcClient, &rc); - - // lpdis->rcItem, lpdis->itemState - - int l = GetWindowTextLength(hwnd); - LPTSTR text = new TCHAR[l + 2]; - if (text == NULL) - { - EndPaint(hwnd, &ps); - return; - } - GetWindowText(hwnd, text, l+1); - - HFONT hfont = (HFONT)SendMessage(hwnd, WM_GETFONT, 0, 0); - LOGFONT lf; - GetObject(hfont, sizeof(lf), &lf); - if (lf.lfHeight == 0) - lf.lfHeight = 20; - lf.lfWidth = 0; - lf.lfWeight = FW_BLACK; - lf.lfEscapement = 0; - lf.lfOrientation = 0; - HFONT hfontTry = CreateFontIndirect(&lf); - - HFONT hfontOld = (HFONT)SelectObject(hdc, hfontTry); - - rcClient.left += 3; - rcClient.top += 3; - rcClient.right -= 3; - rcClient.bottom -= 3; - - cxClient = rcClient.right - rcClient.left; - cyClient = rcClient.bottom - rcClient.top; - - SIZE sizeTextClient; - GetTextExtentPoint(hdc, text, lstrlen(text), &sizeTextClient); - if (cxClient*sizeTextClient.cy > cyClient*sizeTextClient.cx) - lf.lfHeight = MulDiv(lf.lfHeight, cyClient, sizeTextClient.cy); - else - lf.lfHeight = MulDiv(lf.lfHeight, cxClient, sizeTextClient.cx); - - lf.lfHeight--; - - rcClient.left -= 3; - rcClient.top -= 3; - rcClient.right += 3; - rcClient.bottom += 3; - - cxClient = rcClient.right - rcClient.left; - cyClient = rcClient.bottom - rcClient.top; - - hfont = CreateFontIndirect(&lf); - SelectObject(hdc, hfont); - GetTextExtentPoint(hdc, text, lstrlen(text), &sizeTextClient); - - int minx = rcClient.left + (cxClient - sizeTextClient.cx) / 2; - int miny = rcClient.top + (cyClient - sizeTextClient.cy) / 2; - - int iOldBkMode = SetBkMode(hdc, TRANSPARENT); - COLORREF crText = GetSysColor(COLOR_BTNTEXT); - COLORREF crOldText = SetTextColor(hdc, crText); - - int cx = minx; - int cy = miny; - - int s = 1; - cx += 3; - cy += 3; - - // draw 3D highlights - SetTextColor(hdc, GetSysColor(COLOR_3DDKSHADOW)); - TextOut(hdc, cx-s*2, cy+s*2, text, lstrlen(text)); - TextOut(hdc, cx+s*2, cy-s*2, text, lstrlen(text)); - TextOut(hdc, cx+s*2, cy+s*2, text, lstrlen(text)); - SetTextColor(hdc, ::GetSysColor(COLOR_3DHILIGHT)); - TextOut(hdc, cx+s*1, cy-s*2, text, lstrlen(text)); - TextOut(hdc, cx-s*2, cy+s*1, text, lstrlen(text)); - TextOut(hdc, cx-s*2, cy-s*2, text, lstrlen(text)); - SetTextColor(hdc, GetSysColor(COLOR_3DSHADOW)); - TextOut(hdc, cx-s*1, cy+s*1, text, lstrlen(text)); - TextOut(hdc, cx+s*1, cy-s*1, text, lstrlen(text)); - TextOut(hdc, cx+s*1, cy+s*1, text, lstrlen(text)); - SetTextColor(hdc, GetSysColor(COLOR_3DLIGHT)); - TextOut(hdc, cx, cy-s*1, text, lstrlen(text)); - TextOut(hdc, cx-s*1, cy, text, lstrlen(text)); - TextOut(hdc, cx-s*1, cy-s*1, text, lstrlen(text)); - SetTextColor(hdc, crText); - - // draw the text - TextOut(hdc, cx, cy, text, lstrlen(text)); - - // restore dc - SetTextColor(hdc, crOldText); - SetBkMode(hdc, iOldBkMode); - SelectObject(hdc, hfontOld); - - DeleteObject(hfont); - DeleteObject(hfontTry); - - delete[] text; - - EndPaint(hwnd, &ps); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -BOOL CTextButton3d::OnEraseBkgnd( HWND hwnd, HDC hdc ) -{ - // dont do any erasing - return TRUE; -} diff --git a/stella/src/win32/StellaX/TextButton3d.hxx b/stella/src/win32/StellaX/TextButton3d.hxx deleted file mode 100644 index 2f97b0410..000000000 --- a/stella/src/win32/StellaX/TextButton3d.hxx +++ /dev/null @@ -1,43 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll XX XX -// SS SS tt ll ll XX XX -// SS tttttt eeee ll ll aaaa XX XX -// SSSS tt ee ee ll ll aa XXX -// SS tt eeeeee ll ll aaaaa XX XX -// SS SS tt ee ll ll aa aa XX XX -// SSSS ttt eeeee llll llll aaaaa XX XX -// -// Copyright (c) 1995-2000 by Jeff Miller -// Copyright (c) 2004 by Stephen Anthony -// -// See the file "license" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -// -// $Id: TextButton3d.hxx,v 1.2 2004-07-15 03:03:27 stephena Exp $ -//============================================================================ - -#ifndef TEXT_BUTTON_HXX -#define TEXT_BUTTON_HXX - -// derived from Roger Onslow's code - -#include "Wnd.hxx" - -class CTextButton3d : public CWnd -{ - public: - CTextButton3d(); - - protected: - LRESULT WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, BOOL& rfHandled); - - private: - void OnPaint(HWND, HDC); - BOOL OnEraseBkgnd(HWND, HDC); - - CTextButton3d( const CTextButton3d& ); // no implementation - void operator=( const CTextButton3d& ); // no implementation -}; - -#endif diff --git a/stella/src/win32/StellaX/Wnd.cxx b/stella/src/win32/StellaX/Wnd.cxx deleted file mode 100644 index 3bbaea385..000000000 --- a/stella/src/win32/StellaX/Wnd.cxx +++ /dev/null @@ -1,77 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll XX XX -// SS SS tt ll ll XX XX -// SS tttttt eeee ll ll aaaa XX XX -// SSSS tt ee ee ll ll aa XXX -// SS tt eeeeee ll ll aaaaa XX XX -// SS SS tt ee ll ll aa aa XX XX -// SSSS ttt eeeee llll llll aaaaa XX XX -// -// Copyright (c) 1995-2000 by Jeff Miller -// Copyright (c) 2004 by Stephen Anthony -// -// See the file "license" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -// -// $Id: Wnd.cxx,v 1.2 2004-07-15 03:03:27 stephena Exp $ -//============================================================================ - -#include "pch.hxx" -#include "Wnd.hxx" - -// REVIEW: Need to reset old wnd proc? - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -CWnd::CWnd() - : m_pOldWindowProc(NULL), - m_hwnd(NULL) -{ -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -BOOL CWnd::SubclassDlgItem( HWND hwndParent, UINT nID ) -{ - if ( nID == 0 || hwndParent == NULL ) - return FALSE; - - // can't subclass twice! - if ( m_pOldWindowProc != NULL ) - return FALSE; - - m_hwnd = GetDlgItem( hwndParent, nID ); - if (m_hwnd == NULL) - { - ASSERT( FALSE ); - return FALSE; - } - - PreSubclassWindow( m_hwnd ); - - m_pOldWindowProc = (WNDPROC)GetWindowLong( m_hwnd, GWL_WNDPROC ); - SetWindowLong( m_hwnd, GWL_USERDATA, (LONG)this ); - SetWindowLong( m_hwnd, GWL_WNDPROC, (LONG)StaticWndProc ); - - return TRUE; -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void CWnd::PreSubclassWindow( HWND hwnd ) -{ - // no default behavior -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -LRESULT CALLBACK CWnd::StaticWndProc( HWND hWnd, UINT msg, WPARAM wParam, - LPARAM lParam ) -{ - CWnd* pThis = (CWnd*)GetWindowLong(hWnd, GWL_USERDATA); - - BOOL fHandled = FALSE; - LRESULT lRes = pThis->WndProc( hWnd, msg, wParam, lParam, fHandled ); - - if (fHandled) - return lRes; - - return CallWindowProc( pThis->m_pOldWindowProc, hWnd, msg, wParam, lParam ); -} diff --git a/stella/src/win32/StellaX/Wnd.hxx b/stella/src/win32/StellaX/Wnd.hxx deleted file mode 100644 index 131278aa6..000000000 --- a/stella/src/win32/StellaX/Wnd.hxx +++ /dev/null @@ -1,46 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll XX XX -// SS SS tt ll ll XX XX -// SS tttttt eeee ll ll aaaa XX XX -// SSSS tt ee ee ll ll aa XXX -// SS tt eeeeee ll ll aaaaa XX XX -// SS SS tt ee ll ll aa aa XX XX -// SSSS ttt eeeee llll llll aaaaa XX XX -// -// Copyright (c) 1995-2000 by Jeff Miller -// Copyright (c) 2004 by Stephen Anthony -// -// See the file "license" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -// -// $Id: Wnd.hxx,v 1.2 2004-07-15 03:03:27 stephena Exp $ -//============================================================================ - -#ifndef WND_HXX -#define WND_HXX - -class CWnd -{ - public: - CWnd(); - - BOOL SubclassDlgItem( HWND hwndParent, UINT nID ); - - operator HWND() const { return m_hwnd; } - - protected: - virtual void PreSubclassWindow( HWND hwnd ); - virtual LRESULT WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, BOOL& rfHandled ) = 0; - - private: - static LRESULT CALLBACK StaticWndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ); - - WNDPROC m_pOldWindowProc; - HWND m_hwnd; - - CWnd( const CWnd& ); // no implementation - void operator=( const CWnd& ); // no implementation -}; - -#endif diff --git a/stella/src/win32/StellaX/debug.cxx b/stella/src/win32/StellaX/debug.cxx deleted file mode 100644 index c1926606d..000000000 --- a/stella/src/win32/StellaX/debug.cxx +++ /dev/null @@ -1,80 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll XX XX -// SS SS tt ll ll XX XX -// SS tttttt eeee ll ll aaaa XX XX -// SSSS tt ee ee ll ll aa XXX -// SS tt eeeeee ll ll aaaaa XX XX -// SS SS tt ee ll ll aa aa XX XX -// SSSS ttt eeeee llll llll aaaaa XX XX -// -// Copyright (c) 1995-2000 by Jeff Miller -// Copyright (c) 2004 by Stephen Anthony -// -// See the file "license" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -// -// $Id: debug.cxx,v 1.2 2004-07-15 03:03:27 stephena Exp $ -//============================================================================ - -#include "debug.hxx" - -#ifdef _DEBUG // entire file - -// log file name (or NULL for no log) -- must be defined by client - -extern LPCTSTR g_ctszDebugLog; - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void AFX_CDECL AfxTrace( LPCTSTR lpszFormat, ... ) -{ - va_list args; - va_start(args, lpszFormat); - - int nBuf; - TCHAR szBuffer[512]; - - nBuf = _vsntprintf(szBuffer, _countof(szBuffer), lpszFormat, args); - - // was there an error? was the expanded string too long? - ASSERT(nBuf >= 0); - - if (nBuf < 511) - lstrcat(szBuffer, _T("\r\n")); - - _RPT0(_CRT_WARN, szBuffer); - - if (g_ctszDebugLog) - { - HANDLE hfile = CreateFile(g_ctszDebugLog, GENERIC_WRITE, 0, NULL, - OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - if (hfile != INVALID_HANDLE_VALUE) - { - SetFilePointer(hfile, 0, NULL, FILE_END); - - DWORD dw; - WriteFile(hfile, szBuffer, (lstrlen(szBuffer)+1)*sizeof(TCHAR), - &dw, NULL); - - CloseHandle(hfile); - } - } - - va_end(args); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -BOOL AFXAPI AfxAssertFailedLine( LPCSTR lpszFileName, int nLine, - LPCTSTR lpszCondition ) -{ - // we remove WM_QUIT because if it is in the queue then the message box - // won't display - MSG msg; - BOOL bQuit = PeekMessage(&msg, NULL, WM_QUIT, WM_QUIT, PM_REMOVE); - BOOL bResult = _CrtDbgReport(_CRT_ASSERT, lpszFileName, nLine, NULL, lpszCondition); - if (bQuit) - PostQuitMessage(msg.wParam); - return bResult; -} - -#endif diff --git a/stella/src/win32/StellaX/debug.hxx b/stella/src/win32/StellaX/debug.hxx deleted file mode 100644 index 9a79ccd33..000000000 --- a/stella/src/win32/StellaX/debug.hxx +++ /dev/null @@ -1,111 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll XX XX -// SS SS tt ll ll XX XX -// SS tttttt eeee ll ll aaaa XX XX -// SSSS tt ee ee ll ll aa XXX -// SS tt eeeeee ll ll aaaaa XX XX -// SS SS tt ee ll ll aa aa XX XX -// SSSS ttt eeeee llll llll aaaaa XX XX -// -// Copyright (c) 1995-2000 by Jeff Miller -// Copyright (c) 2004 by Stephen Anthony -// -// See the file "license" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -// -// $Id: debug.hxx,v 1.2 2004-07-15 03:03:27 stephena Exp $ -//============================================================================ - -#ifndef _AFX -#define _AFX - -#include -#include - -// --------------------------------------------------------------------------- -// This file defines: -// _countof -// TRACE, TRACE0, TRACE1, TRACE2, TRACE3 -// ASSERT -// VERIFY -// DEBUG_ONLY - - -// determine number of elements in an array (not bytes) -#define _countof(array) (sizeof(array)/sizeof(array[0])) - -// AFXAPI is used on global public functions -#ifndef AFXAPI - #define AFXAPI __stdcall -#endif - -// AFX_CDECL is used for rare functions taking variable arguments -#ifndef AFX_CDECL - #define AFX_CDECL __cdecl -#endif - - -#ifdef _DEBUG - -// --------------------------------------------------------------------------- -// DEBUG DEFINED - -#include - -#include -#include - -#include - -#ifndef AfxDebugBreak -#define AfxDebugBreak() _CrtDbgBreak() -#endif - -BOOL AFXAPI AfxAssertFailedLine(LPCSTR lpszFileName, int nLine, LPCTSTR lpszCondition); - -void AFX_CDECL AfxTrace(LPCTSTR lpszFormat, ...); - -#define TRACE ::AfxTrace -#define THIS_FILE __FILE__ -#define ASSERT(f) \ - do \ - { \ - if (!(f) && AfxAssertFailedLine(THIS_FILE, __LINE__, #f)) \ - AfxDebugBreak(); \ - } while (0) \ - -#define VERIFY(f) ASSERT(f) -#define DEBUG_ONLY(f) (f) - -// The following trace macros are provided for backward compatiblity -// (they also take a fixed number of parameters which provides -// some amount of extra error checking) -#define TRACE0(sz) ::AfxTrace(_T("%s"), _T(sz)) -#define TRACE1(sz, p1) ::AfxTrace(_T(sz), p1) -#define TRACE2(sz, p1, p2) ::AfxTrace(_T(sz), p1, p2) -#define TRACE3(sz, p1, p2, p3) ::AfxTrace(_T(sz), p1, p2, p3) - -#else // _DEBUG - -// --------------------------------------------------------------------------- -// DEBUG NOT DEFINED - -#ifdef AfxDebugBreak -#undef AfxDebugBreak -#endif -#define AfxDebugBreak() - -#define ASSERT(f) ((void)0) -#define VERIFY(f) ((void)(f)) -#define DEBUG_ONLY(f) ((void)0) -inline void AFX_CDECL AfxTrace(LPCTSTR, ...) { } -#define TRACE 1 ? (void)0 : ::AfxTrace -#define TRACE0(sz) -#define TRACE1(sz, p1) -#define TRACE2(sz, p1, p2) -#define TRACE3(sz, p1, p2, p3) - -#endif // !_DEBUG - -#endif diff --git a/stella/src/win32/StellaX/main.cxx b/stella/src/win32/StellaX/main.cxx deleted file mode 100644 index 92e5ec5cd..000000000 --- a/stella/src/win32/StellaX/main.cxx +++ /dev/null @@ -1,94 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll XX XX -// SS SS tt ll ll XX XX -// SS tttttt eeee ll ll aaaa XX XX -// SSSS tt ee ee ll ll aa XXX -// SS tt eeeeee ll ll aaaaa XX XX -// SS SS tt ee ll ll aa aa XX XX -// SSSS ttt eeeee llll llll aaaaa XX XX -// -// Copyright (c) 1995-2000 by Jeff Miller -// Copyright (c) 2004 by Stephen Anthony -// -// See the file "license" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -// -// $Id: main.cxx,v 1.3 2004-07-15 03:03:27 stephena Exp $ -//============================================================================ - -#include "pch.hxx" -#include "resource.h" - -#include "GlobalData.hxx" -#include "MainDlg.hxx" - -class CSingleInstance -{ - public: - CSingleInstance( LPCTSTR pszName ) - { - ::SetLastError( ERROR_SUCCESS ); - m_hMutex = ::CreateMutex( NULL, TRUE, pszName ); - m_dwError = ::GetLastError(); - } - - ~CSingleInstance() - { - if ( m_hMutex != INVALID_HANDLE_VALUE && m_dwError != ERROR_ALREADY_EXISTS ) - { - VERIFY( ::ReleaseMutex( m_hMutex ) ); - VERIFY( ::CloseHandle( m_hMutex ) ); - } - } - - BOOL AlreadyExists( void ) const - { - return ( m_dwError == ERROR_ALREADY_EXISTS ); - } - - private: - HANDLE m_hMutex; - DWORD m_dwError; - - CSingleInstance( const CSingleInstance& ); // no implementation - void operator=( const CSingleInstance& ); // no implementation -}; - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -LPCTSTR g_ctszDebugLog = _T("stella.log"); - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -int WINAPI _tWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, - LPTSTR lpCmdLine, int nCmdShow ) -{ - UNUSED_ALWAYS( hPrevInstance ); - UNUSED_ALWAYS( lpCmdLine ); - UNUSED_ALWAYS( nCmdShow ); - - (void)::DeleteFile(g_ctszDebugLog); - - CSingleInstance mutex( _T("StellaXMutex") ); - if ( mutex.AlreadyExists() ) - { - MessageBox( hInstance, NULL, IDS_ALREADYRUNNING ); - return 1; - } - - HRESULT hrCoInit = ::CoInitialize( NULL ); - if ( FAILED(hrCoInit) ) - MessageBox( hInstance, NULL, IDS_COINIT_FAILED ); - - ::InitCommonControls(); - - CGlobalData globaldata( hInstance ); - - // show the ui - MainDlg dlg( globaldata, hInstance ); - dlg.DoModal( NULL ); - - if ( hrCoInit == S_OK ) - ::CoUninitialize(); - - return 0; -} diff --git a/stella/src/win32/StellaX/pch.cxx b/stella/src/win32/StellaX/pch.cxx deleted file mode 100644 index c275fa106..000000000 --- a/stella/src/win32/StellaX/pch.cxx +++ /dev/null @@ -1,75 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll XX XX -// SS SS tt ll ll XX XX -// SS tttttt eeee ll ll aaaa XX XX -// SSSS tt ee ee ll ll aa XXX -// SS tt eeeeee ll ll aaaaa XX XX -// SS SS tt ee ll ll aa aa XX XX -// SSSS ttt eeeee llll llll aaaaa XX XX -// -// Copyright (c) 1995-2000 by Jeff Miller -// Copyright (c) 2004 by Stephen Anthony -// -// See the file "license" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -// -// $Id: pch.cxx,v 1.2 2004-07-15 03:03:27 stephena Exp $ -//============================================================================ - -#include "pch.hxx" -#include -#include - -#include "resource.h" - -// Bring in the common control library -#pragma comment( lib, "comctl32" ) - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void MessageBox( HINSTANCE hInstance, HWND hwndParent, UINT uIDText ) -{ - const int nMaxStrLen = 1024; - TCHAR tszCaption[nMaxStrLen + 1] = { 0 }; - TCHAR tszText[nMaxStrLen + 1] = { 0 }; - - // Caption is always "StellaX" - LoadString(hInstance, IDS_STELLA, tszCaption, nMaxStrLen); - - LoadString(hInstance, uIDText, tszText, nMaxStrLen); - if (hwndParent == NULL) - hwndParent = ::GetForegroundWindow(); - - ::MessageBox(hwndParent, tszText, tszCaption, MB_ICONWARNING | MB_OK); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void MessageBoxFromWinError( DWORD dwError, LPCTSTR pszCaption /* = NULL */ ) -{ - const int nMaxStrLen = 1024; - TCHAR pszCaptionStellaX[nMaxStrLen + 1]; - - if ( pszCaption == NULL ) - { - // LoadString(hInstance, IDS_STELLA, tszCaption, nMaxStrLen); - lstrcpy( pszCaptionStellaX, _T("StellaX") ); - } - - LPTSTR pszText = NULL; - - FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, - NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR)&pszText, 0, NULL); - - ::MessageBox(::GetForegroundWindow(), pszText, - pszCaption ? pszCaption : pszCaptionStellaX, - MB_ICONWARNING | MB_OK); - - LocalFree( pszText ); -} - -// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -void MessageBoxFromGetLastError( LPCTSTR pszCaption /* = NULL */ ) -{ - MessageBoxFromWinError( GetLastError(), pszCaption ); -} diff --git a/stella/src/win32/StellaX/pch.hxx b/stella/src/win32/StellaX/pch.hxx deleted file mode 100644 index 6f88160aa..000000000 --- a/stella/src/win32/StellaX/pch.hxx +++ /dev/null @@ -1,60 +0,0 @@ -//============================================================================ -// -// SSSS tt lll lll XX XX -// SS SS tt ll ll XX XX -// SS tttttt eeee ll ll aaaa XX XX -// SSSS tt ee ee ll ll aa XXX -// SS tt eeeeee ll ll aaaaa XX XX -// SS SS tt ee ll ll aa aa XX XX -// SSSS ttt eeeee llll llll aaaaa XX XX -// -// Copyright (c) 1995-2000 by Jeff Miller -// Copyright (c) 2004 by Stephen Anthony -// -// See the file "license" for information on usage and redistribution of -// this file, and for a DISCLAIMER OF ALL WARRANTIES. -// -// $Id: pch.hxx,v 1.3 2004-07-15 03:03:27 stephena Exp $ -//============================================================================ - -#ifndef PCH_HXX -#define PCH_HXX - -#define WIN32_LEAN_AND_MEAN -#define DIRECTINPUT_VERSION 5 - -#include -#include -#include - -#include -#include -#include - -#include - -#include "debug.hxx" - -// --------------------------------------------------------------------------- -// Conditional defines - -// Macros -// - -#ifdef _DEBUG -#define UNUSED(x) -#else -#define UNUSED(x) x -#endif -#define UNUSED_ALWAYS(x) x - -// Utility methods -// - -void MessageBox( HINSTANCE hInstance, HWND hwndParent, UINT uIDText ); - -void MessageBoxFromWinError( DWORD dwError, LPCTSTR pszCaption /* = NULL */ ); - -void MessageBoxFromGetLastError( LPCTSTR pszCaption /* = NULL */ ); - -#endif diff --git a/stella/src/win32/StellaX/resource.h b/stella/src/win32/StellaX/resource.h deleted file mode 100644 index 131aaa262..000000000 --- a/stella/src/win32/StellaX/resource.h +++ /dev/null @@ -1,75 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by StellaX.rc -// -#define IDB_TILE 101 -#define IDI_APP 102 -#define IDD_ABOUT 103 -#define IDD_MAIN 104 -#define IDD_ABOUT_PAGE 106 -#define IDD_CONFIG_PAGE 108 -#define IDS_ALREADYRUNNING 200 -#define IDS_CANTOPEN 204 -#define IDS_CW_FAILED 208 -#define IDS_FATALERROR 275 -#define IDS_FILENAME 277 -#define IDS_MANUFACTURER 278 -#define IDS_NAME 280 -#define IDS_OUTOFMEMORY 283 -#define IDS_RARITY 284 -#define IDS_STATUSTEXT 289 -#define IDS_STELLA 290 -#define IDS_UNKNOWNERROR 291 -#define IDS_NO_CACHE_FILE 291 -#define IDS_DEBUGBUILD 292 -#define IDS_CORRUPT_CACHE_FILE 292 -#define IDS_ROMDIR_CHANGED 293 -#define IDS_COINIT_FAILED 296 -#define IDS_ASS_FAILED 297 -#define IDS_PAS_FAILED 298 -#define IDS_NO_ITEM_SELECTED 305 -#define IDC_ABOUT 1001 -#define IDC_EMAIL_MAINTAINER 1002 -#define IDC_EMAIL_STELLA 1003 -#define IDC_EXIT 1004 -#define IDC_PLAY 1005 -#define IDC_ROMCOUNT 1006 -#define IDC_ROMLIST 1007 -#define IDC_STATIC_TEXT 1008 -#define IDC_TITLE 1009 -#define IDC_WEB_MAINTAINER 1010 -#define IDC_WEB_STELLA 1011 -#define IDC_WWW_MAME 1012 -#define IDC_ROMPATH 1013 -#define IDC_ROMNOTE 1014 -#define IDC_CONFIG 1015 -#define IDC_CONFIG2 1016 -#define IDC_PADDLE 1017 -#define IDC_VOLUME 1019 -#define IDC_BROWSE 1022 -#define IDC_EDIT2 1027 -#define IDC_RELOAD 1028 -#define IDC_SNAPSHOT_TYPE 1029 -#define IDC_SNAPSHOT_LOCATION 1030 -#define IDC_SNAPSHOT_MULTIPLE 1031 -#define IDC_SOUND_ENABLE 1032 -#define IDC_SOUND_VOLUME 1033 -#define IDC_LIST1 1033 -#define IDC_VIDEO 1034 -#define IDC_GL_ASPECT 1035 -#define IDC_GL_FSMAX 1036 -#define IDC_SOUND_VOLUME_SPIN 1044 -#define IDC_SOUND_FRAGSIZE 1045 -#define IDC_TAB1 1046 -#define ID_FILE_EXIT 32771 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 296 -#define _APS_NEXT_COMMAND_VALUE 32772 -#define _APS_NEXT_CONTROL_VALUE 1047 -#define _APS_NEXT_SYMED_VALUE 101 -#endif -#endif diff --git a/stella/src/win32/StellaX/tile.bmp b/stella/src/win32/StellaX/tile.bmp deleted file mode 100644 index ec6faadf9c04d772a30d2a834cd336ec1b9cd7ba..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27318 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 CAM#HC diff --git a/stella/src/win32/Stella_Emulator.sln b/stella/src/win32/Stella_Emulator.sln deleted file mode 100644 index 2570f33c7..000000000 --- a/stella/src/win32/Stella_Emulator.sln +++ /dev/null @@ -1,29 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 8.00 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "StellaX", "StellaX\StellaX.vcproj", "{EB852944-92EA-4A83-B13F-E800ADA48A4D}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Stella", "Stella\Stella.vcproj", "{45875C96-4084-4C54-B570-FC92F8791A2F}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfiguration) = preSolution - Debug = Debug - Release = Release - EndGlobalSection - GlobalSection(ProjectConfiguration) = postSolution - {EB852944-92EA-4A83-B13F-E800ADA48A4D}.Debug.ActiveCfg = Debug|Win32 - {EB852944-92EA-4A83-B13F-E800ADA48A4D}.Debug.Build.0 = Debug|Win32 - {EB852944-92EA-4A83-B13F-E800ADA48A4D}.Release.ActiveCfg = Release|Win32 - {EB852944-92EA-4A83-B13F-E800ADA48A4D}.Release.Build.0 = Release|Win32 - {45875C96-4084-4C54-B570-FC92F8791A2F}.Debug.ActiveCfg = Debug|Win32 - {45875C96-4084-4C54-B570-FC92F8791A2F}.Debug.Build.0 = Debug|Win32 - {45875C96-4084-4C54-B570-FC92F8791A2F}.Release.ActiveCfg = Release|Win32 - {45875C96-4084-4C54-B570-FC92F8791A2F}.Release.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - EndGlobalSection - GlobalSection(ExtensibilityAddIns) = postSolution - EndGlobalSection -EndGlobal